@otto-code/protocol 0.7.6 → 0.8.1

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 (54) hide show
  1. package/dist/agent-attention-notification.js +1 -1
  2. package/dist/agent-labels.js +4 -4
  3. package/dist/agent-personalities.d.ts +2 -2
  4. package/dist/agent-personalities.js +17 -17
  5. package/dist/agent-teams.d.ts +4 -4
  6. package/dist/agent-teams.js +5 -5
  7. package/dist/agent-types.d.ts +10 -10
  8. package/dist/agent-types.js +1 -1
  9. package/dist/artifacts/rpc-schemas.js +4 -4
  10. package/dist/artifacts/types.js +3 -3
  11. package/dist/browser-automation/rpc-schemas.js +1 -1
  12. package/dist/daemon-endpoints.d.ts +1 -1
  13. package/dist/default-personalities.js +11 -11
  14. package/dist/effort.d.ts +1 -1
  15. package/dist/effort.js +2 -2
  16. package/dist/forge-manifest.d.ts +3 -3
  17. package/dist/generated/validation/ws-outbound.aot.js +25211 -20528
  18. package/dist/git-hosting.js +3 -3
  19. package/dist/git-remote.js +1 -1
  20. package/dist/judge-verdict.d.ts +1 -1
  21. package/dist/judge-verdict.js +2 -2
  22. package/dist/messages.d.ts +2698 -63
  23. package/dist/messages.js +630 -175
  24. package/dist/model-tiers.d.ts +3 -3
  25. package/dist/model-tiers.js +4 -4
  26. package/dist/observed-subagent-title.d.ts +2 -2
  27. package/dist/observed-subagent-title.js +4 -4
  28. package/dist/orchestration.d.ts +3 -3
  29. package/dist/orchestration.js +32 -32
  30. package/dist/otto-config-schema.js +1 -1
  31. package/dist/provider-config.d.ts +92 -3
  32. package/dist/provider-config.js +58 -6
  33. package/dist/provider-manifest.d.ts +9 -1
  34. package/dist/provider-manifest.js +22 -2
  35. package/dist/schedule/rpc-schemas.d.ts +4 -4
  36. package/dist/schedule/rpc-schemas.js +1 -1
  37. package/dist/schedule/types.d.ts +1 -1
  38. package/dist/schedule/types.js +3 -3
  39. package/dist/tool-call-display.d.ts +1 -1
  40. package/dist/tool-call-display.js +3 -3
  41. package/dist/tool-name-normalization.d.ts +2 -2
  42. package/dist/tool-name-normalization.js +2 -2
  43. package/dist/validation/ws-outbound-schema-metadata.d.ts +526 -8
  44. package/dist/widgets/bridge.d.ts +5 -5
  45. package/dist/widgets/bridge.js +5 -5
  46. package/dist/widgets/document.d.ts +1 -1
  47. package/dist/widgets/document.js +4 -4
  48. package/dist/widgets/icons.d.ts +1 -1
  49. package/dist/widgets/icons.js +1 -1
  50. package/dist/widgets/theme.d.ts +2 -2
  51. package/dist/widgets/theme.js +2 -2
  52. package/dist/widgets/types.d.ts +5 -5
  53. package/dist/widgets/types.js +5 -5
  54. package/package.json +1 -1
@@ -74,7 +74,7 @@ const PERMISSION_INPUT_DESCRIPTION_KEYS = [
74
74
  "query",
75
75
  "prompt",
76
76
  ];
77
- // Deterministic field extraction NOT an AI summary. Picks an existing string
77
+ // Deterministic field extraction - NOT an AI summary. Picks an existing string
78
78
  // field out of the tool's input (by the priority list, then any string field)
79
79
  // so the notification can show it verbatim instead of raw JSON.
