/* eslint-disable */
const { useState: dS, useMemo: dM, useEffect: dE, useRef: dR } = React;

// Code highlighter — minimal, matches existing .code .kw .str .com
const codeify = (src, lang) => {
  let s = src;
  // escape
  s = s.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;");
  if (lang === "bash" || lang === "sh") {
    s = s.replace(/(^|\n)(\s*)(#[^\n]*)/g, '$1$2<span class="com">$3</span>');
    s = s.replace(/("[^"]*")/g, '<span class="str">$1</span>');
    s = s.replace(/\b(curl|export|cat|echo|npm|npx|pnpm|yarn)\b/g, '<span class="kw">$1</span>');
    s = s.replace(/(--?[a-zA-Z][\w-]*)/g, '<span class="kw">$1</span>');
  } else if (lang === "json") {
    s = s.replace(/("(?:\\.|[^"\\])*")(\s*:)/g, '<span class="kw">$1</span>$2');
    s = s.replace(/:(\s*)("(?:\\.|[^"\\])*")/g, ':$1<span class="str">$2</span>');
    s = s.replace(/\b(true|false|null)\b/g, '<span class="kw">$1</span>');
  } else if (lang === "ts" || lang === "js") {
    s = s.replace(/(\/\/[^\n]*)/g, '<span class="com">$1</span>');
    s = s.replace(/("[^"]*"|'[^']*'|`[^`]*`)/g, '<span class="str">$1</span>');
    s = s.replace(/\b(import|from|const|let|var|function|return|async|await|new|class|export|default|if|else|for|of|in|interface|type)\b/g, '<span class="kw">$1</span>');
  } else if (lang === "py") {
    s = s.replace(/(#[^\n]*)/g, '<span class="com">$1</span>');
    s = s.replace(/("[^"]*"|'[^']*')/g, '<span class="str">$1</span>');
    s = s.replace(/\b(import|from|def|return|class|if|else|for|in|async|await|with|as)\b/g, '<span class="kw">$1</span>');
  } else if (lang === "http") {
    s = s.replace(/^(GET|POST|PUT|PATCH|DELETE)(\s)/gm, '<span class="kw">$1</span>$2');
    s = s.replace(/^([A-Z][\w-]*):/gm, '<span class="com">$1:</span>');
  }
  return s;
};

const Code = ({ lang="bash", children }) => {
  const flatten = (n) => {
    if (n == null || n === false) return "";
    if (typeof n === "string" || typeof n === "number") return String(n);
    if (Array.isArray(n)) return n.map(flatten).join("");
    if (n.props && n.props.children != null) return flatten(n.props.children);
    return "";
  };
  const txt = flatten(children);
  return <pre className="code" dangerouslySetInnerHTML={{ __html: codeify(txt, lang) }} style={{margin:0}}/>;
};

const DOCS_NAV = [
  { sec: "Get started" },
  { id:"intro", label:"Introduction" },
  { id:"quickstart", label:"Quickstart" },
  { id:"auth", label:"Authentication" },
  { sec: "API" },
  { id:"personas", label:"Personas" },
  { id:"chat", label:"Chat runtime" },
  { id:"openai", label:"OpenAI-compatible", pill:"compat" },
  { id:"streaming", label:"Streaming (SSE)" },
  { id:"webhooks", label:"Webhooks" },
  { sec: "Integrations" },
  { id:"mcp", label:"MCP server", pill:"new" },
  { id:"sdks", label:"SDKs" },
  { id:"cli", label:"CLI" },
  { sec: "Reference" },
  { id:"errors", label:"Errors" },
  { id:"limits", label:"Rate limits" },
  { id:"changelog", label:"Changelog" },
];

const DocsBlock = ({ id, eyebrow, title, sub, children }) => (
  <section id={id} style={{marginBottom:48, scrollMarginTop:80}}>
    {eyebrow && <div className="eyebrow" style={{marginBottom:8}}>{eyebrow}</div>}
    <h2 className="page-title" style={{fontSize:28, marginBottom:6}}>{title}</h2>
    {sub && <div className="page-sub" style={{marginBottom:18, marginTop:4}}>{sub}</div>}
    {children}
  </section>
);

const KV3 = ({rows}) => (
  <table className="tbl" style={{marginBottom:14}}>
    <thead><tr><th style={{width:"22%"}}>Field</th><th style={{width:"18%"}}>Type</th><th>Description</th></tr></thead>
    <tbody>
      {rows.map((r,i)=>(
        <tr key={i}>
          <td className="mono" style={{color:"var(--ember)"}}>{r[0]}</td>
          <td className="mono" style={{color:"var(--ink-3)"}}>{r[1]}</td>
          <td>{r[2]}</td>
        </tr>
      ))}
    </tbody>
  </table>
);

const Endpoint = ({ method, path, scope }) => (
  <div className="row" style={{gap:10, padding:"10px 14px", background:"var(--bg-2)", border:"1px solid var(--line)", borderRadius:"var(--r-md)", marginBottom:12, fontFamily:"var(--mono)", fontSize:12.5}}>
    <span style={{
      padding:"2px 7px", borderRadius:4, fontSize:10.5, fontWeight:600,
      background: method==="GET" ? "rgba(111,143,181,.12)" : method==="POST" ? "rgba(232,118,58,.12)" : method==="DELETE" ? "rgba(196,80,79,.12)" : "rgba(212,172,79,.12)",
      color: method==="GET" ? "var(--sky)" : method==="POST" ? "var(--ember)" : method==="DELETE" ? "var(--ruby)" : "var(--gold)",
      border: `1px solid ${method==="GET" ? "rgba(111,143,181,.3)" : method==="POST" ? "rgba(232,118,58,.3)" : method==="DELETE" ? "rgba(196,80,79,.3)" : "rgba(212,172,79,.3)"}`
    }}>{method}</span>
    <span style={{color:"var(--ink)"}}>{path}</span>
    {scope && <span style={{marginLeft:"auto", color:"var(--ink-3)", fontSize:11}}>scope · <span style={{color:"var(--ink-2)"}}>{scope}</span></span>}
  </div>
);

const Callout = ({ kind="note", title, children }) => {
  const cls = kind==="warn" ? "warn" : kind==="bad" ? "bad" : "";
  return (
    <div className={"drift " + cls} style={{display:"flex", flexDirection:"column", alignItems:"flex-start", gap:6, padding:"12px 14px", marginBottom:14}}>
      <div style={{fontWeight:600, fontFamily:"var(--sans)", fontSize:12.5, letterSpacing:".02em", textTransform:"uppercase"}}>{title || (kind==="warn"?"Caution":kind==="bad"?"Important":"Note")}</div>
      <div style={{fontFamily:"var(--sans)", fontSize:13, lineHeight:1.55, color:"var(--ink-2)"}}>{children}</div>
    </div>
  );
};

const PageDocs = () => {
  const [active, setActive] = dS("intro");
  const [lang, setLang] = dS("curl");
  const scrollRef = dR(null);

  // Track active section on scroll
  dE(()=>{
    const onScroll = () => {
      const ids = DOCS_NAV.filter(n=>!n.sec).map(n=>n.id);
      let cur = ids[0];
      for (const id of ids) {
        const el = document.getElementById(id);
        if (!el) continue;
        const r = el.getBoundingClientRect();
        if (r.top < 120) cur = id;
      }
      setActive(cur);
    };
    window.addEventListener("scroll", onScroll, {passive:true});
    return () => window.removeEventListener("scroll", onScroll);
  }, []);

  const jump = (id) => {
    const el = document.getElementById(id);
    if (!el) return;
    const y = el.getBoundingClientRect().top + window.scrollY - 70;
    window.scrollTo({top:y, behavior:"smooth"});
  };

  // Sample code snippets per language
  const snippetsCreate = {
    curl: `curl https://api.persona.dev/v1/personas \\
  -H "Authorization: Bearer $PERSONA_API_KEY" \\
  -H "Content-Type: application/json" \\
  -d '{
    "intent": "35-year-old, lonely, intellectual ex-academic bookseller in Istanbul",
    "language": "tr",
    "visibility": "workspace"
  }'`,
    ts: `import Persona from "@persona/sdk";

const client = new Persona({ apiKey: process.env.PERSONA_API_KEY });

const persona = await client.personas.create({
  intent: "35-year-old, lonely, intellectual ex-academic bookseller",
  language: "tr",
  visibility: "workspace",
});

console.log(persona.id, persona.surface.name);`,
    py: `from persona import Persona

client = Persona(api_key=os.environ["PERSONA_API_KEY"])

persona = client.personas.create(
    intent="35-year-old, lonely, intellectual ex-academic bookseller",
    language="tr",
    visibility="workspace",
)

print(persona.id, persona.surface.name)`,
  };

  const langPills = (
    <div className="pill-tabs" style={{marginBottom:10}}>
      {[["curl","cURL"],["ts","TypeScript"],["py","Python"]].map(([k,l])=>(
        <span key={k} className={"pt "+(lang===k?"on":"")} onClick={()=>setLang(k)}>{l}</span>
      ))}
    </div>
  );

  return (
    <div className="page" style={{padding:"24px 32px 80px", maxWidth:1380, display:"grid", gridTemplateColumns:"220px minmax(0,1fr) 220px", gap:32}}>
      {/* Left sub-nav */}
      <aside style={{position:"sticky", top:70, alignSelf:"start", maxHeight:"calc(100vh - 90px)", overflow:"auto"}}>
        <div className="eyebrow" style={{marginBottom:10}}>Developer docs</div>
        <div className="row" style={{gap:6, marginBottom:14}}>
          <span className="tag ember"><span className="dot"/>v1.0</span>
          <span className="tag"><span className="dot"/>stable</span>
        </div>
        <nav style={{display:"flex", flexDirection:"column", gap:1}}>
          {DOCS_NAV.map((n,i)=> n.sec ? (
            <div key={"s"+i} className="nav-section" style={{marginTop:14, padding:"4px 4px 6px"}}>{n.sec}</div>
          ) : (
            <div key={n.id}
                 onClick={()=>jump(n.id)}
                 style={{
                   display:"flex", alignItems:"center", padding:"5px 8px", borderRadius:4, cursor:"pointer",
                   fontSize:13, color: active===n.id?"var(--ink)":"var(--ink-3)",
                   background: active===n.id?"var(--bg-2)":"transparent",
                   boxShadow: active===n.id?"inset 2px 0 0 var(--ember)":"none"
                 }}>
              <span>{n.label}</span>
              {n.pill && <span className="pill" style={{marginLeft:"auto", fontSize:9.5, padding:"1px 6px", color: n.pill==="new"?"var(--ember)":"var(--ink-3)", borderColor: n.pill==="new"?"rgba(232,118,58,.3)":"var(--line)", background: n.pill==="new"?"rgba(232,118,58,.08)":"var(--bg-3)", borderRadius:999, border:"1px solid"}}>{n.pill}</span>}
            </div>
          ))}
        </nav>
      </aside>

      {/* Main content */}
      <div ref={scrollRef}>
        <div className="page-head" style={{marginBottom:30}}>
          <div className="eyebrow" style={{marginBottom:10}}>Persona — Developer reference</div>
          <h1 className="page-title">Build with personas. <span className="muted">Bring your own model, runtime, and tools.</span></h1>
          <div className="page-sub">REST + SSE API, OpenAI-compatible chat endpoint, MCP server, and SDKs for TypeScript, Python, and Go. All endpoints scoped to your workspace.</div>
          <div className="row" style={{gap:8, marginTop:14, flexWrap:"wrap"}}>
            <a className="btn primary"><span style={{fontFamily:"var(--mono)",fontSize:11}}>↗</span> Get an API key</a>
            <a className="btn">View on GitHub</a>
            <a className="btn ghost">OpenAPI spec ↓</a>
            <span className="tag" style={{marginLeft:"auto"}}><span className="dot"/>api.persona.dev/v1</span>
            <span className="tag moss"><span className="dot"/>all systems operational</span>
          </div>
        </div>

        <DocsBlock id="intro" eyebrow="Introduction" title="What is the Persona API?" sub="A character-consistency engine. Personas are 4-layer (Soul / Self / Mask / Surface) constructs that stay in voice across long conversations and multiple runs.">
          <div className="grid grid-2" style={{marginBottom:14}}>
            <div className="card card-pad">
              <div className="layer-eyebrow" style={{marginBottom:6}}>Built around three primitives</div>
              <ul style={{margin:0, paddingLeft:18, fontSize:13.5, lineHeight:1.7, color:"var(--ink-2)"}}>
                <li><b style={{color:"var(--ember)"}}>Personas</b> — generated, edited, forked, versioned.</li>
                <li><b style={{color:"var(--moss)"}}>Runs</b> — every generation is a tracked, replayable run.</li>
                <li><b style={{color:"var(--gold)"}}>Conversations</b> — multi-turn chat against any persona, with drift detection.</li>
              </ul>
            </div>
            <div className="card card-pad">
              <div className="layer-eyebrow" style={{marginBottom:6}}>You can call it three ways</div>
              <ul style={{margin:0, paddingLeft:18, fontSize:13.5, lineHeight:1.7, color:"var(--ink-2)"}}>
                <li>Native REST + SSE — <span className="mono" style={{color:"var(--ember)",fontFamily:"var(--mono)",fontSize:12}}>api.persona.dev/v1</span></li>
                <li>OpenAI-compatible — drop in as a model provider.</li>
                <li>MCP server — stream personas as tools to any MCP host.</li>
              </ul>
            </div>
          </div>
          <Callout kind="note">All requests require a workspace-scoped API key. Personas, runs, and conversations are tenant-isolated; nothing crosses workspaces unless you publish to the marketplace.</Callout>
        </DocsBlock>

        <DocsBlock id="quickstart" eyebrow="01" title="Quickstart" sub="Generate your first persona in 30 seconds. The full pipeline streams Soul → Self → Mask → Surface as it runs.">
          {langPills}
          <Code lang={lang==="curl"?"bash":lang}>{snippetsCreate[lang]}</Code>
          <div style={{height:14}}/>
          <div className="layer-eyebrow" style={{marginBottom:8}}>Response · 201 Created</div>
          <Code lang="json">{`{
  "id": "psn_3kP9aLwX2v",
  "slug": "the-istanbul-bookseller",
  "status": "completed",
  "language": "tr",
  "schema_version": "1.0",
  "soul":    { "core_desire": "...", "core_fear": "...", "wound": "..." },
  "self":    { "big_five": { "O": 0.82, "C": 0.61, "E": 0.22, "A": 0.55, "N": 0.74 }, "archetype": "the-sage" },
  "mask":    { "voice": { "register": "wry, slightly archaic" }, "public_bio": "..." },
  "surface": { "name": "Mert Kavaklı", "age": 35, "occupation": "Sahaf, eski akademisyen" },
  "fingerprint": "sha256:9c4a...",
  "run":     { "id": "run_a8K2zB", "cost_usd": 0.79, "tokens": 18421, "latency_ms": 24310 }
}`}</Code>
        </DocsBlock>

        <DocsBlock id="auth" eyebrow="02" title="Authentication" sub="Bearer-token auth with scoped, rotatable API keys. Each key belongs to one workspace and is bound to a single environment (live or test).">
          <div className="grid grid-2" style={{marginBottom:14}}>
            <div className="card card-pad">
              <div className="layer-eyebrow" style={{marginBottom:8}}>Header</div>
              <Code lang="http">{`Authorization: Bearer pk_live_abcd1234efgh5678
Persona-Workspace: ws_acme_studio
Idempotency-Key: 8f3c2e1a-...     # optional`}</Code>
            </div>
            <div className="card card-pad">
              <div className="layer-eyebrow" style={{marginBottom:8}}>Available scopes</div>
              <div className="row wrap" style={{gap:6}}>
                {["personas:read","personas:write","personas:fork","runs:read","runs:cancel","chat:invoke","chat:read","webhooks:manage","config:read","config:write","keys:manage"].map(s=>(
                  <span key={s} className="tag" style={{fontSize:10.5}}><span className="dot"/>{s}</span>
                ))}
              </div>
              <div className="muted" style={{fontSize:12, marginTop:10}}>Default key: <span className="mono" style={{color:"var(--ember)",fontFamily:"var(--mono)"}}>personas:* runs:read chat:invoke</span></div>
            </div>
          </div>
          <Callout kind="warn" title="Key handling">Keys with <span className="mono" style={{fontFamily:"var(--mono)",color:"var(--ember)"}}>pk_live_</span> prefix are unmasked once at creation and never again. Rotate within 90 days. Live keys cannot be used against test workspaces, and vice versa.</Callout>
        </DocsBlock>

        <DocsBlock id="personas" eyebrow="03" title="Personas" sub="Create, read, fork, refine, and version personas. All mutations emit domain events you can subscribe to via webhooks.">
          <Endpoint method="POST"   path="/v1/personas"                scope="personas:write"/>
          <Endpoint method="GET"    path="/v1/personas"                scope="personas:read"/>
          <Endpoint method="GET"    path="/v1/personas/{id}"            scope="personas:read"/>
          <Endpoint method="PATCH"  path="/v1/personas/{id}"            scope="personas:write"/>
          <Endpoint method="POST"   path="/v1/personas/{id}/refine"     scope="personas:write"/>
          <Endpoint method="POST"   path="/v1/personas/{id}/fork"       scope="personas:fork"/>
          <Endpoint method="POST"   path="/v1/personas/{id}/rollback/{n}" scope="personas:write"/>
          <Endpoint method="DELETE" path="/v1/personas/{id}"            scope="personas:write"/>

          <h3 className="section-title" style={{marginTop:24, marginBottom:10}}>Create — request body</h3>
          <KV3 rows={[
            ["intent",       "string",            <>Free-form character brief (1–4000 chars). Required.</>],
            ["language",     "ISO-639-1",         <>Persona's primary speaking language. Default <span className="mono" style={{fontFamily:"var(--mono)",color:"var(--ember)"}}>en</span>.</>],
            ["visibility",   "enum",              <>One of <span className="mono" style={{fontFamily:"var(--mono)"}}>private</span>, <span className="mono" style={{fontFamily:"var(--mono)"}}>workspace</span>, <span className="mono" style={{fontFamily:"var(--mono)"}}>public</span>. Default <span className="mono" style={{fontFamily:"var(--mono)"}}>private</span>.</>],
            ["pipeline",     "string",            <>Override the active pipeline (Team+). e.g. <span className="mono" style={{fontFamily:"var(--mono)"}}>strict-audit</span>.</>],
            ["seed",         "integer",           <>Reproducibility seed. Pinned across the run.</>],
            ["budget_usd",   "number",            <>Hard cost cap. Run aborts with <span className="mono" style={{fontFamily:"var(--mono)",color:"var(--ruby)"}}>402</span> if exceeded.</>],
            ["custom_fields","object",            <>Workspace-defined fields registered via <span className="mono" style={{fontFamily:"var(--mono)"}}>POST /v1/schema/fields</span>.</>],
          ]}/>

          <h3 className="section-title" style={{marginTop:18, marginBottom:10}}>Persona object — top-level keys</h3>
          <KV3 rows={[
            ["soul",     "Soul",     "Core desire, fear, conflict, wound, growth arc."],
            ["self",     "Self",     "Big Five, archetype, values, attachment style, temperament."],
            ["mask",     "Mask",     "Voice profile, public bio, social role, presentation style."],
            ["surface",  "Surface",  "Demographic ground truth — name, age, occupation, location."],
            ["narrative","Narrative","Bios, key events, secrets, contradictions."],
            ["runtime",  "Runtime",  "System prompt, example dialogues, guardrails, tool permissions."],
            ["meta",     "Meta",     "Schema version, quality scores, tags, license, fingerprint."],
          ]}/>
        </DocsBlock>

        <DocsBlock id="chat" eyebrow="04" title="Chat runtime" sub="Multi-turn conversations against a persona. Drift, coherence, and tool-use are tracked per message.">
          <Endpoint method="POST" path="/v1/chat/conversations"                  scope="chat:invoke"/>
          <Endpoint method="POST" path="/v1/chat/conversations/{id}/messages"    scope="chat:invoke"/>
          <Endpoint method="GET"  path="/v1/chat/conversations/{id}"             scope="chat:read"/>

          <Code lang="bash">{`curl https://api.persona.dev/v1/chat/conversations/conv_72/messages \\
  -H "Authorization: Bearer $PERSONA_API_KEY" \\
  -H "Content-Type: application/json" \\
  -d '{
    "persona_id": "psn_3kP9aLwX2v",
    "message": "Sahafına yeni gelen bir kitabı anlatır mısın?",
    "tools": ["web.search"],
    "stream": true
  }'`}</Code>

          <div style={{height:12}}/>
          <div className="layer-eyebrow" style={{marginBottom:8}}>Response — assistant turn</div>
          <Code lang="json">{`{
  "message_id": "msg_91xQ",
  "role": "assistant",
  "content": "Bu sabah elime, 1973 baskısı bir Yaşar Kemal geçti. Kapağı...",
  "drift": { "voice": 0.08, "values": 0.04, "verdict": "in-character" },
  "coherence": 4.6,
  "tools_used": [],
  "tokens": { "in": 1240, "out": 312 },
  "cost_usd": 0.014
}`}</Code>
        </DocsBlock>

        <DocsBlock id="openai" eyebrow="05 · compat" title="OpenAI-compatible endpoint" sub="Drop Persona into any OpenAI SDK by changing two strings. Personas are exposed as model IDs; the rest of the surface area is identical.">
          <div className="grid grid-2" style={{marginBottom:14, gap:14}}>
            <div className="card card-pad">
              <div className="layer-eyebrow" style={{marginBottom:8}}>Base URL</div>
              <Code lang="http">{`POST  /v1/openai/chat/completions
POST  /v1/openai/embeddings
GET   /v1/openai/models`}</Code>
              <div className="muted" style={{fontSize:12, marginTop:8}}>Host: <span className="mono" style={{fontFamily:"var(--mono)",color:"var(--ember)"}}>api.persona.dev</span></div>
            </div>
            <div className="card card-pad">
              <div className="layer-eyebrow" style={{marginBottom:8}}>Model naming</div>
              <Code lang="http">{`persona/{persona_id}
persona/{persona_slug}
persona/{persona_slug}@{version}`}</Code>
              <div className="muted" style={{fontSize:12, marginTop:8}}>e.g. <span className="mono" style={{fontFamily:"var(--mono)"}}>persona/the-istanbul-bookseller@v3</span></div>
            </div>
          </div>

          <Code lang="ts">{`import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://api.persona.dev/v1/openai",
  apiKey: process.env.PERSONA_API_KEY,
});

const completion = await client.chat.completions.create({
  model: "persona/the-istanbul-bookseller",
  messages: [
    { role: "user", content: "Sevdiğin bir şair var mı?" },
  ],
  temperature: 0.8,
});

console.log(completion.choices[0].message.content);`}</Code>

          <h3 className="section-title" style={{marginTop:22, marginBottom:10}}>Compatibility matrix</h3>
          <table className="tbl">
            <thead><tr><th>Feature</th><th style={{width:120}}>Status</th><th>Notes</th></tr></thead>
            <tbody>
              <tr><td>chat.completions</td><td><span className="tag moss"><span className="dot"/>full</span></td><td>Including tools, streaming, JSON mode.</td></tr>
              <tr><td>embeddings</td><td><span className="tag moss"><span className="dot"/>full</span></td><td>Voyage v3 by default; configurable.</td></tr>
              <tr><td>moderation</td><td><span className="tag gold"><span className="dot"/>partial</span></td><td>Persona-aware classifier; categories differ slightly.</td></tr>
              <tr><td>audio.*</td><td><span className="tag"><span className="dot"/>roadmap</span></td><td>Voice cloning for Mask layer is planned for Q3.</td></tr>
              <tr><td>fine_tuning.*</td><td><span className="tag ruby"><span className="dot"/>n/a</span></td><td>Use Persona refine + version history instead.</td></tr>
              <tr><td>system messages</td><td><span className="tag gold"><span className="dot"/>overlay</span></td><td>Merged on top of the persona's runtime prompt.</td></tr>
            </tbody>
          </table>
          <Callout kind="warn" title="Header passthrough">Pass <span className="mono" style={{fontFamily:"var(--mono)",color:"var(--ember)"}}>X-Persona-Conversation-Id</span> to attach a completion to an existing conversation — drift and lineage will be tracked. Without it, each request is a one-shot.</Callout>
        </DocsBlock>

        <DocsBlock id="streaming" eyebrow="06" title="Streaming (SSE)" sub="Pipeline events stream as they happen. Use during creation to render Soul/Self/Mask/Surface progressively.">
          <Code lang="bash">{`curl -N https://api.persona.dev/v1/personas?stream=true \\
  -H "Authorization: Bearer $PERSONA_API_KEY" \\
  -H "Accept: text/event-stream" \\
  -d '{"intent": "..."}'`}</Code>

          <div style={{height:12}}/>
          <Code lang="http">{`event: run.started
data: {"run_id":"run_a8K","step":"intent_parse"}

event: step.completed
data: {"step":"soul_draft","tokens":2104,"cost_usd":0.08}

event: layer.delta
data: {"path":"soul.core_desire","value":"To be seen ..."}

event: run.completed
data: {"persona_id":"psn_3kP9aLwX2v","total_cost_usd":0.79}`}</Code>

          <h3 className="section-title" style={{marginTop:22, marginBottom:10}}>Event types</h3>
          <KV3 rows={[
            ["run.started",    "event", "Pipeline begins; emits run_id and pipeline version."],
            ["step.started",   "event", "A pipeline step (intent_parse, soul_draft, …) entered."],
            ["layer.delta",    "event", "Streaming JSON-patch of the persona being assembled."],
            ["step.completed", "event", "Step finished with tokens / cost / latency."],
            ["step.failed",    "event", "Step failed — pipeline may retry depending on config."],
            ["run.completed",  "event", "Final persona is persisted; full object included."],
            ["run.cancelled",  "event", "Client closed the connection or called /cancel."],
          ]}/>
        </DocsBlock>

        <DocsBlock id="webhooks" eyebrow="07" title="Webhooks" sub="HMAC-SHA256 signed deliveries with exponential-backoff retries. Replay any event from the dashboard.">
          <Endpoint method="POST"   path="/v1/webhooks"            scope="webhooks:manage"/>
          <Endpoint method="GET"    path="/v1/webhooks"            scope="webhooks:manage"/>
          <Endpoint method="POST"   path="/v1/webhooks/{id}/rotate" scope="webhooks:manage"/>
          <Endpoint method="DELETE" path="/v1/webhooks/{id}"        scope="webhooks:manage"/>

          <h3 className="section-title" style={{marginTop:18, marginBottom:10}}>Verifying signatures</h3>
          <Code lang="ts">{`import crypto from "node:crypto";

export function verify(req, secret) {
  const sig = req.headers["persona-signature"];        // "t=...,v1=..."
  const [t, v1] = sig.split(",").map(p => p.split("=")[1]);
  const payload = t + "." + req.rawBody;
  const expected = crypto.createHmac("sha256", secret).update(payload).digest("hex");
  if (!crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(expected))) {
    throw new Error("invalid signature");
  }
  if (Date.now() / 1000 - Number(t) > 300) throw new Error("stale");
}`}</Code>

          <h3 className="section-title" style={{marginTop:22, marginBottom:10}}>Subscribable events</h3>
          <div className="row wrap" style={{gap:6}}>
            {["persona.created","persona.updated","persona.forked","persona.archived","run.completed","run.failed","conversation.drift_detected","moderation.flagged","audit.test_failed","webhook.test"].map(e=>(
              <span key={e} className="tag"><span className="dot"/>{e}</span>
            ))}
          </div>
          <Callout kind="note">Retries: 5 attempts over ~1h with jitter. After exhaustion, deliveries land in the dead-letter queue and can be replayed for 30 days.</Callout>
        </DocsBlock>

        <DocsBlock id="mcp" eyebrow="08 · new" title="MCP server" sub="Expose your personas as tools to any Model Context Protocol host — Claude Desktop, Cursor, Zed, custom agents. One workspace, one server URL.">
          <div className="grid grid-2" style={{gap:14, marginBottom:14}}>
            <div className="card card-pad">
              <div className="layer-eyebrow" style={{marginBottom:8}}>Server URL</div>
              <Code lang="http">{`https://mcp.persona.dev/sse
Authorization: Bearer $PERSONA_API_KEY
Persona-Workspace: ws_acme_studio`}</Code>
              <div className="muted" style={{fontSize:12, marginTop:8}}>SSE transport · stdio bridge available via the CLI.</div>
            </div>
            <div className="card card-pad">
              <div className="layer-eyebrow" style={{marginBottom:8}}>Exposed tools</div>
              <ul style={{margin:0, paddingLeft:18, fontSize:13, lineHeight:1.7, color:"var(--ink-2)"}}>
                <li><span className="mono" style={{fontFamily:"var(--mono)",color:"var(--ember)"}}>persona.invoke</span> — chat against a persona</li>
                <li><span className="mono" style={{fontFamily:"var(--mono)",color:"var(--ember)"}}>persona.search</span> — semantic + keyword search</li>
                <li><span className="mono" style={{fontFamily:"var(--mono)",color:"var(--ember)"}}>persona.fork</span> — fork from a parent</li>
                <li><span className="mono" style={{fontFamily:"var(--mono)",color:"var(--ember)"}}>ensemble.scenario</span> — multi-persona scene</li>
              </ul>
            </div>
          </div>

          <h3 className="section-title" style={{marginTop:8, marginBottom:10}}>Claude Desktop config</h3>
          <Code lang="json">{`{
  "mcpServers": {
    "persona": {
      "command": "npx",
      "args": ["-y", "@persona/mcp", "--workspace", "ws_acme_studio"],
      "env": { "PERSONA_API_KEY": "pk_live_..." }
    }
  }
}`}</Code>

          <h3 className="section-title" style={{marginTop:22, marginBottom:10}}>Tool: persona.invoke</h3>
          <KV3 rows={[
            ["persona",      "string",  "Persona ID, slug, or slug@version."],
            ["message",      "string",  "User turn. Required."],
            ["conversation", "string?", "Existing conversation ID for continuity."],
            ["budget_usd",   "number?", "Per-call cost cap."],
            ["temperature",  "number?", "Override the persona's runtime temperature."],
          ]}/>
          <Callout kind="warn" title="Permissions">MCP clients only see personas your API key can read. Personas with <span className="mono" style={{fontFamily:"var(--mono)"}}>visibility=private</span> are excluded unless the key owner created them.</Callout>
        </DocsBlock>

        <DocsBlock id="sdks" eyebrow="09" title="SDKs">
          <div className="grid grid-3" style={{gap:14}}>
            {[
              ["TypeScript", "@persona/sdk",   "npm i @persona/sdk", "v1.0.4", "moss"],
              ["Python",     "persona-sdk",    "pip install persona-sdk", "v1.0.2", "moss"],
              ["Go",         "persona-go",     "go get persona.dev/sdk", "v0.9.0", "gold"],
              ["Ruby",       "persona-ruby",   "gem install persona-sdk", "v0.6.1", "gold"],
              ["Rust",       "persona-rs",     "cargo add persona", "v0.4.0", "gold"],
              ["Elixir",     "persona_ex",     "{:persona, \"~> 0.3\"}", "v0.3.0", ""],
            ].map(([name, pkg, install, ver, tone])=>(
              <div key={name} className="card card-pad" style={{padding:"14px 16px"}}>
                <div className="row between" style={{marginBottom:6}}>
                  <div className="section-title" style={{fontSize:15}}>{name}</div>
                  <span className={"tag "+tone} style={{fontSize:10}}><span className="dot"/>{ver}</span>
                </div>
                <div className="muted mono" style={{fontFamily:"var(--mono)", fontSize:11, marginBottom:8}}>{pkg}</div>
                <div className="code" style={{fontSize:11.5, padding:"8px 10px"}}>{install}</div>
              </div>
            ))}
          </div>
        </DocsBlock>

        <DocsBlock id="cli" eyebrow="10" title="CLI" sub="Scripting + local development workflows.">
          <Code lang="bash">{`# install
npm i -g @persona/cli

# log in (opens browser)
persona auth login

# bridge MCP over stdio for Claude Desktop / Cursor
persona mcp serve --workspace ws_acme_studio

# create a persona from a markdown brief
persona personas create -f ./brief.md --visibility workspace

# tail run events
persona runs tail run_a8K2zB

# pull a persona to a local YAML file (round-trips with edit + push)
persona personas pull psn_3kP9aLwX2v -o bookseller.yml`}</Code>
        </DocsBlock>

        <DocsBlock id="errors" eyebrow="11" title="Errors" sub="All errors are JSON; HTTP status mirrors the category. Every error carries a request_id you can quote to support.">
          <Code lang="json">{`{
  "error": {
    "code":     "persona.cost_budget_exceeded",
    "message":  "Run aborted: $1.20 exceeds budget $1.00.",
    "type":     "billing",
    "doc_url":  "https://docs.persona.dev/errors#cost_budget_exceeded",
    "request_id": "req_8f3c2e1a9b",
    "run_id":     "run_a8K2zB"
  }
}`}</Code>

          <h3 className="section-title" style={{marginTop:22, marginBottom:10}}>Status reference</h3>
          <table className="tbl">
            <thead><tr><th style={{width:80}}>Status</th><th style={{width:240}}>Code</th><th>When</th></tr></thead>
            <tbody>
              <tr><td className="mono">400</td><td className="mono" style={{color:"var(--ember)"}}>request.invalid</td><td>Malformed body, unknown field, schema mismatch.</td></tr>
              <tr><td className="mono">401</td><td className="mono" style={{color:"var(--ember)"}}>auth.invalid_key</td><td>Missing or revoked key.</td></tr>
              <tr><td className="mono">402</td><td className="mono" style={{color:"var(--ember)"}}>persona.cost_budget_exceeded</td><td>Run hit hard budget cap.</td></tr>
              <tr><td className="mono">403</td><td className="mono" style={{color:"var(--ember)"}}>moderation.intent_blocked</td><td>Intent blocked by moderation policy.</td></tr>
              <tr><td className="mono">409</td><td className="mono" style={{color:"var(--ember)"}}>persona.slug_taken</td><td>Slug collision in workspace.</td></tr>
              <tr><td className="mono">422</td><td className="mono" style={{color:"var(--ember)"}}>persona.schema_violation</td><td>Cross-layer consistency check failed.</td></tr>
              <tr><td className="mono">429</td><td className="mono" style={{color:"var(--ember)"}}>rate_limit.exceeded</td><td>Slow down — see <span className="mono" style={{fontFamily:"var(--mono)"}}>Retry-After</span>.</td></tr>
              <tr><td className="mono">503</td><td className="mono" style={{color:"var(--ember)"}}>provider.unavailable</td><td>Upstream model provider failure (fallback exhausted).</td></tr>
            </tbody>
          </table>
        </DocsBlock>

        <DocsBlock id="limits" eyebrow="12" title="Rate limits" sub="Token-bucket per workspace + per key. Live and test envs have separate buckets.">
          <table className="tbl" style={{marginBottom:14}}>
            <thead><tr><th>Plan</th><th>Generations / min</th><th>Chat msgs / min</th><th>Concurrent runs</th><th>Webhook deliveries / min</th></tr></thead>
            <tbody>
              <tr><td>Free</td><td className="mono">5</td><td className="mono">30</td><td className="mono">1</td><td className="mono">60</td></tr>
              <tr><td>Pro</td><td className="mono">60</td><td className="mono">600</td><td className="mono">10</td><td className="mono">600</td></tr>
              <tr><td>Team</td><td className="mono">300</td><td className="mono">3 000</td><td className="mono">50</td><td className="mono">3 000</td></tr>
              <tr><td>Enterprise</td><td className="mono">custom</td><td className="mono">custom</td><td className="mono">custom</td><td className="mono">custom</td></tr>
            </tbody>
          </table>
          <div className="layer-eyebrow" style={{marginBottom:8}}>Headers on every response</div>
          <Code lang="http">{`X-RateLimit-Limit:     60
X-RateLimit-Remaining: 41
X-RateLimit-Reset:     1746790012
Retry-After:           7`}</Code>
        </DocsBlock>

        <DocsBlock id="changelog" eyebrow="13" title="Changelog">
          <div className="col" style={{gap:12}}>
            {[
              ["2026-05-09", "v1.0.4", "moss", "MCP server stable. New tool: ensemble.scenario."],
              ["2026-04-22", "v1.0.3", "",     "OpenAI compat: tools + JSON mode reach parity."],
              ["2026-04-08", "v1.0.2", "",     "SSE: layer.delta now emits JSON-patch (was full snapshots)."],
              ["2026-03-25", "v1.0.1", "",     "Webhooks: signed timestamp + 5min replay window."],
              ["2026-03-11", "v1.0.0", "ember","General availability. SLA 99.9%, regional residency."],
            ].map(([d,v,tone,note], i)=>(
              <div key={i} className="row" style={{gap:14, alignItems:"flex-start", padding:"10px 0", borderBottom: i<4 ? "1px solid var(--line)" : "none"}}>
                <div className="mono" style={{fontFamily:"var(--mono)", fontSize:11.5, color:"var(--ink-3)", width:90}}>{d}</div>
                <span className={"tag "+tone} style={{minWidth:62, justifyContent:"center"}}><span className="dot"/>{v}</span>
                <div style={{fontSize:13.5, color:"var(--ink-2)", lineHeight:1.55}}>{note}</div>
              </div>
            ))}
          </div>
        </DocsBlock>
      </div>

      {/* Right rail — on-this-page (decorative anchor) */}
      <aside style={{position:"sticky", top:70, alignSelf:"start", maxHeight:"calc(100vh - 90px)", overflow:"auto"}}>
        <div className="eyebrow" style={{marginBottom:10}}>On this page</div>
        <div style={{display:"flex", flexDirection:"column", gap:6, fontSize:12.5}}>
          {DOCS_NAV.filter(n=>!n.sec).map(n=>(
            <div key={n.id} onClick={()=>jump(n.id)} style={{cursor:"pointer", color: active===n.id?"var(--ember)":"var(--ink-3)", padding:"2px 0", borderLeft: active===n.id?"2px solid var(--ember)":"2px solid transparent", paddingLeft:10}}>{n.label}</div>
          ))}
        </div>
        <div className="divider"/>
        <div className="card card-pad" style={{padding:"12px 14px"}}>
          <div className="layer-eyebrow" style={{marginBottom:6}}>Need help?</div>
          <div style={{fontSize:12.5, color:"var(--ink-2)", lineHeight:1.55, marginBottom:10}}>Pair with a Persona engineer in your stack — TypeScript, Python, or Go.</div>
          <button className="btn btn-sm">Book office hours →</button>
        </div>
      </aside>
    </div>
  );
};

window.PageDocs = PageDocs;
