@maudecode/talaria-web-contracts 1.19.0 → 1.21.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.
Files changed (84) hide show
  1. package/dist/checkpoint.d.ts +78 -0
  2. package/dist/checkpoint.js +16 -0
  3. package/dist/checkpoint.js.map +1 -0
  4. package/dist/context-detail.d.ts +75 -0
  5. package/dist/context-detail.js +18 -0
  6. package/dist/context-detail.js.map +1 -0
  7. package/dist/gateway-session.d.ts +412 -9
  8. package/dist/gateway-session.js +85 -3
  9. package/dist/gateway-session.js.map +1 -1
  10. package/dist/index.d.ts +5 -0
  11. package/dist/index.js +5 -0
  12. package/dist/index.js.map +1 -1
  13. package/dist/mcp-cost-policy.d.ts +110 -0
  14. package/dist/mcp-cost-policy.js +24 -0
  15. package/dist/mcp-cost-policy.js.map +1 -0
  16. package/dist/outbound-drafts.d.ts +114 -0
  17. package/dist/outbound-drafts.js +20 -0
  18. package/dist/outbound-drafts.js.map +1 -0
  19. package/dist/prompt-queue.d.ts +96 -0
  20. package/dist/prompt-queue.js +19 -0
  21. package/dist/prompt-queue.js.map +1 -0
  22. package/dist/router.d.ts +3677 -156
  23. package/dist/routes/automation.d.ts +323 -2
  24. package/dist/routes/automation.js +17 -3
  25. package/dist/routes/automation.js.map +1 -1
  26. package/dist/routes/chat.d.ts +776 -26
  27. package/dist/routes/chat.js +4 -3
  28. package/dist/routes/chat.js.map +1 -1
  29. package/dist/routes/core.d.ts +6 -6
  30. package/dist/routes/git.d.ts +59 -0
  31. package/dist/routes/git.js +9 -3
  32. package/dist/routes/git.js.map +1 -1
  33. package/dist/routes/raw.js +9 -5
  34. package/dist/routes/raw.js.map +1 -1
  35. package/dist/routes/sessions.d.ts +2215 -87
  36. package/dist/routes/sessions.js +11 -0
  37. package/dist/routes/sessions.js.map +1 -1
  38. package/dist/routes/settings.d.ts +29 -13
  39. package/dist/routes/settings.js +3 -2
  40. package/dist/routes/settings.js.map +1 -1
  41. package/dist/routes/tools.d.ts +825 -37
  42. package/dist/routes/tools.js +33 -5
  43. package/dist/routes/tools.js.map +1 -1
  44. package/dist/routes/workspaces.d.ts +49 -4
  45. package/dist/routes/workspaces.js +5 -4
  46. package/dist/routes/workspaces.js.map +1 -1
  47. package/dist/sidecar/methods.d.ts +1122 -25
  48. package/dist/sidecar/methods.js +2 -2
  49. package/dist/sidecar/methods.js.map +1 -1
  50. package/dist/sidecar/namespaces.d.ts +1292 -39
  51. package/dist/sidecar/namespaces.js +120 -14
  52. package/dist/sidecar/namespaces.js.map +1 -1
  53. package/dist/sidecar/rpc.d.ts +1 -0
  54. package/dist/sidecar/rpc.js +2 -0
  55. package/dist/sidecar/rpc.js.map +1 -1
  56. package/dist/sidecar/runtime.d.ts +56 -0
  57. package/dist/sidecar/runtime.js +21 -2
  58. package/dist/sidecar/runtime.js.map +1 -1
  59. package/dist/sidecar/version.d.ts +1 -1
  60. package/dist/sidecar/version.js +1 -1
  61. package/dist/sse.d.ts +199 -10
  62. package/dist/sse.js +15 -4
  63. package/dist/sse.js.map +1 -1
  64. package/dist/views.d.ts +1597 -86
  65. package/dist/views.js +106 -21
  66. package/dist/views.js.map +1 -1
  67. package/fixtures/sidecar/aux.json +8 -0
  68. package/fixtures/sidecar/chat.json +14 -0
  69. package/fixtures/sidecar/checkpoints.json +7 -2
  70. package/fixtures/sidecar/context-detail.json +77 -0
  71. package/fixtures/sidecar/cron.json +3 -1
  72. package/fixtures/sidecar/dashboard_plugins.json +59 -0
  73. package/fixtures/sidecar/gateway.json +208 -0
  74. package/fixtures/sidecar/kanban.json +197 -0
  75. package/fixtures/sidecar/managed-buffers.json +16 -0
  76. package/fixtures/sidecar/mcp.json +12 -0
  77. package/fixtures/sidecar/outbound-drafts.json +1 -0
  78. package/fixtures/sidecar/plugin-catalog.json +4 -0
  79. package/fixtures/sidecar/plugins.json +56 -1
  80. package/fixtures/sidecar/process.json +32 -0
  81. package/fixtures/sidecar/rpc.json +4 -0
  82. package/fixtures/sidecar/runtime.json +3 -3
  83. package/fixtures/sidecar/state_db.json +10 -0
  84. package/package.json +1 -1