80
80
  const describePermissionInput = (input) => {
@@ -11,9 +11,9 @@ export function isDelegatedAgent(agent) {
11
11
  // ── Orchestration node labels (projects/orchestration-graphs) ───────────────
12
12
  // Stamped by the daemon on agents it spawns as orchestration participants. The
13
13
  // otto-tool catalog reads the policy label to enforce the tool binary:
14
- // "deterministic" the daemon does all linking; the node gets NO orchestration
14
+ // "deterministic" - the daemon does all linking; the node gets NO orchestration
15
15
  // tools (spawning/steering agents, runs), NO preview/dev-server tools, and NO
16
- // browser tools. "autonomous" full otto toolset EXCEPT start_run
16
+ // browser tools. "autonomous" - full otto toolset EXCEPT start_run
17
17
  // (orchestrations never nest orchestrations).
18
18
  export const ORCHESTRATION_POLICY_LABEL = "otto.orchestration-policy";
19
19
  export const ORCHESTRATION_POLICIES = ["deterministic", "autonomous"];
@@ -26,10 +26,10 @@ export function getOrchestrationPolicyFromLabels(labels) {
26
26
  export const ORCHESTRATION_RUN_ID_LABEL = "otto.orchestration-run-id";
27
27
  // The node's declared output fields, JSON-encoded, stamped on the spawned
28
28
  // agent. The otto-tool catalog reads it to register that agent's submit_output
29
- // tool which is why this rides a label rather than a spawn option: the
29
+ // tool - which is why this rides a label rather than a spawn option: the
30
30
  // catalog is built per agent from the agent's own record, so every provider
31
31
  // (MCP-served and native-loop alike) inherits the tool with no per-provider
32
- // plumbing. Malformed JSON reads as "no declared fields" a node that can't
32
+ // plumbing. Malformed JSON reads as "no declared fields" - a node that can't
33
33
  // parse its own contract falls back to prose rather than failing to spawn.
34
34
  export const ORCHESTRATION_OUTPUT_FIELDS_LABEL = "otto.orchestration-output-fields";
35
35
  export function getOutputFieldsFromLabels(labels) {
@@ -24,7 +24,7 @@ export declare function personalityCanLaunch(personality: Pick<AgentPersonality,
24
24
  export interface PersonalitySelectionSummary {
25
25
  tier: PersonalityRoleTier;
26
26
  canLaunch: boolean;
27
- /** The "why you'd choose me" blurb each of the personality's roles, joined. */
27
+ /** The "why you'd choose me" blurb - each of the personality's roles, joined. */
28
28
  guidance: string;
29
29
  }
30
30
  /**
@@ -40,7 +40,7 @@ export declare const ORCHESTRATOR_METHOD_DIRECTIVE: string;
40
40
  * spawn. The orchestrator gets the full conductor method; other coordinators
41
41
  * (chatter/artificer/scheduler) get a lighter delegate nudge; focused workers
42
42
  * are told to stay on the task someone is waiting on. Roleless spawns get
43
- * nothing. This is guidance, not a gate the tools stay available either way.
43
+ * nothing. This is guidance, not a gate - the tools stay available either way.
44
44
  */
45
45
  export declare function composeRoleFocusDirective(roles: readonly string[] | undefined): string | undefined;
46
46
  export type PersonalityUnavailableCode = "provider-missing" | "provider-disabled" | "provider-not-ready" | "model-missing" | "mode-missing";
@@ -1,7 +1,7 @@
1
1
  import { PERSONALITY_ROLES } from "./messages.js";
2
2
  // Pure, dependency-free personality helpers shared by the daemon (spawn-time
3
3
  // resolution) and the app (picker availability + role filtering). Effort
4
- // resolution is NOT here it needs the model's advertised thinking options and
4
+ // resolution is NOT here - it needs the model's advertised thinking options and
5
5
  // lives with the daemon's effort resolver; availability does not depend on it.
6
6
  const ROLE_SET = new Set(PERSONALITY_ROLES);
7
7
  // Retired role names, mapped to their canonical replacement. "worker" was split
@@ -41,7 +41,7 @@ export const PERSONALITY_ROLE_INFO = {
41
41
  // ── Surfaces ──────────────────────────────────────────────────────────────
42
42
  chatter: {
43
43
  tier: "coordinator",
44
- guidance: "Interactive driver converse, plan, and delegate. Pick to run a chat or coordinate work.",
44
+ guidance: "Interactive driver - converse, plan, and delegate. Pick to run a chat or coordinate work.",
45
45
  },
46
46
  artificer: {
47
47
  tier: "coordinator",
@@ -54,37 +54,37 @@ export const PERSONALITY_ROLE_INFO = {
54
54
  // ── Thinking workers (read-only, structured findings) ─────────────────────
55
55
  researcher: {
56
56
  tier: "focused",
57
- guidance: "Read-only surveyor maps the code or domain and reports files, types, patterns, and gotchas. Pick to gather facts; proposes no solutions and edits nothing.",
57
+ guidance: "Read-only surveyor - maps the code or domain and reports files, types, patterns, and gotchas. Pick to gather facts; proposes no solutions and edits nothing.",
58
58
  },
59
59
  planner: {
60
60
  tier: "focused",
61
- guidance: "Planning specialist turns a goal into a typed, sequenced phase plan for others to execute. Pick to draft an actionable plan; stays on the plan and doesn't dispatch.",
61
+ guidance: "Planning specialist - turns a goal into a typed, sequenced phase plan for others to execute. Pick to draft an actionable plan; stays on the plan and doesn't dispatch.",
62
62
  },
63
63
  judger: {
64
64
  tier: "focused",
65
- guidance: "Review specialist evaluates work or a plan against criteria and returns a structured verdict. Pick for a focused review; stays on task.",
65
+ guidance: "Review specialist - evaluates work or a plan against criteria and returns a structured verdict. Pick for a focused review; stays on task.",
66
66
  },
67
67
  advisor: {
68
68
  tier: "focused",
69
- guidance: "Read-only second opinion weighs the trade-offs and returns one recommendation. Pick for advice; never edits and does not fan out.",
69
+ guidance: "Read-only second opinion - weighs the trade-offs and returns one recommendation. Pick for advice; never edits and does not fan out.",
70
70
  },
71
71
  // ── Making workers (produce code, design, or text) ────────────────────────
72
72
  coder: {
73
73
  tier: "focused",
74
- guidance: "Focused implementer writes code for one sub-task others are waiting on. Pick to get a coding job done; stays on task.",
74
+ guidance: "Focused implementer - writes code for one sub-task others are waiting on. Pick to get a coding job done; stays on task.",
75
75
  },
76
76
  designer: {
77
77
  tier: "focused",
78
- guidance: "Design maker styling and layout plus the human-skill text (copy, naming). Pick for the look-and-feel or the words; stays on task.",
78
+ guidance: "Design maker - styling and layout plus the human-skill text (copy, naming). Pick for the look-and-feel or the words; stays on task.",
79
79
  },
80
80
  writer: {
81
81
  tier: "focused",
82
- guidance: "Fast small-text specialist commit messages, summaries, names. Pick for quick text; stays on the one task.",
82
+ guidance: "Fast small-text specialist - commit messages, summaries, names. Pick for quick text; stays on the one task.",
83
83
  },
84
84
  // ── Conductor ─────────────────────────────────────────────────────────────
85
85
  orchestrator: {
86
86
  tier: "coordinator",
87
- guidance: "The sole conductor plans team-shaped work, dispatches typed tasks to the right teammates, gathers, and synthesizes. Pick to run a multi-agent workflow.",
87
+ guidance: "The sole conductor - plans team-shaped work, dispatches typed tasks to the right teammates, gathers, and synthesizes. Pick to run a multi-agent workflow.",
88
88
  },
89
89
  };
90
90
  /**
@@ -111,21 +111,21 @@ export function summarizePersonalityForSelection(personality) {
111
111
  guidance: roles.map((role) => PERSONALITY_ROLE_INFO[role].guidance).join(" "),
112
112
  };
113
113
  }
114
- // The conductor's standing directive the distilled `/epic` method taught to
114
+ // The conductor's standing directive - the distilled `/epic` method taught to
115
115
  // the sole orchestrator role at spawn, so orchestration is emergent (the agent
116
116
  // recognizes team-shaped work and runs it) rather than something a user must
117
117
  // invoke. Kept here as one exported constant so the wording is testable and
118
118
  // shared. See projects/agent-orchestration/agent-orchestration.md.
119
- export const ORCHESTRATOR_METHOD_DIRECTIVE = "You are the orchestrator the team's sole conductor. Team-shaped work is yours to run, and you should reach for it naturally, not only when asked. " +
120
- "First apply the complexity gate: if a task is small and not splittable, just do it no ceremony. Only orchestrate when the work is large, parallelizable, or benefits from independent perspectives. " +
121
- "When you do orchestrate: (1) if the shape is unclear, dispatch a researcher to survey and a planner to draft a typed plan; (2) declare that plan as a Run with start_run phases typed research/plan/implement/design/verify/gate/deliver, fanning out candidates where several angles help and attaching a judger to grade them, looping until enough pass; (3) put a gate before irreversible or costly steps so the user approves; (4) synthesize the passing results into the deliverable. " +
122
- "Prefer start_run over hand-spawning and tracking agents yourself the runtime fans out, gathers typed verdicts, and enforces the loop for you. Every phase maps to a teammate's role; if the active team lacks a role a phase needs, say so plainly and stop rather than papering over the gap.";
119
+ export const ORCHESTRATOR_METHOD_DIRECTIVE = "You are the orchestrator - the team's sole conductor. Team-shaped work is yours to run, and you should reach for it naturally, not only when asked. " +
120
+ "First apply the complexity gate: if a task is small and not splittable, just do it - no ceremony. Only orchestrate when the work is large, parallelizable, or benefits from independent perspectives. " +
121
+ "When you do orchestrate: (1) if the shape is unclear, dispatch a researcher to survey and a planner to draft a typed plan; (2) declare that plan as a Run with start_run - phases typed research/plan/implement/design/verify/gate/deliver, fanning out candidates where several angles help and attaching a judger to grade them, looping until enough pass; (3) put a gate before irreversible or costly steps so the user approves; (4) synthesize the passing results into the deliverable. " +
122
+ "Prefer start_run over hand-spawning and tracking agents yourself - the runtime fans out, gathers typed verdicts, and enforces the loop for you. Every phase maps to a teammate's role; if the active team lacks a role a phase needs, say so plainly and stop rather than papering over the gap.";
123
123
  /**
124
124
  * The in-context "role directive" injected into a personality's system prompt at
125
125
  * spawn. The orchestrator gets the full conductor method; other coordinators
126
126
  * (chatter/artificer/scheduler) get a lighter delegate nudge; focused workers
127
127
  * are told to stay on the task someone is waiting on. Roleless spawns get
128
- * nothing. This is guidance, not a gate the tools stay available either way.
128
+ * nothing. This is guidance, not a gate - the tools stay available either way.
129
129
  */
130
130
  export function composeRoleFocusDirective(roles) {
131
131
  const normalized = normalizePersonalityRoles(roles);
@@ -139,7 +139,7 @@ export function composeRoleFocusDirective(roles) {
139
139
  if (normalized.some((role) => PERSONALITY_ROLE_INFO[role].tier === "coordinator")) {
140
140
  return `You are a coordinator personality (roles: ${roleList}). You front interactive work and may delegate: use list_personalities to see who else is available, and spawn other agents or hand off to the team's orchestrator whenever delegating gets the work done faster or better.`;
141
141
  }
142
- return `You are a focused worker personality (roles: ${roleList}). Someone is waiting on this specific task stay on it and finish it. You can still call list_personalities to see the roster, but don't spawn sub-agents or start side workflows unless it is genuinely essential to completing this job.`;
142
+ return `You are a focused worker personality (roles: ${roleList}). Someone is waiting on this specific task - stay on it and finish it. You can still call list_personalities to see the roster, but don't spawn sub-agents or start side workflows unless it is genuinely essential to completing this job.`;
143
143
  }
144
144
  /**
145
145
  * Decide whether a personality is usable against a provider's current snapshot.
@@ -3,7 +3,7 @@ import type { AgentPersonality, AgentTeam, PersonalityRole } from "./messages.js
3
3
  * The dynamic "Team's Scheduler" schedule binding. Stored in the schedule's
4
4
  * `personality` field in place of a personality name; resolved at RUN time to
5
5
  * the active team's first available member carrying the Scheduler role
6
- * (member order). Deliberately contains "@" personality names are sanitized
6
+ * (member order). Deliberately contains "@" - personality names are sanitized
7
7
  * to [A-Za-z0-9_-] at the authoring surface, so the sentinel can never collide
8
8
  * with a real name. No active team, or no available Scheduler member, is a
9
9
  * hard run failure with a named error (same loudness as a bound personality
@@ -17,7 +17,7 @@ export interface AgentTeamsConfigView {
17
17
  export declare function findAgentTeam(teams: readonly AgentTeam[] | undefined, teamId: string | null | undefined): AgentTeam | null;
18
18
  /**
19
19
  * Resolve the host's active team. A dangling `activeTeamId` (team deleted, or
20
- * a patch raced a delete) reads as "no team active" teamlessness is a valid
20
+ * a patch raced a delete) reads as "no team active" - teamlessness is a valid
21
21
  * state and must never error. The daemon additionally heals a dangling id back
22
22
  * to null on the next config patch; this helper is the read-side tolerance.
23
23
  */
@@ -42,13 +42,13 @@ export declare function pruneTeamMemberIds(memberIds: readonly string[] | undefi
42
42
  * team at all, so the delete confirm can offer to clean them up. Dangling member
43
43
  * ids resolve to nothing and drop out, same as everywhere else.
44
44
  *
45
- * Pass the teams that will REMAIN after the delete the caller owns the filter,
45
+ * Pass the teams that will REMAIN after the delete - the caller owns the filter,
46
46
  * so this stays a pure set operation with no notion of "the team being deleted".
47
47
  */
48
48
  export declare function resolveExclusiveTeamMembers(team: Pick<AgentTeam, "memberIds"> | null | undefined, otherTeams: readonly Pick<AgentTeam, "memberIds">[] | undefined, personalities: readonly AgentPersonality[] | undefined): AgentPersonality[];
49
49
  /**
50
50
  * The union of all members' roles, normalized and returned in canonical
51
- * `PERSONALITY_ROLES` order the team card's role-pill strip.
51
+ * `PERSONALITY_ROLES` order - the team card's role-pill strip.
52
52
  */
53
53
  export declare function teamRoleUnion(team: Pick<AgentTeam, "memberIds"> | null | undefined, personalities: readonly AgentPersonality[] | undefined): PersonalityRole[];
54
54
  /**
@@ -1,14 +1,14 @@
1
1
  import { normalizePersonalityRoles } from "./agent-personalities.js";
2
2
  // Pure, dependency-free team helpers shared by the daemon (spawn-time active
3
3
  // team resolution, list_personalities scoping) and the app (team cards,
4
- // pickers, the Active Team switcher). Availability is deliberately NOT here
4
+ // pickers, the Active Team switcher). Availability is deliberately NOT here -
5
5
  // a team is never "out of commission"; its members are individually available
6
6
  // or not, judged by checkPersonalityAvailability per member.
7
7
  /**
8
8
  * The dynamic "Team's Scheduler" schedule binding. Stored in the schedule's
9
9
  * `personality` field in place of a personality name; resolved at RUN time to
10
10
  * the active team's first available member carrying the Scheduler role
11
- * (member order). Deliberately contains "@" personality names are sanitized
11
+ * (member order). Deliberately contains "@" - personality names are sanitized
12
12
  * to [A-Za-z0-9_-] at the authoring surface, so the sentinel can never collide
13
13
  * with a real name. No active team, or no available Scheduler member, is a
14
14
  * hard run failure with a named error (same loudness as a bound personality
@@ -23,7 +23,7 @@ export function findAgentTeam(teams, teamId) {
23
23
  }
24
24
  /**
25
25
  * Resolve the host's active team. A dangling `activeTeamId` (team deleted, or
26
- * a patch raced a delete) reads as "no team active" teamlessness is a valid
26
+ * a patch raced a delete) reads as "no team active" - teamlessness is a valid
27
27
  * state and must never error. The daemon additionally heals a dangling id back
28
28
  * to null on the next config patch; this helper is the read-side tolerance.
29
29
  */
@@ -86,7 +86,7 @@ export function pruneTeamMemberIds(memberIds, personalities) {
86
86
  * team at all, so the delete confirm can offer to clean them up. Dangling member
87
87
  * ids resolve to nothing and drop out, same as everywhere else.
88
88
  *
89
- * Pass the teams that will REMAIN after the delete the caller owns the filter,
89
+ * Pass the teams that will REMAIN after the delete - the caller owns the filter,
90
90
  * so this stays a pure set operation with no notion of "the team being deleted".
91
91
  */
92
92
  export function resolveExclusiveTeamMembers(team, otherTeams, personalities) {
@@ -100,7 +100,7 @@ export function resolveExclusiveTeamMembers(team, otherTeams, personalities) {
100
100
  }
101
101
  /**
102
102
  * The union of all members' roles, normalized and returned in canonical
103
- * `PERSONALITY_ROLES` order the team card's role-pill strip.
103
+ * `PERSONALITY_ROLES` order - the team card's role-pill strip.
104
104
  */
105
105
  export function teamRoleUnion(team, personalities) {
106
106
  const roles = resolveTeamMembers(team, personalities).flatMap((personality) => personality.roles ?? []);
@@ -178,18 +178,18 @@ export interface AgentRunOptions {
178
178
  * origin. Powers the visualizer's context ring/bar colored segments (the same
179
179
  * five categories the vendored render layer draws). Every field is optional and
180
180
  * a token count: a provider fills as many categories as it can attribute and
181
- * omits the rest, so richness degrades gracefully per provider Claude
181
+ * omits the rest, so richness degrades gracefully per provider - Claude
182
182
  * attributes the most; a provider that can attribute nothing omits the whole
183
183
  * object and consumers fall back to occupancy-only (no colored segments, the
184
184
  * pre-composition behavior). Counts are best-effort estimates, not billed usage;
185
185
  * they need not sum exactly to `contextWindowUsedTokens` (the consumer scales).
186
186
  */
187
187
  export interface ContextComposition {
188
- /** System prompt + tool/function definitions the fixed base cost. */
188
+ /** System prompt + tool/function definitions - the fixed base cost. */
189
189
  systemPrompt?: number;
190
190
  /** User-authored input messages. */
191
191
  userMessages?: number;
192
- /** Tool results file contents, search output, command output (usually the
192
+ /** Tool results - file contents, search output, command output (usually the
193
193
  * largest and most volatile category). */
194
194
  toolResults?: number;
195
195
  /** The agent's own reasoning / thinking blocks. */
@@ -199,14 +199,14 @@ export interface ContextComposition {
199
199
  }
200
200
  /**
201
201
  * One provider-reported context-window category. `name` is a provider-supplied
202
- * *display label* ("Messages", "System prompt", "MCP tools") deliberately an
202
+ * *display label* ("Messages", "System prompt", "MCP tools") - deliberately an
203
203
  * OPEN-ENDED string and not an enum, so each provider reports the split it
204
204
  * actually has instead of being squeezed into categories it can't populate.
205
205
  *
206
206
  * Structurally identical to `AgentContextUsageCategory` on the pull path
207
207
  * (`agent.context.get_usage`, see messages.ts) *by design*: the two carry the
208
208
  * same accounting, one pushed on the agent snapshot and one pulled on demand.
209
- * Keep them in sync a divergence here is how the context meter and the
209
+ * Keep them in sync - a divergence here is how the context meter and the
210
210
  * visualizer would start disagreeing about the same agent.
211
211
  */
212
212
  export interface AgentContextCategory {
@@ -219,7 +219,7 @@ export interface AgentUsage {
219
219
  inputTokens?: number;
220
220
  cachedInputTokens?: number;
221
221
  /**
222
- * Prompt tokens spent writing (not reading) the prompt cache this turn
222
+ * Prompt tokens spent writing (not reading) the prompt cache this turn -
223
223
  * Anthropic's `cache_creation_input_tokens`, billed above normal input.
224
224
  * Disjoint from `inputTokens`/`cachedInputTokens`. Claude-specific today;
225
225
  * other providers omit it. Optional/additive.
@@ -236,7 +236,7 @@ export interface AgentUsage {
236
236
  */
237
237
  contextComposition?: ContextComposition;
238
238
  /**
239
- * The provider's OWN context-window split, with its own labels the same
239
+ * The provider's OWN context-window split, with its own labels - the same
240
240
  * accounting the `agent.context.get_usage` RPC returns, pushed here on the
241
241
  * agent snapshot so stream/backfill consumers (the visualizer) read the very
242
242
  * numbers the context meter shows rather than a parallel estimate.
@@ -492,7 +492,7 @@ export interface ObservedSubagentUpdate {
492
492
  requiresAttention?: boolean;
493
493
  usage?: AgentUsage;
494
494
  /**
495
- * True once this run is known to outlive an interrupt of the parent's turn
495
+ * True once this run is known to outlive an interrupt of the parent's turn -
496
496
  * the provider backgrounded it, so the parent's teardown does not take it
497
497
  * down. Sticky: the daemon keeps it set for the row's whole life, and
498
498
  * propagates it to nested rows (a child of a backgrounded run survives too).
@@ -511,7 +511,7 @@ export interface ObservedSubagentUpdate {
511
511
  */
512
512
  toolUseCount?: number;
513
513
  /**
514
- * The tool this subagent is running (or ran last) the "spinning _on a 90s
514
+ * The tool this subagent is running (or ran last) - the "spinning _on a 90s
515
515
  * Bash_" signal. Neutral field any provider can set; unlike the counters it is
516
516
  * NOT monotonic (latest wins) and the daemon drops it once the row goes
517
517
  * terminal. Claude reads it from `task_progress.last_tool_name`. Absent ⇒ the
@@ -523,7 +523,7 @@ export interface ObservedSubagentUpdate {
523
523
  * A background shell task reported by a provider's own Bash tool (Claude:
524
524
  * `run_in_background`). `key` is a provider-local stable identifier (Claude:
525
525
  * the Bash tool_use id); the daemon namespaces it under the owning agent.
526
- * Unlike {@link ObservedSubagentUpdate} this has no transcript/pane it's a
526
+ * Unlike {@link ObservedSubagentUpdate} this has no transcript/pane - it's a
527
527
  * plain status row (command, status, elapsed) in the Background Tasks track.
528
528
  */
529
529
  export interface BackgroundShellTaskUpdate {
@@ -26,7 +26,7 @@ export function getAgentStreamEventTurnId(event) {
26
26
  // accept the setting and ignore it.
27
27
  //
28
28
  // This is a *boundary*, not an instruction. "read" means the write tools are
29
- // not offered, so there is no write to make never a line of prompt asking the
29
+ // not offered, so there is no write to make - never a line of prompt asking the
30
30
  // model to behave. A control a user relies on when deciding to run something
31
31
  // unattended has to be true in exactly the cases where the model is confused.
32
32
  export const WORKSPACE_ACCESS_LEVELS = ["none", "read", "write"];
@@ -20,13 +20,13 @@ export const ArtifactCreateRequestSchema = z.object({
20
20
  systemPrompt: z.string().optional(),
21
21
  // Snapshotted spinner colors of the chosen Agent Personality (optional).
22
22
  spinner: ArtifactSpinnerSchema.optional(),
23
- // Snapshotted human name of the chosen Agent Personality (optional) shown
23
+ // Snapshotted human name of the chosen Agent Personality (optional) - shown
24
24
  // on the artifact card's identity line as the "who generated it".
25
25
  personalityName: z.string().optional(),
26
26
  requestId: z.string(),
27
27
  });
28
28
  // Update edits an artifact's metadata (name/description/project/provider/
29
- // model/thinking) WITHOUT re-running generation editing never regenerates;
29
+ // model/thinking) WITHOUT re-running generation - editing never regenerates;
30
30
  // the user triggers that separately. Every field except artifactId is
31
31
  // optional; only provided fields overwrite.
32
32
  export const ArtifactUpdateRequestSchema = z.object({
@@ -41,7 +41,7 @@ export const ArtifactUpdateRequestSchema = z.object({
41
41
  requestId: z.string(),
42
42
  });
43
43
  // Regenerate re-runs generation for an existing artifact using its stored
44
- // config. It carries no field updates edit those first via update.request.
44
+ // config. It carries no field updates - edit those first via update.request.
45
45
  export const ArtifactRegenerateRequestSchema = z.object({
46
46
  type: z.literal("artifact.regenerate.request"),
47
47
  artifactId: z.string(),
@@ -166,7 +166,7 @@ export const ArtifactDeletedNotificationSchema = z.object({
166
166
  artifactId: z.string(),
167
167
  }),
168
168
  });
169
- // Input validation helper extracts CreateArtifactInput from a create request
169
+ // Input validation helper - extracts CreateArtifactInput from a create request
170
170
  export function validateArtifactCreateRequest(data) {
171
171
  const result = ArtifactCreateRequestSchema.safeParse(data);
172
172
  if (!result.success) {
@@ -27,7 +27,7 @@ export const ArtifactMetadataSchema = z.object({
27
27
  generationModel: z.string().nullable(),
28
28
  // Requested generation mode/effort, persisted so regeneration re-runs with
29
29
  // the same settings. Optional: records written before these fields existed
30
- // omit them (no migrations). The mode is a *request* the artifact service
30
+ // omit them (no migrations). The mode is a *request* - the artifact service
31
31
  // only honors unattended modes and otherwise resolves the provider's
32
32
  // unattended default, so generation never stalls on an approval prompt.
33
33
  generationModeId: z.string().nullable().optional(),
@@ -39,7 +39,7 @@ export const ArtifactMetadataSchema = z.object({
39
39
  generationSpinner: ArtifactSpinnerSchema.nullable().optional(),
40
40
  // Human name of the Agent Personality that generated (last generated) this
41
41
  // artifact, snapshotted at create/regenerate time like the provider/model
42
- // above the "who actually did it" the card's identity line shows alongside
42
+ // above - the "who actually did it" the card's identity line shows alongside
43
43
  // provider/model. Absent ⇒ no personality was used (plain provider/model
44
44
  // selection). Purely additive (no daemon floor needed).
45
45
  generationPersonalityName: z.string().nullable().optional(),
@@ -71,7 +71,7 @@ export const ArtifactRunSchema = z.object({
71
71
  });
72
72
  // The full on-disk record: the lean metadata plus its generation run history.
73
73
  // `runs` defaults to [] so records written before run history existed parse
74
- // unchanged (no migrations same approach the rest of the store takes).
74
+ // unchanged (no migrations - same approach the rest of the store takes).
75
75
  // list_artifacts / broadcasts keep sending ArtifactMetadata (runs stripped);
76
76
  // only inspect_artifact returns this fuller shape.
77
77
  export const StoredArtifactSchema = ArtifactMetadataSchema.extend({
@@ -418,7 +418,7 @@ export const BrowserAutomationScreenshotElementResultSchema = z.object({
418
418
  dataBase64: z.string().min(1),
419
419
  width: z.number().int().nonnegative(),
420
420
  height: z.number().int().nonnegative(),
421
- /** Render scale used for the clip above 1 means the element was re-rendered zoomed in. */
421
+ /** Render scale used for the clip - above 1 means the element was re-rendered zoomed in. */
422
422
  scale: z.number().positive().optional(),
423
423
  });
424
424
  export const BrowserAutomationUploadResultSchema = z.object({
@@ -32,7 +32,7 @@ export declare function buildRelayWebSocketUrl(params: {
32
32
  role: RelayRole;
33
33
  /**
34
34
  * Per-connection routing identifier used by the daemon to open server data sockets.
35
- * Clients should NOT provide this the relay assigns a routing ID on connect.
35
+ * Clients should NOT provide this - the relay assigns a routing ID on connect.
36
36
  */
37
37
  connectionId?: string;
38
38
  version?: RelayProtocolVersion | 1 | 2;
@@ -1,6 +1,6 @@
1
1
  // The starter "team" of Agent Personalities shipped with Otto. These seed a
2
2
  // fresh host so a new user sees a working, role-complete roster instead of an
3
- // empty editor and can be re-added on demand from the settings "Restore
3
+ // empty editor - and can be re-added on demand from the settings "Restore
4
4
  // starter team" button. Both the daemon (first-run seeding) and the app (the
5
5
  // restore button) import this one list so the shipped set stays identical on
6
6
  // both sides.
@@ -12,17 +12,17 @@
12
12
  // - Every one of the 11 roles is covered; some personalities are multi-role to
13
13
  // show that a single template can serve several lanes. Sage is the team's
14
14
  // read-only thinker (advisor + researcher + planner); Pixel both an artificer
15
- // and a designer. Dash is the Writer (fast, cheap small-text generation
15
+ // and a designer. Dash is the Writer (fast, cheap small-text generation -
16
16
  // commit messages, summaries, branch names) and Sprocket is the Coder
17
17
  // (methodical sub-agent building work); the two together are the heirs of the
18
18
  // retired "worker" role. Atlas is the sole conductor (orchestrator).
19
- // - Models are Anthropic (Claude Code) the assumption for launch. On a host
19
+ // - Models are Anthropic (Claude Code) - the assumption for launch. On a host
20
20
  // without Claude these simply show as "out of commission" until a matching
21
21
  // provider exists; nothing breaks.
22
22
  // - Model choice follows cost/fit: Opus for low-volume, high-stakes reasoning
23
23
  // (orchestration, advice); Sonnet for everyday building and review; Haiku for
24
24
  // fast, cheap, high-volume / recurring unattended work.
25
- // - Voices are Kokoro v1.0 (kokoro-multi-lang-v1_0) names a SOFT binding. On a
25
+ // - Voices are Kokoro v1.0 (kokoro-multi-lang-v1_0) names - a SOFT binding. On a
26
26
  // host running OpenAI TTS or the older Kokoro v0.19 they degrade to the host
27
27
  // default at playback time; the user never has to fix them.
28
28
  // - Spinner colors are two-hex glow pairs chosen to match each personality's
@@ -58,11 +58,11 @@ export const DEFAULT_AGENT_PERSONALITIES = [
58
58
  respectGlobalAppendPrompt: true,
59
59
  roles: ["advisor", "researcher", "planner"],
60
60
  personalityPrompt: "You are Sage, the team's read-only thinker: you research, you plan, and you advise, but " +
61
- "you never change code. Asked to survey, map what actually exists the files, types, " +
62
- "patterns, and gotchas and report facts, not solutions. Asked to plan, turn the goal " +
61
+ "you never change code. Asked to survey, map what actually exists - the files, types, " +
62
+ "patterns, and gotchas - and report facts, not solutions. Asked to plan, turn the goal " +
63
63
  "into a clear, sequenced set of steps a team could execute. Asked to advise, weigh the " +
64
64
  "real trade-offs, surface the risk others miss, and give the one option you would take and " +
65
- "why a recommendation, not a menu.",
65
+ "why - a recommendation, not a menu.",
66
66
  spinner: { glowA: "#14B8A6", glowB: "#8B5CF6" },
67
67
  voice: kokoroVoice("af_heart"),
68
68
  },
@@ -92,7 +92,7 @@ export const DEFAULT_AGENT_PERSONALITIES = [
92
92
  respectGlobalAppendPrompt: true,
93
93
  roles: ["artificer", "designer"],
94
94
  personalityPrompt: "You are Pixel, a maker of polished things. You build artifacts and interfaces that " +
95
- "feel intentional real hierarchy, deliberate spacing, no templated defaults. Sweat " +
95
+ "feel intentional - real hierarchy, deliberate spacing, no templated defaults. Sweat " +
96
96
  "the small stuff, prefer a clean version that ships over a clever one that doesn't, and " +
97
97
  "show your work rather than describe it.",
98
98
  spinner: { glowA: "#EC4899", glowB: "#06B6D4" },
@@ -108,7 +108,7 @@ export const DEFAULT_AGENT_PERSONALITIES = [
108
108
  respectGlobalAppendPrompt: true,
109
109
  roles: ["writer", "scheduler"],
110
110
  personalityPrompt: "You are Dash, the workhorse scribe. You turn diffs, context, and recurring jobs into " +
111
- "crisp short text commit messages, summaries, branch names, titles fast and cheaply, " +
111
+ "crisp short text - commit messages, summaries, branch names, titles - fast and cheaply, " +
112
112
  "without ceremony. Say exactly what changed in as few words as it takes, match the house " +
113
113
  "style you're given, never pad, and never editorialize beyond the facts in front of you.",
114
114
  spinner: { glowA: "#22C55E", glowB: "#A3E635" },
@@ -123,7 +123,7 @@ export const DEFAULT_AGENT_PERSONALITIES = [
123
123
  modeId: "default",
124
124
  respectGlobalAppendPrompt: true,
125
125
  roles: ["chatter", "coder"],
126
- personalityPrompt: "You are Sprocket, a friendly machine. You are precise, literal, and methodical you " +
126
+ personalityPrompt: "You are Sprocket, a friendly machine. You are precise, literal, and methodical - you " +
127
127
  "like checklists, exact steps, and confirming inputs before acting. Keep a light, dry " +
128
128
  "wit, explain what you're doing in plain terms, and when a request is ambiguous ask one " +
129
129
  "sharp clarifying question rather than guessing. Beep.",
@@ -134,7 +134,7 @@ export const DEFAULT_AGENT_PERSONALITIES = [
134
134
  // The starter Agent Team shipped with Otto: every starter personality grouped
135
135
  // under one operating template. Seeded the same first-run/absent-section way
136
136
  // as the personalities (see seedDefaultTeamsIfAbsent), and re-addable from the
137
- // Agent teams card. Deliberately NOT active on first run activating a
137
+ // Agent teams card. Deliberately NOT active on first run - activating a
138
138
  // prompt-bearing team silently on install would change spawn behavior out
139
139
  // from under existing users; the user opts in via the Active Team switcher.
140
140
  // The stable `team_builtin_*` id makes restore idempotent, exactly like the
package/dist/effort.d.ts CHANGED
@@ -20,7 +20,7 @@ export interface ResolvedEffortOption {
20
20
  matched: "exact-id" | "level" | "nearest";
21
21
  }
22
22
  /**
23
- * Resolve a requested effort an exact option id or a canonical level
23
+ * Resolve a requested effort - an exact option id or a canonical level -
24
24
  * against a model's advertised `thinkingOptions`. Exact ids always win, so
25
25
  * provider-special options (e.g. Claude's "ultracode") stay reachable even
26
26
  * though they have no place on the canonical scale.
package/dist/effort.js CHANGED
@@ -52,7 +52,7 @@ export class EffortResolutionError extends Error {
52
52
  }
53
53
  }
54
54
  /**
55
- * Resolve a requested effort an exact option id or a canonical level
55
+ * Resolve a requested effort - an exact option id or a canonical level -
56
56
  * against a model's advertised `thinkingOptions`. Exact ids always win, so
57
57
  * provider-special options (e.g. Claude's "ultracode") stay reachable even
58
58
  * though they have no place on the canonical scale.
@@ -88,7 +88,7 @@ export function resolveEffortOption(input) {
88
88
  }
89
89
  if (best === null) {
90
90
  // None of the model's options map onto the canonical scale (fully custom
91
- // option ids) only exact ids can address them.
91
+ // option ids) - only exact ids can address them.
92
92
  throw new EffortResolutionError(requested, availableIds);
93
93
  }
94
94
  return {
@@ -12,12 +12,12 @@
12
12
  */
13
13
  /**
14
14
  * Declarative sign-in recipe for a forge. The client renders install/sign-in
15
- * hints from this data alone no per-CLI switch so a new forge wires its auth
15
+ * hints from this data alone - no per-CLI switch - so a new forge wires its auth
16
16
  * UX entirely from the manifest. Behavioural auth (the actual host probe) stays
17
17
  * in the server adapter; this is only what the user is told to run.
18
18
  */
19
19
  export interface ForgeSignInCommand {
20
- /** Binary the user installs, e.g. "gh" shown in the install-CLI hint. */
20
+ /** Binary the user installs, e.g. "gh" - shown in the install-CLI hint. */
21
21
  cli: string;
22
22
  /** Full sign-in command, e.g. "gh auth login". */
23
23
  command: string;
@@ -47,7 +47,7 @@ export interface ForgeDefinition {
47
47
  signIn: ForgeSignInCommand | null;
48
48
  /**
49
49
  * Public cloud hosts this forge owns exactly. A BOUNDED list, never an
50
- * allowlist for self-hosted detection self-hosted/Enterprise instances are
50
+ * allowlist for self-hosted detection - self-hosted/Enterprise instances are
51
51
  * recognized at runtime by the adapter's host probe, not by this field.
52
52
  */
53
53
  cloudHosts?: string[];