@maudecode/talaria-web-contracts 1.18.0 → 1.20.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/context-detail.d.ts +75 -0
- package/dist/context-detail.js +18 -0
- package/dist/context-detail.js.map +1 -0
- package/dist/gateway-session.d.ts +475 -0
- package/dist/gateway-session.js +106 -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 +4 -0
- package/dist/openapi.js.map +1 -1
- package/dist/router.d.ts +5503 -251
- package/dist/routes/automation.d.ts +100 -18
- package/dist/routes/automation.js +7 -4
- package/dist/routes/automation.js.map +1 -1
- package/dist/routes/chat.d.ts +1605 -47
- package/dist/routes/chat.js +7 -2
- package/dist/routes/chat.js.map +1 -1
- package/dist/routes/core.d.ts +15 -4
- package/dist/routes/core.js +2 -2
- package/dist/routes/core.js.map +1 -1
- package/dist/routes/git.d.ts +9 -0
- package/dist/routes/git.js +6 -1
- package/dist/routes/git.js.map +1 -1
- package/dist/routes/raw.js +10 -6
- package/dist/routes/raw.js.map +1 -1
- package/dist/routes/sessions.d.ts +3189 -181
- package/dist/routes/sessions.js +24 -7
- package/dist/routes/sessions.js.map +1 -1
- package/dist/routes/settings.d.ts +445 -11
- package/dist/routes/settings.js +5 -4
- package/dist/routes/settings.js.map +1 -1
- package/dist/routes/tools.d.ts +945 -34
- package/dist/routes/tools.js +75 -8
- package/dist/routes/tools.js.map +1 -1
- package/dist/routes/workspaces.d.ts +4 -4
- 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 +1906 -52
- package/dist/sidecar/methods.js +9 -2
- package/dist/sidecar/methods.js.map +1 -1
- package/dist/sidecar/namespaces.d.ts +2421 -54
- package/dist/sidecar/namespaces.js +390 -36
- package/dist/sidecar/namespaces.js.map +1 -1
- package/dist/sidecar/rpc.d.ts +1 -0
- package/dist/sidecar/rpc.js +2 -0
- package/dist/sidecar/rpc.js.map +1 -1
- package/dist/sidecar/runtime.d.ts +74 -0
- package/dist/sidecar/runtime.js +29 -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 +868 -5
- package/dist/sse.js +30 -7
- package/dist/sse.js.map +1 -1
- 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 +2627 -176
- package/dist/views.js +321 -52
- package/dist/views.js.map +1 -1
- package/fixtures/sidecar/aux.json +142 -0
- package/fixtures/sidecar/chat.json +28 -0
- package/fixtures/sidecar/checkpoints.json +12 -7
- package/fixtures/sidecar/commands.json +216 -108
- package/fixtures/sidecar/config.json +15 -0
- package/fixtures/sidecar/connectors.json +218 -0
- package/fixtures/sidecar/context-detail.json +77 -0
- package/fixtures/sidecar/cron.json +1004 -32
- package/fixtures/sidecar/dashboard_plugins.json +59 -0
- package/fixtures/sidecar/gateway.json +202 -0
- package/fixtures/sidecar/goals.json +5 -3
- package/fixtures/sidecar/kanban.json +139 -49
- package/fixtures/sidecar/memory.json +50 -0
- package/fixtures/sidecar/models.json +122 -0
- package/fixtures/sidecar/personalities.json +92 -0
- package/fixtures/sidecar/plugin-catalog.json +4 -0
- package/fixtures/sidecar/plugins.json +171 -27
- package/fixtures/sidecar/process.json +63 -0
- package/fixtures/sidecar/profiles.json +2 -0
- package/fixtures/sidecar/providers.json +14 -1
- package/fixtures/sidecar/rpc.json +39 -1
- package/fixtures/sidecar/runtime.json +130 -14
- package/fixtures/sidecar/skills.json +256 -13
- package/fixtures/sidecar/state_db.json +29 -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 +22 -2
- package/fixtures/sidecar/write_approval.json +98 -0
- package/package.json +1 -1
package/dist/views.js
CHANGED
|
@@ -5,7 +5,12 @@
|
|
|
5
5
|
* that must survive a round trip (documented passthrough).
|
|
6
6
|
*/
|
|
7
7
|
import { z } from 'zod';
|
|
8
|
-
import {
|
|
8
|
+
import { RunStatusSchema } from './run-status.js';
|
|
9
|
+
import { AgentRefreshConfirmationSchema } from './sidecar/runtime.js';
|
|
10
|
+
import { SpeedTierSchema } from './speed.js';
|
|
11
|
+
import { ExecutionModeSchema, OwnerAttachmentSchema } from './gateway-session.js';
|
|
12
|
+
import { CanonicalBotChatSchema, GatewayModeSchema, PluginOAuthClientSchema, PluginSettingFieldSchema, SkillCatalogIdentitySchema } from './sidecar/namespaces.js';
|
|
13
|
+
export { SpeedTierSchema } from './speed.js';
|
|
9
14
|
const Json = z.unknown();
|
|
10
15
|
export const NullableString = z.string().nullable();
|
|
11
16
|
export const NullableNumber = z.number().nullable();
|
|
@@ -38,8 +43,10 @@ export const DiffHunkSchema = z.object({
|
|
|
38
43
|
* that diff parsed (TAL-604). Absent on a call whose result has no diff.
|
|
39
44
|
*/
|
|
40
45
|
export const ToolEditDiffSchema = z.object({ added: z.number().int(), removed: z.number().int(), diff: z.string(), truncated: z.boolean(), hunks: z.array(DiffHunkSchema) });
|
|
41
|
-
/**
|
|
42
|
-
export const
|
|
46
|
+
/** The latest server-normalized MCP update; never stored with the transcript. */
|
|
47
|
+
export const ToolProgressSchema = z.object({ percent: z.number().min(0).max(100).nullable(), message: z.string().nullable() });
|
|
48
|
+
/** Shared tool display fields. Progress is ephemeral, absent on older servers and null after completion. */
|
|
49
|
+
export const ToolDisplayFields = { progress: ToolProgressSchema.nullable().optional(), kind: ToolKindSchema.optional(), target: z.string().optional(), edit_diff: ToolEditDiffSchema.optional() };
|
|
43
50
|
/**
|
|
44
51
|
* TAL-315: a tool result's display sections, decided by the server's one rule for live, replayed and persisted results
|
|
45
52
|
* alike. Clients show `stdout`, `stderr`, a labelled `error` and a labelled `exit_code` (sent only when worth showing), or
|
|
@@ -100,8 +107,8 @@ export const TurnFileChangeSchema = z.looseObject({ path: z.string(), action: z.
|
|
|
100
107
|
export const TurnTerminalStateSchema = z.enum(['completed', 'no_response', 'cancelled', 'interrupted', 'tool_limit_reached', 'compression_exhausted', 'error']);
|
|
101
108
|
export const ActivitySceneSchema = z.looseObject({
|
|
102
109
|
version: z.literal('activity_scene_v1'), activity_rows: z.array(ActivitySceneRowSchema), final_answer: z.string().optional(),
|
|
103
|
-
/** TAL-456:
|
|
104
|
-
final_answer_excerpt: z.string().optional(), turn_duration: z.number().nullable().optional(),
|
|
110
|
+
/** 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". */
|
|
111
|
+
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(),
|
|
105
112
|
/** TAL-186: `final_answer` with its media references rewritten for display (see `_display_content`), and its media. */
|
|
106
113
|
final_answer_display: z.string().optional(), final_answer_media: z.array(DisplayMediaSchema).optional(),
|
|
107
114
|
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.'),
|
|
@@ -115,8 +122,13 @@ export const ActivitySceneSchema = z.looseObject({
|
|
|
115
122
|
file_changes: z.array(TurnFileChangeSchema).optional(),
|
|
116
123
|
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(),
|
|
117
124
|
});
|
|
118
|
-
/**
|
|
119
|
-
export const
|
|
125
|
+
/** The server-owned result-review lifecycle (TAL-1022). */
|
|
126
|
+
export const BackgroundReviewStateSchema = z.enum(['waiting', 'reviewing', 'reviewed', 'failed', 'unknown']);
|
|
127
|
+
/** One finished background item (see `_background_update.lines`). */
|
|
128
|
+
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(),
|
|
129
|
+
/** Server-composed worker and parent outcome. Failure/unknown worker outcomes take precedence. */
|
|
130
|
+
review_state: BackgroundReviewStateSchema.optional(),
|
|
131
|
+
});
|
|
120
132
|
export const MessageSchema = z.looseObject({
|
|
121
133
|
role: z.string(), content: MessageContentSchema.optional(), id: MessageIdSchema.optional(), message_id: MessageIdSchema.optional(), timestamp: z.number().nullable().optional(),
|
|
122
134
|
attachments: z.array(AttachmentSchema).optional(), tool_calls: z.array(ToolCallSchema).optional(),
|
|
@@ -144,9 +156,9 @@ export const MessageSchema = z.looseObject({
|
|
|
144
156
|
_steer: z.looseObject({ steer_id: z.string(), submitted_at: z.number().nullable().optional(), consumed_at: z.number().optional(), phase_duration: z.number().optional() }).optional(),
|
|
145
157
|
/** On a steered turn's last reply: seconds from the last consumed steer to the turn's end. */
|
|
146
158
|
_final_phase_duration: z.number().optional(),
|
|
147
|
-
/** A settled body too long to lay out whole
|
|
148
|
-
_display_truncated: z.boolean().optional(),
|
|
149
|
-
_display_excerpt: z.string().optional(),
|
|
159
|
+
/** 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`. */
|
|
160
|
+
_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."),
|
|
161
|
+
_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."),
|
|
150
162
|
/**
|
|
151
163
|
* TAL-452: a typed user message (never a steer, background update or marker) longer than 20 lines or 2,000
|
|
152
164
|
* characters. Clients show it folded to a few lines with a local "Show more"; copy and edit use the whole `content`.
|
|
@@ -168,11 +180,13 @@ export const MessageSchema = z.looseObject({
|
|
|
168
180
|
_background_update: z.object({
|
|
169
181
|
kind: z.enum(['delegation', 'process', 'mixed', 'other']), attention: z.boolean(), count: z.number().int().positive(), summary: z.string(),
|
|
170
182
|
/**
|
|
171
|
-
*
|
|
172
|
-
*
|
|
173
|
-
* `
|
|
183
|
+
* One completion line per finished item. Clients show its label and exactly one leading icon from `review_state`,
|
|
184
|
+
* with localized accessible/help wording. Parent review never overrides failed/unknown worker outcomes.
|
|
185
|
+
* `content` stays available in full on expansion.
|
|
174
186
|
*/
|
|
175
187
|
lines: z.array(BackgroundLineSchema),
|
|
188
|
+
/** Parent review only, established from admission, the live run, and terminal evidence. */
|
|
189
|
+
review_state: BackgroundReviewStateSchema.optional(),
|
|
176
190
|
}).optional(),
|
|
177
191
|
/**
|
|
178
192
|
* TAL-305: a marker the Agent wrote around context compaction, not a message anyone typed. Clients render a collapsed
|
|
@@ -181,6 +195,19 @@ export const MessageSchema = z.looseObject({
|
|
|
181
195
|
_marker_kind: z.enum(['context_compaction', 'preserved_task_list']).optional(),
|
|
182
196
|
/** TAL-305: a preserved task list's card body, without its marker line. */
|
|
183
197
|
_marker_body: z.string().optional(),
|
|
198
|
+
/**
|
|
199
|
+
* TAL-815: an assistant row the Agent wrote as a notice, not the model's reply. `failed_turn`: the boundary closing a
|
|
200
|
+
* turn that failed, with its copy in `content`. Clients show it as a notice in its place, never as a reply bubble or
|
|
201
|
+
* part of a turn's reply; it is absent when Web's own error row already reports that turn. `session_finalize` is
|
|
202
|
+
* a plugin's closing text after clear, with role `local_notice`, display-only and excluded from model history.
|
|
203
|
+
*/
|
|
204
|
+
_notice_kind: z.enum(['failed_turn', 'session_finalize']).optional(),
|
|
205
|
+
/**
|
|
206
|
+
* TAL-816: a user row of a messaging session that the Agent's gateway mirrored after a webhook route's or cron job's
|
|
207
|
+
* delivery to the chat, not a message the user sent. Clients show it as a delivery notice titled by a localized label
|
|
208
|
+
* per `kind` with `name`, and `body` (the delivered text, without its label line) beneath, never as a user bubble.
|
|
209
|
+
*/
|
|
210
|
+
_delivery: z.object({ kind: z.enum(['webhook', 'cron']), name: z.string(), body: z.string() }).optional(),
|
|
184
211
|
/** TAL-460: part of the Agent's reply to the background update just before it in the same turn. */
|
|
185
212
|
_background_reply: z.boolean().optional(),
|
|
186
213
|
/** TAL-460: that reply is only a silence marker; clients show the update's lines and nothing of this turn's reply. */
|
|
@@ -201,6 +228,23 @@ export const PendingSteerSchema = z.object({
|
|
|
201
228
|
steer_id: z.string(), text: z.string(), submitted_at: z.number(), state: z.enum(['pending', 'sending_now']),
|
|
202
229
|
actions: z.object({ edit: z.boolean(), cancel: z.boolean(), send_now: z.boolean() }),
|
|
203
230
|
});
|
|
231
|
+
/**
|
|
232
|
+
* TAL-803: an out-of-band notice the Agent raised for the session (a memory provider that failed to load, credit and
|
|
233
|
+
* usage warnings), one per `key`. The server keeps it until the Agent clears that key, `expires_at` passes, or a new agent
|
|
234
|
+
* replaces the one that raised it.
|
|
235
|
+
*/
|
|
236
|
+
export const SessionNoticeSchema = z.object({
|
|
237
|
+
key: z.string(), level: z.enum(['info', 'warn', 'error', 'success']), text: z.string(),
|
|
238
|
+
expires_at: NullableNumber.describe('Unix seconds when the server drops it; null when only the Agent clears it.'),
|
|
239
|
+
});
|
|
240
|
+
/**
|
|
241
|
+
* TAL-808: the session's standing `/goal` while it runs, from the Agent's goal state. `parked` is an active goal waiting on
|
|
242
|
+
* a process or a timer; `reason` is why it is paused or what it waits on. A done, cleared or absent goal is null.
|
|
243
|
+
*/
|
|
244
|
+
export const SessionGoalSchema = z.object({
|
|
245
|
+
text: z.string(), status: z.enum(['active', 'paused', 'parked']), turns_used: z.number().int().nonnegative(), max_turns: z.number().int().nonnegative(),
|
|
246
|
+
reason: NullableString, parked_until: NullableNumber.describe('Unix seconds a timed park ends; null otherwise.'),
|
|
247
|
+
});
|
|
204
248
|
/**
|
|
205
249
|
* TAL-299: the context ring, computed by the server. `context_used_tokens` is the post-compression estimate, else the last
|
|
206
250
|
* prompt (never the cumulative `input_tokens`); `context_window_tokens` is the model's window. The percents are rounded
|
|
@@ -215,12 +259,13 @@ export const ContextUsageFields = {
|
|
|
215
259
|
const ActiveTurnOriginSchema = z.enum(['user', 'background']).nullable().optional().describe('Who started the running turn; null while idle.');
|
|
216
260
|
const IsStreamingSchema = z.boolean().describe('True only while the session\'s run is a live stream on this server.');
|
|
217
261
|
const ActiveStreamIdSchema = NullableString.optional().describe('The live stream id; non-null only while `is_streaming` is true.');
|
|
262
|
+
const ReadOnlyReasonSchema = NullableString.optional().describe('Server-owned reason this session is display-only or its ownership cannot be verified.');
|
|
218
263
|
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.');
|
|
219
|
-
const CanBranchSchema = z.boolean().describe('Web may branch this session: never a subagent child
|
|
220
|
-
const CanPinSchema = z.boolean().describe('Web may pin or unpin this session: never a subagent child.');
|
|
221
|
-
const CanArchiveSchema = z.boolean().describe('Web may archive or unarchive this session: never a subagent child.');
|
|
264
|
+
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.');
|
|
265
|
+
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.');
|
|
266
|
+
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.');
|
|
222
267
|
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).');
|
|
223
|
-
const CanDuplicateSchema = z.boolean().describe('Web may duplicate this session: it has a WebUI copy
|
|
268
|
+
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.');
|
|
224
269
|
// TAL-310: the server classifies every session's source once; clients file rows by it and never scan source markers.
|
|
225
270
|
export const SourceKindSchema = z.enum(['webui', 'cli', 'messaging', 'cron', 'webhook', 'subagent', 'claude_code', 'kanban', 'api', 'other'])
|
|
226
271
|
.describe('The session\'s source family. `is_cli_session` is true only for `cli` and `claude_code`.');
|
|
@@ -245,18 +290,29 @@ export const CompressionReferenceSchema = z.object({
|
|
|
245
290
|
export const BranchedFromSchema = z.object({ session_id: SessionIdSchema, title: z.string() });
|
|
246
291
|
/** Full session record from `GET /api/session` and mutations returning `session`. */
|
|
247
292
|
export const SessionSchema = z.looseObject({
|
|
293
|
+
context_detail_key: z.string().nullable().optional().describe('Opaque identity for open-only context details; changes with owner epoch, model and context.'),
|
|
294
|
+
composer_state_key: z.string().optional().describe('Opaque profile-home and owner identity for device-local composer state; never an API session id.'),
|
|
248
295
|
session_id: SessionIdSchema, title: z.string(), workspace: z.string().optional(), created_workspace: z.string().nullable().optional(), model: NullableString.optional(), model_provider: NullableString.optional(),
|
|
249
296
|
model_option_id: NullableString.optional().describe('TAL-301: the catalog entry id the stored model/provider selects; null when none.'),
|
|
250
297
|
messages: z.array(MessageSchema).optional(), tool_calls: z.array(ToolCallSchema).optional(), created_at: UnixSeconds.optional(), updated_at: UnixSeconds.optional(), last_message_at: NullableNumber.optional(),
|
|
251
298
|
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(),
|
|
252
299
|
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(),
|
|
253
|
-
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.'),
|
|
300
|
+
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.'),
|
|
301
|
+
run_status: RunStatusSchema.nullable().optional().describe('Current server-selected run presentation; null when no turn runs. Older servers omit it.'),
|
|
302
|
+
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.'),
|
|
303
|
+
notices: z.array(SessionNoticeSchema).optional().describe('TAL-803: the Agent\'s active notices for the session, oldest first.'),
|
|
304
|
+
goal: SessionGoalSchema.nullable().optional().describe('TAL-808: the standing /goal; null when none runs.'),
|
|
305
|
+
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(),
|
|
254
306
|
pending_user_message: NullableString.optional(), pending_attachments: z.array(AttachmentSchema).optional(), pending_started_at: NullableNumber.optional(), pending_user_source: NullableString.optional(),
|
|
255
307
|
context_length: NullableNumber.optional(), threshold_tokens: NullableNumber.optional(), last_prompt_tokens: NullableNumber.optional(), post_compression_context_tokens_estimate: NullableNumber.optional(), ...ContextUsageFields,
|
|
256
|
-
|
|
308
|
+
execution_mode: ExecutionModeSchema.optional().describe('TAL-1040: the Agent execution policy frozen when the session was created; absent from older servers.'),
|
|
309
|
+
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(),
|
|
257
310
|
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.'),
|
|
311
|
+
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.'),
|
|
258
312
|
source_label: NullableString.optional(), session_source: NullableString.optional(), raw_source: NullableString.optional(), parent_session_id: NullableString.optional(), worktree_path: NullableString.optional(),
|
|
259
|
-
worktree_branch: NullableString.optional(), worktree_repo_root: NullableString.optional(),
|
|
313
|
+
worktree_branch: NullableString.optional(), worktree_repo_root: NullableString.optional(),
|
|
314
|
+
worktree_retained: z.literal(true).optional().describe('TAL-1254: the last sidecar start found this worktree gone from git; the Agent\'s sweep keeps an archived one under `refs/hermes/archive/`. Absent while the worktree exists.'),
|
|
315
|
+
share_token: NullableString.optional(), share_url: NullableString.optional(), share_created_at: NullableNumber.optional(), manual_title: z.boolean().optional(),
|
|
260
316
|
compression_anchor_summary: NullableString.optional(), compression_recovery: z.record(z.string(), Json).optional(), recommended_recovery_action: NullableString.optional(), compression_recovery_action: NullableString.optional(),
|
|
261
317
|
compression_recovery_source_session_id: NullableString.optional(), gateway_routing: Json.optional(), _messages_offset: z.number().optional(), _messages_truncated: z.boolean().optional(), _msg_limit_max: z.number().optional(), _load_revision: z.string().optional(),
|
|
262
318
|
/**
|
|
@@ -276,12 +332,18 @@ export const SessionEnvelopeSchema = z.looseObject({ session: SessionSchema });
|
|
|
276
332
|
export const SessionRowSchema = z.looseObject({
|
|
277
333
|
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(),
|
|
278
334
|
message_count: z.number().optional(), pinned: z.boolean().optional(), archived: z.boolean().optional(), project_id: NullableString.optional(), profile: NullableString.optional(), is_streaming: IsStreamingSchema,
|
|
279
|
-
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(),
|
|
335
|
+
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(),
|
|
280
336
|
source_tag: NullableString.optional(), source_label: NullableString.optional(), session_source: NullableString.optional(), raw_source: NullableString.optional(), parent_session_id: NullableString.optional(),
|
|
281
337
|
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(),
|
|
282
338
|
workspace_name: WorkspaceNameSchema,
|
|
283
339
|
...ContextUsageFields,
|
|
284
340
|
});
|
|
341
|
+
/**
|
|
342
|
+
* TAL-785: whether the Agent's `state.db` could serve the Agent session rows. `corrupt`: SQLite reports the file
|
|
343
|
+
* damaged; `unavailable`: it could not be read for another reason (permissions, a lock, an I/O error); `outdated`: a
|
|
344
|
+
* readable database from an older hermes-agent. `reason` explains a degraded state.
|
|
345
|
+
*/
|
|
346
|
+
export const AgentStorageSchema = z.object({ state: z.enum(['ok', 'corrupt', 'unavailable', 'outdated']), reason: z.string().nullable() });
|
|
285
347
|
export const SessionsListSchema = z.looseObject({
|
|
286
348
|
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(),
|
|
287
349
|
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(),
|
|
@@ -289,10 +351,11 @@ export const SessionsListSchema = z.looseObject({
|
|
|
289
351
|
// TAL-482: sidebar counts for the "Scheduled sessions" / "Webhook sessions" groups; `_truncated` means more exist than are listed.
|
|
290
352
|
scheduled_session_count: z.number().int().nonnegative(), scheduled_sessions_truncated: z.boolean(),
|
|
291
353
|
webhook_session_count: z.number().int().nonnegative(), webhook_sessions_truncated: z.boolean(),
|
|
354
|
+
agent_storage: AgentStorageSchema.describe('Agent session storage health; a degraded state explains an empty or missing Agent session list.'),
|
|
292
355
|
archived_limit: z.number().int().nullable().optional(), archived_offset: z.number().int().optional(),
|
|
293
356
|
});
|
|
294
357
|
export const SessionStatusSchema = z.looseObject({
|
|
295
|
-
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(),
|
|
358
|
+
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(),
|
|
296
359
|
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(),
|
|
297
360
|
});
|
|
298
361
|
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() });
|
|
@@ -300,12 +363,20 @@ export const ProjectSchema = z.looseObject({ project_id: z.string(), name: z.str
|
|
|
300
363
|
export const ProjectsSchema = z.looseObject({ projects: z.array(ProjectSchema), active_profile: z.string(), all_profiles: z.boolean(), other_profile_count: z.number().int() });
|
|
301
364
|
export const SessionDeleteResultSchema = z.looseObject({ ok: z.literal(true), state_db_cleanup_failed: z.boolean().optional() });
|
|
302
365
|
// ── chat ─────────────────────────────────────────────────────────────────
|
|
366
|
+
/** `voice_turn` (TAL-801): the turn was spoken (an App voice note), so the Agent runs it on `auxiliary.voice_chat`. */
|
|
303
367
|
export const ChatStartRequestSchema = z.looseObject({
|
|
368
|
+
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.'),
|
|
304
369
|
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(),
|
|
305
370
|
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(),
|
|
371
|
+
voice_turn: z.boolean().optional(),
|
|
372
|
+
/** TAL-818: this client renders `connect_card`, so a `manage_connections` call waits on the card; without it the Agent answers with plain links. */
|
|
373
|
+
connect_card: z.boolean().optional(),
|
|
374
|
+
/** The starting client renders the masked `skill_secret` prompt; omitted by older and native clients. */
|
|
375
|
+
skill_secret: z.boolean().optional(),
|
|
306
376
|
});
|
|
307
377
|
/** Accepted turn. `stream_id` is the owner identity for the SSE connection. */
|
|
308
378
|
export const ChatStartResponseSchema = z.looseObject({
|
|
379
|
+
owner_attachment: OwnerAttachmentSchema.optional(), admission_id: z.string().optional(),
|
|
309
380
|
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(),
|
|
310
381
|
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(),
|
|
311
382
|
});
|
|
@@ -330,14 +401,15 @@ export const SteerWithdrawRequestSchema = z.object({ session_id: SessionIdSchema
|
|
|
330
401
|
/** `withdrawn: false` when the steer is unknown, already taken by the Agent (it then settles as consumed), or being sent. */
|
|
331
402
|
export const SteerWithdrawResponseSchema = z.object({ withdrawn: z.boolean(), text: z.string().optional() });
|
|
332
403
|
export const SteerSendNowRequestSchema = z.object({ session_id: SessionIdSchema, steer_id: z.string().min(1) });
|
|
333
|
-
/**
|
|
334
|
-
export const SteerSendNowResponseSchema = z.object({ redirected: z.boolean() });
|
|
404
|
+
/** The server decides why Send now did or did not deliver. `redirected` remains for older clients. */
|
|
405
|
+
export const SteerSendNowResponseSchema = z.object({ redirected: z.boolean(), outcome: z.enum(['delivered', 'next_step', 'not_running', 'taken', 'failed']) });
|
|
335
406
|
/** `text` is delivered to the running agent; `display_text` is what the transcript shows. */
|
|
336
407
|
export const SteerRequestSchema = z.looseObject({ session_id: SessionIdSchema, text: z.string().min(1), display_text: z.string().optional(), steer_id: z.string().optional() });
|
|
337
408
|
/** `accepted: false` with a `fallback` reason means the message was not delivered; the caller keeps the draft. */
|
|
338
409
|
/** TAL-460: a steer sent while a background turn runs starts the user's own turn instead; `started_turn` is its start response. */
|
|
339
410
|
export const SteerResponseSchema = z.looseObject({ accepted: z.boolean(), fallback: NullableString.optional(), stream_id: NullableString.optional(), steer_id: z.string().optional(), started_turn: ChatStartResponseSchema.optional() });
|
|
340
411
|
export const ApprovalPendingSchema = z.looseObject({
|
|
412
|
+
allowed_choices: z.array(z.enum(['once', 'session', 'always', 'deny'])).optional(), can_enable_yolo: z.boolean().optional(),
|
|
341
413
|
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(),
|
|
342
414
|
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(),
|
|
343
415
|
});
|
|
@@ -347,17 +419,38 @@ export const ApprovalRespondRequestSchema = z.looseObject({ session_id: SessionI
|
|
|
347
419
|
export const ApprovalRespondResponseSchema = z.looseObject({ ok: z.boolean(), choice: z.string().optional(), yolo_enabled: z.boolean().optional(), stale_cleared: z.boolean().optional(), error: z.string().optional(), pending_count: z.number().optional() });
|
|
348
420
|
export const ClarifyChoiceSchema = z.union([z.string(), z.looseObject({ label: z.string().optional(), value: z.string().optional(), text: z.string().optional() })]);
|
|
349
421
|
/** One question the client asks, in server order; answers are keyed by `qid`. A single-question prompt is one `q0` step. */
|
|
350
|
-
export const ClarifyStepSchema = z.looseObject({ qid: z.string(), question: z.string(), choices: z.array(z.string()), multi_select: z.boolean()
|
|
422
|
+
export const ClarifyStepSchema = z.looseObject({ qid: z.string(), question: z.string(), choices: z.array(z.string()), multi_select: z.boolean(),
|
|
423
|
+
answered: z.boolean().optional().describe('TAL-1271: a gateway-owned batch question the owner already holds an answer for; it stays editable until the last answer.') });
|
|
351
424
|
/** Keyed step answers; a multi-select step takes a list. The server shapes them into the Agent's reply. */
|
|
352
425
|
export const ClarifyAnswersSchema = z.record(z.string(), z.union([z.string(), z.array(z.string())]));
|
|
426
|
+
/** TAL-887: one input of a password-manager prompt, answered under its `key`; a `secure` input is masked. */
|
|
427
|
+
export const VaultPromptFieldSchema = z.object({ key: z.enum(['master_password', 'identifier', 'password', 'code', 'secret']), secure: z.boolean() });
|
|
428
|
+
/**
|
|
429
|
+
* TAL-887: the Agent asks for a password manager's master password (`vault_unlock`), a login to save for the page it is
|
|
430
|
+
* on (`vault_save_login`), a one-time code (`vault_code`), or a skill environment secret (`skill_secret`). Clients answer through
|
|
431
|
+
* `/api/clarify/respond` with keyed `answers`, or `decline`; an empty answer, a decline, a cancel and `timeout_at` all
|
|
432
|
+
* resolve it unanswered. Answers never enter chat, logs, streams, or responses. Skill secrets are saved only to the invoking profile.
|
|
433
|
+
*/
|
|
434
|
+
export const VaultPromptSchema = z.object({
|
|
435
|
+
kind: z.enum(['vault_unlock', 'vault_save_login', 'vault_code', 'skill_secret']),
|
|
436
|
+
backend: z.string().nullable().describe('The password manager (`vault_unlock`).'),
|
|
437
|
+
display_name: z.string().nullable().describe('Its display name (`vault_unlock`).'),
|
|
438
|
+
origin: z.string().nullable().describe('The page origin the login is saved for (`vault_save_login`).'),
|
|
439
|
+
site: z.string().nullable().describe('The site, by host (`vault_save_login`, `vault_code`).'),
|
|
440
|
+
hint: z.string().nullable().describe('Where the code was sent, when the Agent says (`vault_code`).'),
|
|
441
|
+
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`).'),
|
|
442
|
+
fields: z.array(VaultPromptFieldSchema),
|
|
443
|
+
timeout_at: z.number().describe('Unix seconds when the Agent stops waiting.'),
|
|
444
|
+
});
|
|
353
445
|
export const ClarifyPendingSchema = z.looseObject({
|
|
354
446
|
steps: z.array(ClarifyStepSchema).optional(),
|
|
447
|
+
vault: VaultPromptSchema.optional(),
|
|
355
448
|
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(),
|
|
356
449
|
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(),
|
|
357
450
|
timeout_seconds: z.number().optional(), pending_count: z.number().optional(), index: z.number().optional(), total: z.number().optional(),
|
|
358
451
|
});
|
|
359
452
|
export const ClarifyPendingEnvelopeSchema = z.looseObject({ pending: ClarifyPendingSchema.nullable(), pending_count: z.number().int() });
|
|
360
|
-
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() });
|
|
453
|
+
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() });
|
|
361
454
|
export const ClarifyRespondResponseSchema = z.looseObject({ ok: z.boolean(), response: z.string().optional(), error: z.string().optional(), stale: z.boolean().optional() });
|
|
362
455
|
export const DraftSchema = z.looseObject({ text: z.string(), files: z.array(Json) });
|
|
363
456
|
export const DraftResponseSchema = z.looseObject({ ok: z.literal(true), draft: DraftSchema, draft_version: z.string().nullable(), unchanged: z.boolean().optional() });
|
|
@@ -391,6 +484,8 @@ export const BackgroundTaskSchema = z.object({
|
|
|
391
484
|
agents: BackgroundLinkSchema.shape.agents.nullable(),
|
|
392
485
|
pinned: z.boolean(),
|
|
393
486
|
dismissible: z.boolean(),
|
|
487
|
+
/** TAL-1172: confirmed running work this session may stop. */
|
|
488
|
+
can_stop: z.boolean().optional(),
|
|
394
489
|
active: z.boolean(),
|
|
395
490
|
});
|
|
396
491
|
/**
|
|
@@ -401,6 +496,7 @@ export const BackgroundTaskSchema = z.object({
|
|
|
401
496
|
export const BackgroundTasksResponseSchema = z.object({ session_id: z.string(), tasks: z.array(BackgroundTaskSchema), agent_available: z.boolean(), agents_working: z.boolean().optional() });
|
|
402
497
|
export const BackgroundTaskResultSchema = z.object({ task_id: z.string(), text: z.string() });
|
|
403
498
|
export const BackgroundDismissRequestSchema = z.object({ session_id: SessionIdSchema, task_id: z.string().min(1) });
|
|
499
|
+
export const BackgroundStopResponseSchema = z.object({ outcome: z.enum(['stopped', 'not_running', 'not_found']) });
|
|
404
500
|
export const BackgroundDismissResponseSchema = z.object({ ok: z.literal(true), task: BackgroundTaskSchema });
|
|
405
501
|
export const ShareCreateResponseSchema = z.looseObject({ ok: z.literal(true), share: z.looseObject({ token: z.string(), url: z.string(), title: z.string(), message_count: z.number().int(), created_at: z.number(), updated_at: z.number() }), session: SessionRowSchema });
|
|
406
502
|
export const ShareMessageSchema = z.looseObject({ role: z.string(), content: z.union([z.string(), z.null(), z.array(Json)]).optional() });
|
|
@@ -409,8 +505,18 @@ export const ShareReadSchema = z.looseObject({ share: ShareSchema });
|
|
|
409
505
|
export const SessionNewRequestSchema = z.looseObject({
|
|
410
506
|
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(),
|
|
411
507
|
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(),
|
|
508
|
+
execution_mode: ExecutionModeSchema.optional().describe('TAL-1040: `ignore_config` and `safe` start the session through the Agent owner; omitted means normal.'),
|
|
509
|
+
request_id: z.string().regex(/^[A-Za-z0-9_-]{1,64}$/).optional().describe('TAL-1040: stable creation identity for a diagnostic chat. Reuse it only to retry the same creation.'),
|
|
412
510
|
});
|
|
413
|
-
|
|
511
|
+
/**
|
|
512
|
+
* `streaming` (TAL-802): live dictation over `TRANSCRIBE_STREAM_PATH` would open for this profile (`stt.streaming` on, a live provider wire).
|
|
513
|
+
* `warm_supported` (TAL-916): a client starting a recording should `POST /api/transcribe/warm` so the engine loads while the user speaks.
|
|
514
|
+
*/
|
|
515
|
+
export const TranscribeCapabilitySchema = z.looseObject({ ok: z.literal(true), available: z.boolean(), provider: z.string(), streaming: z.boolean(), warm_supported: z.boolean() });
|
|
516
|
+
/** TAL-906: what read-aloud speaks for a message; clients play it as is. */
|
|
517
|
+
export const SpeechPrepareSchema = z.object({ spoken_text: z.string() });
|
|
518
|
+
/** `POST /api/transcribe`: the recording's transcript; `filtered` (TAL-917) when the server emptied a phrase Whisper invents on silent audio. */
|
|
519
|
+
export const TranscribeResponseSchema = z.looseObject({ ok: z.literal(true), transcript: z.string(), filtered: z.boolean() });
|
|
414
520
|
// ── settings, profiles, models, providers ───────────────────────────────
|
|
415
521
|
/** TAL-411: the request profile's quota urgency thresholds. A save patches valid fields and clamps critical to at most warning. */
|
|
416
522
|
export const QuotaThresholdsSchema = z.object({
|
|
@@ -422,7 +528,7 @@ export const SettingsSchema = z.looseObject({
|
|
|
422
528
|
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(),
|
|
423
529
|
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(),
|
|
424
530
|
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(),
|
|
425
|
-
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(),
|
|
531
|
+
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(),
|
|
426
532
|
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(),
|
|
427
533
|
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(),
|
|
428
534
|
max_tokens: NullableNumber.optional(), max_tokens_effective: NullableNumber.optional(), max_tokens_fallback: NullableNumber.optional(), tts_engine: z.string().optional(), tts_voice: z.string().optional(),
|
|
@@ -434,20 +540,47 @@ export const SettingsSchema = z.looseObject({
|
|
|
434
540
|
export const ProfileSchema = z.looseObject({
|
|
435
541
|
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(),
|
|
436
542
|
total_skills: z.number().optional(), enabled_skills: z.number().optional(), gateway_running: z.boolean().optional(), has_env: z.boolean().optional(), visible: z.boolean().optional(),
|
|
543
|
+
/** TAL-805: the profile's gateway mode; `gateway_running` is true exactly for `own` and `served`. */
|
|
544
|
+
gateway_mode: GatewayModeSchema.optional(),
|
|
437
545
|
/** TAL-213: Bot Mode identity from `profile.yaml` (the bot's roster title, else the profile's display name), one bounded printable line each. */
|
|
438
546
|
display_name: z.string().optional(), description: z.string().optional(), has_avatar: z.boolean().optional(),
|
|
439
547
|
/** TAL-213: present only when the profile has a canonical Bot Chat; clients open `tip_session_id` after switching to the profile. */
|
|
440
548
|
canonical_session: CanonicalBotChatSchema.nullable().optional(),
|
|
549
|
+
/** TAL-819: skill and memory writes the Agent staged for approval, reviewed on the Skills and Memory pages. */
|
|
550
|
+
pending_writes: z.number().int().optional(),
|
|
441
551
|
});
|
|
442
552
|
export const ProfilesSchema = z.looseObject({ profiles: z.array(ProfileSchema), active: z.string(), single_profile_mode: z.boolean().optional() });
|
|
443
553
|
export const ActiveProfileSchema = z.looseObject({ name: z.string(), path: z.string().optional(), is_default: z.boolean().optional(), default_workspace: NullableString.optional() });
|
|
444
554
|
export const ProfileSwitchSchema = ProfilesSchema.extend({ is_default: z.boolean(), default_model: Json, default_model_provider: Json, default_workspace: z.string().nullable() });
|
|
445
555
|
/** `/api/reasoning`: config.yaml agent.reasoning_effort / display.show_reasoning, resolved for a model. */
|
|
446
|
-
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() });
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
556
|
+
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(), supports_session_scope: z.boolean().optional() });
|
|
557
|
+
export const QuotaLevelSchema = z.enum(['healthy', 'warning', 'critical', 'stale', 'unavailable']);
|
|
558
|
+
/**
|
|
559
|
+
* 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.
|
|
560
|
+
* TAL-807: `limit` is present while the provider's credential pool cannot serve this model until `resets_at` (ISO-8601 UTC).
|
|
561
|
+
*/
|
|
562
|
+
export const ModelEntrySchema = z.looseObject({
|
|
563
|
+
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(),
|
|
564
|
+
limit: z.object({ scope: z.literal('model'), resets_at: z.string() }).optional(),
|
|
565
|
+
});
|
|
566
|
+
/** TAL-807: a group's rate limit: every pool account benched until `resets_at`, else the entry ids (`models`) cooling down until their reset. */
|
|
567
|
+
export const ModelGroupLimitSchema = z.discriminatedUnion('scope', [
|
|
568
|
+
z.object({ scope: z.literal('account'), resets_at: z.string() }),
|
|
569
|
+
z.object({ scope: z.literal('models'), models: z.record(z.string(), z.string()) }),
|
|
570
|
+
]);
|
|
571
|
+
/**
|
|
572
|
+
* TAL-807: `limit` is the provider's live pool rate limit; `quota_level` is the TAL-411 `remaining` level of the tightest
|
|
573
|
+
* account-scope window in the provider's last account-usage read (a model-family window never counts), absent without one
|
|
574
|
+
* and while the group is account-limited.
|
|
575
|
+
*/
|
|
576
|
+
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.') });
|
|
577
|
+
export const ModelGroupSchema = z.looseObject({
|
|
578
|
+
availability: CatalogAvailabilitySchema.optional(),
|
|
579
|
+
provider: z.string(), provider_id: z.string().optional(), models: z.array(ModelEntrySchema), extra_models: z.array(ModelEntrySchema).optional(),
|
|
580
|
+
limit: ModelGroupLimitSchema.optional(), quota_level: QuotaLevelSchema.optional(),
|
|
581
|
+
});
|
|
582
|
+
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() });
|
|
583
|
+
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() });
|
|
451
584
|
/** TAL-603: where a card's credential comes from; `other` is a source the server cannot name, shown as its raw `key_source`. */
|
|
452
585
|
export const KeySourceKindSchema = z.enum(['env', 'oauth', 'config', 'pool', 'plugin', 'other']);
|
|
453
586
|
/**
|
|
@@ -461,8 +594,7 @@ export const ProviderSchema = z.looseObject({
|
|
|
461
594
|
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(),
|
|
462
595
|
is_active: z.boolean().optional(), key_source_kind: KeySourceKindSchema.nullable().optional(), removable: z.boolean().optional(),
|
|
463
596
|
});
|
|
464
|
-
export const ProvidersSchema = z.looseObject({ providers: z.array(ProviderSchema), active_provider: NullableString.optional() });
|
|
465
|
-
export const QuotaLevelSchema = z.enum(['healthy', 'warning', 'critical', 'stale', 'unavailable']);
|
|
597
|
+
export const ProvidersSchema = z.looseObject({ availability: CatalogAvailabilitySchema.optional(), providers: z.array(ProviderSchema), active_provider: NullableString.optional() });
|
|
466
598
|
/** TAL-411: the server's classification per colour basis; `/api/provider/quotas` only, at the profile's thresholds. */
|
|
467
599
|
export const QuotaUrgencySchema = z.looseObject({ remaining: QuotaLevelSchema, pace: QuotaLevelSchema.describe('Burn rate and pace tolerance; the remaining classification when the window has no pace.') });
|
|
468
600
|
/** TAL-409: a window's pace as of the envelope's `computed_at`. Stale once `valid_until` (the window's reset) passes. */
|
|
@@ -487,6 +619,7 @@ export const QuotaWindowSchema = z.looseObject({
|
|
|
487
619
|
});
|
|
488
620
|
const QuotaWindowIndex = z.number().int().nullable().optional();
|
|
489
621
|
export const QuotaSourceSchema = z.looseObject({
|
|
622
|
+
computed_at: z.string().optional().describe('Original reference time of this source, retained with stale windows.'),
|
|
490
623
|
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(),
|
|
491
624
|
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(),
|
|
492
625
|
pace_window_index: QuotaWindowIndex.describe('The window a pace-coloured widget shows: the weekly one, else the first 5h/session window.'),
|
|
@@ -507,8 +640,8 @@ export const ProviderQuotaSchema = z.looseObject({
|
|
|
507
640
|
account_limits: QuotaAccountLimitsSchema.nullable().optional(),
|
|
508
641
|
});
|
|
509
642
|
/** Python `get_provider_quotas`: the stable identity envelope the iOS quota widget persists (`scope_id`/`profile_id`). */
|
|
510
|
-
export const ProviderQuotasSchema = z.looseObject({
|
|
511
|
-
version: z.number(), computed_at: z.string().describe('ISO-8601 UTC reference time
|
|
643
|
+
export const ProviderQuotasSchema = z.looseObject({ availability: CatalogAvailabilitySchema.optional(),
|
|
644
|
+
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,
|
|
512
645
|
missing_source: z.boolean().describe('True when `?source=` names a source id this scope no longer has; `sources` is then empty.'),
|
|
513
646
|
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.'),
|
|
514
647
|
});
|
|
@@ -543,8 +676,12 @@ export const AuxiliaryTaskSchema = z.looseObject({
|
|
|
543
676
|
selected_option_id: z.string().nullable(),
|
|
544
677
|
/** False only for a pinned model the current catalog does not list; it stays visible and editable. */
|
|
545
678
|
in_catalog: z.boolean(),
|
|
679
|
+
/** TAL-800: the slot a plugin task inherits its route from; while the task is Auto, `value_label` names that slot's model. */
|
|
680
|
+
inherit_from: z.string().nullable(),
|
|
681
|
+
/** 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. */
|
|
682
|
+
reasoning_effort: z.string().nullable(),
|
|
546
683
|
});
|
|
547
|
-
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) });
|
|
684
|
+
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) });
|
|
548
685
|
export const MaxTokensSchema = z.looseObject({ max_tokens: NullableNumber, max_tokens_effective: NullableNumber, max_tokens_fallback: NullableNumber });
|
|
549
686
|
// ── workspaces, files, git ───────────────────────────────────────────────
|
|
550
687
|
/** 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). */
|
|
@@ -567,18 +704,20 @@ export const FileContentSchema = z.looseObject({
|
|
|
567
704
|
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() });
|
|
568
705
|
export const GitInfoSchema = z.looseObject({ git: GitBadgeSchema.nullable().optional() });
|
|
569
706
|
// ── tools ────────────────────────────────────────────────────────────────
|
|
570
|
-
export const SkillSchema = z.looseObject({ name: z.string(), description: NullableString.optional(), category: NullableString.optional(), disabled: z.boolean().optional() });
|
|
707
|
+
export const SkillSchema = z.looseObject({ ...SkillCatalogIdentitySchema.shape, name: z.string(), description: NullableString.optional(), category: NullableString.optional(), disabled: z.boolean().optional() });
|
|
571
708
|
export const SkillsSchema = z.looseObject({ skills: z.array(SkillSchema), categories: z.array(Json).optional() });
|
|
572
709
|
/**
|
|
573
710
|
* `linked_files` groups the skill directory's files by folder (`references`, `templates`, ...); open one with `?file=`.
|
|
574
711
|
* A linked file that is not UTF-8 text carries `binary: true` and its `size` instead of `content`.
|
|
575
712
|
*/
|
|
576
|
-
export const SkillContentSchema = z.looseObject({ 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() });
|
|
713
|
+
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() });
|
|
577
714
|
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() });
|
|
578
715
|
export const MemorySchema = z.looseObject({
|
|
579
716
|
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(),
|
|
580
717
|
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(),
|
|
581
718
|
project_context_shadowed: z.array(Json).optional(), external_notes_enabled: z.boolean().optional(),
|
|
719
|
+
/** TAL-784: the revision of each file as this read found it. A save sends the revision its edit started from. */
|
|
720
|
+
memory_revision: z.string(), user_revision: z.string(), soul_revision: z.string(),
|
|
582
721
|
});
|
|
583
722
|
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() });
|
|
584
723
|
export const PromptsSchema = z.looseObject({ prompts: z.array(PromptSchema) });
|
|
@@ -588,12 +727,15 @@ export const PromptsSchema = z.looseObject({ prompts: z.array(PromptSchema) });
|
|
|
588
727
|
* clients can run it, and `unsupported_message` is the English text a client outside `clients` shows when it is typed.
|
|
589
728
|
* Clients suggest the entries listing them whose name or any alias starts with the typed text (case-insensitive), and
|
|
590
729
|
* resolve a typed alias to the entry's `name`. `exec` marks an Agent entry `POST /api/commands/exec` runs: the client
|
|
591
|
-
* posts the typed text there and shows the returned output instead of starting a chat turn
|
|
730
|
+
* posts the typed text there with the open chat's `session_id` and shows the returned output instead of starting a chat turn
|
|
731
|
+
* (TAL-561); `/refine` reviews that chat (TAL-902).
|
|
732
|
+
* `handler: 'prompt'` marks an Agent prompt built-in: the client sends the typed text as a chat turn and the server starts the
|
|
733
|
+
* turn with the Agent's expansion of it (TAL-817).
|
|
592
734
|
*/
|
|
593
735
|
export const CommandClientSchema = z.enum(['web', 'ios']);
|
|
594
736
|
export const CommandRowSchema = z.looseObject({
|
|
595
737
|
name: z.string(), description: z.string().optional(), aliases: z.array(z.string()), args_hint: z.string().optional(), category: z.string().optional(),
|
|
596
|
-
handler: z.enum(['client', 'agent']), clients: z.array(CommandClientSchema), unsupported_message: z.string().optional(),
|
|
738
|
+
handler: z.enum(['client', 'agent', 'prompt']), clients: z.array(CommandClientSchema), unsupported_message: z.string().optional(),
|
|
597
739
|
cli_only: z.boolean().optional(), gateway_only: z.boolean().optional(), subcommands: z.array(Json).optional(), exec: z.boolean().optional(),
|
|
598
740
|
});
|
|
599
741
|
export const CommandsSchema = z.looseObject({ commands: z.array(CommandRowSchema) });
|
|
@@ -609,9 +751,11 @@ export const DashboardStatusSchema = z.looseObject({ running: z.boolean(), enabl
|
|
|
609
751
|
* Gateway status for the Settings banner (TAL-266). `running` and `configured` come from the Agent health probe; when it
|
|
610
752
|
* is inconclusive, stale running metadata or known gateway sessions mark the gateway configured. `platforms` are the
|
|
611
753
|
* messaging platforms of known gateway sessions; `last_active` is the gateway session index's ISO mtime while running, else "".
|
|
754
|
+
* TAL-805: `gateway_mode` is the active profile's mode and decides `running` when it is not null. It is null for a remote
|
|
755
|
+
* gateway, or for the root profile when the sidecar cannot answer; a named profile whose mode is unconfirmed reads `stopped`.
|
|
612
756
|
*/
|
|
613
757
|
export const GatewayStatusSchema = z.object({
|
|
614
|
-
running: z.boolean(), configured: z.boolean(), platforms: z.array(z.object({ name: z.string(), label: z.string() })), last_active: z.string(), session_count: z.number().int(),
|
|
758
|
+
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(),
|
|
615
759
|
health: z.object({ state: NullableString, reason: NullableString, gateway_state: NullableString }),
|
|
616
760
|
});
|
|
617
761
|
export const GatewayActionSchema = z.object({ ok: z.literal(true), action: z.enum(['start', 'stop', 'restart']), message: z.string(), status: GatewayStatusSchema });
|
|
@@ -627,21 +771,55 @@ export const ProjectOsDashboardSchema = z.object({
|
|
|
627
771
|
handoff: z.record(z.string(), Json).nullable(), active: z.record(z.string(), Json).nullable(), heartbeat: z.record(z.string(), Json).nullable(),
|
|
628
772
|
onboarding: z.looseObject({ active: z.boolean(), doc_source: z.enum(['project-os', 'root']) }).optional(), goal_summary: z.string(),
|
|
629
773
|
});
|
|
630
|
-
|
|
774
|
+
/** One server projection used by chat readiness, HTTP refusals, and persisted stream errors. */
|
|
775
|
+
export const AgentRuntimeMetadataSchema = z.object({
|
|
776
|
+
agent_runtime_reason: z.enum(['update_active', 'recovery_incomplete', 'source_changed', 'unknown']).optional(),
|
|
777
|
+
agent_update_state: z.string().optional(),
|
|
778
|
+
retryable: z.boolean().optional(),
|
|
779
|
+
restart_scheduled: z.boolean().optional(),
|
|
780
|
+
});
|
|
781
|
+
/** TAL-951: whether Web chat can run, from the Agent sidecar's status; `condition` says why not, null when available. */
|
|
782
|
+
export const ChatReadinessSchema = z.discriminatedUnion('available', [
|
|
783
|
+
z.object({ available: z.literal(true), condition: z.null() }),
|
|
784
|
+
z.object({ available: z.literal(false), condition: z.enum(['sidecar_unavailable', 'agent_incompatible', 'agent_runtime_stale']), ...AgentRuntimeMetadataSchema.shape }),
|
|
785
|
+
]);
|
|
786
|
+
/** Messaging-gateway liveness (`alive`, `details`, `gateway_chat`) for Settings → System, plus Web chat readiness in `chat`. */
|
|
787
|
+
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() });
|
|
631
788
|
export const SystemHealthSchema = z.looseObject({
|
|
632
789
|
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(),
|
|
633
790
|
errors: z.array(z.looseObject({ code: z.string().optional(), metric: z.string().optional() })).optional(), webui_runtime: Json.optional(),
|
|
634
791
|
});
|
|
635
792
|
export const UpdateStateSchema = z.enum(['up_to_date', 'release_ready', 'commits_behind', 'local_changes', 'finish', 'manual', 'check_failed', 'off', 'unknown']);
|
|
636
|
-
|
|
793
|
+
const AgentSupportSchema = z.enum(['supported', 'unchecked']);
|
|
794
|
+
export const UpdateVersionSchema = z.object({
|
|
795
|
+
version: z.string().describe('The release as shown: the Agent tag or the Web release tag.'),
|
|
796
|
+
ref: z.string().describe('What `updates.apply`/`updates.force` accept back as `version`: the Agent tag or the Web semver.'),
|
|
797
|
+
sha: z.string().optional().describe('Agent only: the commit the tag peels to.'),
|
|
798
|
+
release_url: z.string().nullable(),
|
|
799
|
+
latest: z.boolean().describe('The channel\'s newest release, the one an update without `version` installs.'),
|
|
800
|
+
folded: z.boolean().describe('Shown behind the folded "more versions" node: every entry except the newest.'),
|
|
801
|
+
support: AgentSupportSchema.optional().describe('Agent only: this release\'s classification against the verified Agent window.'),
|
|
802
|
+
support_label: z.string().optional().describe('Agent only: `support` worded to fit one phone line.'),
|
|
803
|
+
}).describe('TAL-946: one installable Stable release newer than the installed one.');
|
|
804
|
+
export const UpdateTargetSchema = z.looseObject({
|
|
805
|
+
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.'),
|
|
806
|
+
name: z.string().optional(), channel: z.enum(['stable', 'experimental']).optional(),
|
|
807
|
+
unsupported: z.boolean().optional().describe('Deprecated (TAL-350): `support === \'unchecked\'`, kept for older clients.'),
|
|
808
|
+
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`.'),
|
|
809
|
+
support_label: z.string().optional().describe('Agent target only (TAL-946): `support` worded to fit one phone line.'),
|
|
810
|
+
current_support: AgentSupportSchema.optional().describe('Agent target only: the same classification for the installed Agent revision.'),
|
|
811
|
+
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(),
|
|
637
812
|
state: UpdateStateSchema.describe('TAL-559: the status clients word; `off` when checks are disabled or Agent updates are ignored.'),
|
|
638
813
|
can_apply: z.boolean().describe('The apply action is available for this target.'),
|
|
639
814
|
installed_unverified: z.boolean().describe('`release_ready` only: the installed revision sits on no release tag.'),
|
|
640
815
|
manual_link: z.boolean().describe('Show the manual-install (releases) link.'),
|
|
641
816
|
target_version: z.string().nullable().describe('The version the update path leads to, when one is shown.'),
|
|
642
817
|
summary_available: z.boolean().describe('TAL-759: offer "Summarize with AI" for this target (`release_ready` or `commits_behind`).'),
|
|
818
|
+
versions: z.array(UpdateVersionSchema).describe('TAL-946: every installable Stable release newer than the installed one, newest first; empty unless `release_ready` can apply.'),
|
|
819
|
+
folded_count: z.number().int().nonnegative().describe('How many `versions` are `folded`.'),
|
|
643
820
|
});
|
|
644
|
-
export const
|
|
821
|
+
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() });
|
|
822
|
+
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() });
|
|
645
823
|
export const UpdatesSummarySchema = z.object({
|
|
646
824
|
ok: z.boolean(), target: z.enum(['webui', 'agent']), summary: z.string(),
|
|
647
825
|
current_version: z.string().nullable().describe('The installed version this summary starts from.'),
|
|
@@ -651,8 +829,13 @@ export const UpdatesSummarySchema = z.object({
|
|
|
651
829
|
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.'),
|
|
652
830
|
cached: z.boolean(),
|
|
653
831
|
});
|
|
654
|
-
export const UpdateApplySchema = z.looseObject({
|
|
655
|
-
|
|
832
|
+
export const UpdateApplySchema = z.looseObject({
|
|
833
|
+
recovery_compatibility: z.object({ manual_execution: z.boolean(), bot_chat_delivery: z.boolean() }).optional()
|
|
834
|
+
.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.'),
|
|
835
|
+
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.')
|
|
836
|
+
});
|
|
837
|
+
/** `verifying` (TAL-1138): the gateway restarted, and the server is checking that the new gateway process and the Agent runtime answer. */
|
|
838
|
+
export const UpdateNotificationPhaseSchema = z.enum(['applying', 'awaiting_confirmation', 'waiting_for_idle', 'restarting', 'verifying', 'succeeded', 'blocked', 'failed', 'unknown']);
|
|
656
839
|
export const UpdateNotificationActionSchema = z.object({
|
|
657
840
|
id: z.string().min(1).max(64).regex(/^[a-z0-9][a-z0-9_-]*$/),
|
|
658
841
|
label: z.string().min(1).max(80),
|
|
@@ -663,6 +846,12 @@ export const UpdateNotificationDestinationSchema = z.object({
|
|
|
663
846
|
key: z.string().min(1).max(64).regex(/^[a-z0-9][a-z0-9_.-]*$/),
|
|
664
847
|
label: z.string().min(1).max(80),
|
|
665
848
|
});
|
|
849
|
+
/** TAL-1138: one step of an update as its Updating dialog lists it; the server derives every label and state. */
|
|
850
|
+
export const UpdateStepSchema = z.object({
|
|
851
|
+
id: z.enum(['install', 'web_restart', 'ready', 'gateway_wait', 'gateway_restart', 'agent_ready']),
|
|
852
|
+
label: z.string().min(1).max(80),
|
|
853
|
+
state: z.enum(['done', 'active', 'pending', 'failed']),
|
|
854
|
+
});
|
|
666
855
|
export const UpdateNotificationSchema = z.object({
|
|
667
856
|
id: z.uuid(),
|
|
668
857
|
kind: z.string().min(1).max(64).regex(/^[a-z0-9][a-z0-9_-]*$/),
|
|
@@ -688,6 +877,12 @@ export const UpdateNotificationSchema = z.object({
|
|
|
688
877
|
active: z.boolean(),
|
|
689
878
|
requires_interaction: z.boolean(),
|
|
690
879
|
can_dismiss: z.boolean(),
|
|
880
|
+
/** TAL-1138: the update's steps in order; empty for records that are not updates. */
|
|
881
|
+
steps: z.array(UpdateStepSchema).max(8),
|
|
882
|
+
/** TAL-1138: every client that sees this record opens its Updating dialog, which cannot be closed while this holds. */
|
|
883
|
+
presents_dialog: z.boolean(),
|
|
884
|
+
/** TAL-1138: how an open Updating dialog for this record closes: not at all, with Close, with Restart later (the wait goes on), or by itself after showing the outcome. */
|
|
885
|
+
dialog_close: z.enum(['none', 'close', 'restart_later', 'auto']),
|
|
691
886
|
});
|
|
692
887
|
export const FrontendBuildIdSchema = z.string().regex(/^[a-f0-9]{64}$/);
|
|
693
888
|
export const TabIdSchema = z.string().regex(/^[A-Za-z0-9_-]{8,64}$/);
|
|
@@ -710,10 +905,69 @@ export const UpdateNotificationsSchema = z.object({
|
|
|
710
905
|
clearable_count: z.number().int().nonnegative(),
|
|
711
906
|
can_clear: z.boolean(),
|
|
712
907
|
});
|
|
713
|
-
|
|
714
|
-
export const
|
|
908
|
+
/** 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. */
|
|
909
|
+
export const PluginSettingViewSchema = PluginSettingFieldSchema.extend({ locked: z.boolean().optional() });
|
|
910
|
+
/** TAL-1276: a plugin OAuth client as Settings shows it; `can_sign_out` is true while the profile stores a grant for it (any state but `logged_out`). */
|
|
911
|
+
export const PluginOAuthClientViewSchema = PluginOAuthClientSchema.extend({ can_sign_out: z.boolean() });
|
|
912
|
+
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(),
|
|
913
|
+
/** Stored Agent check, absent when the installed Agent lacks cached update support. */
|
|
914
|
+
update: z.object({ available: z.boolean(), latest_revision: z.string().optional() }).optional(),
|
|
915
|
+
/** TAL-806: the manifest's `config_schema` fields with current values; absent when the plugin declares none. */
|
|
916
|
+
settings: z.array(PluginSettingViewSchema).optional(),
|
|
917
|
+
/**
|
|
918
|
+
* TAL-1276: the OAuth clients the manifest declares (Agent v0.22.3+), each with its sign-in state and the two hosts the
|
|
919
|
+
* sign-in sends the code to. Sign in through `/api/onboarding/oauth/start` with provider `plugin:<key>:<id>`; absent
|
|
920
|
+
* when the plugin declares none or the Agent cannot sign in to plugin clients.
|
|
921
|
+
*/
|
|
922
|
+
oauth_clients: z.array(PluginOAuthClientViewSchema).optional() });
|
|
923
|
+
/**
|
|
924
|
+
* `read_only` (TAL-806): this session may not save plugin `settings` (not the server owner, or no sidecar).
|
|
925
|
+
* `plugin_isolation_advisory` (TAL-820): more than one profile has third-party plugins installed and one of those runs them
|
|
926
|
+
* `in_process`, so Settings recommends `plugins.isolation: host`; Talaria never sets the mode.
|
|
927
|
+
*/
|
|
928
|
+
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() });
|
|
715
929
|
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() });
|
|
716
930
|
export const McpServersSchema = z.looseObject({ servers: z.array(McpServerSchema), health_pending: z.boolean().optional(), reload_required: z.boolean().optional(), toggle_supported: z.boolean().optional() });
|
|
931
|
+
/** 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. */
|
|
932
|
+
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() });
|
|
933
|
+
/**
|
|
934
|
+
* TAL-818: one app on the Connectors page. `accounts` are its live accounts, active first. `enabled`: Hermes may use it (the
|
|
935
|
+
* 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
|
|
936
|
+
* may change the member rule (readable rules and no lock). `tools_off` counts the tools the member rules turn off.
|
|
937
|
+
*/
|
|
938
|
+
export const ConnectorViewSchema = z.object({
|
|
939
|
+
slug: z.string(), name: z.string(), description: z.string(), category: z.string(), logo_url: z.string().nullable(),
|
|
940
|
+
connected: z.boolean(), accounts: z.array(ConnectorAccountViewSchema), enabled: z.boolean(), org_locked: z.boolean(), rules_editable: z.boolean(), tools_off: z.number().int(),
|
|
941
|
+
});
|
|
942
|
+
/**
|
|
943
|
+
* TAL-818: the Connectors page. `available` is the Agent's connectors gate; false hides the page. `policy_revision` is the
|
|
944
|
+
* member rules' revision every rule change sends back; null when the rules are read-only (no member layer, or unreadable),
|
|
945
|
+
* so no switch changes them. `sign_in_required` offers Nous sign-in without creating a guest on reads.
|
|
946
|
+
* `rules_error`: why the rules could not be read; every app then reads off (fails closed).
|
|
947
|
+
*/
|
|
948
|
+
export const ConnectorsPageSchema = z.object({ available: z.boolean(), sign_in_required: z.boolean().default(false), connectors: z.array(ConnectorViewSchema), policy_revision: z.string().nullable(), rules_error: z.string().nullable() });
|
|
949
|
+
/**
|
|
950
|
+
* TAL-818: one app's tools: `enabled`: Hermes may use it (the member rules leave it on and nothing locks it); `locked`: an
|
|
951
|
+
* 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).
|
|
952
|
+
*/
|
|
953
|
+
export const ConnectorToolsViewSchema = z.object({
|
|
954
|
+
connector: z.string(), policy_revision: z.string().nullable(),
|
|
955
|
+
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() })),
|
|
956
|
+
});
|
|
957
|
+
/**
|
|
958
|
+
* TAL-818: a connection operation, from the Connectors page's Connect or a chat's `manage_connections` card. Each target's
|
|
959
|
+
* `connect_url` is the authorization link while it waits on one; `actions` are the moves the user may make on it now, and
|
|
960
|
+
* `env_fields` the credentials an `approve` sends, each with its `label`. `can_continue`: the card may end the wait for the
|
|
961
|
+
* rest (chat only). `outcome` is null while the operation is open, then `connected` when every target connected.
|
|
962
|
+
*/
|
|
963
|
+
export const ConnectorOperationViewSchema = z.object({
|
|
964
|
+
op_id: z.string(), settled: z.boolean(), outcome: z.enum(['connected', 'not_connected']).nullable(), can_continue: z.boolean(), tool_call_id: z.string().nullable(),
|
|
965
|
+
targets: z.array(z.object({
|
|
966
|
+
name: z.string(), title: z.string(), kind: z.string(), state: z.enum(['pending', 'initiated', 'connected', 'skipped', 'failed', 'expired', 'not_connected']),
|
|
967
|
+
detail: z.string(), connect_url: z.string().nullable(), actions: z.array(z.enum(['skip', 'retry', 'approve'])),
|
|
968
|
+
env_fields: z.array(z.object({ name: z.string(), label: z.string(), required: z.boolean(), secret: z.boolean() })),
|
|
969
|
+
})),
|
|
970
|
+
});
|
|
717
971
|
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() });
|
|
718
972
|
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() });
|
|
719
973
|
/** Joplin search hit: bounded, redacted display text and a snippet around the query; `updated_time` is Joplin's raw value. */
|
|
@@ -750,6 +1004,13 @@ export const OnboardingProbeSchema = z.looseObject({ ok: z.boolean().optional(),
|
|
|
750
1004
|
export const OnboardingOAuthSchema = z.looseObject({
|
|
751
1005
|
ok: z.boolean().optional(), status: z.string().optional(), url: z.string().optional(), verification_url: z.string().optional(), user_code: z.string().optional(), message: z.string().optional(),
|
|
752
1006
|
error: z.string().nullable().optional(), flow_id: z.string().optional(), provider: z.string().optional(), expires_in: z.number().int().optional(), interval: z.number().int().optional(),
|
|
1007
|
+
/**
|
|
1008
|
+
* TAL-1276, a plugin client's browser sign-in (`plugin:<key>:<id>`, no `user_code`): `verification_url` is the
|
|
1009
|
+
* authorize link, `authorize_host` and `token_host` the hosts the code goes to, and `redirect_uri` the address the
|
|
1010
|
+
* browser is sent back to. When that address does not open on this machine, send the one the browser shows to
|
|
1011
|
+
* `/api/plugins/oauth/redirect`.
|
|
1012
|
+
*/
|
|
1013
|
+
authorize_host: z.string().optional(), token_host: z.string().optional(), redirect_uri: z.string().optional(),
|
|
753
1014
|
});
|
|
754
1015
|
// ── automation ───────────────────────────────────────────────────────────
|
|
755
1016
|
export const CronScheduleSchema = z.looseObject({ kind: z.string().optional(), expr: z.string().optional(), minutes: z.number().optional(), run_at: z.string().optional(), display: z.string().optional() });
|
|
@@ -767,12 +1028,17 @@ export const CronJobViewSchema = z.looseObject({
|
|
|
767
1028
|
derived_state: CronDerivedStateSchema.optional(), needs_attention: z.boolean().optional(), resumable: z.boolean().optional(),
|
|
768
1029
|
/** Server-derived (TAL-599): a known cause clients explain in the needs-attention banner. */
|
|
769
1030
|
attention_hint: z.enum(['croniter_missing']).nullable(),
|
|
1031
|
+
/** Server-normalized (TAL-810): the job's latest failed run, kept after later successes; `at` is epoch seconds, null when unparseable. */
|
|
1032
|
+
last_failure: z.object({ at: z.number().nullable(), detail: z.string() }).nullable(),
|
|
770
1033
|
});
|
|
1034
|
+
/** 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. */
|
|
1035
|
+
export const CronStoreHealthSchema = z.object({ profile: z.string(), store: z.string(), error: z.string(), fix: z.string(), since: z.number().nullable() });
|
|
771
1036
|
export const CronsSchema = z.looseObject({
|
|
772
1037
|
jobs: z.array(CronJobViewSchema),
|
|
773
1038
|
/** TAL-601: `jobs` arrive in display order (running first, then soonest next run, none last, then name); clients keep it. Absent from older servers. */
|
|
774
1039
|
ordered: z.boolean().optional(),
|
|
775
1040
|
active_profile: z.string().optional(), all_profiles: z.boolean().optional(), other_profile_count: z.number().optional(), cron_unavailable: z.boolean().optional(),
|
|
1041
|
+
unwritable_stores: z.array(CronStoreHealthSchema),
|
|
776
1042
|
});
|
|
777
1043
|
export const CronContextSourcesSchema = z.object({ profile: z.string(), sources: z.array(z.object({ job_id: z.string(), label: z.string(), selectable: z.boolean() })) });
|
|
778
1044
|
/** `GET /api/crons/recent` row: one job's latest completion, ordered and classified by the server. */
|
|
@@ -793,18 +1059,21 @@ export const KanbanTaskActionsSchema = z.object({ block: z.boolean(), unblock: z
|
|
|
793
1059
|
/** 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. */
|
|
794
1060
|
export const KanbanTaskPolicyShape = { available_actions: KanbanTaskActionsSchema, requires_running_exit_confirmation: z.boolean() };
|
|
795
1061
|
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 });
|
|
796
|
-
|
|
1062
|
+
/** A board column in the Agent workflow's order (TAL-796): `name` is the status key, `label` the Agent's English label. */
|
|
1063
|
+
export const KanbanColumnSchema = z.looseObject({ name: z.string(), label: z.string(), tasks: z.array(KanbanTaskViewSchema) });
|
|
797
1064
|
/** One profile lane (TAL-567): an assignee's tasks (`null` = unassigned) across every board column, with its task count. */
|
|
798
1065
|
export const KanbanLaneSchema = z.object({ assignee: z.string().nullable(), count: z.number().int(), columns: z.array(KanbanColumnSchema) });
|
|
799
1066
|
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(),
|
|
800
1067
|
/** Statuses a bulk status change may target (TAL-557). */
|
|
801
1068
|
bulk_move_targets: z.array(z.string()),
|
|
1069
|
+
/** Statuses a new task may start in (TAL-796). */
|
|
1070
|
+
create_statuses: z.array(z.string()),
|
|
802
1071
|
/** The saved board view (TAL-567): `true` groups the board into `lanes` by assignee. */
|
|
803
1072
|
lane_by_profile: z.boolean(),
|
|
804
1073
|
/** Present when `lane_by_profile`: the columns split into profile lanes, assignees in name order, unassigned last. */
|
|
805
1074
|
lanes: z.array(KanbanLaneSchema).optional() });
|
|
806
1075
|
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(),
|
|
807
|
-
/** Whether the board can be archived or deleted; the default board
|
|
1076
|
+
/** Whether the board can be archived or deleted; the default board (TAL-567) and an archived board (TAL-795) cannot. */
|
|
808
1077
|
removable: z.boolean() })), current: z.string().optional(), read_only: z.boolean().optional() });
|
|
809
1078
|
/** Board-wide task counts (TAL-567): `status_counts` in board-column order, unknown statuses after; `total` excludes archived tasks. */
|
|
810
1079
|
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() })) });
|