@otto-code/protocol 0.5.2 → 0.5.5

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/messages.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { z } from "zod";
2
2
  import { TerminalActivitySchema } from "./terminal-activity.js";
3
+ import { RunSchema } from "./orchestration.js";
3
4
  import { ArtifactMetadataSchema } from "./artifacts/types.js";
4
5
  import { ArtifactListRequestSchema, ArtifactCreateRequestSchema, ArtifactUpdateRequestSchema, ArtifactRegenerateRequestSchema, ArtifactCancelRequestSchema, ArtifactDeleteRequestSchema, ArtifactStarRequestSchema, ArtifactGetContentRequestSchema, ArtifactListResponseSchema, ArtifactCreateResponseSchema, ArtifactUpdateResponseSchema, ArtifactRegenerateResponseSchema, ArtifactCancelResponseSchema, ArtifactDeleteResponseSchema, ArtifactStarResponseSchema, ArtifactGetContentResponseSchema, ArtifactCreatedNotificationSchema, ArtifactUpdatedNotificationSchema, ArtifactDeletedNotificationSchema, } from "./artifacts/rpc-schemas.js";
5
6
  import { CLIENT_CAPS } from "./client-capabilities.js";
@@ -139,13 +140,20 @@ export const MutableGitHostingConfigSchema = z
139
140
  // agent-personalities.ts) so personalities persisted before the split keep their
140
141
  // role rather than silently losing it.
141
142
  export const PERSONALITY_ROLES = [
143
+ // Surfaces — the interactive / host-facing entry points.
142
144
  "chatter",
143
145
  "artificer",
144
146
  "scheduler",
145
- "writer",
146
- "coder",
147
+ // Thinking workers — read-only, return structured findings, never edit.
148
+ "researcher",
149
+ "planner",
147
150
  "judger",
148
151
  "advisor",
152
+ // Making workers — produce code, design, or short text.
153
+ "coder",
154
+ "designer",
155
+ "writer",
156
+ // Conductor — the sole role whose whole job is planning and driving a team.
149
157
  "orchestrator",
150
158
  ];
151
159
  // Two glow colors for the personality's thinking spinner (BlobLoader glowA/glowB).
