@maudecode/talaria-web-contracts 1.19.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.
Files changed (66) hide show
  1. package/dist/context-detail.d.ts +75 -0
  2. package/dist/context-detail.js +18 -0
  3. package/dist/context-detail.js.map +1 -0
  4. package/dist/gateway-session.d.ts +253 -7
  5. package/dist/gateway-session.js +63 -3
  6. package/dist/gateway-session.js.map +1 -1
  7. package/dist/index.d.ts +1 -0
  8. package/dist/index.js +1 -0
  9. package/dist/index.js.map +1 -1
  10. package/dist/router.d.ts +1398 -191
  11. package/dist/routes/automation.d.ts +9 -7
  12. package/dist/routes/automation.js +1 -1
  13. package/dist/routes/automation.js.map +1 -1
  14. package/dist/routes/chat.d.ts +303 -40
  15. package/dist/routes/chat.js +4 -3
  16. package/dist/routes/chat.js.map +1 -1
  17. package/dist/routes/core.d.ts +4 -4
  18. package/dist/routes/git.d.ts +9 -0
  19. package/dist/routes/git.js +6 -1
  20. package/dist/routes/git.js.map +1 -1
  21. package/dist/routes/raw.js +9 -5
  22. package/dist/routes/raw.js.map +1 -1
  23. package/dist/routes/sessions.d.ts +921 -124
  24. package/dist/routes/sessions.js +6 -0
  25. package/dist/routes/sessions.js.map +1 -1
  26. package/dist/routes/settings.d.ts +29 -13
  27. package/dist/routes/settings.js +3 -2
  28. package/dist/routes/settings.js.map +1 -1
  29. package/dist/routes/tools.d.ts +314 -30
  30. package/dist/routes/tools.js +14 -4
  31. package/dist/routes/tools.js.map +1 -1
  32. package/dist/routes/workspaces.d.ts +4 -4
  33. package/dist/sidecar/methods.d.ts +816 -19
  34. package/dist/sidecar/methods.js +2 -2
  35. package/dist/sidecar/methods.js.map +1 -1
  36. package/dist/sidecar/namespaces.d.ts +959 -28
  37. package/dist/sidecar/namespaces.js +101 -14
  38. package/dist/sidecar/namespaces.js.map +1 -1
  39. package/dist/sidecar/rpc.d.ts +1 -0
  40. package/dist/sidecar/rpc.js +2 -0
  41. package/dist/sidecar/rpc.js.map +1 -1
  42. package/dist/sidecar/runtime.d.ts +13 -0
  43. package/dist/sidecar/runtime.js +9 -0
  44. package/dist/sidecar/runtime.js.map +1 -1
  45. package/dist/sidecar/version.d.ts +1 -1
  46. package/dist/sidecar/version.js +1 -1
  47. package/dist/sse.d.ts +83 -12
  48. package/dist/sse.js +8 -2
  49. package/dist/sse.js.map +1 -1
  50. package/dist/views.d.ts +584 -103
  51. package/dist/views.js +54 -11
  52. package/dist/views.js.map +1 -1
  53. package/fixtures/sidecar/aux.json +8 -0
  54. package/fixtures/sidecar/chat.json +14 -0
  55. package/fixtures/sidecar/checkpoints.json +7 -2
  56. package/fixtures/sidecar/context-detail.json +77 -0
  57. package/fixtures/sidecar/cron.json +3 -1
  58. package/fixtures/sidecar/dashboard_plugins.json +59 -0
  59. package/fixtures/sidecar/gateway.json +163 -0
  60. package/fixtures/sidecar/plugin-catalog.json +4 -0
  61. package/fixtures/sidecar/plugins.json +56 -1
  62. package/fixtures/sidecar/process.json +32 -0
  63. package/fixtures/sidecar/rpc.json +4 -0
  64. package/fixtures/sidecar/runtime.json +3 -3
  65. package/fixtures/sidecar/state_db.json +10 -0
  66. package/package.json +1 -1
package/dist/views.js CHANGED
@@ -8,8 +8,8 @@ import { z } from 'zod';
8
8
  import { RunStatusSchema } from './run-status.js';
9
9
  import { AgentRefreshConfirmationSchema } from './sidecar/runtime.js';
10
10
  import { SpeedTierSchema } from './speed.js';
