@orion-agents/orion-code 0.3.0 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (172) hide show
  1. package/CHANGELOG.md +85 -0
  2. package/README.md +45 -18
  3. package/README.zh-CN.md +39 -18
  4. package/dist/commands/model-command-handlers.d.ts.map +1 -1
  5. package/dist/commands/model-command-handlers.js +59 -14
  6. package/dist/commands/model-command-handlers.js.map +1 -1
  7. package/dist/commands/types.d.ts +6 -0
  8. package/dist/commands/types.d.ts.map +1 -1
  9. package/dist/commands/types.js.map +1 -1
  10. package/dist/commands/workflow-command-handlers.d.ts +1 -1
  11. package/dist/commands/workflow-command-handlers.d.ts.map +1 -1
  12. package/dist/commands/workflow-command-handlers.js +42 -3
  13. package/dist/commands/workflow-command-handlers.js.map +1 -1
  14. package/dist/commands/workflow-commands.d.ts.map +1 -1
  15. package/dist/commands/workflow-commands.js +2 -2
  16. package/dist/commands/workflow-commands.js.map +1 -1
  17. package/dist/core/tool-artifacts.d.ts +2 -0
  18. package/dist/core/tool-artifacts.d.ts.map +1 -1
  19. package/dist/core/tool-artifacts.js +27 -1
  20. package/dist/core/tool-artifacts.js.map +1 -1
  21. package/dist/runtime/agent-runtime-controller.d.ts +16 -2
  22. package/dist/runtime/agent-runtime-controller.d.ts.map +1 -1
  23. package/dist/runtime/agent-runtime-controller.js +116 -8
  24. package/dist/runtime/agent-runtime-controller.js.map +1 -1
  25. package/dist/runtime/agent-runtime-protocol.d.ts +7 -0
  26. package/dist/runtime/agent-runtime-protocol.d.ts.map +1 -1
  27. package/dist/runtime/agent-runtime-protocol.js.map +1 -1
  28. package/dist/runtime/agent-runtime-runner.d.ts +8 -0
  29. package/dist/runtime/agent-runtime-runner.d.ts.map +1 -1
  30. package/dist/runtime/durable-tool-receipt-reader.d.ts +32 -0
  31. package/dist/runtime/durable-tool-receipt-reader.d.ts.map +1 -0
  32. package/dist/runtime/durable-tool-receipt-reader.js +130 -0
  33. package/dist/runtime/durable-tool-receipt-reader.js.map +1 -0
  34. package/dist/runtime/legacy-thread-materializer.d.ts +14 -1
  35. package/dist/runtime/legacy-thread-materializer.d.ts.map +1 -1
  36. package/dist/runtime/legacy-thread-materializer.js +44 -5
  37. package/dist/runtime/legacy-thread-materializer.js.map +1 -1
  38. package/dist/runtime/orion-session-runner.d.ts +4 -0
  39. package/dist/runtime/orion-session-runner.d.ts.map +1 -1
  40. package/dist/runtime/orion-session-runner.js +15 -0
  41. package/dist/runtime/orion-session-runner.js.map +1 -1
  42. package/dist/runtime/plan-review.d.ts +38 -0
  43. package/dist/runtime/plan-review.d.ts.map +1 -0
  44. package/dist/runtime/plan-review.js +173 -0
  45. package/dist/runtime/plan-review.js.map +1 -0
  46. package/dist/runtime/product-bootstrap.d.ts.map +1 -1
  47. package/dist/runtime/product-bootstrap.js +28 -6
  48. package/dist/runtime/product-bootstrap.js.map +1 -1
  49. package/dist/runtime/product-orion-runtime.d.ts.map +1 -1
  50. package/dist/runtime/product-orion-runtime.js +14 -35
  51. package/dist/runtime/product-orion-runtime.js.map +1 -1
  52. package/dist/runtime/protocol/runtime-protocol-v1.d.ts +73 -0
  53. package/dist/runtime/protocol/runtime-protocol-v1.d.ts.map +1 -1
  54. package/dist/runtime/protocol/runtime-protocol-v1.js +37 -0
  55. package/dist/runtime/protocol/runtime-protocol-v1.js.map +1 -1
  56. package/dist/runtime/release-receipts.d.ts +8 -3
  57. package/dist/runtime/release-receipts.d.ts.map +1 -1
  58. package/dist/runtime/release-receipts.js +88 -4
  59. package/dist/runtime/release-receipts.js.map +1 -1
  60. package/dist/runtime/session-composer-control.d.ts +136 -0
  61. package/dist/runtime/session-composer-control.d.ts.map +1 -0
  62. package/dist/runtime/session-composer-control.js +532 -0
  63. package/dist/runtime/session-composer-control.js.map +1 -0
  64. package/dist/runtime/thread-event-store.d.ts +62 -9
  65. package/dist/runtime/thread-event-store.d.ts.map +1 -1
  66. package/dist/runtime/thread-event-store.js +363 -31
  67. package/dist/runtime/thread-event-store.js.map +1 -1
  68. package/dist/runtime/thread-projection.d.ts +17 -0
  69. package/dist/runtime/thread-projection.d.ts.map +1 -1
  70. package/dist/runtime/thread-projection.js +87 -0
  71. package/dist/runtime/thread-projection.js.map +1 -1
  72. package/dist/runtime/thread-session-index.d.ts +84 -0
  73. package/dist/runtime/thread-session-index.d.ts.map +1 -0
  74. package/dist/runtime/thread-session-index.js +503 -0
  75. package/dist/runtime/thread-session-index.js.map +1 -0
  76. package/dist/runtime/thread-session-view.d.ts +31 -13
  77. package/dist/runtime/thread-session-view.d.ts.map +1 -1
  78. package/dist/runtime/thread-session-view.js +116 -61
  79. package/dist/runtime/thread-session-view.js.map +1 -1
  80. package/dist/runtime/thread-ui-adapter.d.ts.map +1 -1
  81. package/dist/runtime/thread-ui-adapter.js +18 -58
  82. package/dist/runtime/thread-ui-adapter.js.map +1 -1
  83. package/dist/runtime/tool-detail-repository.d.ts.map +1 -1
  84. package/dist/runtime/tool-detail-repository.js +23 -19
  85. package/dist/runtime/tool-detail-repository.js.map +1 -1
  86. package/dist/runtime/tool-receipt-validator.d.ts +21 -0
  87. package/dist/runtime/tool-receipt-validator.d.ts.map +1 -0
  88. package/dist/runtime/tool-receipt-validator.js +157 -0
  89. package/dist/runtime/tool-receipt-validator.js.map +1 -0
  90. package/dist/runtime/ui-events.d.ts +6 -1
  91. package/dist/runtime/ui-events.d.ts.map +1 -1
  92. package/dist/runtime/ui-events.js.map +1 -1
  93. package/dist/services/redaction.d.ts +4 -0
  94. package/dist/services/redaction.d.ts.map +1 -1
  95. package/dist/services/redaction.js +63 -0
  96. package/dist/services/redaction.js.map +1 -1
  97. package/dist/services/session-index.d.ts +16 -0
  98. package/dist/services/session-index.d.ts.map +1 -1
  99. package/dist/services/session-index.js +45 -36
  100. package/dist/services/session-index.js.map +1 -1
  101. package/dist/services/session-storage.d.ts +36 -0
  102. package/dist/services/session-storage.d.ts.map +1 -1
  103. package/dist/services/session-storage.js +80 -7
  104. package/dist/services/session-storage.js.map +1 -1
  105. package/dist/services/workspace-registry.d.ts +42 -0
  106. package/dist/services/workspace-registry.d.ts.map +1 -0
  107. package/dist/services/workspace-registry.js +222 -0
  108. package/dist/services/workspace-registry.js.map +1 -0
  109. package/dist/web/errors.d.ts +6 -0
  110. package/dist/web/errors.d.ts.map +1 -0
  111. package/dist/web/errors.js +13 -0
  112. package/dist/web/errors.js.map +1 -0
  113. package/dist/web/event-hub.d.ts +4 -0
  114. package/dist/web/event-hub.d.ts.map +1 -1
  115. package/dist/web/event-hub.js +81 -11
  116. package/dist/web/event-hub.js.map +1 -1
  117. package/dist/web/file-read-service.d.ts +64 -0
  118. package/dist/web/file-read-service.d.ts.map +1 -0
  119. package/dist/web/file-read-service.js +409 -0
  120. package/dist/web/file-read-service.js.map +1 -0
  121. package/dist/web/git-read-model-service.d.ts +85 -0
  122. package/dist/web/git-read-model-service.d.ts.map +1 -0
  123. package/dist/web/git-read-model-service.js +657 -0
  124. package/dist/web/git-read-model-service.js.map +1 -0
  125. package/dist/web/protocol.d.ts +205 -1
  126. package/dist/web/protocol.d.ts.map +1 -1
  127. package/dist/web/protocol.js +229 -1
  128. package/dist/web/protocol.js.map +1 -1
  129. package/dist/web/review-service.d.ts +38 -0
  130. package/dist/web/review-service.d.ts.map +1 -0
  131. package/dist/web/review-service.js +74 -0
  132. package/dist/web/review-service.js.map +1 -0
  133. package/dist/web/server.d.ts.map +1 -1
  134. package/dist/web/server.js +312 -29
  135. package/dist/web/server.js.map +1 -1
  136. package/dist/web/terminal-manager.d.ts +156 -0
  137. package/dist/web/terminal-manager.d.ts.map +1 -0
  138. package/dist/web/terminal-manager.js +760 -0
  139. package/dist/web/terminal-manager.js.map +1 -0
  140. package/dist/web/terminal-server.d.ts +8 -0
  141. package/dist/web/terminal-server.d.ts.map +1 -0
  142. package/dist/web/terminal-server.js +275 -0
  143. package/dist/web/terminal-server.js.map +1 -0
  144. package/dist/web/workbench-controller.d.ts +71 -18
  145. package/dist/web/workbench-controller.d.ts.map +1 -1
  146. package/dist/web/workbench-controller.js +1187 -178
  147. package/dist/web/workbench-controller.js.map +1 -1
  148. package/dist/web-client/assets/DiffViewer-eaQNsnCh.js +5 -0
  149. package/dist/web-client/assets/FilesPanel-DYs1MhoM.js +2 -0
  150. package/dist/web-client/assets/GitPanel-CnU4XVr7.js +1 -0
  151. package/dist/web-client/assets/ReviewPanel-BDxG670T.js +1 -0
  152. package/dist/web-client/assets/TerminalPanel-DLuoa74B.css +1 -0
  153. package/dist/web-client/assets/TerminalPanel-Q5mSSsoK.js +23 -0
  154. package/dist/web-client/assets/index-BWV5sIvw.css +1 -0
  155. package/dist/web-client/assets/index-VVUKj6FE.js +17 -0
  156. package/dist/web-client/index.html +2 -2
  157. package/docs/architecture/agent-mode-permission-contract.md +87 -0
  158. package/docs/architecture/v0.3.0-web-api.yaml +44 -13
  159. package/docs/architecture/v0.3.1-web-api.yaml +2338 -0
  160. package/docs/architecture/v0.3.2-web-api.yaml +3029 -0
  161. package/docs/migration/v0.3.0-to-v0.3.1.md +88 -0
  162. package/docs/migration/v0.3.1-to-v0.3.2.md +94 -0
  163. package/docs/plan/v0.3.0-web-workbench-plan.md +58 -7
  164. package/docs/plan/v0.3.1-web-workbench-professional-shell-plan.md +848 -0
  165. package/docs/plan/v0.3.2-web-workbench-layout-and-composer-plan.md +869 -0
  166. package/docs/readme.md +20 -0
  167. package/docs/test/v0.3.1-web-workbench-e2e-plan.md +140 -0
  168. package/docs/test/v0.3.2-web-workbench-e2e-plan.md +100 -0
  169. package/npm-shrinkwrap.json +185 -354
  170. package/package.json +21 -4
  171. package/dist/web-client/assets/index-BAEO71Gp.css +0 -1
  172. package/dist/web-client/assets/index-DSkFy7gM.js +0 -13