@@ -788,7 +796,7 @@ export const AgentSnapshotPayloadSchema = z.object({
788
796
  // cost-less local models. Observed subagents source it from the provider's
789
797
  // per-task usage.total_tokens (already cumulative-per-subagent). Purely
790
798
  // additive; absent ⇒ no readout. Old clients ignore it.
791
- // See projects/subagents-cleanup/subagents-cleanup.md (Item 3).
799
+ // See docs/agent-lifecycle.md (Item 3).
792
800
  cumulativeTokens: z.number().optional(),
793
801
  lastError: z.string().optional(),
794
802
  title: z.string().nullable(),
@@ -807,17 +815,17 @@ export const AgentSnapshotPayloadSchema = z.object({
807
815
  // Spinner colors from the Agent Personality this agent was spawned from, so
808
816
  // its live thinking indicator renders in the personality's identity. Absent ⇒
809
817
  // the client falls back to the theme's default spinner colors. Purely additive
810
- // (no daemon floor needed). See projects/agent-personalities/.
818
+ // (no daemon floor needed). See docs/agent-personalities.md.
811
819
  personalitySpinner: AgentPersonalitySpinnerSchema.optional(),
812
820
  // Name of the Agent Personality this agent was spawned from, so the running
813
821
  // agent's controls keep showing the personality identity (trigger label +
814
822
  // effort hidden) instead of reverting to the raw model. Absent ⇒ no bound
815
- // personality. Purely additive. See projects/agent-personalities/.
823
+ // personality. Purely additive. See docs/agent-personalities.md.
816
824
  personalityName: z.string().optional(),
817
825
  // Stable id of the bound Agent Personality. The client keys roster selection
818
826
  // on this (names can be renamed/duplicated); personalityName remains for
819
827
  // display and as the selection fallback against daemons that predate this
820
- // field. Purely additive. See projects/agent-personalities/.
828
+ // field. Purely additive. See docs/agent-personalities.md.
821
829
  personalityId: z.string().optional(),
822
830
  });
823
831
  export const AgentListItemPayloadSchema = z.object({
@@ -1321,6 +1329,38 @@ export const ProviderUsageListRequestMessageSchema = z.object({
1321
1329
  type: z.literal("provider.usage.list.request"),
1322
1330
  requestId: z.string(),
1323
1331
  });
1332
+ // Daemon-wide "fun stats" counters — see docs/data-model.md ActivityStatsStore.
1333
+ // Every field defaults to 0 so old and new daemons/clients stay compatible as
1334
+ // counters are added later.
1335
+ export const ActivityCountersSchema = z.object({
1336
+ messagesSent: z.number().default(0),
1337
+ messagesReceived: z.number().default(0),
1338
+ tokensSent: z.number().default(0),
1339
+ tokensReceived: z.number().default(0),
1340
+ agentsCreated: z.number().default(0),
1341
+ runsOrchestrated: z.number().default(0),
1342
+ subagentsInvoked: z.number().default(0),
1343
+ backgroundTasksInvoked: z.number().default(0),
1344
+ thoughts: z.number().default(0),
1345
+ toolsCalled: z.number().default(0),
1346
+ artifactsCreated: z.number().default(0),
1347
+ schedulesExecuted: z.number().default(0),
1348
+ });
1349
+ export const StatsActivityGetRequestMessageSchema = z.object({
1350
+ type: z.literal("stats.activity.get.request"),
1351
+ requestId: z.string(),
1352
+ });
1353
+ export const StatsActivityGetResponseMessageSchema = z.object({
1354
+ type: z.literal("stats.activity.get.response"),
1355
+ payload: z.object({
1356
+ requestId: z.string(),
1357
+ today: ActivityCountersSchema,
1358
+ yesterday: ActivityCountersSchema,
1359
+ last7Days: ActivityCountersSchema,
1360
+ last30Days: ActivityCountersSchema,
1361
+ allTime: ActivityCountersSchema,
1362
+ }),
1363
+ });
1324
1364
  export const AgentContextGetUsageRequestMessageSchema = z.object({
1325
1365
  type: z.literal("agent.context.get_usage.request"),
1326
1366
  agentId: z.string(),
@@ -1456,6 +1496,56 @@ export const AgentSubagentStopResponseMessageSchema = z.object({
1456
1496
  type: z.literal("agent.subagent.stop.response"),
1457
1497
  payload: AgentActionResponsePayloadSchema,
1458
1498
  });
1499
+ // A background shell task launched by a provider's own Bash tool (Claude:
1500
+ // run_in_background). Not an agent, not a subagent — a plain shell process
1501
+ // the daemon tracks for the parent agent's Background Tasks track.
1502
+ // COMPAT(backgroundShellTasks): added in v0.5.3, drop the gate when daemon floor >= v0.5.3.
1503
+ export const BackgroundShellTaskInfoSchema = z.object({
1504
+ id: z.string(),
1505
+ parentAgentId: z.string(),
1506
+ provider: z.string(),
1507
+ command: z.string().optional(),
1508
+ description: z.string().optional(),
1509
+ status: z.enum(["running", "idle", "error", "closed"]),
1510
+ requiresAttention: z.boolean().optional(),
1511
+ createdAt: z.string(),
1512
+ updatedAt: z.string(),
1513
+ archivedAt: z.string().optional(),
1514
+ });
1515
+ // Pushed with the full current set of background shell tasks for a parent
1516
+ // agent whenever any of them changes (start/progress/settle/clear) — same
1517
+ // full-list reconciliation shape as TerminalsChangedSchema.
1518
+ export const BackgroundShellTasksChangedSchema = z.object({
1519
+ type: z.literal("background_shell_tasks_changed"),
1520
+ payload: z.object({
1521
+ parentAgentId: z.string(),
1522
+ tasks: z.array(BackgroundShellTaskInfoSchema),
1523
+ }),
1524
+ });
1525
+ // Stop a running background shell task. The daemon resolves it to the owning
1526
+ // provider session's task and calls stopTask, same as agent.subagent.stop.
1527
+ export const AgentBackgroundTaskStopRequestMessageSchema = z.object({
1528
+ type: z.literal("agent.background_task.stop.request"),
1529
+ parentAgentId: z.string(),
1530
+ taskId: z.string(),
1531
+ requestId: z.string(),
1532
+ });
1533
+ export const AgentBackgroundTaskStopResponseMessageSchema = z.object({
1534
+ type: z.literal("agent.background_task.stop.response"),
1535
+ payload: AgentActionResponsePayloadSchema,
1536
+ });
1537
+ // Clear one or more terminal background shell tasks from the track. Still-live
1538
+ // tasks are stopped best-effort first.
1539
+ export const AgentBackgroundTaskClearRequestMessageSchema = z.object({
1540
+ type: z.literal("agent.background_task.clear.request"),
1541
+ parentAgentId: z.string(),
1542
+ taskIds: z.array(z.string()),
1543
+ requestId: z.string(),
1544
+ });
1545
+ export const AgentBackgroundTaskClearResponseMessageSchema = z.object({
1546
+ type: z.literal("agent.background_task.clear.response"),
1547
+ payload: AgentActionResponsePayloadSchema,
1548
+ });
1459
1549
  // Switch a running agent to an Agent Personality (or clear with null). The
1460
1550
  // daemon re-resolves the id against the roster + the agent's cwd provider
1461
1551
  // snapshot and applies the full personality live — system prompt, identity
@@ -1622,6 +1712,80 @@ export const CheckoutGitLogAppendedNotificationSchema = z.object({
1622
1712
  entries: z.array(GitOperationLogEntrySchema),
1623
1713
  }),
1624
1714
  });
1715
+ // ── Orchestration runs (agent-orchestration) ────────────────────────────────
1716
+ // Daemon-owned multi-agent Run projection + control. Gated by
1717
+ // server_info.features.agentOrchestration. See projects/agent-orchestration.
1718
+ export const RunsGetSnapshotRequestSchema = z.object({
1719
+ type: z.literal("runs.get_snapshot.request"),
1720
+ requestId: z.string(),
1721
+ });
1722
+ export const RunsGetSnapshotResponseSchema = z.object({
1723
+ type: z.literal("runs.get_snapshot.response"),
1724
+ payload: z.object({
1725
+ runs: z.array(RunSchema),
1726
+ requestId: z.string(),
1727
+ }),
1728
+ });
1729
+ // Single-run push, broadcast on every phase/status change. Clients merge by id.
1730
+ export const RunsUpdatedNotificationSchema = z.object({
1731
+ type: z.literal("runs.updated.notification"),
1732
+ payload: z.object({
1733
+ run: RunSchema,
1734
+ }),
1735
+ });
1736
+ // Answer an attended run's `gate` phase (approve or reject, with an optional
1737
+ // note). `accepted` is false when the run wasn't awaiting a gate.
1738
+ export const RunsGateRespondRequestSchema = z.object({
1739
+ type: z.literal("runs.gate_respond.request"),
1740
+ runId: z.string(),
1741
+ phaseId: z.string(),
1742
+ approved: z.boolean(),
1743
+ note: z.string().optional(),
1744
+ requestId: z.string(),
1745
+ });
1746
+ export const RunsGateRespondResponseSchema = z.object({
1747
+ type: z.literal("runs.gate_respond.response"),
1748
+ payload: z.object({
1749
+ runId: z.string(),
1750
+ accepted: z.boolean(),
1751
+ requestId: z.string(),
1752
+ }),
1753
+ });
1754
+ export const RunsCancelRequestSchema = z.object({
1755
+ type: z.literal("runs.cancel.request"),
1756
+ runId: z.string(),
1757
+ requestId: z.string(),
1758
+ });
1759
+ export const RunsCancelResponseSchema = z.object({
1760
+ type: z.literal("runs.cancel.response"),
1761
+ payload: z.object({
1762
+ runId: z.string(),
1763
+ canceled: z.boolean(),
1764
+ requestId: z.string(),
1765
+ }),
1766
+ });
1767
+ // Delete every finished (done/failed/canceled) run from disk and memory.
1768
+ // Active/paused runs are left untouched. Gated by
1769
+ // server_info.features.runsClear.
1770
+ export const RunsClearRequestSchema = z.object({
1771
+ type: z.literal("runs.clear.request"),
1772
+ requestId: z.string(),
1773
+ });
1774
+ export const RunsClearResponseSchema = z.object({
1775
+ type: z.literal("runs.clear.response"),
1776
+ payload: z.object({
1777
+ runIds: z.array(z.string()),
1778
+ requestId: z.string(),
1779
+ }),
1780
+ });
1781
+ // Broadcast to every connected client (including the requester) so all
1782
+ // caches drop the same runs, mirroring runs.updated.notification's upsert.
1783
+ export const RunsClearedNotificationSchema = z.object({
1784
+ type: z.literal("runs.cleared.notification"),
1785
+ payload: z.object({
1786
+ runIds: z.array(z.string()),
1787
+ }),
1788
+ });
1625
1789
  // Namespaced successor to checkout_commit_request: per-file selection and
1626
1790
  // structured errors. Gated by server_info.features.checkoutGitCommit; the flat
1627
1791
  // RPC stays accepted for old clients.
@@ -2320,6 +2484,7 @@ export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
2320
2484
  RefreshProvidersSnapshotRequestMessageSchema,
2321
2485
  ProviderDiagnosticRequestMessageSchema,
2322
2486
  ProviderUsageListRequestMessageSchema,
2487
+ StatsActivityGetRequestMessageSchema,
2323
2488
  AgentContextGetUsageRequestMessageSchema,
2324
2489
  ResumeAgentRequestMessageSchema,
2325
2490
  ImportAgentRequestMessageSchema,
@@ -2336,6 +2501,8 @@ export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
2336
2501
  SetAgentFeatureRequestMessageSchema,
2337
2502
  AgentDetachRequestMessageSchema,
2338
2503
  AgentSubagentStopRequestMessageSchema,
2504
+ AgentBackgroundTaskStopRequestMessageSchema,
2505
+ AgentBackgroundTaskClearRequestMessageSchema,
2339
2506
  AgentPersonalitySetRequestMessageSchema,
2340
2507
  AgentRewindRequestMessageSchema,
2341
2508
  AgentPermissionResponseMessageSchema,
@@ -2347,6 +2514,10 @@ export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
2347
2514
  CheckoutGitCommitAgentRequestSchema,
2348
2515
  CheckoutGitRollbackRequestSchema,
2349
2516
  CheckoutGitGetOperationLogRequestSchema,
2517
+ RunsGetSnapshotRequestSchema,
2518
+ RunsGateRespondRequestSchema,
2519
+ RunsCancelRequestSchema,
2520
+ RunsClearRequestSchema,
2350
2521
  CheckoutMergeRequestSchema,
2351
2522
  CheckoutMergeFromBaseRequestSchema,
2352
2523
  CheckoutPullRequestSchema,
@@ -2623,6 +2794,8 @@ export const ServerInfoStatusPayloadSchema = z
2623
2794
  artifacts: z.boolean().optional(),
2624
2795
  // COMPAT(observedSubagents): added in v0.4.3, drop the gate when daemon floor >= v0.4.3.
2625
2796
  observedSubagents: z.boolean().optional(),
2797
+ // COMPAT(backgroundShellTasks): added in v0.5.3, drop the gate when daemon floor >= v0.5.3.
2798
+ backgroundShellTasks: z.boolean().optional(),
2626
2799
  // COMPAT(textEditor): added in v0.4.4, drop the gate when daemon floor >= v0.4.4.
2627
2800
  textEditor: z.boolean().optional(),
2628
2801
  // COMPAT(projectSearch): added in v0.4.4, drop the gate when daemon floor >= v0.4.4.
@@ -2653,6 +2826,12 @@ export const ServerInfoStatusPayloadSchema = z
2653
2826
  agentTeams: z.boolean().optional(),
2654
2827
  // COMPAT(modelTierOverrides): added in v0.5.2, drop the gate when daemon floor >= v0.5.2.
2655
2828
  modelTierOverrides: z.boolean().optional(),
2829
+ // COMPAT(agentOrchestration): added in v0.5.3, drop the gate when daemon floor >= v0.5.3.
2830
+ agentOrchestration: z.boolean().optional(),
2831
+ // COMPAT(activityStats): added in v0.5.3, drop the gate when daemon floor >= v0.5.3.
2832
+ activityStats: z.boolean().optional(),
2833
+ // COMPAT(runsClear): added in v0.5.3, drop the gate when daemon floor >= v0.5.3.
2834
+ runsClear: z.boolean().optional(),
2656
2835
  })
2657
2836
  .optional(),
2658
2837
  })