11
- import { OwnerAttachmentSchema } from './gateway-session.js';
12
- import { CanonicalBotChatSchema, GatewayModeSchema, PluginSettingFieldSchema, SkillCatalogIdentitySchema } from './sidecar/namespaces.js';
11
+ import { ExecutionModeSchema, OwnerAttachmentSchema } from './gateway-session.js';
12
+ import { CanonicalBotChatSchema, GatewayModeSchema, PluginOAuthClientSchema, PluginSettingFieldSchema, SkillCatalogIdentitySchema } from './sidecar/namespaces.js';
13
13
  export { SpeedTierSchema } from './speed.js';
14
14
  const Json = z.unknown();
15
15
  export const NullableString = z.string().nullable();
@@ -43,8 +43,10 @@ export const DiffHunkSchema = z.object({
43
43
  * that diff parsed (TAL-604). Absent on a call whose result has no diff.
44
44
  */
45
45
  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() };
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() };
48
50
  /**
49
51
  * TAL-315: a tool result's display sections, decided by the server's one rule for live, replayed and persisted results
50
52
  * alike. Clients show `stdout`, `stderr`, a labelled `error` and a labelled `exit_code` (sent only when worth showing), or
@@ -288,6 +290,7 @@ export const CompressionReferenceSchema = z.object({
288
290
  export const BranchedFromSchema = z.object({ session_id: SessionIdSchema, title: z.string() });
289
291
  /** Full session record from `GET /api/session` and mutations returning `session`. */
290
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.'),
291
294
  composer_state_key: z.string().optional().describe('Opaque profile-home and owner identity for device-local composer state; never an API session id.'),
292
295
  session_id: SessionIdSchema, title: z.string(), workspace: z.string().optional(), created_workspace: z.string().nullable().optional(), model: NullableString.optional(), model_provider: NullableString.optional(),
293
296
  model_option_id: NullableString.optional().describe('TAL-301: the catalog entry id the stored model/provider selects; null when none.'),