package/dist/views.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { McpCostPolicySchema } from './mcp-cost-policy.js';
1
2
  /**
2
3
  * Pinned response shapes shared by every consumer (formerly the frontend's
3
4
  * hand-written `src/contracts/*` schemas). Known fields are typed; every
@@ -5,11 +6,12 @@
5
6
  * that must survive a round trip (documented passthrough).
6
7
  */
7
8
  import { z } from 'zod';
9
+ import { OutboundDraftRefSchema } from './outbound-drafts.js';
8
10
  import { RunStatusSchema } from './run-status.js';
9
- import { AgentRefreshConfirmationSchema } from './sidecar/runtime.js';
11
+ import { AgentRefreshConfirmationSchema, AgentUpdateOperationSchema } from './sidecar/runtime.js';
10
12
  import { SpeedTierSchema } from './speed.js';
11
- import { OwnerAttachmentSchema } from './gateway-session.js';
12
- import { CanonicalBotChatSchema, GatewayModeSchema, PluginSettingFieldSchema, SkillCatalogIdentitySchema } from './sidecar/namespaces.js';
13
+ import { ExecutionModeSchema, OwnerAttachmentSchema, MessageReactionViewSchema } from './gateway-session.js';
14
+ import { KanbanInspectionNodeSchema, KanbanInspectionSnapshotSchema, CanonicalBotChatSchema, GatewayModeSchema, PluginOAuthClientSchema, PluginSettingFieldSchema, SkillCatalogIdentitySchema } from './sidecar/namespaces.js';
13
15
  export { SpeedTierSchema } from './speed.js';
14
16
  const Json = z.unknown();
15
17
  export const NullableString = z.string().nullable();