@@ -3213,7 +3392,7 @@ export const CancelAgentResponseMessageSchema = z.object({
3213
3392
  // Whether an in-flight run was actually interrupted. False when the agent
3214
3393
  // had nothing running (already finished, still initializing), so clients
3215
3394
  // can say "nothing to stop" instead of silently no-oping. Purely additive;
3216
- // absent ⇒ unknown (old daemon). See projects/subagents-cleanup/subagents-cleanup.md (Item 2).
3395
+ // absent ⇒ unknown (old daemon). See docs/agent-lifecycle.md (Item 2).
3217
3396
  cancelled: z.boolean().optional(),
3218
3397
  }),
3219
3398
  });
@@ -4807,6 +4986,9 @@ export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
4807
4986
  SetAgentFeatureResponseMessageSchema,
4808
4987
  AgentDetachResponseMessageSchema,
4809
4988
  AgentSubagentStopResponseMessageSchema,
4989
+ AgentBackgroundTaskStopResponseMessageSchema,
4990
+ AgentBackgroundTaskClearResponseMessageSchema,
4991
+ BackgroundShellTasksChangedSchema,
4810
4992
  AgentPersonalitySetResponseMessageSchema,
4811
4993
  AgentRewindResponseMessageSchema,
4812
4994
  UpdateAgentResponseMessageSchema,
