ソースを参照

chore: generate

opencode-agent[bot] 3 ヶ月 前
コミット
e7aed64949
1 ファイル変更565 行追加185 行削除
  1. 565 185
      specs/v2/api.html

+ 565 - 185
specs/v2/api.html

@@ -17,7 +17,13 @@
         --accent: #496b5a;
         --accent-soft: #dce7dc;
         font-family:
-          Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
+          Inter,
+          ui-sans-serif,
+          system-ui,
+          -apple-system,
+          BlinkMacSystemFont,
+          "Segoe UI",
+          sans-serif;
       }
 
       * {
@@ -34,8 +40,7 @@
         background:
           radial-gradient(circle at 12% 0%, rgba(73, 107, 90, 0.12), transparent 34rem),
           linear-gradient(90deg, rgba(38, 52, 47, 0.055) 1px, transparent 1px),
-          linear-gradient(rgba(38, 52, 47, 0.045) 1px, transparent 1px),
-          var(--bg);
+          linear-gradient(rgba(38, 52, 47, 0.045) 1px, transparent 1px), var(--bg);
         background-size: 72px 72px;
         color: var(--fg);
         line-height: 1.5;
@@ -231,7 +236,13 @@
       .diagram text {
         fill: var(--fg);
         font-family:
-          Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
+          Inter,
+          ui-sans-serif,
+          system-ui,
+          -apple-system,
+          BlinkMacSystemFont,
+          "Segoe UI",
+          sans-serif;
       }
 
       .diagram .box {
@@ -412,7 +423,10 @@
 
       <section class="grid">
         <article class="span-8 rule">
-          <strong>Everything has one canonical route. Some routes are server-scoped; runtime routes use context; session item routes use the session.</strong>
+          <strong
+            >Everything has one canonical route. Some routes are server-scoped; runtime routes use context; session item
+            routes use the session.</strong
+          >
           <p>
             Server-scoped routes manage the whole server: projects, workspace lifecycle, and auth accounts. Runtime
             context is for anything resolved from an active directory, including config, provider capabilities, tools,
@@ -432,7 +446,9 @@
           <h2>Context Model</h2>
           <svg class="diagram" viewBox="0 0 1280 360" role="img" aria-labelledby="ctx-title ctx-desc">
             <title id="ctx-title">API context resolution</title>
-            <desc id="ctx-desc">Non-session routes resolve from request context, session item routes resolve from session storage.</desc>
+            <desc id="ctx-desc">
+              Non-session routes resolve from request context, session item routes resolve from session storage.
+            </desc>
             <defs>
               <marker id="arrow" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto">
                 <path d="M0,0 L0,6 L9,3 z" fill="#26342f" />
@@ -468,8 +484,8 @@
         <article class="span-6 panel panel-pad stack">
           <h3>Request-context calls</h3>
           <p class="muted">
-            These calls operate against a directory, optionally through a workspace. Simple clients omit context and
-            use the default runtime.
+            These calls operate against a directory, optionally through a workspace. Simple clients omit context and use
+            the default runtime.
           </p>
           <pre><code>GET /api/fs/tree?path=.&directory=/repo/app&workspace=ws_123</code></pre>
         </article>
@@ -491,187 +507,551 @@ sessionID -&gt; { directory, workspaceID? }</code></pre>
         <div class="span-12 stack">
           <h2>Operation Inventory</h2>
           <p class="muted">
-            The SDK is the source of truth. HTTP routes are mounts for RPC-style operations. <span class="context-tag server">server</span> operations do not use runtime context. <span class="context-tag request">request</span> operations use request/default runtime context from <code>directory</code> and <code>workspace</code> query parameters. <span class="context-tag session">session</span> operations use pinned session context and should not accept context input.
+            The SDK is the source of truth. HTTP routes are mounts for RPC-style operations.
+            <span class="context-tag server">server</span> operations do not use runtime context.
+            <span class="context-tag request">request</span> operations use request/default runtime context from
+            <code>directory</code> and <code>workspace</code> query parameters.
+            <span class="context-tag session">session</span> operations use pinned session context and should not accept
+            context input.
           </p>
         </div>
 
         <article class="span-12 panel panel-pad stack">
           <table>
-            <thead><tr><th>Operation</th><th>Input</th><th>Context</th><th>HTTP mount</th><th>Purpose</th></tr></thead>
+            <thead>
+              <tr>
+                <th>Operation</th>
+                <th>Input</th>
+                <th>Context</th>
+                <th>HTTP mount</th>
+                <th>Purpose</th>
+              </tr>
+            </thead>
             <tbody>
-              <tr><td class="operation"><code>agent.list</code></td><td class="body"><code>{}</code></td><td><span class="context-tag request">request</span></td><td class="route"><code>GET /api/agent</code></td><td>Available agents.</td></tr>
-              <tr><td class="operation"><code>auth.activate</code></td><td class="body"><code>{ accountID: AccountID }</code></td><td><span class="context-tag server">server</span></td><td class="route"><code>POST /api/auth/:accountID/activate</code></td><td>Set the account as active for its service.</td></tr>
-              <tr><td class="operation"><code>auth.create</code></td><td class="body"><code>{
-  serviceID: ServiceID
-  credential:
-    | { type: "oauth", refresh: string, access: string, expires: number }
-    | { type: "api", key: string, metadata?: Record&lt;string, string&gt; }
-  description?: string
-  active?: boolean
-}</code></td><td><span class="context-tag server">server</span></td><td class="route"><code>POST /api/auth</code></td><td>Create an auth account.</td></tr>
-              <tr><td class="operation"><code>auth.delete</code></td><td class="body"><code>{ accountID: AccountID }</code></td><td><span class="context-tag server">server</span></td><td class="route"><code>DELETE /api/auth/:accountID</code></td><td>Remove an auth account.</td></tr>
-              <tr><td class="operation"><code>auth.get</code></td><td class="body"><code>{ accountID: AccountID }</code></td><td><span class="context-tag server">server</span></td><td class="route"><code>GET /api/auth/:accountID</code></td><td>Get one auth account.</td></tr>
-              <tr><td class="operation"><code>auth.list</code></td><td class="body"><code>{ serviceID?: ServiceID }</code></td><td><span class="context-tag server">server</span></td><td class="route"><code>GET /api/auth</code></td><td>List saved auth accounts. Response includes active account mapping.</td></tr>
-              <tr><td class="operation"><code>auth.update</code></td><td class="body"><code>{
-  accountID: AccountID
-  description?: string
-  credential?:
-    | { type: "oauth", refresh: string, access: string, expires: number }
-    | { type: "api", key: string, metadata?: Record&lt;string, string&gt; }
-}</code></td><td><span class="context-tag server">server</span></td><td class="route"><code>PATCH /api/auth/:accountID</code></td><td>Update account description or credential.</td></tr>
-              <tr><td class="operation"><code>catalog.model.get</code></td><td class="body"><code>{
-  providerID: ProviderID
-  modelID: ModelID
-}</code></td><td><span class="context-tag server">server</span></td><td class="route"><code>GET /api/catalog/model/:providerID/:modelID</code></td><td>Get one catalog model.</td></tr>
-              <tr><td class="operation"><code>catalog.model.list</code></td><td class="body"><code>{}</code></td><td><span class="context-tag server">server</span></td><td class="route"><code>GET /api/catalog/model</code></td><td>List flattened catalog models.</td></tr>
-              <tr><td class="operation"><code>command.list</code></td><td class="body"><code>{}</code></td><td><span class="context-tag request">request</span></td><td class="route"><code>GET /api/command</code></td><td>Available commands.</td></tr>
-              <tr><td class="operation"><code>config.get</code></td><td class="body"><code>{}</code></td><td><span class="context-tag request">request</span></td><td class="route"><code>GET /api/config</code></td><td>Resolved config.</td></tr>
-              <tr><td class="operation"><code>config.update</code></td><td class="body"><code>{ config: Config }</code></td><td><span class="context-tag request">request</span></td><td class="route"><code>PATCH /api/config</code></td><td>Update config.</td></tr>
-              <tr><td class="operation"><code>event.subscribe</code></td><td class="body"><code>{}</code></td><td><span class="context-tag request">request</span></td><td class="route"><code>GET /api/event</code></td><td>Server-sent events for the resolved runtime context.</td></tr>
-              <tr><td class="operation"><code>formatter.status</code></td><td class="body"><code>{}</code></td><td><span class="context-tag request">request</span></td><td class="route"><code>GET /api/formatter</code></td><td>Formatter status.</td></tr>
-              <tr><td class="operation"><code>fs.file</code></td><td class="body"><code>{ path: string }</code></td><td><span class="context-tag request">request</span></td><td class="route"><code>GET /api/fs/file</code></td><td>Read one file.</td></tr>
-              <tr><td class="operation"><code>fs.grep</code></td><td class="body"><code>{
-  pattern: string
-  include?: string
-  limit?: number
-}</code></td><td><span class="context-tag request">request</span></td><td class="route"><code>POST /api/fs/grep</code></td><td>Search file contents.</td></tr>
-              <tr><td class="operation"><code>fs.search</code></td><td class="body"><code>{
-  query: string
-  type?: "file" | "directory"
-  limit?: number
-}</code></td><td><span class="context-tag request">request</span></td><td class="route"><code>POST /api/fs/search</code></td><td>Search paths by name.</td></tr>
-              <tr><td class="operation"><code>fs.tree</code></td><td class="body"><code>{ path: string }</code></td><td><span class="context-tag request">request</span></td><td class="route"><code>GET /api/fs/tree</code></td><td>Browse a directory.</td></tr>
-              <tr><td class="operation"><code>lsp.status</code></td><td class="body"><code>{}</code></td><td><span class="context-tag request">request</span></td><td class="route"><code>GET /api/lsp</code></td><td>LSP status.</td></tr>
-              <tr><td class="operation"><code>mcp.prompt.list</code></td><td class="body"><code>{}</code></td><td><span class="context-tag request">request</span></td><td class="route"><code>GET /api/mcp/prompt</code></td><td>List MCP prompts.</td></tr>
-              <tr><td class="operation"><code>mcp.prompt.render</code></td><td class="body"><code>{
-  server: string
-  name: string
-  arguments?: Record&lt;string, string&gt;
-}</code></td><td><span class="context-tag request">request</span></td><td class="route"><code>POST /api/mcp/prompt/render</code></td><td>Render one MCP prompt.</td></tr>
-              <tr><td class="operation"><code>mcp.resource.list</code></td><td class="body"><code>{}</code></td><td><span class="context-tag request">request</span></td><td class="route"><code>GET /api/mcp/resource</code></td><td>List MCP resources.</td></tr>
-              <tr><td class="operation"><code>mcp.resource.read</code></td><td class="body"><code>{
-  server: string
-  uri: string
-}</code></td><td><span class="context-tag request">request</span></td><td class="route"><code>GET /api/mcp/resource/read</code></td><td>Read one MCP resource.</td></tr>
-              <tr><td class="operation"><code>mcp.server.create</code></td><td class="body"><code>{
-  name: string
-  config:
-    | { type: "local", command: string, arguments?: string[], environment?: Record&lt;string, string&gt; }
-    | { type: "remote", url: string, headers?: Record&lt;string, string&gt;, oauth?: boolean | object }
-}</code></td><td><span class="context-tag request">request</span></td><td class="route"><code>POST /api/mcp/server</code></td><td>Add an MCP server to runtime config.</td></tr>
-              <tr><td class="operation"><code>mcp.server.list</code></td><td class="body"><code>{}</code></td><td><span class="context-tag request">request</span></td><td class="route"><code>GET /api/mcp/server</code></td><td>List MCP servers with status and auth state.</td></tr>
-              <tr><td class="operation"><code>mcp.server.oauth.callback</code></td><td class="body"><code>{
-  name: string
-  code: string
-}</code></td><td><span class="context-tag request">request</span></td><td class="route"><code>POST /api/mcp/server/:name/oauth/callback</code></td><td>Complete MCP OAuth.</td></tr>
-              <tr><td class="operation"><code>mcp.server.oauth.delete</code></td><td class="body"><code>{ name: string }</code></td><td><span class="context-tag request">request</span></td><td class="route"><code>DELETE /api/mcp/server/:name/oauth</code></td><td>Remove MCP OAuth credentials.</td></tr>
-              <tr><td class="operation"><code>mcp.server.oauth.start</code></td><td class="body"><code>{ name: string }</code></td><td><span class="context-tag request">request</span></td><td class="route"><code>POST /api/mcp/server/:name/oauth</code></td><td>Start MCP OAuth.</td></tr>
-              <tr><td class="operation"><code>permission.list</code></td><td class="body"><code>{}</code></td><td><span class="context-tag request">request</span></td><td class="route"><code>GET /api/permission</code></td><td>Pending permission requests.</td></tr>
-              <tr><td class="operation"><code>permission.reply</code></td><td class="body"><code>{
-  permissionID: PermissionID
-  response: PermissionReply
-}</code></td><td><span class="context-tag request">request</span></td><td class="route"><code>POST /api/permission/:permissionID/reply</code></td><td>Reply to a permission request.</td></tr>
-              <tr><td class="operation"><code>project.get</code></td><td class="body"><code>{ projectID: ProjectID }</code></td><td><span class="context-tag server">server</span></td><td class="route"><code>GET /api/project/:projectID</code></td><td>Get project metadata.</td></tr>
-              <tr><td class="operation"><code>project.list</code></td><td class="body"><code>{}</code></td><td><span class="context-tag server">server</span></td><td class="route"><code>GET /api/project</code></td><td>List projects known to this server.</td></tr>
-              <tr><td class="operation"><code>project.update</code></td><td class="body"><code>{
-  projectID: ProjectID
-  name?: string
-  icon?: string
-  commands?: Array&lt;{
-    name: string
-    command: string
-  }&gt;
-}</code></td><td><span class="context-tag server">server</span></td><td class="route"><code>PATCH /api/project/:projectID</code></td><td>Update project metadata.</td></tr>
-              <tr><td class="operation"><code>provider.list</code></td><td class="body"><code>{}</code></td><td><span class="context-tag request">request</span></td><td class="route"><code>GET /api/provider</code></td><td>Provider inventory for the runtime context.</td></tr>
-              <tr><td class="operation"><code>pty.create</code></td><td class="body"><code>{
-  command?: string
-  cwd?: string
-  shell?: string
-}</code></td><td><span class="context-tag request">request</span></td><td class="route"><code>POST /api/pty</code></td><td>Create PTY in the runtime context.</td></tr>
-              <tr><td class="operation"><code>pty.delete</code></td><td class="body"><code>{ ptyID: PtyID }</code></td><td><span class="context-tag request">request</span></td><td class="route"><code>DELETE /api/pty/:ptyID</code></td><td>Delete PTY.</td></tr>
-              <tr><td class="operation"><code>pty.get</code></td><td class="body"><code>{ ptyID: PtyID }</code></td><td><span class="context-tag request">request</span></td><td class="route"><code>GET /api/pty/:ptyID</code></td><td>Get PTY info.</td></tr>
-              <tr><td class="operation"><code>pty.list</code></td><td class="body"><code>{}</code></td><td><span class="context-tag request">request</span></td><td class="route"><code>GET /api/pty</code></td><td>List PTYs for the runtime.</td></tr>
-              <tr><td class="operation"><code>pty.update</code></td><td class="body"><code>{
-  ptyID: PtyID
-  title?: string
-  size?: { columns: number, rows: number }
-}</code></td><td><span class="context-tag request">request</span></td><td class="route"><code>PATCH /api/pty/:ptyID</code></td><td>Update PTY.</td></tr>
-              <tr><td class="operation"><code>question.list</code></td><td class="body"><code>{}</code></td><td><span class="context-tag request">request</span></td><td class="route"><code>GET /api/question</code></td><td>Pending user questions.</td></tr>
-              <tr><td class="operation"><code>question.reject</code></td><td class="body"><code>{ questionID: QuestionID }</code></td><td><span class="context-tag request">request</span></td><td class="route"><code>POST /api/question/:questionID/reject</code></td><td>Reject a question.</td></tr>
-              <tr><td class="operation"><code>question.reply</code></td><td class="body"><code>{
-  questionID: QuestionID
-  response: QuestionResponse
-}</code></td><td><span class="context-tag request">request</span></td><td class="route"><code>POST /api/question/:questionID/reply</code></td><td>Reply to a question.</td></tr>
-              <tr><td class="operation"><code>session.compact</code></td><td class="body"><code>{ sessionID: SessionID }</code></td><td><span class="context-tag session">session</span></td><td class="route"><code>POST /api/session/:sessionID/compact</code></td><td>Compact the session conversation.</td></tr>
-              <tr><td class="operation"><code>session.context</code></td><td class="body"><code>{ sessionID: SessionID }</code></td><td><span class="context-tag session">session</span></td><td class="route"><code>GET /api/session/:sessionID/context</code></td><td>Return active context messages after the last compaction.</td></tr>
-              <tr><td class="operation"><code>session.create</code></td><td class="body"><code>{
-  title?: string
-  agent?: string
-  model?: { providerID: ProviderID, modelID: ModelID }
-  permission?: PermissionRule[]
-}</code></td><td><span class="context-tag request">request</span></td><td class="route"><code>POST /api/session</code></td><td>Create a session pinned to resolved runtime context.</td></tr>
-              <tr><td class="operation"><code>session.delete</code></td><td class="body"><code>{ sessionID: SessionID }</code></td><td><span class="context-tag session">session</span></td><td class="route"><code>DELETE /api/session/:sessionID</code></td><td>Delete a session.</td></tr>
-              <tr><td class="operation"><code>session.diff</code></td><td class="body"><code>{ sessionID: SessionID }</code></td><td><span class="context-tag session">session</span></td><td class="route"><code>GET /api/session/:sessionID/diff</code></td><td>Return session diff summary.</td></tr>
-              <tr><td class="operation"><code>session.get</code></td><td class="body"><code>{ sessionID: SessionID }</code></td><td><span class="context-tag session">session</span></td><td class="route"><code>GET /api/session/:sessionID</code></td><td>Get one session.</td></tr>
-              <tr><td class="operation"><code>session.list</code></td><td class="body"><code>{
-  limit?: number
-  order?: "asc" | "desc"
-  path?: string
-  roots?: boolean
-  start?: number
-  search?: string
-  cursor?: string
-}</code></td><td><span class="context-tag request">request</span></td><td class="route"><code>GET /api/session</code></td><td>List sessions for the current runtime context by default.</td></tr>
-              <tr><td class="operation"><code>session.message.list</code></td><td class="body"><code>{
-  sessionID: SessionID
-  limit?: number
-  order?: "asc" | "desc"
-  cursor?: string
-}</code></td><td><span class="context-tag session">session</span></td><td class="route"><code>GET /api/session/:sessionID/message</code></td><td>Page through session messages.</td></tr>
-              <tr><td class="operation"><code>session.prompt</code></td><td class="body"><code>{
-  sessionID: SessionID
-  prompt: Prompt
-  delivery?: "immediate" | "deferred"
-}</code></td><td><span class="context-tag session">session</span></td><td class="route"><code>POST /api/session/:sessionID/prompt</code></td><td>Create a user message and queue the agent loop.</td></tr>
-              <tr><td class="operation"><code>session.todo</code></td><td class="body"><code>{ sessionID: SessionID }</code></td><td><span class="context-tag session">session</span></td><td class="route"><code>GET /api/session/:sessionID/todo</code></td><td>Return todos associated with the session.</td></tr>
-              <tr><td class="operation"><code>session.update</code></td><td class="body"><code>{
-  sessionID: SessionID
-  title?: string
-  archived?: number
-  permission?: PermissionRule[]
-}</code></td><td><span class="context-tag session">session</span></td><td class="route"><code>PATCH /api/session/:sessionID</code></td><td>Update title, archival state, or session metadata.</td></tr>
-              <tr><td class="operation"><code>session.wait</code></td><td class="body"><code>{ sessionID: SessionID }</code></td><td><span class="context-tag session">session</span></td><td class="route"><code>POST /api/session/:sessionID/wait</code></td><td>Wait until the session is idle.</td></tr>
-              <tr><td class="operation"><code>skill.list</code></td><td class="body"><code>{}</code></td><td><span class="context-tag request">request</span></td><td class="route"><code>GET /api/skill</code></td><td>Available skills.</td></tr>
-              <tr><td class="operation"><code>vcs.diff</code></td><td class="body"><code>{
-  format?: "json" | "patch"
-  mode?: "worktree" | "default"
-}</code></td><td><span class="context-tag request">request</span></td><td class="route"><code>GET /api/vcs/diff</code></td><td>Diff for the runtime directory.</td></tr>
-              <tr><td class="operation"><code>vcs.get</code></td><td class="body"><code>{}</code></td><td><span class="context-tag request">request</span></td><td class="route"><code>GET /api/vcs</code></td><td>VCS metadata.</td></tr>
-              <tr><td class="operation"><code>vcs.patch</code></td><td class="body"><code>{ patch: string }</code></td><td><span class="context-tag request">request</span></td><td class="route"><code>POST /api/vcs/patch</code></td><td>Apply a patch to the runtime directory.</td></tr>
-              <tr><td class="operation"><code>vcs.status</code></td><td class="body"><code>{}</code></td><td><span class="context-tag request">request</span></td><td class="route"><code>GET /api/vcs/status</code></td><td>Changed files.</td></tr>
-              <tr><td class="operation"><code>workspace.create</code></td><td class="body"><code>{
-  projectID?: ProjectID
-  name?: string
-  directory?: string
-  type: string
-  metadata?: Record&lt;string, unknown&gt;
-}</code></td><td><span class="context-tag server">server</span></td><td class="route"><code>POST /api/workspace</code></td><td>Create or register a workspace.</td></tr>
-              <tr><td class="operation"><code>workspace.delete</code></td><td class="body"><code>{ workspaceID: WorkspaceID }</code></td><td><span class="context-tag server">server</span></td><td class="route"><code>DELETE /api/workspace/:workspaceID</code></td><td>Remove a workspace registration.</td></tr>
-              <tr><td class="operation"><code>workspace.get</code></td><td class="body"><code>{ workspaceID: WorkspaceID }</code></td><td><span class="context-tag server">server</span></td><td class="route"><code>GET /api/workspace/:workspaceID</code></td><td>Get workspace metadata.</td></tr>
-              <tr><td class="operation"><code>workspace.list</code></td><td class="body"><code>{ projectID?: ProjectID }</code></td><td><span class="context-tag server">server</span></td><td class="route"><code>GET /api/workspace</code></td><td>List workspaces, optionally filtered by project.</td></tr>
-              <tr class="question-row"><td class="operation"><code>workspace.status</code></td><td class="body"><code>{}</code></td><td><span class="context-tag server">server</span></td><td class="route"><code>GET /api/workspace/status</code></td><td>Connection/lifecycle status for all workspaces. Needs team discussion.</td></tr>
-              <tr class="question-row"><td class="operation"><code>workspace.sync</code></td><td class="body"><code>{}</code></td><td><span class="context-tag server">server</span></td><td class="route"><code>POST /api/workspace/sync</code></td><td>Sync workspace metadata from adapters. Needs team discussion.</td></tr>
-              <tr><td class="operation"><code>workspace.update</code></td><td class="body"><code>{
-  workspaceID: WorkspaceID
-  name?: string
-  metadata?: Record&lt;string, unknown&gt;
-  archived?: boolean
-}</code></td><td><span class="context-tag server">server</span></td><td class="route"><code>PATCH /api/workspace/:workspaceID</code></td><td>Update workspace metadata or lifecycle state.</td></tr>
-              <tr class="question-row"><td class="operation"><code>workspace.warp</code></td><td class="body"><code>{
-  workspaceID?: WorkspaceID
-  sessionID: SessionID
-  copyChanges: boolean
-}</code></td><td><span class="context-tag server">server</span></td><td class="route"><code>POST /api/workspace/warp</code></td><td>Move a session into or out of a workspace. Needs team discussion.</td></tr>
+              <tr>
+                <td class="operation"><code>agent.list</code></td>
+                <td class="body"><code>{}</code></td>
+                <td><span class="context-tag request">request</span></td>
+                <td class="route"><code>GET /api/agent</code></td>
+                <td>Available agents.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>auth.activate</code></td>
+                <td class="body"><code>{ accountID: AccountID }</code></td>
+                <td><span class="context-tag server">server</span></td>
+                <td class="route"><code>POST /api/auth/:accountID/activate</code></td>
+                <td>Set the account as active for its service.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>auth.create</code></td>
+                <td class="body">
+                  <code
+                    >{ serviceID: ServiceID credential: | { type: "oauth", refresh: string, access: string, expires:
+                    number } | { type: "api", key: string, metadata?: Record&lt;string, string&gt; } description?:
+                    string active?: boolean }</code
+                  >
+                </td>
+                <td><span class="context-tag server">server</span></td>
+                <td class="route"><code>POST /api/auth</code></td>
+                <td>Create an auth account.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>auth.delete</code></td>
+                <td class="body"><code>{ accountID: AccountID }</code></td>
+                <td><span class="context-tag server">server</span></td>
+                <td class="route"><code>DELETE /api/auth/:accountID</code></td>
+                <td>Remove an auth account.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>auth.get</code></td>
+                <td class="body"><code>{ accountID: AccountID }</code></td>
+                <td><span class="context-tag server">server</span></td>
+                <td class="route"><code>GET /api/auth/:accountID</code></td>
+                <td>Get one auth account.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>auth.list</code></td>
+                <td class="body"><code>{ serviceID?: ServiceID }</code></td>
+                <td><span class="context-tag server">server</span></td>
+                <td class="route"><code>GET /api/auth</code></td>
+                <td>List saved auth accounts. Response includes active account mapping.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>auth.update</code></td>
+                <td class="body">
+                  <code
+                    >{ accountID: AccountID description?: string credential?: | { type: "oauth", refresh: string,
+                    access: string, expires: number } | { type: "api", key: string, metadata?: Record&lt;string,
+                    string&gt; } }</code
+                  >
+                </td>
+                <td><span class="context-tag server">server</span></td>
+                <td class="route"><code>PATCH /api/auth/:accountID</code></td>
+                <td>Update account description or credential.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>catalog.model.get</code></td>
+                <td class="body"><code>{ providerID: ProviderID modelID: ModelID }</code></td>
+                <td><span class="context-tag server">server</span></td>
+                <td class="route"><code>GET /api/catalog/model/:providerID/:modelID</code></td>
+                <td>Get one catalog model.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>catalog.model.list</code></td>
+                <td class="body"><code>{}</code></td>
+                <td><span class="context-tag server">server</span></td>
+                <td class="route"><code>GET /api/catalog/model</code></td>
+                <td>List flattened catalog models.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>command.list</code></td>
+                <td class="body"><code>{}</code></td>
+                <td><span class="context-tag request">request</span></td>
+                <td class="route"><code>GET /api/command</code></td>
+                <td>Available commands.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>config.get</code></td>
+                <td class="body"><code>{}</code></td>
+                <td><span class="context-tag request">request</span></td>
+                <td class="route"><code>GET /api/config</code></td>
+                <td>Resolved config.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>config.update</code></td>
+                <td class="body"><code>{ config: Config }</code></td>
+                <td><span class="context-tag request">request</span></td>
+                <td class="route"><code>PATCH /api/config</code></td>
+                <td>Update config.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>event.subscribe</code></td>
+                <td class="body"><code>{}</code></td>
+                <td><span class="context-tag request">request</span></td>
+                <td class="route"><code>GET /api/event</code></td>
+                <td>Server-sent events for the resolved runtime context.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>formatter.status</code></td>
+                <td class="body"><code>{}</code></td>
+                <td><span class="context-tag request">request</span></td>
+                <td class="route"><code>GET /api/formatter</code></td>
+                <td>Formatter status.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>fs.file</code></td>
+                <td class="body"><code>{ path: string }</code></td>
+                <td><span class="context-tag request">request</span></td>
+                <td class="route"><code>GET /api/fs/file</code></td>
+                <td>Read one file.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>fs.grep</code></td>
+                <td class="body"><code>{ pattern: string include?: string limit?: number }</code></td>
+                <td><span class="context-tag request">request</span></td>
+                <td class="route"><code>POST /api/fs/grep</code></td>
+                <td>Search file contents.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>fs.search</code></td>
+                <td class="body"><code>{ query: string type?: "file" | "directory" limit?: number }</code></td>
+                <td><span class="context-tag request">request</span></td>
+                <td class="route"><code>POST /api/fs/search</code></td>
+                <td>Search paths by name.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>fs.tree</code></td>
+                <td class="body"><code>{ path: string }</code></td>
+                <td><span class="context-tag request">request</span></td>
+                <td class="route"><code>GET /api/fs/tree</code></td>
+                <td>Browse a directory.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>lsp.status</code></td>
+                <td class="body"><code>{}</code></td>
+                <td><span class="context-tag request">request</span></td>
+                <td class="route"><code>GET /api/lsp</code></td>
+                <td>LSP status.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>mcp.prompt.list</code></td>
+                <td class="body"><code>{}</code></td>
+                <td><span class="context-tag request">request</span></td>
+                <td class="route"><code>GET /api/mcp/prompt</code></td>
+                <td>List MCP prompts.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>mcp.prompt.render</code></td>
+                <td class="body">
+                  <code>{ server: string name: string arguments?: Record&lt;string, string&gt; }</code>
+                </td>
+                <td><span class="context-tag request">request</span></td>
+                <td class="route"><code>POST /api/mcp/prompt/render</code></td>
+                <td>Render one MCP prompt.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>mcp.resource.list</code></td>
+                <td class="body"><code>{}</code></td>
+                <td><span class="context-tag request">request</span></td>
+                <td class="route"><code>GET /api/mcp/resource</code></td>
+                <td>List MCP resources.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>mcp.resource.read</code></td>
+                <td class="body"><code>{ server: string uri: string }</code></td>
+                <td><span class="context-tag request">request</span></td>
+                <td class="route"><code>GET /api/mcp/resource/read</code></td>
+                <td>Read one MCP resource.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>mcp.server.create</code></td>
+                <td class="body">
+                  <code
+                    >{ name: string config: | { type: "local", command: string, arguments?: string[], environment?:
+                    Record&lt;string, string&gt; } | { type: "remote", url: string, headers?: Record&lt;string,
+                    string&gt;, oauth?: boolean | object } }</code
+                  >
+                </td>
+                <td><span class="context-tag request">request</span></td>
+                <td class="route"><code>POST /api/mcp/server</code></td>
+                <td>Add an MCP server to runtime config.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>mcp.server.list</code></td>
+                <td class="body"><code>{}</code></td>
+                <td><span class="context-tag request">request</span></td>
+                <td class="route"><code>GET /api/mcp/server</code></td>
+                <td>List MCP servers with status and auth state.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>mcp.server.oauth.callback</code></td>
+                <td class="body"><code>{ name: string code: string }</code></td>
+                <td><span class="context-tag request">request</span></td>
+                <td class="route"><code>POST /api/mcp/server/:name/oauth/callback</code></td>
+                <td>Complete MCP OAuth.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>mcp.server.oauth.delete</code></td>
+                <td class="body"><code>{ name: string }</code></td>
+                <td><span class="context-tag request">request</span></td>
+                <td class="route"><code>DELETE /api/mcp/server/:name/oauth</code></td>
+                <td>Remove MCP OAuth credentials.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>mcp.server.oauth.start</code></td>
+                <td class="body"><code>{ name: string }</code></td>
+                <td><span class="context-tag request">request</span></td>
+                <td class="route"><code>POST /api/mcp/server/:name/oauth</code></td>
+                <td>Start MCP OAuth.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>permission.list</code></td>
+                <td class="body"><code>{}</code></td>
+                <td><span class="context-tag request">request</span></td>
+                <td class="route"><code>GET /api/permission</code></td>
+                <td>Pending permission requests.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>permission.reply</code></td>
+                <td class="body"><code>{ permissionID: PermissionID response: PermissionReply }</code></td>
+                <td><span class="context-tag request">request</span></td>
+                <td class="route"><code>POST /api/permission/:permissionID/reply</code></td>
+                <td>Reply to a permission request.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>project.get</code></td>
+                <td class="body"><code>{ projectID: ProjectID }</code></td>
+                <td><span class="context-tag server">server</span></td>
+                <td class="route"><code>GET /api/project/:projectID</code></td>
+                <td>Get project metadata.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>project.list</code></td>
+                <td class="body"><code>{}</code></td>
+                <td><span class="context-tag server">server</span></td>
+                <td class="route"><code>GET /api/project</code></td>
+                <td>List projects known to this server.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>project.update</code></td>
+                <td class="body">
+                  <code
+                    >{ projectID: ProjectID name?: string icon?: string commands?: Array&lt;{ name: string command:
+                    string }&gt; }</code
+                  >
+                </td>
+                <td><span class="context-tag server">server</span></td>
+                <td class="route"><code>PATCH /api/project/:projectID</code></td>
+                <td>Update project metadata.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>provider.list</code></td>
+                <td class="body"><code>{}</code></td>
+                <td><span class="context-tag request">request</span></td>
+                <td class="route"><code>GET /api/provider</code></td>
+                <td>Provider inventory for the runtime context.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>pty.create</code></td>
+                <td class="body"><code>{ command?: string cwd?: string shell?: string }</code></td>
+                <td><span class="context-tag request">request</span></td>
+                <td class="route"><code>POST /api/pty</code></td>
+                <td>Create PTY in the runtime context.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>pty.delete</code></td>
+                <td class="body"><code>{ ptyID: PtyID }</code></td>
+                <td><span class="context-tag request">request</span></td>
+                <td class="route"><code>DELETE /api/pty/:ptyID</code></td>
+                <td>Delete PTY.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>pty.get</code></td>
+                <td class="body"><code>{ ptyID: PtyID }</code></td>
+                <td><span class="context-tag request">request</span></td>
+                <td class="route"><code>GET /api/pty/:ptyID</code></td>
+                <td>Get PTY info.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>pty.list</code></td>
+                <td class="body"><code>{}</code></td>
+                <td><span class="context-tag request">request</span></td>
+                <td class="route"><code>GET /api/pty</code></td>
+                <td>List PTYs for the runtime.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>pty.update</code></td>
+                <td class="body">
+                  <code>{ ptyID: PtyID title?: string size?: { columns: number, rows: number } }</code>
+                </td>
+                <td><span class="context-tag request">request</span></td>
+                <td class="route"><code>PATCH /api/pty/:ptyID</code></td>
+                <td>Update PTY.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>question.list</code></td>
+                <td class="body"><code>{}</code></td>
+                <td><span class="context-tag request">request</span></td>
+                <td class="route"><code>GET /api/question</code></td>
+                <td>Pending user questions.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>question.reject</code></td>
+                <td class="body"><code>{ questionID: QuestionID }</code></td>
+                <td><span class="context-tag request">request</span></td>
+                <td class="route"><code>POST /api/question/:questionID/reject</code></td>
+                <td>Reject a question.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>question.reply</code></td>
+                <td class="body"><code>{ questionID: QuestionID response: QuestionResponse }</code></td>
+                <td><span class="context-tag request">request</span></td>
+                <td class="route"><code>POST /api/question/:questionID/reply</code></td>
+                <td>Reply to a question.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>session.compact</code></td>
+                <td class="body"><code>{ sessionID: SessionID }</code></td>
+                <td><span class="context-tag session">session</span></td>
+                <td class="route"><code>POST /api/session/:sessionID/compact</code></td>
+                <td>Compact the session conversation.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>session.context</code></td>
+                <td class="body"><code>{ sessionID: SessionID }</code></td>
+                <td><span class="context-tag session">session</span></td>
+                <td class="route"><code>GET /api/session/:sessionID/context</code></td>
+                <td>Return active context messages after the last compaction.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>session.create</code></td>
+                <td class="body">
+                  <code
+                    >{ title?: string agent?: string model?: { providerID: ProviderID, modelID: ModelID } permission?:
+                    PermissionRule[] }</code
+                  >
+                </td>
+                <td><span class="context-tag request">request</span></td>
+                <td class="route"><code>POST /api/session</code></td>
+                <td>Create a session pinned to resolved runtime context.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>session.delete</code></td>
+                <td class="body"><code>{ sessionID: SessionID }</code></td>
+                <td><span class="context-tag session">session</span></td>
+                <td class="route"><code>DELETE /api/session/:sessionID</code></td>
+                <td>Delete a session.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>session.diff</code></td>
+                <td class="body"><code>{ sessionID: SessionID }</code></td>
+                <td><span class="context-tag session">session</span></td>
+                <td class="route"><code>GET /api/session/:sessionID/diff</code></td>
+                <td>Return session diff summary.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>session.get</code></td>
+                <td class="body"><code>{ sessionID: SessionID }</code></td>
+                <td><span class="context-tag session">session</span></td>
+                <td class="route"><code>GET /api/session/:sessionID</code></td>
+                <td>Get one session.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>session.list</code></td>
+                <td class="body">
+                  <code
+                    >{ limit?: number order?: "asc" | "desc" path?: string roots?: boolean start?: number search?:
+                    string cursor?: string }</code
+                  >
+                </td>
+                <td><span class="context-tag request">request</span></td>
+                <td class="route"><code>GET /api/session</code></td>
+                <td>List sessions for the current runtime context by default.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>session.message.list</code></td>
+                <td class="body">
+                  <code>{ sessionID: SessionID limit?: number order?: "asc" | "desc" cursor?: string }</code>
+                </td>
+                <td><span class="context-tag session">session</span></td>
+                <td class="route"><code>GET /api/session/:sessionID/message</code></td>
+                <td>Page through session messages.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>session.prompt</code></td>
+                <td class="body">
+                  <code>{ sessionID: SessionID prompt: Prompt delivery?: "immediate" | "deferred" }</code>
+                </td>
+                <td><span class="context-tag session">session</span></td>
+                <td class="route"><code>POST /api/session/:sessionID/prompt</code></td>
+                <td>Create a user message and queue the agent loop.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>session.todo</code></td>
+                <td class="body"><code>{ sessionID: SessionID }</code></td>
+                <td><span class="context-tag session">session</span></td>
+                <td class="route"><code>GET /api/session/:sessionID/todo</code></td>
+                <td>Return todos associated with the session.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>session.update</code></td>
+                <td class="body">
+                  <code>{ sessionID: SessionID title?: string archived?: number permission?: PermissionRule[] }</code>
+                </td>
+                <td><span class="context-tag session">session</span></td>
+                <td class="route"><code>PATCH /api/session/:sessionID</code></td>
+                <td>Update title, archival state, or session metadata.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>session.wait</code></td>
+                <td class="body"><code>{ sessionID: SessionID }</code></td>
+                <td><span class="context-tag session">session</span></td>
+                <td class="route"><code>POST /api/session/:sessionID/wait</code></td>
+                <td>Wait until the session is idle.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>skill.list</code></td>
+                <td class="body"><code>{}</code></td>
+                <td><span class="context-tag request">request</span></td>
+                <td class="route"><code>GET /api/skill</code></td>
+                <td>Available skills.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>vcs.diff</code></td>
+                <td class="body"><code>{ format?: "json" | "patch" mode?: "worktree" | "default" }</code></td>
+                <td><span class="context-tag request">request</span></td>
+                <td class="route"><code>GET /api/vcs/diff</code></td>
+                <td>Diff for the runtime directory.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>vcs.get</code></td>
+                <td class="body"><code>{}</code></td>
+                <td><span class="context-tag request">request</span></td>
+                <td class="route"><code>GET /api/vcs</code></td>
+                <td>VCS metadata.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>vcs.patch</code></td>
+                <td class="body"><code>{ patch: string }</code></td>
+                <td><span class="context-tag request">request</span></td>
+                <td class="route"><code>POST /api/vcs/patch</code></td>
+                <td>Apply a patch to the runtime directory.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>vcs.status</code></td>
+                <td class="body"><code>{}</code></td>
+                <td><span class="context-tag request">request</span></td>
+                <td class="route"><code>GET /api/vcs/status</code></td>
+                <td>Changed files.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>workspace.create</code></td>
+                <td class="body">
+                  <code
+                    >{ projectID?: ProjectID name?: string directory?: string type: string metadata?: Record&lt;string,
+                    unknown&gt; }</code
+                  >
+                </td>
+                <td><span class="context-tag server">server</span></td>
+                <td class="route"><code>POST /api/workspace</code></td>
+                <td>Create or register a workspace.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>workspace.delete</code></td>
+                <td class="body"><code>{ workspaceID: WorkspaceID }</code></td>
+                <td><span class="context-tag server">server</span></td>
+                <td class="route"><code>DELETE /api/workspace/:workspaceID</code></td>
+                <td>Remove a workspace registration.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>workspace.get</code></td>
+                <td class="body"><code>{ workspaceID: WorkspaceID }</code></td>
+                <td><span class="context-tag server">server</span></td>
+                <td class="route"><code>GET /api/workspace/:workspaceID</code></td>
+                <td>Get workspace metadata.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>workspace.list</code></td>
+                <td class="body"><code>{ projectID?: ProjectID }</code></td>
+                <td><span class="context-tag server">server</span></td>
+                <td class="route"><code>GET /api/workspace</code></td>
+                <td>List workspaces, optionally filtered by project.</td>
+              </tr>
+              <tr class="question-row">
+                <td class="operation"><code>workspace.status</code></td>
+                <td class="body"><code>{}</code></td>
+                <td><span class="context-tag server">server</span></td>
+                <td class="route"><code>GET /api/workspace/status</code></td>
+                <td>Connection/lifecycle status for all workspaces. Needs team discussion.</td>
+              </tr>
+              <tr class="question-row">
+                <td class="operation"><code>workspace.sync</code></td>
+                <td class="body"><code>{}</code></td>
+                <td><span class="context-tag server">server</span></td>
+                <td class="route"><code>POST /api/workspace/sync</code></td>
+                <td>Sync workspace metadata from adapters. Needs team discussion.</td>
+              </tr>
+              <tr>
+                <td class="operation"><code>workspace.update</code></td>
+                <td class="body">
+                  <code
+                    >{ workspaceID: WorkspaceID name?: string metadata?: Record&lt;string, unknown&gt; archived?:
+                    boolean }</code
+                  >
+                </td>
+                <td><span class="context-tag server">server</span></td>
+                <td class="route"><code>PATCH /api/workspace/:workspaceID</code></td>
+                <td>Update workspace metadata or lifecycle state.</td>
+              </tr>
+              <tr class="question-row">
+                <td class="operation"><code>workspace.warp</code></td>
+                <td class="body">
+                  <code>{ workspaceID?: WorkspaceID sessionID: SessionID copyChanges: boolean }</code>
+                </td>
+                <td><span class="context-tag server">server</span></td>
+                <td class="route"><code>POST /api/workspace/warp</code></td>
+                <td>Move a session into or out of a workspace. Needs team discussion.</td>
+              </tr>
             </tbody>
           </table>
         </article>
@@ -681,8 +1061,8 @@ sessionID -&gt; { directory, workspaceID? }</code></pre>
         <article class="span-12 panel panel-pad stack">
           <h2>Event Envelope</h2>
           <p class="muted">
-            Every event uses the same envelope. Resource identity belongs in <code>payload</code>. Runtime identity belongs
-            in <code>context</code>.
+            Every event uses the same envelope. Resource identity belongs in <code>payload</code>. Runtime identity
+            belongs in <code>context</code>.
           </p>
           <div class="grid">
             <pre class="span-6"><code>type ApiEvent&lt;Payload&gt; = {