@maudecode/talaria-web-contracts 1.17.2 → 1.19.0
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/dist/gateway-session.d.ts +229 -0
- package/dist/gateway-session.js +46 -0
- package/dist/gateway-session.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/openapi.js +9 -1
- package/dist/openapi.js.map +1 -1
- package/dist/router.d.ts +8256 -1763
- package/dist/routes/automation.d.ts +130 -25
- package/dist/routes/automation.js +8 -4
- package/dist/routes/automation.js.map +1 -1
- package/dist/routes/chat.d.ts +2484 -41
- package/dist/routes/chat.js +10 -4
- package/dist/routes/chat.js.map +1 -1
- package/dist/routes/core.d.ts +28 -6
- package/dist/routes/core.js +5 -2
- package/dist/routes/core.js.map +1 -1
- package/dist/routes/git.d.ts +76 -1
- package/dist/routes/git.js +13 -3
- package/dist/routes/git.js.map +1 -1
- package/dist/routes/raw.d.ts +3 -1
- package/dist/routes/raw.js +30 -6
- package/dist/routes/raw.js.map +1 -1
- package/dist/routes/sessions.d.ts +5181 -744
- package/dist/routes/sessions.js +76 -8
- package/dist/routes/sessions.js.map +1 -1
- package/dist/routes/settings.d.ts +457 -8
- package/dist/routes/settings.js +2 -2
- package/dist/routes/settings.js.map +1 -1
- package/dist/routes/tools.d.ts +1001 -33
- package/dist/routes/tools.js +82 -6
- package/dist/routes/tools.js.map +1 -1
- package/dist/routes/workspaces.d.ts +82 -0
- package/dist/routes/workspaces.js +18 -1
- package/dist/routes/workspaces.js.map +1 -1
- package/dist/run-status.d.ts +39 -0
- package/dist/run-status.js +13 -0
- package/dist/run-status.js.map +1 -0
- package/dist/sidecar/methods.d.ts +1299 -109
- package/dist/sidecar/methods.js +10 -2
- package/dist/sidecar/methods.js.map +1 -1
- package/dist/sidecar/namespaces.d.ts +1736 -123
- package/dist/sidecar/namespaces.js +332 -32
- package/dist/sidecar/namespaces.js.map +1 -1
- package/dist/sidecar/runtime.d.ts +61 -0
- package/dist/sidecar/runtime.js +20 -0
- package/dist/sidecar/runtime.js.map +1 -1
- package/dist/sidecar/version.d.ts +1 -1
- package/dist/sidecar/version.js +1 -1
- package/dist/speed.d.ts +14 -0
- package/dist/speed.js +6 -0
- package/dist/speed.js.map +1 -0
- package/dist/sse.d.ts +833 -14
- package/dist/sse.js +25 -9
- package/dist/sse.js.map +1 -1
- package/dist/theme.d.ts +10 -0
- package/dist/theme.js +10 -0
- package/dist/theme.js.map +1 -0
- package/dist/transcribe-stream.d.ts +34 -0
- package/dist/transcribe-stream.js +23 -0
- package/dist/transcribe-stream.js.map +1 -0
- package/dist/views.d.ts +2900 -159
- package/dist/views.js +380 -55
- package/dist/views.js.map +1 -1
- package/fixtures/sidecar/aux.json +134 -0
- package/fixtures/sidecar/chat.json +14 -0
- package/fixtures/sidecar/checkpoints.json +50 -0
- package/fixtures/sidecar/commands.json +258 -99
- package/fixtures/sidecar/config.json +15 -0
- package/fixtures/sidecar/connectors.json +218 -0
- package/fixtures/sidecar/cron.json +1008 -55
- package/fixtures/sidecar/gateway.json +39 -0
- package/fixtures/sidecar/goals.json +10 -8
- package/fixtures/sidecar/kanban.json +181 -90
- package/fixtures/sidecar/memory.json +50 -0
- package/fixtures/sidecar/models.json +122 -0
- package/fixtures/sidecar/personalities.json +92 -0
- package/fixtures/sidecar/plugins.json +262 -174
- package/fixtures/sidecar/process.json +31 -0
- package/fixtures/sidecar/profiles.json +12 -2
- package/fixtures/sidecar/providers.json +39 -13
- package/fixtures/sidecar/rpc.json +50 -1
- package/fixtures/sidecar/runtime.json +131 -22
- package/fixtures/sidecar/skills.json +256 -13
- package/fixtures/sidecar/state_db.json +34 -2
- package/fixtures/sidecar/stt.json +62 -1
- package/fixtures/sidecar/text.json +20 -2
- package/fixtures/sidecar/toolsets.json +468 -0
- package/fixtures/sidecar/usage.json +24 -4
- package/fixtures/sidecar/write_approval.json +98 -0
- package/package.json +1 -1
package/dist/views.js
CHANGED
|
@@ -5,6 +5,12 @@
|
|
|
5
5
|
* that must survive a round trip (documented passthrough).
|
|
6
6
|
*/
|
|
7
7
|
import { z } from 'zod';
|
|
8
|
+
import { RunStatusSchema } from './run-status.js';
|
|
9
|
+
import { AgentRefreshConfirmationSchema } from './sidecar/runtime.js';
|
|
10
|
+
import { SpeedTierSchema } from './speed.js';
|
|
11
|
+
import { OwnerAttachmentSchema } from './gateway-session.js';
|
|
12
|
+
import { CanonicalBotChatSchema, GatewayModeSchema, PluginSettingFieldSchema, SkillCatalogIdentitySchema } from './sidecar/namespaces.js';
|
|
13
|
+
export { SpeedTierSchema } from './speed.js';
|
|
8
14
|
const Json = z.unknown();
|
|
9
15
|
export const NullableString = z.string().nullable();
|
|
10
16
|
export const NullableNumber = z.number().nullable();
|
|
@@ -17,12 +23,26 @@ export const AttachmentSchema = z.looseObject({
|
|
|
17
23
|
});
|
|
18
24
|
/** The server's display class for a tool call: clients map it to an icon and localized verb, and never classify names themselves. */
|
|
19
25
|
export const ToolKindSchema = z.enum(['shell', 'read', 'list', 'search', 'web', 'write', 'skill', 'memory', 'delegate', 'unknown']);
|
|
26
|
+
/**
|
|
27
|
+
* TAL-604: one row of a unified diff hunk as the server parsed it. `text` is the raw line, its `+` / `-` / space prefix kept;
|
|
28
|
+
* `old_line` / `new_line` number it on each side (null on the side it is absent from, and on a `\ No newline` marker).
|
|
29
|
+
*/
|
|
30
|
+
export const DiffLineSchema = z.object({ kind: z.enum(['addition', 'deletion', 'context']), old_line: z.number().int().nullable(), new_line: z.number().int().nullable(), text: z.string() });
|
|
31
|
+
/**
|
|
32
|
+
* TAL-604: one hunk of a unified diff: its `@@` `header`, the first old and new line numbers, the last new line it covers
|
|
33
|
+
* (`new_end`, at least `new_start`), its added and removed line counts, and its lines. A diff without `@@` headers yields
|
|
34
|
+
* one hunk per file with an empty `header` and null numbers.
|
|
35
|
+
*/
|
|
36
|
+
export const DiffHunkSchema = z.object({
|
|
37
|
+
header: z.string(), old_start: z.number().int().nullable(), new_start: z.number().int().nullable(), new_end: z.number().int().nullable(),
|
|
38
|
+
additions: z.number().int(), deletions: z.number().int(), lines: z.array(DiffLineSchema),
|
|
39
|
+
});
|
|
20
40
|
/**
|
|
21
41
|
* TAL-448: a completed file-edit call's change, from its result's unified diff: `added` / `removed` count the whole diff's
|
|
22
|
-
* lines (file headers excluded); `diff` is the redacted diff, capped at 400 lines, with `truncated` when cut
|
|
23
|
-
* call whose result has no diff.
|
|
42
|
+
* lines (file headers excluded); `diff` is the redacted diff, capped at 400 lines, with `truncated` when cut, and `hunks`
|
|
43
|
+
* that diff parsed (TAL-604). Absent on a call whose result has no diff.
|
|
24
44
|
*/
|
|
25
|
-
export const ToolEditDiffSchema = z.object({ added: z.number().int(), removed: z.number().int(), diff: z.string(), truncated: z.boolean() });
|
|
45
|
+
export const ToolEditDiffSchema = z.object({ added: z.number().int(), removed: z.number().int(), diff: z.string(), truncated: z.boolean(), hunks: z.array(DiffHunkSchema) });
|
|
26
46
|
/** Server-derived display fields every tool call carries: the kind, and the redacted first-line label of its main argument (`''` when none; omitted on a live frame with none, which keeps its start frame's target), and a file edit's `edit_diff`. */
|
|
27
47
|
export const ToolDisplayFields = { kind: ToolKindSchema.optional(), target: z.string().optional(), edit_diff: ToolEditDiffSchema.optional() };
|
|
28
48
|
/**
|
|
@@ -85,8 +105,8 @@ export const TurnFileChangeSchema = z.looseObject({ path: z.string(), action: z.
|
|
|
85
105
|
export const TurnTerminalStateSchema = z.enum(['completed', 'no_response', 'cancelled', 'interrupted', 'tool_limit_reached', 'compression_exhausted', 'error']);
|
|
86
106
|
export const ActivitySceneSchema = z.looseObject({
|
|
87
107
|
version: z.literal('activity_scene_v1'), activity_rows: z.array(ActivitySceneRowSchema), final_answer: z.string().optional(),
|
|
88
|
-
/** TAL-456:
|
|
89
|
-
final_answer_excerpt: z.string().optional(), turn_duration: z.number().nullable().optional(),
|
|
108
|
+
/** TAL-456: an older settled final answer too long to lay out whole. Absent on the session-global newest settled visible reply and throughout the next running turn. Clients render the excerpt with a local "Show more". */
|
|
109
|
+
final_answer_excerpt: z.string().optional().describe("Collapsed preview of an older settled final answer. Absent on the session-global newest visible reply; its exemption transfers only when a newer visible reply settles."), turn_duration: z.number().nullable().optional(),
|
|
90
110
|
/** TAL-186: `final_answer` with its media references rewritten for display (see `_display_content`), and its media. */
|
|
91
111
|
final_answer_display: z.string().optional(), final_answer_media: z.array(DisplayMediaSchema).optional(),
|
|
92
112
|
terminal_state: z.string().optional().describe('The turn\'s outcome: a `TurnTerminalState` (`completed`, `no_response`, `error`, `cancelled`, `interrupted`, `tool_limit_reached`, ...), or `running` for the running turn of a run with no journal to replay (TAL-374). A running scene holds every persisted row (no final answer) and renders open, with no "Worked" fold or outcome; the live rows streamed after attach continue it, and the settled scene replaces both.'),
|
|
@@ -100,8 +120,13 @@ export const ActivitySceneSchema = z.looseObject({
|
|
|
100
120
|
file_changes: z.array(TurnFileChangeSchema).optional(),
|
|
101
121
|
activity_rows_total: z.number().int().optional(), activity_rows_offset: z.number().int().optional(), activity_rows_complete: z.boolean().optional(), activity_rows_omitted: z.number().int().optional(), activity_scene_ref: z.string().optional(),
|
|
102
122
|
});
|
|
103
|
-
/**
|
|
104
|
-
export const
|
|
123
|
+
/** The server-owned result-review lifecycle (TAL-1022). */
|
|
124
|
+
export const BackgroundReviewStateSchema = z.enum(['waiting', 'reviewing', 'reviewed', 'failed', 'unknown']);
|
|
125
|
+
/** One finished background item (see `_background_update.lines`). */
|
|
126
|
+
export const BackgroundLineSchema = z.object({ kind: z.enum(['agent', 'command', 'other']), status: z.enum(['completed', 'failed', 'notice']), label: z.string(), exit_code: z.number().int().nullable().optional(),
|
|
127
|
+
/** Server-composed worker and parent outcome. Failure/unknown worker outcomes take precedence. */
|
|
128
|
+
review_state: BackgroundReviewStateSchema.optional(),
|
|
129
|
+
});
|
|
105
130
|
export const MessageSchema = z.looseObject({
|
|
106
131
|
role: z.string(), content: MessageContentSchema.optional(), id: MessageIdSchema.optional(), message_id: MessageIdSchema.optional(), timestamp: z.number().nullable().optional(),
|
|
107
132
|
attachments: z.array(AttachmentSchema).optional(), tool_calls: z.array(ToolCallSchema).optional(),
|
|
@@ -115,15 +140,23 @@ export const MessageSchema = z.looseObject({
|
|
|
115
140
|
provider_details: Json.optional(), provider_details_label: z.string().optional(), recovery_control: Json.optional(), _anchor_activity_scene: ActivitySceneSchema.optional(),
|
|
116
141
|
/** The turn this row belongs to; the server stamps every row it sends, so clients group turns by equality alone. */
|
|
117
142
|
_turn_id: z.string().optional(),
|
|
143
|
+
/** On a turn's last assistant row: seconds the turn ran. */
|
|
144
|
+
_turnDuration: z.number().optional(),
|
|
145
|
+
/** On a turn's last assistant row: output tokens per second, when the turn reported usage. */
|
|
146
|
+
_turnTps: z.number().optional(),
|
|
147
|
+
/** Epoch seconds the row was written; `timestamp` when absent. */
|
|
148
|
+
_ts: z.number().optional(),
|
|
149
|
+
/** Reasoning titles an older Web stored on the row, in order. */
|
|
150
|
+
reasoning_titles: z.array(z.string()).optional(),
|
|
118
151
|
/** The running turn's prompt, which the turn's settlement replaces with its persisted row. */
|
|
119
152
|
_active_turn_user: z.boolean().optional(),
|
|
120
153
|
/** A consumed steer at its causal place in the turn: display-only, never model history. A steer only the Agent recorded has no timing. */
|
|
121
154
|
_steer: z.looseObject({ steer_id: z.string(), submitted_at: z.number().nullable().optional(), consumed_at: z.number().optional(), phase_duration: z.number().optional() }).optional(),
|
|
122
155
|
/** On a steered turn's last reply: seconds from the last consumed steer to the turn's end. */
|
|
123
156
|
_final_phase_duration: z.number().optional(),
|
|
124
|
-
/** A settled body too long to lay out whole
|
|
125
|
-
_display_truncated: z.boolean().optional(),
|
|
126
|
-
_display_excerpt: z.string().optional(),
|
|
157
|
+
/** A settled body too long to lay out whole. The session-global newest settled visible assistant reply and running output carry no excerpt. Only a newer visible terminal answer transfers that exemption. Clients render `_display_excerpt` with a local "Show more" for full `content`. */
|
|
158
|
+
_display_truncated: z.boolean().optional().describe("Whether this settled body has a collapsed preview. The newest settled visible assistant reply and active-turn output remain full."),
|
|
159
|
+
_display_excerpt: z.string().optional().describe("Collapsed preview with full content retained. The newest settled visible assistant reply remains exempt throughout the next running turn, until a newer visible reply settles."),
|
|
127
160
|
/**
|
|
128
161
|
* TAL-452: a typed user message (never a steer, background update or marker) longer than 20 lines or 2,000
|
|
129
162
|
* characters. Clients show it folded to a few lines with a local "Show more"; copy and edit use the whole `content`.
|
|
@@ -145,11 +178,13 @@ export const MessageSchema = z.looseObject({
|
|
|
145
178
|
_background_update: z.object({
|
|
146
179
|
kind: z.enum(['delegation', 'process', 'mixed', 'other']), attention: z.boolean(), count: z.number().int().positive(), summary: z.string(),
|
|
147
180
|
/**
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
* `
|
|
181
|
+
* One completion line per finished item. Clients show its label and exactly one leading icon from `review_state`,
|
|
182
|
+
* with localized accessible/help wording. Parent review never overrides failed/unknown worker outcomes.
|
|
183
|
+
* `content` stays available in full on expansion.
|
|
151
184
|
*/
|
|
152
185
|
lines: z.array(BackgroundLineSchema),
|
|
186
|
+
/** Parent review only, established from admission, the live run, and terminal evidence. */
|
|
187
|
+
review_state: BackgroundReviewStateSchema.optional(),
|
|
153
188
|
}).optional(),
|
|
154
189
|
/**
|
|
155
190
|
* TAL-305: a marker the Agent wrote around context compaction, not a message anyone typed. Clients render a collapsed
|
|
@@ -158,10 +193,29 @@ export const MessageSchema = z.looseObject({
|
|
|
158
193
|
_marker_kind: z.enum(['context_compaction', 'preserved_task_list']).optional(),
|
|
159
194
|
/** TAL-305: a preserved task list's card body, without its marker line. */
|
|
160
195
|
_marker_body: z.string().optional(),
|
|
196
|
+
/**
|
|
197
|
+
* TAL-815: an assistant row the Agent wrote as a notice, not the model's reply. `failed_turn`: the boundary closing a
|
|
198
|
+
* turn that failed, with its copy in `content`. Clients show it as a notice in its place, never as a reply bubble or
|
|
199
|
+
* part of a turn's reply; it is absent when Web's own error row already reports that turn. `session_finalize` is
|
|
200
|
+
* a plugin's closing text after clear, with role `local_notice`, display-only and excluded from model history.
|
|
201
|
+
*/
|
|
202
|
+
_notice_kind: z.enum(['failed_turn', 'session_finalize']).optional(),
|
|
203
|
+
/**
|
|
204
|
+
* TAL-816: a user row of a messaging session that the Agent's gateway mirrored after a webhook route's or cron job's
|
|
205
|
+
* delivery to the chat, not a message the user sent. Clients show it as a delivery notice titled by a localized label
|
|
206
|
+
* per `kind` with `name`, and `body` (the delivered text, without its label line) beneath, never as a user bubble.
|
|
207
|
+
*/
|
|
208
|
+
_delivery: z.object({ kind: z.enum(['webhook', 'cron']), name: z.string(), body: z.string() }).optional(),
|
|
161
209
|
/** TAL-460: part of the Agent's reply to the background update just before it in the same turn. */
|
|
162
210
|
_background_reply: z.boolean().optional(),
|
|
163
211
|
/** TAL-460: that reply is only a silence marker; clients show the update's lines and nothing of this turn's reply. */
|
|
164
212
|
_background_silent: z.boolean().optional(),
|
|
213
|
+
/**
|
|
214
|
+
* TAL-600: how clients show the row, on every row the server sends: `row` on its own, `in_scene` only inside its turn's
|
|
215
|
+
* activity scene (a tool result or a consumed steer), `hidden` not at all (a silent background reply, or a row with
|
|
216
|
+
* nothing to show).
|
|
217
|
+
*/
|
|
218
|
+
_display: z.enum(['row', 'hidden', 'in_scene']).optional(),
|
|
165
219
|
});
|
|
166
220
|
export const ComposerDraftSchema = z.looseObject({ text: z.string().optional(), files: z.array(Json).optional() });
|
|
167
221
|
/**
|
|
@@ -172,6 +226,23 @@ export const PendingSteerSchema = z.object({
|
|
|
172
226
|
steer_id: z.string(), text: z.string(), submitted_at: z.number(), state: z.enum(['pending', 'sending_now']),
|
|
173
227
|
actions: z.object({ edit: z.boolean(), cancel: z.boolean(), send_now: z.boolean() }),
|
|
174
228
|
});
|
|
229
|
+
/**
|
|
230
|
+
* TAL-803: an out-of-band notice the Agent raised for the session (a memory provider that failed to load, credit and
|
|
231
|
+
* usage warnings), one per `key`. The server keeps it until the Agent clears that key, `expires_at` passes, or a new agent
|
|
232
|
+
* replaces the one that raised it.
|
|
233
|
+
*/
|
|
234
|
+
export const SessionNoticeSchema = z.object({
|
|
235
|
+
key: z.string(), level: z.enum(['info', 'warn', 'error', 'success']), text: z.string(),
|
|
236
|
+
expires_at: NullableNumber.describe('Unix seconds when the server drops it; null when only the Agent clears it.'),
|
|
237
|
+
});
|
|
238
|
+
/**
|
|
239
|
+
* TAL-808: the session's standing `/goal` while it runs, from the Agent's goal state. `parked` is an active goal waiting on
|
|
240
|
+
* a process or a timer; `reason` is why it is paused or what it waits on. A done, cleared or absent goal is null.
|
|
241
|
+
*/
|
|
242
|
+
export const SessionGoalSchema = z.object({
|
|
243
|
+
text: z.string(), status: z.enum(['active', 'paused', 'parked']), turns_used: z.number().int().nonnegative(), max_turns: z.number().int().nonnegative(),
|
|
244
|
+
reason: NullableString, parked_until: NullableNumber.describe('Unix seconds a timed park ends; null otherwise.'),
|
|
245
|
+
});
|
|
175
246
|
/**
|
|
176
247
|
* TAL-299: the context ring, computed by the server. `context_used_tokens` is the post-compression estimate, else the last
|
|
177
248
|
* prompt (never the cumulative `input_tokens`); `context_window_tokens` is the model's window. The percents are rounded
|
|
@@ -186,12 +257,13 @@ export const ContextUsageFields = {
|
|
|
186
257
|
const ActiveTurnOriginSchema = z.enum(['user', 'background']).nullable().optional().describe('Who started the running turn; null while idle.');
|
|
187
258
|
const IsStreamingSchema = z.boolean().describe('True only while the session\'s run is a live stream on this server.');
|
|
188
259
|
const ActiveStreamIdSchema = NullableString.optional().describe('The live stream id; non-null only while `is_streaming` is true.');
|
|
260
|
+
const ReadOnlyReasonSchema = NullableString.optional().describe('Server-owned reason this session is display-only or its ownership cannot be verified.');
|
|
189
261
|
const ReadOnlySchema = z.boolean().describe('The session cannot be modified from Web: a read-only import, a view-only subagent child, or a foreign session whose owner refuses claiming.');
|
|
190
|
-
const CanBranchSchema = z.boolean().describe('Web may branch this session: never a subagent child
|
|
191
|
-
const CanPinSchema = z.boolean().describe('Web may pin or unpin this session: never a subagent child.');
|
|
192
|
-
const CanArchiveSchema = z.boolean().describe('Web may archive or unarchive this session: never a subagent child.');
|
|
262
|
+
const CanBranchSchema = z.boolean().describe('Web may branch this session: never a subagent child or an ownership-locked session; other read-only sessions only when they are cron runs.');
|
|
263
|
+
const CanPinSchema = z.boolean().describe('Web may pin or unpin this session: never a subagent child or a session locked by canonical ownership or unreadable ownership storage.');
|
|
264
|
+
const CanArchiveSchema = z.boolean().describe('Web may archive or unarchive this session: never a subagent child or a session locked by canonical ownership or unreadable ownership storage.');
|
|
193
265
|
const CanDeleteSchema = z.boolean().describe('Web may delete this session: never a read-only session (a read-only import, a view-only subagent child, or a foreign session whose owner refuses claiming).');
|
|
194
|
-
const CanDuplicateSchema = z.boolean().describe('Web may duplicate this session: it has a WebUI copy
|
|
266
|
+
const CanDuplicateSchema = z.boolean().describe('Web may duplicate this session: it has a WebUI copy, is not a subagent child, and is not locked by canonical ownership or unreadable ownership storage.');
|
|
195
267
|
// TAL-310: the server classifies every session's source once; clients file rows by it and never scan source markers.
|
|
196
268
|
export const SourceKindSchema = z.enum(['webui', 'cli', 'messaging', 'cron', 'webhook', 'subagent', 'claude_code', 'kanban', 'api', 'other'])
|
|
197
269
|
.describe('The session\'s source family. `is_cli_session` is true only for `cli` and `claude_code`.');
|
|
@@ -212,17 +284,27 @@ export const CompressionReferenceSchema = z.object({
|
|
|
212
284
|
text: z.string(),
|
|
213
285
|
after_message_index: z.number().int().nonnegative().nullable().describe('The full-transcript index of the row the card follows; null puts it above the transcript.'),
|
|
214
286
|
});
|
|
287
|
+
/** TAL-454: the chat a `/branch` copied, with its redacted title. */
|
|
288
|
+
export const BranchedFromSchema = z.object({ session_id: SessionIdSchema, title: z.string() });
|
|
215
289
|
/** Full session record from `GET /api/session` and mutations returning `session`. */
|
|
216
290
|
export const SessionSchema = z.looseObject({
|
|
291
|
+
composer_state_key: z.string().optional().describe('Opaque profile-home and owner identity for device-local composer state; never an API session id.'),
|
|
217
292
|
session_id: SessionIdSchema, title: z.string(), workspace: z.string().optional(), created_workspace: z.string().nullable().optional(), model: NullableString.optional(), model_provider: NullableString.optional(),
|
|
218
293
|
model_option_id: NullableString.optional().describe('TAL-301: the catalog entry id the stored model/provider selects; null when none.'),
|
|
219
294
|
messages: z.array(MessageSchema).optional(), tool_calls: z.array(ToolCallSchema).optional(), created_at: UnixSeconds.optional(), updated_at: UnixSeconds.optional(), last_message_at: NullableNumber.optional(),
|
|
220
295
|
message_count: z.number().optional(), user_message_count: z.number().optional(), pinned: z.boolean().optional(), archived: z.boolean().optional(), project_id: NullableString.optional(), profile: NullableString.optional(),
|
|
221
296
|
personality: NullableString.optional(), input_tokens: z.number().optional(), output_tokens: z.number().optional(), cache_read_tokens: z.number().optional(), cache_write_tokens: z.number().optional(),
|
|
222
|
-
cache_hit_percent: NullableNumber.optional(), estimated_cost: NullableNumber.optional(), active_stream_id: ActiveStreamIdSchema, is_streaming: IsStreamingSchema, active_turn_origin: ActiveTurnOriginSchema, pending_steers: z.array(PendingSteerSchema).optional().describe('TAL-424: the active stream\'s pending steers, oldest first.'),
|
|
297
|
+
cache_hit_percent: NullableNumber.optional(), estimated_cost: NullableNumber.optional(), active_stream_id: ActiveStreamIdSchema, is_streaming: IsStreamingSchema, active_turn_origin: ActiveTurnOriginSchema, pending_steers: z.array(PendingSteerSchema).optional().describe('TAL-424: the active stream\'s pending steers, oldest first.'),
|
|
298
|
+
run_status: RunStatusSchema.nullable().optional().describe('Current server-selected run presentation; null when no turn runs. Older servers omit it.'),
|
|
299
|
+
compression_started_at: NullableNumber.optional().describe('TAL-1006: when the compression clients show started (epoch seconds): the running manual job\'s, else the live run\'s open span; null when none runs.'),
|
|
300
|
+
notices: z.array(SessionNoticeSchema).optional().describe('TAL-803: the Agent\'s active notices for the session, oldest first.'),
|
|
301
|
+
goal: SessionGoalSchema.nullable().optional().describe('TAL-808: the standing /goal; null when none runs.'),
|
|
302
|
+
automatic_turns_held: z.boolean().optional().describe('TAL-899: the user pressed Stop, so no automatic turn (background wakeup or goal continuation) starts until their next message.'), has_pending_user_message: z.boolean().optional(),
|
|
223
303
|
pending_user_message: NullableString.optional(), pending_attachments: z.array(AttachmentSchema).optional(), pending_started_at: NullableNumber.optional(), pending_user_source: NullableString.optional(),
|
|
224
304
|
context_length: NullableNumber.optional(), threshold_tokens: NullableNumber.optional(), last_prompt_tokens: NullableNumber.optional(), post_compression_context_tokens_estimate: NullableNumber.optional(), ...ContextUsageFields,
|
|
225
|
-
enabled_toolsets: z.array(z.string()).nullable().optional(), composer_draft: ComposerDraftSchema.optional(), is_cli_session: z.boolean().optional(), source_kind: SourceKindSchema, is_messaging_session: IsMessagingSessionSchema, sort_ts: SortTsSchema, read_only: ReadOnlySchema, can_branch: CanBranchSchema, can_pin: CanPinSchema, can_archive: CanArchiveSchema, can_delete: CanDeleteSchema, can_duplicate: CanDuplicateSchema, source_tag: NullableString.optional(),
|
|
305
|
+
enabled_toolsets: z.array(z.string()).nullable().optional(), composer_draft: ComposerDraftSchema.optional(), is_cli_session: z.boolean().optional(), source_kind: SourceKindSchema, is_messaging_session: IsMessagingSessionSchema, sort_ts: SortTsSchema, read_only: ReadOnlySchema, read_only_reason: ReadOnlyReasonSchema, owner_attachment: OwnerAttachmentSchema.optional(), can_branch: CanBranchSchema, can_pin: CanPinSchema, can_archive: CanArchiveSchema, can_delete: CanDeleteSchema, can_duplicate: CanDuplicateSchema, source_tag: NullableString.optional(),
|
|
306
|
+
can_compress: z.boolean().optional().describe('TAL-614: a manual compression would start now: writable, no running turn, and at least four model-history messages. Only the full session detail carries it; absent means no.'),
|
|
307
|
+
confirms_deep_truncate: z.boolean().optional().describe('TAL-929: this server holds a `session.truncate` that discards more than one user turn until it is confirmed; absent on older servers, which cut at once.'),
|
|
226
308
|
source_label: NullableString.optional(), session_source: NullableString.optional(), raw_source: NullableString.optional(), parent_session_id: NullableString.optional(), worktree_path: NullableString.optional(),
|
|
227
309
|
worktree_branch: NullableString.optional(), worktree_repo_root: NullableString.optional(), share_token: NullableString.optional(), share_url: NullableString.optional(), share_created_at: NullableNumber.optional(), manual_title: z.boolean().optional(),
|
|
228
310
|
compression_anchor_summary: NullableString.optional(), compression_recovery: z.record(z.string(), Json).optional(), recommended_recovery_action: NullableString.optional(), compression_recovery_action: NullableString.optional(),
|
|
@@ -237,18 +319,25 @@ export const SessionSchema = z.looseObject({
|
|
|
237
319
|
assistant_name: z.string().optional(),
|
|
238
320
|
workspace_name: WorkspaceNameSchema,
|
|
239
321
|
compression_reference: CompressionReferenceSchema.nullable().optional(),
|
|
322
|
+
branched_from: BranchedFromSchema.nullable().optional().describe('TAL-454: the chat this one was branched from while it still loads (archived included); null for a compression continuation, a deleted or missing parent, and every other chat.'),
|
|
240
323
|
});
|
|
241
324
|
export const SessionEnvelopeSchema = z.looseObject({ session: SessionSchema });
|
|
242
325
|
/** Sidebar row from `GET /api/sessions`. */
|
|
243
326
|
export const SessionRowSchema = z.looseObject({
|
|
244
327
|
session_id: SessionIdSchema, title: z.string(), workspace: z.string().optional(), model: NullableString.optional(), created_at: UnixSeconds.optional(), updated_at: UnixSeconds.optional(), last_message_at: NullableNumber.optional(),
|
|
245
328
|
message_count: z.number().optional(), pinned: z.boolean().optional(), archived: z.boolean().optional(), project_id: NullableString.optional(), profile: NullableString.optional(), is_streaming: IsStreamingSchema,
|
|
246
|
-
is_cli_session: z.boolean().optional(), source_kind: SourceKindSchema, is_messaging_session: IsMessagingSessionSchema, sort_ts: SortTsSchema, cron_running: z.boolean().optional(), read_only: ReadOnlySchema, can_branch: CanBranchSchema, can_pin: CanPinSchema, can_archive: CanArchiveSchema, can_delete: CanDeleteSchema, can_duplicate: CanDuplicateSchema, attention: z.looseObject({ kind: z.string().optional(), count: z.number().optional() }).nullable().optional(),
|
|
329
|
+
is_cli_session: z.boolean().optional(), source_kind: SourceKindSchema, is_messaging_session: IsMessagingSessionSchema, sort_ts: SortTsSchema, cron_running: z.boolean().optional(), read_only: ReadOnlySchema, read_only_reason: ReadOnlyReasonSchema, owner_attachment: OwnerAttachmentSchema.optional(), can_branch: CanBranchSchema, can_pin: CanPinSchema, can_archive: CanArchiveSchema, can_delete: CanDeleteSchema, can_duplicate: CanDuplicateSchema, attention: z.looseObject({ kind: z.string().optional(), count: z.number().optional() }).nullable().optional(),
|
|
247
330
|
source_tag: NullableString.optional(), source_label: NullableString.optional(), session_source: NullableString.optional(), raw_source: NullableString.optional(), parent_session_id: NullableString.optional(),
|
|
248
331
|
active_stream_id: ActiveStreamIdSchema, share_token: NullableString.optional(), share_url: NullableString.optional(), worktree_branch: NullableString.optional(), match_type: z.enum(['title', 'metadata', 'content']).optional(), match_preview: NullableString.optional(),
|
|
249
332
|
workspace_name: WorkspaceNameSchema,
|
|
250
333
|
...ContextUsageFields,
|
|
251
334
|
});
|
|
335
|
+
/**
|
|
336
|
+
* TAL-785: whether the Agent's `state.db` could serve the Agent session rows. `corrupt`: SQLite reports the file
|
|
337
|
+
* damaged; `unavailable`: it could not be read for another reason (permissions, a lock, an I/O error); `outdated`: a
|
|
338
|
+
* readable database from an older hermes-agent. `reason` explains a degraded state.
|
|
339
|
+
*/
|
|
340
|
+
export const AgentStorageSchema = z.object({ state: z.enum(['ok', 'corrupt', 'unavailable', 'outdated']), reason: z.string().nullable() });
|
|
252
341
|
export const SessionsListSchema = z.looseObject({
|
|
253
342
|
sessions: z.array(SessionRowSchema).describe('Canonical display order (TAL-306): pinned first, then active (streaming or a pending prompt), then newest `sort_ts`, then `session_id`. Clients keep it.'), sidebar_reference_sessions: z.array(SessionRowSchema), server_time: z.number(), server_tz: z.string(), active_profile: z.string(), all_profiles: z.boolean(), include_archived: z.boolean(),
|
|
254
343
|
archived_count: z.number().int(), archived_webui_count: z.number().int(), archived_cli_count: z.number().int(), other_profile_count: z.number().int(), cli_count: z.number().int(), webui_session_count: z.number().int(),
|
|
@@ -256,10 +345,11 @@ export const SessionsListSchema = z.looseObject({
|
|
|
256
345
|
// TAL-482: sidebar counts for the "Scheduled sessions" / "Webhook sessions" groups; `_truncated` means more exist than are listed.
|
|
257
346
|
scheduled_session_count: z.number().int().nonnegative(), scheduled_sessions_truncated: z.boolean(),
|
|
258
347
|
webhook_session_count: z.number().int().nonnegative(), webhook_sessions_truncated: z.boolean(),
|
|
348
|
+
agent_storage: AgentStorageSchema.describe('Agent session storage health; a degraded state explains an empty or missing Agent session list.'),
|
|
259
349
|
archived_limit: z.number().int().nullable().optional(), archived_offset: z.number().int().optional(),
|
|
260
350
|
});
|
|
261
351
|
export const SessionStatusSchema = z.looseObject({
|
|
262
|
-
session_id: SessionIdSchema, title: z.string().optional(), active_stream_id: ActiveStreamIdSchema, active_turn_origin: ActiveTurnOriginSchema, agent_running: IsStreamingSchema, is_streaming: IsStreamingSchema, read_only: ReadOnlySchema, message_count: z.number().optional(), model: NullableString.optional(),
|
|
352
|
+
session_id: SessionIdSchema, title: z.string().optional(), active_stream_id: ActiveStreamIdSchema, active_turn_origin: ActiveTurnOriginSchema, agent_running: IsStreamingSchema, is_streaming: IsStreamingSchema, read_only: ReadOnlySchema, read_only_reason: ReadOnlyReasonSchema, owner_attachment: OwnerAttachmentSchema.optional(), message_count: z.number().optional(), model: NullableString.optional(),
|
|
263
353
|
profile: NullableString.optional(), workspace: z.string().optional(), input_tokens: z.number().optional(), output_tokens: z.number().optional(), total_tokens: z.number().optional(), estimated_cost: NullableNumber.optional(), updated_at: UnixSeconds.optional(),
|
|
264
354
|
});
|
|
265
355
|
export const SessionUsageSchema = z.looseObject({ input_tokens: z.number().optional(), output_tokens: z.number().optional(), total_tokens: z.number().optional(), estimated_cost: NullableNumber.optional(), model: NullableString.optional() });
|
|
@@ -267,12 +357,20 @@ export const ProjectSchema = z.looseObject({ project_id: z.string(), name: z.str
|
|
|
267
357
|
export const ProjectsSchema = z.looseObject({ projects: z.array(ProjectSchema), active_profile: z.string(), all_profiles: z.boolean(), other_profile_count: z.number().int() });
|
|
268
358
|
export const SessionDeleteResultSchema = z.looseObject({ ok: z.literal(true), state_db_cleanup_failed: z.boolean().optional() });
|
|
269
359
|
// ── chat ─────────────────────────────────────────────────────────────────
|
|
360
|
+
/** `voice_turn` (TAL-801): the turn was spoken (an App voice note), so the Agent runs it on `auxiliary.voice_chat`. */
|
|
270
361
|
export const ChatStartRequestSchema = z.looseObject({
|
|
362
|
+
submission_id: z.string().min(1).max(128).optional().describe('Stable native-owner admission identity. Reuse only for an exact retry of the same submission.'),
|
|
271
363
|
session_id: SessionIdSchema, message: z.string().optional(), model: z.string().nullable().optional(), model_provider: z.string().nullable().optional(), workspace: z.string().nullable().optional(), profile: z.string().nullable().optional(),
|
|
272
364
|
explicit_model_pick: z.boolean().optional(), attachments: z.array(z.union([AttachmentSchema, z.string()])).optional(), moa_config: z.boolean().optional(), regenerate: z.boolean().optional(), regeneration_revision: z.string().optional(),
|
|
365
|
+
voice_turn: z.boolean().optional(),
|
|
366
|
+
/** TAL-818: this client renders `connect_card`, so a `manage_connections` call waits on the card; without it the Agent answers with plain links. */
|
|
367
|
+
connect_card: z.boolean().optional(),
|
|
368
|
+
/** The starting client renders the masked `skill_secret` prompt; omitted by older and native clients. */
|
|
369
|
+
skill_secret: z.boolean().optional(),
|
|
273
370
|
});
|
|
274
371
|
/** Accepted turn. `stream_id` is the owner identity for the SSE connection. */
|
|
275
372
|
export const ChatStartResponseSchema = z.looseObject({
|
|
373
|
+
owner_attachment: OwnerAttachmentSchema.optional(), admission_id: z.string().optional(),
|
|
276
374
|
stream_id: z.string().optional(), session_id: SessionIdSchema.optional(), turn_id: z.string().optional(), user_message_id: z.union([z.string(), z.number()]).nullable().optional(), pending_started_at: z.number().nullable().optional(),
|
|
277
375
|
title: z.string().optional(), effective_model: z.string().optional(), effective_model_provider: z.string().optional(), queued: z.boolean().optional(), ok: z.boolean().optional(), status: z.string().optional(), reason: z.string().optional(), session: SessionSchema.optional(),
|
|
278
376
|
});
|
|
@@ -297,14 +395,15 @@ export const SteerWithdrawRequestSchema = z.object({ session_id: SessionIdSchema
|
|
|
297
395
|
/** `withdrawn: false` when the steer is unknown, already taken by the Agent (it then settles as consumed), or being sent. */
|
|
298
396
|
export const SteerWithdrawResponseSchema = z.object({ withdrawn: z.boolean(), text: z.string().optional() });
|
|
299
397
|
export const SteerSendNowRequestSchema = z.object({ session_id: SessionIdSchema, steer_id: z.string().min(1) });
|
|
300
|
-
/**
|
|
301
|
-
export const SteerSendNowResponseSchema = z.object({ redirected: z.boolean() });
|
|
398
|
+
/** The server decides why Send now did or did not deliver. `redirected` remains for older clients. */
|
|
399
|
+
export const SteerSendNowResponseSchema = z.object({ redirected: z.boolean(), outcome: z.enum(['delivered', 'next_step', 'not_running', 'taken', 'failed']) });
|
|
302
400
|
/** `text` is delivered to the running agent; `display_text` is what the transcript shows. */
|
|
303
401
|
export const SteerRequestSchema = z.looseObject({ session_id: SessionIdSchema, text: z.string().min(1), display_text: z.string().optional(), steer_id: z.string().optional() });
|
|
304
402
|
/** `accepted: false` with a `fallback` reason means the message was not delivered; the caller keeps the draft. */
|
|
305
403
|
/** TAL-460: a steer sent while a background turn runs starts the user's own turn instead; `started_turn` is its start response. */
|
|
306
404
|
export const SteerResponseSchema = z.looseObject({ accepted: z.boolean(), fallback: NullableString.optional(), stream_id: NullableString.optional(), steer_id: z.string().optional(), started_turn: ChatStartResponseSchema.optional() });
|
|
307
405
|
export const ApprovalPendingSchema = z.looseObject({
|
|
406
|
+
allowed_choices: z.array(z.enum(['once', 'session', 'always', 'deny'])).optional(), can_enable_yolo: z.boolean().optional(),
|
|
308
407
|
approval_id: z.string().optional(), session_id: z.string().optional(), command: z.string().optional(), description: z.string().optional(), title: z.string().optional(), name: z.string().optional(), kind: z.string().optional(),
|
|
309
408
|
reason: z.string().optional(), action: z.string().optional(), question: z.string().optional(), status: z.string().optional(), pending_count: z.number().optional(), run_id: z.string().optional(), mirror_token: z.string().optional(),
|
|
310
409
|
});
|
|
@@ -317,14 +416,34 @@ export const ClarifyChoiceSchema = z.union([z.string(), z.looseObject({ label: z
|
|
|
317
416
|
export const ClarifyStepSchema = z.looseObject({ qid: z.string(), question: z.string(), choices: z.array(z.string()), multi_select: z.boolean() });
|
|
318
417
|
/** Keyed step answers; a multi-select step takes a list. The server shapes them into the Agent's reply. */
|
|
319
418
|
export const ClarifyAnswersSchema = z.record(z.string(), z.union([z.string(), z.array(z.string())]));
|
|
419
|
+
/** TAL-887: one input of a password-manager prompt, answered under its `key`; a `secure` input is masked. */
|
|
420
|
+
export const VaultPromptFieldSchema = z.object({ key: z.enum(['master_password', 'identifier', 'password', 'code', 'secret']), secure: z.boolean() });
|
|
421
|
+
/**
|
|
422
|
+
* TAL-887: the Agent asks for a password manager's master password (`vault_unlock`), a login to save for the page it is
|
|
423
|
+
* on (`vault_save_login`), a one-time code (`vault_code`), or a skill environment secret (`skill_secret`). Clients answer through
|
|
424
|
+
* `/api/clarify/respond` with keyed `answers`, or `decline`; an empty answer, a decline, a cancel and `timeout_at` all
|
|
425
|
+
* resolve it unanswered. Answers never enter chat, logs, streams, or responses. Skill secrets are saved only to the invoking profile.
|
|
426
|
+
*/
|
|
427
|
+
export const VaultPromptSchema = z.object({
|
|
428
|
+
kind: z.enum(['vault_unlock', 'vault_save_login', 'vault_code', 'skill_secret']),
|
|
429
|
+
backend: z.string().nullable().describe('The password manager (`vault_unlock`).'),
|
|
430
|
+
display_name: z.string().nullable().describe('Its display name (`vault_unlock`).'),
|
|
431
|
+
origin: z.string().nullable().describe('The page origin the login is saved for (`vault_save_login`).'),
|
|
432
|
+
site: z.string().nullable().describe('The site, by host (`vault_save_login`, `vault_code`).'),
|
|
433
|
+
hint: z.string().nullable().describe('Where the code was sent, when the Agent says (`vault_code`).'),
|
|
434
|
+
skill: z.object({ env_var: z.string(), skill_name: z.string(), help: z.string().nullable(), required_for: z.string().nullable() }).optional().describe('Profile-local environment setup metadata (`skill_secret`).'),
|
|
435
|
+
fields: z.array(VaultPromptFieldSchema),
|
|
436
|
+
timeout_at: z.number().describe('Unix seconds when the Agent stops waiting.'),
|
|
437
|
+
});
|
|
320
438
|
export const ClarifyPendingSchema = z.looseObject({
|
|
321
439
|
steps: z.array(ClarifyStepSchema).optional(),
|
|
440
|
+
vault: VaultPromptSchema.optional(),
|
|
322
441
|
clarify_id: z.string().optional(), session_id: z.string().optional(), question: z.string().optional(), description: z.string().optional(), choices: z.array(ClarifyChoiceSchema).optional(), title: z.string().optional(),
|
|
323
442
|
name: z.string().optional(), kind: z.string().optional(), reason: z.string().optional(), action: z.string().optional(), status: z.string().optional(), raw_preview: z.string().optional(), timeout_at: z.number().optional(),
|
|
324
443
|
timeout_seconds: z.number().optional(), pending_count: z.number().optional(), index: z.number().optional(), total: z.number().optional(),
|
|
325
444
|
});
|
|
326
445
|
export const ClarifyPendingEnvelopeSchema = z.looseObject({ pending: ClarifyPendingSchema.nullable(), pending_count: z.number().int() });
|
|
327
|
-
export const ClarifyRespondRequestSchema = z.looseObject({ session_id: SessionIdSchema, answers: ClarifyAnswersSchema.optional(), response: z.string().optional(), answer: z.string().optional(), choice: z.string().optional(), clarify_id: z.string().optional() });
|
|
446
|
+
export const ClarifyRespondRequestSchema = z.looseObject({ session_id: SessionIdSchema, answers: ClarifyAnswersSchema.optional(), response: z.string().optional(), answer: z.string().optional(), choice: z.string().optional(), clarify_id: z.string().optional(), decline: z.boolean().optional() });
|
|
328
447
|
export const ClarifyRespondResponseSchema = z.looseObject({ ok: z.boolean(), response: z.string().optional(), error: z.string().optional(), stale: z.boolean().optional() });
|
|
329
448
|
export const DraftSchema = z.looseObject({ text: z.string(), files: z.array(Json) });
|
|
330
449
|
export const DraftResponseSchema = z.looseObject({ ok: z.literal(true), draft: DraftSchema, draft_version: z.string().nullable(), unchanged: z.boolean().optional() });
|
|
@@ -333,8 +452,6 @@ export const MAX_CHAT_ATTACHMENTS = 20;
|
|
|
333
452
|
export const UploadResponseSchema = z.looseObject({ filename: z.string(), path: z.string(), size: z.number(), mime: z.string(), is_image: z.boolean().optional(), rollback_token: z.string().optional(), named_in_prompt: z.boolean().optional(), max_attachments_per_message: z.number().int().positive().optional() });
|
|
334
453
|
export const GoalViewSchema = z.looseObject({ text: z.string().optional(), state: z.string().optional(), status: z.string().optional(), turns: z.number().optional(), max_turns: z.number().optional(), reason: z.string().optional() });
|
|
335
454
|
export const GoalResponseSchema = z.looseObject({ ok: z.boolean().optional(), action: z.string().optional(), goal: GoalViewSchema.nullable().optional(), message: z.string().optional(), message_key: z.string().optional(), stream_id: z.string().optional(), status: z.string().optional(), reason: z.string().optional() });
|
|
336
|
-
export const BackgroundResultSchema = z.looseObject({ id: z.string().optional(), task_id: z.string().optional(), status: z.string().optional(), title: z.string().optional(), summary: z.string().optional(), prompt: z.string().optional(), answer: NullableString.optional(), error: z.string().optional(), completed_at: z.number().nullable().optional() });
|
|
337
|
-
export const BackgroundStatusSchema = z.looseObject({ results: z.array(BackgroundResultSchema) });
|
|
338
455
|
/**
|
|
339
456
|
* TAL-372: one piece of background work a session owns, the same record for every client, reload and restart.
|
|
340
457
|
* - `task_id` is stable: the delegation unit's id, the process id, or the `/background` task id.
|
|
@@ -379,7 +496,15 @@ export const SessionNewRequestSchema = z.looseObject({
|
|
|
379
496
|
title: z.string().optional(), workspace: z.string().optional(), workspace_inherited_from_prev_session: z.boolean().optional(), model: z.string().nullable().optional(), model_provider: z.string().nullable().optional(),
|
|
380
497
|
profile: z.string().nullable().optional(), prev_session_id: z.string().optional(), project_id: z.string().nullable().optional(), worktree: Json.optional(), enabled_toolsets: z.array(z.string()).nullable().optional(), parent_session_id: z.string().optional(),
|
|
381
498
|
});
|
|
382
|
-
|
|
499
|
+
/**
|
|
500
|
+
* `streaming` (TAL-802): live dictation over `TRANSCRIBE_STREAM_PATH` would open for this profile (`stt.streaming` on, a live provider wire).
|
|
501
|
+
* `warm_supported` (TAL-916): a client starting a recording should `POST /api/transcribe/warm` so the engine loads while the user speaks.
|
|
502
|
+
*/
|
|
503
|
+
export const TranscribeCapabilitySchema = z.looseObject({ ok: z.literal(true), available: z.boolean(), provider: z.string(), streaming: z.boolean(), warm_supported: z.boolean() });
|
|
504
|
+
/** TAL-906: what read-aloud speaks for a message; clients play it as is. */
|
|
505
|
+
export const SpeechPrepareSchema = z.object({ spoken_text: z.string() });
|
|
506
|
+
/** `POST /api/transcribe`: the recording's transcript; `filtered` (TAL-917) when the server emptied a phrase Whisper invents on silent audio. */
|
|
507
|
+
export const TranscribeResponseSchema = z.looseObject({ ok: z.literal(true), transcript: z.string(), filtered: z.boolean() });
|
|
383
508
|
// ── settings, profiles, models, providers ───────────────────────────────
|
|
384
509
|
/** TAL-411: the request profile's quota urgency thresholds. A save patches valid fields and clamps critical to at most warning. */
|
|
385
510
|
export const QuotaThresholdsSchema = z.object({
|
|
@@ -391,7 +516,7 @@ export const SettingsSchema = z.looseObject({
|
|
|
391
516
|
bot_name: z.string().optional(), default_model: z.string().optional(), default_workspace: z.string().optional(), language: z.string().optional(), send_key: z.string().optional(), font_size: z.string().optional(),
|
|
392
517
|
full_width_chat: z.boolean().optional(), chat_width: z.enum(['comfortable', 'wide', 'full']).optional(), auto_scroll_follow: z.boolean().optional(), render_user_markdown: z.boolean().optional(), chat_activity_display_mode: z.string().optional(), default_message_mode: z.string().optional(),
|
|
393
518
|
fade_text_effect: z.boolean().optional(), hidden_tabs: z.array(z.string()).optional(), composer_control_order: z.array(z.string()).optional(), show_cli_sessions: z.boolean().optional(), show_claude_code_sessions: z.boolean().optional(),
|
|
394
|
-
show_cron_sessions: z.boolean().optional(), show_webhook_sessions: z.boolean().optional(), show_kanban_sessions: z.boolean().optional(), check_for_updates: z.boolean().optional(), ignore_agent_updates: z.boolean().optional(),
|
|
519
|
+
show_cron_sessions: z.boolean().optional(), show_webhook_sessions: z.boolean().optional(), show_kanban_sessions: z.boolean().optional(), check_for_updates: z.boolean().optional(), summarize_updates_automatically: z.boolean().optional(), ignore_agent_updates: z.boolean().optional(),
|
|
395
520
|
auth_enabled: z.boolean().optional(), password_auth_enabled: z.boolean().optional(), password_env_var: z.boolean().optional(), passkeys_enabled: z.boolean().optional(), passwordless_enabled: z.boolean().optional(),
|
|
396
521
|
auth_disabled_acknowledged: z.boolean().optional(), webui_version: z.string().optional(), agent_version: z.string().optional(), update_channel: z.string().optional(), agent_update_channel: z.enum(['stable', 'experimental']).optional(), update_channel_version: NullableString.optional(),
|
|
397
522
|
max_tokens: NullableNumber.optional(), max_tokens_effective: NullableNumber.optional(), max_tokens_fallback: NullableNumber.optional(), tts_engine: z.string().optional(), tts_voice: z.string().optional(),
|
|
@@ -403,23 +528,61 @@ export const SettingsSchema = z.looseObject({
|
|
|
403
528
|
export const ProfileSchema = z.looseObject({
|
|
404
529
|
name: z.string(), path: z.string().optional(), is_active: z.boolean().optional(), is_default: z.boolean().optional(), model: NullableString.optional(), provider: NullableString.optional(), skill_count: z.number().optional(),
|
|
405
530
|
total_skills: z.number().optional(), enabled_skills: z.number().optional(), gateway_running: z.boolean().optional(), has_env: z.boolean().optional(), visible: z.boolean().optional(),
|
|
531
|
+
/** TAL-805: the profile's gateway mode; `gateway_running` is true exactly for `own` and `served`. */
|
|
532
|
+
gateway_mode: GatewayModeSchema.optional(),
|
|
533
|
+
/** TAL-213: Bot Mode identity from `profile.yaml` (the bot's roster title, else the profile's display name), one bounded printable line each. */
|
|
534
|
+
display_name: z.string().optional(), description: z.string().optional(), has_avatar: z.boolean().optional(),
|
|
535
|
+
/** TAL-213: present only when the profile has a canonical Bot Chat; clients open `tip_session_id` after switching to the profile. */
|
|
536
|
+
canonical_session: CanonicalBotChatSchema.nullable().optional(),
|
|
537
|
+
/** TAL-819: skill and memory writes the Agent staged for approval, reviewed on the Skills and Memory pages. */
|
|
538
|
+
pending_writes: z.number().int().optional(),
|
|
406
539
|
});
|
|
407
540
|
export const ProfilesSchema = z.looseObject({ profiles: z.array(ProfileSchema), active: z.string(), single_profile_mode: z.boolean().optional() });
|
|
408
541
|
export const ActiveProfileSchema = z.looseObject({ name: z.string(), path: z.string().optional(), is_default: z.boolean().optional(), default_workspace: NullableString.optional() });
|
|
409
542
|
export const ProfileSwitchSchema = ProfilesSchema.extend({ is_default: z.boolean(), default_model: Json, default_model_provider: Json, default_workspace: z.string().nullable() });
|
|
410
543
|
/** `/api/reasoning`: config.yaml agent.reasoning_effort / display.show_reasoning, resolved for a model. */
|
|
411
544
|
export const ReasoningStatusSchema = z.looseObject({ show_reasoning: z.boolean().optional(), reasoning_effort: z.string().nullable().optional(), supported_efforts: z.array(z.string()).optional(), supports_reasoning_effort: z.boolean().optional(), supports_thinking_toggle: z.boolean().optional() });
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
545
|
+
export const QuotaLevelSchema = z.enum(['healthy', 'warning', 'critical', 'stale', 'unavailable']);
|
|
546
|
+
/**
|
|
547
|
+
* TAL-301: `provider_id`/`bare_id` are the server's split of `id`; clients match a stored `(model, provider)` against them and send `id` back.
|
|
548
|
+
* TAL-807: `limit` is present while the provider's credential pool cannot serve this model until `resets_at` (ISO-8601 UTC).
|
|
549
|
+
*/
|
|
550
|
+
export const ModelEntrySchema = z.looseObject({
|
|
551
|
+
id: z.string(), label: z.string().optional(), provider: z.string().optional(), provider_id: z.string().optional(), bare_id: z.string().optional(), supports_fast_tier: z.boolean().optional(), supported_speed_tiers: z.array(SpeedTierSchema).optional(),
|
|
552
|
+
limit: z.object({ scope: z.literal('model'), resets_at: z.string() }).optional(),
|
|
553
|
+
});
|
|
554
|
+
/** TAL-807: a group's rate limit: every pool account benched until `resets_at`, else the entry ids (`models`) cooling down until their reset. */
|
|
555
|
+
export const ModelGroupLimitSchema = z.discriminatedUnion('scope', [
|
|
556
|
+
z.object({ scope: z.literal('account'), resets_at: z.string() }),
|
|
557
|
+
z.object({ scope: z.literal('models'), models: z.record(z.string(), z.string()) }),
|
|
558
|
+
]);
|
|
559
|
+
/**
|
|
560
|
+
* TAL-807: `limit` is the provider's live pool rate limit; `quota_level` is the TAL-411 `remaining` level of the tightest
|
|
561
|
+
* account-scope window in the provider's last account-usage read (a model-family window never counts), absent without one
|
|
562
|
+
* and while the group is account-limited.
|
|
563
|
+
*/
|
|
564
|
+
export const CatalogAvailabilitySchema = z.object({ status: z.enum(['available', 'stale', 'unavailable']), authoritative: z.boolean(), unavailable_reason: NullableString, generation: z.string().min(1).describe('Opaque source generation; cached data from another generation must never be merged.') });
|
|
565
|
+
export const ModelGroupSchema = z.looseObject({
|
|
566
|
+
availability: CatalogAvailabilitySchema.optional(),
|
|
567
|
+
provider: z.string(), provider_id: z.string().optional(), models: z.array(ModelEntrySchema), extra_models: z.array(ModelEntrySchema).optional(),
|
|
568
|
+
limit: ModelGroupLimitSchema.optional(), quota_level: QuotaLevelSchema.optional(),
|
|
569
|
+
});
|
|
570
|
+
export const ModelsSchema = z.looseObject({ availability: CatalogAvailabilitySchema.optional(), active_provider: NullableString.optional(), default_model: z.string().optional(), default_provider_id: NullableString.optional(), default_bare_id: z.string().optional(), default_option_id: NullableString.optional(), groups: z.array(ModelGroupSchema), aliases: z.record(z.string(), Json).optional(), configured_model_badges: z.record(z.string(), Json).optional() });
|
|
571
|
+
export const ModelsLiveSchema = z.looseObject({ availability: CatalogAvailabilitySchema.optional(), provider: z.string().optional(), source: z.string().optional(), models: z.array(ModelEntrySchema), count: z.number().optional(), error: z.string().optional() });
|
|
572
|
+
/** TAL-603: where a card's credential comes from; `other` is a source the server cannot name, shown as its raw `key_source`. */
|
|
573
|
+
export const KeySourceKindSchema = z.enum(['env', 'oauth', 'config', 'pool', 'plugin', 'other']);
|
|
574
|
+
/**
|
|
575
|
+
* `has_key` reports a credential; `configured` (TAL-570) is the row's setup status, which a keyless Ollama or LM Studio endpoint also meets.
|
|
576
|
+
* TAL-603: `is_active` marks the active provider's card; `key_source_kind` is the key badge (`null` without a credential);
|
|
577
|
+
* `models_total` is the catalog size, never below `models.length`. `is_active` and `key_source_kind` are absent from older servers.
|
|
578
|
+
* TAL-641: `removable` marks a key Remove would clear: a built-in, not self-hosted, provider whose only key is its own profile `.env` variable.
|
|
579
|
+
*/
|
|
417
580
|
export const ProviderSchema = z.looseObject({
|
|
418
581
|
id: z.string(), display_name: z.string().optional(), has_key: z.boolean().optional(), configured: z.boolean().optional(), configurable: z.boolean().optional(), is_oauth: z.boolean().optional(), is_plugin_provider: z.boolean().optional(), is_self_hosted: z.boolean().optional(),
|
|
419
582
|
is_custom: z.boolean().optional(), key_source: z.string().optional(), base_url: NullableString.optional(), auth_error: NullableString.optional(), env_var: NullableString.optional(), models: z.array(ModelEntrySchema).optional(), models_total: z.number().optional(),
|
|
583
|
+
is_active: z.boolean().optional(), key_source_kind: KeySourceKindSchema.nullable().optional(), removable: z.boolean().optional(),
|
|
420
584
|
});
|
|
421
|
-
export const ProvidersSchema = z.looseObject({ providers: z.array(ProviderSchema), active_provider: NullableString.optional() });
|
|
422
|
-
export const QuotaLevelSchema = z.enum(['healthy', 'warning', 'critical', 'stale', 'unavailable']);
|
|
585
|
+
export const ProvidersSchema = z.looseObject({ availability: CatalogAvailabilitySchema.optional(), providers: z.array(ProviderSchema), active_provider: NullableString.optional() });
|
|
423
586
|
/** TAL-411: the server's classification per colour basis; `/api/provider/quotas` only, at the profile's thresholds. */
|
|
424
587
|
export const QuotaUrgencySchema = z.looseObject({ remaining: QuotaLevelSchema, pace: QuotaLevelSchema.describe('Burn rate and pace tolerance; the remaining classification when the window has no pace.') });
|
|
425
588
|
/** TAL-409: a window's pace as of the envelope's `computed_at`. Stale once `valid_until` (the window's reset) passes. */
|
|
@@ -444,6 +607,7 @@ export const QuotaWindowSchema = z.looseObject({
|
|
|
444
607
|
});
|
|
445
608
|
const QuotaWindowIndex = z.number().int().nullable().optional();
|
|
446
609
|
export const QuotaSourceSchema = z.looseObject({
|
|
610
|
+
computed_at: z.string().optional().describe('Original reference time of this source, retained with stale windows.'),
|
|
447
611
|
source_id: z.string(), provider_id: z.string().optional(), provider_label: z.string().optional(), account_label: z.string().optional(), status: z.string().optional(), supported: z.boolean().optional(), message: z.string().nullable().optional(),
|
|
448
612
|
is_active_provider: z.boolean().optional(), quota: Json.optional(), windows: z.array(QuotaWindowSchema).optional(), balances: Json.optional(), plan: Json.optional(), details: Json.optional(), unavailable_reason: Json.optional(), retry_after: Json.optional(), fetched_at: Json.optional(),
|
|
449
613
|
pace_window_index: QuotaWindowIndex.describe('The window a pace-coloured widget shows: the weekly one, else the first 5h/session window.'),
|
|
@@ -464,8 +628,8 @@ export const ProviderQuotaSchema = z.looseObject({
|
|
|
464
628
|
account_limits: QuotaAccountLimitsSchema.nullable().optional(),
|
|
465
629
|
});
|
|
466
630
|
/** Python `get_provider_quotas`: the stable identity envelope the iOS quota widget persists (`scope_id`/`profile_id`). */
|
|
467
|
-
export const ProviderQuotasSchema = z.looseObject({
|
|
468
|
-
version: z.number(), computed_at: z.string().describe('ISO-8601 UTC reference time
|
|
631
|
+
export const ProviderQuotasSchema = z.looseObject({ availability: CatalogAvailabilitySchema.optional(),
|
|
632
|
+
version: z.number(), computed_at: z.string().describe('ISO-8601 UTC request reference time; coalesced or stale sources retain their own computed_at.'), scope_id: z.string(), profile_id: z.string(), active_provider: NullableString, requested_source_id: NullableString,
|
|
469
633
|
missing_source: z.boolean().describe('True when `?source=` names a source id this scope no longer has; `sources` is then empty.'),
|
|
470
634
|
sources: z.array(QuotaSourceSchema).describe('Each live source id exactly once, ordered by `provider_id`, then `account_label`, then `source_id`. Clients render this list as-is; a `?source=` read returns that one row.'),
|
|
471
635
|
});
|
|
@@ -500,8 +664,12 @@ export const AuxiliaryTaskSchema = z.looseObject({
|
|
|
500
664
|
selected_option_id: z.string().nullable(),
|
|
501
665
|
/** False only for a pinned model the current catalog does not list; it stays visible and editable. */
|
|
502
666
|
in_catalog: z.boolean(),
|
|
667
|
+
/** TAL-800: the slot a plugin task inherits its route from; while the task is Auto, `value_label` names that slot's model. */
|
|
668
|
+
inherit_from: z.string().nullable(),
|
|
669
|
+
/** TAL-800: the reasoning effort the slot runs with (the Agent's default until one is saved; `''` = provider default); null when the Agent does not report its slots. */
|
|
670
|
+
reasoning_effort: z.string().nullable(),
|
|
503
671
|
});
|
|
504
|
-
export const AuxiliaryModelsSchema = z.looseObject({ main: z.looseObject({ model: z.string().optional(), provider: z.string().optional(), base_url: z.string().optional(), api_key_set: z.boolean().optional() }), tasks: z.array(AuxiliaryTaskSchema) });
|
|
672
|
+
export const AuxiliaryModelsSchema = z.looseObject({ main: z.looseObject({ model: z.string().optional(), provider: z.string().optional(), base_url: z.string().optional(), api_key_set: z.boolean().optional(), service_tier: z.enum(['', 'default', 'priority', 'ultrafast']).optional().describe('Empty string is the Standard value returned by older servers.'), supported_speed_tiers: z.array(SpeedTierSchema).optional() }), tasks: z.array(AuxiliaryTaskSchema) });
|
|
505
673
|
export const MaxTokensSchema = z.looseObject({ max_tokens: NullableNumber, max_tokens_effective: NullableNumber, max_tokens_fallback: NullableNumber });
|
|
506
674
|
// ── workspaces, files, git ───────────────────────────────────────────────
|
|
507
675
|
/** A registry entry; `name` is never empty (the folder name when none is registered, `Home` for `default`), so pickers show it as-is (TAL-303). */
|
|
@@ -521,16 +689,23 @@ export const FileContentSchema = z.looseObject({
|
|
|
521
689
|
preview: FilePreviewKindSchema.optional(), table: z.array(z.array(z.string())).optional(), table_truncated: z.boolean().optional(),
|
|
522
690
|
preview_url: z.string().optional(),
|
|
523
691
|
});
|
|
524
|
-
|
|
692
|
+
const GitBadgeSchema = z.looseObject({ is_git: z.boolean().optional(), branch: NullableString.optional(), dirty: z.number().optional(), modified: z.number().optional(), untracked: z.number().optional(), ahead: z.number().optional(), behind: z.number().optional() });
|
|
693
|
+
export const GitInfoSchema = z.looseObject({ git: GitBadgeSchema.nullable().optional() });
|
|
525
694
|
// ── tools ────────────────────────────────────────────────────────────────
|
|
526
|
-
export const SkillSchema = z.looseObject({ name: z.string(), description: NullableString.optional(), category: NullableString.optional(), disabled: z.boolean().optional() });
|
|
695
|
+
export const SkillSchema = z.looseObject({ ...SkillCatalogIdentitySchema.shape, name: z.string(), description: NullableString.optional(), category: NullableString.optional(), disabled: z.boolean().optional() });
|
|
527
696
|
export const SkillsSchema = z.looseObject({ skills: z.array(SkillSchema), categories: z.array(Json).optional() });
|
|
528
|
-
|
|
697
|
+
/**
|
|
698
|
+
* `linked_files` groups the skill directory's files by folder (`references`, `templates`, ...); open one with `?file=`.
|
|
699
|
+
* A linked file that is not UTF-8 text carries `binary: true` and its `size` instead of `content`.
|
|
700
|
+
*/
|
|
701
|
+
export const SkillContentSchema = z.looseObject({ editable: z.boolean().optional(), name: z.string().optional(), content: z.string().optional(), path: z.string().optional(), linked_files: z.record(z.string(), z.array(z.string())).optional(), binary: z.literal(true).optional(), size: z.number().optional(), success: z.boolean().optional(), message: z.string().optional(), ok: z.boolean().optional() });
|
|
529
702
|
export const SkillsUsageSchema = z.looseObject({ usage: z.record(z.string(), z.looseObject({ use_count: z.number().optional(), view_count: z.number().optional(), patch_count: z.number().optional() })), skill_names: z.array(z.string()).optional(), total_invocations: z.number().optional(), unique_skills_used: z.number().optional() });
|
|
530
703
|
export const MemorySchema = z.looseObject({
|
|
531
704
|
memory: z.string(), user: z.string(), soul: z.string(), project_context: z.string().optional(), memory_path: z.string().optional(), user_path: z.string().optional(), soul_path: z.string().optional(), project_context_path: z.string().optional(),
|
|
532
705
|
project_context_name: z.string().optional(), project_context_workspace: z.string().optional(), memory_mtime: NullableNumber.optional(), user_mtime: NullableNumber.optional(), soul_mtime: NullableNumber.optional(), project_context_mtime: NullableNumber.optional(),
|
|
533
706
|
project_context_shadowed: z.array(Json).optional(), external_notes_enabled: z.boolean().optional(),
|
|
707
|
+
/** TAL-784: the revision of each file as this read found it. A save sends the revision its edit started from. */
|
|
708
|
+
memory_revision: z.string(), user_revision: z.string(), soul_revision: z.string(),
|
|
534
709
|
});
|
|
535
710
|
export const PromptSchema = z.looseObject({ id: z.string().optional(), name: z.string().optional(), title: z.string().optional(), label: z.string().optional(), text: z.string().optional(), content: z.string().optional(), created_at: z.number().optional() });
|
|
536
711
|
export const PromptsSchema = z.looseObject({ prompts: z.array(PromptSchema) });
|
|
@@ -540,12 +715,15 @@ export const PromptsSchema = z.looseObject({ prompts: z.array(PromptSchema) });
|
|
|
540
715
|
* clients can run it, and `unsupported_message` is the English text a client outside `clients` shows when it is typed.
|
|
541
716
|
* Clients suggest the entries listing them whose name or any alias starts with the typed text (case-insensitive), and
|
|
542
717
|
* resolve a typed alias to the entry's `name`. `exec` marks an Agent entry `POST /api/commands/exec` runs: the client
|
|
543
|
-
* posts the typed text there and shows the returned output instead of starting a chat turn
|
|
718
|
+
* posts the typed text there with the open chat's `session_id` and shows the returned output instead of starting a chat turn
|
|
719
|
+
* (TAL-561); `/refine` reviews that chat (TAL-902).
|
|
720
|
+
* `handler: 'prompt'` marks an Agent prompt built-in: the client sends the typed text as a chat turn and the server starts the
|
|
721
|
+
* turn with the Agent's expansion of it (TAL-817).
|
|
544
722
|
*/
|
|
545
723
|
export const CommandClientSchema = z.enum(['web', 'ios']);
|
|
546
724
|
export const CommandRowSchema = z.looseObject({
|
|
547
725
|
name: z.string(), description: z.string().optional(), aliases: z.array(z.string()), args_hint: z.string().optional(), category: z.string().optional(),
|
|
548
|
-
handler: z.enum(['client', 'agent']), clients: z.array(CommandClientSchema), unsupported_message: z.string().optional(),
|
|
726
|
+
handler: z.enum(['client', 'agent', 'prompt']), clients: z.array(CommandClientSchema), unsupported_message: z.string().optional(),
|
|
549
727
|
cli_only: z.boolean().optional(), gateway_only: z.boolean().optional(), subcommands: z.array(Json).optional(), exec: z.boolean().optional(),
|
|
550
728
|
});
|
|
551
729
|
export const CommandsSchema = z.looseObject({ commands: z.array(CommandRowSchema) });
|
|
@@ -557,23 +735,94 @@ export const InsightsSchema = z.looseObject({
|
|
|
557
735
|
models: z.array(z.looseObject({ model: z.string().optional(), sessions: z.number().optional(), tokens: z.number().optional(), cost: z.number().optional() })).optional(),
|
|
558
736
|
});
|
|
559
737
|
export const DashboardStatusSchema = z.looseObject({ running: z.boolean(), enabled: z.string().optional(), url: z.string().optional(), browser_url: z.string().optional(), host: z.string().optional(), port: z.number().int().optional(), version: z.string().optional(), error: z.string().optional() });
|
|
560
|
-
|
|
738
|
+
/**
|
|
739
|
+
* Gateway status for the Settings banner (TAL-266). `running` and `configured` come from the Agent health probe; when it
|
|
740
|
+
* is inconclusive, stale running metadata or known gateway sessions mark the gateway configured. `platforms` are the
|
|
741
|
+
* messaging platforms of known gateway sessions; `last_active` is the gateway session index's ISO mtime while running, else "".
|
|
742
|
+
* TAL-805: `gateway_mode` is the active profile's mode and decides `running` when it is not null. It is null for a remote
|
|
743
|
+
* gateway, or for the root profile when the sidecar cannot answer; a named profile whose mode is unconfirmed reads `stopped`.
|
|
744
|
+
*/
|
|
745
|
+
export const GatewayStatusSchema = z.object({
|
|
746
|
+
running: z.boolean(), configured: z.boolean(), gateway_mode: GatewayModeSchema.nullable(), platforms: z.array(z.object({ name: z.string(), label: z.string() })), last_active: z.string(), session_count: z.number().int(),
|
|
747
|
+
health: z.object({ state: NullableString, reason: NullableString, gateway_state: NullableString }),
|
|
748
|
+
});
|
|
749
|
+
export const GatewayActionSchema = z.object({ ok: z.literal(true), action: z.enum(['start', 'stop', 'restart']), message: z.string(), status: GatewayStatusSchema });
|
|
750
|
+
export const DashboardConfigSchema = z.object({ enabled: z.enum(['auto', 'always', 'never']), url: z.string() });
|
|
751
|
+
/**
|
|
752
|
+
* Project OS dashboard for a repo found from the last workspace or the `board`'s default workdir (TAL-266). Every field is
|
|
753
|
+
* null or empty when the profile has no local workspace I/O or no repo is found. `onboarding.active` means the docs came
|
|
754
|
+
* from the repo root's `PROJECT.md`/`PLAN.md`/`STATUS.md` instead of `docs/project-os/`.
|
|
755
|
+
*/
|
|
756
|
+
export const ProjectOsDashboardSchema = z.object({
|
|
757
|
+
workspace: NullableString, repo_root: NullableString, selected_board_slug: NullableString.optional(), git: GitBadgeSchema.nullable(),
|
|
758
|
+
docs: z.object({ project: FileContentSchema.nullable(), plan: FileContentSchema.nullable(), status: FileContentSchema.nullable(), blocker_resolver: FileContentSchema.nullable() }).partial(),
|
|
759
|
+
handoff: z.record(z.string(), Json).nullable(), active: z.record(z.string(), Json).nullable(), heartbeat: z.record(z.string(), Json).nullable(),
|
|
760
|
+
onboarding: z.looseObject({ active: z.boolean(), doc_source: z.enum(['project-os', 'root']) }).optional(), goal_summary: z.string(),
|
|
761
|
+
});
|
|
762
|
+
/** One server projection used by chat readiness, HTTP refusals, and persisted stream errors. */
|
|
763
|
+
export const AgentRuntimeMetadataSchema = z.object({
|
|
764
|
+
agent_runtime_reason: z.enum(['update_active', 'recovery_incomplete', 'source_changed', 'unknown']).optional(),
|
|
765
|
+
agent_update_state: z.string().optional(),
|
|
766
|
+
retryable: z.boolean().optional(),
|
|
767
|
+
restart_scheduled: z.boolean().optional(),
|
|
768
|
+
});
|
|
769
|
+
/** TAL-951: whether Web chat can run, from the Agent sidecar's status; `condition` says why not, null when available. */
|
|
770
|
+
export const ChatReadinessSchema = z.discriminatedUnion('available', [
|
|
771
|
+
z.object({ available: z.literal(true), condition: z.null() }),
|
|
772
|
+
z.object({ available: z.literal(false), condition: z.enum(['sidecar_unavailable', 'agent_incompatible', 'agent_runtime_stale']), ...AgentRuntimeMetadataSchema.shape }),
|
|
773
|
+
]);
|
|
774
|
+
/** Messaging-gateway liveness (`alive`, `details`, `gateway_chat`) for Settings → System, plus Web chat readiness in `chat`. */
|
|
775
|
+
export const AgentHealthSchema = z.looseObject({ chat: ChatReadinessSchema.optional().describe('Always sent since TAL-951; absent from older servers.'), alive: z.boolean().nullable().optional(), checked_at: z.string().optional(), details: z.looseObject({ state: z.string().optional(), reason: z.string().optional() }).optional(), gateway_chat: z.looseObject({ enabled: z.boolean().optional(), backend: z.string().optional(), base_url_configured: z.boolean().optional(), api_key_configured: z.boolean().optional() }).optional(), error: z.string().optional() });
|
|
561
776
|
export const SystemHealthSchema = z.looseObject({
|
|
562
777
|
available: z.boolean().optional(), status: z.string().optional(), checked_at: z.string().optional(), cpu: Json.nullable().optional(), memory: Json.nullable().optional(), disk: z.looseObject({ percent: z.number().optional(), total_bytes: z.number().optional(), used_bytes: z.number().optional() }).nullable().optional(),
|
|
563
778
|
errors: z.array(z.looseObject({ code: z.string().optional(), metric: z.string().optional() })).optional(), webui_runtime: Json.optional(),
|
|
564
779
|
});
|
|
565
780
|
export const UpdateStateSchema = z.enum(['up_to_date', 'release_ready', 'commits_behind', 'local_changes', 'finish', 'manual', 'check_failed', 'off', 'unknown']);
|
|
566
|
-
|
|
781
|
+
const AgentSupportSchema = z.enum(['supported', 'unchecked']);
|
|
782
|
+
export const UpdateVersionSchema = z.object({
|
|
783
|
+
version: z.string().describe('The release as shown: the Agent tag or the Web release tag.'),
|
|
784
|
+
ref: z.string().describe('What `updates.apply`/`updates.force` accept back as `version`: the Agent tag or the Web semver.'),
|
|
785
|
+
sha: z.string().optional().describe('Agent only: the commit the tag peels to.'),
|
|
786
|
+
release_url: z.string().nullable(),
|
|
787
|
+
latest: z.boolean().describe('The channel\'s newest release, the one an update without `version` installs.'),
|
|
788
|
+
folded: z.boolean().describe('Shown behind the folded "more versions" node: every entry except the newest.'),
|
|
789
|
+
support: AgentSupportSchema.optional().describe('Agent only: this release\'s classification against the verified Agent window.'),
|
|
790
|
+
support_label: z.string().optional().describe('Agent only: `support` worded to fit one phone line.'),
|
|
791
|
+
}).describe('TAL-946: one installable Stable release newer than the installed one.');
|
|
792
|
+
export const UpdateTargetSchema = z.looseObject({
|
|
793
|
+
failed_update: z.object({ version: z.string(), restored_version: z.string() }).optional().describe('Web only: the update that failed before HTTP readiness and the restored package version. Manual retry remains available.'),
|
|
794
|
+
name: z.string().optional(), channel: z.enum(['stable', 'experimental']).optional(),
|
|
795
|
+
unsupported: z.boolean().optional().describe('Deprecated (TAL-350): `support === \'unchecked\'`, kept for older clients.'),
|
|
796
|
+
support: AgentSupportSchema.optional().describe('Agent target only (TAL-350): `supported` when the target revision is exactly a release in the verified Agent window, else `unchecked`; an `unchecked` apply requires `confirmed_agent_revision`.'),
|
|
797
|
+
support_label: z.string().optional().describe('Agent target only (TAL-946): `support` worded to fit one phone line.'),
|
|
798
|
+
current_support: AgentSupportSchema.optional().describe('Agent target only: the same classification for the installed Agent revision.'),
|
|
799
|
+
supported_revision: z.string().optional(), supported_version: z.string().optional(), candidate_revision: z.string().optional(), behind: z.number().nullable().optional(), current_sha: z.string().nullable().optional(), latest_sha: z.string().nullable().optional(), compare_url: z.string().optional(), repo_url: z.string().optional(), error: z.string().optional(), ok: z.boolean().optional(), manual_update: z.boolean().optional(), no_git: z.boolean().optional(), install_kind: z.literal('npm').optional(), npm: z.string().optional(), channel_switch: z.boolean().optional(), dirty: z.boolean().optional(), metadata_repair: z.boolean().optional(), release_url: z.string().optional(), ignored: z.boolean().optional(), stale_check: z.boolean().optional(), current_version: z.string().optional(),
|
|
567
800
|
state: UpdateStateSchema.describe('TAL-559: the status clients word; `off` when checks are disabled or Agent updates are ignored.'),
|
|
568
801
|
can_apply: z.boolean().describe('The apply action is available for this target.'),
|
|
569
802
|
installed_unverified: z.boolean().describe('`release_ready` only: the installed revision sits on no release tag.'),
|
|
570
803
|
manual_link: z.boolean().describe('Show the manual-install (releases) link.'),
|
|
571
804
|
target_version: z.string().nullable().describe('The version the update path leads to, when one is shown.'),
|
|
805
|
+
summary_available: z.boolean().describe('TAL-759: offer "Summarize with AI" for this target (`release_ready` or `commits_behind`).'),
|
|
806
|
+
versions: z.array(UpdateVersionSchema).describe('TAL-946: every installable Stable release newer than the installed one, newest first; empty unless `release_ready` can apply.'),
|
|
807
|
+
folded_count: z.number().int().nonnegative().describe('How many `versions` are `folded`.'),
|
|
808
|
+
});
|
|
809
|
+
export const AgentRecoveryStateSchema = z.object({ phase: z.enum(['idle', 'running', 'waiting', 'complete', 'blocked']), attempt: z.number().int().nonnegative(), detail: z.string(), retry_at: z.string().nullable() });
|
|
810
|
+
export const UpdatesCheckSchema = z.looseObject({ agent_recovery: AgentRecoveryStateSchema.optional(), disabled: z.boolean().optional(), cached: z.boolean().optional(), channel: z.string().optional(), agent_channel: z.enum(['stable', 'experimental']).optional(), checked_at: z.number().optional(), include_agent: z.boolean().optional(), webui: UpdateTargetSchema.nullable().optional(), agent: UpdateTargetSchema.nullable().optional() });
|
|
811
|
+
export const UpdatesSummarySchema = z.object({
|
|
812
|
+
ok: z.boolean(), target: z.enum(['webui', 'agent']), summary: z.string(),
|
|
813
|
+
current_version: z.string().nullable().describe('The installed version this summary starts from.'),
|
|
814
|
+
target_version: z.string().nullable().describe('The version this summary leads to, when the update names one.'),
|
|
815
|
+
summary_sections: z.array(z.object({ title: z.string(), items: z.array(z.string()) })).describe('Display-ready headed bullet lists; empty when nothing is pending.'),
|
|
816
|
+
generated_by: z.enum(['llm', 'fallback', 'none']).describe('`fallback` when no model answered; `none` when the target has no pending update to summarize.'),
|
|
817
|
+
source: z.enum(['release_notes', 'commits', 'none']).describe('Stable targets summarize the release notes they install; commit-tracking targets, or unreadable notes, use commit subjects.'),
|
|
818
|
+
cached: z.boolean(),
|
|
819
|
+
});
|
|
820
|
+
export const UpdateApplySchema = z.looseObject({
|
|
821
|
+
recovery_compatibility: z.object({ manual_execution: z.boolean(), bot_chat_delivery: z.boolean() }).optional()
|
|
822
|
+
.describe('Whether the target Agent can reconcile retained manual execution and pending Bot Chat records. A false value blocks the update before any source or repair-intent change.'),
|
|
823
|
+
ok: z.boolean().optional(), status: z.string().optional(), error: z.string().optional(), message: z.string().optional(), lock: Json.optional(), confirmation_required: z.boolean().optional(), refresh_confirmation: AgentRefreshConfirmationSchema.optional(), candidate_revision: z.string().optional(), supported_revision: z.string().optional(), supported_version: z.string().optional(), agent_channel: z.enum(['stable', 'experimental']).optional(), notification_id: z.uuid().optional(), channel_switch: z.boolean().optional(), backup_dir: z.string().nullable().optional(), backup_failed: z.boolean().optional(), stash_conflict: z.boolean().optional(), gateway_restart: z.string().optional().describe('TAL-953: `waiting_for_idle` when an Agent update left the gateway restart to wait for the gateway\'s running work; the update notification reports its outcome.')
|
|
572
824
|
});
|
|
573
|
-
export const
|
|
574
|
-
export const UpdatesSummarySchema = z.looseObject({ summary: z.string().optional(), text: z.string().optional(), ok: z.boolean().optional(), error: z.string().optional(), diff_links: z.array(Json).optional() });
|
|
575
|
-
export const UpdateApplySchema = z.looseObject({ ok: z.boolean().optional(), status: z.string().optional(), error: z.string().optional(), message: z.string().optional(), lock: Json.optional(), confirmation_required: z.boolean().optional(), candidate_revision: z.string().optional(), supported_revision: z.string().optional(), supported_version: z.string().optional(), agent_channel: z.enum(['stable', 'experimental']).optional(), notification_id: z.uuid().optional(), channel_switch: z.boolean().optional(), backup_dir: z.string().nullable().optional(), backup_failed: z.boolean().optional(), stash_conflict: z.boolean().optional() });
|
|
576
|
-
export const UpdateNotificationPhaseSchema = z.enum(['applying', 'awaiting_confirmation', 'restarting', 'succeeded', 'blocked', 'failed', 'unknown']);
|
|
825
|
+
export const UpdateNotificationPhaseSchema = z.enum(['applying', 'awaiting_confirmation', 'waiting_for_idle', 'restarting', 'succeeded', 'blocked', 'failed', 'unknown']);
|
|
577
826
|
export const UpdateNotificationActionSchema = z.object({
|
|
578
827
|
id: z.string().min(1).max(64).regex(/^[a-z0-9][a-z0-9_-]*$/),
|
|
579
828
|
label: z.string().min(1).max(80),
|
|
@@ -631,12 +880,72 @@ export const UpdateNotificationsSchema = z.object({
|
|
|
631
880
|
clearable_count: z.number().int().nonnegative(),
|
|
632
881
|
can_clear: z.boolean(),
|
|
633
882
|
});
|
|
634
|
-
|
|
635
|
-
export const
|
|
883
|
+
/** TAL-806: a plugin setting as Settings shows it; `locked` marks a secret the server's launch environment supplies, so an edit would not take effect. */
|
|
884
|
+
export const PluginSettingViewSchema = PluginSettingFieldSchema.extend({ locked: z.boolean().optional() });
|
|
885
|
+
export const PluginSchema = z.looseObject({ key: z.string(), name: z.string().optional(), kind: z.string().optional(), enabled: z.boolean().optional(), description: z.string().optional(), version: z.string().optional(), activation: z.string().optional(), is_active_provider: z.boolean().optional(), hooks: z.array(Json).optional(),
|
|
886
|
+
/** TAL-806: the manifest's `config_schema` fields with current values; absent when the plugin declares none. */
|
|
887
|
+
settings: z.array(PluginSettingViewSchema).optional() });
|
|
888
|
+
/**
|
|
889
|
+
* `read_only` (TAL-806): this session may not save plugin `settings` (not the server owner, or no sidecar).
|
|
890
|
+
* `plugin_isolation_advisory` (TAL-820): more than one profile has third-party plugins installed and one of those runs them
|
|
891
|
+
* `in_process`, so Settings recommends `plugins.isolation: host`; Talaria never sets the mode.
|
|
892
|
+
*/
|
|
893
|
+
export const PluginsSchema = z.looseObject({ plugins: z.array(PluginSchema), empty: z.boolean().optional(), read_only: z.boolean().optional(), supported_hooks: z.array(z.string()).optional(), unavailable: z.boolean().optional(), plugin_isolation_advisory: z.boolean().optional() });
|
|
636
894
|
export const McpServerSchema = z.looseObject({ name: z.string(), id: z.string().optional(), transport: z.string().optional(), enabled: z.boolean().optional(), can_toggle: z.boolean().optional().describe('Whether PATCH can enable or disable this server; false for invalid config.'), active: z.boolean().optional(), status: z.string().optional(), tools: z.number().optional(), tool_count: z.number().int().nullable().optional(), health: z.string().optional(), health_detail: z.string().optional(), health_checked_at: Json.optional(), health_pending: z.boolean().optional() });
|
|
637
895
|
export const McpServersSchema = z.looseObject({ servers: z.array(McpServerSchema), health_pending: z.boolean().optional(), reload_required: z.boolean().optional(), toggle_supported: z.boolean().optional() });
|
|
896
|
+
/** TAL-818: one connected account of a Nous tool-gateway app; `name` is its alias, else the vendor label. `problem` is its gateway status while it is not active, else null. */
|
|
897
|
+
export const ConnectorAccountViewSchema = z.object({ connection_id: z.string(), name: z.string(), problem: z.enum(['pending', 'failed', 'expired', 'revoked', 'inactive']).nullable(), status_reason: z.string().nullable(), active: z.boolean(), created_at: z.string() });
|
|
898
|
+
/**
|
|
899
|
+
* TAL-818: one app on the Connectors page. `accounts` are its live accounts, active first. `enabled`: Hermes may use it (the
|
|
900
|
+
* member rule allows it and no other layer locks it). `org_locked` means an organization or role rule keeps it off whatever the member rule says. `rules_editable`: the switch
|
|
901
|
+
* may change the member rule (readable rules and no lock). `tools_off` counts the tools the member rules turn off.
|
|
902
|
+
*/
|
|
903
|
+
export const ConnectorViewSchema = z.object({
|
|
904
|
+
slug: z.string(), name: z.string(), description: z.string(), category: z.string(), logo_url: z.string().nullable(),
|
|
905
|
+
connected: z.boolean(), accounts: z.array(ConnectorAccountViewSchema), enabled: z.boolean(), org_locked: z.boolean(), rules_editable: z.boolean(), tools_off: z.number().int(),
|
|
906
|
+
});
|
|
907
|
+
/**
|
|
908
|
+
* TAL-818: the Connectors page. `available` is the Agent's connectors gate; false hides the page. `policy_revision` is the
|
|
909
|
+
* member rules' revision every rule change sends back; null when the rules are read-only (no member layer, or unreadable),
|
|
910
|
+
* so no switch changes them. `rules_error`: why the rules could not be read; every app then reads off (fails closed).
|
|
911
|
+
*/
|
|
912
|
+
export const ConnectorsPageSchema = z.object({ available: z.boolean(), connectors: z.array(ConnectorViewSchema), policy_revision: z.string().nullable(), rules_error: z.string().nullable() });
|
|
913
|
+
/**
|
|
914
|
+
* TAL-818: one app's tools: `enabled`: Hermes may use it (the member rules leave it on and nothing locks it); `locked`: an
|
|
915
|
+
* organization or role rule (by name or tag) keeps it off. `editable`: its switch may change the member rule (readable rules, the app on in them, and no lock).
|
|
916
|
+
*/
|
|
917
|
+
export const ConnectorToolsViewSchema = z.object({
|
|
918
|
+
connector: z.string(), policy_revision: z.string().nullable(),
|
|
919
|
+
tools: z.array(z.object({ slug: z.string(), name: z.string(), description: z.string(), facet: z.enum(['read', 'write', 'destructive', 'unclassified']), deprecated: z.boolean(), enabled: z.boolean(), locked: z.boolean(), editable: z.boolean() })),
|
|
920
|
+
});
|
|
921
|
+
/**
|
|
922
|
+
* TAL-818: a connection operation, from the Connectors page's Connect or a chat's `manage_connections` card. Each target's
|
|
923
|
+
* `connect_url` is the authorization link while it waits on one; `actions` are the moves the user may make on it now, and
|
|
924
|
+
* `env_fields` the credentials an `approve` sends, each with its `label`. `can_continue`: the card may end the wait for the
|
|
925
|
+
* rest (chat only). `outcome` is null while the operation is open, then `connected` when every target connected.
|
|
926
|
+
*/
|
|
927
|
+
export const ConnectorOperationViewSchema = z.object({
|
|
928
|
+
op_id: z.string(), settled: z.boolean(), outcome: z.enum(['connected', 'not_connected']).nullable(), can_continue: z.boolean(), tool_call_id: z.string().nullable(),
|
|
929
|
+
targets: z.array(z.object({
|
|
930
|
+
name: z.string(), title: z.string(), kind: z.string(), state: z.enum(['pending', 'initiated', 'connected', 'skipped', 'failed', 'expired', 'not_connected']),
|
|
931
|
+
detail: z.string(), connect_url: z.string().nullable(), actions: z.array(z.enum(['skip', 'retry', 'approve'])),
|
|
932
|
+
env_fields: z.array(z.object({ name: z.string(), label: z.string(), required: z.boolean(), secret: z.boolean() })),
|
|
933
|
+
})),
|
|
934
|
+
});
|
|
638
935
|
export const McpToolsSchema = z.looseObject({ tools: z.array(z.looseObject({ name: z.string().optional(), server: z.string().optional(), description: z.string().optional() })), total: z.number().int().optional(), source: z.string().optional(), inventory_scope: z.string().optional(), unavailable_servers: z.array(z.string()).optional() });
|
|
639
936
|
export const NotesSourcesSchema = z.looseObject({ enabled: z.boolean().optional(), sources: z.array(Json).optional(), source: z.string().optional(), inventory_scope: z.string().optional(), recent_ai_notes: z.array(Json).optional(), attach_supported: z.boolean().optional(), automatic_recall_unchanged: z.boolean().optional() });
|
|
937
|
+
/** Joplin search hit: bounded, redacted display text and a snippet around the query; `updated_time` is Joplin's raw value. */
|
|
938
|
+
export const NoteSearchResultSchema = z.object({ id: z.string(), title: z.string(), snippet: z.string(), parent_id: z.string(), updated_time: Json, source: z.literal('joplin') });
|
|
939
|
+
export const NotesSearchSchema = z.object({ source: z.literal('joplin'), query: z.string(), results: z.array(NoteSearchResultSchema) });
|
|
940
|
+
/** One Joplin note for preview: `body` is cut at 50,000 characters (with a notice) and redacted. */
|
|
941
|
+
export const NoteItemSchema = z.object({ source: z.literal('joplin'), note: z.object({ id: z.string(), title: z.string(), body: z.string(), parent_id: z.string(), updated_time: Json, created_time: Json, source: z.literal('joplin') }) });
|
|
942
|
+
/** LLM wiki summary: counts and timestamps only, never page bodies or the wiki path. `error` names the exception type when `status` is `error`. */
|
|
943
|
+
export const WikiStatusSchema = z.object({
|
|
944
|
+
available: z.boolean(), enabled: z.boolean(), status: z.enum(['missing', 'not_directory', 'ready', 'empty', 'error']), entry_count: z.number().int(), page_count: z.number().int(), raw_source_count: z.number().int(),
|
|
945
|
+
last_updated: z.string().nullable(), last_writer: z.string(), path_configured: z.boolean(), path_source: z.string(), toggle_available: z.literal(false), toggle_reason: z.string(), docs_url: z.string(), error: z.string().optional(),
|
|
946
|
+
});
|
|
947
|
+
export const WikiBrowseSchema = z.object({ pages: z.array(z.object({ name: z.string(), path: z.string(), size: z.number().int(), mtime: z.number().int() })) });
|
|
948
|
+
export const WikiPageSchema = z.object({ content: z.string(), path: z.string() });
|
|
640
949
|
export const TodoItemSchema = z.looseObject({ id: z.union([z.string(), z.number()]).optional(), text: z.string().optional(), content: z.string().optional(), title: z.string().optional(), status: z.string().optional(), done: z.boolean().optional(), completed: z.boolean().optional() });
|
|
641
950
|
export const TodoStateSchema = z.looseObject({ session_id: z.string().optional(), todos: z.array(TodoItemSchema).optional(), summary: z.record(z.string(), z.unknown()).optional(), version: z.number().optional(), ts: z.number().optional(), source: z.string().optional(), description: z.string().optional(), pending_count: z.number().optional() });
|
|
642
951
|
// ── onboarding ───────────────────────────────────────────────────────────
|
|
@@ -674,8 +983,20 @@ export const CronJobViewSchema = z.looseObject({
|
|
|
674
983
|
context_from: z.union([z.array(z.string()), z.string(), z.null()]).optional(), reasoning_effort: NullableString.optional(), toast_notifications: z.boolean().optional(), running: z.boolean().optional(),
|
|
675
984
|
/** Server-derived (TAL-296): the job's status, whether it needs attention, and whether its primary action is Resume. Live runs overlay it. */
|
|
676
985
|
derived_state: CronDerivedStateSchema.optional(), needs_attention: z.boolean().optional(), resumable: z.boolean().optional(),
|
|
986
|
+
/** Server-derived (TAL-599): a known cause clients explain in the needs-attention banner. */
|
|
987
|
+
attention_hint: z.enum(['croniter_missing']).nullable(),
|
|
988
|
+
/** Server-normalized (TAL-810): the job's latest failed run, kept after later successes; `at` is epoch seconds, null when unparseable. */
|
|
989
|
+
last_failure: z.object({ at: z.number().nullable(), detail: z.string() }).nullable(),
|
|
990
|
+
});
|
|
991
|
+
/** TAL-810: a listed profile's cron store whose writes fail (full disk, read-only mount, permissions), so its scheduler skips every run. `error` and `fix` are the Agent's text; `since` is the last write that landed (epoch seconds), null when unknown. */
|
|
992
|
+
export const CronStoreHealthSchema = z.object({ profile: z.string(), store: z.string(), error: z.string(), fix: z.string(), since: z.number().nullable() });
|
|
993
|
+
export const CronsSchema = z.looseObject({
|
|
994
|
+
jobs: z.array(CronJobViewSchema),
|
|
995
|
+
/** TAL-601: `jobs` arrive in display order (running first, then soonest next run, none last, then name); clients keep it. Absent from older servers. */
|
|
996
|
+
ordered: z.boolean().optional(),
|
|
997
|
+
active_profile: z.string().optional(), all_profiles: z.boolean().optional(), other_profile_count: z.number().optional(), cron_unavailable: z.boolean().optional(),
|
|
998
|
+
unwritable_stores: z.array(CronStoreHealthSchema),
|
|
677
999
|
});
|
|
678
|
-
export const CronsSchema = z.looseObject({ jobs: z.array(CronJobViewSchema), active_profile: z.string().optional(), all_profiles: z.boolean().optional(), other_profile_count: z.number().optional(), cron_unavailable: z.boolean().optional() });
|
|
679
1000
|
export const CronContextSourcesSchema = z.object({ profile: z.string(), sources: z.array(z.object({ job_id: z.string(), label: z.string(), selectable: z.boolean() })) });
|
|
680
1001
|
/** `GET /api/crons/recent` row: one job's latest completion, ordered and classified by the server. */
|
|
681
1002
|
export const CronRecentCompletionSchema = z.object({
|
|
@@ -687,25 +1008,29 @@ export const CronMutationSchema = z.looseObject({ ok: z.boolean().optional(), jo
|
|
|
687
1008
|
export const CronRunUsageSchema = z.looseObject({ input_tokens: NullableNumber.optional(), output_tokens: NullableNumber.optional(), total_tokens: NullableNumber.optional(), estimated_cost_usd: NullableNumber.optional(), duration_seconds: NullableNumber.optional(), model: z.string().optional(), provider: z.string().optional() });
|
|
688
1009
|
export const CronRunSummarySchema = z.looseObject({ filename: z.string(), size: z.number(), modified: z.number(), usage: CronRunUsageSchema.optional() });
|
|
689
1010
|
export const CronHistorySchema = z.looseObject({ job_id: z.string().optional(), runs: z.array(CronRunSummarySchema), total: z.number().optional(), offset: z.number().optional() });
|
|
690
|
-
|
|
1011
|
+
/** `response` is server-extracted (TAL-599): the agent's reply after the run file's `## Response` heading, else the whole text. */
|
|
1012
|
+
export const CronRunSchema = z.looseObject({ content: z.string().optional(), snippet: z.string().optional(), response: z.string().optional(), usage: CronRunUsageSchema.optional(), error: z.string().optional() });
|
|
691
1013
|
export const CronStatusSchema = z.looseObject({ running: z.union([z.boolean(), z.record(z.string(), z.number())]).optional() });
|
|
692
1014
|
/** Card actions the server offers for a task's current status (TAL-557); clients show exactly these. `move_to` lists the statuses a Move may target, in display order. */
|
|
693
1015
|
export const KanbanTaskActionsSchema = z.object({ block: z.boolean(), unblock: z.boolean(), complete: z.boolean(), archive: z.boolean(), move_to: z.array(z.string()) });
|
|
694
1016
|
/** Server-computed card policy on every task the Kanban routes return (TAL-557). `requires_running_exit_confirmation`: any action takes the task out of a live run, so clients confirm first. */
|
|
695
1017
|
export const KanbanTaskPolicyShape = { available_actions: KanbanTaskActionsSchema, requires_running_exit_confirmation: z.boolean() };
|
|
696
1018
|
export const KanbanTaskViewSchema = z.looseObject({ id: z.union([z.string(), z.number()]), title: z.string().optional(), status: z.string().optional(), assignee: NullableString.optional(), priority: z.union([z.string(), z.number()]).nullable().optional(), description: z.string().optional(), tags: z.array(z.string()).optional(), session_id: NullableString.optional(), archived: z.boolean().optional(), created_at: Json.optional(), updated_at: Json.optional(), ...KanbanTaskPolicyShape });
|
|
697
|
-
|
|
1019
|
+
/** A board column in the Agent workflow's order (TAL-796): `name` is the status key, `label` the Agent's English label. */
|
|
1020
|
+
export const KanbanColumnSchema = z.looseObject({ name: z.string(), label: z.string(), tasks: z.array(KanbanTaskViewSchema) });
|
|
698
1021
|
/** One profile lane (TAL-567): an assignee's tasks (`null` = unassigned) across every board column, with its task count. */
|
|
699
1022
|
export const KanbanLaneSchema = z.object({ assignee: z.string().nullable(), count: z.number().int(), columns: z.array(KanbanColumnSchema) });
|
|
700
1023
|
export const KanbanBoardViewSchema = z.looseObject({ columns: z.array(KanbanColumnSchema).optional(), assignees: z.array(Json).optional(), filters: Json.optional(), latest_event_id: z.number().optional(), read_only: z.boolean().optional(), tenants: z.array(Json).optional(), changed: z.boolean().optional(),
|
|
701
1024
|
/** Statuses a bulk status change may target (TAL-557). */
|
|
702
1025
|
bulk_move_targets: z.array(z.string()),
|
|
1026
|
+
/** Statuses a new task may start in (TAL-796). */
|
|
1027
|
+
create_statuses: z.array(z.string()),
|
|
703
1028
|
/** The saved board view (TAL-567): `true` groups the board into `lanes` by assignee. */
|
|
704
1029
|
lane_by_profile: z.boolean(),
|
|
705
1030
|
/** Present when `lane_by_profile`: the columns split into profile lanes, assignees in name order, unassigned last. */
|
|
706
1031
|
lanes: z.array(KanbanLaneSchema).optional() });
|
|
707
1032
|
export const KanbanBoardsViewSchema = z.looseObject({ boards: z.array(z.looseObject({ slug: z.string(), name: z.string().nullable().optional(), is_current: z.boolean().optional(), total: z.number().optional(), archived: z.boolean().optional(), color: z.string().optional(), icon: z.string().optional(), description: z.string().optional(),
|
|
708
|
-
/** Whether the board can be archived or deleted; the default board
|
|
1033
|
+
/** Whether the board can be archived or deleted; the default board (TAL-567) and an archived board (TAL-795) cannot. */
|
|
709
1034
|
removable: z.boolean() })), current: z.string().optional(), read_only: z.boolean().optional() });
|
|
710
1035
|
/** Board-wide task counts (TAL-567): `status_counts` in board-column order, unknown statuses after; `total` excludes archived tasks. */
|
|
711
1036
|
export const KanbanStatsViewSchema = z.looseObject({ by_status: z.record(z.string(), z.number()), total: z.number().int(), status_counts: z.array(z.object({ status: z.string(), count: z.number().int() })) });
|