@@ -4829,6 +5011,12 @@ export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
4829
5011
  CheckoutGitRollbackResponseSchema,
4830
5012
  CheckoutGitGetOperationLogResponseSchema,
4831
5013
  CheckoutGitLogAppendedNotificationSchema,
5014
+ RunsGetSnapshotResponseSchema,
5015
+ RunsUpdatedNotificationSchema,
5016
+ RunsGateRespondResponseSchema,
5017
+ RunsCancelResponseSchema,
5018
+ RunsClearResponseSchema,
5019
+ RunsClearedNotificationSchema,
4832
5020
  CheckoutMergeResponseSchema,
4833
5021
  CheckoutMergeFromBaseResponseSchema,
4834
5022
  CheckoutPullResponseSchema,
@@ -4881,6 +5069,7 @@ export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
4881
5069
  RefreshProvidersSnapshotResponseMessageSchema,
4882
5070
  ProviderDiagnosticResponseMessageSchema,
4883
5071
  ProviderUsageListResponseMessageSchema,
5072
+ StatsActivityGetResponseMessageSchema,
4884
5073
  AgentContextGetUsageResponseMessageSchema,
4885
5074
  ListCommandsResponseSchema,
4886
5075
  ListTerminalsResponseSchema,
@@ -0,0 +1,152 @@
1
+ import { z } from "zod";
2
+ export declare const RUN_PHASE_TYPES: readonly ["research", "plan", "refactor", "implement", "design", "verify", "gate", "deliver"];
3
+ export type RunPhaseType = (typeof RUN_PHASE_TYPES)[number];
4
+ export declare function isRunPhaseType(value: string): value is RunPhaseType;
5
+ /** The role a phase type dispatches to by default (null for human `gate`). */
6
+ export declare function defaultRoleForPhaseType(type: RunPhaseType): string | null;
7
+ export declare const RUN_PHASE_STATUSES: readonly ["pending", "running", "blocked", "done", "failed", "skipped"];
8
+ export type RunPhaseStatus = (typeof RUN_PHASE_STATUSES)[number];
9
+ export declare const RUN_STATUSES: readonly ["pending", "running", "paused", "done", "failed", "canceled"];
10
+ export type RunStatus = (typeof RUN_STATUSES)[number];
11
+ export declare function isRunPhaseStatus(value: string): value is RunPhaseStatus;
12
+ export declare function isRunStatus(value: string): value is RunStatus;
13
+ /** Terminal run statuses — no further phases will run. */
14
+ export declare function isTerminalRunStatus(value: string): boolean;
15
+ /** Terminal phase statuses — the phase will not change again on its own. */
16
+ export declare function isTerminalPhaseStatus(value: string): boolean;
17
+ export declare const RunPhaseJudgeSpecSchema: z.ZodObject<{
18
+ role: z.ZodOptional<z.ZodString>;
19
+ criteria: z.ZodOptional<z.ZodArray<z.ZodString>>;
20
+ }, z.core.$loose>;
21
+ export declare const RunPhaseDeclarationSchema: z.ZodObject<{
22
+ id: z.ZodString;
23
+ type: z.ZodString;
24
+ title: z.ZodString;
25
+ task: z.ZodString;
26
+ role: z.ZodOptional<z.ZodString>;
27
+ dependsOn: z.ZodOptional<z.ZodArray<z.ZodString>>;
28
+ fanOut: z.ZodOptional<z.ZodNumber>;
29
+ keepBest: z.ZodOptional<z.ZodNumber>;
30
+ judge: z.ZodOptional<z.ZodObject<{
31
+ role: z.ZodOptional<z.ZodString>;
32
+ criteria: z.ZodOptional<z.ZodArray<z.ZodString>>;
33
+ }, z.core.$loose>>;
34
+ }, z.core.$loose>;
35
+ export type RunPhaseDeclaration = z.infer<typeof RunPhaseDeclarationSchema>;
36
+ export declare const RunPlanSchema: z.ZodObject<{
37
+ title: z.ZodString;
38
+ requirements: z.ZodOptional<z.ZodArray<z.ZodString>>;
39
+ autopilot: z.ZodOptional<z.ZodBoolean>;
40
+ phases: z.ZodArray<z.ZodObject<{
41
+ id: z.ZodString;
42
+ type: z.ZodString;
43
+ title: z.ZodString;
44
+ task: z.ZodString;
45
+ role: z.ZodOptional<z.ZodString>;
46
+ dependsOn: z.ZodOptional<z.ZodArray<z.ZodString>>;
47
+ fanOut: z.ZodOptional<z.ZodNumber>;
48
+ keepBest: z.ZodOptional<z.ZodNumber>;
49
+ judge: z.ZodOptional<z.ZodObject<{
50
+ role: z.ZodOptional<z.ZodString>;
51
+ criteria: z.ZodOptional<z.ZodArray<z.ZodString>>;
52
+ }, z.core.$loose>>;
53
+ }, z.core.$loose>>;
54
+ }, z.core.$loose>;
55
+ export type RunPlan = z.infer<typeof RunPlanSchema>;
56
+ export declare const RunPhaseCandidateSchema: z.ZodObject<{
57
+ agentId: z.ZodString;
58
+ personalityId: z.ZodOptional<z.ZodString>;
59
+ verdict: z.ZodOptional<z.ZodObject<{
60
+ verdict: z.ZodString;
61
+ score: z.ZodOptional<z.ZodNumber>;
62
+ criteria: z.ZodOptional<z.ZodArray<z.ZodObject<{
63
+ name: z.ZodString;
64
+ met: z.ZodBoolean;
65
+ evidence: z.ZodOptional<z.ZodString>;
66
+ }, z.core.$loose>>>;
67
+ summary: z.ZodOptional<z.ZodString>;
68
+ }, z.core.$loose>>;
69
+ summary: z.ZodOptional<z.ZodString>;
70
+ }, z.core.$loose>;
71
+ export type RunPhaseCandidate = z.infer<typeof RunPhaseCandidateSchema>;
72
+ export declare const RunPhaseSchema: z.ZodObject<{
73
+ id: z.ZodString;
74
+ type: z.ZodString;
75
+ title: z.ZodString;
76
+ task: z.ZodString;
77
+ status: z.ZodString;
78
+ assigneeRole: z.ZodOptional<z.ZodString>;
79
+ dependsOn: z.ZodOptional<z.ZodArray<z.ZodString>>;
80
+ fanOut: z.ZodOptional<z.ZodNumber>;
81
+ keepBest: z.ZodOptional<z.ZodNumber>;
82
+ candidates: z.ZodOptional<z.ZodArray<z.ZodObject<{
83
+ agentId: z.ZodString;
84
+ personalityId: z.ZodOptional<z.ZodString>;
85
+ verdict: z.ZodOptional<z.ZodObject<{
86
+ verdict: z.ZodString;
87
+ score: z.ZodOptional<z.ZodNumber>;
88
+ criteria: z.ZodOptional<z.ZodArray<z.ZodObject<{
89
+ name: z.ZodString;
90
+ met: z.ZodBoolean;
91
+ evidence: z.ZodOptional<z.ZodString>;
92
+ }, z.core.$loose>>>;
93
+ summary: z.ZodOptional<z.ZodString>;
94
+ }, z.core.$loose>>;
95
+ summary: z.ZodOptional<z.ZodString>;
96
+ }, z.core.$loose>>>;
97
+ notes: z.ZodOptional<z.ZodString>;
98
+ startedAt: z.ZodOptional<z.ZodString>;
99
+ completedAt: z.ZodOptional<z.ZodString>;
100
+ }, z.core.$loose>;
101
+ export type RunPhase = z.infer<typeof RunPhaseSchema>;
102
+ export declare const RunSchema: z.ZodObject<{
103
+ id: z.ZodString;
104
+ title: z.ZodString;
105
+ status: z.ZodString;
106
+ requirements: z.ZodOptional<z.ZodArray<z.ZodString>>;
107
+ autopilot: z.ZodOptional<z.ZodBoolean>;
108
+ phases: z.ZodDefault<z.ZodArray<z.ZodObject<{
109
+ id: z.ZodString;
110
+ type: z.ZodString;
111
+ title: z.ZodString;
112
+ task: z.ZodString;
113
+ status: z.ZodString;
114
+ assigneeRole: z.ZodOptional<z.ZodString>;
115
+ dependsOn: z.ZodOptional<z.ZodArray<z.ZodString>>;
116
+ fanOut: z.ZodOptional<z.ZodNumber>;
117
+ keepBest: z.ZodOptional<z.ZodNumber>;
118
+ candidates: z.ZodOptional<z.ZodArray<z.ZodObject<{
119
+ agentId: z.ZodString;
120
+ personalityId: z.ZodOptional<z.ZodString>;
121
+ verdict: z.ZodOptional<z.ZodObject<{
122
+ verdict: z.ZodString;
123
+ score: z.ZodOptional<z.ZodNumber>;
124
+ criteria: z.ZodOptional<z.ZodArray<z.ZodObject<{
125
+ name: z.ZodString;
126
+ met: z.ZodBoolean;
127
+ evidence: z.ZodOptional<z.ZodString>;
128
+ }, z.core.$loose>>>;
129
+ summary: z.ZodOptional<z.ZodString>;
130
+ }, z.core.$loose>>;
131
+ summary: z.ZodOptional<z.ZodString>;
132
+ }, z.core.$loose>>>;
133
+ notes: z.ZodOptional<z.ZodString>;
134
+ startedAt: z.ZodOptional<z.ZodString>;
135
+ completedAt: z.ZodOptional<z.ZodString>;
136
+ }, z.core.$loose>>>;
137
+ conductorAgentId: z.ZodOptional<z.ZodString>;
138
+ cwd: z.ZodOptional<z.ZodString>;
139
+ workspaceId: z.ZodOptional<z.ZodString>;
140
+ teamId: z.ZodOptional<z.ZodString>;
141
+ teamName: z.ZodOptional<z.ZodString>;
142
+ error: z.ZodOptional<z.ZodString>;
143
+ summary: z.ZodOptional<z.ZodString>;
144
+ summaryStatus: z.ZodOptional<z.ZodString>;
145
+ agentCount: z.ZodOptional<z.ZodNumber>;
146
+ createdAt: z.ZodOptional<z.ZodString>;
147
+ updatedAt: z.ZodOptional<z.ZodString>;
148
+ }, z.core.$loose>;
149
+ export type Run = z.infer<typeof RunSchema>;
150
+ export declare const RUN_SUMMARY_STATUSES: readonly ["pending", "ready", "failed"];
151
+ export type RunSummaryStatus = (typeof RUN_SUMMARY_STATUSES)[number];
152
+ //# sourceMappingURL=orchestration.d.ts.map
@@ -0,0 +1,199 @@
1
+ import { z } from "zod";
2
+ import { JudgeVerdictSchema } from "./judge-verdict.js";
3
+ // The orchestration data model — a daemon-owned "Run": one execution of a
4
+ // declared multi-agent plan, and its observable/resumable projection to clients.
5
+ // See projects/agent-orchestration/agent-orchestration.md. This is Otto's
6
+ // provider-agnostic answer to a harness "Workflow": the conductor (an
7
+ // orchestrator-role agent) DECLARES the shape (typed phases, assignments, the
8
+ // loop target) via `start_run`, and the daemon runtime drives control flow —
9
+ // fan-out, gather-barrier, gate, loop — in code, so orchestrating is cheaper
10
+ // than hand-tracking N agent ids across async notifications.
11
+ //
12
+ // Wire-forward-compat, per the protocol contract: every open vocabulary (phase
13
+ // type, phase/run status) rides as a plain string leaf validated by a
14
+ // normalizer, never a z.enum, so the daemon can grow the vocabulary without
15
+ // breaking an older client's parse. Objects `.passthrough()`; no transforms.
16
+ // ── The deterministic plan vocabulary ──────────────────────────────────────
17
+ // Fixed phase types used by the runtime (NOT roles). The dispatcher maps a phase
18
+ // type to the role that fills it: research→researcher, plan→planner,
19
+ // refactor/implement→coder, design→designer, verify→judger, gate→human (no
20
+ // agent), deliver→coder/writer.
21
+ export const RUN_PHASE_TYPES = [
22
+ "research",
23
+ "plan",
24
+ "refactor",
25
+ "implement",
26
+ "design",
27
+ "verify",
28
+ "gate",
29
+ "deliver",
30
+ ];
31
+ const PHASE_TYPE_SET = new Set(RUN_PHASE_TYPES);
32
+ export function isRunPhaseType(value) {
33
+ return PHASE_TYPE_SET.has(value);
34
+ }
35
+ // The default role that fills each phase type. `gate` has no role — it's a human
36
+ // approval point. `deliver` defaults to coder (a writer may cover small text
37
+ // deliverables; the conductor can override per phase).
38
+ const PHASE_TYPE_DEFAULT_ROLE = {
39
+ research: "researcher",
40
+ plan: "planner",
41
+ refactor: "coder",
42
+ implement: "coder",
43
+ design: "designer",
44
+ verify: "judger",
45
+ gate: null,
46
+ deliver: "coder",
47
+ };
48
+ /** The role a phase type dispatches to by default (null for human `gate`). */
49
+ export function defaultRoleForPhaseType(type) {
50
+ return PHASE_TYPE_DEFAULT_ROLE[type];
51
+ }
52
+ // ── Phase + run status (open vocabularies, plain-string on the wire) ─────────
53
+ export const RUN_PHASE_STATUSES = [
54
+ "pending",
55
+ "running",
56
+ "blocked", // a gate phase awaiting human approval
57
+ "done",
58
+ "failed",
59
+ "skipped",
60
+ ];
61
+ export const RUN_STATUSES = [
62
+ "pending",
63
+ "running",
64
+ "paused", // stopped at an attended gate, awaiting the user
65
+ "done",
66
+ "failed",
67
+ "canceled",
68
+ ];
69
+ const PHASE_STATUS_SET = new Set(RUN_PHASE_STATUSES);
70
+ const RUN_STATUS_SET = new Set(RUN_STATUSES);
71
+ export function isRunPhaseStatus(value) {
72
+ return PHASE_STATUS_SET.has(value);
73
+ }
74
+ export function isRunStatus(value) {
75
+ return RUN_STATUS_SET.has(value);
76
+ }
77
+ /** Terminal run statuses — no further phases will run. */
78
+ export function isTerminalRunStatus(value) {
79
+ return value === "done" || value === "failed" || value === "canceled";
80
+ }
81
+ /** Terminal phase statuses — the phase will not change again on its own. */
82
+ export function isTerminalPhaseStatus(value) {
83
+ return value === "done" || value === "failed" || value === "skipped";
84
+ }
85
+ // ── Declaration schema (the `start_run` input) ──────────────────────────────
86
+ // What the conductor DECLARES. Kept minimal and schema-validated so a bad plan
87
+ // is rejected at the tool boundary. `role` overrides the phase-type default;
88
+ // `fanOut` spawns N parallel candidates; `judge` attaches a verify sub-step so a
89
+ // making/research phase's output is graded and (with `keepBest`) looped until
90
+ // enough candidates pass.
91
+ export const RunPhaseJudgeSpecSchema = z
92
+ .object({
93
+ role: z.string().min(1).optional(),
94
+ criteria: z.array(z.string().min(1)).optional(),
95
+ })
96
+ .passthrough();
97
+ export const RunPhaseDeclarationSchema = z
98
+ .object({
99
+ // Caller-assigned id, referenced by other phases' `dependsOn`.
100
+ id: z.string().min(1),
101
+ type: z.string().min(1),
102
+ title: z.string().min(1),
103
+ // The instruction handed to the assigned agent(s) as their prompt.
104
+ task: z.string().min(1),
105
+ // Override the phase-type's default role (e.g. deliver→writer).
106
+ role: z.string().min(1).optional(),
107
+ // Phase ids that must reach a terminal state before this phase starts.
108
+ // Absent/empty ⇒ runs after the previous declared phase (linear default).
109
+ dependsOn: z.array(z.string().min(1)).optional(),
110
+ // Spawn N parallel candidates from the same task (different angles). 1 ⇒ solo.
111
+ fanOut: z.number().int().min(1).max(16).optional(),
112
+ // With a judge: keep the best N passers; if fewer pass, the runtime
113
+ // re-dispatches replacements until the target is met or a cap trips.
114
+ keepBest: z.number().int().min(1).max(16).optional(),
115
+ // Attach a structured-judge sub-step to a non-verify phase.
116
+ judge: RunPhaseJudgeSpecSchema.optional(),
117
+ })
118
+ .passthrough();
119
+ export const RunPlanSchema = z
120
+ .object({
121
+ title: z.string().min(1),
122
+ // Immutable acceptance criteria — the run is "not done until every one is
123
+ // met." Carried onto the Run and shown at gates.
124
+ requirements: z.array(z.string().min(1)).optional(),
125
+ // Attended by default: the run pauses at `gate` phases for the user.
126
+ // Autopilot runs straight through (eligibility enforced daemon-side).
127
+ autopilot: z.boolean().optional(),
128
+ phases: z.array(RunPhaseDeclarationSchema).min(1).max(64),
129
+ })
130
+ .passthrough();
131
+ // ── Projection schema (the Run the daemon persists + pushes to clients) ─────
132
+ // One spawned candidate for a phase: the observable child agent plus, when the
133
+ // phase judged it, that candidate's verdict.
134
+ export const RunPhaseCandidateSchema = z
135
+ .object({
136
+ agentId: z.string().min(1),
137
+ // The personality that filled the role for this candidate, if resolved.
138
+ personalityId: z.string().min(1).optional(),
139
+ verdict: JudgeVerdictSchema.optional(),
140
+ // The candidate's final message (synthesis input); may be large — clients
141
+ // truncate for display.
142
+ summary: z.string().optional(),
143
+ })
144
+ .passthrough();
145
+ export const RunPhaseSchema = z
146
+ .object({
147
+ id: z.string().min(1),
148
+ type: z.string().min(1),
149
+ title: z.string().min(1),
150
+ task: z.string().min(1),
151
+ status: z.string().min(1),
152
+ // Resolved dispatch target. `assigneeRole` is what the type/override asked
153
+ // for; `candidates` are the spawned agents (>1 when fanned out).
154
+ assigneeRole: z.string().min(1).optional(),
155
+ dependsOn: z.array(z.string().min(1)).optional(),
156
+ fanOut: z.number().int().min(1).optional(),
157
+ keepBest: z.number().int().min(1).optional(),
158
+ candidates: z.array(RunPhaseCandidateSchema).optional(),
159
+ // Free-text runtime notes (why it blocked, which cap tripped, gap named).
160
+ notes: z.string().optional(),
161
+ startedAt: z.string().optional(),
162
+ completedAt: z.string().optional(),
163
+ })
164
+ .passthrough();
165
+ export const RunSchema = z
166
+ .object({
167
+ id: z.string().min(1),
168
+ title: z.string().min(1),
169
+ status: z.string().min(1),
170
+ // Immutable requirements block (see RunPlan.requirements).
171
+ requirements: z.array(z.string().min(1)).optional(),
172
+ autopilot: z.boolean().optional(),
173
+ phases: z.array(RunPhaseSchema).default([]),
174
+ // The conductor agent that owns this run, and the workspace it runs in.
175
+ conductorAgentId: z.string().min(1).optional(),
176
+ cwd: z.string().optional(),
177
+ workspaceId: z.string().optional(),
178
+ // The team that was active when this run started (id for a stable filter key,
179
+ // name for display). Absent on runs started without an active team.
180
+ teamId: z.string().min(1).optional(),
181
+ teamName: z.string().min(1).optional(),
182
+ // Set when the run ends in failure or a cap trips.
183
+ error: z.string().optional(),
184
+ // AI-generated, human-readable summary of the whole run (from a Writer
185
+ // personality). `summaryStatus` is a plain-string, forward-compat leaf:
186
+ // "pending" (being generated), "ready", or "failed". Both absent on daemons
187
+ // or runs without the run-summary feature.
188
+ summary: z.string().optional(),
189
+ summaryStatus: z.string().optional(),
190
+ // Total child agents this run spawned (makers + judgers) — a complexity
191
+ // signal surfaced in the Runs display. Grows as the run executes.
192
+ agentCount: z.number().int().min(0).optional(),
193
+ createdAt: z.string().optional(),
194
+ updatedAt: z.string().optional(),
195
+ })
196
+ .passthrough();
197
+ // Summary generation lifecycle (plain-string on the wire; see RunSchema.summaryStatus).
198
+ export const RUN_SUMMARY_STATUSES = ["pending", "ready", "failed"];
199
+ //# sourceMappingURL=orchestration.js.map