@@ -302,11 +305,14 @@ export const SessionSchema = z.looseObject({
302
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(),
303
306
  pending_user_message: NullableString.optional(), pending_attachments: z.array(AttachmentSchema).optional(), pending_started_at: NullableNumber.optional(), pending_user_source: NullableString.optional(),
304
307
  context_length: NullableNumber.optional(), threshold_tokens: NullableNumber.optional(), last_prompt_tokens: NullableNumber.optional(), post_compression_context_tokens_estimate: NullableNumber.optional(), ...ContextUsageFields,
308
+ execution_mode: ExecutionModeSchema.optional().describe('TAL-1040: the Agent execution policy frozen when the session was created; absent from older servers.'),
305
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(),
306
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.'),
307
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.'),
308
312
  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(),
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(),
310
316
  compression_anchor_summary: NullableString.optional(), compression_recovery: z.record(z.string(), Json).optional(), recommended_recovery_action: NullableString.optional(), compression_recovery_action: NullableString.optional(),
311
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(),
312
318
  /**
@@ -413,7 +419,8 @@ export const ApprovalRespondRequestSchema = z.looseObject({ session_id: SessionI
413
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() });
414
420
  export const ClarifyChoiceSchema = z.union([z.string(), z.looseObject({ label: z.string().optional(), value: z.string().optional(), text: z.string().optional() })]);
415
421
  /** 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() });
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.') });
417
424
  /** Keyed step answers; a multi-select step takes a list. The server shapes them into the Agent's reply. */
418
425
  export const ClarifyAnswersSchema = z.record(z.string(), z.union([z.string(), z.array(z.string())]));
419
426
  /** TAL-887: one input of a password-manager prompt, answered under its `key`; a `secure` input is masked. */
@@ -477,6 +484,8 @@ export const BackgroundTaskSchema = z.object({
477
484
  agents: BackgroundLinkSchema.shape.agents.nullable(),
478
485
  pinned: z.boolean(),
479
486
  dismissible: z.boolean(),
487
+ /** TAL-1172: confirmed running work this session may stop. */
488
+ can_stop: z.boolean().optional(),
480
489
  active: z.boolean(),
481
490
  });
482
491
  /**
@@ -487,6 +496,7 @@ export const BackgroundTaskSchema = z.object({
487
496
  export const BackgroundTasksResponseSchema = z.object({ session_id: z.string(), tasks: z.array(BackgroundTaskSchema), agent_available: z.boolean(), agents_working: z.boolean().optional() });
488
497
  export const BackgroundTaskResultSchema = z.object({ task_id: z.string(), text: z.string() });
489
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']) });
490
500
  export const BackgroundDismissResponseSchema = z.object({ ok: z.literal(true), task: BackgroundTaskSchema });
491
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 });
492
502
  export const ShareMessageSchema = z.looseObject({ role: z.string(), content: z.union([z.string(), z.null(), z.array(Json)]).optional() });
@@ -495,6 +505,8 @@ export const ShareReadSchema = z.looseObject({ share: ShareSchema });
495
505
  export const SessionNewRequestSchema = z.looseObject({
496
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(),
497
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.'),
498
510
  });
499
511
  /**
500
512
  * `streaming` (TAL-802): live dictation over `TRANSCRIBE_STREAM_PATH` would open for this profile (`stt.streaming` on, a live provider wire).
@@ -541,7 +553,7 @@ export const ProfilesSchema = z.looseObject({ profiles: z.array(ProfileSchema),
541
553
  export const ActiveProfileSchema = z.looseObject({ name: z.string(), path: z.string().optional(), is_default: z.boolean().optional(), default_workspace: NullableString.optional() });
542
554
  export const ProfileSwitchSchema = ProfilesSchema.extend({ is_default: z.boolean(), default_model: Json, default_model_provider: Json, default_workspace: z.string().nullable() });
543
555
  /** `/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() });
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() });
545
557
  export const QuotaLevelSchema = z.enum(['healthy', 'warning', 'critical', 'stale', 'unavailable']);
546
558
  /**
547
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.
@@ -822,7 +834,8 @@ export const UpdateApplySchema = z.looseObject({
822
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.'),
823
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.')
824
836
  });
825
- export const UpdateNotificationPhaseSchema = z.enum(['applying', 'awaiting_confirmation', 'waiting_for_idle', 'restarting', 'succeeded', 'blocked', 'failed', 'unknown']);
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']);
826
839
  export const UpdateNotificationActionSchema = z.object({
827
840
  id: z.string().min(1).max(64).regex(/^[a-z0-9][a-z0-9_-]*$/),
828
841
  label: z.string().min(1).max(80),
@@ -833,6 +846,12 @@ export const UpdateNotificationDestinationSchema = z.object({
833
846
  key: z.string().min(1).max(64).regex(/^[a-z0-9][a-z0-9_.-]*$/),
834
847
  label: z.string().min(1).max(80),
835
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
+ });
836
855
  export const UpdateNotificationSchema = z.object({
837
856
  id: z.uuid(),
838
857
  kind: z.string().min(1).max(64).regex(/^[a-z0-9][a-z0-9_-]*$/),
@@ -858,6 +877,12 @@ export const UpdateNotificationSchema = z.object({
858
877
  active: z.boolean(),
859
878
  requires_interaction: z.boolean(),
860
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']),
861
886
  });
862
887
  export const FrontendBuildIdSchema = z.string().regex(/^[a-f0-9]{64}$/);
863
888
  export const TabIdSchema = z.string().regex(/^[A-Za-z0-9_-]{8,64}$/);
@@ -882,9 +907,19 @@ export const UpdateNotificationsSchema = z.object({
882
907
  });
883
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. */
884
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() });
885
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(),
886
915
  /** TAL-806: the manifest's `config_schema` fields with current values; absent when the plugin declares none. */
887
- settings: z.array(PluginSettingViewSchema).optional() });
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() });
888
923
  /**
889
924
  * `read_only` (TAL-806): this session may not save plugin `settings` (not the server owner, or no sidecar).
890
925
  * `plugin_isolation_advisory` (TAL-820): more than one profile has third-party plugins installed and one of those runs them
@@ -907,9 +942,10 @@ export const ConnectorViewSchema = z.object({
907
942
  /**
908
943
  * TAL-818: the Connectors page. `available` is the Agent's connectors gate; false hides the page. `policy_revision` is the
909
944
  * 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).
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).
911
947
  */
912
- export const ConnectorsPageSchema = z.object({ available: z.boolean(), connectors: z.array(ConnectorViewSchema), policy_revision: z.string().nullable(), rules_error: z.string().nullable() });
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() });
913
949
  /**
914
950
  * TAL-818: one app's tools: `enabled`: Hermes may use it (the member rules leave it on and nothing locks it); `locked`: an
915
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).
@@ -968,6 +1004,13 @@ export const OnboardingProbeSchema = z.looseObject({ ok: z.boolean().optional(),
968
1004
  export const OnboardingOAuthSchema = z.looseObject({
969
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(),
970
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(),
971
1014
  });
972
1015
  // ── automation ───────────────────────────────────────────────────────────
973
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() });