@@ -43,15 +45,20 @@ export const DiffHunkSchema = z.object({
43
45
  * that diff parsed (TAL-604). Absent on a call whose result has no diff.
44
46
  */
45
47
  export const ToolEditDiffSchema = z.object({ added: z.number().int(), removed: z.number().int(), diff: z.string(), truncated: z.boolean(), hunks: z.array(DiffHunkSchema) });
46
- /** Server-derived display fields every tool call carries: the kind, and the redacted first-line label of its main argument (`''` when none; omitted on a live frame with none, which keeps its start frame's target), and a file edit's `edit_diff`. */
47
- export const ToolDisplayFields = { kind: ToolKindSchema.optional(), target: z.string().optional(), edit_diff: ToolEditDiffSchema.optional() };
48
+ /** The latest server-normalized MCP update; never stored with the transcript. */
49
+ export const ToolProgressSchema = z.object({ percent: z.number().min(0).max(100).nullable(), message: z.string().nullable() });
50
+ /** Shared tool display fields. Progress is ephemeral, absent on older servers and null after completion. */
51
+ export const ToolDisplayFields = {
52
+ progress: ToolProgressSchema.nullable().optional(), kind: ToolKindSchema.optional(), target: z.string().optional(), edit_diff: ToolEditDiffSchema.optional(),
53
+ focus_path: NullableString.optional().describe('TAL-1458: a read or write call\'s file as a workspace-relative path, the file a companion page shows; absent for any other call or an absolute, home or out-of-workspace path.'),
54
+ };
48
55
  /**
49
56
  * TAL-315: a tool result's display sections, decided by the server's one rule for live, replayed and persisted results
50
57
  * alike. Clients show `stdout`, `stderr`, a labelled `error` and a labelled `exit_code` (sent only when worth showing), or
51
58
  * `text`, in that order, and never parse result text. Each string is capped server-side; a client without the field
52
59
  * shows `preview`.
53
60
  */
54
- export const ToolResultViewSchema = z.object({ text: z.string().optional(), stdout: z.string().optional(), stderr: z.string().optional(), error: z.string().optional(), exit_code: z.number().int().optional() });
61
+ export const ToolResultViewSchema = z.object({ outbound_draft: OutboundDraftRefSchema.optional(), text: z.string().optional(), stdout: z.string().optional(), stderr: z.string().optional(), error: z.string().optional(), exit_code: z.number().int().optional() });
55
62
  /**
56
63
  * Stored transcripts carry the OpenAI shape (`function.name` / `function.arguments` JSON string); live events carry `name` / `args`.
57
64
  * On an assistant row the server resolves every call (TAL-313, `session-sse-contract-v1.md`): Anthropic `tool_use` parts and
@@ -129,6 +136,7 @@ export const BackgroundLineSchema = z.object({ kind: z.enum(['agent', 'command',
129
136
  });
130
137
  export const MessageSchema = z.looseObject({
131
138
  role: z.string(), content: MessageContentSchema.optional(), id: MessageIdSchema.optional(), message_id: MessageIdSchema.optional(), timestamp: z.number().nullable().optional(),
139
+ reaction_view: MessageReactionViewSchema.optional(),
132
140
  attachments: z.array(AttachmentSchema).optional(), tool_calls: z.array(ToolCallSchema).optional(),
133
141
  /**
134
142
  * TAL-302: an assistant row's whole reasoning as one string (its reasoning fields, typed thinking parts and inline
@@ -286,8 +294,19 @@ export const CompressionReferenceSchema = z.object({
286
294
  });
287
295
  /** TAL-454: the chat a `/branch` copied, with its redacted title. */
288
296
  export const BranchedFromSchema = z.object({ session_id: SessionIdSchema, title: z.string() });
297
+ export const MAX_SOURCE_REFERENCES = 5;
298
+ export const SourceReferenceSchema = z.object({
299
+ session_id: z.string().regex(/^[A-Za-z0-9_-]{1,128}$/).describe('Retained logical conversation identity.'),
300
+ tip_session_id: z.string().regex(/^[A-Za-z0-9_-]{1,128}$/),
301
+ profile: z.string().min(1).max(128),
302
+ });
303
+ export const AcceptedSourceReferenceSchema = SourceReferenceSchema.extend({ title: z.string() });
289
304
  /** Full session record from `GET /api/session` and mutations returning `session`. */
305
+ export const SessionActivityPhaseSchema = z.enum(['starting', 'running', 'waiting_for_approval', 'waiting_for_input', 'completed', 'failed', 'cancelled', 'stale']);
290
306
  export const SessionSchema = z.looseObject({
307
+ activity_phase: SessionActivityPhaseSchema.optional(),
308
+ source_references: z.array(AcceptedSourceReferenceSchema).optional(),
309
+ context_detail_key: z.string().nullable().optional().describe('Opaque identity for open-only context details; changes with owner epoch, model and context.'),
291
310
  composer_state_key: z.string().optional().describe('Opaque profile-home and owner identity for device-local composer state; never an API session id.'),
292
311
  session_id: SessionIdSchema, title: z.string(), workspace: z.string().optional(), created_workspace: z.string().nullable().optional(), model: NullableString.optional(), model_provider: NullableString.optional(),
293
312
  model_option_id: NullableString.optional().describe('TAL-301: the catalog entry id the stored model/provider selects; null when none.'),
@@ -302,11 +321,14 @@ export const SessionSchema = z.looseObject({
302
321
  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(),
303
322
  pending_user_message: NullableString.optional(), pending_attachments: z.array(AttachmentSchema).optional(), pending_started_at: NullableNumber.optional(), pending_user_source: NullableString.optional(),
304
323
  context_length: NullableNumber.optional(), threshold_tokens: NullableNumber.optional(), last_prompt_tokens: NullableNumber.optional(), post_compression_context_tokens_estimate: NullableNumber.optional(), ...ContextUsageFields,
324
+ execution_mode: ExecutionModeSchema.optional().describe('TAL-1040: the Agent execution policy frozen when the session was created; absent from older servers.'),
305
325
  enabled_toolsets: z.array(z.string()).nullable().optional(), composer_draft: ComposerDraftSchema.optional(), is_cli_session: z.boolean().optional(), source_kind: SourceKindSchema, is_messaging_session: IsMessagingSessionSchema, sort_ts: SortTsSchema, read_only: ReadOnlySchema, read_only_reason: ReadOnlyReasonSchema, owner_attachment: OwnerAttachmentSchema.optional(), can_branch: CanBranchSchema, can_pin: CanPinSchema, can_archive: CanArchiveSchema, can_delete: CanDeleteSchema, can_duplicate: CanDuplicateSchema, source_tag: NullableString.optional(),
306
326
  can_compress: z.boolean().optional().describe('TAL-614: a manual compression would start now: writable, no running turn, and at least four model-history messages. Only the full session detail carries it; absent means no.'),
307
327
  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.'),
308
328
  source_label: NullableString.optional(), session_source: NullableString.optional(), raw_source: NullableString.optional(), parent_session_id: NullableString.optional(), worktree_path: NullableString.optional(),
309
- worktree_branch: NullableString.optional(), worktree_repo_root: NullableString.optional(), share_token: NullableString.optional(), share_url: NullableString.optional(), share_created_at: NullableNumber.optional(), manual_title: z.boolean().optional(),
329
+ worktree_branch: NullableString.optional(), worktree_repo_root: NullableString.optional(),
330
+ 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.'),
331
+ share_token: NullableString.optional(), share_url: NullableString.optional(), share_created_at: NullableNumber.optional(), manual_title: z.boolean().optional(),
310
332
  compression_anchor_summary: NullableString.optional(), compression_recovery: z.record(z.string(), Json).optional(), recommended_recovery_action: NullableString.optional(), compression_recovery_action: NullableString.optional(),
311
333
  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(),
312
334
  /**
@@ -319,6 +341,7 @@ export const SessionSchema = z.looseObject({
319
341
  assistant_name: z.string().optional(),
320
342
  workspace_name: WorkspaceNameSchema,
321
343
  compression_reference: CompressionReferenceSchema.nullable().optional(),
344
+ focus_path: NullableString.optional().describe('TAL-1458: the last non-null `focus_path` of the session\'s persisted tool calls, so a reopened chat shows its file before any stream event; null when none.'),
322
345
  branched_from: BranchedFromSchema.nullable().optional().describe('TAL-454: the chat this one was branched from while it still loads (archived included); null for a compression continuation, a deleted or missing parent, and every other chat.'),
323
346
  });
324
347
  export const SessionEnvelopeSchema = z.looseObject({ session: SessionSchema });
@@ -349,6 +372,7 @@ export const SessionsListSchema = z.looseObject({
349
372
  archived_limit: z.number().int().nullable().optional(), archived_offset: z.number().int().optional(),
350
373
  });
351
374
  export const SessionStatusSchema = z.looseObject({
375
+ activity_phase: SessionActivityPhaseSchema.optional(),
352
376
  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(),
353
377
  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(),
354
378
  });
@@ -379,7 +403,7 @@ export const ChatStartResponseSchema = z.looseObject({
379
403
  * stream's session: this run while it unwinds after a Stop, or a successor such as a goal continuation. A session delete
380
404
  * answers 409 while it is set, so a client draining a session before deleting it waits until it is null.
381
405
  */
382
- export const StreamStatusSchema = z.looseObject({ active: z.boolean(), stream_id: z.string(), replay_available: z.boolean().optional(), journal: Json.optional(), blocking_stream_id: z.string().nullable() });
406
+ export const StreamStatusSchema = z.looseObject({ activity_phase: SessionActivityPhaseSchema.optional(), active: z.boolean(), stream_id: z.string(), replay_available: z.boolean().optional(), journal: Json.optional(), blocking_stream_id: z.string().nullable() });
383
407
  /**
384
408
  * TAL-424: a pending steer is no longer pending without the Agent taking it: Edit and Cancel by the user, `stopped` by a
385
409
  * Stop (`text` goes back to the composer), or `followup` when the server sends it as the next turn. `steer_id` is null
@@ -390,7 +414,7 @@ export const SteerWithdrawnSchema = z.object({ steer_id: z.string().nullable(),
390
414
  * `withdrawn_steers` (TAL-426): the steers this Stop withdrew, the same `steer_withdrawn` (stopped) the stream carries, so
391
415
  * a client that stops reading the stream once the Stop answers still gives its own text back.
392
416
  */
393
- export const CancelResponseSchema = z.looseObject({ ok: z.boolean(), cancelled: z.boolean(), stream_id: z.string().optional(), withdrawn_steers: z.array(SteerWithdrawnSchema).optional(), error: z.string().optional() });
417
+ export const CancelResponseSchema = z.looseObject({ activity_phase: SessionActivityPhaseSchema.optional(), ok: z.boolean(), cancelled: z.boolean(), stream_id: z.string().optional(), withdrawn_steers: z.array(SteerWithdrawnSchema).optional(), error: z.string().optional() });
394
418
  export const SteerWithdrawRequestSchema = z.object({ session_id: SessionIdSchema, steer_id: z.string().min(1), reason: z.enum(['edit', 'cancel']) });
395
419
  /** `withdrawn: false` when the steer is unknown, already taken by the Agent (it then settles as consumed), or being sent. */
396
420
  export const SteerWithdrawResponseSchema = z.object({ withdrawn: z.boolean(), text: z.string().optional() });
@@ -413,7 +437,8 @@ export const ApprovalRespondRequestSchema = z.looseObject({ session_id: SessionI
413
437
  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() });
414
438
  export const ClarifyChoiceSchema = z.union([z.string(), z.looseObject({ label: z.string().optional(), value: z.string().optional(), text: z.string().optional() })]);
415
439
  /** One question the client asks, in server order; answers are keyed by `qid`. A single-question prompt is one `q0` step. */
416
- export const ClarifyStepSchema = z.looseObject({ qid: z.string(), question: z.string(), choices: z.array(z.string()), multi_select: z.boolean() });
440
+ export const ClarifyStepSchema = z.looseObject({ qid: z.string(), question: z.string(), choices: z.array(z.string()), multi_select: z.boolean(),
441
+ 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.') });
417
442
  /** Keyed step answers; a multi-select step takes a list. The server shapes them into the Agent's reply. */
418
443
  export const ClarifyAnswersSchema = z.record(z.string(), z.union([z.string(), z.array(z.string())]));
419
444
  /** TAL-887: one input of a password-manager prompt, answered under its `key`; a `secure` input is masked. */
@@ -477,6 +502,8 @@ export const BackgroundTaskSchema = z.object({
477
502
  agents: BackgroundLinkSchema.shape.agents.nullable(),
478
503
  pinned: z.boolean(),
479
504
  dismissible: z.boolean(),
505
+ /** TAL-1172: confirmed running work this session may stop. */
506
+ can_stop: z.boolean().optional(),
480
507
  active: z.boolean(),
481
508
  });
482
509
  /**
@@ -484,17 +511,25 @@ export const BackgroundTaskSchema = z.object({
484
511
  * result. `agents_working` (TAL-373): a delegation is running or needs attention, whatever `kind` the list is narrowed to;
485
512
  * the chat's side panel opens on Agents for it. Absent from servers before TAL-373.
486
513
  */
487
- export const BackgroundTasksResponseSchema = z.object({ session_id: z.string(), tasks: z.array(BackgroundTaskSchema), agent_available: z.boolean(), agents_working: z.boolean().optional() });
514
+ export const BackgroundTasksResponseSchema = z.object({ activity_phase: SessionActivityPhaseSchema.optional(), session_id: z.string(), tasks: z.array(BackgroundTaskSchema), agent_available: z.boolean(), agents_working: z.boolean().optional() });
488
515
  export const BackgroundTaskResultSchema = z.object({ task_id: z.string(), text: z.string() });
489
516
  export const BackgroundDismissRequestSchema = z.object({ session_id: SessionIdSchema, task_id: z.string().min(1) });
517
+ export const BackgroundStopResponseSchema = z.object({ outcome: z.enum(['stopped', 'not_running', 'not_found']) });
490
518
  export const BackgroundDismissResponseSchema = z.object({ ok: z.literal(true), task: BackgroundTaskSchema });
491
519
  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 });
492
520
  export const ShareMessageSchema = z.looseObject({ role: z.string(), content: z.union([z.string(), z.null(), z.array(Json)]).optional() });
493
521
  export const ShareSchema = z.looseObject({ title: z.string(), messages: z.array(ShareMessageSchema), message_count: z.number().int(), created_at: z.number().optional(), updated_at: z.number().optional(), model: NullableString.optional() });
494
522
  export const ShareReadSchema = z.looseObject({ share: ShareSchema });
523
+ export const SourceReferenceSearchSchema = z.object({
524
+ sessions: z.array(SessionRowSchema.extend({ source_reference: SourceReferenceSchema })),
525
+ active_profile: z.string(), max_sources: z.number().int(),
526
+ });
495
527
  export const SessionNewRequestSchema = z.looseObject({
496
528
  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(),
497
529
  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(),
530
+ execution_mode: ExecutionModeSchema.optional().describe('TAL-1040: `ignore_config` and `safe` start the session through the Agent owner; omitted means normal.'),
531
+ request_id: z.string().regex(/^[A-Za-z0-9_-]{1,64}$/).optional().describe('TAL-1040: stable creation identity for a diagnostic or referenced chat. Reuse it only to retry the same creation.'),
532
+ source_references: z.array(SourceReferenceSchema).max(MAX_SOURCE_REFERENCES).optional().describe('Same-profile search pointers. Nonempty selections require request_id; unavailable or changed identities refuse creation.'),
498
533
  });
499
534
  /**
500
535
  * `streaming` (TAL-802): live dictation over `TRANSCRIBE_STREAM_PATH` would open for this profile (`stt.streaming` on, a live provider wire).
@@ -541,7 +576,7 @@ export const ProfilesSchema = z.looseObject({ profiles: z.array(ProfileSchema),
541
576
  export const ActiveProfileSchema = z.looseObject({ name: z.string(), path: z.string().optional(), is_default: z.boolean().optional(), default_workspace: NullableString.optional() });
542
577
  export const ProfileSwitchSchema = ProfilesSchema.extend({ is_default: z.boolean(), default_model: Json, default_model_provider: Json, default_workspace: z.string().nullable() });
543
578
  /** `/api/reasoning`: config.yaml agent.reasoning_effort / display.show_reasoning, resolved for a model. */
544
- export const ReasoningStatusSchema = z.looseObject({ show_reasoning: z.boolean().optional(), reasoning_effort: z.string().nullable().optional(), supported_efforts: z.array(z.string()).optional(), supports_reasoning_effort: z.boolean().optional(), supports_thinking_toggle: z.boolean().optional() });
579
+ 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() });
545
580
  export const QuotaLevelSchema = z.enum(['healthy', 'warning', 'critical', 'stale', 'unavailable']);
546
581
  /**
547
582
  * 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.
@@ -676,15 +711,17 @@ export const MaxTokensSchema = z.looseObject({ max_tokens: NullableNumber, max_t
676
711
  export const WorkspaceEntrySchema = z.looseObject({ name: z.string().min(1), path: z.string() });
677
712
  export const WorkspacesSchema = z.looseObject({ workspaces: z.array(WorkspaceEntrySchema), last: NullableString.optional(), terminal_remote_backend: z.boolean().optional() });
678
713
  export const FileEntrySchema = z.looseObject({
679
- name: z.string(), path: z.string().optional(), is_dir: z.boolean().optional(), type: z.string().optional(), size: z.number().nullable().optional(), mtime: z.number().nullable().optional(), mtime_ns: z.union([z.number(), z.string()]).nullable().optional(),
714
+ read_only: z.boolean().optional(), name: z.string(), path: z.string().optional(), is_dir: z.boolean().optional(), type: z.string().optional(), size: z.number().nullable().optional(), mtime: z.number().nullable().optional(), mtime_ns: z.union([z.number(), z.string()]).nullable().optional(),
680
715
  birthtime_ns: z.union([z.number(), z.string()]).nullable().optional(), hidden: z.boolean().optional(), workspace_sort_rank: z.number().int().optional(), target: z.string().optional(), target_outside_workspace: z.boolean().optional(),
681
716
  });
682
- export const DirListingSchema = z.looseObject({ path: z.string().optional(), entries: z.array(FileEntrySchema), signature: z.string().optional(), workspace: z.string().optional(), workspace_recovered: z.boolean().optional(), is_git: z.boolean().optional() });
717
+ export const FileSourceSchema = z.enum(['workspace', 'managed']);
718
+ const ManagedFileFields = { source: FileSourceSchema.optional(), read_only: z.boolean().optional(), write_semantics: z.literal('unconditional').optional() };
719
+ export const DirListingSchema = z.looseObject({ ...ManagedFileFields, unavailable: z.boolean().optional(), path: z.string().optional(), entries: z.array(FileEntrySchema), signature: z.string().optional(), workspace: z.string().optional(), workspace_recovered: z.boolean().optional(), is_git: z.boolean().optional() });
683
720
  /** How a workspace file renders (TAL-566): media streams from `/api/file/raw`; text kinds carry `content`. */
684
721
  export const FilePreviewKindSchema = z.enum(['text', 'markdown', 'csv', 'html', 'image', 'pdf', 'audio', 'video', 'binary']);
685
722
  /** `table` is a `csv` preview's leading rows (header first); `table_truncated` says the file has more. `preview_url` is an
686
723
  * `html` preview's app-relative frame URL, under which the page's relative assets also resolve. */
687
- export const FileContentSchema = z.looseObject({
724
+ export const FileContentSchema = z.looseObject({ ...ManagedFileFields, name: z.string().optional(),
688
725
  path: z.string().optional(), content: z.string().optional(), lines: z.number().optional(), size: z.number().optional(), truncated: z.boolean().optional(), binary: z.boolean().optional(), mime: z.string().optional(),
689
726
  preview: FilePreviewKindSchema.optional(), table: z.array(z.array(z.string())).optional(), table_truncated: z.boolean().optional(),
690
727
  preview_url: z.string().optional(),
@@ -806,7 +843,7 @@ export const UpdateTargetSchema = z.looseObject({
806
843
  versions: z.array(UpdateVersionSchema).describe('TAL-946: every installable Stable release newer than the installed one, newest first; empty unless `release_ready` can apply.'),
807
844
  folded_count: z.number().int().nonnegative().describe('How many `versions` are `folded`.'),
808
845
  });
809
- export const AgentRecoveryStateSchema = z.object({ phase: z.enum(['idle', 'running', 'waiting', 'complete', 'blocked']), attempt: z.number().int().nonnegative(), detail: z.string(), retry_at: z.string().nullable() });
846
+ 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(), operation_id: z.uuid().optional(), operation: AgentUpdateOperationSchema.optional(), verified_revision: z.string().regex(/^[a-f0-9]{40}$/).optional(), runtime_revision: z.string().regex(/^[a-f0-9]{40}$/).optional(), verified_version: z.string().nullable().optional() });
810
847
  export const UpdatesCheckSchema = z.looseObject({ agent_recovery: AgentRecoveryStateSchema.optional(), disabled: z.boolean().optional(), cached: z.boolean().optional(), channel: z.string().optional(), agent_channel: z.enum(['stable', 'experimental']).optional(), checked_at: z.number().optional(), include_agent: z.boolean().optional(), webui: UpdateTargetSchema.nullable().optional(), agent: UpdateTargetSchema.nullable().optional() });
811
848
  export const UpdatesSummarySchema = z.object({
812
849
  ok: z.boolean(), target: z.enum(['webui', 'agent']), summary: z.string(),
@@ -818,11 +855,15 @@ export const UpdatesSummarySchema = z.object({
818
855
  cached: z.boolean(),
819
856
  });
820
857
  export const UpdateApplySchema = z.looseObject({
858
+ recovery_only: z.boolean().optional().describe('Only a retained transaction was repaired; the selected update outcome remains unverified.'),
859
+ recovery_pending: z.boolean().optional().describe('The initiating operation remains active through automatic recovery; follow its notification_id without replaying the update.'),
860
+ verified_revision: z.string().regex(/^[a-f0-9]{40}$/).optional(), verified_version: z.string().nullable().optional(),
821
861
  recovery_compatibility: z.object({ manual_execution: z.boolean(), bot_chat_delivery: z.boolean() }).optional()
822
862
  .describe('Whether the target Agent can reconcile retained manual execution and pending Bot Chat records. A false value blocks the update before any source or repair-intent change.'),
823
863
  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.')
824
864
  });
825
- export const UpdateNotificationPhaseSchema = z.enum(['applying', 'awaiting_confirmation', 'waiting_for_idle', 'restarting', 'succeeded', 'blocked', 'failed', 'unknown']);
865
+ /** `verifying` (TAL-1138): the gateway restarted, and the server is checking that the new gateway process and the Agent runtime answer. */
866
+ export const UpdateNotificationPhaseSchema = z.enum(['applying', 'awaiting_confirmation', 'waiting_for_idle', 'restarting', 'verifying', 'recovering', 'succeeded', 'blocked', 'failed', 'unknown']);
826
867
  export const UpdateNotificationActionSchema = z.object({
827
868
  id: z.string().min(1).max(64).regex(/^[a-z0-9][a-z0-9_-]*$/),
828
869
  label: z.string().min(1).max(80),
@@ -833,6 +874,17 @@ export const UpdateNotificationDestinationSchema = z.object({
833
874
  key: z.string().min(1).max(64).regex(/^[a-z0-9][a-z0-9_.-]*$/),
834
875
  label: z.string().min(1).max(80),
835
876
  });
877
+ /** TAL-1138: one step of an update as its Updating dialog lists it; the server derives every label and state. */
878
+ export const UpdateStepSchema = z.object({
879
+ id: z.enum(['install', 'web_restart', 'ready', 'gateway_wait', 'gateway_restart', 'agent_ready', 'recovery']),
880
+ label: z.string().min(1).max(80),
881
+ state: z.enum(['done', 'active', 'pending', 'failed']),
882
+ });
883
+ export const AgentUpdateRecoverySchema = z.object({
884
+ operation: AgentUpdateOperationSchema, attempt_error: z.string().max(2000).nullable(), runtime_revision: z.string().regex(/^[a-f0-9]{40}$/).nullable(),
885
+ rollback: z.boolean().nullable().optional(),
886
+ outcome: z.enum(['recovering', 'target_installed', 'baseline_restored', 'other_revision', 'blocked', 'unknown']),
887
+ });
836
888
  export const UpdateNotificationSchema = z.object({
837
889
  id: z.uuid(),
838
890
  kind: z.string().min(1).max(64).regex(/^[a-z0-9][a-z0-9_-]*$/),
@@ -854,10 +906,17 @@ export const UpdateNotificationSchema = z.object({
854
906
  verified_version: z.string().min(1).max(80).nullable(),
855
907
  /** The apply's own explanation of a failed or blocked attempt, or of a success that needs attention (an Agent update that kept local edits in the git stash), line breaks kept; null otherwise. */
856
908
  detail: z.string().max(2000).nullable(),
909
+ recovery: AgentUpdateRecoverySchema.optional(),
857
910
  unread: z.boolean(),
858
911
  active: z.boolean(),
859
912
  requires_interaction: z.boolean(),
860
913
  can_dismiss: z.boolean(),
914
+ /** TAL-1138: the update's steps in order; empty for records that are not updates. */
915
+ steps: z.array(UpdateStepSchema).max(8),
916
+ /** TAL-1138: every client that sees this record opens its Updating dialog, which cannot be closed while this holds. */
917
+ presents_dialog: z.boolean(),
918
+ /** 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. */
919
+ dialog_close: z.enum(['none', 'close', 'restart_later', 'auto']),
861
920
  });
862
921
  export const FrontendBuildIdSchema = z.string().regex(/^[a-f0-9]{64}$/);
863
922
  export const TabIdSchema = z.string().regex(/^[A-Za-z0-9_-]{8,64}$/);
@@ -882,16 +941,26 @@ export const UpdateNotificationsSchema = z.object({
882
941
  });
883
942
  /** TAL-806: a plugin setting as Settings shows it; `locked` marks a secret the server's launch environment supplies, so an edit would not take effect. */
884
943
  export const PluginSettingViewSchema = PluginSettingFieldSchema.extend({ locked: z.boolean().optional() });
944
+ /** 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`). */
945
+ export const PluginOAuthClientViewSchema = PluginOAuthClientSchema.extend({ can_sign_out: z.boolean() });
885
946
  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(),
947
+ /** Stored Agent check, absent when the installed Agent lacks cached update support. */
948
+ update: z.object({ available: z.boolean(), latest_revision: z.string().optional() }).optional(),
886
949
  /** TAL-806: the manifest's `config_schema` fields with current values; absent when the plugin declares none. */
887
- settings: z.array(PluginSettingViewSchema).optional() });
950
+ settings: z.array(PluginSettingViewSchema).optional(),
951
+ /**
952
+ * TAL-1276: the OAuth clients the manifest declares (Agent v0.22.3+), each with its sign-in state and the two hosts the
953
+ * sign-in sends the code to. Sign in through `/api/onboarding/oauth/start` with provider `plugin:<key>:<id>`; absent
954
+ * when the plugin declares none or the Agent cannot sign in to plugin clients.
955
+ */
956
+ oauth_clients: z.array(PluginOAuthClientViewSchema).optional() });
888
957
  /**
889
958
  * `read_only` (TAL-806): this session may not save plugin `settings` (not the server owner, or no sidecar).
890
959
  * `plugin_isolation_advisory` (TAL-820): more than one profile has third-party plugins installed and one of those runs them
891
960
  * `in_process`, so Settings recommends `plugins.isolation: host`; Talaria never sets the mode.
892
961
  */
893
962
  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() });
894
- export const McpServerSchema = z.looseObject({ name: z.string(), id: z.string().optional(), transport: z.string().optional(), enabled: z.boolean().optional(), can_toggle: z.boolean().optional().describe('Whether PATCH can enable or disable this server; false for invalid config.'), active: z.boolean().optional(), status: z.string().optional(), tools: z.number().optional(), tool_count: z.number().int().nullable().optional(), health: z.string().optional(), health_detail: z.string().optional(), health_checked_at: Json.optional(), health_pending: z.boolean().optional() });
963
+ export const McpServerSchema = z.looseObject({ cost_policy: McpCostPolicySchema.nullable().optional(), 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() });
895
964
  export const McpServersSchema = z.looseObject({ servers: z.array(McpServerSchema), health_pending: z.boolean().optional(), reload_required: z.boolean().optional(), toggle_supported: z.boolean().optional() });
896
965
  /** TAL-818: one connected account of a Nous tool-gateway app; `name` is its alias, else the vendor label. `problem` is its gateway status while it is not active, else null. */
897
966
  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() });
@@ -907,9 +976,10 @@ export const ConnectorViewSchema = z.object({
907
976
  /**
908
977
  * TAL-818: the Connectors page. `available` is the Agent's connectors gate; false hides the page. `policy_revision` is the
909
978
  * member rules' revision every rule change sends back; null when the rules are read-only (no member layer, or unreadable),
910
- * so no switch changes them. `rules_error`: why the rules could not be read; every app then reads off (fails closed).
979
+ * so no switch changes them. `sign_in_required` offers Nous sign-in without creating a guest on reads.
980
+ * `rules_error`: why the rules could not be read; every app then reads off (fails closed).
911
981
  */
912
- export const ConnectorsPageSchema = z.object({ available: z.boolean(), connectors: z.array(ConnectorViewSchema), policy_revision: z.string().nullable(), rules_error: z.string().nullable() });
982
+ 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() });
913
983
  /**
914
984
  * TAL-818: one app's tools: `enabled`: Hermes may use it (the member rules leave it on and nothing locks it); `locked`: an
915
985
  * 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).
@@ -968,6 +1038,13 @@ export const OnboardingProbeSchema = z.looseObject({ ok: z.boolean().optional(),
968
1038
  export const OnboardingOAuthSchema = z.looseObject({
969
1039
  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(),
970
1040
  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(),
1041
+ /**
1042
+ * TAL-1276, a plugin client's browser sign-in (`plugin:<key>:<id>`, no `user_code`): `verification_url` is the
1043
+ * authorize link, `authorize_host` and `token_host` the hosts the code goes to, and `redirect_uri` the address the
1044
+ * browser is sent back to. When that address does not open on this machine, send the one the browser shows to
1045
+ * `/api/plugins/oauth/redirect`.
1046
+ */
1047
+ authorize_host: z.string().optional(), token_host: z.string().optional(), redirect_uri: z.string().optional(),
971
1048
  });
972
1049
  // ── automation ───────────────────────────────────────────────────────────
973
1050
  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() });
