api.html 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153
  1. <!doctype html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="utf-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1" />
  6. <title>opencode v2 API</title>
  7. <style>
  8. :root {
  9. --bg: #f6f1e8;
  10. --fg: #1f2723;
  11. --muted: #6f756d;
  12. --dim: #ebe3d6;
  13. --panel: #fffaf1;
  14. --line: #26342f;
  15. --thin: #d6ccbd;
  16. --code: #eee5d8;
  17. --accent: #496b5a;
  18. --accent-soft: #dce7dc;
  19. font-family:
  20. Inter,
  21. ui-sans-serif,
  22. system-ui,
  23. -apple-system,
  24. BlinkMacSystemFont,
  25. "Segoe UI",
  26. sans-serif;
  27. }
  28. * {
  29. box-sizing: border-box;
  30. }
  31. html {
  32. background: var(--bg);
  33. color: var(--fg);
  34. }
  35. body {
  36. margin: 0;
  37. background:
  38. radial-gradient(circle at 12% 0%, rgba(73, 107, 90, 0.12), transparent 34rem),
  39. linear-gradient(90deg, rgba(38, 52, 47, 0.055) 1px, transparent 1px),
  40. linear-gradient(rgba(38, 52, 47, 0.045) 1px, transparent 1px), var(--bg);
  41. background-size: 72px 72px;
  42. color: var(--fg);
  43. line-height: 1.5;
  44. }
  45. main {
  46. width: 100%;
  47. padding: 40px 32px 72px;
  48. }
  49. header {
  50. display: grid;
  51. grid-template-columns: minmax(0, 1.25fr) minmax(360px, 0.75fr);
  52. gap: 32px;
  53. align-items: end;
  54. border-bottom: 2px solid var(--line);
  55. padding-bottom: 32px;
  56. }
  57. h1,
  58. h2,
  59. h3,
  60. p {
  61. margin: 0;
  62. }
  63. h1 {
  64. max-width: 1180px;
  65. font-size: clamp(4rem, 12vw, 13rem);
  66. line-height: 0.82;
  67. letter-spacing: -0.09em;
  68. }
  69. h2 {
  70. font-size: clamp(1.75rem, 4vw, 4rem);
  71. line-height: 0.95;
  72. letter-spacing: -0.07em;
  73. }
  74. h3 {
  75. font-size: 0.78rem;
  76. letter-spacing: 0.12em;
  77. text-transform: uppercase;
  78. }
  79. code,
  80. pre {
  81. font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
  82. }
  83. code {
  84. border: 1px solid var(--thin);
  85. padding: 1px 5px;
  86. background: var(--code);
  87. color: var(--fg);
  88. font-size: 0.9em;
  89. }
  90. pre {
  91. overflow: auto;
  92. margin: 0;
  93. border: 1px solid var(--line);
  94. padding: 16px;
  95. background: var(--code);
  96. color: var(--fg);
  97. font-size: 0.92rem;
  98. line-height: 1.5;
  99. }
  100. pre code {
  101. border: 0;
  102. padding: 0;
  103. background: transparent;
  104. font-size: inherit;
  105. }
  106. section {
  107. margin-top: 34px;
  108. }
  109. .eyebrow {
  110. display: inline-block;
  111. border: 1px solid var(--line);
  112. margin-bottom: 18px;
  113. padding: 5px 8px;
  114. font-size: 0.78rem;
  115. font-weight: 800;
  116. letter-spacing: 0.12em;
  117. text-transform: uppercase;
  118. }
  119. .lede {
  120. max-width: 620px;
  121. color: var(--muted);
  122. font-size: 1.15rem;
  123. }
  124. .panel {
  125. border: 2px solid var(--line);
  126. background: rgba(255, 250, 241, 0.92);
  127. box-shadow: 0 20px 50px rgba(31, 39, 35, 0.08);
  128. }
  129. .panel-pad {
  130. padding: 22px;
  131. }
  132. .grid {
  133. display: grid;
  134. grid-template-columns: repeat(12, minmax(0, 1fr));
  135. gap: 18px;
  136. }
  137. .span-12 {
  138. grid-column: span 12;
  139. }
  140. .span-8 {
  141. grid-column: span 8;
  142. }
  143. .span-6 {
  144. grid-column: span 6;
  145. }
  146. .span-4 {
  147. grid-column: span 4;
  148. }
  149. .stack {
  150. display: grid;
  151. gap: 16px;
  152. }
  153. .muted {
  154. color: var(--muted);
  155. }
  156. .rule {
  157. display: grid;
  158. gap: 16px;
  159. border: 2px solid var(--line);
  160. padding: 22px;
  161. background: var(--accent);
  162. color: #fffaf1;
  163. }
  164. .rule strong {
  165. font-size: clamp(1.45rem, 3vw, 2.45rem);
  166. line-height: 1;
  167. letter-spacing: -0.06em;
  168. }
  169. .rule code {
  170. border-color: var(--bg);
  171. background: rgba(255, 250, 241, 0.18);
  172. color: #fffaf1;
  173. }
  174. .key {
  175. display: flex;
  176. flex-wrap: wrap;
  177. gap: 8px;
  178. }
  179. .pill {
  180. display: inline-flex;
  181. align-items: center;
  182. width: fit-content;
  183. border: 1px solid var(--line);
  184. padding: 4px 8px;
  185. background: var(--panel);
  186. color: var(--fg);
  187. font-size: 0.75rem;
  188. font-weight: 900;
  189. letter-spacing: 0.08em;
  190. text-transform: uppercase;
  191. }
  192. .pill.inverse {
  193. background: var(--accent);
  194. color: #fffaf1;
  195. }
  196. .diagram {
  197. display: block;
  198. width: 100%;
  199. height: auto;
  200. border: 2px solid var(--line);
  201. background: var(--panel);
  202. }
  203. .diagram text {
  204. fill: var(--fg);
  205. font-family:
  206. Inter,
  207. ui-sans-serif,
  208. system-ui,
  209. -apple-system,
  210. BlinkMacSystemFont,
  211. "Segoe UI",
  212. sans-serif;
  213. }
  214. .diagram .box {
  215. fill: var(--panel);
  216. stroke: var(--fg);
  217. stroke-width: 2;
  218. }
  219. .diagram .fill {
  220. fill: var(--accent);
  221. stroke: var(--accent);
  222. stroke-width: 2;
  223. }
  224. .diagram .fill-text {
  225. fill: #fffaf1;
  226. }
  227. .diagram .line {
  228. stroke: var(--fg);
  229. stroke-width: 2;
  230. fill: none;
  231. marker-end: url(#arrow);
  232. }
  233. table {
  234. width: 100%;
  235. border-collapse: collapse;
  236. border: 2px solid var(--line);
  237. background: var(--panel);
  238. }
  239. th,
  240. td {
  241. border: 1px solid var(--thin);
  242. padding: 11px 12px;
  243. text-align: left;
  244. vertical-align: top;
  245. }
  246. th {
  247. border-bottom: 2px solid var(--line);
  248. background: var(--accent);
  249. color: #fffaf1;
  250. font-size: 0.75rem;
  251. letter-spacing: 0.12em;
  252. text-transform: uppercase;
  253. }
  254. td.route {
  255. width: 34%;
  256. white-space: nowrap;
  257. }
  258. td.body {
  259. width: 28%;
  260. }
  261. td.body code {
  262. display: block;
  263. white-space: pre-wrap;
  264. line-height: 1.45;
  265. }
  266. td.method {
  267. width: 72px;
  268. font-weight: 900;
  269. letter-spacing: 0.06em;
  270. }
  271. td.context {
  272. width: 150px;
  273. }
  274. td.operation {
  275. width: 210px;
  276. white-space: nowrap;
  277. }
  278. .context-tag {
  279. display: inline-block;
  280. border: 1px solid var(--line);
  281. padding: 3px 7px;
  282. font-size: 0.72rem;
  283. font-weight: 900;
  284. letter-spacing: 0.07em;
  285. text-transform: uppercase;
  286. }
  287. tr.question-row td {
  288. background: #f7e8b7;
  289. }
  290. .request {
  291. background: var(--accent);
  292. color: #fffaf1;
  293. }
  294. .session {
  295. background: var(--panel);
  296. color: var(--fg);
  297. }
  298. .server {
  299. background: var(--dim);
  300. color: var(--fg);
  301. }
  302. .note {
  303. border-left: 6px solid var(--line);
  304. padding: 14px 18px;
  305. background: var(--dim);
  306. }
  307. .toc {
  308. display: grid;
  309. gap: 8px;
  310. }
  311. .toc a {
  312. display: flex;
  313. justify-content: space-between;
  314. gap: 16px;
  315. border-bottom: 1px solid var(--thin);
  316. padding: 8px 0;
  317. color: var(--fg);
  318. text-decoration: none;
  319. }
  320. .toc span {
  321. color: var(--muted);
  322. }
  323. @media (max-width: 980px) {
  324. main {
  325. padding: 28px 16px 56px;
  326. }
  327. header,
  328. .grid {
  329. grid-template-columns: 1fr;
  330. }
  331. .span-12,
  332. .span-8,
  333. .span-6,
  334. .span-4 {
  335. grid-column: 1 / -1;
  336. }
  337. table {
  338. display: block;
  339. overflow-x: auto;
  340. white-space: nowrap;
  341. }
  342. }
  343. </style>
  344. </head>
  345. <body>
  346. <main>
  347. <header>
  348. <div>
  349. <div class="eyebrow">opencode v2</div>
  350. <h1>API map</h1>
  351. </div>
  352. <div class="stack">
  353. <p class="lede">
  354. A single <code>/api</code> route surface for simple clients and multi-directory frontends. The important
  355. design question is not route nesting; it is where runtime context comes from.
  356. </p>
  357. <div class="key">
  358. <span class="pill">Server scoped</span>
  359. <span class="pill inverse">Request context</span>
  360. <span class="pill">Session pinned</span>
  361. </div>
  362. </div>
  363. </header>
  364. <section class="grid">
  365. <article class="span-8 rule">
  366. <strong
  367. >Everything has one canonical route. Some routes are server-scoped; runtime routes use context; session item
  368. routes use the session.</strong
  369. >
  370. <p>
  371. Server-scoped routes manage the whole server: projects, workspace lifecycle, and auth accounts. Runtime
  372. context is for anything resolved from an active directory, including config, provider capabilities, tools,
  373. files, and VCS.
  374. </p>
  375. </article>
  376. <nav class="span-4 panel panel-pad toc" aria-label="Page sections">
  377. <a href="#context"><strong>Context Model</strong><span>how calls resolve</span></a>
  378. <a href="#endpoints"><strong>Endpoint Inventory</strong><span>all planned routes</span></a>
  379. <a href="#events"><strong>Events</strong><span>one envelope</span></a>
  380. <a href="#store"><strong>Frontend Store</strong><span>sync model</span></a>
  381. </nav>
  382. </section>
  383. <section id="context" class="grid">
  384. <div class="span-12 stack">
  385. <h2>Context Model</h2>
  386. <svg class="diagram" viewBox="0 0 1280 360" role="img" aria-labelledby="ctx-title ctx-desc">
  387. <title id="ctx-title">API context resolution</title>
  388. <desc id="ctx-desc">
  389. Non-session routes resolve from request context, session item routes resolve from session storage.
  390. </desc>
  391. <defs>
  392. <marker id="arrow" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto">
  393. <path d="M0,0 L0,6 L9,3 z" fill="#26342f" />
  394. </marker>
  395. </defs>
  396. <rect class="fill" x="34" y="44" width="294" height="96" />
  397. <text class="fill-text" x="58" y="84" font-size="24" font-weight="900">Non-session route</text>
  398. <text class="fill-text" x="58" y="116" font-size="17">/api/file, /api/vcs/status</text>
  399. <path class="line" d="M328 92 H472" />
  400. <rect class="box" x="486" y="44" width="286" height="96" />
  401. <text x="510" y="84" font-size="24" font-weight="900">Request context</text>
  402. <text x="510" y="116" font-size="17">query params or default runtime</text>
  403. <path class="line" d="M772 92 H916" />
  404. <rect class="box" x="930" y="44" width="316" height="96" />
  405. <text x="954" y="84" font-size="24" font-weight="900">Runtime context</text>
  406. <text x="954" y="116" font-size="17">directory + workspaceID?</text>
  407. <rect class="box" x="34" y="220" width="294" height="96" />
  408. <text x="58" y="260" font-size="24" font-weight="900">Session item route</text>
  409. <text x="58" y="292" font-size="17">/api/session/:id/prompt</text>
  410. <path class="line" d="M328 268 H472" />
  411. <rect class="fill" x="486" y="220" width="286" height="96" />
  412. <text class="fill-text" x="510" y="260" font-size="24" font-weight="900">Session row</text>
  413. <text class="fill-text" x="510" y="292" font-size="17">contains pinned context</text>
  414. <path class="line" d="M772 268 H916" />
  415. <rect class="box" x="930" y="220" width="316" height="96" />
  416. <text x="954" y="260" font-size="24" font-weight="900">Runtime context</text>
  417. <text x="954" y="292" font-size="17">directory + workspaceID?</text>
  418. </svg>
  419. </div>
  420. <article class="span-6 panel panel-pad stack">
  421. <h3>Request-context calls</h3>
  422. <p class="muted">
  423. These calls operate against a directory, optionally through a workspace. Simple clients omit context and use
  424. the default runtime.
  425. </p>
  426. <pre><code>GET /api/fs/tree?path=.&directory=/repo/app&workspace=ws_123</code></pre>
  427. </article>
  428. <article class="span-6 panel panel-pad stack">
  429. <h3>Session-pinned calls</h3>
  430. <p class="muted">
  431. These calls never take request context. The session is already pinned to the directory and workspace it was
  432. created in.
  433. </p>
  434. <pre><code>POST /api/session/ses_123/prompt
  435. // server resolves
  436. sessionID -&gt; { directory, workspaceID? }</code></pre>
  437. </article>
  438. </section>
  439. <section id="endpoints" class="grid">
  440. <div class="span-12 stack">
  441. <h2>Operation Inventory</h2>
  442. <p class="muted">
  443. The SDK is the source of truth. HTTP routes are mounts for RPC-style operations.
  444. <span class="context-tag server">server</span> operations do not use runtime context.
  445. <span class="context-tag request">request</span> operations use request/default runtime context from
  446. <code>directory</code> and <code>workspace</code> query parameters.
  447. <span class="context-tag session">session</span> operations use pinned session context and should not accept
  448. context input.
  449. </p>
  450. </div>
  451. <article class="span-12 panel panel-pad stack">
  452. <table>
  453. <thead>
  454. <tr>
  455. <th>Operation</th>
  456. <th>Input</th>
  457. <th>Context</th>
  458. <th>HTTP mount</th>
  459. <th>Purpose</th>
  460. </tr>
  461. </thead>
  462. <tbody>
  463. <tr>
  464. <td class="operation"><code>agent.list</code></td>
  465. <td class="body"><code>{}</code></td>
  466. <td><span class="context-tag request">request</span></td>
  467. <td class="route"><code>GET /api/agent</code></td>
  468. <td>Available agents.</td>
  469. </tr>
  470. <tr>
  471. <td class="operation"><code>auth.activate</code></td>
  472. <td class="body"><code>{ accountID: AccountID }</code></td>
  473. <td><span class="context-tag server">server</span></td>
  474. <td class="route"><code>POST /api/auth/:accountID/activate</code></td>
  475. <td>Set the account as active for its service.</td>
  476. </tr>
  477. <tr>
  478. <td class="operation"><code>auth.create</code></td>
  479. <td class="body">
  480. <code
  481. >{ serviceID: ServiceID credential: | { type: "oauth", refresh: string, access: string, expires:
  482. number } | { type: "api", key: string, metadata?: Record&lt;string, string&gt; } description?:
  483. string active?: boolean }</code
  484. >
  485. </td>
  486. <td><span class="context-tag server">server</span></td>
  487. <td class="route"><code>POST /api/auth</code></td>
  488. <td>Create an auth account.</td>
  489. </tr>
  490. <tr>
  491. <td class="operation"><code>auth.delete</code></td>
  492. <td class="body"><code>{ accountID: AccountID }</code></td>
  493. <td><span class="context-tag server">server</span></td>
  494. <td class="route"><code>DELETE /api/auth/:accountID</code></td>
  495. <td>Remove an auth account.</td>
  496. </tr>
  497. <tr>
  498. <td class="operation"><code>auth.get</code></td>
  499. <td class="body"><code>{ accountID: AccountID }</code></td>
  500. <td><span class="context-tag server">server</span></td>
  501. <td class="route"><code>GET /api/auth/:accountID</code></td>
  502. <td>Get one auth account.</td>
  503. </tr>
  504. <tr>
  505. <td class="operation"><code>auth.list</code></td>
  506. <td class="body"><code>{ serviceID?: ServiceID }</code></td>
  507. <td><span class="context-tag server">server</span></td>
  508. <td class="route"><code>GET /api/auth</code></td>
  509. <td>List saved auth accounts. Response includes active account mapping.</td>
  510. </tr>
  511. <tr>
  512. <td class="operation"><code>auth.update</code></td>
  513. <td class="body">
  514. <code
  515. >{ accountID: AccountID description?: string credential?: | { type: "oauth", refresh: string,
  516. access: string, expires: number } | { type: "api", key: string, metadata?: Record&lt;string,
  517. string&gt; } }</code
  518. >
  519. </td>
  520. <td><span class="context-tag server">server</span></td>
  521. <td class="route"><code>PATCH /api/auth/:accountID</code></td>
  522. <td>Update account description or credential.</td>
  523. </tr>
  524. <tr>
  525. <td class="operation"><code>catalog.model.get</code></td>
  526. <td class="body"><code>{ providerID: ProviderID modelID: ModelID }</code></td>
  527. <td><span class="context-tag server">server</span></td>
  528. <td class="route"><code>GET /api/catalog/model/:providerID/:modelID</code></td>
  529. <td>Get one catalog model.</td>
  530. </tr>
  531. <tr>
  532. <td class="operation"><code>catalog.model.list</code></td>
  533. <td class="body"><code>{}</code></td>
  534. <td><span class="context-tag server">server</span></td>
  535. <td class="route"><code>GET /api/catalog/model</code></td>
  536. <td>List flattened catalog models.</td>
  537. </tr>
  538. <tr>
  539. <td class="operation"><code>command.list</code></td>
  540. <td class="body"><code>{}</code></td>
  541. <td><span class="context-tag request">request</span></td>
  542. <td class="route"><code>GET /api/command</code></td>
  543. <td>Available commands.</td>
  544. </tr>
  545. <tr>
  546. <td class="operation"><code>config.get</code></td>
  547. <td class="body"><code>{}</code></td>
  548. <td><span class="context-tag request">request</span></td>
  549. <td class="route"><code>GET /api/config</code></td>
  550. <td>Resolved config.</td>
  551. </tr>
  552. <tr>
  553. <td class="operation"><code>config.update</code></td>
  554. <td class="body"><code>{ config: Config }</code></td>
  555. <td><span class="context-tag request">request</span></td>
  556. <td class="route"><code>PATCH /api/config</code></td>
  557. <td>Update config.</td>
  558. </tr>
  559. <tr>
  560. <td class="operation"><code>event.subscribe</code></td>
  561. <td class="body"><code>{}</code></td>
  562. <td><span class="context-tag request">request</span></td>
  563. <td class="route"><code>GET /api/event</code></td>
  564. <td>Server-sent events for the resolved runtime context.</td>
  565. </tr>
  566. <tr>
  567. <td class="operation"><code>formatter.status</code></td>
  568. <td class="body"><code>{}</code></td>
  569. <td><span class="context-tag request">request</span></td>
  570. <td class="route"><code>GET /api/formatter</code></td>
  571. <td>Formatter status.</td>
  572. </tr>
  573. <tr>
  574. <td class="operation"><code>fs.file</code></td>
  575. <td class="body"><code>{ path: string }</code></td>
  576. <td><span class="context-tag request">request</span></td>
  577. <td class="route"><code>GET /api/fs/file</code></td>
  578. <td>Read one file.</td>
  579. </tr>
  580. <tr>
  581. <td class="operation"><code>fs.grep</code></td>
  582. <td class="body"><code>{ pattern: string include?: string limit?: number }</code></td>
  583. <td><span class="context-tag request">request</span></td>
  584. <td class="route"><code>POST /api/fs/grep</code></td>
  585. <td>Search file contents.</td>
  586. </tr>
  587. <tr>
  588. <td class="operation"><code>fs.search</code></td>
  589. <td class="body"><code>{ query: string type?: "file" | "directory" limit?: number }</code></td>
  590. <td><span class="context-tag request">request</span></td>
  591. <td class="route"><code>POST /api/fs/search</code></td>
  592. <td>Search paths by name.</td>
  593. </tr>
  594. <tr>
  595. <td class="operation"><code>fs.tree</code></td>
  596. <td class="body"><code>{ path: string }</code></td>
  597. <td><span class="context-tag request">request</span></td>
  598. <td class="route"><code>GET /api/fs/tree</code></td>
  599. <td>Browse a directory.</td>
  600. </tr>
  601. <tr>
  602. <td class="operation"><code>lsp.status</code></td>
  603. <td class="body"><code>{}</code></td>
  604. <td><span class="context-tag request">request</span></td>
  605. <td class="route"><code>GET /api/lsp</code></td>
  606. <td>LSP status.</td>
  607. </tr>
  608. <tr>
  609. <td class="operation"><code>mcp.prompt.list</code></td>
  610. <td class="body"><code>{}</code></td>
  611. <td><span class="context-tag request">request</span></td>
  612. <td class="route"><code>GET /api/mcp/prompt</code></td>
  613. <td>List MCP prompts.</td>
  614. </tr>
  615. <tr>
  616. <td class="operation"><code>mcp.prompt.render</code></td>
  617. <td class="body">
  618. <code>{ server: string name: string arguments?: Record&lt;string, string&gt; }</code>
  619. </td>
  620. <td><span class="context-tag request">request</span></td>
  621. <td class="route"><code>POST /api/mcp/prompt/render</code></td>
  622. <td>Render one MCP prompt.</td>
  623. </tr>
  624. <tr>
  625. <td class="operation"><code>mcp.resource.list</code></td>
  626. <td class="body"><code>{}</code></td>
  627. <td><span class="context-tag request">request</span></td>
  628. <td class="route"><code>GET /api/mcp/resource</code></td>
  629. <td>List MCP resources.</td>
  630. </tr>
  631. <tr>
  632. <td class="operation"><code>mcp.resource.read</code></td>
  633. <td class="body"><code>{ server: string uri: string }</code></td>
  634. <td><span class="context-tag request">request</span></td>
  635. <td class="route"><code>GET /api/mcp/resource/read</code></td>
  636. <td>Read one MCP resource.</td>
  637. </tr>
  638. <tr>
  639. <td class="operation"><code>mcp.server.create</code></td>
  640. <td class="body">
  641. <code
  642. >{ name: string config: | { type: "local", command: string, arguments?: string[], environment?:
  643. Record&lt;string, string&gt; } | { type: "remote", url: string, headers?: Record&lt;string,
  644. string&gt;, oauth?: boolean | object } }</code
  645. >
  646. </td>
  647. <td><span class="context-tag request">request</span></td>
  648. <td class="route"><code>POST /api/mcp/server</code></td>
  649. <td>Add an MCP server to runtime config.</td>
  650. </tr>
  651. <tr>
  652. <td class="operation"><code>mcp.server.list</code></td>
  653. <td class="body"><code>{}</code></td>
  654. <td><span class="context-tag request">request</span></td>
  655. <td class="route"><code>GET /api/mcp/server</code></td>
  656. <td>List MCP servers with status and auth state.</td>
  657. </tr>
  658. <tr>
  659. <td class="operation"><code>mcp.server.oauth.callback</code></td>
  660. <td class="body"><code>{ name: string code: string }</code></td>
  661. <td><span class="context-tag request">request</span></td>
  662. <td class="route"><code>POST /api/mcp/server/:name/oauth/callback</code></td>
  663. <td>Complete MCP OAuth.</td>
  664. </tr>
  665. <tr>
  666. <td class="operation"><code>mcp.server.oauth.delete</code></td>
  667. <td class="body"><code>{ name: string }</code></td>
  668. <td><span class="context-tag request">request</span></td>
  669. <td class="route"><code>DELETE /api/mcp/server/:name/oauth</code></td>
  670. <td>Remove MCP OAuth credentials.</td>
  671. </tr>
  672. <tr>
  673. <td class="operation"><code>mcp.server.oauth.start</code></td>
  674. <td class="body"><code>{ name: string }</code></td>
  675. <td><span class="context-tag request">request</span></td>
  676. <td class="route"><code>POST /api/mcp/server/:name/oauth</code></td>
  677. <td>Start MCP OAuth.</td>
  678. </tr>
  679. <tr>
  680. <td class="operation"><code>permission.list</code></td>
  681. <td class="body"><code>{}</code></td>
  682. <td><span class="context-tag request">request</span></td>
  683. <td class="route"><code>GET /api/permission</code></td>
  684. <td>Pending permission requests.</td>
  685. </tr>
  686. <tr>
  687. <td class="operation"><code>permission.reply</code></td>
  688. <td class="body"><code>{ permissionID: PermissionID response: PermissionReply }</code></td>
  689. <td><span class="context-tag request">request</span></td>
  690. <td class="route"><code>POST /api/permission/:permissionID/reply</code></td>
  691. <td>Reply to a permission request.</td>
  692. </tr>
  693. <tr>
  694. <td class="operation"><code>project.get</code></td>
  695. <td class="body"><code>{ projectID: ProjectID }</code></td>
  696. <td><span class="context-tag server">server</span></td>
  697. <td class="route"><code>GET /api/project/:projectID</code></td>
  698. <td>Get project metadata.</td>
  699. </tr>
  700. <tr>
  701. <td class="operation"><code>project.list</code></td>
  702. <td class="body"><code>{}</code></td>
  703. <td><span class="context-tag server">server</span></td>
  704. <td class="route"><code>GET /api/project</code></td>
  705. <td>List projects known to this server.</td>
  706. </tr>
  707. <tr>
  708. <td class="operation"><code>project.update</code></td>
  709. <td class="body">
  710. <code
  711. >{ projectID: ProjectID name?: string icon?: string commands?: Array&lt;{ name: string command:
  712. string }&gt; }</code
  713. >
  714. </td>
  715. <td><span class="context-tag server">server</span></td>
  716. <td class="route"><code>PATCH /api/project/:projectID</code></td>
  717. <td>Update project metadata.</td>
  718. </tr>
  719. <tr>
  720. <td class="operation"><code>provider.list</code></td>
  721. <td class="body"><code>{}</code></td>
  722. <td><span class="context-tag request">request</span></td>
  723. <td class="route"><code>GET /api/provider</code></td>
  724. <td>Provider inventory for the runtime context.</td>
  725. </tr>
  726. <tr>
  727. <td class="operation"><code>pty.create</code></td>
  728. <td class="body"><code>{ command?: string cwd?: string shell?: string }</code></td>
  729. <td><span class="context-tag request">request</span></td>
  730. <td class="route"><code>POST /api/pty</code></td>
  731. <td>Create PTY in the runtime context.</td>
  732. </tr>
  733. <tr>
  734. <td class="operation"><code>pty.delete</code></td>
  735. <td class="body"><code>{ ptyID: PtyID }</code></td>
  736. <td><span class="context-tag request">request</span></td>
  737. <td class="route"><code>DELETE /api/pty/:ptyID</code></td>
  738. <td>Delete PTY.</td>
  739. </tr>
  740. <tr>
  741. <td class="operation"><code>pty.get</code></td>
  742. <td class="body"><code>{ ptyID: PtyID }</code></td>
  743. <td><span class="context-tag request">request</span></td>
  744. <td class="route"><code>GET /api/pty/:ptyID</code></td>
  745. <td>Get PTY info.</td>
  746. </tr>
  747. <tr>
  748. <td class="operation"><code>pty.list</code></td>
  749. <td class="body"><code>{}</code></td>
  750. <td><span class="context-tag request">request</span></td>
  751. <td class="route"><code>GET /api/pty</code></td>
  752. <td>List PTYs for the runtime.</td>
  753. </tr>
  754. <tr>
  755. <td class="operation"><code>pty.update</code></td>
  756. <td class="body">
  757. <code>{ ptyID: PtyID title?: string size?: { columns: number, rows: number } }</code>
  758. </td>
  759. <td><span class="context-tag request">request</span></td>
  760. <td class="route"><code>PATCH /api/pty/:ptyID</code></td>
  761. <td>Update PTY.</td>
  762. </tr>
  763. <tr>
  764. <td class="operation"><code>question.list</code></td>
  765. <td class="body"><code>{}</code></td>
  766. <td><span class="context-tag request">request</span></td>
  767. <td class="route"><code>GET /api/question</code></td>
  768. <td>Pending user questions.</td>
  769. </tr>
  770. <tr>
  771. <td class="operation"><code>question.reject</code></td>
  772. <td class="body"><code>{ questionID: QuestionID }</code></td>
  773. <td><span class="context-tag request">request</span></td>
  774. <td class="route"><code>POST /api/question/:questionID/reject</code></td>
  775. <td>Reject a question.</td>
  776. </tr>
  777. <tr>
  778. <td class="operation"><code>question.reply</code></td>
  779. <td class="body"><code>{ questionID: QuestionID response: QuestionResponse }</code></td>
  780. <td><span class="context-tag request">request</span></td>
  781. <td class="route"><code>POST /api/question/:questionID/reply</code></td>
  782. <td>Reply to a question.</td>
  783. </tr>
  784. <tr>
  785. <td class="operation"><code>session.compact</code></td>
  786. <td class="body"><code>{ sessionID: SessionID }</code></td>
  787. <td><span class="context-tag session">session</span></td>
  788. <td class="route"><code>POST /api/session/:sessionID/compact</code></td>
  789. <td>Compact the session conversation.</td>
  790. </tr>
  791. <tr>
  792. <td class="operation"><code>session.context</code></td>
  793. <td class="body"><code>{ sessionID: SessionID }</code></td>
  794. <td><span class="context-tag session">session</span></td>
  795. <td class="route"><code>GET /api/session/:sessionID/context</code></td>
  796. <td>Return active context messages after the last compaction.</td>
  797. </tr>
  798. <tr>
  799. <td class="operation"><code>session.create</code></td>
  800. <td class="body">
  801. <code
  802. >{ title?: string agent?: string model?: { providerID: ProviderID, modelID: ModelID } permission?:
  803. PermissionRule[] }</code
  804. >
  805. </td>
  806. <td><span class="context-tag request">request</span></td>
  807. <td class="route"><code>POST /api/session</code></td>
  808. <td>Create a session pinned to resolved runtime context.</td>
  809. </tr>
  810. <tr>
  811. <td class="operation"><code>session.delete</code></td>
  812. <td class="body"><code>{ sessionID: SessionID }</code></td>
  813. <td><span class="context-tag session">session</span></td>
  814. <td class="route"><code>DELETE /api/session/:sessionID</code></td>
  815. <td>Delete a session.</td>
  816. </tr>
  817. <tr>
  818. <td class="operation"><code>session.diff</code></td>
  819. <td class="body"><code>{ sessionID: SessionID }</code></td>
  820. <td><span class="context-tag session">session</span></td>
  821. <td class="route"><code>GET /api/session/:sessionID/diff</code></td>
  822. <td>Return session diff summary.</td>
  823. </tr>
  824. <tr>
  825. <td class="operation"><code>session.get</code></td>
  826. <td class="body"><code>{ sessionID: SessionID }</code></td>
  827. <td><span class="context-tag session">session</span></td>
  828. <td class="route"><code>GET /api/session/:sessionID</code></td>
  829. <td>Get one session.</td>
  830. </tr>
  831. <tr>
  832. <td class="operation"><code>session.list</code></td>
  833. <td class="body">
  834. <code
  835. >{ limit?: number order?: "asc" | "desc" path?: string roots?: boolean start?: number search?:
  836. string cursor?: string }</code
  837. >
  838. </td>
  839. <td><span class="context-tag request">request</span></td>
  840. <td class="route"><code>GET /api/session</code></td>
  841. <td>List sessions for the current runtime context by default.</td>
  842. </tr>
  843. <tr>
  844. <td class="operation"><code>session.message.list</code></td>
  845. <td class="body">
  846. <code>{ sessionID: SessionID limit?: number order?: "asc" | "desc" cursor?: string }</code>
  847. </td>
  848. <td><span class="context-tag session">session</span></td>
  849. <td class="route"><code>GET /api/session/:sessionID/message</code></td>
  850. <td>Page through session messages.</td>
  851. </tr>
  852. <tr>
  853. <td class="operation"><code>session.prompt</code></td>
  854. <td class="body">
  855. <code>{ sessionID: SessionID prompt: Prompt delivery?: "immediate" | "deferred" }</code>
  856. </td>
  857. <td><span class="context-tag session">session</span></td>
  858. <td class="route"><code>POST /api/session/:sessionID/prompt</code></td>
  859. <td>Create a user message and queue the agent loop.</td>
  860. </tr>
  861. <tr>
  862. <td class="operation"><code>session.update</code></td>
  863. <td class="body">
  864. <code>{ sessionID: SessionID title?: string archived?: number permission?: PermissionRule[] }</code>
  865. </td>
  866. <td><span class="context-tag session">session</span></td>
  867. <td class="route"><code>PATCH /api/session/:sessionID</code></td>
  868. <td>Update title, archival state, or session metadata.</td>
  869. </tr>
  870. <tr>
  871. <td class="operation"><code>session.wait</code></td>
  872. <td class="body"><code>{ sessionID: SessionID }</code></td>
  873. <td><span class="context-tag session">session</span></td>
  874. <td class="route"><code>POST /api/session/:sessionID/wait</code></td>
  875. <td>Wait until the session is idle.</td>
  876. </tr>
  877. <tr>
  878. <td class="operation"><code>skill.list</code></td>
  879. <td class="body"><code>{}</code></td>
  880. <td><span class="context-tag request">request</span></td>
  881. <td class="route"><code>GET /api/skill</code></td>
  882. <td>Available skills.</td>
  883. </tr>
  884. <tr>
  885. <td class="operation"><code>vcs.diff</code></td>
  886. <td class="body"><code>{ format?: "json" | "patch" mode?: "worktree" | "default" }</code></td>
  887. <td><span class="context-tag request">request</span></td>
  888. <td class="route"><code>GET /api/vcs/diff</code></td>
  889. <td>Diff for the runtime directory.</td>
  890. </tr>
  891. <tr>
  892. <td class="operation"><code>vcs.get</code></td>
  893. <td class="body"><code>{}</code></td>
  894. <td><span class="context-tag request">request</span></td>
  895. <td class="route"><code>GET /api/vcs</code></td>
  896. <td>VCS metadata.</td>
  897. </tr>
  898. <tr>
  899. <td class="operation"><code>vcs.patch</code></td>
  900. <td class="body"><code>{ patch: string }</code></td>
  901. <td><span class="context-tag request">request</span></td>
  902. <td class="route"><code>POST /api/vcs/patch</code></td>
  903. <td>Apply a patch to the runtime directory.</td>
  904. </tr>
  905. <tr>
  906. <td class="operation"><code>vcs.status</code></td>
  907. <td class="body"><code>{}</code></td>
  908. <td><span class="context-tag request">request</span></td>
  909. <td class="route"><code>GET /api/vcs/status</code></td>
  910. <td>Changed files.</td>
  911. </tr>
  912. <tr>
  913. <td class="operation"><code>workspace.create</code></td>
  914. <td class="body">
  915. <code
  916. >{ projectID?: ProjectID name?: string directory?: string type: string metadata?: Record&lt;string,
  917. unknown&gt; }</code
  918. >
  919. </td>
  920. <td><span class="context-tag server">server</span></td>
  921. <td class="route"><code>POST /api/workspace</code></td>
  922. <td>Create or register a workspace.</td>
  923. </tr>
  924. <tr>
  925. <td class="operation"><code>workspace.delete</code></td>
  926. <td class="body"><code>{ workspaceID: WorkspaceID }</code></td>
  927. <td><span class="context-tag server">server</span></td>
  928. <td class="route"><code>DELETE /api/workspace/:workspaceID</code></td>
  929. <td>Remove a workspace registration.</td>
  930. </tr>
  931. <tr>
  932. <td class="operation"><code>workspace.get</code></td>
  933. <td class="body"><code>{ workspaceID: WorkspaceID }</code></td>
  934. <td><span class="context-tag server">server</span></td>
  935. <td class="route"><code>GET /api/workspace/:workspaceID</code></td>
  936. <td>Get workspace metadata.</td>
  937. </tr>
  938. <tr>
  939. <td class="operation"><code>workspace.list</code></td>
  940. <td class="body"><code>{ projectID?: ProjectID }</code></td>
  941. <td><span class="context-tag server">server</span></td>
  942. <td class="route"><code>GET /api/workspace</code></td>
  943. <td>List workspaces, optionally filtered by project.</td>
  944. </tr>
  945. <tr class="question-row">
  946. <td class="operation"><code>workspace.status</code></td>
  947. <td class="body"><code>{}</code></td>
  948. <td><span class="context-tag server">server</span></td>
  949. <td class="route"><code>GET /api/workspace/status</code></td>
  950. <td>Connection/lifecycle status for all workspaces. Needs team discussion.</td>
  951. </tr>
  952. <tr class="question-row">
  953. <td class="operation"><code>workspace.sync</code></td>
  954. <td class="body"><code>{}</code></td>
  955. <td><span class="context-tag server">server</span></td>
  956. <td class="route"><code>POST /api/workspace/sync</code></td>
  957. <td>Sync workspace metadata from adapters. Needs team discussion.</td>
  958. </tr>
  959. <tr>
  960. <td class="operation"><code>workspace.update</code></td>
  961. <td class="body">
  962. <code
  963. >{ workspaceID: WorkspaceID name?: string metadata?: Record&lt;string, unknown&gt; archived?:
  964. boolean }</code
  965. >
  966. </td>
  967. <td><span class="context-tag server">server</span></td>
  968. <td class="route"><code>PATCH /api/workspace/:workspaceID</code></td>
  969. <td>Update workspace metadata or lifecycle state.</td>
  970. </tr>
  971. <tr class="question-row">
  972. <td class="operation"><code>workspace.warp</code></td>
  973. <td class="body">
  974. <code>{ workspaceID?: WorkspaceID sessionID: SessionID copyChanges: boolean }</code>
  975. </td>
  976. <td><span class="context-tag server">server</span></td>
  977. <td class="route"><code>POST /api/workspace/warp</code></td>
  978. <td>Move a session into or out of a workspace. Needs team discussion.</td>
  979. </tr>
  980. </tbody>
  981. </table>
  982. </article>
  983. </section>
  984. <section id="events" class="grid">
  985. <article class="span-12 panel panel-pad stack">
  986. <h2>Event Envelope</h2>
  987. <p class="muted">
  988. Every event uses the same envelope. Resource identity belongs in <code>payload</code>. Runtime identity
  989. belongs in <code>context</code>.
  990. </p>
  991. <div class="grid">
  992. <pre class="span-6"><code>type ApiEvent&lt;Payload&gt; = {
  993. id: string
  994. type: string
  995. time: number
  996. context: {
  997. directory: string
  998. workspaceID?: string
  999. }
  1000. payload: Payload
  1001. }</code></pre>
  1002. <pre class="span-6"><code>{
  1003. "id": "evt_01",
  1004. "type": "message.part.delta",
  1005. "time": 1760000000000,
  1006. "context": {
  1007. "directory": "/repo/app",
  1008. "workspaceID": "ws_123"
  1009. },
  1010. "payload": {
  1011. "sessionID": "ses_123",
  1012. "messageID": "msg_456",
  1013. "partID": "part_789",
  1014. "field": "text",
  1015. "delta": "hello"
  1016. }
  1017. }</code></pre>
  1018. </div>
  1019. </article>
  1020. </section>
  1021. <section id="store" class="grid">
  1022. <article class="span-12 panel panel-pad stack">
  1023. <h2>Frontend Sync Store</h2>
  1024. <p class="muted">
  1025. A frontend can keep one giant store like the current TUI. Runtime data is partitioned by
  1026. <code>contextKey</code>. Durable entities such as sessions and messages are keyed by their own IDs.
  1027. </p>
  1028. <pre><code>type RuntimeContext = {
  1029. directory: string
  1030. workspaceID?: string
  1031. }
  1032. type ContextKey = string
  1033. type SessionID = string
  1034. type MessageID = string
  1035. type SyncStore = {
  1036. status: "loading" | "partial" | "complete"
  1037. shared: {
  1038. provider: Provider[]
  1039. provider_default: Record&lt;string, string&gt;
  1040. provider_next: ProviderListResponse
  1041. provider_auth: Record&lt;string, ProviderAuthMethod[]&gt;
  1042. console_state: ConsoleState
  1043. }
  1044. contexts: Record&lt;
  1045. ContextKey,
  1046. {
  1047. context: RuntimeContext
  1048. config: Config
  1049. agent: Agent[]
  1050. command: Command[]
  1051. lsp: LspStatus[]
  1052. formatter: FormatterStatus[]
  1053. vcs: VcsInfo | undefined
  1054. mcp: Record&lt;string, McpStatus&gt;
  1055. mcp_resource: Record&lt;string, McpResource&gt;
  1056. session: SessionID[]
  1057. session_status: Record&lt;SessionID, SessionStatus&gt;
  1058. }
  1059. &gt;
  1060. session: Record&lt;SessionID, Session &amp; { context: RuntimeContext }&gt;
  1061. session_diff: Record&lt;SessionID, Snapshot.FileDiff[]&gt;
  1062. permission: Record&lt;SessionID, PermissionRequest[]&gt;
  1063. question: Record&lt;SessionID, QuestionRequest[]&gt;
  1064. message: Record&lt;SessionID, Message[]&gt;
  1065. part: Record&lt;MessageID, Part[]&gt;
  1066. }
  1067. function contextKey(context: RuntimeContext) {
  1068. return `${context.workspaceID ?? "local"}:${context.directory}`
  1069. }</code></pre>
  1070. </article>
  1071. </section>
  1072. </main>
  1073. </body>
  1074. </html>