api.html 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161
  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.todo</code></td>
  863. <td class="body"><code>{ sessionID: SessionID }</code></td>
  864. <td><span class="context-tag session">session</span></td>
  865. <td class="route"><code>GET /api/session/:sessionID/todo</code></td>
  866. <td>Return todos associated with the session.</td>
  867. </tr>
  868. <tr>
  869. <td class="operation"><code>session.update</code></td>
  870. <td class="body">
  871. <code>{ sessionID: SessionID title?: string archived?: number permission?: PermissionRule[] }</code>
  872. </td>
  873. <td><span class="context-tag session">session</span></td>
  874. <td class="route"><code>PATCH /api/session/:sessionID</code></td>
  875. <td>Update title, archival state, or session metadata.</td>
  876. </tr>
  877. <tr>
  878. <td class="operation"><code>session.wait</code></td>
  879. <td class="body"><code>{ sessionID: SessionID }</code></td>
  880. <td><span class="context-tag session">session</span></td>
  881. <td class="route"><code>POST /api/session/:sessionID/wait</code></td>
  882. <td>Wait until the session is idle.</td>
  883. </tr>
  884. <tr>
  885. <td class="operation"><code>skill.list</code></td>
  886. <td class="body"><code>{}</code></td>
  887. <td><span class="context-tag request">request</span></td>
  888. <td class="route"><code>GET /api/skill</code></td>
  889. <td>Available skills.</td>
  890. </tr>
  891. <tr>
  892. <td class="operation"><code>vcs.diff</code></td>
  893. <td class="body"><code>{ format?: "json" | "patch" mode?: "worktree" | "default" }</code></td>
  894. <td><span class="context-tag request">request</span></td>
  895. <td class="route"><code>GET /api/vcs/diff</code></td>
  896. <td>Diff for the runtime directory.</td>
  897. </tr>
  898. <tr>
  899. <td class="operation"><code>vcs.get</code></td>
  900. <td class="body"><code>{}</code></td>
  901. <td><span class="context-tag request">request</span></td>
  902. <td class="route"><code>GET /api/vcs</code></td>
  903. <td>VCS metadata.</td>
  904. </tr>
  905. <tr>
  906. <td class="operation"><code>vcs.patch</code></td>
  907. <td class="body"><code>{ patch: string }</code></td>
  908. <td><span class="context-tag request">request</span></td>
  909. <td class="route"><code>POST /api/vcs/patch</code></td>
  910. <td>Apply a patch to the runtime directory.</td>
  911. </tr>
  912. <tr>
  913. <td class="operation"><code>vcs.status</code></td>
  914. <td class="body"><code>{}</code></td>
  915. <td><span class="context-tag request">request</span></td>
  916. <td class="route"><code>GET /api/vcs/status</code></td>
  917. <td>Changed files.</td>
  918. </tr>
  919. <tr>
  920. <td class="operation"><code>workspace.create</code></td>
  921. <td class="body">
  922. <code
  923. >{ projectID?: ProjectID name?: string directory?: string type: string metadata?: Record&lt;string,
  924. unknown&gt; }</code
  925. >
  926. </td>
  927. <td><span class="context-tag server">server</span></td>
  928. <td class="route"><code>POST /api/workspace</code></td>
  929. <td>Create or register a workspace.</td>
  930. </tr>
  931. <tr>
  932. <td class="operation"><code>workspace.delete</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>DELETE /api/workspace/:workspaceID</code></td>
  936. <td>Remove a workspace registration.</td>
  937. </tr>
  938. <tr>
  939. <td class="operation"><code>workspace.get</code></td>
  940. <td class="body"><code>{ workspaceID: WorkspaceID }</code></td>
  941. <td><span class="context-tag server">server</span></td>
  942. <td class="route"><code>GET /api/workspace/:workspaceID</code></td>
  943. <td>Get workspace metadata.</td>
  944. </tr>
  945. <tr>
  946. <td class="operation"><code>workspace.list</code></td>
  947. <td class="body"><code>{ projectID?: ProjectID }</code></td>
  948. <td><span class="context-tag server">server</span></td>
  949. <td class="route"><code>GET /api/workspace</code></td>
  950. <td>List workspaces, optionally filtered by project.</td>
  951. </tr>
  952. <tr class="question-row">
  953. <td class="operation"><code>workspace.status</code></td>
  954. <td class="body"><code>{}</code></td>
  955. <td><span class="context-tag server">server</span></td>
  956. <td class="route"><code>GET /api/workspace/status</code></td>
  957. <td>Connection/lifecycle status for all workspaces. Needs team discussion.</td>
  958. </tr>
  959. <tr class="question-row">
  960. <td class="operation"><code>workspace.sync</code></td>
  961. <td class="body"><code>{}</code></td>
  962. <td><span class="context-tag server">server</span></td>
  963. <td class="route"><code>POST /api/workspace/sync</code></td>
  964. <td>Sync workspace metadata from adapters. Needs team discussion.</td>
  965. </tr>
  966. <tr>
  967. <td class="operation"><code>workspace.update</code></td>
  968. <td class="body">
  969. <code
  970. >{ workspaceID: WorkspaceID name?: string metadata?: Record&lt;string, unknown&gt; archived?:
  971. boolean }</code
  972. >
  973. </td>
  974. <td><span class="context-tag server">server</span></td>
  975. <td class="route"><code>PATCH /api/workspace/:workspaceID</code></td>
  976. <td>Update workspace metadata or lifecycle state.</td>
  977. </tr>
  978. <tr class="question-row">
  979. <td class="operation"><code>workspace.warp</code></td>
  980. <td class="body">
  981. <code>{ workspaceID?: WorkspaceID sessionID: SessionID copyChanges: boolean }</code>
  982. </td>
  983. <td><span class="context-tag server">server</span></td>
  984. <td class="route"><code>POST /api/workspace/warp</code></td>
  985. <td>Move a session into or out of a workspace. Needs team discussion.</td>
  986. </tr>
  987. </tbody>
  988. </table>
  989. </article>
  990. </section>
  991. <section id="events" class="grid">
  992. <article class="span-12 panel panel-pad stack">
  993. <h2>Event Envelope</h2>
  994. <p class="muted">
  995. Every event uses the same envelope. Resource identity belongs in <code>payload</code>. Runtime identity
  996. belongs in <code>context</code>.
  997. </p>
  998. <div class="grid">
  999. <pre class="span-6"><code>type ApiEvent&lt;Payload&gt; = {
  1000. id: string
  1001. type: string
  1002. time: number
  1003. context: {
  1004. directory: string
  1005. workspaceID?: string
  1006. }
  1007. payload: Payload
  1008. }</code></pre>
  1009. <pre class="span-6"><code>{
  1010. "id": "evt_01",
  1011. "type": "message.part.delta",
  1012. "time": 1760000000000,
  1013. "context": {
  1014. "directory": "/repo/app",
  1015. "workspaceID": "ws_123"
  1016. },
  1017. "payload": {
  1018. "sessionID": "ses_123",
  1019. "messageID": "msg_456",
  1020. "partID": "part_789",
  1021. "field": "text",
  1022. "delta": "hello"
  1023. }
  1024. }</code></pre>
  1025. </div>
  1026. </article>
  1027. </section>
  1028. <section id="store" class="grid">
  1029. <article class="span-12 panel panel-pad stack">
  1030. <h2>Frontend Sync Store</h2>
  1031. <p class="muted">
  1032. A frontend can keep one giant store like the current TUI. Runtime data is partitioned by
  1033. <code>contextKey</code>. Durable entities such as sessions and messages are keyed by their own IDs.
  1034. </p>
  1035. <pre><code>type RuntimeContext = {
  1036. directory: string
  1037. workspaceID?: string
  1038. }
  1039. type ContextKey = string
  1040. type SessionID = string
  1041. type MessageID = string
  1042. type SyncStore = {
  1043. status: "loading" | "partial" | "complete"
  1044. shared: {
  1045. provider: Provider[]
  1046. provider_default: Record&lt;string, string&gt;
  1047. provider_next: ProviderListResponse
  1048. provider_auth: Record&lt;string, ProviderAuthMethod[]&gt;
  1049. console_state: ConsoleState
  1050. }
  1051. contexts: Record&lt;
  1052. ContextKey,
  1053. {
  1054. context: RuntimeContext
  1055. config: Config
  1056. agent: Agent[]
  1057. command: Command[]
  1058. lsp: LspStatus[]
  1059. formatter: FormatterStatus[]
  1060. vcs: VcsInfo | undefined
  1061. mcp: Record&lt;string, McpStatus&gt;
  1062. mcp_resource: Record&lt;string, McpResource&gt;
  1063. session: SessionID[]
  1064. session_status: Record&lt;SessionID, SessionStatus&gt;
  1065. }
  1066. &gt;
  1067. session: Record&lt;SessionID, Session &amp; { context: RuntimeContext }&gt;
  1068. session_diff: Record&lt;SessionID, Snapshot.FileDiff[]&gt;
  1069. todo: Record&lt;SessionID, Todo[]&gt;
  1070. permission: Record&lt;SessionID, PermissionRequest[]&gt;
  1071. question: Record&lt;SessionID, QuestionRequest[]&gt;
  1072. message: Record&lt;SessionID, Message[]&gt;
  1073. part: Record&lt;MessageID, Part[]&gt;
  1074. }
  1075. function contextKey(context: RuntimeContext) {
  1076. return `${context.workspaceID ?? "local"}:${context.directory}`
  1077. }</code></pre>
  1078. </article>
  1079. </section>
  1080. </main>
  1081. </body>
  1082. </html>