@@ -1018,6 +1095,14 @@ export const KanbanTaskPolicyShape = { available_actions: KanbanTaskActionsSchem
1018
1095
  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 });
1019
1096
  /** A board column in the Agent workflow's order (TAL-796): `name` is the status key, `label` the Agent's English label. */
1020
1097
  export const KanbanColumnSchema = z.looseObject({ name: z.string(), label: z.string(), tasks: z.array(KanbanTaskViewSchema) });
1098
+ /** One bounded profile-scoped read shared by timeline and relationship layouts. Null timing means unknown, never planned effort. */
1099
+ export const KanbanInspectionSchema = KanbanInspectionSnapshotSchema.extend({
1100
+ nodes: z.array(KanbanInspectionNodeSchema.extend({ task: KanbanTaskViewSchema,
1101
+ ancestors: z.array(z.string()), descendants: z.array(z.string()), cycle: z.boolean(), running_lineage: z.boolean(),
1102
+ timing: z.object({ start: z.number().nullable(), end: z.number().nullable(), duration_seconds: z.number().nullable(), offset: z.number().nullable(), width: z.number().nullable() }),
1103
+ })).max(500),
1104
+ window: z.object({ start: z.number().nullable(), end: z.number().nullable() }),
1105
+ });
1021
1106
  /** One profile lane (TAL-567): an assignee's tasks (`null` = unassigned) across every board column, with its task count. */
1022
1107
  export const KanbanLaneSchema = z.object({ assignee: z.string().nullable(), count: z.number().int(), columns: z.array(KanbanColumnSchema) });
1023
1108
  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(),