@huynle/hub 0.10.1 → 0.11.1
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.
- package/CHANGELOG.md +80 -0
- package/README.md +36 -8
- package/package.json +1 -1
- package/packages/claude-code/package.json +1 -1
- package/packages/claude-code/src/sessions.ts +4 -1
- package/packages/cli/dist/hub-cli.js +851 -466
- package/packages/cli/package.json +1 -1
- package/packages/cli/src/cli.ts +12 -7
- package/packages/cli/src/decisions.ts +52 -4
- package/packages/cli/src/format.ts +9 -0
- package/packages/cli/src/grants-mcp.ts +65 -0
- package/packages/cli/src/mcp-operations.ts +49 -0
- package/packages/cli/src/mcp.ts +26 -4
- package/packages/cli/src/subscriptions-mcp.ts +76 -0
- package/packages/cli/src/team-intake-mcp.ts +2 -1
- package/packages/cli/src/teams-mcp.ts +9 -3
- package/packages/codex/package.json +1 -1
- package/packages/codex/src/sessions.ts +14 -3
- package/packages/node/package.json +1 -1
- package/packages/preset/package.json +1 -1
- package/packages/protocol/package.json +1 -1
- package/packages/protocol/schema/api/v1/_root.json +119 -0
- package/packages/protocol/schema/api/v1/account.json +419 -0
- package/packages/protocol/schema/api/v1/decisions.json +635 -0
- package/packages/protocol/schema/api/v1/discovery.json +110 -0
- package/packages/protocol/schema/api/v1/events.json +679 -0
- package/packages/protocol/schema/api/v1/session-actions.json +660 -0
- package/packages/protocol/schema/api/v1/sessions.json +2055 -0
- package/packages/protocol/schema/api/v1/speech.json +492 -0
- package/packages/protocol/schema/api/v1/unspecified.json +282 -0
- package/packages/protocol/schema/app-delivery/v1.schema.json +67 -5
- package/packages/protocol/schema/app-front/v1.schema.json +7 -3
- package/packages/protocol/src/api-v1.ts +8 -0
- package/packages/protocol/src/index.ts +2 -0
- package/packages/protocol/src/teams.ts +16 -0
- package/packages/protocol/src/voice-recording.ts +39 -2
- package/packages/runtime-openshell/image/entry.sh +3 -1
- package/packages/runtime-openshell/image/start.sh +3 -1
- package/packages/runtime-openshell/package.json +1 -1
- package/packages/runtime-sdk/package.json +1 -1
- package/packages/sdk/package.json +1 -1
- package/packages/sdk/src/app-front.ts +2 -2
- package/packages/sdk/src/ask-fields.ts +76 -0
- package/packages/sdk/src/client.ts +24 -2
- package/packages/sdk/src/envelope.ts +3 -2
- package/packages/sdk/src/index.ts +1 -0
- package/packages/sdk/src/team-intake.ts +6 -0
- package/packages/sdk/src/teams.ts +4 -0
- package/packages/sdk/src/types.ts +36 -4
- package/packages/sdk/src/wake.ts +9 -4
- package/packages/spoke-sdk/package.json +1 -1
- package/src/central/agent/agent-limits.ts +185 -0
- package/src/central/agent/app-decisions.ts +6 -5
- package/src/central/agent/decisions.ts +136 -9
- package/src/central/agent/delivery.ts +164 -22
- package/src/central/agent/errors.ts +2 -1
- package/src/central/agent/events.ts +20 -2
- package/src/central/agent/grant-routes.ts +14 -1
- package/src/central/agent/grants.ts +23 -0
- package/src/central/agent/launch-engine.ts +9 -6
- package/src/central/agent/message-limits.ts +6 -0
- package/src/central/agent/message-routes.ts +33 -6
- package/src/central/agent/messages.ts +7 -0
- package/src/central/agent/placement.ts +4 -2
- package/src/central/agent/read-routes.ts +5 -0
- package/src/central/agent/routes.ts +13 -0
- package/src/central/agent/subscriptions.ts +15 -4
- package/src/central/api-v1.ts +115 -0
- package/src/central/artifacts/store.ts +4 -2
- package/src/central/concierge/board-results.ts +2 -1
- package/src/central/concierge/notifier.ts +4 -2
- package/src/central/config.ts +24 -3
- package/src/central/health/classify.ts +209 -0
- package/src/central/http.ts +380 -36
- package/src/central/recording/export.ts +57 -3
- package/src/central/recording/index.ts +236 -17
- package/src/central/recording/ingest.ts +11 -2
- package/src/central/recording/routes.ts +61 -7
- package/src/central/recording/schema.ts +68 -3
- package/src/central/recording/settings.ts +19 -5
- package/src/central/recording/store.ts +19 -0
- package/src/central/recording/taps.ts +45 -1
- package/src/central/registry.ts +34 -3
- package/src/central/speech/openai.ts +4 -4
- package/src/central/speech/openrouter.ts +4 -4
- package/src/central/speech/provider.ts +32 -1
- package/src/central/speech/service.ts +6 -5
- package/src/central/teams/budgets.ts +144 -0
- package/src/central/teams/hop-stalls.ts +80 -0
- package/src/central/teams/intake.ts +38 -6
- package/src/central/teams/involvement.ts +95 -0
- package/src/central/teams/item-decisions.ts +60 -0
- package/src/central/teams/item-eligibility.ts +35 -0
- package/src/central/teams/item-stalls.ts +87 -0
- package/src/central/teams/loops.ts +40 -0
- package/src/central/teams/policy.ts +10 -0
- package/src/central/teams/progress.ts +154 -0
- package/src/central/teams/routes.ts +2 -0
- package/src/central/teams/seats.ts +3 -3
- package/src/central/teams/staffing.ts +5 -0
- package/src/central/teams/store.ts +20 -1
- package/src/central/teams/validation.ts +16 -2
- package/src/central/workspaces/coordinator.ts +3 -1
- package/src/spoke/hub-tool.ts +26 -11
- package/web/dist/assets/{ArtifactPage-CsPjam8D.js → ArtifactPage-TbFJi59n.js} +1 -1
- package/web/dist/assets/{ArtifactPane-B9weO8L6.js → ArtifactPane-7D-M-Ich.js} +1 -1
- package/web/dist/assets/{ArtifactWorkbench-DzKhMs3l.js → ArtifactWorkbench-DlCLEjut.js} +1 -1
- package/web/dist/assets/{Diagram-CuRIffka.js → Diagram-PvOPetOI.js} +1 -1
- package/web/dist/assets/{Library-rv5DGtrm.js → Library-Cdi83pOV.js} +2 -2
- package/web/dist/assets/{ProfilesDestination-DUuQ9jmd.js → ProfilesDestination-cryC7P6j.js} +1 -1
- package/web/dist/assets/TeamsPage-B4xrlGhp.js +1 -0
- package/web/dist/assets/Watchtower-60B1JX_J.js +2 -0
- package/web/dist/assets/{artifacts-But87Jfo.js → artifacts-DlQEYmDl.js} +1 -1
- package/web/dist/assets/index-DA0gKIzv.js +33 -0
- package/web/dist/assets/{index-rW6LKQj1.css → index-Dyq-jBeE.css} +1 -1
- package/web/dist/assets/live-B2IfKm37.js +5 -0
- package/web/dist/assets/{live-BUofsQpz.css → live-De-kd3eW.css} +1 -1
- package/web/dist/assets/{pane-layout-BW0RdX5a.js → pane-layout-BAuu_pA3.js} +1 -1
- package/web/dist/assets/{renderer2d-DyANQ1WS.js → renderer2d-CsZnF3_o.js} +1 -1
- package/web/dist/assets/{renderer3d-vYYKFAJq.js → renderer3d-BIMA0wFn.js} +2 -2
- package/web/dist/assets/{safe-area-B2Bk__FK.js → safe-area-dtrnw9NF.js} +1 -1
- package/web/dist/assets/{silero-worker-e802lB5T.js → silero-worker-CC2etKS3.js} +1 -1
- package/web/dist/assets/{source-C-De8L3s.js → source-GYayxUxS.js} +1 -1
- package/web/dist/assets/{toast-CXTwTvDw.js → toast-q818mjUF.js} +1 -1
- package/web/dist/index.html +5 -5
- package/web/dist/assets/TeamsPage-D_17MkvN.js +0 -1
- package/web/dist/assets/Watchtower-DlrNOJ7X.js +0 -2
- package/web/dist/assets/index-bX8B6NLo.js +0 -33
- package/web/dist/assets/live-BGLA-peO.js +0 -5
|
@@ -0,0 +1,660 @@
|
|
|
1
|
+
{
|
|
2
|
+
"paths": {
|
|
3
|
+
"/api/v1/sessions/{session}/turn": {
|
|
4
|
+
"post": {
|
|
5
|
+
"operationId": "promptSession",
|
|
6
|
+
"tags": [
|
|
7
|
+
"session-actions"
|
|
8
|
+
],
|
|
9
|
+
"x-hub-access": "session",
|
|
10
|
+
"summary": "Prompt a session",
|
|
11
|
+
"description": "Sends typed text (and images) to the session. While anything in the session's tree runs, the prompt is steered into the running work and the answer is 202 at once with `mode: \"steer\"`. Otherwise it starts a turn, and the request waits for the turn to end and answers 200 with its result (a turn may run for minutes; this request never times out on the hub, and a stop or interrupt ends it at once as `interrupted`). With `Prefer: respond-async`, a turn still running after a short accept window (1.5 s) is answered 202 `{mode: \"turn\"}` with `Preference-Applied: respond-async`; its result then comes on the live stream as a `turn` message `{type: \"turn\", sessionID, outcome, reply, message?}` (a failure there is `outcome: \"failed\"` with the error's message, or `timeout`), while the reply streams meanwhile; a turn that ends within the window, and every refusal, answers as without the header. Fails with 400 invalid (empty prompt, text over 100,000 characters, an image that is not acceptable), 409 conflict when no process of the session is connected, 409 conflict while another turn holds the session, 409 unsupported (with `feature` and `harness`) when the session's spoke does not serve the action, 502 upstream_failed when the spoke fails the turn and 504 timeout when the hub stops waiting for it.",
|
|
12
|
+
"parameters": [
|
|
13
|
+
{
|
|
14
|
+
"name": "session",
|
|
15
|
+
"in": "path",
|
|
16
|
+
"required": true,
|
|
17
|
+
"description": "The session's ID. A session of another user, or one the hub does not know, answers 404 not_found.",
|
|
18
|
+
"schema": {
|
|
19
|
+
"type": "string"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"name": "Prefer",
|
|
24
|
+
"in": "header",
|
|
25
|
+
"required": false,
|
|
26
|
+
"description": "`respond-async`: do not wait for a long turn; answer 202 and send its result on the live stream (RFC 7240). Other preferences are ignored.",
|
|
27
|
+
"schema": {
|
|
28
|
+
"type": "string"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
],
|
|
32
|
+
"requestBody": {
|
|
33
|
+
"required": true,
|
|
34
|
+
"content": {
|
|
35
|
+
"application/json": {
|
|
36
|
+
"schema": {
|
|
37
|
+
"$ref": "#/components/schemas/TurnRequest"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"responses": {
|
|
43
|
+
"200": {
|
|
44
|
+
"description": "The turn ended: its result.",
|
|
45
|
+
"content": {
|
|
46
|
+
"application/json": {
|
|
47
|
+
"schema": {
|
|
48
|
+
"$ref": "#/components/schemas/TurnResult"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"202": {
|
|
54
|
+
"description": "Accepted, not finished: steered into the running work (`mode: \"steer\"`, without the Prefer header too), or with `Prefer: respond-async` a turn still running (`mode: \"turn\"`, its result comes on the live stream).",
|
|
55
|
+
"headers": {
|
|
56
|
+
"Preference-Applied": {
|
|
57
|
+
"description": "`respond-async` when the turn was accepted to finish in the background; absent for a steer.",
|
|
58
|
+
"schema": {
|
|
59
|
+
"type": "string"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
"content": {
|
|
64
|
+
"application/json": {
|
|
65
|
+
"schema": {
|
|
66
|
+
"$ref": "#/components/schemas/TurnAccepted"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
"default": {
|
|
72
|
+
"$ref": "#/components/responses/Error"
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
"/api/v1/sessions/{session}/interrupt": {
|
|
78
|
+
"post": {
|
|
79
|
+
"operationId": "interruptSession",
|
|
80
|
+
"tags": [
|
|
81
|
+
"session-actions"
|
|
82
|
+
],
|
|
83
|
+
"x-hub-access": "session",
|
|
84
|
+
"summary": "Interrupt a session (barge-in)",
|
|
85
|
+
"description": "Interrupts the session's current work; while a voice front is active, the front is interrupted instead (barge-in), not the session's work. A turn request in flight ends at once as `interrupted`. The request has no body. Fails with 409 conflict when no process of the session is connected, 409 unsupported (with `feature` and `harness`) when the session's spoke does not serve the action and 502 upstream_failed when the spoke fails it.",
|
|
86
|
+
"parameters": [
|
|
87
|
+
{
|
|
88
|
+
"name": "session",
|
|
89
|
+
"in": "path",
|
|
90
|
+
"required": true,
|
|
91
|
+
"description": "The session's ID. A session of another user, or one the hub does not know, answers 404 not_found.",
|
|
92
|
+
"schema": {
|
|
93
|
+
"type": "string"
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
],
|
|
97
|
+
"responses": {
|
|
98
|
+
"204": {
|
|
99
|
+
"description": "Interrupted."
|
|
100
|
+
},
|
|
101
|
+
"default": {
|
|
102
|
+
"$ref": "#/components/responses/Error"
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
"/api/v1/sessions/{session}/stop": {
|
|
108
|
+
"post": {
|
|
109
|
+
"operationId": "stopSession",
|
|
110
|
+
"tags": [
|
|
111
|
+
"session-actions"
|
|
112
|
+
],
|
|
113
|
+
"x-hub-access": "session",
|
|
114
|
+
"summary": "Stop a session and its subagents",
|
|
115
|
+
"description": "Stops the session's work and the subagent sessions it runs. A turn request in flight ends at once as `interrupted`. The request has no body. Fails with 409 conflict when no process of the session is connected, 409 unsupported (with `feature` and `harness`) when the session's spoke does not serve the action and 502 upstream_failed when the spoke fails it.",
|
|
116
|
+
"parameters": [
|
|
117
|
+
{
|
|
118
|
+
"name": "session",
|
|
119
|
+
"in": "path",
|
|
120
|
+
"required": true,
|
|
121
|
+
"description": "The session's ID. A session of another user, or one the hub does not know, answers 404 not_found.",
|
|
122
|
+
"schema": {
|
|
123
|
+
"type": "string"
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
],
|
|
127
|
+
"responses": {
|
|
128
|
+
"200": {
|
|
129
|
+
"description": "Stopped: what the spoke stopped.",
|
|
130
|
+
"content": {
|
|
131
|
+
"application/json": {
|
|
132
|
+
"schema": {
|
|
133
|
+
"$ref": "#/components/schemas/StopResult"
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
"default": {
|
|
139
|
+
"$ref": "#/components/responses/Error"
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
"/api/v1/sessions/{session}/permission": {
|
|
145
|
+
"post": {
|
|
146
|
+
"operationId": "answerPermission",
|
|
147
|
+
"tags": [
|
|
148
|
+
"session-actions"
|
|
149
|
+
],
|
|
150
|
+
"x-hub-access": "session",
|
|
151
|
+
"summary": "Answer a permission request",
|
|
152
|
+
"description": "Answers a pending permission request in the session's tree (a subagent's request is answered through its root session, the one in the path). Fails with 400 invalid for a missing request ID or an unknown decision, 409 gone when the request is not pending any more (answered elsewhere or expired), 409 unsupported (with `feature` and `harness`) when the session's spoke does not serve the action and 502 upstream_failed when the spoke fails it.",
|
|
153
|
+
"parameters": [
|
|
154
|
+
{
|
|
155
|
+
"name": "session",
|
|
156
|
+
"in": "path",
|
|
157
|
+
"required": true,
|
|
158
|
+
"description": "The session's ID. A session of another user, or one the hub does not know, answers 404 not_found.",
|
|
159
|
+
"schema": {
|
|
160
|
+
"type": "string"
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
],
|
|
164
|
+
"requestBody": {
|
|
165
|
+
"required": true,
|
|
166
|
+
"content": {
|
|
167
|
+
"application/json": {
|
|
168
|
+
"schema": {
|
|
169
|
+
"$ref": "#/components/schemas/PermissionAnswer"
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
"responses": {
|
|
175
|
+
"204": {
|
|
176
|
+
"description": "Answered."
|
|
177
|
+
},
|
|
178
|
+
"default": {
|
|
179
|
+
"$ref": "#/components/responses/Error"
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
"/api/v1/sessions/{session}/form": {
|
|
185
|
+
"post": {
|
|
186
|
+
"operationId": "answerForm",
|
|
187
|
+
"tags": [
|
|
188
|
+
"session-actions"
|
|
189
|
+
],
|
|
190
|
+
"x-hub-access": "session",
|
|
191
|
+
"summary": "Answer or cancel a form (a question)",
|
|
192
|
+
"description": "Answers a pending form of the session's tree, or cancels it: send `answer` or `cancel: true`, never both. Fails with 400 invalid (no form ID, both or neither, an answer that is not acceptable), 409 gone when the form is not pending any more, 409 unsupported (with `feature` and `harness`) when the session's spoke does not serve the action and 502 upstream_failed when the spoke fails it.",
|
|
193
|
+
"parameters": [
|
|
194
|
+
{
|
|
195
|
+
"name": "session",
|
|
196
|
+
"in": "path",
|
|
197
|
+
"required": true,
|
|
198
|
+
"description": "The session's ID. A session of another user, or one the hub does not know, answers 404 not_found.",
|
|
199
|
+
"schema": {
|
|
200
|
+
"type": "string"
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
],
|
|
204
|
+
"requestBody": {
|
|
205
|
+
"required": true,
|
|
206
|
+
"content": {
|
|
207
|
+
"application/json": {
|
|
208
|
+
"schema": {
|
|
209
|
+
"$ref": "#/components/schemas/FormSubmission"
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
},
|
|
214
|
+
"responses": {
|
|
215
|
+
"204": {
|
|
216
|
+
"description": "Answered or cancelled."
|
|
217
|
+
},
|
|
218
|
+
"default": {
|
|
219
|
+
"$ref": "#/components/responses/Error"
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
},
|
|
224
|
+
"/api/v1/sessions/{session}/expose": {
|
|
225
|
+
"post": {
|
|
226
|
+
"operationId": "exposeSession",
|
|
227
|
+
"tags": [
|
|
228
|
+
"session-actions"
|
|
229
|
+
],
|
|
230
|
+
"x-hub-access": "session",
|
|
231
|
+
"summary": "Turn Voice on or off for a session",
|
|
232
|
+
"description": "Enables or disables Voice (speech and conversation mode) for the session, through a process that reports it (its machine's background service first). Allowed while Voice is off. Fails with 400 invalid without a boolean `on`, 404 not_found when no connected process can do it, and 502 upstream_failed when the spoke fails it.",
|
|
233
|
+
"parameters": [
|
|
234
|
+
{
|
|
235
|
+
"name": "session",
|
|
236
|
+
"in": "path",
|
|
237
|
+
"required": true,
|
|
238
|
+
"description": "The session's ID. A session of another user, or one the hub does not know, answers 404 not_found.",
|
|
239
|
+
"schema": {
|
|
240
|
+
"type": "string"
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
],
|
|
244
|
+
"requestBody": {
|
|
245
|
+
"required": true,
|
|
246
|
+
"content": {
|
|
247
|
+
"application/json": {
|
|
248
|
+
"schema": {
|
|
249
|
+
"$ref": "#/components/schemas/ExposeRequest"
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
},
|
|
254
|
+
"responses": {
|
|
255
|
+
"200": {
|
|
256
|
+
"description": "Whether Voice is on now.",
|
|
257
|
+
"content": {
|
|
258
|
+
"application/json": {
|
|
259
|
+
"schema": {
|
|
260
|
+
"$ref": "#/components/schemas/ExposeResult"
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
},
|
|
265
|
+
"default": {
|
|
266
|
+
"$ref": "#/components/responses/Error"
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
},
|
|
271
|
+
"/api/v1/sessions/{session}/conversation": {
|
|
272
|
+
"post": {
|
|
273
|
+
"operationId": "setConversation",
|
|
274
|
+
"tags": [
|
|
275
|
+
"session-actions"
|
|
276
|
+
],
|
|
277
|
+
"x-hub-access": "session",
|
|
278
|
+
"summary": "Turn conversation mode on or off",
|
|
279
|
+
"description": "Conversation mode (hands-free Voice) on or off for the session. When turned on, the session's spoke may put a voice front in front of it (a separate session that talks with the user and relays to this one): it is asked for unless `front: false`. The live stream reports the change. Answers 403 not_exposed while Voice is off for the session (it is listed for discovery only; POST …/expose turns Voice on). Fails with 400 invalid (no boolean `on`, a `front` that is not a boolean), 409 conflict when no process of the session is connected and 502 upstream_failed when the spoke fails it.",
|
|
280
|
+
"parameters": [
|
|
281
|
+
{
|
|
282
|
+
"name": "session",
|
|
283
|
+
"in": "path",
|
|
284
|
+
"required": true,
|
|
285
|
+
"description": "The session's ID. A session of another user, or one the hub does not know, answers 404 not_found.",
|
|
286
|
+
"schema": {
|
|
287
|
+
"type": "string"
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
],
|
|
291
|
+
"requestBody": {
|
|
292
|
+
"required": true,
|
|
293
|
+
"content": {
|
|
294
|
+
"application/json": {
|
|
295
|
+
"schema": {
|
|
296
|
+
"$ref": "#/components/schemas/ConversationRequest"
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
},
|
|
301
|
+
"responses": {
|
|
302
|
+
"200": {
|
|
303
|
+
"description": "The mode now.",
|
|
304
|
+
"content": {
|
|
305
|
+
"application/json": {
|
|
306
|
+
"schema": {
|
|
307
|
+
"$ref": "#/components/schemas/ConversationState"
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
},
|
|
312
|
+
"default": {
|
|
313
|
+
"$ref": "#/components/responses/Error"
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
},
|
|
318
|
+
"/api/v1/sessions/{session}/utterance": {
|
|
319
|
+
"post": {
|
|
320
|
+
"operationId": "sendUtterance",
|
|
321
|
+
"tags": [
|
|
322
|
+
"session-actions"
|
|
323
|
+
],
|
|
324
|
+
"x-hub-access": "session",
|
|
325
|
+
"summary": "Say something to a session (conversation mode)",
|
|
326
|
+
"description": "Steers what the user said into the session (allowed while it is busy; while a voice front is active, to the front, which relays it) and answers at once. The utterance is tracked: when the session takes it, the live stream says so (a `heard` message with the inbox ID). Answers 403 not_exposed while Voice is off for the session (it is listed for discovery only; POST …/expose turns Voice on). Fails with 400 invalid (empty, or over 4,000 characters after trimming), 409 conflict when no process of the session is connected, 409 unsupported (with `feature` and `harness`) when the session's spoke does not serve the action and 502 upstream_failed when the spoke fails it.",
|
|
327
|
+
"parameters": [
|
|
328
|
+
{
|
|
329
|
+
"name": "session",
|
|
330
|
+
"in": "path",
|
|
331
|
+
"required": true,
|
|
332
|
+
"description": "The session's ID. A session of another user, or one the hub does not know, answers 404 not_found.",
|
|
333
|
+
"schema": {
|
|
334
|
+
"type": "string"
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
],
|
|
338
|
+
"requestBody": {
|
|
339
|
+
"required": true,
|
|
340
|
+
"content": {
|
|
341
|
+
"application/json": {
|
|
342
|
+
"schema": {
|
|
343
|
+
"$ref": "#/components/schemas/UtteranceRequest"
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
},
|
|
348
|
+
"responses": {
|
|
349
|
+
"202": {
|
|
350
|
+
"description": "Accepted: the inbox ID of the utterance.",
|
|
351
|
+
"content": {
|
|
352
|
+
"application/json": {
|
|
353
|
+
"schema": {
|
|
354
|
+
"$ref": "#/components/schemas/UtteranceAccepted"
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
},
|
|
359
|
+
"default": {
|
|
360
|
+
"$ref": "#/components/responses/Error"
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
},
|
|
365
|
+
"/api/v1/sessions/{session}/presence": {
|
|
366
|
+
"post": {
|
|
367
|
+
"operationId": "setSessionPresence",
|
|
368
|
+
"tags": [
|
|
369
|
+
"session-actions"
|
|
370
|
+
],
|
|
371
|
+
"x-hub-access": "session",
|
|
372
|
+
"summary": "Say whether this device shows the session",
|
|
373
|
+
"description": "Whether the session is on this device's screen now: while a device shows a session (or another of its tree), the hub sends no push notification for what it says. Send it when that changes and again every 30 seconds while visible; a report counts for 45 seconds. Allowed while Voice is off. Fails with 400 invalid without a boolean `visible`.",
|
|
374
|
+
"parameters": [
|
|
375
|
+
{
|
|
376
|
+
"name": "session",
|
|
377
|
+
"in": "path",
|
|
378
|
+
"required": true,
|
|
379
|
+
"description": "The session's ID. A session of another user, or one the hub does not know, answers 404 not_found.",
|
|
380
|
+
"schema": {
|
|
381
|
+
"type": "string"
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
],
|
|
385
|
+
"requestBody": {
|
|
386
|
+
"required": true,
|
|
387
|
+
"content": {
|
|
388
|
+
"application/json": {
|
|
389
|
+
"schema": {
|
|
390
|
+
"$ref": "#/components/schemas/PresenceRequest"
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
},
|
|
395
|
+
"responses": {
|
|
396
|
+
"204": {
|
|
397
|
+
"description": "Recorded."
|
|
398
|
+
},
|
|
399
|
+
"default": {
|
|
400
|
+
"$ref": "#/components/responses/Error"
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
},
|
|
406
|
+
"components": {
|
|
407
|
+
"schemas": {
|
|
408
|
+
"TurnRequest": {
|
|
409
|
+
"type": "object",
|
|
410
|
+
"required": [
|
|
411
|
+
"text"
|
|
412
|
+
],
|
|
413
|
+
"properties": {
|
|
414
|
+
"text": {
|
|
415
|
+
"type": "string",
|
|
416
|
+
"description": "The prompt, at most 100,000 characters after trimming. May be empty only when images are attached."
|
|
417
|
+
},
|
|
418
|
+
"images": {
|
|
419
|
+
"type": "array",
|
|
420
|
+
"maxItems": 4,
|
|
421
|
+
"description": "Images to attach, at most 4. An empty list is the same as none.",
|
|
422
|
+
"items": {
|
|
423
|
+
"$ref": "#/components/schemas/PromptImage"
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
},
|
|
428
|
+
"PromptImage": {
|
|
429
|
+
"type": "object",
|
|
430
|
+
"required": [
|
|
431
|
+
"mime",
|
|
432
|
+
"data"
|
|
433
|
+
],
|
|
434
|
+
"description": "An image attached to a prompt. Each at most 512 KB decoded, together at most 750,000 base64 characters; the bytes must be of the declared type.",
|
|
435
|
+
"properties": {
|
|
436
|
+
"mime": {
|
|
437
|
+
"type": "string",
|
|
438
|
+
"enum": [
|
|
439
|
+
"image/png",
|
|
440
|
+
"image/jpeg",
|
|
441
|
+
"image/webp",
|
|
442
|
+
"image/gif"
|
|
443
|
+
]
|
|
444
|
+
},
|
|
445
|
+
"data": {
|
|
446
|
+
"type": "string",
|
|
447
|
+
"description": "The image's bytes, canonical base64 (padded, no line breaks)."
|
|
448
|
+
},
|
|
449
|
+
"name": {
|
|
450
|
+
"type": "string",
|
|
451
|
+
"maxLength": 200,
|
|
452
|
+
"description": "The file name, for display."
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
},
|
|
456
|
+
"TurnResult": {
|
|
457
|
+
"type": "object",
|
|
458
|
+
"required": [
|
|
459
|
+
"outcome",
|
|
460
|
+
"reply"
|
|
461
|
+
],
|
|
462
|
+
"properties": {
|
|
463
|
+
"outcome": {
|
|
464
|
+
"type": "string",
|
|
465
|
+
"description": "succeeded; failed or interrupted (with `message`); timeout: the harness stopped waiting (the reply so far).",
|
|
466
|
+
"x-hub-known": [
|
|
467
|
+
"succeeded",
|
|
468
|
+
"failed",
|
|
469
|
+
"interrupted",
|
|
470
|
+
"timeout"
|
|
471
|
+
]
|
|
472
|
+
},
|
|
473
|
+
"reply": {
|
|
474
|
+
"type": "string",
|
|
475
|
+
"description": "The turn's reply text, possibly partial or empty."
|
|
476
|
+
},
|
|
477
|
+
"message": {
|
|
478
|
+
"type": "string",
|
|
479
|
+
"description": "Why it failed or was interrupted (\"Stopped\" for a stop or interrupt through the hub)."
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
},
|
|
483
|
+
"TurnAccepted": {
|
|
484
|
+
"type": "object",
|
|
485
|
+
"required": [
|
|
486
|
+
"mode"
|
|
487
|
+
],
|
|
488
|
+
"properties": {
|
|
489
|
+
"mode": {
|
|
490
|
+
"type": "string",
|
|
491
|
+
"description": "steer: the prompt went into the running work (`inboxID`). turn: a new turn runs in the background (Prefer: respond-async); its result comes on the live stream.",
|
|
492
|
+
"x-hub-known": [
|
|
493
|
+
"steer",
|
|
494
|
+
"turn"
|
|
495
|
+
]
|
|
496
|
+
},
|
|
497
|
+
"inboxID": {
|
|
498
|
+
"type": "string",
|
|
499
|
+
"description": "steer: the steered input's ID."
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
},
|
|
503
|
+
"StopResult": {
|
|
504
|
+
"type": "object",
|
|
505
|
+
"required": [
|
|
506
|
+
"stopped"
|
|
507
|
+
],
|
|
508
|
+
"properties": {
|
|
509
|
+
"stopped": {
|
|
510
|
+
"type": "array",
|
|
511
|
+
"description": "The IDs of the sessions stopped (the session and its subagents).",
|
|
512
|
+
"items": {
|
|
513
|
+
"type": "string"
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
},
|
|
518
|
+
"PermissionAnswer": {
|
|
519
|
+
"type": "object",
|
|
520
|
+
"required": [
|
|
521
|
+
"requestID",
|
|
522
|
+
"decision"
|
|
523
|
+
],
|
|
524
|
+
"properties": {
|
|
525
|
+
"requestID": {
|
|
526
|
+
"type": "string",
|
|
527
|
+
"description": "The permission blocker's ID."
|
|
528
|
+
},
|
|
529
|
+
"decision": {
|
|
530
|
+
"type": "string",
|
|
531
|
+
"enum": [
|
|
532
|
+
"once",
|
|
533
|
+
"always",
|
|
534
|
+
"reject"
|
|
535
|
+
],
|
|
536
|
+
"description": "once: allow this time. always: allow this and the same kind of request from now on. reject: refuse."
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
},
|
|
540
|
+
"FormSubmission": {
|
|
541
|
+
"type": "object",
|
|
542
|
+
"required": [
|
|
543
|
+
"formID"
|
|
544
|
+
],
|
|
545
|
+
"properties": {
|
|
546
|
+
"formID": {
|
|
547
|
+
"type": "string",
|
|
548
|
+
"maxLength": 300,
|
|
549
|
+
"description": "The form blocker's ID, 1 to 300 characters."
|
|
550
|
+
},
|
|
551
|
+
"answer": {
|
|
552
|
+
"type": "object",
|
|
553
|
+
"maxProperties": 50,
|
|
554
|
+
"description": "Field key (1 to 300 characters) → value, at most 50 fields. A value by the field's type: string → text, number and integer → a number, boolean → true or false, multiselect → a list of texts (at most 100); external fields take no value. Texts at most 20,000 characters each. Anything else (an object, null) is refused. Required unless `cancel` is true.",
|
|
555
|
+
"additionalProperties": {
|
|
556
|
+
"$ref": "#/components/schemas/JsonValue"
|
|
557
|
+
}
|
|
558
|
+
},
|
|
559
|
+
"cancel": {
|
|
560
|
+
"type": "boolean",
|
|
561
|
+
"description": "true: dismiss the form instead of answering it (send no `answer`)."
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
},
|
|
565
|
+
"ExposeRequest": {
|
|
566
|
+
"type": "object",
|
|
567
|
+
"required": [
|
|
568
|
+
"on"
|
|
569
|
+
],
|
|
570
|
+
"properties": {
|
|
571
|
+
"on": {
|
|
572
|
+
"type": "boolean"
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
},
|
|
576
|
+
"ExposeResult": {
|
|
577
|
+
"type": "object",
|
|
578
|
+
"required": [
|
|
579
|
+
"exposed"
|
|
580
|
+
],
|
|
581
|
+
"properties": {
|
|
582
|
+
"exposed": {
|
|
583
|
+
"type": "boolean",
|
|
584
|
+
"description": "Whether Voice is on for the session now."
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
},
|
|
588
|
+
"ConversationRequest": {
|
|
589
|
+
"type": "object",
|
|
590
|
+
"required": [
|
|
591
|
+
"on"
|
|
592
|
+
],
|
|
593
|
+
"properties": {
|
|
594
|
+
"on": {
|
|
595
|
+
"type": "boolean"
|
|
596
|
+
},
|
|
597
|
+
"front": {
|
|
598
|
+
"type": "boolean",
|
|
599
|
+
"description": "false: no voice front (this device opted out). Absent or true: a front when the session's spoke serves one."
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
},
|
|
603
|
+
"ConversationState": {
|
|
604
|
+
"type": "object",
|
|
605
|
+
"required": [
|
|
606
|
+
"on"
|
|
607
|
+
],
|
|
608
|
+
"properties": {
|
|
609
|
+
"on": {
|
|
610
|
+
"type": "boolean"
|
|
611
|
+
},
|
|
612
|
+
"agent": {
|
|
613
|
+
"type": "string",
|
|
614
|
+
"description": "The session's agent, as its spoke reports it."
|
|
615
|
+
},
|
|
616
|
+
"front": {
|
|
617
|
+
"type": "boolean",
|
|
618
|
+
"description": "Whether a voice front is in front of the session now. Present when a front was asked for, and when turning off a session that had one."
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
},
|
|
622
|
+
"UtteranceRequest": {
|
|
623
|
+
"type": "object",
|
|
624
|
+
"required": [
|
|
625
|
+
"text"
|
|
626
|
+
],
|
|
627
|
+
"properties": {
|
|
628
|
+
"text": {
|
|
629
|
+
"type": "string",
|
|
630
|
+
"description": "What the user said, at most 4,000 characters after trimming."
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
},
|
|
634
|
+
"UtteranceAccepted": {
|
|
635
|
+
"type": "object",
|
|
636
|
+
"required": [
|
|
637
|
+
"inboxID"
|
|
638
|
+
],
|
|
639
|
+
"properties": {
|
|
640
|
+
"inboxID": {
|
|
641
|
+
"type": "string",
|
|
642
|
+
"description": "The utterance's inbox ID, as the live stream's `heard` message names it."
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
},
|
|
646
|
+
"PresenceRequest": {
|
|
647
|
+
"type": "object",
|
|
648
|
+
"required": [
|
|
649
|
+
"visible"
|
|
650
|
+
],
|
|
651
|
+
"properties": {
|
|
652
|
+
"visible": {
|
|
653
|
+
"type": "boolean",
|
|
654
|
+
"description": "Whether this device shows the session now."
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
}
|