@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.
- package/dist/agent-attention-notification.js +1 -1
- package/dist/agent-labels.js +4 -4
- package/dist/agent-personalities.d.ts +2 -2
- package/dist/agent-personalities.js +17 -17
- package/dist/agent-teams.d.ts +4 -4
- package/dist/agent-teams.js +5 -5
- package/dist/agent-types.d.ts +10 -10
- package/dist/agent-types.js +1 -1
- package/dist/artifacts/rpc-schemas.js +4 -4
- package/dist/artifacts/types.js +3 -3
- package/dist/browser-automation/rpc-schemas.js +1 -1
- package/dist/daemon-endpoints.d.ts +1 -1
- package/dist/default-personalities.js +11 -11
- package/dist/effort.d.ts +1 -1
- package/dist/effort.js +2 -2
- package/dist/forge-manifest.d.ts +3 -3
- package/dist/generated/validation/ws-outbound.aot.js +25211 -20528
- package/dist/git-hosting.js +3 -3
- package/dist/git-remote.js +1 -1
- package/dist/judge-verdict.d.ts +1 -1
- package/dist/judge-verdict.js +2 -2
- package/dist/messages.d.ts +2698 -63
- package/dist/messages.js +630 -175
- package/dist/model-tiers.d.ts +3 -3
- package/dist/model-tiers.js +4 -4
- package/dist/observed-subagent-title.d.ts +2 -2
- package/dist/observed-subagent-title.js +4 -4
- package/dist/orchestration.d.ts +3 -3
- package/dist/orchestration.js +32 -32
- package/dist/otto-config-schema.js +1 -1
- package/dist/provider-config.d.ts +92 -3
- package/dist/provider-config.js +58 -6
- package/dist/provider-manifest.d.ts +9 -1
- package/dist/provider-manifest.js +22 -2
- package/dist/schedule/rpc-schemas.d.ts +4 -4
- package/dist/schedule/rpc-schemas.js +1 -1
- package/dist/schedule/types.d.ts +1 -1
- package/dist/schedule/types.js +3 -3
- package/dist/tool-call-display.d.ts +1 -1
- package/dist/tool-call-display.js +3 -3
- package/dist/tool-name-normalization.d.ts +2 -2
- package/dist/tool-name-normalization.js +2 -2
- package/dist/validation/ws-outbound-schema-metadata.d.ts +526 -8
- package/dist/widgets/bridge.d.ts +5 -5
- package/dist/widgets/bridge.js +5 -5
- package/dist/widgets/document.d.ts +1 -1
- package/dist/widgets/document.js +4 -4
- package/dist/widgets/icons.d.ts +1 -1
- package/dist/widgets/icons.js +1 -1
- package/dist/widgets/theme.d.ts +2 -2
- package/dist/widgets/theme.js +2 -2
- package/dist/widgets/types.d.ts +5 -5
- package/dist/widgets/types.js +5 -5
- 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
|
|
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) => {
|
package/dist/agent-labels.js
CHANGED
|
@@ -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"
|
|
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"
|
|
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
|
|
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"
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
120
|
-
"First apply the complexity gate: if a task is small and not splittable, just do it
|
|
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
|
|
122
|
-
"Prefer start_run over hand-spawning and tracking agents yourself
|
|
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
|
|
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
|
|
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.
|
package/dist/agent-teams.d.ts
CHANGED
|
@@ -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 "@"
|
|
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"
|
|
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
|
|
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
|
|
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
|
/**
|
package/dist/agent-teams.js
CHANGED
|
@@ -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 "@"
|
|
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"
|
|
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
|
|
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
|
|
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 ?? []);
|
package/dist/agent-types.d.ts
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
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")
|
|
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
|
|
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
|
|
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)
|
|
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
|
|
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 {
|
package/dist/agent-types.js
CHANGED
|
@@ -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
|
|
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)
|
|
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
|
|
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
|
|
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
|
|
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) {
|
package/dist/artifacts/types.js
CHANGED
|
@@ -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*
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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)
|
|
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
|
|
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
|
|
62
|
-
"patterns, and gotchas
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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)
|
|
91
|
+
// option ids) - only exact ids can address them.
|
|
92
92
|
throw new EffortResolutionError(requested, availableIds);
|
|
93
93
|
}
|
|
94
94
|
return {
|
package/dist/forge-manifest.d.ts
CHANGED
|
@@ -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
|
|
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"
|
|
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
|
|
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[];
|