@@ -0,0 +1,3029 @@
1
+ openapi: 3.1.0
2
+ info:
3
+ title: Orion Code Local Web API
4
+ version: 0.3.2
5
+ description: >-
6
+ Same-origin loopback API for the Orion Code v0.3.2 Web Workbench. It extends the v0.3.1
7
+ engineering shell with revision-bound Session Composer controls, a Host model catalog,
8
+ structured Context references and durable Plan review. Unary resources use bounded JSON HTTP;
9
+ commands use POST; runtime invalidations use one replayable Server-Sent Events downlink.
10
+ Terminal bytes remain isolated on a ticket-authenticated, same-origin WebSocket and never enter
11
+ SSE, snapshots, diagnostics, evidence logs, or durable transcripts.
12
+ servers:
13
+ - url: /api/v1
14
+ paths:
15
+ /health:
16
+ get:
17
+ operationId: getHealth
18
+ responses:
19
+ '200':
20
+ description: Process health without secret or workspace data.
21
+ content:
22
+ application/json:
23
+ schema:
24
+ $ref: '#/components/schemas/HealthResponse'
25
+ /bootstrap:
26
+ get:
27
+ operationId: getBootstrap
28
+ responses:
29
+ '200':
30
+ description: Secret-free workbench bootstrap state.
31
+ content:
32
+ application/json:
33
+ schema:
34
+ $ref: '#/components/schemas/BootstrapResponse'
35
+ /workspaces:
36
+ get:
37
+ operationId: listWorkspaces
38
+ description: Cursor-paged canonical workspaces known to the local Orion installation.
39
+ parameters:
40
+ - $ref: '#/components/parameters/ContextWorkspaceId'
41
+ - $ref: '#/components/parameters/ExpectedContextRevision'
42
+ - $ref: '#/components/parameters/CollectionCursor'
43
+ - $ref: '#/components/parameters/PageSize'
44
+ responses:
45
+ '200':
46
+ description: One bounded workspace page.
47
+ content:
48
+ application/json:
49
+ schema:
50
+ $ref: '#/components/schemas/WorkspacePage'
51
+ '400': { $ref: '#/components/responses/Problem' }
52
+ '409': { $ref: '#/components/responses/Problem' }
53
+ /workspaces/{workspaceId}/sessions:
54
+ get:
55
+ operationId: listWorkspaceSessions
56
+ description: >-
57
+ Read one revision-bound Session page for a registered project, including an inactive
58
+ project, without activating or constructing its Runtime.
59
+ parameters:
60
+ - $ref: '#/components/parameters/WorkspaceId'
61
+ - $ref: '#/components/parameters/ContextWorkspaceId'
62
+ - $ref: '#/components/parameters/ExpectedContextRevision'
63
+ - $ref: '#/components/parameters/CollectionCursor'
64
+ - $ref: '#/components/parameters/PageSize'
65
+ responses:
66
+ '200':
67
+ description: One bounded Session page for the named workspace.
68
+ content:
69
+ application/json:
70
+ schema: { $ref: '#/components/schemas/SessionPage' }
71
+ '400': { $ref: '#/components/responses/Problem' }
72
+ '404': { $ref: '#/components/responses/Problem' }
73
+ '409': { $ref: '#/components/responses/Problem' }
74
+ /workspaces/{workspaceId}/summary:
75
+ get:
76
+ operationId: getWorkspaceSummary
77
+ description: Return a bounded Git/project summary without activating the workspace Runtime.
78
+ parameters:
79
+ - $ref: '#/components/parameters/WorkspaceId'
80
+ - $ref: '#/components/parameters/ContextWorkspaceId'
81
+ - $ref: '#/components/parameters/ExpectedContextRevision'
82
+ responses:
83
+ '200':
84
+ description: Repository facts for one registered workspace.
85
+ content:
86
+ application/json:
87
+ schema: { $ref: '#/components/schemas/WorkspaceProjectSummary' }
88
+ '400': { $ref: '#/components/responses/Problem' }
89
+ '404': { $ref: '#/components/responses/Problem' }
90
+ '409': { $ref: '#/components/responses/ContextConflict' }
91
+ /workspaces/{workspaceId}/pin:
92
+ post:
93
+ operationId: setWorkspacePinned
94
+ description: Pin or unpin a registered workspace through the process idempotency ledger.
95
+ security: [{ webNonce: [] }]
96
+ parameters:
97
+ - $ref: '#/components/parameters/WorkspaceId'
98
+ requestBody:
99
+ required: true
100
+ content:
101
+ application/json:
102
+ schema: { $ref: '#/components/schemas/WorkspacePinRequest' }
103
+ responses:
104
+ '200':
105
+ description: Updated workspace summary, or an exact requestId replay.
106
+ content:
107
+ application/json:
108
+ schema: { $ref: '#/components/schemas/WorkspacePinResult' }
109
+ '400': { $ref: '#/components/responses/Problem' }
110
+ '403': { $ref: '#/components/responses/Problem' }
111
+ '404': { $ref: '#/components/responses/Problem' }
112
+ '409': { $ref: '#/components/responses/Problem' }
113
+ /workspaces/{workspaceId}:
114
+ delete:
115
+ operationId: removeWorkspace
116
+ description: >-
117
+ Remove an inactive registry entry. Session/Thread data and files are not deleted; the
118
+ active workspace cannot be removed.
119
+ security: [{ webNonce: [] }]
120
+ parameters:
121
+ - $ref: '#/components/parameters/WorkspaceId'
122
+ requestBody:
123
+ required: true
124
+ content:
125
+ application/json:
126
+ schema: { $ref: '#/components/schemas/WorkspaceRemoveRequest' }
127
+ responses:
128
+ '200':
129
+ description: Registry entry removed, or an exact requestId replay.
130
+ content:
131
+ application/json:
132
+ schema: { $ref: '#/components/schemas/WorkspaceRemoveResult' }
133
+ '400': { $ref: '#/components/responses/Problem' }
134
+ '403': { $ref: '#/components/responses/Problem' }
135
+ '404': { $ref: '#/components/responses/Problem' }
136
+ '409': { $ref: '#/components/responses/Problem' }
137
+ /context/activate:
138
+ post:
139
+ operationId: activateContext
140
+ description: >-
141
+ Atomically switch workspace and optional Session under expectedContextRevision. Failure
142
+ leaves the previous context authoritative; success returns a complete bootstrap.
143
+ security: [{ webNonce: [] }]
144
+ requestBody:
145
+ required: true
146
+ content:
147
+ application/json:
148
+ schema: { $ref: '#/components/schemas/ContextActivateRequest' }
149
+ responses:
150
+ '200':
151
+ description: New atomic context, or an exact requestId replay.
152
+ content:
153
+ application/json:
154
+ schema: { $ref: '#/components/schemas/ContextMutationResult' }
155
+ '400': { $ref: '#/components/responses/Problem' }
156
+ '403': { $ref: '#/components/responses/Problem' }
157
+ '404': { $ref: '#/components/responses/Problem' }
158
+ '409': { $ref: '#/components/responses/Problem' }
159
+ /workspaces/activate:
160
+ post:
161
+ operationId: activateWorkspace
162
+ description: Select a canonical workspace after draining the previous runtime owner.
163
+ security: [{ webNonce: [] }]
164
+ requestBody:
165
+ required: true
166
+ content:
167
+ application/json:
168
+ schema:
169
+ $ref: '#/components/schemas/ActivateWorkspaceRequest'
170
+ responses:
171
+ '200':
172
+ description: Workspace selected, or an exact requestId retry replayed.
173
+ content:
174
+ application/json:
175
+ schema:
176
+ $ref: '#/components/schemas/WorkspaceMutationResult'
177
+ '400': { $ref: '#/components/responses/Problem' }
178
+ '403': { $ref: '#/components/responses/Problem' }
179
+ '409': { $ref: '#/components/responses/Problem' }
180
+ /sessions:
181
+ get:
182
+ operationId: listSessions
183
+ description: Cursor-paged sessions whose canonical project is the active workspace.
184
+ parameters:
185
+ - $ref: '#/components/parameters/ContextWorkspaceId'
186
+ - $ref: '#/components/parameters/ExpectedContextRevision'
187
+ - $ref: '#/components/parameters/CollectionCursor'
188
+ - $ref: '#/components/parameters/PageSize'
189
+ responses:
190
+ '200':
191
+ description: One bounded session page.
192
+ content:
193
+ application/json:
194
+ schema:
195
+ $ref: '#/components/schemas/SessionPage'
196
+ '400': { $ref: '#/components/responses/Problem' }
197
+ '409': { $ref: '#/components/responses/Problem' }
198
+ post:
199
+ operationId: createSession
200
+ security: [{ webNonce: [] }]
201
+ requestBody:
202
+ required: true
203
+ content:
204
+ application/json:
205
+ schema:
206
+ $ref: '#/components/schemas/CreateSessionRequest'
207
+ responses:
208
+ '201':
209
+ description: New active session, or an exact requestId retry replayed.
210
+ content:
211
+ application/json:
212
+ schema:
213
+ $ref: '#/components/schemas/SessionMutationResult'
214
+ '400': { $ref: '#/components/responses/Problem' }
215
+ '403': { $ref: '#/components/responses/Problem' }
216
+ '409': { $ref: '#/components/responses/Problem' }
217
+ /sessions/{sessionId}:
218
+ patch:
219
+ operationId: renameSession
220
+ security: [{ webNonce: [] }]
221
+ parameters:
222
+ - $ref: '#/components/parameters/SessionId'
223
+ requestBody:
224
+ required: true
225
+ content:
226
+ application/json:
227
+ schema:
228
+ $ref: '#/components/schemas/RenameSessionRequest'
229
+ responses:
230
+ '200':
231
+ description: Updated session, or an exact requestId retry replayed.
232
+ content:
233
+ application/json:
234
+ schema:
235
+ $ref: '#/components/schemas/SessionMutationResult'
236
+ '400': { $ref: '#/components/responses/Problem' }
237
+ '403': { $ref: '#/components/responses/Problem' }
238
+ '404': { $ref: '#/components/responses/Problem' }
239
+ '409': { $ref: '#/components/responses/Problem' }
240
+ /sessions/{sessionId}/activate:
241
+ post:
242
+ operationId: activateSession
243
+ description: Select and restore a session after draining the previous runtime owner.
244
+ security: [{ webNonce: [] }]
245
+ parameters:
246
+ - $ref: '#/components/parameters/SessionId'
247
+ requestBody:
248
+ required: true
249
+ content:
250
+ application/json:
251
+ schema:
252
+ $ref: '#/components/schemas/ContextGuardRequest'
253
+ responses:
254
+ '200':
255
+ description: Session selected, or an exact requestId retry replayed.
256
+ content:
257
+ application/json:
258
+ schema:
259
+ $ref: '#/components/schemas/CommandResult'
260
+ '400': { $ref: '#/components/responses/Problem' }
261
+ '403': { $ref: '#/components/responses/Problem' }
262
+ '404': { $ref: '#/components/responses/Problem' }
263
+ '409': { $ref: '#/components/responses/Problem' }
264
+ /sessions/{sessionId}/snapshot:
265
+ get:
266
+ operationId: getSessionSnapshot
267
+ description: >-
268
+ Recovery snapshot for one session. Transcript items are cursor-paged; `threadCursor`
269
+ identifies the durable Thread projection edge and the independent `eventCursor` resumes
270
+ `/events`. Pending approvals are projected here and remain pending across refresh, network
271
+ loss and tab closure.
272
+ parameters:
273
+ - $ref: '#/components/parameters/SessionId'
274
+ - $ref: '#/components/parameters/ContextWorkspaceId'
275
+ - $ref: '#/components/parameters/ExpectedContextRevision'
276
+ - $ref: '#/components/parameters/TranscriptCursor'
277
+ - $ref: '#/components/parameters/PageSize'
278
+ responses:
279
+ '200':
280
+ description: Sanitized recovery state from durable runtime sources.
281
+ content:
282
+ application/json:
283
+ schema:
284
+ $ref: '#/components/schemas/SessionSnapshot'
285
+ '400': { $ref: '#/components/responses/Problem' }
286
+ '404': { $ref: '#/components/responses/Problem' }
287
+ '409': { $ref: '#/components/responses/Problem' }
288
+ /sessions/{sessionId}/composer-state:
289
+ get:
290
+ operationId: getSessionComposerState
291
+ description: >-
292
+ Return the complete revision-bound Composer baseline for the active Session. The state is
293
+ independent of transcript length and includes current, pending, last-good/error, Context,
294
+ durable Plan review and queue projections.
295
+ parameters:
296
+ - $ref: '#/components/parameters/SessionId'
297
+ - $ref: '#/components/parameters/ContextWorkspaceId'
298
+ - $ref: '#/components/parameters/ExpectedContextRevision'
299
+ responses:
300
+ '200':
301
+ description: Matching active Session Composer state.
302
+ content:
303
+ application/json:
304
+ schema: { $ref: '#/components/schemas/ComposerControlState' }
305
+ '400': { $ref: '#/components/responses/Problem' }
306
+ '404': { $ref: '#/components/responses/Problem' }
307
+ '409': { $ref: '#/components/responses/ContextConflict' }
308
+ '503': { $ref: '#/components/responses/Problem' }
309
+ /sessions/{sessionId}/model-catalog:
310
+ get:
311
+ operationId: getSessionModelCatalog
312
+ description: >-
313
+ Return one cursor-bounded Host model page. Unavailable providers remain explicit and never
314
+ expose credential values or raw provider errors; healthy provider groups remain usable.
315
+ parameters:
316
+ - $ref: '#/components/parameters/SessionId'
317
+ - $ref: '#/components/parameters/ContextWorkspaceId'
318
+ - $ref: '#/components/parameters/ExpectedContextRevision'
319
+ - $ref: '#/components/parameters/CollectionCursor'
320
+ - $ref: '#/components/parameters/PageSize'
321
+ responses:
322
+ '200':
323
+ description: One revision-bound model catalog page.
324
+ content:
325
+ application/json:
326
+ schema: { $ref: '#/components/schemas/ModelCatalogPage' }
327
+ '400': { $ref: '#/components/responses/Problem' }
328
+ '404': { $ref: '#/components/responses/Problem' }
329
+ '409': { $ref: '#/components/responses/ContextConflict' }
330
+ '503': { $ref: '#/components/responses/Problem' }
331
+ /sessions/{sessionId}/composer-actions:
332
+ post:
333
+ operationId: applySessionComposerAction
334
+ description: >-
335
+ Apply exactly one idempotent Composer control mutation after workspace, Context, Session,
336
+ control and item/Plan revision admission. Any stale guard fails before side effects; the
337
+ client must recover and must not automatically replay a high-risk action.
338
+ security: [{ webNonce: [] }]
339
+ parameters:
340
+ - $ref: '#/components/parameters/SessionId'
341
+ requestBody:
342
+ required: true
343
+ content:
344
+ application/json:
345
+ schema: { $ref: '#/components/schemas/ComposerAction' }
346
+ responses:
347
+ '200':
348
+ description: Applied/deferred receipt and matching Composer state, or exact replay.
349
+ content:
350
+ application/json:
351
+ schema: { $ref: '#/components/schemas/ComposerActionResult' }
352
+ '400': { $ref: '#/components/responses/Problem' }
353
+ '403': { $ref: '#/components/responses/Problem' }
354
+ '404': { $ref: '#/components/responses/Problem' }
355
+ '409': { $ref: '#/components/responses/Problem' }
356
+ '422': { $ref: '#/components/responses/Problem' }
357
+ '503': { $ref: '#/components/responses/Problem' }
358
+ /files:
359
+ get:
360
+ operationId: listFiles
361
+ description: >-
362
+ Lazily list one active-workspace directory by opaque node id. The cursor binds the parent
363
+ id and file revision; paths outside the canonical workspace and symlink escapes fail closed.
364
+ parameters:
365
+ - $ref: '#/components/parameters/ContextWorkspaceId'
366
+ - $ref: '#/components/parameters/ExpectedContextRevision'
367
+ - $ref: '#/components/parameters/ParentFileId'
368
+ - $ref: '#/components/parameters/ResourceCursor'
369
+ - $ref: '#/components/parameters/PageSize'
370
+ responses:
371
+ '200':
372
+ description: One bounded directory page with no absolute filesystem paths.
373
+ content:
374
+ application/json:
375
+ schema: { $ref: '#/components/schemas/FileTreePage' }
376
+ '400': { $ref: '#/components/responses/Problem' }
377
+ '403': { $ref: '#/components/responses/Problem' }
378
+ '404': { $ref: '#/components/responses/Problem' }
379
+ '409': { $ref: '#/components/responses/Problem' }
380
+ /files/{fileId}/content:
381
+ get:
382
+ operationId: getFileContent
383
+ description: >-
384
+ Read one bounded UTF-8 page from a non-sensitive regular file. Binary files return metadata
385
+ only. The continuation is bound to the file revision and byte boundary.
386
+ parameters:
387
+ - $ref: '#/components/parameters/FileId'
388
+ - $ref: '#/components/parameters/ContextWorkspaceId'
389
+ - $ref: '#/components/parameters/ExpectedContextRevision'
390
+ - $ref: '#/components/parameters/ResourceCursor'
391
+ - $ref: '#/components/parameters/FileLimitBytes'
392
+ responses:
393
+ '200':
394
+ description: One redacted text page or binary metadata.
395
+ content:
396
+ application/json:
397
+ schema: { $ref: '#/components/schemas/FileContentPage' }
398
+ '400': { $ref: '#/components/responses/Problem' }
399
+ '403': { $ref: '#/components/responses/Problem' }
400
+ '404': { $ref: '#/components/responses/Problem' }
401
+ '409': { $ref: '#/components/responses/Problem' }
402
+ '415': { $ref: '#/components/responses/Problem' }
403
+ /git/status:
404
+ get:
405
+ operationId: getGitStatus
406
+ description: >-
407
+ Return bounded, argv-only Git facts for the active workspace. The opaque cursor binds the
408
+ repository revision and record offset; it never carries credentials or raw .git content.
409
+ parameters:
410
+ - $ref: '#/components/parameters/ContextWorkspaceId'
411
+ - $ref: '#/components/parameters/ExpectedContextRevision'
412
+ - $ref: '#/components/parameters/ResourceCursor'
413
+ - $ref: '#/components/parameters/GitStatusPageSize'
414
+ responses:
415
+ '200':
416
+ description: Grouped clean/staged/unstaged/untracked/conflicted repository state.
417
+ content:
418
+ application/json:
419
+ schema: { $ref: '#/components/schemas/GitStatus' }
420
+ '400': { $ref: '#/components/responses/Problem' }
421
+ '409': { $ref: '#/components/responses/Problem' }
422
+ '503': { $ref: '#/components/responses/Problem' }
423
+ /git/log:
424
+ get:
425
+ operationId: getGitLog
426
+ description: Return one sanitized commit page bound to the current repository revision.
427
+ parameters:
428
+ - $ref: '#/components/parameters/ContextWorkspaceId'
429
+ - $ref: '#/components/parameters/ExpectedContextRevision'
430
+ - $ref: '#/components/parameters/ResourceCursor'
431
+ - $ref: '#/components/parameters/GitLogPageSize'
432
+ responses:
433
+ '200':
434
+ description: One bounded Git history page.
435
+ content:
436
+ application/json:
437
+ schema: { $ref: '#/components/schemas/GitLogPage' }
438
+ '400': { $ref: '#/components/responses/Problem' }
439
+ '409': { $ref: '#/components/responses/Problem' }
440
+ '503': { $ref: '#/components/responses/Problem' }
441
+ /git/diff/{fileId}:
442
+ get:
443
+ operationId: getGitDiff
444
+ description: >-
445
+ Return bounded redacted diff lines for an opaque file id. Continuations bind file identity,
446
+ repository revision and page boundary; binary data is never emitted.
447
+ parameters:
448
+ - $ref: '#/components/parameters/FileId'
449
+ - $ref: '#/components/parameters/ContextWorkspaceId'
450
+ - $ref: '#/components/parameters/ExpectedContextRevision'
451
+ - $ref: '#/components/parameters/ResourceCursor'
452
+ - $ref: '#/components/parameters/DiffLineLimit'
453
+ - $ref: '#/components/parameters/DiffByteLimit'
454
+ responses:
455
+ '200':
456
+ description: One revision-bound diff page.
457
+ content:
458
+ application/json:
459
+ schema: { $ref: '#/components/schemas/GitDiffPage' }
460
+ '400': { $ref: '#/components/responses/Problem' }
461
+ '404': { $ref: '#/components/responses/Problem' }
462
+ '409': { $ref: '#/components/responses/Problem' }
463
+ '503': { $ref: '#/components/responses/Problem' }
464
+ /review:
465
+ get:
466
+ operationId: getReview
467
+ description: >-
468
+ Compose a read-only review summary from Git facts and durable tool-detail metadata. Sending
469
+ selected diff text to Composer is a client action; this endpoint never edits files.
470
+ parameters:
471
+ - $ref: '#/components/parameters/ContextWorkspaceId'
472
+ - $ref: '#/components/parameters/ExpectedContextRevision'
473
+ responses:
474
+ '200':
475
+ description: Revisioned change-set and verification metadata.
476
+ content:
477
+ application/json:
478
+ schema: { $ref: '#/components/schemas/ReviewSnapshot' }
479
+ '409': { $ref: '#/components/responses/Problem' }
480
+ '503': { $ref: '#/components/responses/Problem' }
481
+ /terminals:
482
+ get:
483
+ operationId: listTerminals
484
+ description: List only ephemeral terminals owned by the active workspace.
485
+ parameters:
486
+ - $ref: '#/components/parameters/ContextWorkspaceId'
487
+ - $ref: '#/components/parameters/ExpectedContextRevision'
488
+ - $ref: '#/components/parameters/CollectionCursor'
489
+ - $ref: '#/components/parameters/PageSize'
490
+ responses:
491
+ '200':
492
+ description: One bounded terminal metadata page; no terminal output is included.
493
+ content:
494
+ application/json:
495
+ schema: { $ref: '#/components/schemas/TerminalPage' }
496
+ '400': { $ref: '#/components/responses/Problem' }
497
+ '409': { $ref: '#/components/responses/Problem' }
498
+ post:
499
+ operationId: createTerminal
500
+ description: >-
501
+ Create a real PTY only after an explicit user gesture. The single-use attach ticket is
502
+ short-lived and must never be logged, persisted, placed in a URL, or sent on SSE.
503
+ security: [{ webNonce: [], terminalUserGesture: [] }]
504
+ requestBody:
505
+ required: true
506
+ content:
507
+ application/json:
508
+ schema: { $ref: '#/components/schemas/TerminalCreateRequest' }
509
+ responses:
510
+ '201':
511
+ description: Terminal metadata plus one short-lived single-use ticket.
512
+ content:
513
+ application/json:
514
+ schema: { $ref: '#/components/schemas/TerminalCreateMutationResult' }
515
+ '400': { $ref: '#/components/responses/Problem' }
516
+ '403': { $ref: '#/components/responses/Problem' }
517
+ '409': { $ref: '#/components/responses/Problem' }
518
+ '503': { $ref: '#/components/responses/Problem' }
519
+ /terminals/{terminalId}/attach-ticket:
520
+ post:
521
+ operationId: issueTerminalAttachTicket
522
+ description: Replace any unused ticket with a new single-use, short-lived attach ticket.
523
+ security: [{ webNonce: [] }]
524
+ parameters:
525
+ - $ref: '#/components/parameters/TerminalId'
526
+ requestBody:
527
+ required: true
528
+ content:
529
+ application/json:
530
+ schema: { $ref: '#/components/schemas/ContextGuardRequest' }
531
+ responses:
532
+ '200':
533
+ description: Fresh attach ticket, or an exact requestId replay.
534
+ content:
535
+ application/json:
536
+ schema: { $ref: '#/components/schemas/TerminalTicketMutationResult' }
537
+ '400': { $ref: '#/components/responses/Problem' }
538
+ '403': { $ref: '#/components/responses/Problem' }
539
+ '404': { $ref: '#/components/responses/Problem' }
540
+ '409': { $ref: '#/components/responses/Problem' }
541
+ /terminals/{terminalId}:
542
+ delete:
543
+ operationId: closeTerminal
544
+ description: Terminate the PTY process tree and invalidate outstanding attach tickets.
545
+ security: [{ webNonce: [] }]
546
+ parameters:
547
+ - $ref: '#/components/parameters/TerminalId'
548
+ requestBody:
549
+ required: true
550
+ content:
551
+ application/json:
552
+ schema: { $ref: '#/components/schemas/ContextGuardRequest' }
553
+ responses:
554
+ '200':
555
+ description: Closed terminal metadata, or an exact requestId replay.
556
+ content:
557
+ application/json:
558
+ schema: { $ref: '#/components/schemas/TerminalCloseMutationResult' }
559
+ '400': { $ref: '#/components/responses/Problem' }
560
+ '403': { $ref: '#/components/responses/Problem' }
561
+ '404': { $ref: '#/components/responses/Problem' }
562
+ '409': { $ref: '#/components/responses/Problem' }
563
+ /terminals/{terminalId}/stream:
564
+ get:
565
+ operationId: streamTerminal
566
+ description: >-
567
+ WebSocket upgrade only; HTTP success bodies are not used. The client offers subprotocol
568
+ `orion-terminal-v1`, then sends Authenticate as its first JSON message within five seconds.
569
+ The ticket stays in the message body, never in the URL. Terminal output is non-durable and
570
+ isolated from the Workbench SSE cursor.
571
+ parameters:
572
+ - $ref: '#/components/parameters/TerminalId'
573
+ x-orion-websocket:
574
+ subprotocol: orion-terminal-v1
575
+ firstClientMessage: '#/components/schemas/TerminalAuthenticateMessage'
576
+ clientMessages: '#/components/schemas/TerminalClientMessage'
577
+ serverMessages: '#/components/schemas/TerminalServerMessage'
578
+ closeCodes: [1000, 1001, 4400, 4401, 4403, 4409, 4413]
579
+ responses:
580
+ '101':
581
+ description: Switching Protocols to the terminal WebSocket.
582
+ '400': { $ref: '#/components/responses/Problem' }
583
+ '403': { $ref: '#/components/responses/Problem' }
584
+ '404': { $ref: '#/components/responses/Problem' }
585
+ /tool-details:
586
+ get:
587
+ operationId: listToolDetails
588
+ description: >-
589
+ Cursor-paged safe summaries from the active workspace's project artifact repository.
590
+ Current artifact metadata has no session identity, so this route is deliberately
591
+ workspace/project-scoped and must not be presented as proof that an artifact belongs to a
592
+ particular session.
593
+ parameters:
594
+ - $ref: '#/components/parameters/ContextWorkspaceId'
595
+ - $ref: '#/components/parameters/ExpectedContextRevision'
596
+ - $ref: '#/components/parameters/CollectionCursor'
597
+ - $ref: '#/components/parameters/PageSize'
598
+ responses:
599
+ '200':
600
+ description: One bounded tool-detail summary page.
601
+ content:
602
+ application/json:
603
+ schema:
604
+ $ref: '#/components/schemas/ToolDetailSummaryPage'
605
+ '400': { $ref: '#/components/responses/Problem' }
606
+ '404': { $ref: '#/components/responses/Problem' }
607
+ '409': { $ref: '#/components/responses/Problem' }
608
+ /tool-details/{callId}:
609
+ get:
610
+ operationId: getToolDetail
611
+ description: >-
612
+ Byte-paged output from a pre-sanitized derivative resolved only from the active workspace's
613
+ artifact list. `offsetBytes` addresses derivative bytes, never raw tool-output bytes, so a
614
+ caller cannot bypass redaction by choosing a sensitive-field boundary. The current artifact
615
+ metadata cannot prove session ownership; the host returns no artifact filesystem path and
616
+ makes no session-attribution claim.
617
+ parameters:
618
+ - $ref: '#/components/parameters/CallId'
619
+ - $ref: '#/components/parameters/ContextWorkspaceId'
620
+ - $ref: '#/components/parameters/ExpectedContextRevision'
621
+ - $ref: '#/components/parameters/OffsetBytes'
622
+ - $ref: '#/components/parameters/LimitBytes'
623
+ responses:
624
+ '200':
625
+ description: One UTF-8-safe redacted output page.
626
+ content:
627
+ application/json:
628
+ schema:
629
+ $ref: '#/components/schemas/ToolDetailPage'
630
+ '400': { $ref: '#/components/responses/Problem' }
631
+ '404': { $ref: '#/components/responses/Problem' }
632
+ '409': { $ref: '#/components/responses/ContextConflict' }
633
+ /skills:
634
+ get:
635
+ operationId: listSkills
636
+ description: >-
637
+ Cursor-paged safe Skill descriptors. Bodies, resource paths and trigger implementations are
638
+ excluded.
639
+ parameters:
640
+ - $ref: '#/components/parameters/ContextWorkspaceId'
641
+ - $ref: '#/components/parameters/ExpectedContextRevision'
642
+ - $ref: '#/components/parameters/CollectionCursor'
643
+ - $ref: '#/components/parameters/PageSize'
644
+ responses:
645
+ '200':
646
+ description: One bounded Skill descriptor page.
647
+ content:
648
+ application/json:
649
+ schema:
650
+ $ref: '#/components/schemas/SkillPage'
651
+ '400': { $ref: '#/components/responses/Problem' }
652
+ '409': { $ref: '#/components/responses/Problem' }
653
+ /mcp:
654
+ get:
655
+ operationId: listMcpServers
656
+ description: >-
657
+ Cursor-paged safe MCP catalog/runtime summaries. Commands, endpoints, headers and
658
+ credentials are excluded and this read never activates a dormant server.
659
+ parameters:
660
+ - $ref: '#/components/parameters/ContextWorkspaceId'
661
+ - $ref: '#/components/parameters/ExpectedContextRevision'
662
+ - $ref: '#/components/parameters/CollectionCursor'
663
+ - $ref: '#/components/parameters/PageSize'
664
+ responses:
665
+ '200':
666
+ description: One bounded MCP summary page.
667
+ content:
668
+ application/json:
669
+ schema:
670
+ $ref: '#/components/schemas/McpPage'
671
+ '400': { $ref: '#/components/responses/Problem' }
672
+ '409': { $ref: '#/components/responses/Problem' }
673
+ /commands:
674
+ post:
675
+ operationId: dispatchCommand
676
+ description: >-
677
+ Dispatch a renderer-neutral runtime mutation. Approval decisions allow only once, project
678
+ or global scope. Interrupt and shutdown paths deny affected unresolved approvals and fail
679
+ their waiting tool calls closed.
680
+ security: [{ webNonce: [] }]
681
+ requestBody:
682
+ required: true
683
+ content:
684
+ application/json:
685
+ schema:
686
+ $ref: '#/components/schemas/WebCommand'
687
+ responses:
688
+ '202':
689
+ description: Accepted command, or an exact requestId retry replayed.
690
+ content:
691
+ application/json:
692
+ schema:
693
+ $ref: '#/components/schemas/CommandResult'
694
+ '400': { $ref: '#/components/responses/Problem' }
695
+ '403': { $ref: '#/components/responses/Problem' }
696
+ '409': { $ref: '#/components/responses/Problem' }
697
+ /events:
698
+ get:
699
+ operationId: streamEvents
700
+ description: >-
701
+ One Server-Sent Events downlink. `cursor` or `Last-Event-ID` is the last delivered durable
702
+ sequence; the query value wins when both are present. Each SSE `id` is the decimal cursor,
703
+ while the JSON envelope also carries a UUID `eventId`. Disconnecting this stream does not
704
+ resolve or deny pending approvals.
705
+ parameters:
706
+ - $ref: '#/components/parameters/EventCursor'
707
+ - $ref: '#/components/parameters/LastEventId'
708
+ responses:
709
+ '200':
710
+ description: text/event-stream of discriminated WebEventEnvelope values.
711
+ content:
712
+ text/event-stream:
713
+ schema:
714
+ $ref: '#/components/schemas/WebEventEnvelope'
715
+ '400': { $ref: '#/components/responses/Problem' }
716
+ '409': { $ref: '#/components/responses/Problem' }
717
+ /diagnostics:
718
+ get:
719
+ operationId: getDiagnostics
720
+ parameters:
721
+ - $ref: '#/components/parameters/ContextWorkspaceId'
722
+ - $ref: '#/components/parameters/ExpectedContextRevision'
723
+ responses:
724
+ '200':
725
+ description: Sanitized runtime and harness diagnostics.
726
+ content:
727
+ application/json:
728
+ schema:
729
+ type: object
730
+ properties:
731
+ performance: { $ref: '#/components/schemas/WebPerformanceCounters' }
732
+ additionalProperties: true
733
+ '409': { $ref: '#/components/responses/ContextConflict' }
734
+ /settings:
735
+ get:
736
+ operationId: getSettings
737
+ responses:
738
+ '200':
739
+ description: Current secret-free, source-aware Settings document and durable revision.
740
+ content:
741
+ application/json:
742
+ schema:
743
+ $ref: '#/components/schemas/SettingsDocument'
744
+ patch:
745
+ operationId: updateSettings
746
+ description: >-
747
+ Atomically apply one bounded batch only when `expectedRevision` equals the keyed revision of
748
+ the exact current orion.json bytes. Duplicate keys and partial commits are rejected.
749
+ security: [{ webNonce: [] }]
750
+ requestBody:
751
+ required: true
752
+ content:
753
+ application/json:
754
+ schema:
755
+ $ref: '#/components/schemas/UpdateSettingsRequest'
756
+ responses:
757
+ '200':
758
+ description: Updated settings, or an exact requestId retry replayed.
759
+ content:
760
+ application/json:
761
+ schema:
762
+ $ref: '#/components/schemas/SettingsMutationResult'
763
+ '400': { $ref: '#/components/responses/Problem' }
764
+ '403': { $ref: '#/components/responses/Problem' }
765
+ '409':
766
+ description: requestId/body conflict, stale expectedRevision, or busy Runtime; no field was applied.
767
+ content:
768
+ application/problem+json:
769
+ schema:
770
+ $ref: '#/components/schemas/Problem'
771
+ '422': { $ref: '#/components/responses/Problem' }
772
+ '503': { $ref: '#/components/responses/Problem' }
773
+ /settings/open-document:
774
+ post:
775
+ operationId: openSettingsDocument
776
+ description: >-
777
+ Open the Host-resolved orion.json in the native text editor. This loopback-only action accepts
778
+ no path and never returns the resolved filesystem path.
779
+ security: [{ webNonce: [] }]
780
+ requestBody:
781
+ required: true
782
+ content:
783
+ application/json:
784
+ schema:
785
+ type: object
786
+ additionalProperties: false
787
+ required: [requestId]
788
+ properties:
789
+ requestId: { $ref: '#/components/schemas/RequestId' }
790
+ responses:
791
+ '200':
792
+ description: The pathless open request was accepted or replayed idempotently.
793
+ content:
794
+ application/json:
795
+ schema:
796
+ type: object
797
+ additionalProperties: false
798
+ required: [requestId, opened]
799
+ properties:
800
+ requestId: { $ref: '#/components/schemas/RequestId' }
801
+ opened: { type: boolean, const: true }
802
+ '400': { $ref: '#/components/responses/Problem' }
803
+ '403': { $ref: '#/components/responses/Problem' }
804
+ '409': { $ref: '#/components/responses/Problem' }
805
+ '503': { $ref: '#/components/responses/Problem' }
806
+ components:
807
+ securitySchemes:
808
+ webNonce:
809
+ type: apiKey
810
+ in: header
811
+ name: X-Orion-Web-Nonce
812
+ description: Per-process secret returned only by same-origin bootstrap and required on mutations.
813
+ terminalUserGesture:
814
+ type: apiKey
815
+ in: header
816
+ name: X-Orion-User-Gesture
817
+ description: Terminal creation requires the exact value terminal-create-v1 from a user gesture.
818
+ parameters:
819
+ ContextWorkspaceId:
820
+ in: query
821
+ name: workspaceId
822
+ required: true
823
+ description: >-
824
+ UUID of the active workspace observed with expectedContextRevision. A mismatch returns 409
825
+ context_revision_conflict and the Host performs no activation, read, spawn, or mutation.
826
+ schema: { type: string, format: uuid }
827
+ ExpectedContextRevision:
828
+ in: query
829
+ name: expectedContextRevision
830
+ required: true
831
+ description: >-
832
+ ContextRevision from bootstrap or the last successful atomic activation. A stale value
833
+ returns 409 context_revision_conflict with zero side effects.
834
+ schema: { $ref: '#/components/schemas/ContextRevision' }
835
+ WorkspaceId:
836
+ in: path
837
+ name: workspaceId
838
+ required: true
839
+ schema: { type: string, format: uuid }
840
+ SessionId:
841
+ in: path
842
+ name: sessionId
843
+ required: true
844
+ schema: { type: string, minLength: 1, maxLength: 256 }
845
+ FileId:
846
+ in: path
847
+ name: fileId
848
+ required: true
849
+ description: Opaque active-workspace file identity; never a client-supplied path.
850
+ schema: { type: string, minLength: 1, maxLength: 256 }
851
+ ParentFileId:
852
+ in: query
853
+ name: parentId
854
+ required: false
855
+ description: Opaque directory identity; omission selects the active-workspace root.
856
+ schema: { type: string, minLength: 1, maxLength: 256 }
857
+ TerminalId:
858
+ in: path
859
+ name: terminalId
860
+ required: true
861
+ schema: { type: string, format: uuid }
862
+ CallId:
863
+ in: path
864
+ name: callId
865
+ required: true
866
+ description: >-
867
+ Opaque identifier returned by the active workspace's tool-detail summary. The current file
868
+ repository aliases callId to its project artifact identifier.
869
+ schema: { type: string, minLength: 1, maxLength: 256 }
870
+ CollectionCursor:
871
+ in: query
872
+ name: cursor
873
+ required: false
874
+ description: >-
875
+ Opaque continuation returned by the preceding page. It binds the route scope, the complete
876
+ ordered collection revision and the last stable item key. Any insertion, deletion or
877
+ reorder makes it stale; the Host returns 409 collection_cursor_stale and the client restarts
878
+ from the first page.
879
+ schema: { type: string, minLength: 1, maxLength: 512 }
880
+ TranscriptCursor:
881
+ in: query
882
+ name: cursor
883
+ required: false
884
+ description: >-
885
+ Opaque backward-page continuation bound to the Session's Thread identity, immutable
886
+ transcript-manifest revision and page boundary. A newer Thread revision returns 409
887
+ transcript_cursor_stale; the client must recover a fresh tail snapshot before paging again.
888
+ schema: { type: string, minLength: 1, maxLength: 512 }
889
+ ResourceCursor:
890
+ in: query
891
+ name: cursor
892
+ required: false
893
+ description: >-
894
+ Opaque continuation bound to the active workspace, resource identity, resource revision and
895
+ page boundary. A stale or cross-resource value returns 409 and must be restarted from the
896
+ first page; the value is not an encoded filesystem path.
897
+ schema: { type: string, minLength: 1, maxLength: 4096 }
898
+ PageSize:
899
+ in: query
900
+ name: pageSize
901
+ required: false
902
+ schema: { type: integer, minimum: 1, maximum: 100, default: 50 }
903
+ OffsetBytes:
904
+ in: query
905
+ name: offsetBytes
906
+ required: false
907
+ schema: { type: integer, minimum: 0, default: 0 }
908
+ LimitBytes:
909
+ in: query
910
+ name: limitBytes
911
+ required: false
912
+ schema: { type: integer, minimum: 1, maximum: 1048576, default: 65536 }
913
+ FileLimitBytes:
914
+ in: query
915
+ name: limitBytes
916
+ required: false
917
+ schema: { type: integer, minimum: 1, maximum: 262144, default: 65536 }
918
+ GitStatusPageSize:
919
+ in: query
920
+ name: pageSize
921
+ required: false
922
+ schema: { type: integer, minimum: 1, maximum: 2000, default: 200 }
923
+ GitLogPageSize:
924
+ in: query
925
+ name: pageSize
926
+ required: false
927
+ schema: { type: integer, minimum: 1, maximum: 100, default: 30 }
928
+ DiffLineLimit:
929
+ in: query
930
+ name: lineLimit
931
+ required: false
932
+ schema: { type: integer, minimum: 1, maximum: 500, default: 240 }
933
+ DiffByteLimit:
934
+ in: query
935
+ name: byteLimit
936
+ required: false
937
+ schema: { type: integer, minimum: 1024, maximum: 1048576, default: 262144 }
938
+ EventCursor:
939
+ in: query
940
+ name: cursor
941
+ required: false
942
+ description: Last durable Web event cursor accepted by the client.
943
+ schema: { type: integer, minimum: 0, default: 0 }
944
+ LastEventId:
945
+ in: header
946
+ name: Last-Event-ID
947
+ required: false
948
+ description: Browser-provided fallback for the last durable Web event cursor.
949
+ schema: { type: string, pattern: '^[0-9]+$' }
950
+ responses:
951
+ Problem:
952
+ description: Safe structured error with no secret-bearing data.
953
+ content:
954
+ application/problem+json:
955
+ schema:
956
+ $ref: '#/components/schemas/Problem'
957
+ ContextConflict:
958
+ description: >-
959
+ workspaceId or expectedContextRevision is stale. The Host returns
960
+ context_revision_conflict and performs zero reads from another workspace and zero side
961
+ effects.
962
+ content:
963
+ application/problem+json:
964
+ schema: { $ref: '#/components/schemas/Problem' }
965
+ example:
966
+ type: https://orioncode.dev/problems/context_revision_conflict
967
+ title: State conflict
968
+ status: 409
969
+ code: context_revision_conflict
970
+ detail: The active Context changed before the request was admitted.
971
+ schemas:
972
+ WebPerformanceCounters:
973
+ type: object
974
+ additionalProperties: false
975
+ required: [files, git]
976
+ properties:
977
+ files:
978
+ type: object
979
+ additionalProperties: false
980
+ required: [readOperations, bytesRead, itemsParsed]
981
+ properties:
982
+ readOperations: { type: integer, minimum: 0 }
983
+ bytesRead: { type: integer, minimum: 0 }
984
+ itemsParsed: { type: integer, minimum: 0 }
985
+ git:
986
+ type: object
987
+ additionalProperties: false
988
+ required: [processCount, bytesRead, itemsParsed]
989
+ properties:
990
+ processCount: { type: integer, minimum: 0 }
991
+ bytesRead: { type: integer, minimum: 0 }
992
+ itemsParsed: { type: integer, minimum: 0 }
993
+ HealthResponse:
994
+ type: object
995
+ additionalProperties: false
996
+ required: [ok, version]
997
+ properties:
998
+ ok: { type: boolean, const: true }
999
+ version: { type: string }
1000
+ BootstrapResponse:
1001
+ type: object
1002
+ additionalProperties: false
1003
+ required:
1004
+ - apiVersion
1005
+ - productVersion
1006
+ - nonce
1007
+ - contextRevision
1008
+ - workspaceId
1009
+ - workspace
1010
+ - configured
1011
+ - activeSessionId
1012
+ - settings
1013
+ - capabilities
1014
+ properties:
1015
+ apiVersion: { type: integer, const: 1 }
1016
+ productVersion: { type: string }
1017
+ nonce: { type: string, minLength: 32 }
1018
+ contextRevision: { type: string, format: uuid }
1019
+ workspaceId: { type: string, format: uuid }
1020
+ workspace: { type: string }
1021
+ configured: { type: boolean }
1022
+ activeSessionId: { type: [string, 'null'] }
1023
+ settings: { $ref: '#/components/schemas/SettingsDocument' }
1024
+ capabilities:
1025
+ type: object
1026
+ additionalProperties: false
1027
+ required: [goal, plan, skills, mcp, diagnostics, review, files, git, terminal]
1028
+ properties:
1029
+ goal: { type: boolean }
1030
+ plan: { type: boolean }
1031
+ skills: { type: boolean }
1032
+ mcp: { type: boolean }
1033
+ diagnostics: { type: boolean }
1034
+ review: { type: boolean, const: true }
1035
+ files: { type: boolean, const: true }
1036
+ git: { type: boolean, const: true }
1037
+ terminal: { type: boolean }
1038
+ MutationRequest:
1039
+ type: object
1040
+ additionalProperties: false
1041
+ required: [requestId]
1042
+ properties:
1043
+ requestId: { $ref: '#/components/schemas/RequestId' }
1044
+ RequestId:
1045
+ type: string
1046
+ format: uuid
1047
+ description: >-
1048
+ Client-generated idempotency key. Reuse is valid only for a byte-equivalent normalized
1049
+ mutation body.
1050
+ ContextRevision:
1051
+ type: string
1052
+ format: uuid
1053
+ description: Compare-and-swap identity for the single active Workspace/Session context.
1054
+ ContextActivateRequest:
1055
+ type: object
1056
+ additionalProperties: false
1057
+ required: [requestId, expectedContextRevision, workspaceId, sessionId]
1058
+ properties:
1059
+ requestId: { $ref: '#/components/schemas/RequestId' }
1060
+ expectedContextRevision: { $ref: '#/components/schemas/ContextRevision' }
1061
+ workspaceId: { type: string, format: uuid }
1062
+ sessionId: { type: [string, 'null'] }
1063
+ ContextMutationResult:
1064
+ type: object
1065
+ additionalProperties: false
1066
+ required: [requestId, contextRevision, bootstrap]
1067
+ properties:
1068
+ requestId: { $ref: '#/components/schemas/RequestId' }
1069
+ contextRevision: { $ref: '#/components/schemas/ContextRevision' }
1070
+ bootstrap: { $ref: '#/components/schemas/BootstrapResponse' }
1071
+ ActivateWorkspaceRequest:
1072
+ type: object
1073
+ additionalProperties: false
1074
+ required: [requestId, expectedContextRevision, path]
1075
+ properties:
1076
+ requestId: { $ref: '#/components/schemas/RequestId' }
1077
+ expectedContextRevision: { $ref: '#/components/schemas/ContextRevision' }
1078
+ path: { type: string, minLength: 1, maxLength: 4096 }
1079
+ CreateSessionRequest:
1080
+ type: object
1081
+ additionalProperties: false
1082
+ required: [requestId, expectedContextRevision, workspaceId]
1083
+ properties:
1084
+ requestId: { $ref: '#/components/schemas/RequestId' }
1085
+ expectedContextRevision: { $ref: '#/components/schemas/ContextRevision' }
1086
+ workspaceId: { type: string, format: uuid }
1087
+ name: { type: string, minLength: 1, maxLength: 120 }
1088
+ RenameSessionRequest:
1089
+ type: object
1090
+ additionalProperties: false
1091
+ required: [requestId, expectedContextRevision, workspaceId, name]
1092
+ properties:
1093
+ requestId: { $ref: '#/components/schemas/RequestId' }
1094
+ expectedContextRevision: { $ref: '#/components/schemas/ContextRevision' }
1095
+ workspaceId: { type: string, format: uuid }
1096
+ name: { type: string, minLength: 1, maxLength: 120 }
1097
+ WorkspaceSummary:
1098
+ type: object
1099
+ additionalProperties: false
1100
+ required: [id, path, label, active, available, sessionCount, lastActivatedAt]
1101
+ properties:
1102
+ id: { type: string, format: uuid }
1103
+ path: { type: string }
1104
+ label: { type: string }
1105
+ active: { type: boolean }
1106
+ available: { type: boolean }
1107
+ sessionCount: { type: integer, minimum: 0 }
1108
+ lastActivatedAt: { type: string, format: date-time }
1109
+ pinnedOrder: { type: integer, minimum: 0 }
1110
+ WorkspacePage:
1111
+ type: object
1112
+ additionalProperties: false
1113
+ required: [items, nextCursor]
1114
+ properties:
1115
+ items:
1116
+ type: array
1117
+ maxItems: 100
1118
+ items: { $ref: '#/components/schemas/WorkspaceSummary' }
1119
+ nextCursor: { type: [string, 'null'] }
1120
+ WorkspaceMutationResult:
1121
+ type: object
1122
+ additionalProperties: false
1123
+ required: [requestId, active, page]
1124
+ properties:
1125
+ requestId: { $ref: '#/components/schemas/RequestId' }
1126
+ active: { type: string }
1127
+ page: { $ref: '#/components/schemas/WorkspacePage' }
1128
+ WorkspaceProjectSummary:
1129
+ type: object
1130
+ additionalProperties: false
1131
+ required:
1132
+ - workspaceId
1133
+ - repositoryRevision
1134
+ - isRepository
1135
+ - branch
1136
+ - detached
1137
+ - head
1138
+ - dirtyCount
1139
+ - conflictCount
1140
+ properties:
1141
+ workspaceId: { type: string, format: uuid }
1142
+ repositoryRevision: { type: string, minLength: 1 }
1143
+ isRepository: { type: boolean }
1144
+ branch: { type: [string, 'null'] }
1145
+ detached: { type: boolean }
1146
+ head: { type: [string, 'null'] }
1147
+ dirtyCount: { type: integer, minimum: 0 }
1148
+ conflictCount: { type: integer, minimum: 0 }
1149
+ WorkspacePinRequest:
1150
+ type: object
1151
+ additionalProperties: false
1152
+ required: [requestId, expectedContextRevision, pinned]
1153
+ properties:
1154
+ requestId: { $ref: '#/components/schemas/RequestId' }
1155
+ expectedContextRevision: { $ref: '#/components/schemas/ContextRevision' }
1156
+ pinned: { type: boolean }
1157
+ WorkspacePinResult:
1158
+ type: object
1159
+ additionalProperties: false
1160
+ required: [requestId, workspace]
1161
+ properties:
1162
+ requestId: { $ref: '#/components/schemas/RequestId' }
1163
+ workspace: { $ref: '#/components/schemas/WorkspaceSummary' }
1164
+ WorkspaceRemoveRequest:
1165
+ type: object
1166
+ additionalProperties: false
1167
+ required: [requestId, expectedContextRevision]
1168
+ properties:
1169
+ requestId: { $ref: '#/components/schemas/RequestId' }
1170
+ expectedContextRevision: { $ref: '#/components/schemas/ContextRevision' }
1171
+ WorkspaceRemoveResult:
1172
+ type: object
1173
+ additionalProperties: false
1174
+ required: [requestId, removed]
1175
+ properties:
1176
+ requestId: { $ref: '#/components/schemas/RequestId' }
1177
+ removed: { type: boolean, const: true }
1178
+ SessionSummary:
1179
+ type: object
1180
+ additionalProperties: false
1181
+ required: [id, projectPath, model, createdAt, updatedAt, messageCount]
1182
+ properties:
1183
+ id: { type: string }
1184
+ projectPath: { type: string }
1185
+ name: { type: string }
1186
+ model: { type: string }
1187
+ createdAt: { type: string, format: date-time }
1188
+ updatedAt: { type: string, format: date-time }
1189
+ messageCount: { type: integer, minimum: 0 }
1190
+ taskSummary: { type: string }
1191
+ activeGoalId: { type: string }
1192
+ activeGoalObjective: { type: string }
1193
+ SessionPage:
1194
+ type: object
1195
+ additionalProperties: false
1196
+ required: [items, nextCursor]
1197
+ properties:
1198
+ items:
1199
+ type: array
1200
+ maxItems: 100
1201
+ items: { $ref: '#/components/schemas/SessionSummary' }
1202
+ nextCursor: { type: [string, 'null'] }
1203
+ SessionMutationResult:
1204
+ type: object
1205
+ additionalProperties: false
1206
+ required: [requestId, session]
1207
+ properties:
1208
+ requestId: { $ref: '#/components/schemas/RequestId' }
1209
+ session: { $ref: '#/components/schemas/SessionSummary' }
1210
+ FileNode:
1211
+ type: object
1212
+ additionalProperties: false
1213
+ required: [id, name, displayPath, kind, modifiedAt, sensitive, readable]
1214
+ properties:
1215
+ id: { type: string, minLength: 1 }
1216
+ name: { type: string, minLength: 1 }
1217
+ displayPath:
1218
+ type: string
1219
+ minLength: 1
1220
+ description: Sanitized workspace-relative display metadata; requests still use opaque id.
1221
+ kind: { type: string, enum: [file, directory, symlink] }
1222
+ sizeBytes: { type: integer, minimum: 0 }
1223
+ modifiedAt: { type: string, format: date-time }
1224
+ sensitive: { type: boolean }
1225
+ readable: { type: boolean }
1226
+ FileTreePage:
1227
+ type: object
1228
+ additionalProperties: false
1229
+ required: [parentId, revision, items, nextCursor]
1230
+ properties:
1231
+ parentId: { type: string, minLength: 1 }
1232
+ revision: { type: string, minLength: 1 }
1233
+ items:
1234
+ type: array
1235
+ maxItems: 100
1236
+ items: { $ref: '#/components/schemas/FileNode' }
1237
+ nextCursor: { type: [string, 'null'] }
1238
+ FileContentPage:
1239
+ type: object
1240
+ additionalProperties: false
1241
+ required:
1242
+ - fileId
1243
+ - name
1244
+ - revision
1245
+ - sizeBytes
1246
+ - binary
1247
+ - sensitive
1248
+ - mediaType
1249
+ - offsetBytes
1250
+ - nextCursor
1251
+ properties:
1252
+ fileId: { type: string, minLength: 1 }
1253
+ name: { type: string, minLength: 1 }
1254
+ revision: { type: string, minLength: 1 }
1255
+ sizeBytes: { type: integer, minimum: 0 }
1256
+ binary: { type: boolean }
1257
+ sensitive: { type: boolean, const: false }
1258
+ mediaType: { type: string, enum: [text/plain, application/octet-stream] }
1259
+ offsetBytes: { type: integer, minimum: 0 }
1260
+ content:
1261
+ type: string
1262
+ description: Present only for redacted UTF-8 text; omitted for binary metadata.
1263
+ nextCursor: { type: [string, 'null'] }
1264
+ GitFile:
1265
+ type: object
1266
+ additionalProperties: false
1267
+ required: [fileId, path, indexStatus, worktreeStatus]
1268
+ properties:
1269
+ fileId: { type: string, minLength: 1 }
1270
+ path:
1271
+ type: string
1272
+ description: Sanitized workspace-relative display path; requests still use fileId.
1273
+ indexStatus: { type: string, minLength: 1, maxLength: 1 }
1274
+ worktreeStatus: { type: string, minLength: 1, maxLength: 1 }
1275
+ renamedFrom: { type: string }
1276
+ GitFileList:
1277
+ type: array
1278
+ maxItems: 2000
1279
+ items: { $ref: '#/components/schemas/GitFile' }
1280
+ GitStatus:
1281
+ type: object
1282
+ additionalProperties: false
1283
+ required:
1284
+ - isRepository
1285
+ - repositoryRevision
1286
+ - branch
1287
+ - detached
1288
+ - head
1289
+ - upstream
1290
+ - ahead
1291
+ - behind
1292
+ - clean
1293
+ - staged
1294
+ - unstaged
1295
+ - untracked
1296
+ - conflicted
1297
+ - totalFiles
1298
+ - truncated
1299
+ - nextCursor
1300
+ properties:
1301
+ isRepository: { type: boolean }
1302
+ repositoryRevision: { type: string, minLength: 1 }
1303
+ rootLabel: { type: string }
1304
+ branch: { type: [string, 'null'] }
1305
+ detached: { type: boolean }
1306
+ head: { type: [string, 'null'] }
1307
+ upstream: { type: [string, 'null'] }
1308
+ ahead: { type: integer, minimum: 0 }
1309
+ behind: { type: integer, minimum: 0 }
1310
+ clean: { type: boolean }
1311
+ staged: { $ref: '#/components/schemas/GitFileList' }
1312
+ unstaged: { $ref: '#/components/schemas/GitFileList' }
1313
+ untracked: { $ref: '#/components/schemas/GitFileList' }
1314
+ conflicted: { $ref: '#/components/schemas/GitFileList' }
1315
+ totalFiles: { type: integer, minimum: 0 }
1316
+ truncated: { type: boolean }
1317
+ nextCursor: { type: [string, 'null'] }
1318
+ GitCommit:
1319
+ type: object
1320
+ additionalProperties: false
1321
+ required: [id, shortId, authoredAt, authorName, subject]
1322
+ properties:
1323
+ id: { type: string, pattern: '^[a-f0-9]{40,64}$' }
1324
+ shortId: { type: string, pattern: '^[a-f0-9]{7,16}$' }
1325
+ authoredAt: { type: string, format: date-time }
1326
+ authorName: { type: string }
1327
+ subject: { type: string }
1328
+ GitLogPage:
1329
+ type: object
1330
+ additionalProperties: false
1331
+ required: [repositoryRevision, items, nextCursor]
1332
+ properties:
1333
+ repositoryRevision: { type: string, minLength: 1 }
1334
+ items:
1335
+ type: array
1336
+ maxItems: 100
1337
+ items: { $ref: '#/components/schemas/GitCommit' }
1338
+ nextCursor: { type: [string, 'null'] }
1339
+ GitDiffPage:
1340
+ type: object
1341
+ additionalProperties: false
1342
+ required:
1343
+ - fileId
1344
+ - path
1345
+ - repositoryRevision
1346
+ - binary
1347
+ - lines
1348
+ - nextCursor
1349
+ - truncated
1350
+ properties:
1351
+ fileId: { type: string, minLength: 1 }
1352
+ path: { type: string }
1353
+ repositoryRevision: { type: string, minLength: 1 }
1354
+ binary: { type: boolean }
1355
+ lines:
1356
+ type: array
1357
+ maxItems: 500
1358
+ items: { type: string }
1359
+ nextCursor: { type: [string, 'null'] }
1360
+ truncated: { type: boolean }
1361
+ ReviewVerification:
1362
+ type: object
1363
+ additionalProperties: false
1364
+ required:
1365
+ - callId
1366
+ - sessionId
1367
+ - threadId
1368
+ - sequence
1369
+ - toolName
1370
+ - state
1371
+ - terminal
1372
+ - success
1373
+ - outputBytes
1374
+ - hasArtifact
1375
+ - executionPolicyDigest
1376
+ - receiptDigest
1377
+ properties:
1378
+ callId: { type: string, minLength: 1 }
1379
+ sessionId: { type: string, minLength: 1 }
1380
+ threadId: { type: string, minLength: 1 }
1381
+ sequence: { type: integer, minimum: 1 }
1382
+ toolName: { type: string, minLength: 1 }
1383
+ state: { type: string, enum: [success, error, skipped] }
1384
+ terminal: { type: string, enum: [completed, failed, interrupted, indeterminate] }
1385
+ success: { type: boolean }
1386
+ outputBytes: { type: integer, minimum: 0 }
1387
+ hasArtifact: { type: boolean }
1388
+ executionPolicyDigest: { type: string, pattern: '^[a-f0-9]{64}$' }
1389
+ receiptDigest: { type: string, pattern: '^[a-f0-9]{64}$' }
1390
+ ReviewSnapshot:
1391
+ type: object
1392
+ additionalProperties: false
1393
+ required:
1394
+ - revision
1395
+ - repositoryRevision
1396
+ - isRepository
1397
+ - clean
1398
+ - changedFiles
1399
+ - stagedCount
1400
+ - unstagedCount
1401
+ - untrackedCount
1402
+ - conflictCount
1403
+ - truncated
1404
+ - verification
1405
+ properties:
1406
+ revision: { type: string, minLength: 1 }
1407
+ repositoryRevision: { type: string, minLength: 1 }
1408
+ isRepository: { type: boolean }
1409
+ clean: { type: boolean }
1410
+ changedFiles: { $ref: '#/components/schemas/GitFileList' }
1411
+ stagedCount: { type: integer, minimum: 0 }
1412
+ unstagedCount: { type: integer, minimum: 0 }
1413
+ untrackedCount: { type: integer, minimum: 0 }
1414
+ conflictCount: { type: integer, minimum: 0 }
1415
+ truncated: { type: boolean }
1416
+ verification:
1417
+ type: array
1418
+ maxItems: 100
1419
+ items: { $ref: '#/components/schemas/ReviewVerification' }
1420
+ ContextGuardRequest:
1421
+ type: object
1422
+ additionalProperties: false
1423
+ required: [requestId, expectedContextRevision, workspaceId]
1424
+ properties:
1425
+ requestId: { $ref: '#/components/schemas/RequestId' }
1426
+ expectedContextRevision: { $ref: '#/components/schemas/ContextRevision' }
1427
+ workspaceId: { type: string, format: uuid }
1428
+ TerminalCreateRequest:
1429
+ type: object
1430
+ additionalProperties: false
1431
+ required: [requestId, expectedContextRevision, workspaceId]
1432
+ properties:
1433
+ requestId: { $ref: '#/components/schemas/RequestId' }
1434
+ expectedContextRevision: { $ref: '#/components/schemas/ContextRevision' }
1435
+ workspaceId: { type: string, format: uuid }
1436
+ cols: { type: integer, minimum: 2, maximum: 400, default: 100 }
1437
+ rows: { type: integer, minimum: 1, maximum: 200, default: 30 }
1438
+ TerminalMetadata:
1439
+ type: object
1440
+ additionalProperties: false
1441
+ required:
1442
+ - id
1443
+ - workspaceId
1444
+ - title
1445
+ - shell
1446
+ - state
1447
+ - cols
1448
+ - rows
1449
+ - connected
1450
+ - createdAt
1451
+ - lastActiveAt
1452
+ - earliestSequence
1453
+ - lastSequence
1454
+ properties:
1455
+ id: { type: string, format: uuid }
1456
+ workspaceId: { type: string, format: uuid }
1457
+ title: { type: string }
1458
+ shell: { type: string, description: Display basename only; no shell argv or environment. }
1459
+ state: { type: string, enum: [running, exited, closing] }
1460
+ cols: { type: integer, minimum: 2, maximum: 400 }
1461
+ rows: { type: integer, minimum: 1, maximum: 200 }
1462
+ connected: { type: boolean }
1463
+ createdAt: { type: string, format: date-time }
1464
+ lastActiveAt: { type: string, format: date-time }
1465
+ earliestSequence: { type: integer, minimum: 1 }
1466
+ lastSequence: { type: integer, minimum: 0 }
1467
+ exitCode: { type: integer }
1468
+ signal: { type: integer }
1469
+ TerminalPage:
1470
+ type: object
1471
+ additionalProperties: false
1472
+ required: [items, nextCursor]
1473
+ properties:
1474
+ items:
1475
+ type: array
1476
+ maxItems: 100
1477
+ items: { $ref: '#/components/schemas/TerminalMetadata' }
1478
+ nextCursor: { type: [string, 'null'] }
1479
+ TerminalTicket:
1480
+ type: object
1481
+ additionalProperties: false
1482
+ required: [ticket, ticketExpiresAt]
1483
+ properties:
1484
+ ticket:
1485
+ type: string
1486
+ minLength: 32
1487
+ maxLength: 128
1488
+ writeOnly: true
1489
+ description: Single-use bearer delivered only in this JSON body and first WS message.
1490
+ ticketExpiresAt: { type: string, format: date-time }
1491
+ TerminalCreateMutationResult:
1492
+ type: object
1493
+ additionalProperties: false
1494
+ required: [requestId, terminal, ticket, ticketExpiresAt]
1495
+ properties:
1496
+ requestId: { $ref: '#/components/schemas/RequestId' }
1497
+ terminal: { $ref: '#/components/schemas/TerminalMetadata' }
1498
+ ticket: { type: string, minLength: 32, maxLength: 128, writeOnly: true }
1499
+ ticketExpiresAt: { type: string, format: date-time }
1500
+ TerminalTicketMutationResult:
1501
+ type: object
1502
+ additionalProperties: false
1503
+ required: [requestId, ticket, ticketExpiresAt]
1504
+ properties:
1505
+ requestId: { $ref: '#/components/schemas/RequestId' }
1506
+ ticket: { type: string, minLength: 32, maxLength: 128, writeOnly: true }
1507
+ ticketExpiresAt: { type: string, format: date-time }
1508
+ TerminalCloseMutationResult:
1509
+ type: object
1510
+ additionalProperties: false
1511
+ required: [requestId, terminal]
1512
+ properties:
1513
+ requestId: { $ref: '#/components/schemas/RequestId' }
1514
+ terminal: { $ref: '#/components/schemas/TerminalMetadata' }
1515
+ TerminalAuthenticateMessage:
1516
+ type: object
1517
+ additionalProperties: false
1518
+ required: [type, ticket, afterSequence]
1519
+ properties:
1520
+ type: { type: string, const: authenticate }
1521
+ ticket: { type: string, minLength: 32, maxLength: 128, writeOnly: true }
1522
+ afterSequence: { type: integer, minimum: 0 }
1523
+ TerminalInputMessage:
1524
+ type: object
1525
+ additionalProperties: false
1526
+ required: [type, data]
1527
+ properties:
1528
+ type: { type: string, const: input }
1529
+ data: { type: string, maxLength: 65536 }
1530
+ TerminalResizeMessage:
1531
+ type: object
1532
+ additionalProperties: false
1533
+ required: [type, cols, rows]
1534
+ properties:
1535
+ type: { type: string, const: resize }
1536
+ cols: { type: integer, minimum: 2, maximum: 400 }
1537
+ rows: { type: integer, minimum: 1, maximum: 200 }
1538
+ TerminalPingMessage:
1539
+ type: object
1540
+ additionalProperties: false
1541
+ required: [type, timestamp]
1542
+ properties:
1543
+ type: { type: string, const: ping }
1544
+ timestamp: { type: number }
1545
+ TerminalClientMessage:
1546
+ oneOf:
1547
+ - $ref: '#/components/schemas/TerminalInputMessage'
1548
+ - $ref: '#/components/schemas/TerminalResizeMessage'
1549
+ - $ref: '#/components/schemas/TerminalPingMessage'
1550
+ discriminator: { propertyName: type }
1551
+ TerminalReadyMessage:
1552
+ type: object
1553
+ additionalProperties: false
1554
+ required: [type, terminal]
1555
+ properties:
1556
+ type: { type: string, const: ready }
1557
+ terminal: { $ref: '#/components/schemas/TerminalMetadata' }
1558
+ TerminalOutputMessage:
1559
+ type: object
1560
+ additionalProperties: false
1561
+ required: [type, sequence, data]
1562
+ properties:
1563
+ type: { type: string, const: output }
1564
+ sequence: { type: integer, minimum: 1 }
1565
+ data: { type: string, maxLength: 8000 }
1566
+ TerminalGapMessage:
1567
+ type: object
1568
+ additionalProperties: false
1569
+ required: [type, earliestSequence, latestSequence]
1570
+ properties:
1571
+ type: { type: string, const: gap }
1572
+ earliestSequence: { type: integer, minimum: 1 }
1573
+ latestSequence: { type: integer, minimum: 0 }
1574
+ TerminalExitMessage:
1575
+ type: object
1576
+ additionalProperties: false
1577
+ required: [type, exitCode]
1578
+ properties:
1579
+ type: { type: string, const: exit }
1580
+ exitCode: { type: integer }
1581
+ signal: { type: integer }
1582
+ TerminalPongMessage:
1583
+ type: object
1584
+ additionalProperties: false
1585
+ required: [type, timestamp]
1586
+ properties:
1587
+ type: { type: string, const: pong }
1588
+ timestamp: { type: number }
1589
+ TerminalErrorMessage:
1590
+ type: object
1591
+ additionalProperties: false
1592
+ required: [type, code]
1593
+ properties:
1594
+ type: { type: string, const: error }
1595
+ code: { type: string, minLength: 1 }
1596
+ TerminalServerMessage:
1597
+ oneOf:
1598
+ - $ref: '#/components/schemas/TerminalReadyMessage'
1599
+ - $ref: '#/components/schemas/TerminalOutputMessage'
1600
+ - $ref: '#/components/schemas/TerminalGapMessage'
1601
+ - $ref: '#/components/schemas/TerminalExitMessage'
1602
+ - $ref: '#/components/schemas/TerminalPongMessage'
1603
+ - $ref: '#/components/schemas/TerminalErrorMessage'
1604
+ discriminator: { propertyName: type }
1605
+ TranscriptMessage:
1606
+ type: object
1607
+ additionalProperties: false
1608
+ required: [id, role, content, timestamp]
1609
+ properties:
1610
+ id: { type: string }
1611
+ role:
1612
+ type: string
1613
+ enum: [system, user, assistant, tool]
1614
+ content: { type: string }
1615
+ timestamp: { type: number, minimum: 0 }
1616
+ modelVisibleContent: { type: string }
1617
+ toolCallId: { type: string }
1618
+ tool_calls:
1619
+ type: array
1620
+ items: {}
1621
+ appliedSkills:
1622
+ type: array
1623
+ items: { type: string }
1624
+ TranscriptPage:
1625
+ type: object
1626
+ additionalProperties: false
1627
+ required: [items, nextCursor]
1628
+ properties:
1629
+ items:
1630
+ type: array
1631
+ maxItems: 100
1632
+ items: { $ref: '#/components/schemas/TranscriptMessage' }
1633
+ nextCursor: { type: [string, 'null'] }
1634
+ GoalView:
1635
+ type: object
1636
+ additionalProperties: false
1637
+ description: >-
1638
+ Goal projection from the latest valid TurnCommitV1. A legacy Goal sidecar is eligible only
1639
+ as a one-time migration seed and is never a competing read authority.
1640
+ required: [authority, digest, state]
1641
+ properties:
1642
+ authority: { type: string, const: turn_commit }
1643
+ digest: { type: string, minLength: 1 }
1644
+ state:
1645
+ description: >-
1646
+ Opaque JSON value parsed from TurnCommitV1.goalState. The v0.3.0 wire type is unknown;
1647
+ this contract does not invent required Goal fields or status/revision enums.
1648
+ PlanView:
1649
+ type: object
1650
+ additionalProperties: false
1651
+ description: >-
1652
+ Exact safe projection of the PlanReceipt bound into TurnCommitV1. A valid planning commit
1653
+ enters durable Plan review; it never schedules execution until the exact digest is approved.
1654
+ required: [body, returnMode, digest]
1655
+ properties:
1656
+ body: { type: string, minLength: 1 }
1657
+ returnMode: { type: string, enum: [build, auto] }
1658
+ digest: { type: string, minLength: 1 }
1659
+ PendingApproval:
1660
+ type: object
1661
+ additionalProperties: false
1662
+ description: Runtime-owned approval that survives browser disconnect and tab closure.
1663
+ required: [id, toolName, sanitizedArguments, allowedScopes]
1664
+ properties:
1665
+ id: { type: string }
1666
+ toolName: { type: string }
1667
+ reason: { type: string }
1668
+ sanitizedArguments: { type: object, additionalProperties: true }
1669
+ allowedScopes:
1670
+ type: array
1671
+ const: [once, project, global]
1672
+ items: { type: string, enum: [once, project, global] }
1673
+ FollowupItem:
1674
+ type: object
1675
+ additionalProperties: false
1676
+ required: [id, text, queuedAt]
1677
+ properties:
1678
+ id: { type: string }
1679
+ text: { type: string }
1680
+ queuedAt: { type: number, minimum: 0 }
1681
+ ControlRevision:
1682
+ type: string
1683
+ format: uuid
1684
+ description: Compare-and-swap identity for the active Session Composer authority.
1685
+ ContextUsageView:
1686
+ type: object
1687
+ additionalProperties: false
1688
+ required:
1689
+ - modelId
1690
+ - usedTokens
1691
+ - contextWindow
1692
+ - percent
1693
+ - source
1694
+ - warningThresholdPercent
1695
+ - autoCompactThresholdPercent
1696
+ - autoCompactEnabled
1697
+ properties:
1698
+ modelId: { type: string, minLength: 1 }
1699
+ usedTokens: { type: integer, minimum: 0 }
1700
+ contextWindow: { type: integer, minimum: 1 }
1701
+ percent: { type: number, minimum: 0 }
1702
+ rawPercent: { type: number, minimum: 0 }
1703
+ safeInputBudget: { type: integer, minimum: 0 }
1704
+ reservedOutputTokens: { type: integer, minimum: 0 }
1705
+ safetyMarginTokens: { type: integer, minimum: 0 }
1706
+ source: { type: string, enum: [estimated, provider, provider_adjusted] }
1707
+ warningThresholdPercent: { type: number, minimum: 0 }
1708
+ autoCompactThresholdPercent: { type: number, minimum: 0 }
1709
+ autoCompactEnabled: { type: boolean }
1710
+ ComposerEffortSelection:
1711
+ type: object
1712
+ additionalProperties: false
1713
+ required: [requested, effective, source, supported, supportedLevels]
1714
+ properties:
1715
+ requested: { $ref: '#/components/schemas/EffortPreference' }
1716
+ effective:
1717
+ oneOf:
1718
+ - type: string
1719
+ enum: [none, minimal, low, medium, high, xhigh, max]
1720
+ - type: 'null'
1721
+ source:
1722
+ type: string
1723
+ enum: [request, session, project, global, model-default, provider-default]
1724
+ supported: { type: boolean }
1725
+ supportedLevels:
1726
+ type: array
1727
+ uniqueItems: true
1728
+ items: { type: string, enum: [none, minimal, low, medium, high, xhigh, max] }
1729
+ warning: { type: string }
1730
+ ComposerModelSelection:
1731
+ type: object
1732
+ additionalProperties: false
1733
+ required:
1734
+ - modelId
1735
+ - providerId
1736
+ - providerLabel
1737
+ - contextWindow
1738
+ - maxOutputTokens
1739
+ - effort
1740
+ properties:
1741
+ modelId: { type: string, minLength: 1, maxLength: 256 }
1742
+ providerId: { type: [string, 'null'] }
1743
+ providerLabel: { type: [string, 'null'] }
1744
+ contextWindow: { type: integer, minimum: 1 }
1745
+ maxOutputTokens: { type: integer, minimum: 0 }
1746
+ effort: { $ref: '#/components/schemas/ComposerEffortSelection' }
1747
+ ComposerPermissionSelection:
1748
+ type: object
1749
+ additionalProperties: false
1750
+ required: [effective, override, projectDefault, source]
1751
+ properties:
1752
+ effective: { type: string, enum: [ask, allow, deny] }
1753
+ override:
1754
+ oneOf:
1755
+ - type: string
1756
+ enum: [ask, allow, deny]
1757
+ - type: 'null'
1758
+ projectDefault: { type: string, enum: [ask, allow, deny] }
1759
+ source: { type: string, enum: [session, project] }
1760
+ ComposerPendingState:
1761
+ type: object
1762
+ additionalProperties: false
1763
+ required: [model, permission]
1764
+ properties:
1765
+ model:
1766
+ oneOf:
1767
+ - type: object
1768
+ additionalProperties: false
1769
+ required: [modelId, effort]
1770
+ properties:
1771
+ modelId: { type: string, minLength: 1, maxLength: 256 }
1772
+ effort: { $ref: '#/components/schemas/EffortPreference' }
1773
+ - type: 'null'
1774
+ permission:
1775
+ oneOf:
1776
+ - type: object
1777
+ additionalProperties: false
1778
+ required: [override]
1779
+ properties:
1780
+ override:
1781
+ oneOf:
1782
+ - type: string
1783
+ enum: [ask, allow, deny]
1784
+ - type: 'null'
1785
+ - type: 'null'
1786
+ ComposerLastError:
1787
+ type: object
1788
+ additionalProperties: false
1789
+ required: [code, message]
1790
+ properties:
1791
+ code:
1792
+ type: string
1793
+ enum:
1794
+ - runtime_busy
1795
+ - model_unavailable
1796
+ - model_effort_unsupported
1797
+ - model_switch_rolled_back
1798
+ - permission_override_rejected
1799
+ - composer_control_conflict
1800
+ - composer_recovery_required
1801
+ - session_unavailable
1802
+ message: { type: string, minLength: 1 }
1803
+ PlanReviewView:
1804
+ type: object
1805
+ additionalProperties: false
1806
+ required: [planDigest, revision, status, createdAt, createdModel, returnMode]
1807
+ properties:
1808
+ planDigest: { type: string, pattern: '^[a-f0-9]{64}$' }
1809
+ revision: { type: string, format: uuid }
1810
+ status: { type: string, enum: [awaiting_review, approved, continued, cancelled] }
1811
+ createdAt: { type: number, minimum: 0 }
1812
+ createdModel: { type: string, minLength: 1 }
1813
+ returnMode: { type: string, enum: [build, auto] }
1814
+ resolvedAt: { type: number, minimum: 0 }
1815
+ ComposerQueueItem:
1816
+ type: object
1817
+ additionalProperties: false
1818
+ required: [id, text, queuedAt, revision]
1819
+ properties:
1820
+ id: { type: string, minLength: 1 }
1821
+ text: { type: string, minLength: 1, maxLength: 1048576 }
1822
+ queuedAt: { type: number, minimum: 0 }
1823
+ revision: { type: integer, minimum: 1 }
1824
+ ComposerQueue:
1825
+ type: object
1826
+ additionalProperties: false
1827
+ required: [items, limit]
1828
+ properties:
1829
+ items:
1830
+ type: array
1831
+ maxItems: 16
1832
+ items: { $ref: '#/components/schemas/ComposerQueueItem' }
1833
+ limit: { type: integer, minimum: 0, maximum: 16 }
1834
+ ComposerControlState:
1835
+ type: object
1836
+ additionalProperties: false
1837
+ required:
1838
+ - apiVersion
1839
+ - workspaceId
1840
+ - sessionId
1841
+ - contextRevision
1842
+ - controlRevision
1843
+ - processing
1844
+ - mode
1845
+ - model
1846
+ - permission
1847
+ - contextUsage
1848
+ - compactAvailable
1849
+ - pending
1850
+ - lastError
1851
+ - planReview
1852
+ - queue
1853
+ properties:
1854
+ apiVersion: { type: integer, const: 1 }
1855
+ workspaceId: { type: string, format: uuid }
1856
+ sessionId: { type: string, minLength: 1, maxLength: 256 }
1857
+ contextRevision: { $ref: '#/components/schemas/ContextRevision' }
1858
+ controlRevision: { $ref: '#/components/schemas/ControlRevision' }
1859
+ processing: { type: boolean }
1860
+ compactAvailable: { type: boolean }
1861
+ mode:
1862
+ type: object
1863
+ additionalProperties: false
1864
+ required: [baseMode, pendingBaseMode]
1865
+ properties:
1866
+ baseMode: { type: string, enum: [interactive, plan, auto] }
1867
+ pendingBaseMode:
1868
+ oneOf:
1869
+ - type: string
1870
+ enum: [interactive, plan, auto]
1871
+ - type: 'null'
1872
+ model: { $ref: '#/components/schemas/ComposerModelSelection' }
1873
+ permission: { $ref: '#/components/schemas/ComposerPermissionSelection' }
1874
+ contextUsage:
1875
+ oneOf:
1876
+ - $ref: '#/components/schemas/ContextUsageView'
1877
+ - type: 'null'
1878
+ pending: { $ref: '#/components/schemas/ComposerPendingState' }
1879
+ lastError:
1880
+ oneOf:
1881
+ - $ref: '#/components/schemas/ComposerLastError'
1882
+ - type: 'null'
1883
+ planReview:
1884
+ oneOf:
1885
+ - $ref: '#/components/schemas/PlanReviewView'
1886
+ - type: 'null'
1887
+ queue: { $ref: '#/components/schemas/ComposerQueue' }
1888
+ ModelCatalogEntry:
1889
+ type: object
1890
+ additionalProperties: false
1891
+ required:
1892
+ - id
1893
+ - label
1894
+ - providerId
1895
+ - providerLabel
1896
+ - contextWindow
1897
+ - maxOutputTokens
1898
+ - reasoning
1899
+ - effortLevels
1900
+ - aliases
1901
+ - fingerprint
1902
+ properties:
1903
+ id: { type: string, minLength: 1, maxLength: 256 }
1904
+ label: { type: string, minLength: 1 }
1905
+ providerId: { type: string, minLength: 1 }
1906
+ providerLabel: { type: string, minLength: 1 }
1907
+ contextWindow: { type: integer, minimum: 1 }
1908
+ maxOutputTokens: { type: integer, minimum: 0 }
1909
+ reasoning: { type: boolean }
1910
+ effortLevels:
1911
+ type: array
1912
+ uniqueItems: true
1913
+ items: { type: string, enum: [none, minimal, low, medium, high, xhigh, max] }
1914
+ defaultEffort: { type: string, enum: [none, minimal, low, medium, high, xhigh, max] }
1915
+ aliases:
1916
+ type: array
1917
+ items: { type: string }
1918
+ fingerprint: { type: string, pattern: '^[a-f0-9]{64}$' }
1919
+ ModelCatalogPage:
1920
+ type: object
1921
+ additionalProperties: false
1922
+ required: [revision, unavailableProviders, items, nextCursor]
1923
+ properties:
1924
+ revision: { type: string, pattern: '^[a-f0-9]{64}$' }
1925
+ unavailableProviders:
1926
+ type: array
1927
+ items:
1928
+ type: object
1929
+ additionalProperties: false
1930
+ required: [id, reason]
1931
+ properties:
1932
+ id: { type: string, minLength: 1 }
1933
+ reason: { type: string, minLength: 1 }
1934
+ items:
1935
+ type: array
1936
+ maxItems: 100
1937
+ items: { $ref: '#/components/schemas/ModelCatalogEntry' }
1938
+ nextCursor: { type: [string, 'null'] }
1939
+ SessionRuntimeSnapshot:
1940
+ type: object
1941
+ additionalProperties: false
1942
+ required:
1943
+ - active
1944
+ - processing
1945
+ - agentMode
1946
+ - permissionMode
1947
+ - status
1948
+ - followups
1949
+ - followupLimit
1950
+ - contextUsage
1951
+ - tokenUsage
1952
+ properties:
1953
+ active: { type: boolean }
1954
+ processing: { type: boolean }
1955
+ agentMode: { type: string }
1956
+ permissionMode: { type: string }
1957
+ status: { type: string }
1958
+ followups:
1959
+ type: array
1960
+ items: { $ref: '#/components/schemas/FollowupItem' }
1961
+ followupLimit: { type: integer, minimum: 0 }
1962
+ contextUsage:
1963
+ description: Runtime context-usage projection or null; the wire type is currently unknown.
1964
+ tokenUsage:
1965
+ description: Runtime token-usage projection or null; the wire type is currently unknown.
1966
+ SessionSnapshot:
1967
+ type: object
1968
+ additionalProperties: false
1969
+ required:
1970
+ - apiVersion
1971
+ - session
1972
+ - threadId
1973
+ - threadCursor
1974
+ - eventCursor
1975
+ - threadStatus
1976
+ - transcript
1977
+ - runtime
1978
+ - pendingApprovals
1979
+ - goal
1980
+ - plan
1981
+ - composer
1982
+ - recoveryDiagnostics
1983
+ properties:
1984
+ apiVersion: { type: integer, const: 1 }
1985
+ session: { $ref: '#/components/schemas/SessionSummary' }
1986
+ threadId:
1987
+ type: [string, 'null']
1988
+ description: Null for a legacy session that has no materialized Thread identity.
1989
+ threadCursor:
1990
+ type: integer
1991
+ minimum: 0
1992
+ description: Latest projected durable Thread sequence; independent of eventCursor.
1993
+ eventCursor: { type: integer, minimum: 0 }
1994
+ projectionDigest: { type: string }
1995
+ threadStatus: { type: string, enum: [new, active, idle, legacy] }
1996
+ activeTurnId: { type: string }
1997
+ transcript: { $ref: '#/components/schemas/TranscriptPage' }
1998
+ runtime: { $ref: '#/components/schemas/SessionRuntimeSnapshot' }
1999
+ pendingApprovals:
2000
+ type: array
2001
+ items: { $ref: '#/components/schemas/PendingApproval' }
2002
+ goal:
2003
+ oneOf:
2004
+ - $ref: '#/components/schemas/GoalView'
2005
+ - type: 'null'
2006
+ plan:
2007
+ oneOf:
2008
+ - $ref: '#/components/schemas/PlanView'
2009
+ - type: 'null'
2010
+ composer: { $ref: '#/components/schemas/ComposerControlState' }
2011
+ recoveryDiagnostics:
2012
+ type: array
2013
+ items: {}
2014
+ SkillSummary:
2015
+ type: object
2016
+ additionalProperties: false
2017
+ required:
2018
+ - id
2019
+ - name
2020
+ - description
2021
+ - providerId
2022
+ - sourceScope
2023
+ - modelInvocable
2024
+ - userInvocable
2025
+ - requestedCapabilities
2026
+ - digest
2027
+ properties:
2028
+ id: { type: string }
2029
+ name: { type: string }
2030
+ description: { type: string }
2031
+ providerId: { type: string }
2032
+ sourceScope: { type: string, enum: [builtin, user, configured, project, remote] }
2033
+ modelInvocable: { type: boolean }
2034
+ userInvocable: { type: boolean }
2035
+ requestedCapabilities:
2036
+ type: array
2037
+ items: { type: string }
2038
+ digest: { type: string }
2039
+ SkillPage:
2040
+ type: object
2041
+ additionalProperties: false
2042
+ required: [items, nextCursor]
2043
+ properties:
2044
+ items:
2045
+ type: array
2046
+ maxItems: 100
2047
+ items: { $ref: '#/components/schemas/SkillSummary' }
2048
+ nextCursor: { type: [string, 'null'] }
2049
+ McpServerSummary:
2050
+ type: object
2051
+ additionalProperties: false
2052
+ required:
2053
+ - id
2054
+ - name
2055
+ - transport
2056
+ - tags
2057
+ - disabled
2058
+ - state
2059
+ - generation
2060
+ - toolCount
2061
+ - activeCallCount
2062
+ properties:
2063
+ id: { type: string }
2064
+ name: { type: string }
2065
+ description: { type: string }
2066
+ transport:
2067
+ type: string
2068
+ enum: [stdio, sse, http, streamable-http, websocket]
2069
+ tags:
2070
+ type: array
2071
+ items: { type: string }
2072
+ disabled: { type: boolean }
2073
+ state:
2074
+ type: string
2075
+ enum: [dormant, activating, connected, idle, draining, failed]
2076
+ generation: { type: integer, minimum: 0 }
2077
+ toolCount: { type: integer, minimum: 0 }
2078
+ activeCallCount: { type: integer, minimum: 0 }
2079
+ failure: { type: string }
2080
+ McpPage:
2081
+ type: object
2082
+ additionalProperties: false
2083
+ required: [items, nextCursor]
2084
+ properties:
2085
+ items:
2086
+ type: array
2087
+ maxItems: 100
2088
+ items: { $ref: '#/components/schemas/McpServerSummary' }
2089
+ nextCursor: { type: [string, 'null'] }
2090
+ ToolDetailSummary:
2091
+ type: object
2092
+ additionalProperties: false
2093
+ required: [callId, sequence, toolName, state, outputBytes, hasArtifact]
2094
+ properties:
2095
+ callId: { type: string }
2096
+ sequence: { type: integer, minimum: 0 }
2097
+ turnId: { type: string }
2098
+ toolName: { type: string }
2099
+ state: { type: string, enum: [success, error, skipped] }
2100
+ outputBytes: { type: integer, minimum: 0 }
2101
+ artifactId:
2102
+ type: string
2103
+ description: Opaque project artifact identifier; it is not a filesystem path.
2104
+ hasArtifact: { type: boolean }
2105
+ ToolDetailSummaryPage:
2106
+ type: object
2107
+ additionalProperties: false
2108
+ required: [items, nextCursor]
2109
+ properties:
2110
+ items:
2111
+ type: array
2112
+ maxItems: 100
2113
+ items: { $ref: '#/components/schemas/ToolDetailSummary' }
2114
+ nextCursor: { type: [string, 'null'] }
2115
+ ToolDetailPage:
2116
+ type: object
2117
+ additionalProperties: false
2118
+ required: [content, offsetBytes, totalBytes, redacted]
2119
+ properties:
2120
+ content: { type: string }
2121
+ offsetBytes: { type: integer, minimum: 0 }
2122
+ nextOffsetBytes:
2123
+ type: [integer, 'null']
2124
+ minimum: 0
2125
+ description: Omitted or null when the page reaches the end of the artifact.
2126
+ totalBytes: { type: integer, minimum: 0 }
2127
+ redacted:
2128
+ type: boolean
2129
+ description: >-
2130
+ True when content is served from the browser-safe, pre-sanitized derivative. It does
2131
+ not imply that this particular page contained a secret replacement.
2132
+ SettingsRevision:
2133
+ type: string
2134
+ pattern: '^hmac-sha256:[a-f0-9]{64}$'
2135
+ description: >-
2136
+ Opaque HMAC over the exact current config bytes. The local HMAC key is never exposed.
2137
+ SettingsFieldCommon:
2138
+ type: object
2139
+ required: [source, scope, applies, overridden, writable]
2140
+ properties:
2141
+ source: { type: string, enum: [internal, model, global, project, session] }
2142
+ scope: { type: string, enum: [global, project, session] }
2143
+ applies:
2144
+ type: string
2145
+ enum: [live, next-logical-request, new-session, restart]
2146
+ overridden: { type: boolean }
2147
+ writable: { type: boolean }
2148
+ blockedReason:
2149
+ type: string
2150
+ enum: [runtime_busy, read_only, invalid_document]
2151
+ ThemeSettingsField:
2152
+ allOf:
2153
+ - $ref: '#/components/schemas/SettingsFieldCommon'
2154
+ - type: object
2155
+ required: [effectiveValue]
2156
+ properties:
2157
+ effectiveValue: { type: string, enum: [system, light, dark] }
2158
+ explicitValue: { type: string, enum: [system, light, dark] }
2159
+ inheritedValue: { type: string, enum: [system, light, dark] }
2160
+ MotionSettingsField:
2161
+ allOf:
2162
+ - $ref: '#/components/schemas/SettingsFieldCommon'
2163
+ - type: object
2164
+ required: [effectiveValue]
2165
+ properties:
2166
+ effectiveValue: { type: string, enum: [system, reduced] }
2167
+ explicitValue: { type: string, enum: [system, reduced] }
2168
+ inheritedValue: { type: string, enum: [system, reduced] }
2169
+ ModelSettingsField:
2170
+ allOf:
2171
+ - $ref: '#/components/schemas/SettingsFieldCommon'
2172
+ - type: object
2173
+ required: [effectiveValue]
2174
+ properties:
2175
+ effectiveValue: { type: string, minLength: 1 }
2176
+ explicitValue: { type: string, minLength: 1 }
2177
+ inheritedValue: { type: string, minLength: 1 }
2178
+ EffortSettingsField:
2179
+ allOf:
2180
+ - $ref: '#/components/schemas/SettingsFieldCommon'
2181
+ - type: object
2182
+ required: [effectiveValue]
2183
+ properties:
2184
+ effectiveValue: { $ref: '#/components/schemas/EffortPreference' }
2185
+ explicitValue: { $ref: '#/components/schemas/EffortPreference' }
2186
+ inheritedValue: { $ref: '#/components/schemas/EffortPreference' }
2187
+ ToolConfirmationSettingsField:
2188
+ allOf:
2189
+ - $ref: '#/components/schemas/SettingsFieldCommon'
2190
+ - type: object
2191
+ required: [effectiveValue]
2192
+ properties:
2193
+ effectiveValue: { type: string, enum: [allow, ask, deny] }
2194
+ explicitValue: { type: string, enum: [allow, ask, deny] }
2195
+ inheritedValue: { type: string, enum: [allow, ask, deny] }
2196
+ EffortPreference:
2197
+ type: string
2198
+ enum: [auto, none, minimal, low, medium, high, xhigh, max]
2199
+ ModelSummary:
2200
+ type: object
2201
+ additionalProperties: false
2202
+ required: [id, label]
2203
+ properties:
2204
+ id: { type: string, minLength: 1 }
2205
+ label: { type: string, minLength: 1 }
2206
+ provider: { type: string }
2207
+ CredentialSlot:
2208
+ type: object
2209
+ additionalProperties: false
2210
+ required: [providerId, state, source, writable]
2211
+ properties:
2212
+ providerId: { type: string, minLength: 1 }
2213
+ state: { type: string, enum: [ready, missing, unavailable] }
2214
+ source: { type: string, enum: [environment, legacy, none] }
2215
+ writable: { type: boolean, const: false }
2216
+ SettingsDocument:
2217
+ type: object
2218
+ additionalProperties: false
2219
+ required:
2220
+ - schemaVersion
2221
+ - revision
2222
+ - state
2223
+ - writable
2224
+ - hasDocument
2225
+ - workspace
2226
+ - sections
2227
+ - models
2228
+ - credentials
2229
+ properties:
2230
+ schemaVersion: { type: integer, const: 1 }
2231
+ revision: { $ref: '#/components/schemas/SettingsRevision' }
2232
+ state: { type: string, enum: [ready, invalid, read-only, unavailable] }
2233
+ writable: { type: boolean }
2234
+ hasDocument: { type: boolean }
2235
+ workspace: { type: string }
2236
+ sections:
2237
+ type: object
2238
+ additionalProperties: false
2239
+ required: [appearance, defaults, permissions]
2240
+ properties:
2241
+ appearance:
2242
+ type: object
2243
+ additionalProperties: false
2244
+ required: [theme, motion]
2245
+ properties:
2246
+ theme: { $ref: '#/components/schemas/ThemeSettingsField' }
2247
+ motion: { $ref: '#/components/schemas/MotionSettingsField' }
2248
+ defaults:
2249
+ type: object
2250
+ additionalProperties: false
2251
+ required: [model, effort]
2252
+ properties:
2253
+ model: { $ref: '#/components/schemas/ModelSettingsField' }
2254
+ effort: { $ref: '#/components/schemas/EffortSettingsField' }
2255
+ permissions:
2256
+ type: object
2257
+ additionalProperties: false
2258
+ required: [toolConfirmation]
2259
+ properties:
2260
+ toolConfirmation:
2261
+ $ref: '#/components/schemas/ToolConfirmationSettingsField'
2262
+ models:
2263
+ type: array
2264
+ items: { $ref: '#/components/schemas/ModelSummary' }
2265
+ credentials:
2266
+ type: array
2267
+ items: { $ref: '#/components/schemas/CredentialSlot' }
2268
+ currentSession:
2269
+ type: object
2270
+ additionalProperties: false
2271
+ required: [model, effort, overridesProjectEffort]
2272
+ properties:
2273
+ model: { type: string }
2274
+ effort: { $ref: '#/components/schemas/EffortPreference' }
2275
+ overridesProjectEffort: { type: boolean }
2276
+ diagnostic:
2277
+ type: object
2278
+ additionalProperties: false
2279
+ required: [code, message]
2280
+ properties:
2281
+ code: { type: string }
2282
+ message: { type: string }
2283
+ SettingsOperation:
2284
+ oneOf:
2285
+ - $ref: '#/components/schemas/SetThemeSetting'
2286
+ - $ref: '#/components/schemas/UnsetThemeSetting'
2287
+ - $ref: '#/components/schemas/SetMotionSetting'
2288
+ - $ref: '#/components/schemas/UnsetMotionSetting'
2289
+ - $ref: '#/components/schemas/SetModelSetting'
2290
+ - $ref: '#/components/schemas/UnsetModelSetting'
2291
+ - $ref: '#/components/schemas/SetEffortSetting'
2292
+ - $ref: '#/components/schemas/UnsetEffortSetting'
2293
+ - $ref: '#/components/schemas/SetToolConfirmationSetting'
2294
+ - $ref: '#/components/schemas/UnsetToolConfirmationSetting'
2295
+ SetThemeSetting:
2296
+ type: object
2297
+ additionalProperties: false
2298
+ required: [op, key, value]
2299
+ properties:
2300
+ op: { type: string, const: set }
2301
+ key: { type: string, const: appearance.theme }
2302
+ value: { type: string, enum: [system, light, dark] }
2303
+ UnsetThemeSetting:
2304
+ type: object
2305
+ additionalProperties: false
2306
+ required: [op, key]
2307
+ properties:
2308
+ op: { type: string, const: unset }
2309
+ key: { type: string, const: appearance.theme }
2310
+ SetMotionSetting:
2311
+ type: object
2312
+ additionalProperties: false
2313
+ required: [op, key, value]
2314
+ properties:
2315
+ op: { type: string, const: set }
2316
+ key: { type: string, const: appearance.motion }
2317
+ value: { type: string, enum: [system, reduced] }
2318
+ UnsetMotionSetting:
2319
+ type: object
2320
+ additionalProperties: false
2321
+ required: [op, key]
2322
+ properties:
2323
+ op: { type: string, const: unset }
2324
+ key: { type: string, const: appearance.motion }
2325
+ SetModelSetting:
2326
+ type: object
2327
+ additionalProperties: false
2328
+ required: [op, key, value]
2329
+ properties:
2330
+ op: { type: string, const: set }
2331
+ key: { type: string, const: defaults.model }
2332
+ value: { type: string, minLength: 1, maxLength: 200 }
2333
+ UnsetModelSetting:
2334
+ type: object
2335
+ additionalProperties: false
2336
+ required: [op, key]
2337
+ properties:
2338
+ op: { type: string, const: unset }
2339
+ key: { type: string, const: defaults.model }
2340
+ SetEffortSetting:
2341
+ type: object
2342
+ additionalProperties: false
2343
+ required: [op, key, value]
2344
+ properties:
2345
+ op: { type: string, const: set }
2346
+ key: { type: string, const: defaults.effort }
2347
+ value: { $ref: '#/components/schemas/EffortPreference' }
2348
+ UnsetEffortSetting:
2349
+ type: object
2350
+ additionalProperties: false
2351
+ required: [op, key]
2352
+ properties:
2353
+ op: { type: string, const: unset }
2354
+ key: { type: string, const: defaults.effort }
2355
+ SetToolConfirmationSetting:
2356
+ type: object
2357
+ additionalProperties: false
2358
+ required: [op, key, value]
2359
+ properties:
2360
+ op: { type: string, const: set }
2361
+ key: { type: string, const: permissions.toolConfirmation }
2362
+ value: { type: string, enum: [allow, ask, deny] }
2363
+ UnsetToolConfirmationSetting:
2364
+ type: object
2365
+ additionalProperties: false
2366
+ required: [op, key]
2367
+ properties:
2368
+ op: { type: string, const: unset }
2369
+ key: { type: string, const: permissions.toolConfirmation }
2370
+ UpdateSettingsRequest:
2371
+ type: object
2372
+ additionalProperties: false
2373
+ required: [requestId, expectedRevision, operations]
2374
+ properties:
2375
+ requestId: { $ref: '#/components/schemas/RequestId' }
2376
+ expectedRevision: { $ref: '#/components/schemas/SettingsRevision' }
2377
+ operations:
2378
+ type: array
2379
+ minItems: 1
2380
+ maxItems: 20
2381
+ items: { $ref: '#/components/schemas/SettingsOperation' }
2382
+ SettingsMutationResult:
2383
+ type: object
2384
+ additionalProperties: false
2385
+ required: [requestId, revision, appliedKeys, settings]
2386
+ properties:
2387
+ requestId: { $ref: '#/components/schemas/RequestId' }
2388
+ revision: { $ref: '#/components/schemas/SettingsRevision' }
2389
+ appliedKeys:
2390
+ type: array
2391
+ minItems: 1
2392
+ maxItems: 20
2393
+ items:
2394
+ type: string
2395
+ enum:
2396
+ - appearance.theme
2397
+ - appearance.motion
2398
+ - defaults.model
2399
+ - defaults.effort
2400
+ - permissions.toolConfirmation
2401
+ settings: { $ref: '#/components/schemas/SettingsDocument' }
2402
+ ContextReference:
2403
+ oneOf:
2404
+ - $ref: '#/components/schemas/FileContextReference'
2405
+ - $ref: '#/components/schemas/FolderContextReference'
2406
+ - $ref: '#/components/schemas/ReviewContextReference'
2407
+ - $ref: '#/components/schemas/SessionContextReference'
2408
+ - $ref: '#/components/schemas/SkillContextReference'
2409
+ discriminator:
2410
+ propertyName: kind
2411
+ mapping:
2412
+ file: '#/components/schemas/FileContextReference'
2413
+ folder: '#/components/schemas/FolderContextReference'
2414
+ review: '#/components/schemas/ReviewContextReference'
2415
+ session: '#/components/schemas/SessionContextReference'
2416
+ skill: '#/components/schemas/SkillContextReference'
2417
+ FileContextReference:
2418
+ type: object
2419
+ additionalProperties: false
2420
+ required: [kind, id, label, revision]
2421
+ properties:
2422
+ kind: { type: string, const: file }
2423
+ id: { type: string, minLength: 1, maxLength: 1024 }
2424
+ label: { type: string, minLength: 1, maxLength: 256 }
2425
+ revision: { type: string, minLength: 1, maxLength: 256 }
2426
+ FolderContextReference:
2427
+ type: object
2428
+ additionalProperties: false
2429
+ required: [kind, id, label, revision]
2430
+ properties:
2431
+ kind: { type: string, const: folder }
2432
+ id: { type: string, minLength: 1, maxLength: 1024 }
2433
+ label: { type: string, minLength: 1, maxLength: 256 }
2434
+ revision: { type: string, minLength: 1, maxLength: 256 }
2435
+ ReviewContextReference:
2436
+ type: object
2437
+ additionalProperties: false
2438
+ required: [kind, id, label, gitRevision]
2439
+ properties:
2440
+ kind: { type: string, const: review }
2441
+ id: { type: string, minLength: 1, maxLength: 1024 }
2442
+ label: { type: string, minLength: 1, maxLength: 256 }
2443
+ gitRevision: { type: string, minLength: 1, maxLength: 256 }
2444
+ SessionContextReference:
2445
+ type: object
2446
+ additionalProperties: false
2447
+ required: [kind, id, label, digest]
2448
+ properties:
2449
+ kind: { type: string, const: session }
2450
+ id: { type: string, minLength: 1, maxLength: 256 }
2451
+ label: { type: string, minLength: 1, maxLength: 256 }
2452
+ digest: { type: string, pattern: '^[a-f0-9]{64}$' }
2453
+ SkillContextReference:
2454
+ type: object
2455
+ additionalProperties: false
2456
+ required: [kind, id, label, digest]
2457
+ properties:
2458
+ kind: { type: string, const: skill }
2459
+ id: { type: string, minLength: 1, maxLength: 256 }
2460
+ label: { type: string, minLength: 1, maxLength: 256 }
2461
+ digest: { type: string, pattern: '^[a-f0-9]{64}$' }
2462
+ ComposerActionBase:
2463
+ type: object
2464
+ required:
2465
+ - requestId
2466
+ - workspaceId
2467
+ - expectedContextRevision
2468
+ - expectedSessionId
2469
+ - expectedControlRevision
2470
+ - type
2471
+ properties:
2472
+ requestId: { $ref: '#/components/schemas/RequestId' }
2473
+ workspaceId: { type: string, format: uuid }
2474
+ expectedContextRevision: { $ref: '#/components/schemas/ContextRevision' }
2475
+ expectedSessionId: { type: string, format: uuid }
2476
+ expectedControlRevision: { $ref: '#/components/schemas/ControlRevision' }
2477
+ type:
2478
+ type: string
2479
+ enum:
2480
+ - set_agent_mode
2481
+ - set_permission_override
2482
+ - clear_permission_override
2483
+ - select_model
2484
+ - compact_context
2485
+ - review_plan
2486
+ - edit_queue_item
2487
+ - move_queue_item
2488
+ - remove_queue_item
2489
+ ComposerSetModeAction:
2490
+ allOf:
2491
+ - $ref: '#/components/schemas/ComposerActionBase'
2492
+ - type: object
2493
+ required: [mode]
2494
+ properties:
2495
+ type: { type: string, const: set_agent_mode }
2496
+ mode: { type: string, enum: [interactive, plan, auto] }
2497
+ unevaluatedProperties: false
2498
+ ComposerSetPermissionAction:
2499
+ allOf:
2500
+ - $ref: '#/components/schemas/ComposerActionBase'
2501
+ - type: object
2502
+ required: [value]
2503
+ properties:
2504
+ type: { type: string, const: set_permission_override }
2505
+ value: { type: string, enum: [ask, allow, deny] }
2506
+ unevaluatedProperties: false
2507
+ ComposerClearPermissionAction:
2508
+ allOf:
2509
+ - $ref: '#/components/schemas/ComposerActionBase'
2510
+ - type: object
2511
+ properties:
2512
+ type: { type: string, const: clear_permission_override }
2513
+ unevaluatedProperties: false
2514
+ ComposerSelectModelAction:
2515
+ allOf:
2516
+ - $ref: '#/components/schemas/ComposerActionBase'
2517
+ - type: object
2518
+ required: [modelId]
2519
+ properties:
2520
+ type: { type: string, const: select_model }
2521
+ modelId: { type: string, minLength: 1, maxLength: 256 }
2522
+ effort: { $ref: '#/components/schemas/EffortPreference' }
2523
+ unevaluatedProperties: false
2524
+ ComposerCompactAction:
2525
+ allOf:
2526
+ - $ref: '#/components/schemas/ComposerActionBase'
2527
+ - type: object
2528
+ properties:
2529
+ type: { type: string, const: compact_context }
2530
+ unevaluatedProperties: false
2531
+ ComposerReviewPlanAction:
2532
+ allOf:
2533
+ - $ref: '#/components/schemas/ComposerActionBase'
2534
+ - type: object
2535
+ required: [planDigest, action]
2536
+ properties:
2537
+ type: { type: string, const: review_plan }
2538
+ planDigest: { type: string, pattern: '^[a-f0-9]{64}$' }
2539
+ action: { type: string, enum: [approve, continue, cancel] }
2540
+ feedback: { type: string, minLength: 1, maxLength: 1048576 }
2541
+ unevaluatedProperties: false
2542
+ ComposerEditQueueAction:
2543
+ allOf:
2544
+ - $ref: '#/components/schemas/ComposerActionBase'
2545
+ - type: object
2546
+ required: [itemId, expectedItemRevision, text]
2547
+ properties:
2548
+ type: { type: string, const: edit_queue_item }
2549
+ itemId: { type: string, minLength: 1, maxLength: 256 }
2550
+ expectedItemRevision: { type: integer, minimum: 1 }
2551
+ text: { type: string, minLength: 1, maxLength: 1048576 }
2552
+ unevaluatedProperties: false
2553
+ ComposerMoveQueueAction:
2554
+ allOf:
2555
+ - $ref: '#/components/schemas/ComposerActionBase'
2556
+ - type: object
2557
+ required: [itemId, expectedItemRevision, targetIndex]
2558
+ properties:
2559
+ type: { type: string, const: move_queue_item }
2560
+ itemId: { type: string, minLength: 1, maxLength: 256 }
2561
+ expectedItemRevision: { type: integer, minimum: 1 }
2562
+ targetIndex: { type: integer, minimum: 0, maximum: 15 }
2563
+ unevaluatedProperties: false
2564
+ ComposerRemoveQueueAction:
2565
+ allOf:
2566
+ - $ref: '#/components/schemas/ComposerActionBase'
2567
+ - type: object
2568
+ required: [itemId, expectedItemRevision]
2569
+ properties:
2570
+ type: { type: string, const: remove_queue_item }
2571
+ itemId: { type: string, minLength: 1, maxLength: 256 }
2572
+ expectedItemRevision: { type: integer, minimum: 1 }
2573
+ unevaluatedProperties: false
2574
+ ComposerAction:
2575
+ oneOf:
2576
+ - $ref: '#/components/schemas/ComposerSetModeAction'
2577
+ - $ref: '#/components/schemas/ComposerSetPermissionAction'
2578
+ - $ref: '#/components/schemas/ComposerClearPermissionAction'
2579
+ - $ref: '#/components/schemas/ComposerSelectModelAction'
2580
+ - $ref: '#/components/schemas/ComposerCompactAction'
2581
+ - $ref: '#/components/schemas/ComposerReviewPlanAction'
2582
+ - $ref: '#/components/schemas/ComposerEditQueueAction'
2583
+ - $ref: '#/components/schemas/ComposerMoveQueueAction'
2584
+ - $ref: '#/components/schemas/ComposerRemoveQueueAction'
2585
+ discriminator:
2586
+ propertyName: type
2587
+ mapping:
2588
+ set_agent_mode: '#/components/schemas/ComposerSetModeAction'
2589
+ set_permission_override: '#/components/schemas/ComposerSetPermissionAction'
2590
+ clear_permission_override: '#/components/schemas/ComposerClearPermissionAction'
2591
+ select_model: '#/components/schemas/ComposerSelectModelAction'
2592
+ compact_context: '#/components/schemas/ComposerCompactAction'
2593
+ review_plan: '#/components/schemas/ComposerReviewPlanAction'
2594
+ edit_queue_item: '#/components/schemas/ComposerEditQueueAction'
2595
+ move_queue_item: '#/components/schemas/ComposerMoveQueueAction'
2596
+ remove_queue_item: '#/components/schemas/ComposerRemoveQueueAction'
2597
+ SessionModelSwitchReceipt:
2598
+ type: object
2599
+ additionalProperties: false
2600
+ required:
2601
+ - receiptId
2602
+ - fromModelId
2603
+ - toModelId
2604
+ - requestedEffort
2605
+ - compacted
2606
+ - compactRequired
2607
+ - compactPreflight
2608
+ - appliesFrom
2609
+ - sessionPreferencesDigest
2610
+ properties:
2611
+ receiptId: { type: string, format: uuid }
2612
+ fromModelId: { type: string, minLength: 1 }
2613
+ toModelId: { type: string, minLength: 1 }
2614
+ requestedEffort: { $ref: '#/components/schemas/EffortPreference' }
2615
+ compacted: { type: boolean }
2616
+ compactRequired: { type: boolean }
2617
+ compactPreflight:
2618
+ type: string
2619
+ enum: [not_required, unavailable, not_needed, committed, deferred]
2620
+ appliesFrom: { type: string, enum: [immediate, next-logical-request] }
2621
+ sessionPreferencesDigest: { type: string, pattern: '^[a-f0-9]{64}$' }
2622
+ SessionPermissionReceipt:
2623
+ type: object
2624
+ additionalProperties: false
2625
+ required: [receiptId, previous, current, appliesFrom, sessionPreferencesDigest]
2626
+ properties:
2627
+ receiptId: { type: string, format: uuid }
2628
+ previous: { $ref: '#/components/schemas/ComposerPermissionSelection' }
2629
+ current: { $ref: '#/components/schemas/ComposerPermissionSelection' }
2630
+ appliesFrom: { type: string, enum: [immediate, next-tool-admission] }
2631
+ sessionPreferencesDigest: { type: string, pattern: '^[a-f0-9]{64}$' }
2632
+ PlanReviewProjection:
2633
+ type: object
2634
+ additionalProperties: false
2635
+ required:
2636
+ - reviewId
2637
+ - revision
2638
+ - planDigest
2639
+ - planReceiptDigest
2640
+ - status
2641
+ - createdAt
2642
+ - createdModel
2643
+ - returnMode
2644
+ - requestedSeq
2645
+ properties:
2646
+ reviewId: { type: string, format: uuid }
2647
+ revision: { type: string, format: uuid }
2648
+ planDigest: { type: string, pattern: '^[a-f0-9]{64}$' }
2649
+ planReceiptDigest: { type: string, pattern: '^[a-f0-9]{64}$' }
2650
+ status: { type: string, enum: [awaiting_review, approved, continued, cancelled] }
2651
+ createdAt: { type: number, minimum: 0 }
2652
+ createdModel: { type: string, minLength: 1 }
2653
+ returnMode: { type: string, enum: [build, auto] }
2654
+ requestedSeq: { type: integer, minimum: 1 }
2655
+ resolvedAt: { type: number, minimum: 0 }
2656
+ resolvedSeq: { type: integer, minimum: 1 }
2657
+ feedback: { type: string }
2658
+ feedbackDigest: { type: string, pattern: '^[a-f0-9]{64}$' }
2659
+ PlanReviewAdmission:
2660
+ oneOf:
2661
+ - type: object
2662
+ additionalProperties: false
2663
+ required: [status, turnId]
2664
+ properties:
2665
+ status: { type: string, const: started }
2666
+ turnId: { type: string, minLength: 1 }
2667
+ - type: object
2668
+ additionalProperties: false
2669
+ required: [status, queueId]
2670
+ properties:
2671
+ status: { type: string, const: queued }
2672
+ queueId: { type: string, minLength: 1 }
2673
+ - type: object
2674
+ additionalProperties: false
2675
+ required: [status]
2676
+ properties:
2677
+ status: { type: string, enum: [already_admitted, cancelled] }
2678
+ - type: object
2679
+ additionalProperties: false
2680
+ required: [status, reason]
2681
+ properties:
2682
+ status: { type: string, const: pending }
2683
+ reason: { type: string, minLength: 1 }
2684
+ discriminator: { propertyName: status }
2685
+ PlanReviewResolutionReceipt:
2686
+ type: object
2687
+ additionalProperties: false
2688
+ required: [receiptId, state, admission, digest]
2689
+ properties:
2690
+ receiptId: { type: string, format: uuid }
2691
+ state: { $ref: '#/components/schemas/PlanReviewProjection' }
2692
+ admission: { $ref: '#/components/schemas/PlanReviewAdmission' }
2693
+ digest: { type: string, pattern: '^[a-f0-9]{64}$' }
2694
+ ComposerActionResult:
2695
+ type: object
2696
+ additionalProperties: false
2697
+ required: [requestId, outcome, controlRevision, state]
2698
+ properties:
2699
+ requestId: { $ref: '#/components/schemas/RequestId' }
2700
+ outcome: { type: string, enum: [applied, deferred] }
2701
+ controlRevision: { $ref: '#/components/schemas/ControlRevision' }
2702
+ state: { $ref: '#/components/schemas/ComposerControlState' }
2703
+ modelReceipt: { $ref: '#/components/schemas/SessionModelSwitchReceipt' }
2704
+ permissionReceipt: { $ref: '#/components/schemas/SessionPermissionReceipt' }
2705
+ planReviewReceipt: { $ref: '#/components/schemas/PlanReviewResolutionReceipt' }
2706
+ detail: { type: string }
2707
+ WebCommand:
2708
+ type: object
2709
+ additionalProperties: false
2710
+ required: [requestId, expectedContextRevision, workspaceId, expectedSessionId, type]
2711
+ allOf:
2712
+ - if:
2713
+ properties:
2714
+ type: { const: set_agent_mode }
2715
+ required: [type]
2716
+ then:
2717
+ required: [agentMode]
2718
+ properties:
2719
+ requestId: { $ref: '#/components/schemas/RequestId' }
2720
+ expectedContextRevision: { $ref: '#/components/schemas/ContextRevision' }
2721
+ workspaceId: { type: string, format: uuid }
2722
+ expectedSessionId:
2723
+ type: string
2724
+ minLength: 1
2725
+ maxLength: 256
2726
+ description: >-
2727
+ Compare-and-swap guard for the active Session. The Host returns 409
2728
+ active_session_changed without dispatching when the selection no longer matches.
2729
+ type:
2730
+ type: string
2731
+ enum:
2732
+ - submit
2733
+ - queue_followup
2734
+ - remove_followup
2735
+ - clear_followups
2736
+ - interrupt
2737
+ - permission_decision
2738
+ - goal_control
2739
+ - permission_mode_change
2740
+ - cycle_agent_mode
2741
+ - set_agent_mode
2742
+ text: { type: string, maxLength: 1048576 }
2743
+ itemId: { type: string }
2744
+ requestPermissionId: { type: string }
2745
+ approved: { type: boolean }
2746
+ scope: { type: string, enum: [once, project, global] }
2747
+ goalAction: { type: string, enum: [create, status, pause, resume, clear] }
2748
+ objective: { type: string }
2749
+ toolConfirmation: { type: string, enum: [allow, ask, deny] }
2750
+ agentMode: { type: string, enum: [interactive, plan, auto] }
2751
+ contextReferences:
2752
+ type: array
2753
+ maxItems: 20
2754
+ items: { $ref: '#/components/schemas/ContextReference' }
2755
+ CommandResult:
2756
+ type: object
2757
+ additionalProperties: false
2758
+ required: [requestId, result]
2759
+ properties:
2760
+ requestId: { $ref: '#/components/schemas/RequestId' }
2761
+ result: { type: string }
2762
+ detail: { type: string }
2763
+ WebEventEnvelope:
2764
+ description: >-
2765
+ Versioned, cursor-ordered event union. `type` is the discriminator; every branch carries
2766
+ explicit `sessionId` and `threadId` keys. Runtime events allow null identities before a
2767
+ session or Thread exists; committed Thread events require both values to be non-null.
2768
+ oneOf:
2769
+ - $ref: '#/components/schemas/RuntimeEventEnvelope'
2770
+ - $ref: '#/components/schemas/ThreadEventEnvelope'
2771
+ - $ref: '#/components/schemas/WorkbenchStateEnvelope'
2772
+ - $ref: '#/components/schemas/SettingsInvalidatedEnvelope'
2773
+ - $ref: '#/components/schemas/WorkspaceResourceInvalidatedEnvelope'
2774
+ - $ref: '#/components/schemas/ComposerStateChangedEnvelope'
2775
+ - $ref: '#/components/schemas/ReplayResetEnvelope'
2776
+ discriminator:
2777
+ propertyName: type
2778
+ mapping:
2779
+ runtime_event: '#/components/schemas/RuntimeEventEnvelope'
2780
+ thread_event: '#/components/schemas/ThreadEventEnvelope'
2781
+ workbench_state: '#/components/schemas/WorkbenchStateEnvelope'
2782
+ settings_invalidated: '#/components/schemas/SettingsInvalidatedEnvelope'
2783
+ workspace_resource_invalidated: '#/components/schemas/WorkspaceResourceInvalidatedEnvelope'
2784
+ composer_state_changed: '#/components/schemas/ComposerStateChangedEnvelope'
2785
+ replay_reset: '#/components/schemas/ReplayResetEnvelope'
2786
+ RuntimeEventEnvelope:
2787
+ type: object
2788
+ additionalProperties: false
2789
+ required:
2790
+ - apiVersion
2791
+ - eventId
2792
+ - cursor
2793
+ - sessionId
2794
+ - threadId
2795
+ - type
2796
+ - durable
2797
+ - timestamp
2798
+ - payload
2799
+ properties:
2800
+ apiVersion: { type: integer, const: 1 }
2801
+ eventId: { type: string, format: uuid }
2802
+ cursor: { type: integer, minimum: 1 }
2803
+ sessionId: { type: [string, 'null'] }
2804
+ threadId: { type: [string, 'null'] }
2805
+ type: { type: string, const: runtime_event }
2806
+ durable: { type: boolean }
2807
+ timestamp: { type: string, format: date-time }
2808
+ payload:
2809
+ type: object
2810
+ additionalProperties: false
2811
+ required: [eventType, value]
2812
+ properties:
2813
+ eventType: { type: string, minLength: 1 }
2814
+ value: { type: object, additionalProperties: true }
2815
+ ThreadEventEnvelope:
2816
+ type: object
2817
+ additionalProperties: false
2818
+ required:
2819
+ - apiVersion
2820
+ - eventId
2821
+ - cursor
2822
+ - sessionId
2823
+ - threadId
2824
+ - type
2825
+ - durable
2826
+ - timestamp
2827
+ - payload
2828
+ properties:
2829
+ apiVersion: { type: integer, const: 1 }
2830
+ eventId: { type: string, format: uuid }
2831
+ cursor: { type: integer, minimum: 1 }
2832
+ sessionId: { type: string, minLength: 1 }
2833
+ threadId: { type: string, minLength: 1 }
2834
+ type: { type: string, const: thread_event }
2835
+ durable: { type: boolean, const: true }
2836
+ timestamp: { type: string, format: date-time }
2837
+ payload:
2838
+ type: object
2839
+ additionalProperties: false
2840
+ required: [sequence, eventType, value]
2841
+ properties:
2842
+ sequence: { type: integer, minimum: 1 }
2843
+ eventType: { type: string, minLength: 1 }
2844
+ value: { type: object, additionalProperties: true }
2845
+ WorkbenchStateEnvelope:
2846
+ type: object
2847
+ additionalProperties: false
2848
+ required:
2849
+ - apiVersion
2850
+ - eventId
2851
+ - cursor
2852
+ - sessionId
2853
+ - threadId
2854
+ - type
2855
+ - durable
2856
+ - timestamp
2857
+ - payload
2858
+ properties:
2859
+ apiVersion: { type: integer, const: 1 }
2860
+ eventId: { type: string, format: uuid }
2861
+ cursor: { type: integer, minimum: 1 }
2862
+ sessionId: { type: [string, 'null'] }
2863
+ threadId: { type: [string, 'null'] }
2864
+ type: { type: string, const: workbench_state }
2865
+ durable: { type: boolean }
2866
+ timestamp: { type: string, format: date-time }
2867
+ payload:
2868
+ type: object
2869
+ additionalProperties: false
2870
+ required: [contextRevision, workspaceId, workspace, activeSessionId]
2871
+ properties:
2872
+ contextRevision: { $ref: '#/components/schemas/ContextRevision' }
2873
+ workspaceId: { type: string, format: uuid }
2874
+ workspace: { type: string }
2875
+ activeSessionId: { type: [string, 'null'] }
2876
+ SettingsInvalidatedEnvelope:
2877
+ type: object
2878
+ additionalProperties: false
2879
+ required:
2880
+ - apiVersion
2881
+ - eventId
2882
+ - cursor
2883
+ - sessionId
2884
+ - threadId
2885
+ - type
2886
+ - durable
2887
+ - timestamp
2888
+ - payload
2889
+ properties:
2890
+ apiVersion: { type: integer, const: 1 }
2891
+ eventId: { type: string, format: uuid }
2892
+ cursor: { type: integer, minimum: 1 }
2893
+ sessionId: { type: [string, 'null'] }
2894
+ threadId: { type: [string, 'null'] }
2895
+ type: { type: string, const: settings_invalidated }
2896
+ durable: { type: boolean, const: false }
2897
+ timestamp: { type: string, format: date-time }
2898
+ payload:
2899
+ type: object
2900
+ additionalProperties: false
2901
+ required: [revision, reason, state]
2902
+ properties:
2903
+ revision: { $ref: '#/components/schemas/SettingsRevision' }
2904
+ reason: { type: string, enum: [local-write, external-edit, workspace-change] }
2905
+ state: { type: string, enum: [ready, invalid] }
2906
+ WorkspaceResourceInvalidatedEnvelope:
2907
+ type: object
2908
+ additionalProperties: false
2909
+ required:
2910
+ - apiVersion
2911
+ - eventId
2912
+ - cursor
2913
+ - sessionId
2914
+ - threadId
2915
+ - type
2916
+ - durable
2917
+ - timestamp
2918
+ - payload
2919
+ properties:
2920
+ apiVersion: { type: integer, const: 1 }
2921
+ eventId: { type: string, format: uuid }
2922
+ cursor: { type: integer, minimum: 1 }
2923
+ sessionId: { type: [string, 'null'] }
2924
+ threadId: { type: [string, 'null'] }
2925
+ type: { type: string, const: workspace_resource_invalidated }
2926
+ durable: { type: boolean, const: false }
2927
+ timestamp: { type: string, format: date-time }
2928
+ payload:
2929
+ type: object
2930
+ additionalProperties: false
2931
+ required: [workspaceId, resources, reason]
2932
+ properties:
2933
+ workspaceId: { type: string, format: uuid }
2934
+ resources:
2935
+ type: array
2936
+ minItems: 1
2937
+ uniqueItems: true
2938
+ items: { type: string, enum: [files, git, review] }
2939
+ reason:
2940
+ type: string
2941
+ enum: [context-change, filesystem-change, terminal-command, tool-finished]
2942
+ ComposerStateChangedEnvelope:
2943
+ type: object
2944
+ additionalProperties: false
2945
+ required:
2946
+ - apiVersion
2947
+ - eventId
2948
+ - cursor
2949
+ - sessionId
2950
+ - threadId
2951
+ - type
2952
+ - durable
2953
+ - timestamp
2954
+ - payload
2955
+ properties:
2956
+ apiVersion: { type: integer, const: 1 }
2957
+ eventId: { type: string, format: uuid }
2958
+ cursor: { type: integer, minimum: 1 }
2959
+ sessionId: { type: string, minLength: 1 }
2960
+ threadId: { type: [string, 'null'] }
2961
+ type: { type: string, const: composer_state_changed }
2962
+ durable: { type: boolean, const: true }
2963
+ timestamp: { type: string, format: date-time }
2964
+ payload:
2965
+ type: object
2966
+ additionalProperties: false
2967
+ required: [state]
2968
+ properties:
2969
+ state: { $ref: '#/components/schemas/ComposerControlState' }
2970
+ ReplayResetEnvelope:
2971
+ type: object
2972
+ additionalProperties: false
2973
+ required:
2974
+ - apiVersion
2975
+ - eventId
2976
+ - cursor
2977
+ - sessionId
2978
+ - threadId
2979
+ - type
2980
+ - durable
2981
+ - timestamp
2982
+ - payload
2983
+ properties:
2984
+ apiVersion: { type: integer, const: 1 }
2985
+ eventId: { type: string, format: uuid }
2986
+ cursor: { type: integer, minimum: 1 }
2987
+ sessionId: { type: [string, 'null'] }
2988
+ threadId: { type: [string, 'null'] }
2989
+ type: { type: string, const: replay_reset }
2990
+ durable: { type: boolean, const: true }
2991
+ timestamp: { type: string, format: date-time }
2992
+ payload:
2993
+ type: object
2994
+ additionalProperties: false
2995
+ required: [reason, snapshotRequired]
2996
+ properties:
2997
+ reason: { type: string }
2998
+ snapshotRequired: { type: boolean, const: true }
2999
+ ComposerProblemCode:
3000
+ type: string
3001
+ description: Stable RFC 9457 code family for v0.3.2 Composer and Context operations.
3002
+ enum:
3003
+ - context_revision_conflict
3004
+ - active_session_changed
3005
+ - composer_control_conflict
3006
+ - composer_recovery_required
3007
+ - composer_control_failed
3008
+ - runtime_busy
3009
+ - model_unavailable
3010
+ - model_effort_unsupported
3011
+ - model_compaction_required
3012
+ - model_switch_rolled_back
3013
+ - permission_override_rejected
3014
+ - plan_review_stale
3015
+ - plan_review_invalid
3016
+ - context_reference_stale
3017
+ - context_reference_forbidden
3018
+ - context_reference_invalid
3019
+ - queue_item_conflict
3020
+ Problem:
3021
+ type: object
3022
+ additionalProperties: false
3023
+ required: [type, title, status, code]
3024
+ properties:
3025
+ type: { type: string }
3026
+ title: { type: string }
3027
+ status: { type: integer }
3028
+ code: { type: string, minLength: 1 }
3029
+ detail: { type: string }