@otto-code/protocol 0.7.6 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
package/dist/messages.js
CHANGED
|
@@ -51,7 +51,7 @@ const MutableMetadataGenerationConfigSchema = z
|
|
|
51
51
|
// true preserves today's behavior. Read by the generation path (WP-B).
|
|
52
52
|
enabled: z.boolean().default(true),
|
|
53
53
|
// When true, metadata generation prefers a role-matched Writer personality
|
|
54
|
-
// over the cheap default tier. Default false
|
|
54
|
+
// over the cheap default tier. Default false - cheap-tier routing is the
|
|
55
55
|
// default. Read by the generation routing (WP-B).
|
|
56
56
|
preferWriterPersonalities: z.boolean().default(false),
|
|
57
57
|
})
|
|
@@ -97,11 +97,11 @@ const MutableBrowserToolsConfigSchema = z
|
|
|
97
97
|
.passthrough();
|
|
98
98
|
/**
|
|
99
99
|
* Language-server code intelligence, host-scoped because the servers are processes
|
|
100
|
-
* on the daemon's machine
|
|
100
|
+
* on the daemon's machine - they follow the host, not the client.
|
|
101
101
|
*
|
|
102
102
|
* `enabled` defaults **on** and that is safe: nothing spawns until a
|
|
103
103
|
* code-intelligence action needs a language in a workspace, so an unused language
|
|
104
|
-
* costs nothing. What the switch guarantees is that off means off
|
|
104
|
+
* costs nothing. What the switch guarantees is that off means off - no server
|
|
105
105
|
* spawns for any workspace, and the ctags index still serves the outline and the
|
|
106
106
|
* fuzzy finder.
|
|
107
107
|
*
|
|
@@ -121,16 +121,16 @@ const MutableLspConfigSchema = z
|
|
|
121
121
|
})
|
|
122
122
|
.passthrough();
|
|
123
123
|
/**
|
|
124
|
-
* "Microsoft .NET Solution Management"
|
|
124
|
+
* "Microsoft .NET Solution Management" - the Solution view's own switch.
|
|
125
125
|
*
|
|
126
126
|
* **A sibling of `lsp`, not a member of it.** Turning C# code intelligence off does not turn
|
|
127
127
|
* this off and vice versa: they are independent capabilities that happen to share a language,
|
|
128
128
|
* and nesting this inside the LSP settings object would imply exactly the coupling that
|
|
129
|
-
* decision rejects. (It would also be wrong on the facts
|
|
129
|
+
* decision rejects. (It would also be wrong on the facts - LSP has no project-structure
|
|
130
130
|
* request, so nothing here rides on a language server.)
|
|
131
131
|
*
|
|
132
132
|
* Defaults **off**: the feature spawns a process and evaluates MSBuild. Disabled is genuinely
|
|
133
|
-
* off, not merely hidden
|
|
133
|
+
* off, not merely hidden - no discovery walk, no `.sln` read, no `.csproj` parse, no sidecar,
|
|
134
134
|
* no cache, no watcher, and no view switcher. The daemon reads this before scheduling any work,
|
|
135
135
|
* so a disabled feature costs exactly one boolean check.
|
|
136
136
|
*/
|
|
@@ -214,26 +214,26 @@ export const MutableGitHostingConfigSchema = z
|
|
|
214
214
|
.passthrough();
|
|
215
215
|
// Canonical personality roles, in display order. Kept as an exported const so
|
|
216
216
|
// the daemon and app share one vocabulary, but the wire schema stores roles as
|
|
217
|
-
// plain strings (below)
|
|
217
|
+
// plain strings (below) - adding a role later must never break an older peer's
|
|
218
218
|
// parsing. Consumers filter incoming role arrays to this known set. The retired
|
|
219
219
|
// "worker" role is mapped to "coder" on the way in (see LEGACY_ROLE_ALIASES in
|
|
220
220
|
// agent-personalities.ts) so personalities persisted before the split keep their
|
|
221
221
|
// role rather than silently losing it.
|
|
222
222
|
export const PERSONALITY_ROLES = [
|
|
223
|
-
// Surfaces
|
|
223
|
+
// Surfaces - the interactive / host-facing entry points.
|
|
224
224
|
"chatter",
|
|
225
225
|
"artificer",
|
|
226
226
|
"scheduler",
|
|
227
|
-
// Thinking workers
|
|
227
|
+
// Thinking workers - read-only, return structured findings, never edit.
|
|
228
228
|
"researcher",
|
|
229
229
|
"planner",
|
|
230
230
|
"judger",
|
|
231
231
|
"advisor",
|
|
232
|
-
// Making workers
|
|
232
|
+
// Making workers - produce code, design, or short text.
|
|
233
233
|
"coder",
|
|
234
234
|
"designer",
|
|
235
235
|
"writer",
|
|
236
|
-
// Conductor
|
|
236
|
+
// Conductor - the sole role whose whole job is planning and driving a team.
|
|
237
237
|
"orchestrator",
|
|
238
238
|
];
|
|
239
239
|
// Two glow colors for the personality's thinking spinner (BlobLoader glowA/glowB).
|
|
@@ -243,8 +243,8 @@ const AgentPersonalitySpinnerSchema = z
|
|
|
243
243
|
glowB: z.string().min(1),
|
|
244
244
|
})
|
|
245
245
|
.passthrough();
|
|
246
|
-
// A TTS voice for the personality's spoken identity. Stored self-describing
|
|
247
|
-
// provider + model + voice name
|
|
246
|
+
// A TTS voice for the personality's spoken identity. Stored self-describing -
|
|
247
|
+
// provider + model + voice name - because voice names are namespaced per TTS
|
|
248
248
|
// engine/model (the same speaker index maps to different names across models),
|
|
249
249
|
// so a bare name is ambiguous across hosts. All plain strings (like the speech
|
|
250
250
|
// config) for forward-compat. This is a soft binding: an unavailable voice
|
|
@@ -258,17 +258,17 @@ const AgentPersonalityVoiceSchema = z
|
|
|
258
258
|
})
|
|
259
259
|
.passthrough();
|
|
260
260
|
// The Visualizer lifecycle moments a personality voice-cue line can belong to.
|
|
261
|
-
// Protocol owns this vocabulary
|
|
261
|
+
// Protocol owns this vocabulary - the daemon's cue generator, the personality
|
|
262
262
|
// editor, and the Visualizer playback hook all import it from here.
|
|
263
263
|
// "waiting" is the parent's turn ending while its observed sub-agents are still
|
|
264
264
|
// running; it DEFERS "done" rather than replacing it (see docs/visualizer.md).
|
|
265
265
|
export const CUE_MOMENTS = ["join", "thinking", "waiting", "done"];
|
|
266
266
|
// Pre-generated (and user-editable) spoken "voice cue" lines for the personality
|
|
267
|
-
//
|
|
267
|
+
// - a few short variations for each Visualizer moment (its node joins the graph,
|
|
268
268
|
// first starts thinking, finishes its turn but waits on sub-agents, completes).
|
|
269
269
|
// Stored on the personality so they're deterministic and hand-tunable in the
|
|
270
270
|
// editor; the Visualizer reads them directly (no runtime generation). All groups
|
|
271
|
-
// optional/loose
|
|
271
|
+
// optional/loose - a personality may have none, or only some (personalities
|
|
272
272
|
// authored before "waiting" existed simply stay silent for that moment).
|
|
273
273
|
// See docs/visualizer.md "Voice cues".
|
|
274
274
|
const AgentPersonalityVoiceCuesSchema = z
|
|
@@ -326,7 +326,7 @@ const MutableAgentPersonalitiesConfigPatchSchema = z
|
|
|
326
326
|
})
|
|
327
327
|
.passthrough();
|
|
328
328
|
// A team's avatar. v1 ships only `color` (hex, validated at the editor like
|
|
329
|
-
// spinner colors); `imageId` is reserved for the future themed avatar set
|
|
329
|
+
// spinner colors); `imageId` is reserved for the future themed avatar set -
|
|
330
330
|
// when present it wins over color, and color stays the fallback so an old
|
|
331
331
|
// client that doesn't know `imageId` keeps rendering the swatch. Plain
|
|
332
332
|
// strings for forward compat.
|
|
@@ -340,7 +340,7 @@ const AgentTeamAvatarSchema = z
|
|
|
340
340
|
// template: which personalities are on deck, plus a shared team prompt stacked
|
|
341
341
|
// directly ahead of the member's personality prompt at spawn. `id` is the
|
|
342
342
|
// stable identity everything binds to; `name` is a freely-renamable label.
|
|
343
|
-
// `memberIds` bind personality ids (order = display order)
|
|
343
|
+
// `memberIds` bind personality ids (order = display order) - an entry pointing
|
|
344
344
|
// at a deleted personality is tolerated and ignored everywhere, then pruned on
|
|
345
345
|
// the next save of that team. Membership is many-to-many.
|
|
346
346
|
export const AgentTeamSchema = z
|
|
@@ -376,7 +376,7 @@ export const ModelTierSchema = z.enum(["deep", "standard", "fast"]);
|
|
|
376
376
|
// A user's explicit tier tag for one model of one provider. The daemon stamps
|
|
377
377
|
// `model.tier` at ingest, preferring a matching override here over inference
|
|
378
378
|
// (see model-tiers.ts). Stored as an array (not a nested record) so a patch
|
|
379
|
-
// replaces it wholesale
|
|
379
|
+
// replaces it wholesale - that's how a tag gets cleared, since deep-merge can't
|
|
380
380
|
// delete a record key.
|
|
381
381
|
export const ModelTierOverrideSchema = z
|
|
382
382
|
.object({
|
|
@@ -390,13 +390,13 @@ export const ModelTierOverrideSchema = z
|
|
|
390
390
|
// pick instead of re-typing the key. Entries are scoped by the connection
|
|
391
391
|
// env-var pair they belong to (OPENAI_BASE_URL/OPENAI_API_KEY vs
|
|
392
392
|
// ANTHROPIC_BASE_URL/ANTHROPIC_AUTH_TOKEN), which is exactly what the provider
|
|
393
|
-
// settings sheet keys its dropdown off
|
|
393
|
+
// settings sheet keys its dropdown off - so every openai-compatible provider
|
|
394
394
|
// entry on the host shares one pool, and Claude-compatible entries share
|
|
395
395
|
// another. Deliberately `z.string()` rather than an enum: a future env-var
|
|
396
396
|
// family must not make old entries unparseable.
|
|
397
397
|
export const SavedProviderEndpointSchema = z
|
|
398
398
|
.object({
|
|
399
|
-
/** Stable identity, `${baseUrlKey}::${baseUrl}`
|
|
399
|
+
/** Stable identity, `${baseUrlKey}::${baseUrl}` - dedupes on re-save. */
|
|
400
400
|
id: z.string().min(1),
|
|
401
401
|
baseUrlKey: z.string().min(1),
|
|
402
402
|
apiKeyKey: z.string().min(1),
|
|
@@ -434,7 +434,7 @@ export const MutableBrainRemoteConfigSchema = z
|
|
|
434
434
|
// SHA-256 fingerprint of the remote brain's TLS certificate (openssl's
|
|
435
435
|
// "AB:CD:..." form; colons optional). When set, the daemon pins HTTPS
|
|
436
436
|
// connections to exactly this certificate instead of the system trust
|
|
437
|
-
// store
|
|
437
|
+
// store - required for a brain serving tls.mode=self-signed. When null,
|
|
438
438
|
// the certificate must validate against the system trust store.
|
|
439
439
|
certFingerprint: z.string().nullable().default(null),
|
|
440
440
|
})
|
|
@@ -484,13 +484,13 @@ export const MutableBrainConfigSchema = z
|
|
|
484
484
|
}),
|
|
485
485
|
})
|
|
486
486
|
.passthrough();
|
|
487
|
-
// The brain PATCH schema
|
|
487
|
+
// The brain PATCH schema - deliberately NOT `MutableBrainConfigSchema.partial()`.
|
|
488
488
|
// Every field of the full schema carries a `.default()` (so an old daemon's
|
|
489
489
|
// half-written config still parses as a well-formed OFF section), and Zod keeps
|
|
490
490
|
// those defaults through `.partial()`: `MutableBrainConfigSchema.partial().parse(
|
|
491
491
|
// { allowRemoteConfig: true })` expands to the FULL object with every other field
|
|
492
492
|
// defaulted. The daemon deep-merges the parsed patch over the stored config, so a
|
|
493
|
-
// single-field patch would silently reset the entire brain block to defaults
|
|
493
|
+
// single-field patch would silently reset the entire brain block to defaults -
|
|
494
494
|
// turning sharing off (host back to loopback), wiping the auth token, and
|
|
495
495
|
// disabling the server. Mirroring the shape WITHOUT defaults keeps an omitted
|
|
496
496
|
// field omitted, so the deep-merge preserves it. Every level is deep-partial so a
|
|
@@ -575,7 +575,7 @@ export const MutableDaemonConfigSchema = z
|
|
|
575
575
|
toolGroups: z.array(z.enum(OTTO_TOOL_GROUPS)).optional(),
|
|
576
576
|
})
|
|
577
577
|
.passthrough(),
|
|
578
|
-
// Defaults off, matching the daemon's own resolution
|
|
578
|
+
// Defaults off, matching the daemon's own resolution - browser tools are an
|
|
579
579
|
// explicit opt-in, so an omitted section must never read as on.
|
|
580
580
|
browserTools: MutableBrowserToolsConfigSchema.default({ enabled: false }),
|
|
581
581
|
// Daemon-wide agent behavior toggles (Claude-tier capabilities). Defaults to
|
|
@@ -667,7 +667,7 @@ export const MutableDaemonConfigPatchSchema = z
|
|
|
667
667
|
// Gated by server_info features.agentBehaviorToggles; patches deep-merge.
|
|
668
668
|
agentBehaviors: MutableAgentBehaviorsConfigSchema.partial().optional(),
|
|
669
669
|
// A null entry removes the provider's config entirely (custom provider
|
|
670
|
-
// uninstall). Gated by server_info features.providerRemove
|
|
670
|
+
// uninstall). Gated by server_info features.providerRemove - old daemons
|
|
671
671
|
// reject null values.
|
|
672
672
|
providers: z
|
|
673
673
|
.record(z.string(), MutableDaemonProviderConfigSchema.partial().passthrough().nullable())
|
|
@@ -754,7 +754,7 @@ export const AgentRateLimitInfoSchema = z.object({
|
|
|
754
754
|
// does not report it (Claude only includes it near the limit).
|
|
755
755
|
utilizationPercent: z.number().optional(),
|
|
756
756
|
// Provider-reported window identifier, e.g. "five_hour" | "seven_day".
|
|
757
|
-
// Open set
|
|
757
|
+
// Open set - display code falls back to a generic label for unknown values.
|
|
758
758
|
limitType: z.string().optional(),
|
|
759
759
|
// ISO 8601 timestamp when the window resets.
|
|
760
760
|
resetsAt: z.string().optional(),
|
|
@@ -858,7 +858,7 @@ const AgentUsageSchema = z.object({
|
|
|
858
858
|
// Provider-graded context breakdown for the visualizer ring/bar; absent ⇒
|
|
859
859
|
// occupancy only (pre-composition behavior). See ContextComposition.
|
|
860
860
|
contextComposition: ContextCompositionSchema.optional(),
|
|
861
|
-
// The provider's own labelled split
|
|
861
|
+
// The provider's own labelled split - same accounting as
|
|
862
862
|
// `agent.context.get_usage`, pushed on the snapshot. Preferred over
|
|
863
863
|
// contextComposition; absent ⇒ fall back to the estimate, then to occupancy.
|
|
864
864
|
contextCategories: z.array(AgentContextCategorySchema).optional(),
|
|
@@ -1106,7 +1106,7 @@ export const AgentTimelineItemPayloadSchema = z.union([
|
|
|
1106
1106
|
type: z.literal("compaction"),
|
|
1107
1107
|
// COMPAT(compactionFailedStatus): "failed" added in v0.4.3. Clients older
|
|
1108
1108
|
// than that drop the whole timeline event on parse and keep showing the
|
|
1109
|
-
// loading row
|
|
1109
|
+
// loading row - exactly their pre-"failed" behavior, so no gate is needed.
|
|
1110
1110
|
// Nothing to remove: this tag records why the enum could be widened without
|
|
1111
1111
|
// a shim, so it has no cleanup date by design.
|
|
1112
1112
|
status: z.enum(["loading", "completed", "failed"]),
|
|
@@ -1213,7 +1213,7 @@ const AgentRuntimeInfoSchema = z.object({
|
|
|
1213
1213
|
/**
|
|
1214
1214
|
* One message parked for delivery as an agent's NEXT turn (`delivery: "queue"`).
|
|
1215
1215
|
* The daemon owns the queue; this is the read-only projection the Queue track
|
|
1216
|
-
* renders. Declared above AgentSnapshotPayloadSchema
|
|
1216
|
+
* renders. Declared above AgentSnapshotPayloadSchema - zod-aot emits schemas in
|
|
1217
1217
|
* source order, so a forward reference is a build-time ReferenceError.
|
|
1218
1218
|
*/
|
|
1219
1219
|
export const QueuedAgentMessagePayloadSchema = z.object({
|
|
@@ -1225,14 +1225,14 @@ export const QueuedAgentMessagePayloadSchema = z.object({
|
|
|
1225
1225
|
/**
|
|
1226
1226
|
* Who parked the message. Absent (from an older daemon) or "user" is a normal
|
|
1227
1227
|
* user turn; "system" marks a system-injected entry (a chat mention, a
|
|
1228
|
-
* scheduled fire) that the daemon's drain never merges into a user turn
|
|
1228
|
+
* scheduled fire) that the daemon's drain never merges into a user turn - the
|
|
1229
1229
|
* client must likewise exclude it from "Send all".
|
|
1230
1230
|
*/
|
|
1231
1231
|
source: z.enum(["user", "system"]).optional(),
|
|
1232
1232
|
});
|
|
1233
1233
|
/**
|
|
1234
1234
|
* An agent's LIFETIME SPEND, kept as the real token split plus the provider's
|
|
1235
|
-
* own cost
|
|
1235
|
+
* own cost - the raw material for "what did this chat cost".
|
|
1236
1236
|
*
|
|
1237
1237
|
* Deliberately distinct from context-window occupancy (`agent.context.get_usage`
|
|
1238
1238
|
* and `lastUsage.contextWindow*`), which answers "how full am I" and shares no
|
|
@@ -1241,12 +1241,12 @@ export const QueuedAgentMessagePayloadSchema = z.object({
|
|
|
1241
1241
|
*
|
|
1242
1242
|
* `costUsd` is only ever a provider's OWN reported cost, already de-inflated so
|
|
1243
1243
|
* a parent never carries what its sub-agents reported. It is NEVER derived from
|
|
1244
|
-
* a $/M rate table
|
|
1244
|
+
* a $/M rate table - a rate keyed off a model id misprices a gateway serving
|
|
1245
1245
|
* that model at its own prices (docs/subagent-accounting.md, pricing invariant).
|
|
1246
1246
|
* `costCoverage` says how far it can be trusted, so a surface can show a floor
|
|
1247
1247
|
* or an honest blank rather than a confident wrong figure.
|
|
1248
1248
|
*
|
|
1249
|
-
* Declared above AgentSnapshotPayloadSchema
|
|
1249
|
+
* Declared above AgentSnapshotPayloadSchema - zod-aot emits schemas in source
|
|
1250
1250
|
* order, so a forward reference is a build-time ReferenceError.
|
|
1251
1251
|
*/
|
|
1252
1252
|
export const AgentCumulativeUsageSchema = z.object({
|
|
@@ -1257,9 +1257,9 @@ export const AgentCumulativeUsageSchema = z.object({
|
|
|
1257
1257
|
/** Provider-reported cost booked so far. Absent ⇒ nothing was priceable. */
|
|
1258
1258
|
costUsd: z.number().optional(),
|
|
1259
1259
|
/**
|
|
1260
|
-
* `complete`
|
|
1261
|
-
* `partial`
|
|
1262
|
-
* one. `none`
|
|
1260
|
+
* `complete` - every token-bearing turn was priced; `costUsd` is the total.
|
|
1261
|
+
* `partial` - some turns were unpriced; `costUsd` is a FLOOR, present it as
|
|
1262
|
+
* one. `none` - nothing priceable; show tokens and a blank, never an estimate.
|
|
1263
1263
|
*/
|
|
1264
1264
|
costCoverage: z.enum(["complete", "partial", "none"]).optional(),
|
|
1265
1265
|
});
|
|
@@ -1284,7 +1284,7 @@ export const AgentSnapshotPayloadSchema = z.object({
|
|
|
1284
1284
|
runtimeInfo: AgentRuntimeInfoSchema.optional(),
|
|
1285
1285
|
lastUsage: AgentUsageSchema.optional(),
|
|
1286
1286
|
// Honest cumulative token total (Σ across the whole run) from the provider,
|
|
1287
|
-
// for the subagents-track cost readout
|
|
1287
|
+
// for the subagents-track cost readout - the only currency that works for
|
|
1288
1288
|
// cost-less local models. Observed subagents source it from the provider's
|
|
1289
1289
|
// per-task usage.total_tokens (already cumulative-per-subagent). Purely
|
|
1290
1290
|
// additive; absent ⇒ no readout. Old clients ignore it.
|
|
@@ -1301,7 +1301,7 @@ export const AgentSnapshotPayloadSchema = z.object({
|
|
|
1301
1301
|
cumulativeUsage: AgentCumulativeUsageSchema.optional(),
|
|
1302
1302
|
// Liveness signals for the sub-agents track: how much work this agent has done
|
|
1303
1303
|
// (`toolUseCount`, cumulative and monotonic) and what it is doing right now
|
|
1304
|
-
// (`currentTool`, the latest tool name, cleared once the agent is terminal
|
|
1304
|
+
// (`currentTool`, the latest tool name, cleared once the agent is terminal -
|
|
1305
1305
|
// a finished agent isn't "running Bash"). Both are purely additive optional
|
|
1306
1306
|
// leaves: a provider that can't report them leaves them absent and the row
|
|
1307
1307
|
// omits the readout rather than showing a wrong value.
|
|
@@ -1312,7 +1312,7 @@ export const AgentSnapshotPayloadSchema = z.object({
|
|
|
1312
1312
|
toolUseCount: z.number().optional(),
|
|
1313
1313
|
currentTool: z.string().optional(),
|
|
1314
1314
|
// Messages parked for delivery as this agent's NEXT turn (delivery: "queue").
|
|
1315
|
-
// Daemon-owned and ephemeral
|
|
1315
|
+
// Daemon-owned and ephemeral - the composer's Queue track renders straight
|
|
1316
1316
|
// from this. Absent/empty ⇒ nothing queued; old clients ignore it.
|
|
1317
1317
|
// COMPAT(steerQueue): added in v0.6.8, drop the gate when floor >= v0.6.8.
|
|
1318
1318
|
queuedMessages: z.array(QueuedAgentMessagePayloadSchema).optional(),
|
|
@@ -1325,7 +1325,7 @@ export const AgentSnapshotPayloadSchema = z.object({
|
|
|
1325
1325
|
archivedAt: z.string().nullable().optional(),
|
|
1326
1326
|
providerUnavailable: z.boolean().optional(),
|
|
1327
1327
|
// Attendability. "observed" marks a provider-managed subagent (Claude Task /
|
|
1328
|
-
// ultracode fan-out) that the user can watch but not prompt or reconfigure
|
|
1328
|
+
// ultracode fan-out) that the user can watch but not prompt or reconfigure -
|
|
1329
1329
|
// the daemon refuses attended operations and the client renders it read-only.
|
|
1330
1330
|
// COMPAT(observedSubagents): added in v0.4.3; absent ⇒ "attended". Drop the
|
|
1331
1331
|
// gate when daemon floor >= v0.4.3. See projects/observed-subagents/observed-subagents.md.
|
|
@@ -1435,7 +1435,7 @@ export const CloseItemsRequestMessageSchema = z.object({
|
|
|
1435
1435
|
// OpenCode sessions) is deliberately left in place: Otto never created it,
|
|
1436
1436
|
// another tool still reads it, and silently deleting another tool's state is not
|
|
1437
1437
|
// ours to do. There is intentionally **no** opt-in flag for provider data on the
|
|
1438
|
-
// wire
|
|
1438
|
+
// wire - the UI discloses what stays behind instead. See docs/chat-lifecycle.md.
|
|
1439
1439
|
// Gated by server_info.features.historyDelete.
|
|
1440
1440
|
export const HistoryAgentsClearArchivedRequestSchema = z.object({
|
|
1441
1441
|
type: z.literal("history.agents.clear_archived.request"),
|
|
@@ -1449,7 +1449,7 @@ export const HistoryAgentsClearArchivedRequestSchema = z.object({
|
|
|
1449
1449
|
export const HistoryAgentsClearArchivedResponseSchema = z.object({
|
|
1450
1450
|
type: z.literal("history.agents.clear_archived.response"),
|
|
1451
1451
|
payload: z.object({
|
|
1452
|
-
// How many archived records the cutoff selected
|
|
1452
|
+
// How many archived records the cutoff selected - the number the confirm
|
|
1453
1453
|
// dialog quotes back after a dry run.
|
|
1454
1454
|
matched: z.number().int().nonnegative(),
|
|
1455
1455
|
deleted: z.number().int().nonnegative(),
|
|
@@ -1506,7 +1506,7 @@ export const AttachmentsImagesClearRequestSchema = z.object({
|
|
|
1506
1506
|
olderThanDays: z.number().int().min(0).default(0),
|
|
1507
1507
|
// Safe by default: a request that omits the flag previews instead of deleting.
|
|
1508
1508
|
// The client always sends it explicitly. Same contract as
|
|
1509
|
-
// history.agents.clear_archived, and for the same reason
|
|
1509
|
+
// history.agents.clear_archived, and for the same reason - the client cannot
|
|
1510
1510
|
// enumerate the set, and there is no undo.
|
|
1511
1511
|
dryRun: z.boolean().default(true),
|
|
1512
1512
|
requestId: z.string(),
|
|
@@ -1527,6 +1527,27 @@ export const AttachmentsImagesClearResponseSchema = z.object({
|
|
|
1527
1527
|
// server_info.features.brainControl (lifecycle) and features.brainStatus
|
|
1528
1528
|
// (evals). Live status streaming (subscribe_brain_status + brain_status_changed)
|
|
1529
1529
|
// is added alongside its client/daemon consumers.
|
|
1530
|
+
/**
|
|
1531
|
+
* What the brain on the far side can actually serve. Passthrough so it can grow.
|
|
1532
|
+
*
|
|
1533
|
+
* Declared here rather than beside the Brain Console RPCs below because
|
|
1534
|
+
* BrainHostStatusSchema carries it, and a zod const must be initialised before
|
|
1535
|
+
* the schema that references it (see docs on the AOT validator's declaration
|
|
1536
|
+
* ordering). Moving it back down produces a module-evaluation TDZ error.
|
|
1537
|
+
*/
|
|
1538
|
+
export const BrainCapabilitiesSchema = z
|
|
1539
|
+
.object({
|
|
1540
|
+
profiles: z.boolean().default(false),
|
|
1541
|
+
budget: z.boolean().default(false),
|
|
1542
|
+
logs: z.boolean().default(false),
|
|
1543
|
+
delete: z.boolean().default(false),
|
|
1544
|
+
load: z.boolean().default(false),
|
|
1545
|
+
resources: z.boolean().default(false),
|
|
1546
|
+
inventory: z.boolean().default(false),
|
|
1547
|
+
/** Whether writes are permitted right now (the brain's allowRemoteConfig). */
|
|
1548
|
+
writable: z.boolean().default(false),
|
|
1549
|
+
})
|
|
1550
|
+
.passthrough();
|
|
1530
1551
|
// The brain's host status, as the daemon derives it: liveness plus the fields
|
|
1531
1552
|
// proxied from the brain's own `/__host/status`. Passthrough on the opaque
|
|
1532
1553
|
// sub-objects so the brain can evolve them without a protocol bump.
|
|
@@ -1549,6 +1570,64 @@ export const BrainHostStatusSchema = z
|
|
|
1549
1570
|
telemetry: z.record(z.string(), z.unknown()).nullable().optional(),
|
|
1550
1571
|
scheduler: z.record(z.string(), z.unknown()).nullable().optional(),
|
|
1551
1572
|
recent: z.array(z.record(z.string(), z.unknown())).optional(),
|
|
1573
|
+
/**
|
|
1574
|
+
* What the brain on the far side can serve. Carried here rather than fetched
|
|
1575
|
+
* from /__host/capabilities so the client gets it with the status it is
|
|
1576
|
+
* already polling, and so it cannot go stale when the owner toggles remote
|
|
1577
|
+
* configuration. Null from a brain that predates the management API.
|
|
1578
|
+
*/
|
|
1579
|
+
capabilities: BrainCapabilitiesSchema.nullable().optional(),
|
|
1580
|
+
/** Live CPU/RAM/GPU/slot telemetry, only when the request asked for it. */
|
|
1581
|
+
resources: z.record(z.string(), z.unknown()).nullable().optional(),
|
|
1582
|
+
/** How many log lines the brain currently holds, for the Logs tab. */
|
|
1583
|
+
logLineCount: z.number().nullable().optional(),
|
|
1584
|
+
/**
|
|
1585
|
+
* Which long-running op currently owns the brain, if any. Cheap to carry:
|
|
1586
|
+
* the brain reads it from a small file beside its pid file, so this rides on
|
|
1587
|
+
* the liveness poll rather than needing `resources: true`.
|
|
1588
|
+
*
|
|
1589
|
+
* `kind` is a plain string, not an enum: the brain may grow ops this client
|
|
1590
|
+
* has never heard of, and the protocol contract forbids narrowing a field
|
|
1591
|
+
* later. Unknown kinds fall through to the ordinary busy states.
|
|
1592
|
+
*/
|
|
1593
|
+
activity: z
|
|
1594
|
+
.object({
|
|
1595
|
+
kind: z.string(),
|
|
1596
|
+
target: z.string().nullable().optional(),
|
|
1597
|
+
/** Completion in [0,1], for ops that can measure it. */
|
|
1598
|
+
progress: z.number().nullable().optional(),
|
|
1599
|
+
startedAt: z.string().nullable().optional(),
|
|
1600
|
+
})
|
|
1601
|
+
.passthrough()
|
|
1602
|
+
.nullable()
|
|
1603
|
+
.optional(),
|
|
1604
|
+
/**
|
|
1605
|
+
* Whether any in-flight completion is currently mid-reasoning: reasoning
|
|
1606
|
+
* deltas have arrived and no content has yet. Also on the liveness poll,
|
|
1607
|
+
* because it is one boolean the router already knows.
|
|
1608
|
+
*/
|
|
1609
|
+
reasoning: z.boolean().nullable().optional(),
|
|
1610
|
+
/**
|
|
1611
|
+
* Slot occupancy split by phase, so a client can tell a prompt being
|
|
1612
|
+
* ingested from a model that has started answering. Rides here rather than
|
|
1613
|
+
* inside `resources` on purpose: `resources` costs an `nvidia-smi` spawn and
|
|
1614
|
+
* is off by default, and this is the half the status rail needs every poll.
|
|
1615
|
+
*/
|
|
1616
|
+
slots: z
|
|
1617
|
+
.object({
|
|
1618
|
+
total: z.number().nullable().optional(),
|
|
1619
|
+
busy: z.number().nullable().optional(),
|
|
1620
|
+
idle: z.number().nullable().optional(),
|
|
1621
|
+
prefill: z.number().nullable().optional(),
|
|
1622
|
+
decode: z.number().nullable().optional(),
|
|
1623
|
+
})
|
|
1624
|
+
.passthrough()
|
|
1625
|
+
.nullable()
|
|
1626
|
+
.optional(),
|
|
1627
|
+
/** Jobs the scheduler is holding because no slot is free, or a swap is mid-flight. */
|
|
1628
|
+
queued: z.number().nullable().optional(),
|
|
1629
|
+
/** Whether the daemon reached the brain on its last probe. */
|
|
1630
|
+
reachable: z.boolean().nullable().optional(),
|
|
1552
1631
|
})
|
|
1553
1632
|
.passthrough();
|
|
1554
1633
|
const BrainHostStatusResultSchema = z.object({
|
|
@@ -1558,6 +1637,13 @@ const BrainHostStatusResultSchema = z.object({
|
|
|
1558
1637
|
});
|
|
1559
1638
|
export const BrainHostStatusRequestSchema = z.object({
|
|
1560
1639
|
type: z.literal("brain.host.status.request"),
|
|
1640
|
+
/**
|
|
1641
|
+
* Ask for live CPU/RAM/GPU/slot telemetry alongside the status. Off by default
|
|
1642
|
+
* on purpose: it costs an `nvidia-smi` spawn plus a /slots round trip on the
|
|
1643
|
+
* brain, and this RPC is also the liveness poll. Only a surface actually
|
|
1644
|
+
* rendering the numbers should turn it on.
|
|
1645
|
+
*/
|
|
1646
|
+
resources: z.boolean().default(false),
|
|
1561
1647
|
requestId: z.string(),
|
|
1562
1648
|
});
|
|
1563
1649
|
export const BrainHostStatusResponseSchema = z.object({
|
|
@@ -1795,7 +1881,7 @@ const BrainJobsResultSchema = z.object({
|
|
|
1795
1881
|
error: z.string().nullable(),
|
|
1796
1882
|
requestId: z.string(),
|
|
1797
1883
|
});
|
|
1798
|
-
// Installed models
|
|
1884
|
+
// Installed models - `otto-brain scan`.
|
|
1799
1885
|
export const BrainModelsScanRequestSchema = z.object({
|
|
1800
1886
|
type: z.literal("brain.models.scan.request"),
|
|
1801
1887
|
requestId: z.string(),
|
|
@@ -1808,7 +1894,7 @@ export const BrainModelsScanResponseSchema = z.object({
|
|
|
1808
1894
|
requestId: z.string(),
|
|
1809
1895
|
}),
|
|
1810
1896
|
});
|
|
1811
|
-
// Downloadable catalog
|
|
1897
|
+
// Downloadable catalog - `otto-brain catalog`.
|
|
1812
1898
|
export const BrainCatalogListRequestSchema = z.object({
|
|
1813
1899
|
type: z.literal("brain.catalog.list.request"),
|
|
1814
1900
|
requestId: z.string(),
|
|
@@ -1821,7 +1907,7 @@ export const BrainCatalogListResponseSchema = z.object({
|
|
|
1821
1907
|
requestId: z.string(),
|
|
1822
1908
|
}),
|
|
1823
1909
|
});
|
|
1824
|
-
// Installed runtimes
|
|
1910
|
+
// Installed runtimes - `otto-brain runtime list`.
|
|
1825
1911
|
export const BrainRuntimeListRequestSchema = z.object({
|
|
1826
1912
|
type: z.literal("brain.runtime.list.request"),
|
|
1827
1913
|
requestId: z.string(),
|
|
@@ -1834,7 +1920,7 @@ export const BrainRuntimeListResponseSchema = z.object({
|
|
|
1834
1920
|
requestId: z.string(),
|
|
1835
1921
|
}),
|
|
1836
1922
|
});
|
|
1837
|
-
// Download a catalog model
|
|
1923
|
+
// Download a catalog model - starts a `pull` job.
|
|
1838
1924
|
export const BrainModelsPullRequestSchema = z.object({
|
|
1839
1925
|
type: z.literal("brain.models.pull.request"),
|
|
1840
1926
|
// Catalog id or name fragment.
|
|
@@ -1845,7 +1931,7 @@ export const BrainModelsPullResponseSchema = z.object({
|
|
|
1845
1931
|
type: z.literal("brain.models.pull.response"),
|
|
1846
1932
|
payload: BrainJobResultSchema,
|
|
1847
1933
|
});
|
|
1848
|
-
// Install a llama.cpp runtime
|
|
1934
|
+
// Install a llama.cpp runtime - starts a `runtime-install` job.
|
|
1849
1935
|
export const BrainRuntimeInstallRequestSchema = z.object({
|
|
1850
1936
|
type: z.literal("brain.runtime.install.request"),
|
|
1851
1937
|
// Optional llama.cpp release build tag; null = the brain's default.
|
|
@@ -1856,7 +1942,7 @@ export const BrainRuntimeInstallResponseSchema = z.object({
|
|
|
1856
1942
|
type: z.literal("brain.runtime.install.response"),
|
|
1857
1943
|
payload: BrainJobResultSchema,
|
|
1858
1944
|
});
|
|
1859
|
-
// Measure real KV bytes/token for a model
|
|
1945
|
+
// Measure real KV bytes/token for a model - starts a `calibrate` job. Needs a
|
|
1860
1946
|
// runtime + GPU; refused with a helpful error otherwise.
|
|
1861
1947
|
export const BrainCalibrateRequestSchema = z.object({
|
|
1862
1948
|
type: z.literal("brain.calibrate.request"),
|
|
@@ -1867,7 +1953,7 @@ export const BrainCalibrateResponseSchema = z.object({
|
|
|
1867
1953
|
type: z.literal("brain.calibrate.response"),
|
|
1868
1954
|
payload: BrainJobResultSchema,
|
|
1869
1955
|
});
|
|
1870
|
-
// Find the best reasoning budget for a model
|
|
1956
|
+
// Find the best reasoning budget for a model - starts a `sweep` job.
|
|
1871
1957
|
export const BrainSweepRequestSchema = z.object({
|
|
1872
1958
|
type: z.literal("brain.sweep.request"),
|
|
1873
1959
|
model: z.string(),
|
|
@@ -1877,7 +1963,7 @@ export const BrainSweepResponseSchema = z.object({
|
|
|
1877
1963
|
type: z.literal("brain.sweep.response"),
|
|
1878
1964
|
payload: BrainJobResultSchema,
|
|
1879
1965
|
});
|
|
1880
|
-
// Run the agentic-coding benchmark
|
|
1966
|
+
// Run the agentic-coding benchmark - starts a `bench` job. `model` is an
|
|
1881
1967
|
// optional comma list of name fragments; null lets the brain pick.
|
|
1882
1968
|
export const BrainBenchRequestSchema = z.object({
|
|
1883
1969
|
type: z.literal("brain.bench.request"),
|
|
@@ -1924,7 +2010,7 @@ export const BrainHfSearchResultSchema = z
|
|
|
1924
2010
|
installed: z.boolean().default(false),
|
|
1925
2011
|
})
|
|
1926
2012
|
.passthrough();
|
|
1927
|
-
// One downloadable quantization of a repo
|
|
2013
|
+
// One downloadable quantization of a repo - `otto-brain add <repo> --list-quants`.
|
|
1928
2014
|
export const BrainRepoQuantSchema = z
|
|
1929
2015
|
.object({
|
|
1930
2016
|
quant: z.string().default(""),
|
|
@@ -1935,7 +2021,7 @@ export const BrainRepoQuantSchema = z
|
|
|
1935
2021
|
installed: z.boolean().default(false),
|
|
1936
2022
|
})
|
|
1937
2023
|
.passthrough();
|
|
1938
|
-
// Search Hugging Face for GGUF models
|
|
2024
|
+
// Search Hugging Face for GGUF models - `otto-brain search <query>`.
|
|
1939
2025
|
export const BrainHfSearchRequestSchema = z.object({
|
|
1940
2026
|
type: z.literal("brain.hf.search.request"),
|
|
1941
2027
|
query: z.string(),
|
|
@@ -1950,7 +2036,7 @@ export const BrainHfSearchResponseSchema = z.object({
|
|
|
1950
2036
|
requestId: z.string(),
|
|
1951
2037
|
}),
|
|
1952
2038
|
});
|
|
1953
|
-
// List the quantizations a repo offers
|
|
2039
|
+
// List the quantizations a repo offers - `otto-brain add <repo> --list-quants`.
|
|
1954
2040
|
export const BrainHfQuantsRequestSchema = z.object({
|
|
1955
2041
|
type: z.literal("brain.hf.quants.request"),
|
|
1956
2042
|
repo: z.string(),
|
|
@@ -1964,7 +2050,7 @@ export const BrainHfQuantsResponseSchema = z.object({
|
|
|
1964
2050
|
requestId: z.string(),
|
|
1965
2051
|
}),
|
|
1966
2052
|
});
|
|
1967
|
-
// Download a chosen quant of an arbitrary HF repo
|
|
2053
|
+
// Download a chosen quant of an arbitrary HF repo - starts a `pull` job.
|
|
1968
2054
|
export const BrainModelsAddRequestSchema = z.object({
|
|
1969
2055
|
type: z.literal("brain.models.add.request"),
|
|
1970
2056
|
repo: z.string(),
|
|
@@ -1975,6 +2061,283 @@ export const BrainModelsAddResponseSchema = z.object({
|
|
|
1975
2061
|
type: z.literal("brain.models.add.response"),
|
|
1976
2062
|
payload: BrainJobResultSchema,
|
|
1977
2063
|
});
|
|
2064
|
+
// --- Brain Console: the management API, proxied ---------------------------
|
|
2065
|
+
// Unlike the job RPCs above (which shell out to `otto-brain <verb> --json` and
|
|
2066
|
+
// are therefore local-only), these proxy the brain's own `/__host/*` HTTP API.
|
|
2067
|
+
// The daemon already resolves that endpoint by mode, so a local child and a
|
|
2068
|
+
// remote brain are reached by the same code with no branch on either side.
|
|
2069
|
+
// All gated by server_info.features.brainConsole.
|
|
2070
|
+
//
|
|
2071
|
+
// Two versions matter and they move independently: the daemon (does it know how
|
|
2072
|
+
// to proxy?) and the brain (does it serve it?). features.brainConsole answers
|
|
2073
|
+
// the first; `capabilities` on brain.host.status answers the second. A brain too
|
|
2074
|
+
// old for a capability is reported honestly rather than reimplemented.
|
|
2075
|
+
/**
|
|
2076
|
+
* A model's hosting profile. Passthrough because the brain persists more than it
|
|
2077
|
+
* exposes for editing (batchSize, extraArgs, the reasoning-budget message) and
|
|
2078
|
+
* those must survive a round trip untouched rather than being dropped here.
|
|
2079
|
+
*/
|
|
2080
|
+
export const BrainProfileSchema = z
|
|
2081
|
+
.object({
|
|
2082
|
+
contextSize: z.number().default(0),
|
|
2083
|
+
cacheTypeK: z.string().default(""),
|
|
2084
|
+
cacheTypeV: z.string().default(""),
|
|
2085
|
+
flashAttention: z.boolean().default(true),
|
|
2086
|
+
gpuLayers: z.number().default(0),
|
|
2087
|
+
vision: z.boolean().default(false),
|
|
2088
|
+
reasoningBudget: z.number().default(0),
|
|
2089
|
+
parallelSlots: z.number().default(1),
|
|
2090
|
+
})
|
|
2091
|
+
.passthrough();
|
|
2092
|
+
/** One editable field, as the brain describes it, so the editor cannot drift. */
|
|
2093
|
+
export const BrainProfileFieldSchema = z
|
|
2094
|
+
.object({
|
|
2095
|
+
key: z.string(),
|
|
2096
|
+
label: z.string().default(""),
|
|
2097
|
+
kind: z.string().default("number"),
|
|
2098
|
+
step: z.number().nullable().optional(),
|
|
2099
|
+
min: z.number().nullable().optional(),
|
|
2100
|
+
max: z.number().nullable().optional(),
|
|
2101
|
+
options: z.array(z.union([z.string(), z.number()])).default([]),
|
|
2102
|
+
optionLabels: z.array(z.string()).default([]),
|
|
2103
|
+
available: z.boolean().default(true),
|
|
2104
|
+
unavailableReason: z.string().nullable().optional(),
|
|
2105
|
+
})
|
|
2106
|
+
.passthrough();
|
|
2107
|
+
/** A note on a field. `blocksStart` means this combination cannot load at all. */
|
|
2108
|
+
export const BrainProfileWarningSchema = z
|
|
2109
|
+
.object({
|
|
2110
|
+
field: z.string().nullable().default(null),
|
|
2111
|
+
severity: z.string().default("info"),
|
|
2112
|
+
message: z.string().default(""),
|
|
2113
|
+
blocksStart: z.boolean().default(false),
|
|
2114
|
+
})
|
|
2115
|
+
.passthrough();
|
|
2116
|
+
/**
|
|
2117
|
+
* Where the KV bytes/token figure came from. `inherited` means it was measured
|
|
2118
|
+
* on a relative with the same attention geometry and rescaled, which the UI must
|
|
2119
|
+
* never present as measured on this file.
|
|
2120
|
+
*/
|
|
2121
|
+
export const BrainCalibrationInfoSchema = z
|
|
2122
|
+
.object({
|
|
2123
|
+
state: z.string().default("unknown"),
|
|
2124
|
+
kvBytesPerToken: z.number().nullable().default(null),
|
|
2125
|
+
measuredAt: z.string().nullable().default(null),
|
|
2126
|
+
measuredOn: z.string().nullable().default(null),
|
|
2127
|
+
})
|
|
2128
|
+
.passthrough();
|
|
2129
|
+
/** The VRAM breakdown for a profile. Raw bytes; the client formats at the edge. */
|
|
2130
|
+
export const BrainBudgetSchema = z
|
|
2131
|
+
.object({
|
|
2132
|
+
weightsBytes: z.number().default(0),
|
|
2133
|
+
mmprojBytes: z.number().default(0),
|
|
2134
|
+
kvBytes: z.number().default(0),
|
|
2135
|
+
overheadBytes: z.number().default(0),
|
|
2136
|
+
totalBytes: z.number().default(0),
|
|
2137
|
+
usableBytes: z.number().default(0),
|
|
2138
|
+
totalVramBytes: z.number().default(0),
|
|
2139
|
+
reserveBytes: z.number().default(0),
|
|
2140
|
+
kvBytesPerToken: z.number().default(0),
|
|
2141
|
+
source: z.string().default("unknown"),
|
|
2142
|
+
theoreticalKvBytesPerToken: z.number().nullable().default(null),
|
|
2143
|
+
fits: z.boolean().default(false),
|
|
2144
|
+
headroomBytes: z.number().default(0),
|
|
2145
|
+
utilization: z.number().default(0),
|
|
2146
|
+
})
|
|
2147
|
+
.passthrough();
|
|
2148
|
+
/** A model's benchmark standing, joined onto its inventory row. */
|
|
2149
|
+
export const BrainModelScoreSchema = z
|
|
2150
|
+
.object({
|
|
2151
|
+
id: z.string().nullable().default(null),
|
|
2152
|
+
displayName: z.string().default(""),
|
|
2153
|
+
overall: z.number().default(0),
|
|
2154
|
+
runs: z.number().default(0),
|
|
2155
|
+
std: z.number().default(0),
|
|
2156
|
+
grade: z.string().default(""),
|
|
2157
|
+
rank: z.number().nullable().optional(),
|
|
2158
|
+
})
|
|
2159
|
+
.passthrough();
|
|
2160
|
+
/**
|
|
2161
|
+
* One installed model with everything the Models tab shows, joined by the brain.
|
|
2162
|
+
* The client must not have to correlate the scan, the metadata and the rankings
|
|
2163
|
+
* itself: they key on different things and only the brain knows the file layout.
|
|
2164
|
+
*/
|
|
2165
|
+
export const BrainInventoryModelSchema = z
|
|
2166
|
+
.object({
|
|
2167
|
+
id: z.string(),
|
|
2168
|
+
displayName: z.string().default(""),
|
|
2169
|
+
publisher: z.string().nullable().default(null),
|
|
2170
|
+
quant: z.string().nullable().default(null),
|
|
2171
|
+
sizeBytes: z.number().default(0),
|
|
2172
|
+
mmprojBytes: z.number().default(0),
|
|
2173
|
+
origin: z.string().nullable().default(null),
|
|
2174
|
+
arch: z.string().nullable().default(null),
|
|
2175
|
+
contextLength: z.number().nullable().default(null),
|
|
2176
|
+
blockCount: z.number().nullable().default(null),
|
|
2177
|
+
headCountKv: z.number().nullable().default(null),
|
|
2178
|
+
hasProjector: z.boolean().default(false),
|
|
2179
|
+
reasoning: z.boolean().default(false),
|
|
2180
|
+
mtp: z.boolean().default(false),
|
|
2181
|
+
distilled: z.boolean().default(false),
|
|
2182
|
+
useCases: z.array(z.string()).default([]),
|
|
2183
|
+
tier: z.string().nullable().default(null),
|
|
2184
|
+
profile: BrainProfileSchema.nullable().default(null),
|
|
2185
|
+
calibration: BrainCalibrationInfoSchema.nullable().default(null),
|
|
2186
|
+
budget: BrainBudgetSchema.nullable().default(null),
|
|
2187
|
+
maxContextThatFits: z.number().nullable().default(null),
|
|
2188
|
+
score: BrainModelScoreSchema.nullable().default(null),
|
|
2189
|
+
state: z.string().default("not-loaded"),
|
|
2190
|
+
warnings: z.array(BrainProfileWarningSchema).default([]),
|
|
2191
|
+
})
|
|
2192
|
+
.passthrough();
|
|
2193
|
+
export const BrainDiskUsageSchema = z
|
|
2194
|
+
.object({
|
|
2195
|
+
freeBytes: z.number().default(0),
|
|
2196
|
+
totalBytes: z.number().default(0),
|
|
2197
|
+
modelBytes: z.number().default(0),
|
|
2198
|
+
})
|
|
2199
|
+
.passthrough();
|
|
2200
|
+
// The joined inventory - GET /__host/models.
|
|
2201
|
+
export const BrainModelsInventoryRequestSchema = z.object({
|
|
2202
|
+
type: z.literal("brain.models.inventory.request"),
|
|
2203
|
+
requestId: z.string(),
|
|
2204
|
+
});
|
|
2205
|
+
export const BrainModelsInventoryResponseSchema = z.object({
|
|
2206
|
+
type: z.literal("brain.models.inventory.response"),
|
|
2207
|
+
payload: z.object({
|
|
2208
|
+
models: z.array(BrainInventoryModelSchema).default([]),
|
|
2209
|
+
disk: BrainDiskUsageSchema.nullable().default(null),
|
|
2210
|
+
error: z.string().nullable(),
|
|
2211
|
+
requestId: z.string(),
|
|
2212
|
+
}),
|
|
2213
|
+
});
|
|
2214
|
+
// Read a model's profile plus the descriptors an editor renders from.
|
|
2215
|
+
export const BrainModelProfileGetRequestSchema = z.object({
|
|
2216
|
+
type: z.literal("brain.model.profile.get.request"),
|
|
2217
|
+
modelId: z.string(),
|
|
2218
|
+
requestId: z.string(),
|
|
2219
|
+
});
|
|
2220
|
+
export const BrainModelProfileGetResponseSchema = z.object({
|
|
2221
|
+
type: z.literal("brain.model.profile.get.response"),
|
|
2222
|
+
payload: z.object({
|
|
2223
|
+
profile: BrainProfileSchema.nullable().default(null),
|
|
2224
|
+
fields: z.array(BrainProfileFieldSchema).default([]),
|
|
2225
|
+
warnings: z.array(BrainProfileWarningSchema).default([]),
|
|
2226
|
+
calibration: BrainCalibrationInfoSchema.nullable().default(null),
|
|
2227
|
+
error: z.string().nullable(),
|
|
2228
|
+
requestId: z.string(),
|
|
2229
|
+
}),
|
|
2230
|
+
});
|
|
2231
|
+
// Write the editable fields. `patch` carries only the eight the brain accepts;
|
|
2232
|
+
// anything else is ignored there rather than rejected, so an older client that
|
|
2233
|
+
// sends a field a newer brain dropped still succeeds.
|
|
2234
|
+
export const BrainModelProfileSetRequestSchema = z.object({
|
|
2235
|
+
type: z.literal("brain.model.profile.set.request"),
|
|
2236
|
+
modelId: z.string(),
|
|
2237
|
+
patch: z.record(z.string(), z.unknown()),
|
|
2238
|
+
requestId: z.string(),
|
|
2239
|
+
});
|
|
2240
|
+
export const BrainModelProfileSetResponseSchema = z.object({
|
|
2241
|
+
type: z.literal("brain.model.profile.set.response"),
|
|
2242
|
+
payload: z.object({
|
|
2243
|
+
profile: BrainProfileSchema.nullable().default(null),
|
|
2244
|
+
/** Human-readable notes about anything clamped or ignored. */
|
|
2245
|
+
adjustments: z.array(z.string()).default([]),
|
|
2246
|
+
warnings: z.array(BrainProfileWarningSchema).default([]),
|
|
2247
|
+
calibration: BrainCalibrationInfoSchema.nullable().default(null),
|
|
2248
|
+
budget: BrainBudgetSchema.nullable().default(null),
|
|
2249
|
+
maxContextThatFits: z.number().nullable().default(null),
|
|
2250
|
+
/** True when the edited model is the resident one, so a restart applies it. */
|
|
2251
|
+
requiresRestart: z.boolean().default(false),
|
|
2252
|
+
error: z.string().nullable(),
|
|
2253
|
+
requestId: z.string(),
|
|
2254
|
+
}),
|
|
2255
|
+
});
|
|
2256
|
+
// The budget for a hypothetical profile - GET /__host/model/budget. `overrides`
|
|
2257
|
+
// are string-encoded field values so the UI can preview a budget while a control
|
|
2258
|
+
// is mid-drag, without persisting a value the user is scrubbing past.
|
|
2259
|
+
export const BrainModelBudgetGetRequestSchema = z.object({
|
|
2260
|
+
type: z.literal("brain.model.budget.get.request"),
|
|
2261
|
+
modelId: z.string(),
|
|
2262
|
+
overrides: z.record(z.string(), z.string()).default({}),
|
|
2263
|
+
requestId: z.string(),
|
|
2264
|
+
});
|
|
2265
|
+
export const BrainModelBudgetGetResponseSchema = z.object({
|
|
2266
|
+
type: z.literal("brain.model.budget.get.response"),
|
|
2267
|
+
payload: z.object({
|
|
2268
|
+
profile: BrainProfileSchema.nullable().default(null),
|
|
2269
|
+
budget: BrainBudgetSchema.nullable().default(null),
|
|
2270
|
+
maxContextThatFits: z.number().nullable().default(null),
|
|
2271
|
+
gpu: z.record(z.string(), z.unknown()).nullable().default(null),
|
|
2272
|
+
warnings: z.array(BrainProfileWarningSchema).default([]),
|
|
2273
|
+
error: z.string().nullable(),
|
|
2274
|
+
requestId: z.string(),
|
|
2275
|
+
}),
|
|
2276
|
+
});
|
|
2277
|
+
// Load a model into the running brain. Distinct from brain.host.start, which
|
|
2278
|
+
// restarts the daemon's child and has no remote equivalent.
|
|
2279
|
+
export const BrainModelLoadRequestSchema = z.object({
|
|
2280
|
+
type: z.literal("brain.model.load.request"),
|
|
2281
|
+
modelId: z.string(),
|
|
2282
|
+
requestId: z.string(),
|
|
2283
|
+
});
|
|
2284
|
+
export const BrainModelLoadResponseSchema = z.object({
|
|
2285
|
+
type: z.literal("brain.model.load.response"),
|
|
2286
|
+
payload: z.object({
|
|
2287
|
+
status: BrainHostStatusSchema.nullable().default(null),
|
|
2288
|
+
/** The profile actually used: the brain clamps context to fit VRAM. */
|
|
2289
|
+
profile: BrainProfileSchema.nullable().default(null),
|
|
2290
|
+
error: z.string().nullable(),
|
|
2291
|
+
requestId: z.string(),
|
|
2292
|
+
}),
|
|
2293
|
+
});
|
|
2294
|
+
export const BrainModelUnloadRequestSchema = z.object({
|
|
2295
|
+
type: z.literal("brain.model.unload.request"),
|
|
2296
|
+
requestId: z.string(),
|
|
2297
|
+
});
|
|
2298
|
+
export const BrainModelUnloadResponseSchema = z.object({
|
|
2299
|
+
type: z.literal("brain.model.unload.response"),
|
|
2300
|
+
payload: z.object({
|
|
2301
|
+
status: BrainHostStatusSchema.nullable().default(null),
|
|
2302
|
+
error: z.string().nullable(),
|
|
2303
|
+
requestId: z.string(),
|
|
2304
|
+
}),
|
|
2305
|
+
});
|
|
2306
|
+
// Delete a model's files. The brain refuses while that model is loaded.
|
|
2307
|
+
export const BrainModelDeleteRequestSchema = z.object({
|
|
2308
|
+
type: z.literal("brain.model.delete.request"),
|
|
2309
|
+
modelId: z.string(),
|
|
2310
|
+
requestId: z.string(),
|
|
2311
|
+
});
|
|
2312
|
+
export const BrainModelDeleteResponseSchema = z.object({
|
|
2313
|
+
type: z.literal("brain.model.delete.response"),
|
|
2314
|
+
payload: z.object({
|
|
2315
|
+
deleted: z.array(z.string()).default([]),
|
|
2316
|
+
freedBytes: z.number().default(0),
|
|
2317
|
+
includesProjector: z.boolean().default(false),
|
|
2318
|
+
/** How many models remain after the re-scan. */
|
|
2319
|
+
remaining: z.number().default(0),
|
|
2320
|
+
error: z.string().nullable(),
|
|
2321
|
+
requestId: z.string(),
|
|
2322
|
+
}),
|
|
2323
|
+
});
|
|
2324
|
+
// Tail the brain's llama-server log.
|
|
2325
|
+
export const BrainLogsTailRequestSchema = z.object({
|
|
2326
|
+
type: z.literal("brain.logs.tail.request"),
|
|
2327
|
+
limit: z.number().nullable().default(null),
|
|
2328
|
+
requestId: z.string(),
|
|
2329
|
+
});
|
|
2330
|
+
export const BrainLogsTailResponseSchema = z.object({
|
|
2331
|
+
type: z.literal("brain.logs.tail.response"),
|
|
2332
|
+
payload: z.object({
|
|
2333
|
+
lines: z.array(z.string()).default([]),
|
|
2334
|
+
total: z.number().default(0),
|
|
2335
|
+
state: z.string().nullable().default(null),
|
|
2336
|
+
command: z.string().nullable().default(null),
|
|
2337
|
+
error: z.string().nullable(),
|
|
2338
|
+
requestId: z.string(),
|
|
2339
|
+
}),
|
|
2340
|
+
});
|
|
1978
2341
|
export const ProjectRenameRequestSchema = z.object({
|
|
1979
2342
|
type: z.literal("project.rename.request"),
|
|
1980
2343
|
projectId: z.string(),
|
|
@@ -2073,7 +2436,7 @@ export const GitHubIssueAttachmentSchema = z.object({
|
|
|
2073
2436
|
// COMPAT(hostingAttachments): added in v0.7.6, remove after 2027-02-01.
|
|
2074
2437
|
// These were the provider-neutral successors to github_pr/github_issue. The
|
|
2075
2438
|
// forge merge replaced them with forge_change_request/forge_issue, so no
|
|
2076
|
-
// current client sends them
|
|
2439
|
+
// current client sends them - they stay accepted (protocol contract) purely so
|
|
2077
2440
|
// a client from before that merge can still attach a PR or an issue. The
|
|
2078
2441
|
// daemon renders them at
|
|
2079
2442
|
// server/src/server/agent/prompt-attachments.ts; retire both halves together.
|
|
@@ -2386,11 +2749,11 @@ export const SetDaemonConfigRequestMessageSchema = z.object({
|
|
|
2386
2749
|
requestId: z.string(),
|
|
2387
2750
|
config: MutableDaemonConfigPatchSchema,
|
|
2388
2751
|
});
|
|
2389
|
-
// Connectors
|
|
2752
|
+
// Connectors - MCP servers surfaced as named, toggle-able integrations. The
|
|
2390
2753
|
// registry itself (add/remove/enable/disable a connector or an individual tool)
|
|
2391
2754
|
// lives in daemon config and is edited via set_daemon_config's `connectors`
|
|
2392
2755
|
// patch. The one thing config can't answer is what tools a connector actually
|
|
2393
|
-
// exposes, which needs a live connect + listTools
|
|
2756
|
+
// exposes, which needs a live connect + listTools - that is this RPC. Gated by
|
|
2394
2757
|
// features.connectors.
|
|
2395
2758
|
export const ConnectorsListToolsRequestSchema = z.object({
|
|
2396
2759
|
type: z.literal("connectors.list_tools.request"),
|
|
@@ -2413,6 +2776,61 @@ export const ConnectorsListToolsResponseSchema = z.object({
|
|
|
2413
2776
|
requestId: z.string(),
|
|
2414
2777
|
}),
|
|
2415
2778
|
});
|
|
2779
|
+
// Connector OAuth - the "sign in" path for connectors whose MCP server
|
|
2780
|
+
// authenticates by login rather than by a pasted token. Three steps, because a
|
|
2781
|
+
// login is not a request/response: the client asks to authorize, the daemon
|
|
2782
|
+
// answers with a URL to open (or "already authorized"), and the actual result
|
|
2783
|
+
// arrives later as a pushed status once the user finishes in their browser.
|
|
2784
|
+
// Gated by features.connectorOauth.
|
|
2785
|
+
export const ConnectorsOauthAuthorizeRequestSchema = z.object({
|
|
2786
|
+
type: z.literal("connectors.oauth.authorize.request"),
|
|
2787
|
+
requestId: z.string(),
|
|
2788
|
+
connectorId: z.string(),
|
|
2789
|
+
/** Scopes to request, when the catalog entry names them. */
|
|
2790
|
+
scope: z.string().optional(),
|
|
2791
|
+
});
|
|
2792
|
+
export const ConnectorsOauthAuthorizeResponseSchema = z.object({
|
|
2793
|
+
type: z.literal("connectors.oauth.authorize.response"),
|
|
2794
|
+
payload: z.object({
|
|
2795
|
+
connectorId: z.string(),
|
|
2796
|
+
/**
|
|
2797
|
+
* Present when the user must sign in: the client opens this URL. Absent when
|
|
2798
|
+
* the daemon already held a usable authorization, in which case status is
|
|
2799
|
+
* "authorized" and there is nothing to open.
|
|
2800
|
+
*/
|
|
2801
|
+
authorizationUrl: z.string().nullable().default(null),
|
|
2802
|
+
status: z.enum(["redirect", "authorized", "error"]).default("error"),
|
|
2803
|
+
error: z.string().nullable().default(null),
|
|
2804
|
+
requestId: z.string(),
|
|
2805
|
+
}),
|
|
2806
|
+
});
|
|
2807
|
+
export const ConnectorsOauthDisconnectRequestSchema = z.object({
|
|
2808
|
+
type: z.literal("connectors.oauth.disconnect.request"),
|
|
2809
|
+
requestId: z.string(),
|
|
2810
|
+
connectorId: z.string(),
|
|
2811
|
+
});
|
|
2812
|
+
export const ConnectorsOauthDisconnectResponseSchema = z.object({
|
|
2813
|
+
type: z.literal("connectors.oauth.disconnect.response"),
|
|
2814
|
+
payload: z.object({
|
|
2815
|
+
connectorId: z.string(),
|
|
2816
|
+
requestId: z.string(),
|
|
2817
|
+
}),
|
|
2818
|
+
});
|
|
2819
|
+
/**
|
|
2820
|
+
* Pushed when an in-flight authorization settles. Not correlated to a requestId:
|
|
2821
|
+
* the browser round-trip outlives the request that started it, and more than one
|
|
2822
|
+
* client may be watching the same connector.
|
|
2823
|
+
*/
|
|
2824
|
+
export const ConnectorsOauthStatusMessageSchema = z.object({
|
|
2825
|
+
type: z.literal("connectors.oauth.status"),
|
|
2826
|
+
payload: z.object({
|
|
2827
|
+
connectorId: z.string(),
|
|
2828
|
+
status: z.enum(["connected", "failed"]),
|
|
2829
|
+
/** Account label to show once connected, when the server reveals one. */
|
|
2830
|
+
account: z.string().nullable().default(null),
|
|
2831
|
+
error: z.string().nullable().default(null),
|
|
2832
|
+
}),
|
|
2833
|
+
});
|
|
2416
2834
|
export const SpeechSettingsGetOptionsRequestSchema = z.object({
|
|
2417
2835
|
type: z.literal("speech.settings.get_options.request"),
|
|
2418
2836
|
requestId: z.string(),
|
|
@@ -2436,8 +2854,8 @@ export const SpeechTtsPreviewRequestSchema = z.object({
|
|
|
2436
2854
|
.optional(),
|
|
2437
2855
|
});
|
|
2438
2856
|
// Read a full assistant message aloud on demand (the per-message playback
|
|
2439
|
-
// button). Unlike the preview RPC
|
|
2440
|
-
// returns one buffered clip
|
|
2857
|
+
// button). Unlike the preview RPC - which truncates to a short sample and
|
|
2858
|
+
// returns one buffered clip - this synthesizes the ENTIRE text and streams it
|
|
2441
2859
|
// back as `audio_output` chunks (isVoiceMode: false), one group per sentence, so
|
|
2442
2860
|
// playback starts after the first sentence instead of the whole message.
|
|
2443
2861
|
// `voice` (optional) is the speaking agent's personality voice, resolved on the
|
|
@@ -2466,8 +2884,8 @@ export const SpeechTtsSpeakCancelRequestSchema = z.object({
|
|
|
2466
2884
|
});
|
|
2467
2885
|
// COMPAT(visualizerVoiceCues): added in v0.6.3; gate lives in
|
|
2468
2886
|
// features.visualizerVoiceCues. Author short spoken "cue" lines for a
|
|
2469
|
-
// personality
|
|
2470
|
-
// (join / thinking / done)
|
|
2887
|
+
// personality - a handful of variations each for three Visualizer moments
|
|
2888
|
+
// (join / thinking / done) - via the Writer mini-task chain, flavored by the
|
|
2471
2889
|
// persona's `name` + `prompt`. The persona is passed inline (not a stored id)
|
|
2472
2890
|
// so the personality editor can generate for an unsaved draft too; the result
|
|
2473
2891
|
// is stored on the personality (`voiceCues`) and edited there, so this is an
|
|
@@ -2586,7 +3004,7 @@ export const CreateAgentRequestMessageSchema = z.object({
|
|
|
2586
3004
|
config: AgentSessionConfigSchema,
|
|
2587
3005
|
// Optional personality id. When present the daemon resolves the personality
|
|
2588
3006
|
// against this cwd's provider snapshot and snapshots its identity (spinner,
|
|
2589
|
-
// voice, prompt) onto the agent
|
|
3007
|
+
// voice, prompt) onto the agent - the brain (provider/model/mode/effort) still
|
|
2590
3008
|
// comes from `config`, so hand-deviations in the picker keep the identity.
|
|
2591
3009
|
// COMPAT(agentPersonalities): added in v0.5.0; gate lives in features.agentPersonalities.
|
|
2592
3010
|
personality: z.string().optional(),
|
|
@@ -2643,7 +3061,7 @@ export const ProviderUsageListRequestMessageSchema = z.object({
|
|
|
2643
3061
|
type: z.literal("provider.usage.list.request"),
|
|
2644
3062
|
requestId: z.string(),
|
|
2645
3063
|
});
|
|
2646
|
-
// Daemon-wide "fun stats" counters
|
|
3064
|
+
// Daemon-wide "fun stats" counters - see docs/data-model.md ActivityStatsStore.
|
|
2647
3065
|
// Every field defaults to 0 so old and new daemons/clients stay compatible as
|
|
2648
3066
|
// counters are added later.
|
|
2649
3067
|
export const ActivityCountersSchema = z.object({
|
|
@@ -2662,7 +3080,7 @@ export const ActivityCountersSchema = z.object({
|
|
|
2662
3080
|
// Usage & cost accounting (WP-G). Additive/defaulted like every counter above,
|
|
2663
3081
|
// so old daemons emit 0 and old clients drop the unknown leaves. "In"/"Out"
|
|
2664
3082
|
// are token totals; *CostMicroUsd are integer micro-USD (usd*1e6) to stay
|
|
2665
|
-
// summable
|
|
3083
|
+
// summable - populated only for turns reporting a real provider cost (Claude).
|
|
2666
3084
|
// The client detects whether the daemon actually populates these via
|
|
2667
3085
|
// features.usageCostCategories (see below).
|
|
2668
3086
|
costMicroUsd: z.number().default(0),
|
|
@@ -2695,10 +3113,10 @@ export const StatsActivityGetResponseMessageSchema = z.object({
|
|
|
2695
3113
|
allTime: ActivityCountersSchema,
|
|
2696
3114
|
}),
|
|
2697
3115
|
});
|
|
2698
|
-
// Daemon-wide "activity counters moved" ping
|
|
3116
|
+
// Daemon-wide "activity counters moved" ping - broadcast to every client,
|
|
2699
3117
|
// coalesced at the daemon (at most once every few seconds) so bursts of
|
|
2700
3118
|
// increments don't get chatty. Carries no payload: clients re-fetch the
|
|
2701
|
-
// rollups via stats.activity.get. Purely additive
|
|
3119
|
+
// rollups via stats.activity.get. Purely additive - old clients drop the
|
|
2702
3120
|
// unknown type with a warning, and against old daemons (which never send it)
|
|
2703
3121
|
// the stats screen degrades to today's focus/manual refresh. Rides the
|
|
2704
3122
|
// existing activityStats capability; no new feature flag needed because no
|
|
@@ -2706,12 +3124,12 @@ export const StatsActivityGetResponseMessageSchema = z.object({
|
|
|
2706
3124
|
export const ActivityStatsChangedSchema = z.object({
|
|
2707
3125
|
type: z.literal("activity_stats_changed"),
|
|
2708
3126
|
});
|
|
2709
|
-
// One itemized row of the usage ledger
|
|
3127
|
+
// One itemized row of the usage ledger - a single token/cost-bearing activity
|
|
2710
3128
|
// (a chat turn, a sub-agent turn, or a background generation). The aggregate
|
|
2711
3129
|
// ActivityCounters above are the rollup of this same event stream; the ledger is
|
|
2712
3130
|
// the scrollable detail behind the tiles (usage-ledger project). `kind` and
|
|
2713
3131
|
// `provider` are plain strings (not enums) so an OLD client still parses a NEW
|
|
2714
|
-
// daemon that emits a kind it hasn't heard of
|
|
3132
|
+
// daemon that emits a kind it hasn't heard of - it renders it generically rather
|
|
2715
3133
|
// than failing the whole message. All token/cost leaves default to 0.
|
|
2716
3134
|
export const UsageEventSchema = z.object({
|
|
2717
3135
|
/** Stable unique id for the row (daemon-generated). */
|
|
@@ -2747,20 +3165,20 @@ export const UsageEventSchema = z.object({
|
|
|
2747
3165
|
/**
|
|
2748
3166
|
* How many model round-trips this row aggregates. A chat row is one query, but
|
|
2749
3167
|
* a sub-agent row covers a whole delegated task that internally ran many
|
|
2750
|
-
* rounds
|
|
3168
|
+
* rounds - and each round re-reads the growing context, so `cachedTokensIn` is
|
|
2751
3169
|
* cumulative cache-READS, not a cache size. Surfacing the count is what makes a
|
|
2752
3170
|
* large cached figure legible instead of looking like a bug. Absent when the
|
|
2753
3171
|
* provider doesn't report it.
|
|
2754
3172
|
*/
|
|
2755
3173
|
rounds: z.number().optional(),
|
|
2756
3174
|
/**
|
|
2757
|
-
* Sub-agent rows only
|
|
3175
|
+
* Sub-agent rows only - the spawn-tree identity that lets the Log group rows
|
|
2758
3176
|
* the way a human reads the run (chat turn → its sub-agents → their
|
|
2759
3177
|
* sub-agents) instead of by settle time, which async sub-agents crossing turn
|
|
2760
3178
|
* boundaries makes wrong. `startedAt` is when the sub-agent was first
|
|
2761
3179
|
* observed (epoch ms; a row belongs to the turn that spawned it, not the turn
|
|
2762
3180
|
* it happened to settle in), `subagentKey` is its stable observed key, and
|
|
2763
|
-
* `parentSubagentKey` is the spawning sub-agent's key
|
|
3181
|
+
* `parentSubagentKey` is the spawning sub-agent's key - absent for depth-1
|
|
2764
3182
|
* sub-agents spawned by the chat itself.
|
|
2765
3183
|
*/
|
|
2766
3184
|
startedAt: z.number().optional(),
|
|
@@ -2786,7 +3204,7 @@ export const UsageLogGetResponseMessageSchema = z.object({
|
|
|
2786
3204
|
}),
|
|
2787
3205
|
});
|
|
2788
3206
|
// Wipe every daemon-wide usage counter AND the itemized usage ledger back to
|
|
2789
|
-
// zero
|
|
3207
|
+
// zero - the "Reset" action on the Metrics screen. One RPC clears both sinks
|
|
2790
3208
|
// (the day-bucketed ActivityStatsStore and the UsageLogStore) so the tiles and
|
|
2791
3209
|
// the Log tab start fresh together. Gated behind features.statsReset so an old
|
|
2792
3210
|
// daemon (no handler) never receives a request the client thinks it can send.
|
|
@@ -2984,7 +3402,7 @@ export const AgentSubagentStopResponseMessageSchema = z.object({
|
|
|
2984
3402
|
payload: AgentActionResponsePayloadSchema,
|
|
2985
3403
|
});
|
|
2986
3404
|
// A background shell task launched by a provider's own Bash tool (Claude:
|
|
2987
|
-
// run_in_background). Not an agent, not a subagent
|
|
3405
|
+
// run_in_background). Not an agent, not a subagent - a plain shell process
|
|
2988
3406
|
// the daemon tracks for the parent agent's Background Tasks track.
|
|
2989
3407
|
// COMPAT(backgroundShellTasks): added in v0.5.3, drop the gate when daemon floor >= v0.5.3.
|
|
2990
3408
|
export const BackgroundShellTaskInfoSchema = z.object({
|
|
@@ -3000,7 +3418,7 @@ export const BackgroundShellTaskInfoSchema = z.object({
|
|
|
3000
3418
|
archivedAt: z.string().optional(),
|
|
3001
3419
|
});
|
|
3002
3420
|
// Pushed with the full current set of background shell tasks for a parent
|
|
3003
|
-
// agent whenever any of them changes (start/progress/settle/clear)
|
|
3421
|
+
// agent whenever any of them changes (start/progress/settle/clear) - same
|
|
3004
3422
|
// full-list reconciliation shape as TerminalsChangedSchema.
|
|
3005
3423
|
export const BackgroundShellTasksChangedSchema = z.object({
|
|
3006
3424
|
type: z.literal("background_shell_tasks_changed"),
|
|
@@ -3036,7 +3454,7 @@ export const AgentBackgroundTaskClearResponseMessageSchema = z.object({
|
|
|
3036
3454
|
// A suggested task an agent surfaced via the `spawn_task` tool (Claude Desktop
|
|
3037
3455
|
// parity). Renders as a chip in the parent agent's session; the user starts it
|
|
3038
3456
|
// (new worktree / local / this session) or dismisses it. The `prompt` is
|
|
3039
|
-
// deliberately NOT part of this wire shape
|
|
3457
|
+
// deliberately NOT part of this wire shape - it stays server-side and is only
|
|
3040
3458
|
// used when the task is started ("not shown directly" in Claude Desktop).
|
|
3041
3459
|
// COMPAT(suggestedTasks): added in v0.5.6, drop the gate when daemon floor >= v0.5.6.
|
|
3042
3460
|
export const SuggestedTaskStateSchema = z.enum(["pending", "started", "dismissed"]);
|
|
@@ -3051,7 +3469,7 @@ export const SuggestedTaskInfoSchema = z.object({
|
|
|
3051
3469
|
updatedAt: z.string(),
|
|
3052
3470
|
});
|
|
3053
3471
|
// Pushed with the full current set of pending suggested tasks for a parent
|
|
3054
|
-
// agent whenever any of them changes (spawn/start/dismiss)
|
|
3472
|
+
// agent whenever any of them changes (spawn/start/dismiss) - same full-list
|
|
3055
3473
|
// reconciliation shape as BackgroundShellTasksChangedSchema.
|
|
3056
3474
|
export const SuggestedTasksChangedSchema = z.object({
|
|
3057
3475
|
type: z.literal("suggested_tasks_changed"),
|
|
@@ -3060,7 +3478,7 @@ export const SuggestedTasksChangedSchema = z.object({
|
|
|
3060
3478
|
tasks: z.array(SuggestedTaskInfoSchema),
|
|
3061
3479
|
}),
|
|
3062
3480
|
});
|
|
3063
|
-
// Context Management
|
|
3481
|
+
// Context Management - the daemon's accounting of everything a provider sends
|
|
3064
3482
|
// before the user types (see docs/context-management.md).
|
|
3065
3483
|
//
|
|
3066
3484
|
// Two distinctions carry the whole feature and must not be collapsed on the
|
|
@@ -3121,7 +3539,7 @@ export const ContextFindingSchema = z.object({
|
|
|
3121
3539
|
range: ContextRangeSchema.optional(),
|
|
3122
3540
|
relatedNodeIds: z.array(z.string()).optional(),
|
|
3123
3541
|
// The node this finding is about. Redundant while the finding sits on its
|
|
3124
|
-
// node, load-bearing once the report flattens them all into one list
|
|
3542
|
+
// node, load-bearing once the report flattens them all into one list - that
|
|
3125
3543
|
// list is the "Issues" tab, and without this a row cannot say where it came
|
|
3126
3544
|
// from or take you there.
|
|
3127
3545
|
nodeId: z.string().optional(),
|
|
@@ -3132,9 +3550,9 @@ export const ContextFindingSchema = z.object({
|
|
|
3132
3550
|
// rather than dropping a cursor at the top of it.
|
|
3133
3551
|
lineEnd: z.number().optional(),
|
|
3134
3552
|
// True for kinds a mechanical delete can resolve on its own (dead links, a
|
|
3135
|
-
// duplicate block)
|
|
3553
|
+
// duplicate block) - false/absent for kinds that need judgment (which side
|
|
3136
3554
|
// of an import cycle to cut, how to split an oversized entry). Computed
|
|
3137
|
-
// server-side, once, in `locateFinding`
|
|
3555
|
+
// server-side, once, in `locateFinding` - the only place that knows the kind
|
|
3138
3556
|
// vocabulary, so the fix-all button never has to guess.
|
|
3139
3557
|
fixable: z.boolean().optional(),
|
|
3140
3558
|
// The exact text at `range` when the file was scanned. `context.findings.fix`
|
|
@@ -3158,7 +3576,7 @@ export const ContextNodeSchema = z.object({
|
|
|
3158
3576
|
});
|
|
3159
3577
|
export const ContextEdgeSchema = z.object({
|
|
3160
3578
|
fromNodeId: z.string(),
|
|
3161
|
-
// Null when the target could not be resolved
|
|
3579
|
+
// Null when the target could not be resolved - pairs with a dead_* finding.
|
|
3162
3580
|
toNodeId: z.string().nullable(),
|
|
3163
3581
|
kind: z.enum(["import", "reference"]),
|
|
3164
3582
|
rawTarget: z.string(),
|
|
@@ -3179,7 +3597,7 @@ export const ContextCategoryTotalSchema = z.object({
|
|
|
3179
3597
|
export const ContextReportSchema = z.object({
|
|
3180
3598
|
workspaceId: z.string(),
|
|
3181
3599
|
provider: z.string(),
|
|
3182
|
-
// The window the report was evaluated against
|
|
3600
|
+
// The window the report was evaluated against - from the active model, or
|
|
3183
3601
|
// the client's what-if picker. Severity is meaningless without it.
|
|
3184
3602
|
windowTokens: z.number(),
|
|
3185
3603
|
scannedAt: z.string(),
|
|
@@ -3236,7 +3654,7 @@ export const ContextReportGetResponseMessageSchema = z.object({
|
|
|
3236
3654
|
}),
|
|
3237
3655
|
});
|
|
3238
3656
|
// One readable block of the assembled prompt. `text` is absent exactly when
|
|
3239
|
-
// `visibility` is "not_visible"
|
|
3657
|
+
// `visibility` is "not_visible" - the provider composes that part internally and
|
|
3240
3658
|
// Otto has nothing to show, which the section states rather than hides.
|
|
3241
3659
|
export const ContextPromptSectionSchema = z.object({
|
|
3242
3660
|
category: ContextCategorySchema,
|
|
@@ -3259,8 +3677,8 @@ export const ContextPromptPreviewGetRequestMessageSchema = z.object({
|
|
|
3259
3677
|
provider: z.string().optional(),
|
|
3260
3678
|
windowTokens: z.number().optional(),
|
|
3261
3679
|
personalityId: z.string().optional(),
|
|
3262
|
-
// Assemble only this category. The tab reads one section at a time
|
|
3263
|
-
// clicked a row in the tree
|
|
3680
|
+
// Assemble only this category. The tab reads one section at a time - the user
|
|
3681
|
+
// clicked a row in the tree - and assembling the rest would re-read every
|
|
3264
3682
|
// context file on disk to build text nobody asked to see. Omitted means all,
|
|
3265
3683
|
// which is what an older client sends.
|
|
3266
3684
|
category: ContextCategorySchema.optional(),
|
|
@@ -3278,7 +3696,7 @@ export const ContextEdgeConvertRequestMessageSchema = z.object({
|
|
|
3278
3696
|
type: z.literal("context.edge.convert.request"),
|
|
3279
3697
|
requestId: z.string(),
|
|
3280
3698
|
workspaceId: z.string(),
|
|
3281
|
-
// The parent file holding the reference
|
|
3699
|
+
// The parent file holding the reference - its `ContextNode.path`, not its
|
|
3282
3700
|
// id: ids are case-folded on Windows and are not safe to write through.
|
|
3283
3701
|
filePath: z.string(),
|
|
3284
3702
|
rawTarget: z.string(),
|
|
@@ -3293,7 +3711,7 @@ export const ContextEdgeConvertResponseMessageSchema = z.object({
|
|
|
3293
3711
|
error: z.string().optional(),
|
|
3294
3712
|
}),
|
|
3295
3713
|
});
|
|
3296
|
-
// Deletes every mechanically-fixable finding's range in one pass
|
|
3714
|
+
// Deletes every mechanically-fixable finding's range in one pass - the
|
|
3297
3715
|
// "Fix all" button in the Issues tab. Each item names the file, the range the
|
|
3298
3716
|
// scan flagged, and the snippet expected there; a file that changed since the
|
|
3299
3717
|
// scan is skipped rather than corrupted (charter §7.5).
|
|
@@ -3317,7 +3735,7 @@ export const ContextFindingsFixResponseMessageSchema = z.object({
|
|
|
3317
3735
|
}),
|
|
3318
3736
|
});
|
|
3319
3737
|
// ---------------------------------------------------------------------------
|
|
3320
|
-
// Personality memory
|
|
3738
|
+
// Personality memory - the lessons a named personality accrues across sessions.
|
|
3321
3739
|
// See docs/agent-personalities.md § Memory.
|
|
3322
3740
|
// ---------------------------------------------------------------------------
|
|
3323
3741
|
// Plain strings on the wire, like personality roles and effort levels, so the
|
|
@@ -3360,7 +3778,7 @@ export const PersonalityMemoryListResponseMessageSchema = z.object({
|
|
|
3360
3778
|
personalityName: z.string(),
|
|
3361
3779
|
/** Whether this personality is accruing (the `memoryEnabled` switch). */
|
|
3362
3780
|
enabled: z.boolean(),
|
|
3363
|
-
/** Every stored entry, including other projects'
|
|
3781
|
+
/** Every stored entry, including other projects' - the UI shows them all. */
|
|
3364
3782
|
entries: z.array(PersonalityMemoryEntrySchema),
|
|
3365
3783
|
// The EXACT text the daemon would inject for `projectRoot`, not a
|
|
3366
3784
|
// reconstruction. Memory is only trustworthy if it is inspectable, and the
|
|
@@ -3428,7 +3846,7 @@ export const PersonalityMemoryTransferResponseMessageSchema = z.object({
|
|
|
3428
3846
|
}),
|
|
3429
3847
|
});
|
|
3430
3848
|
// Per-personality lesson counts. Its own RPC over its own file, mirroring
|
|
3431
|
-
// agentPersonalities.get_stats
|
|
3849
|
+
// agentPersonalities.get_stats - counts must not ride the daemon-config
|
|
3432
3850
|
// broadcast, or every recorded lesson would fan a config change to every client.
|
|
3433
3851
|
export const PersonalityMemoryStatsRequestMessageSchema = z.object({
|
|
3434
3852
|
type: z.literal("personality.memory.stats.request"),
|
|
@@ -3452,14 +3870,14 @@ const SuggestedTaskActionResponsePayloadSchema = z.object({
|
|
|
3452
3870
|
failed: z.number(),
|
|
3453
3871
|
error: z.string().nullable(),
|
|
3454
3872
|
});
|
|
3455
|
-
// Start one or more suggested tasks, applying the SAME mode to each
|
|
3873
|
+
// Start one or more suggested tasks, applying the SAME mode to each - no
|
|
3456
3874
|
// combining. Four modes, only `subagent` links the new agent to the parent:
|
|
3457
3875
|
// - `new_chat`: a fresh independent agent in its own tab, same repo/cwd, NO
|
|
3458
|
-
// parent link
|
|
3876
|
+
// parent link - survives the parent's cancel/archive.
|
|
3459
3877
|
// - `subagent`: a bound child agent that shows in the parent's Subagents
|
|
3460
3878
|
// track and archive-cascades with it.
|
|
3461
3879
|
// - `worktree`: an independent agent on a new git worktree (auto branch-off),
|
|
3462
|
-
// isolated workspace
|
|
3880
|
+
// isolated workspace - also unlinked from the parent.
|
|
3463
3881
|
// - `in_session`: steers the parent agent with the task prompt (no new agent).
|
|
3464
3882
|
// The daemon resolves the parent agent's brain (provider/model/personality) so a
|
|
3465
3883
|
// started task continues the suggesting agent.
|
|
@@ -3492,8 +3910,8 @@ export const TasksSuggestedDismissResponseMessageSchema = z.object({
|
|
|
3492
3910
|
});
|
|
3493
3911
|
// Switch a running agent to an Agent Personality (or clear with null). The
|
|
3494
3912
|
// daemon re-resolves the id against the roster + the agent's cwd provider
|
|
3495
|
-
// snapshot and applies the full personality live
|
|
3496
|
-
// (name/spinner), and brain (model/mode/effort)
|
|
3913
|
+
// snapshot and applies the full personality live - system prompt, identity
|
|
3914
|
+
// (name/spinner), and brain (model/mode/effort) - restarting the provider query
|
|
3497
3915
|
// so the new prompt takes effect on the next turn. Providers that cannot apply
|
|
3498
3916
|
// a prompt mid-session reject. COMPAT(setAgentPersonality): added in v0.5.0;
|
|
3499
3917
|
// gate lives in features.setAgentPersonality.
|
|
@@ -3811,7 +4229,7 @@ export const RunsClearResponseSchema = z.object({
|
|
|
3811
4229
|
requestId: z.string(),
|
|
3812
4230
|
}),
|
|
3813
4231
|
});
|
|
3814
|
-
// Delete one run by id. Terminal (done/failed/canceled) and draft runs only
|
|
4232
|
+
// Delete one run by id. Terminal (done/failed/canceled) and draft runs only -
|
|
3815
4233
|
// deleting an active run is refused so a cleanup click can't silently orphan
|
|
3816
4234
|
// running agents; cancel it first. Gated by server_info.features.runsDelete.
|
|
3817
4235
|
export const RunsDeleteRequestSchema = z.object({
|
|
@@ -3823,7 +4241,7 @@ export const RunsDeleteResponseSchema = z.object({
|
|
|
3823
4241
|
type: z.literal("runs.delete.response"),
|
|
3824
4242
|
payload: z.object({
|
|
3825
4243
|
// The deleted id, or absent when nothing was deleted (unknown or still
|
|
3826
|
-
// active)
|
|
4244
|
+
// active) - `error` then carries why.
|
|
3827
4245
|
runId: z.string().optional(),
|
|
3828
4246
|
error: z.string().optional(),
|
|
3829
4247
|
requestId: z.string(),
|
|
@@ -3938,11 +4356,11 @@ export const RunsTemplatesChangedNotificationSchema = z.object({
|
|
|
3938
4356
|
}),
|
|
3939
4357
|
});
|
|
3940
4358
|
// Start (or draft) a user-initiated orchestration from the New Orchestration
|
|
3941
|
-
// dialog. `flavor` is an open vocabulary: "ai" (prompt-and-go
|
|
4359
|
+
// dialog. `flavor` is an open vocabulary: "ai" (prompt-and-go - the daemon
|
|
3942
4360
|
// spawns an orchestrator agent that declares its own plan via start_run) or
|
|
3943
|
-
// "graph" (deterministic
|
|
4361
|
+
// "graph" (deterministic - the daemon executes `graphId` with `graphInputs`).
|
|
3944
4362
|
// `draft: true` creates the record without executing (the designer flow);
|
|
3945
|
-
// `runId` executes an existing draft in place
|
|
4363
|
+
// `runId` executes an existing draft in place - or, with `draft: true`, re-saves
|
|
3946
4364
|
// that draft in place (Edit Orchestration).
|
|
3947
4365
|
export const RunsStartRequestSchema = z.object({
|
|
3948
4366
|
type: z.literal("runs.start.request"),
|
|
@@ -3994,7 +4412,7 @@ export const CheckoutGitCommitRequestSchema = z.object({
|
|
|
3994
4412
|
});
|
|
3995
4413
|
// Resolve which agent the daemon would use to author a commit message for this
|
|
3996
4414
|
// checkout (the "writer" role) so the client can name it in a confirmation
|
|
3997
|
-
// before running the AI-authored commit. A pure query
|
|
4415
|
+
// before running the AI-authored commit. A pure query - it never commits. Gated
|
|
3998
4416
|
// by server_info.features.checkoutGitCommitAgent.
|
|
3999
4417
|
export const CheckoutGitCommitAgentRequestSchema = z.object({
|
|
4000
4418
|
type: z.literal("checkout.git.commit_agent.request"),
|
|
@@ -4046,8 +4464,8 @@ export const CheckoutGitFileCommitDiffRequestSchema = z.object({
|
|
|
4046
4464
|
ignoreWhitespace: z.boolean().optional(),
|
|
4047
4465
|
requestId: z.string(),
|
|
4048
4466
|
});
|
|
4049
|
-
// One page of blame. Always paged
|
|
4050
|
-
// daemon
|
|
4467
|
+
// One page of blame. Always paged - blaming a large file whole would block the
|
|
4468
|
+
// daemon - so the client walks the file a page at a time.
|
|
4051
4469
|
export const CheckoutGitFileBlameRequestSchema = z.object({
|
|
4052
4470
|
type: z.literal("checkout.git.get_file_blame.request"),
|
|
4053
4471
|
cwd: z.string(),
|
|
@@ -4326,7 +4744,7 @@ export const HostingSearchRequestSchema = z.object({
|
|
|
4326
4744
|
kinds: z.array(HostingSearchKindSchema).optional(),
|
|
4327
4745
|
requestId: z.string(),
|
|
4328
4746
|
});
|
|
4329
|
-
// Reports whether a host-level provider's credentials are valid
|
|
4747
|
+
// Reports whether a host-level provider's credentials are valid - drives the
|
|
4330
4748
|
// connection-status row in the host Git providers settings section.
|
|
4331
4749
|
export const HostingAuthStatusRequestSchema = z.object({
|
|
4332
4750
|
type: z.literal("hosting.auth_status.request"),
|
|
@@ -4429,10 +4847,10 @@ export const ProjectAddRequestSchema = z.object({
|
|
|
4429
4847
|
// from a remote), optionally create that remote on a connected hosting
|
|
4430
4848
|
// provider, then register the result as a project. One RPC rather than a
|
|
4431
4849
|
// client-driven sequence so a half-finished project can never be left behind by
|
|
4432
|
-
// a dropped socket
|
|
4850
|
+
// a dropped socket - the daemon owns the whole transaction.
|
|
4433
4851
|
// COMPAT(projectScaffold): added in v0.6.9. Gated by server_info.features.projectScaffold.
|
|
4434
4852
|
// Built-in .gitignore starters. Deliberately a short list of the ecosystems Otto
|
|
4435
|
-
// itself works in
|
|
4853
|
+
// itself works in - this is a convenience, not a mirror of github/gitignore. The
|
|
4436
4854
|
// wire field stays an open string so a newer daemon can add one without an older
|
|
4437
4855
|
// client's validator rejecting the message.
|
|
4438
4856
|
export const PROJECT_SCAFFOLD_GITIGNORE_TEMPLATE_IDS = [
|
|
@@ -4547,7 +4965,7 @@ export const ArchiveWorkspaceRequestSchema = z.object({
|
|
|
4547
4965
|
workspaceId: z.string(),
|
|
4548
4966
|
requestId: z.string(),
|
|
4549
4967
|
// COMPAT(worktreeArchiveBranchCleanup): added in v0.6.7, drop the optional
|
|
4550
|
-
// gate when daemon floor >= v0.6.7. Absent means "keep"
|
|
4968
|
+
// gate when daemon floor >= v0.6.7. Absent means "keep" - the leftover local
|
|
4551
4969
|
// branch is never touched (old-client behavior). "delete" asks the daemon to
|
|
4552
4970
|
// remove the worktree's local branch after the backing directory is torn down
|
|
4553
4971
|
// (only when this was the last reference to it and the branch is not checked
|
|
@@ -4569,7 +4987,7 @@ export const WorkspaceArchivePreflightRequestSchema = z.object({
|
|
|
4569
4987
|
// record the answer, and it has to look like one or a wrong guess reads as a bug in the diff.
|
|
4570
4988
|
// COMPAT(checkoutDiffBaseAnyRepo): added in v0.7.4.
|
|
4571
4989
|
export const CheckoutBaseSourceSchema = z.enum(["user", "inferred", "worktree", "default"]);
|
|
4572
|
-
// Repoint a worktree-backed workspace's base branch
|
|
4990
|
+
// Repoint a worktree-backed workspace's base branch - what the Changes view diffs
|
|
4573
4991
|
// against, and what merge-into-base and PR creation target. On a stacked branch the
|
|
4574
4992
|
// useful base is the parent branch, not the repo default, the same way a forge PR
|
|
4575
4993
|
// carries an explicit base. A null baseRef resets to the repository default branch.
|
|
@@ -4579,7 +4997,7 @@ export const WorktreeBaseRefSetRequestSchema = z.object({
|
|
|
4579
4997
|
requestId: z.string(),
|
|
4580
4998
|
workspaceId: z.string(),
|
|
4581
4999
|
// Branch name; null resets to the default branch. An `origin/` prefix is meaningful and is
|
|
4582
|
-
// kept
|
|
5000
|
+
// kept - `main` and `origin/main` are different comparisons whenever the two have drifted.
|
|
4583
5001
|
baseRef: z.string().nullable(),
|
|
4584
5002
|
// Forget the remembered base and detect the branch's parent again, ignoring `baseRef`.
|
|
4585
5003
|
// The escape hatch for a wrong guess: parent detection is a heuristic over a graph that does
|
|
@@ -4772,7 +5190,7 @@ export const FsFileWriteRequestSchema = z.object({
|
|
|
4772
5190
|
* The counterpart to `fs.file.write`, which is text only: it LF-normalizes,
|
|
4773
5191
|
* re-applies the file's detected EOL, and outright refuses to overwrite a file
|
|
4774
5192
|
* whose current bytes look binary. None of that can carry a PDF, an image or
|
|
4775
|
-
* any other generated artifact, so those go through here instead
|
|
5193
|
+
* any other generated artifact, so those go through here instead - the bytes
|
|
4776
5194
|
* land verbatim.
|
|
4777
5195
|
*
|
|
4778
5196
|
* Deliberately not a conditional write. Callers are producing a generated file
|
|
@@ -4787,8 +5205,8 @@ export const FsFileWriteRequestSchema = z.object({
|
|
|
4787
5205
|
* is a different power and does not need to be that wide.
|
|
4788
5206
|
*
|
|
4789
5207
|
* The bytes themselves do not ride in this message. They follow it as
|
|
4790
|
-
* `FileTransfer` binary frames correlated on `requestId`
|
|
4791
|
-
* FileChunk, then FileEnd
|
|
5208
|
+
* `FileTransfer` binary frames correlated on `requestId` - FileBegin, then
|
|
5209
|
+
* FileChunk, then FileEnd - the same transport `file.upload` uses. This request
|
|
4792
5210
|
* is the metadata half: where the bytes go and how many of them to expect.
|
|
4793
5211
|
* Everything here writes multi-megabyte files (a printed PDF, a dropped image),
|
|
4794
5212
|
* and base64 in a JSON message costs a third again on the wire plus the whole
|
|
@@ -4810,8 +5228,8 @@ export const FsFileWriteBinaryRequestSchema = z.object({
|
|
|
4810
5228
|
*
|
|
4811
5229
|
* COMPAT(binaryWriteBase64): added in v0.7.6, drop this field and its daemon
|
|
4812
5230
|
* branch on 2027-02-02. Superseded by `size` plus file-transfer frames. The
|
|
4813
|
-
* daemon still reads it
|
|
4814
|
-
* accepting
|
|
5231
|
+
* daemon still reads it - a field we stopped sending is not a field we stop
|
|
5232
|
+
* accepting - and picks the branch from which of the two is present.
|
|
4815
5233
|
*/
|
|
4816
5234
|
contentBase64: z.string().optional(),
|
|
4817
5235
|
/**
|
|
@@ -4843,7 +5261,7 @@ export const FileUploadRequestSchema = z.object({
|
|
|
4843
5261
|
/**
|
|
4844
5262
|
* Text-editor save. A conditional write: the request carries the client's
|
|
4845
5263
|
* last-known file identity and the daemon refuses to clobber content it did
|
|
4846
|
-
* not hand out
|
|
5264
|
+
* not hand out - a mismatch comes back as a typed conflict, never a write.
|
|
4847
5265
|
*/
|
|
4848
5266
|
export const FileWriteRequestSchema = z.object({
|
|
4849
5267
|
type: z.literal("file.write.request"),
|
|
@@ -4881,7 +5299,7 @@ export const FileCreateRequestSchema = z.object({
|
|
|
4881
5299
|
requestId: z.string(),
|
|
4882
5300
|
});
|
|
4883
5301
|
/**
|
|
4884
|
-
* Permanent delete
|
|
5302
|
+
* Permanent delete - an unlink, not a move to the OS trash. The daemon may be
|
|
4885
5303
|
* headless, remote, or inside WSL, where there is no reliable trash to move to;
|
|
4886
5304
|
* a "deleted" file that silently stayed on disk in one environment and vanished
|
|
4887
5305
|
* in another would be worse than either. The client's confirmation says so.
|
|
@@ -4897,7 +5315,7 @@ export const FileDeleteRequestSchema = z.object({
|
|
|
4897
5315
|
requestId: z.string(),
|
|
4898
5316
|
});
|
|
4899
5317
|
/**
|
|
4900
|
-
* Rename and move are the same operation
|
|
5318
|
+
* Rename and move are the same operation - a move is a rename whose new path
|
|
4901
5319
|
* has a different parent. Never clobbers: an occupied destination comes back as
|
|
4902
5320
|
* `exists` and nothing moves. There is no overwrite flag on purpose, so this
|
|
4903
5321
|
* RPC cannot destroy a file the user did not name.
|
|
@@ -4910,7 +5328,7 @@ export const FileRenameRequestSchema = z.object({
|
|
|
4910
5328
|
requestId: z.string(),
|
|
4911
5329
|
});
|
|
4912
5330
|
/**
|
|
4913
|
-
* Refine
|
|
5331
|
+
* Refine - an AI rewrite the user reviews as a diff before anything is written.
|
|
4914
5332
|
* This RPC only *proposes*: it reads nothing from disk and writes nothing. The
|
|
4915
5333
|
* accepted result goes back through `file.write.request` like any other save,
|
|
4916
5334
|
* so the conditional-write precondition still guards it.
|
|
@@ -4938,7 +5356,7 @@ export const FileRefineReferenceSchema = z.object({
|
|
|
4938
5356
|
});
|
|
4939
5357
|
export const FileRefineRequestSchema = z.object({
|
|
4940
5358
|
type: z.literal("file.refine.request"),
|
|
4941
|
-
// Provider resolution only
|
|
5359
|
+
// Provider resolution only - which workspace's mini-task chain runs this.
|
|
4942
5360
|
// Documents are NOT read from disk here; they travel on the wire.
|
|
4943
5361
|
cwd: z.string(),
|
|
4944
5362
|
// What the model may rewrite. The blast radius of the whole request: a file
|
|
@@ -5059,7 +5477,7 @@ export const CodeRenamePreviewRequestSchema = z.object({
|
|
|
5059
5477
|
*
|
|
5060
5478
|
* The client sends back only the `planId` it was shown; the daemon recomputes the plan and
|
|
5061
5479
|
* refuses unless the identity matches. A request that carried its own edit list would be a
|
|
5062
|
-
* remote arbitrary-write primitive wearing a rename's name
|
|
5480
|
+
* remote arbitrary-write primitive wearing a rename's name - any client could post any text
|
|
5063
5481
|
* at any path. This shape makes the daemon's own language server the sole author of what
|
|
5064
5482
|
* gets written, and the plan id the proof that the user saw it.
|
|
5065
5483
|
*/
|
|
@@ -5075,7 +5493,7 @@ export const CodeRenameApplyRequestSchema = z.object({
|
|
|
5075
5493
|
requestId: z.string(),
|
|
5076
5494
|
});
|
|
5077
5495
|
/**
|
|
5078
|
-
* Undo a run. Carries only the run's id
|
|
5496
|
+
* Undo a run. Carries only the run's id - the daemon holds the before-images.
|
|
5079
5497
|
*
|
|
5080
5498
|
* Declared here, with the other inbound rename schemas, rather than beside its response
|
|
5081
5499
|
* further down: `SessionInboundMessageSchema` is a top-level const, so a schema it names
|
|
@@ -5119,8 +5537,8 @@ export const LspServerStopRequestSchema = z.object({
|
|
|
5119
5537
|
* as the build system sees it rather than as the filesystem lays it out.
|
|
5120
5538
|
*
|
|
5121
5539
|
* **Independent of the LSP family above, despite sharing the `code.` domain.** There is no
|
|
5122
|
-
* project-structure request in the Language Server Protocol
|
|
5123
|
-
* that does not exist
|
|
5540
|
+
* project-structure request in the Language Server Protocol - not one Otto has yet to wire, one
|
|
5541
|
+
* that does not exist - so this subsystem builds its own model through Microsoft's solution
|
|
5124
5542
|
* libraries. Turning C# code intelligence off does not turn this off, and vice versa.
|
|
5125
5543
|
*
|
|
5126
5544
|
* Discovery is separate from loading on purpose: `list` decides whether the switcher appears at
|
|
@@ -5136,7 +5554,7 @@ export const CodeSolutionListRequestSchema = z.object({
|
|
|
5136
5554
|
});
|
|
5137
5555
|
/**
|
|
5138
5556
|
* One solution's organisation: folders, the projects inside them, and the configurations. No file
|
|
5139
|
-
* membership
|
|
5557
|
+
* membership - that is `load_project`, paid per project on expand, because evaluating fifty
|
|
5140
5558
|
* projects to render a collapsed tree is the cost this design exists to avoid.
|
|
5141
5559
|
*/
|
|
5142
5560
|
export const CodeSolutionGetTreeRequestSchema = z.object({
|
|
@@ -5148,7 +5566,7 @@ export const CodeSolutionGetTreeRequestSchema = z.object({
|
|
|
5148
5566
|
});
|
|
5149
5567
|
/**
|
|
5150
5568
|
* One project's evaluated file membership. `solutionPath` scopes the sidecar instance so two
|
|
5151
|
-
* solutions in one repo never share a warm `ProjectCollection`
|
|
5569
|
+
* solutions in one repo never share a warm `ProjectCollection` - and so Phase 4 has the selection
|
|
5152
5570
|
* it needs for `--solution`.
|
|
5153
5571
|
*/
|
|
5154
5572
|
export const CodeSolutionLoadProjectRequestSchema = z.object({
|
|
@@ -5186,7 +5604,7 @@ const FileReplaceMatchSchema = z.object({
|
|
|
5186
5604
|
});
|
|
5187
5605
|
/**
|
|
5188
5606
|
* Preview-first project replace. Each file carries the hash the preview was
|
|
5189
|
-
* built against
|
|
5607
|
+
* built against - files changed since are skipped and reported, never
|
|
5190
5608
|
* corrupted. The replacement string is literal (no capture references in v1).
|
|
5191
5609
|
*/
|
|
5192
5610
|
export const FileReplaceRequestSchema = z.object({
|
|
@@ -5271,7 +5689,7 @@ export const CreateTerminalRequestSchema = z.object({
|
|
|
5271
5689
|
command: z.string().optional(),
|
|
5272
5690
|
args: z.array(z.string()).optional(),
|
|
5273
5691
|
// Initial PTY size. Added in v0.1.107; the app no longer sends it (the estimate cache that fed
|
|
5274
|
-
// it was removed
|
|
5692
|
+
// it was removed - the pane-focus resize claim sizes the PTY instead). Kept and honored
|
|
5275
5693
|
// permanently: released v0.1.107 clients still send it, and programmatic callers may pass an
|
|
5276
5694
|
// exact size. Daemons without it start at 80x24 and the first resize corrects that.
|
|
5277
5695
|
size: z
|
|
@@ -5432,6 +5850,14 @@ export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
5432
5850
|
BrainHfSearchRequestSchema,
|
|
5433
5851
|
BrainHfQuantsRequestSchema,
|
|
5434
5852
|
BrainModelsAddRequestSchema,
|
|
5853
|
+
BrainModelsInventoryRequestSchema,
|
|
5854
|
+
BrainModelProfileGetRequestSchema,
|
|
5855
|
+
BrainModelProfileSetRequestSchema,
|
|
5856
|
+
BrainModelBudgetGetRequestSchema,
|
|
5857
|
+
BrainModelLoadRequestSchema,
|
|
5858
|
+
BrainModelUnloadRequestSchema,
|
|
5859
|
+
BrainModelDeleteRequestSchema,
|
|
5860
|
+
BrainLogsTailRequestSchema,
|
|
5435
5861
|
UpdateAgentRequestMessageSchema,
|
|
5436
5862
|
ProjectRenameRequestSchema,
|
|
5437
5863
|
ProjectRemoveRequestSchema,
|
|
@@ -5454,6 +5880,8 @@ export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
5454
5880
|
GetDaemonConfigRequestMessageSchema,
|
|
5455
5881
|
SetDaemonConfigRequestMessageSchema,
|
|
5456
5882
|
ConnectorsListToolsRequestSchema,
|
|
5883
|
+
ConnectorsOauthAuthorizeRequestSchema,
|
|
5884
|
+
ConnectorsOauthDisconnectRequestSchema,
|
|
5457
5885
|
SpeechSettingsGetOptionsRequestSchema,
|
|
5458
5886
|
SpeechTtsPreviewRequestSchema,
|
|
5459
5887
|
SpeechTtsSpeakRequestSchema,
|
|
@@ -5902,6 +6330,16 @@ export const ServerInfoStatusPayloadSchema = z
|
|
|
5902
6330
|
// Without it the Brain "Models" section hides the Hugging Face search box.
|
|
5903
6331
|
// COMPAT(brainHfSearch): added in v0.7.5, remove gate after 2026-07-30 once daemon floor >= v0.7.5.
|
|
5904
6332
|
brainHfSearch: z.boolean().optional(),
|
|
6333
|
+
// Daemon proxies the brain's own /__host/* management API: the joined
|
|
6334
|
+
// model inventory, per-model profiles, the VRAM budget, load/unload,
|
|
6335
|
+
// delete, and the log tail. Unlike brainManage (which shells out to the
|
|
6336
|
+
// CLI and is therefore local-only) these work against a remote brain too.
|
|
6337
|
+
// Without it the Brain page is not offered at all. Which of those the
|
|
6338
|
+
// brain on the far side actually serves is a separate question, answered
|
|
6339
|
+
// by `capabilities` on brain.host.status, because the daemon and the
|
|
6340
|
+
// brain version independently.
|
|
6341
|
+
// COMPAT(brainConsole): added in v0.7.7, drop the gate when daemon floor >= v0.7.7.
|
|
6342
|
+
brainConsole: z.boolean().optional(),
|
|
5905
6343
|
// COMPAT(agentForkContext): added in v0.1.102, remove gate after 2026-12-28.
|
|
5906
6344
|
agentForkContext: z.boolean().optional(),
|
|
5907
6345
|
// COMPAT(providerRemove): added in v0.1.105, drop the gate when daemon floor >= v0.1.105.
|
|
@@ -5924,7 +6362,7 @@ export const ServerInfoStatusPayloadSchema = z
|
|
|
5924
6362
|
// Daemon owns a per-agent queue of steering messages, accepts
|
|
5925
6363
|
// `delivery: "queue"` on send, reports `queuedMessages` on the agent
|
|
5926
6364
|
// snapshot, and serves agent.queue.remove/clear. Without it the
|
|
5927
|
-
// composer keeps its own local queue
|
|
6365
|
+
// composer keeps its own local queue - that is the pre-existing
|
|
5928
6366
|
// behavior, not a degraded build of this feature.
|
|
5929
6367
|
steerQueue: z.boolean().optional(),
|
|
5930
6368
|
// Daemon serves agent.queue.reorder. Separate from `steerQueue`
|
|
@@ -5935,34 +6373,34 @@ export const ServerInfoStatusPayloadSchema = z
|
|
|
5935
6373
|
// Daemon reports `cumulativeUsage` (the lifetime in/cached/out split
|
|
5936
6374
|
// plus its own booked cost) on every agent snapshot, so a chat's total
|
|
5937
6375
|
// spend can be summed and priced honestly. Without it the client shows
|
|
5938
|
-
// token totals only and no cost
|
|
6376
|
+
// token totals only and no cost - NOT an estimated cost, which is the
|
|
5939
6377
|
// behavior this feature exists to remove.
|
|
5940
6378
|
// COMPAT(cumulativeUsage): added in v0.7.0, drop the gate when daemon floor >= v0.7.0.
|
|
5941
6379
|
cumulativeUsage: z.boolean().optional(),
|
|
5942
6380
|
// Daemon can resolve and evaluate the provider's context graph, serve
|
|
5943
6381
|
// context.report.* and push context_report_changed. Without it the
|
|
5944
6382
|
// client hides both the Context Management tab and the composer
|
|
5945
|
-
// warning entirely
|
|
6383
|
+
// warning entirely - there is no degraded client-side fallback, since
|
|
5946
6384
|
// only the daemon can see the files a provider loads.
|
|
5947
6385
|
// COMPAT(contextManagement): added in v0.6.5, drop the gate when daemon floor >= v0.6.5.
|
|
5948
6386
|
contextManagement: z.boolean().optional(),
|
|
5949
6387
|
// COMPAT(textEditor): added in v0.4.4, drop the gate when daemon floor >= v0.4.4.
|
|
5950
6388
|
textEditor: z.boolean().optional(),
|
|
5951
|
-
// Refine
|
|
6389
|
+
// Refine - the daemon can turn a pinned document plus an instruction
|
|
5952
6390
|
// into a proposed rewrite (`file.refine.*`). Without it the Refine
|
|
5953
6391
|
// entry is absent: there is no client-side substitute for a model, and
|
|
5954
6392
|
// a degraded "open a chat instead" path is exactly the unreviewed edit
|
|
5955
6393
|
// Refine exists to replace.
|
|
5956
6394
|
// COMPAT(refine): added in v0.6.9, drop the gate when daemon floor >= v0.6.9.
|
|
5957
6395
|
refine: z.boolean().optional(),
|
|
5958
|
-
// Personality memory
|
|
6396
|
+
// Personality memory - the daemon stores per-personality lessons, injects
|
|
5959
6397
|
// them at spawn, and serves personality.memory.*. Without it the client
|
|
5960
6398
|
// hides the Memory tab, the accrual indicator and the transfer-on-delete
|
|
5961
6399
|
// choice: storage is daemon-side by definition, so there is nothing a
|
|
5962
6400
|
// client-side fallback could read.
|
|
5963
6401
|
// COMPAT(personalityMemory): added in v0.7.0, drop the gate when daemon floor >= v0.7.0.
|
|
5964
6402
|
personalityMemory: z.boolean().optional(),
|
|
5965
|
-
// Script discovery
|
|
6403
|
+
// Script discovery - the daemon scans a workspace for the Scripts its
|
|
5966
6404
|
// project files already declare (package.json scripts, and later
|
|
5967
6405
|
// Makefile targets, .NET launch profiles) and serves them from
|
|
5968
6406
|
// `workspace.script.list` with `includeDiscovered`. Without it the
|
|
@@ -5988,11 +6426,11 @@ export const ServerInfoStatusPayloadSchema = z
|
|
|
5988
6426
|
// flag the client says to update the host rather than showing an empty screen.
|
|
5989
6427
|
// COMPAT(lspHostServers): added in v0.7.3, drop the gate when daemon floor >= v0.7.3.
|
|
5990
6428
|
lspHostServers: z.boolean().optional(),
|
|
5991
|
-
// The Solution view
|
|
6429
|
+
// The Solution view - the daemon can discover solutions and serve
|
|
5992
6430
|
// `code.solution.*`. Deliberately NOT implied by `lsp`: there is no
|
|
5993
6431
|
// project-structure request in LSP, so this subsystem is independent of
|
|
5994
6432
|
// language servers and of the C# row's on/off state. Without the flag the
|
|
5995
|
-
// client never shows the view switcher and never asks
|
|
6433
|
+
// client never shows the view switcher and never asks - there is no
|
|
5996
6434
|
// client-side substitute for reading a solution, and a hand-parsed
|
|
5997
6435
|
// half-tree is exactly the mistake this design exists to avoid.
|
|
5998
6436
|
// COMPAT(solutionView): added in v0.6.8, drop the gate when daemon floor >= v0.6.8.
|
|
@@ -6027,7 +6465,7 @@ export const ServerInfoStatusPayloadSchema = z
|
|
|
6027
6465
|
// COMPAT(checkoutGitLog): added in v0.5.1, drop the gate when daemon floor >= v0.5.1.
|
|
6028
6466
|
checkoutGitLog: z.boolean().optional(),
|
|
6029
6467
|
// Local-git file investigation: history, per-commit diff, blame, origin
|
|
6030
|
-
// commit
|
|
6468
|
+
// commit - for a whole file or a line range. No forge connection needed
|
|
6031
6469
|
// and no per-provider rollout; it is git, so every provider gets it at
|
|
6032
6470
|
// once.
|
|
6033
6471
|
// COMPAT(checkoutGitFileHistory): added in v0.6.6, drop the gate when daemon floor >= v0.6.6.
|
|
@@ -6036,19 +6474,19 @@ export const ServerInfoStatusPayloadSchema = z
|
|
|
6036
6474
|
// archiving (workspace.archive.preflight.*) and delete it as part of the
|
|
6037
6475
|
// archive (archive_workspace_request.branchDisposition). Without it the
|
|
6038
6476
|
// client archives the worktree exactly as before and never offers to
|
|
6039
|
-
// remove the branch
|
|
6477
|
+
// remove the branch - no degraded client-side branch detection exists.
|
|
6040
6478
|
// COMPAT(worktreeArchiveBranchCleanup): added in v0.6.7, drop the gate when daemon floor >= v0.6.7.
|
|
6041
6479
|
worktreeArchiveBranchCleanup: z.boolean().optional(),
|
|
6042
6480
|
// COMPAT(worktreeReattach): added in v0.6.7, drop the gate when daemon floor >= v0.6.7.
|
|
6043
6481
|
worktreeReattach: z.boolean().optional(),
|
|
6044
6482
|
// Set when the daemon can repoint a worktree's stored base branch
|
|
6045
6483
|
// (worktree.baseRef.set.*). Without it the client renders the base as a
|
|
6046
|
-
// read-only "vs <base>" label
|
|
6484
|
+
// read-only "vs <base>" label - there is no client-side override, since only
|
|
6047
6485
|
// the daemon can write the worktree's metadata.
|
|
6048
6486
|
// COMPAT(worktreeDiffBase): added in v0.6.8, drop the gate when daemon floor >= v0.6.8.
|
|
6049
6487
|
worktreeDiffBase: z.boolean().optional(),
|
|
6050
6488
|
// Set when the daemon stores the diff base *per branch*, which is what lets any git
|
|
6051
|
-
// checkout repoint it rather than only an Otto worktree
|
|
6489
|
+
// checkout repoint it rather than only an Otto worktree - a plain checkout's gitdir is
|
|
6052
6490
|
// shared by every branch in it, so a single stored base would bleed across branch
|
|
6053
6491
|
// switches. Also gates parent-branch detection, the `origin/`-qualified pin, and the
|
|
6054
6492
|
// re-detect action. Without it the client keeps the worktree-only picker.
|
|
@@ -6104,24 +6542,30 @@ export const ServerInfoStatusPayloadSchema = z
|
|
|
6104
6542
|
// cap) shows "Update the host" instead of a knob that does nothing.
|
|
6105
6543
|
openaiCompatMaxToolRounds: z.boolean().optional(),
|
|
6106
6544
|
// COMPAT(mcpToolGroups): added in v0.6.4, drop the gate when daemon floor >= v0.6.4.
|
|
6107
|
-
// Set when the daemon honors `mcp.toolGroups`
|
|
6545
|
+
// Set when the daemon honors `mcp.toolGroups` - per-group gating of the
|
|
6108
6546
|
// Otto tool catalog on the MCP (Claude) path. Old daemons register every
|
|
6109
6547
|
// group regardless, so the client hides the categorized section instead
|
|
6110
6548
|
// of showing category switches that do nothing.
|
|
6111
6549
|
mcpToolGroups: z.boolean().optional(),
|
|
6112
6550
|
// COMPAT(connectors): added in v0.7.5, drop the gate when daemon floor >= v0.7.5.
|
|
6113
|
-
// Set when the daemon persists and honors `connectors`
|
|
6551
|
+
// Set when the daemon persists and honors `connectors` - MCP servers
|
|
6114
6552
|
// surfaced as named, toggle-able integrations with per-tool disable,
|
|
6115
6553
|
// enforced today on the openai-compat path. Old daemons ignore the
|
|
6116
6554
|
// section, so the client hides the Connectors settings entirely.
|
|
6117
6555
|
connectors: z.boolean().optional(),
|
|
6556
|
+
// COMPAT(connectorOauth): added in v0.7.7, drop the gate when daemon floor >= v0.7.7.
|
|
6557
|
+
// Set when the daemon can run the OAuth authorization-code flow for a
|
|
6558
|
+
// connector and attach the resulting token to its MCP transport. Old
|
|
6559
|
+
// daemons have no broker and no way to hold a token, so the client hides
|
|
6560
|
+
// Connect / Disconnect and offers only the paste-a-token connectors.
|
|
6561
|
+
connectorOauth: z.boolean().optional(),
|
|
6118
6562
|
// COMPAT(agentBehaviorToggles): added in v0.6.4, drop the gate when daemon floor >= v0.6.4.
|
|
6119
6563
|
// Set when the daemon persists `agentBehaviors.*` (promptSuggestions,
|
|
6120
6564
|
// agentProgressSummaries, notifyOnFinishDefault). The reads are wired by
|
|
6121
6565
|
// Claude-tier providers (WP-E); the client gates the toggle cards on this.
|
|
6122
6566
|
agentBehaviorToggles: z.boolean().optional(),
|
|
6123
6567
|
// COMPAT(todoReminders): added in v0.7.5, drop the gate when daemon floor >= v0.7.5.
|
|
6124
|
-
// Set when the daemon acts on `agentBehaviors.{todoNudge,todoReconcileOnIdle}`
|
|
6568
|
+
// Set when the daemon acts on `agentBehaviors.{todoNudge,todoReconcileOnIdle}` -
|
|
6125
6569
|
// the provider-agnostic stale-todo nudge (next turn) and idle reconcile pass.
|
|
6126
6570
|
// The client gates the task-list toggle cards on this so an old daemon never
|
|
6127
6571
|
// shows switches that do nothing.
|
|
@@ -6152,27 +6596,27 @@ export const ServerInfoStatusPayloadSchema = z
|
|
|
6152
6596
|
// the existing `delete_agent_request`, and in bulk via
|
|
6153
6597
|
// `history.agents.clear_archived`. Archive has always been a soft delete
|
|
6154
6598
|
// with no counterpart; this is the counterpart. Deleting removes Otto's
|
|
6155
|
-
// record only
|
|
6599
|
+
// record only - provider transcripts are never touched (see the
|
|
6156
6600
|
// clear_archived schema). The client hides both affordances when this is
|
|
6157
6601
|
// absent rather than shipping a degraded path.
|
|
6158
6602
|
historyDelete: z.boolean().optional(),
|
|
6159
6603
|
// COMPAT(fileMutations): added in v0.7.0, drop the gate when daemon floor >= v0.7.0.
|
|
6160
6604
|
// Set when the daemon serves `file.create`, `file.delete` and
|
|
6161
|
-
// `file.rename`
|
|
6605
|
+
// `file.rename` - creating, removing and moving entries, as opposed to
|
|
6162
6606
|
// `file.write`, which only changes what is inside an existing file.
|
|
6163
6607
|
// There is no client-side substitute (the client never touches the
|
|
6164
6608
|
// filesystem), so an old daemon simply does not get the menu items.
|
|
6165
6609
|
fileMutations: z.boolean().optional(),
|
|
6166
6610
|
// COMPAT(binaryFileWrite): added in v0.7.6, drop the gate when daemon
|
|
6167
6611
|
// floor >= v0.7.6. Set when the daemon serves
|
|
6168
|
-
// `fs.file.write_binary`
|
|
6612
|
+
// `fs.file.write_binary` - bytes to a workspace path, as opposed to
|
|
6169
6613
|
// `fs.file.write`, which is text and refuses binary targets outright.
|
|
6170
6614
|
// The client cannot write a workspace file itself on any platform, so
|
|
6171
6615
|
// an old daemon simply does not offer the exports that produce bytes.
|
|
6172
6616
|
binaryFileWrite: z.boolean().optional(),
|
|
6173
6617
|
// COMPAT(attachmentStorage): added in v0.7.1, drop the gate when daemon floor >= v0.7.1.
|
|
6174
6618
|
// Set when the daemon serves `attachments.images.get_stats` and
|
|
6175
|
-
// `attachments.images.clear`
|
|
6619
|
+
// `attachments.images.clear` - the readout and reclaim for the images it
|
|
6176
6620
|
// materializes on the agent's behalf. The client has no way to size or
|
|
6177
6621
|
// clear a directory on the host, so an old daemon simply does not get
|
|
6178
6622
|
// the daemon half of the Storage section; the app-side preview cache row
|
|
@@ -6180,7 +6624,7 @@ export const ServerInfoStatusPayloadSchema = z
|
|
|
6180
6624
|
attachmentStorage: z.boolean().optional(),
|
|
6181
6625
|
// COMPAT(agentWorkspaceTransfer): added in v0.7.4, drop the gate when
|
|
6182
6626
|
// daemon floor >= v0.7.4. Set when the daemon serves
|
|
6183
|
-
// `agent.workspace.transfer`
|
|
6627
|
+
// `agent.workspace.transfer` - moving a chat to another workspace over
|
|
6184
6628
|
// the same directory. The client cannot restamp ownership itself (it is
|
|
6185
6629
|
// daemon state), so an old daemon simply does not get the menu item.
|
|
6186
6630
|
agentWorkspaceTransfer: z.boolean().optional(),
|
|
@@ -6306,7 +6750,7 @@ export const DaemonConfigChangedStatusPayloadSchema = z
|
|
|
6306
6750
|
* spinner, so an idempotent snapshot cannot drift out of sync the way a missed
|
|
6307
6751
|
* transition would.
|
|
6308
6752
|
*
|
|
6309
|
-
* Separate from the workspace status bucket on purpose
|
|
6753
|
+
* Separate from the workspace status bucket on purpose - indexing is not the workspace
|
|
6310
6754
|
* "working", and folding it in would mislabel a quiet workspace as busy with agent work.
|
|
6311
6755
|
*/
|
|
6312
6756
|
export const LspActivityChangedStatusPayloadSchema = z
|
|
@@ -6329,11 +6773,11 @@ export const CodeDiagnosticSchema = z.object({
|
|
|
6329
6773
|
endColumn: z.number().int().positive(),
|
|
6330
6774
|
severity: CodeDiagnosticSeveritySchema,
|
|
6331
6775
|
message: z.string(),
|
|
6332
|
-
/** Who says so
|
|
6776
|
+
/** Who says so - `ts`, `pyright`, a linter behind the server. */
|
|
6333
6777
|
source: z.string().optional(),
|
|
6334
6778
|
/** The server's own code for the rule or error, e.g. TypeScript's `2345`. */
|
|
6335
6779
|
code: z.string().optional(),
|
|
6336
|
-
/** Documentation for that rule, when the server offers one
|
|
6780
|
+
/** Documentation for that rule, when the server offers one - oxlint does. */
|
|
6337
6781
|
codeHref: z.string().optional(),
|
|
6338
6782
|
/** Which registry row published it, so two servers on one file stay attributable. */
|
|
6339
6783
|
serverId: z.string().optional(),
|
|
@@ -6344,7 +6788,7 @@ export const CodeDiagnosticSchema = z.object({
|
|
|
6344
6788
|
* This is the one part of code intelligence that is not request/response:
|
|
6345
6789
|
* `textDocument/publishDiagnostics` arrives whenever the server has recomputed, which is
|
|
6346
6790
|
* whenever it feels like it. So it is a status broadcast, and the payload is the document's
|
|
6347
|
-
* **whole** current set
|
|
6791
|
+
* **whole** current set - never a delta. A missed delta would leave a stale squiggle on a
|
|
6348
6792
|
* line the user already fixed, and an idempotent snapshot cannot drift.
|
|
6349
6793
|
*
|
|
6350
6794
|
* Only documents a client has synced produce these. A server may know about every file in
|
|
@@ -6463,7 +6907,7 @@ export const WorkspaceScriptPayloadSchema = z.object({
|
|
|
6463
6907
|
*/
|
|
6464
6908
|
scriptName: z.string(),
|
|
6465
6909
|
/**
|
|
6466
|
-
* What to show instead of `scriptName`
|
|
6910
|
+
* What to show instead of `scriptName` - the name the project itself uses.
|
|
6467
6911
|
* COMPAT(workspaceScriptDiscovery): added in v0.7.6; absent ⇒ show `scriptName`.
|
|
6468
6912
|
*/
|
|
6469
6913
|
label: z.string().optional(),
|
|
@@ -6742,7 +7186,7 @@ export const WorkspaceUpdateMessageSchema = z.object({
|
|
|
6742
7186
|
});
|
|
6743
7187
|
// A project's own metadata changed (today: the user renamed it). The workspace
|
|
6744
7188
|
// channel can only carry a project's name inside its workspaces' descriptors, so
|
|
6745
|
-
// a project with no active workspaces had no live channel at all
|
|
7189
|
+
// a project with no active workspaces had no live channel at all - its name only
|
|
6746
7190
|
// refreshed on the next full workspace fetch. This is the project-level channel:
|
|
6747
7191
|
// it fires whether or not the project currently has workspaces, and the daemon
|
|
6748
7192
|
// fans it out to every connected session because project metadata is host-global.
|
|
@@ -6823,7 +7267,7 @@ export const ProjectScaffoldResponseSchema = z.object({
|
|
|
6823
7267
|
type: z.literal("project.scaffold.response"),
|
|
6824
7268
|
payload: z.object({
|
|
6825
7269
|
requestId: z.string(),
|
|
6826
|
-
// Registered project on success. Null whenever any step failed
|
|
7270
|
+
// Registered project on success. Null whenever any step failed - the
|
|
6827
7271
|
// daemon does not register a half-built directory.
|
|
6828
7272
|
project: WorkspaceProjectDescriptorPayloadSchema.nullable(),
|
|
6829
7273
|
// Absolute path of the created directory. Non-null even on a late failure
|
|
@@ -7032,7 +7476,7 @@ export const ArchiveWorkspaceResponseMessageSchema = z.object({
|
|
|
7032
7476
|
// the workspace is archived. See WorkspaceArchivePreflightRequestSchema.
|
|
7033
7477
|
export const WorktreeArchiveBranchDetectionSchema = z.object({
|
|
7034
7478
|
// True only for Otto-owned worktrees whose branch we can offer to delete.
|
|
7035
|
-
// False for local checkouts, plain directories, and non-owned worktrees
|
|
7479
|
+
// False for local checkouts, plain directories, and non-owned worktrees - the
|
|
7036
7480
|
// client then skips the branch-cleanup UI entirely.
|
|
7037
7481
|
isOttoWorktree: z.boolean(),
|
|
7038
7482
|
// The local branch checked out in the worktree, or null when detached/unknown.
|
|
@@ -7042,7 +7486,7 @@ export const WorktreeArchiveBranchDetectionSchema = z.object({
|
|
|
7042
7486
|
mergeState: z.enum(["merged", "unmerged", "unknown"]),
|
|
7043
7487
|
// Commits on the branch not contained in the base ref; null when unknown.
|
|
7044
7488
|
unmergedCommitCount: z.number().int().nonnegative().nullable(),
|
|
7045
|
-
// A matching origin/<branch> exists
|
|
7489
|
+
// A matching origin/<branch> exists - deleting the local branch keeps the
|
|
7046
7490
|
// remote copy. Purely informational for the confirmation copy.
|
|
7047
7491
|
hasRemoteBranch: z.boolean(),
|
|
7048
7492
|
// The branch is checked out in another worktree too, so git will refuse to
|
|
@@ -7279,7 +7723,7 @@ export const AgentQueueRemoveResponseMessageSchema = z.object({
|
|
|
7279
7723
|
/**
|
|
7280
7724
|
* The removed message's text, handed back so the composer can put it back
|
|
7281
7725
|
* in the box for editing or re-send it right away. Null when the id was
|
|
7282
|
-
* already gone
|
|
7726
|
+
* already gone - the turn drained it while the tap was in flight.
|
|
7283
7727
|
* Attachments are not echoed: the client that queued the message keeps its
|
|
7284
7728
|
* own local copy keyed by `id` (see the composer's queued-attachment
|
|
7285
7729
|
* sidecar), and a client that never queued it has nothing to restore.
|
|
@@ -7374,7 +7818,7 @@ export const SendAgentMessageResponseMessageSchema = z.object({
|
|
|
7374
7818
|
error: z.string().nullable(),
|
|
7375
7819
|
// Set when the message was parked for the next turn rather than dispatched
|
|
7376
7820
|
// (`delivery: "queue"` against a busy agent). `queuedMessageId` is the
|
|
7377
|
-
// entry's id in `AgentSnapshotPayload.queuedMessages`
|
|
7821
|
+
// entry's id in `AgentSnapshotPayload.queuedMessages` - the key the sender
|
|
7378
7822
|
// uses to find its own entry again. Absent ⇒ dispatched now (or old daemon).
|
|
7379
7823
|
// COMPAT(steerQueue): added in v0.6.8, drop the gate when floor >= v0.6.8.
|
|
7380
7824
|
queued: z.boolean().optional(),
|
|
@@ -7793,7 +8237,7 @@ const CheckoutPrGithubStatusObjectSchema = z.object({
|
|
|
7793
8237
|
isInMergeQueue: z.boolean().optional().default(false),
|
|
7794
8238
|
});
|
|
7795
8239
|
const CheckoutPrGithubStatusSchema = CheckoutPrGithubStatusObjectSchema.optional();
|
|
7796
|
-
// The open facts envelope for forge-specific PR facts. Permanent
|
|
8240
|
+
// The open facts envelope for forge-specific PR facts. Permanent - non-GitHub
|
|
7797
8241
|
// forges deliver their native facts through it. The transitional piece is the
|
|
7798
8242
|
// `github` mirror above, which stays populated for clients predating this
|
|
7799
8243
|
// envelope; see COMPAT(forgeSpecific) in status-projection.ts for the shim.
|
|
@@ -8069,7 +8513,7 @@ export const GitFileHistoryEntrySchema = z.object({
|
|
|
8069
8513
|
authoredAt: z.number(),
|
|
8070
8514
|
committerName: z.string(),
|
|
8071
8515
|
committedAt: z.number(),
|
|
8072
|
-
// The file's name at this commit
|
|
8516
|
+
// The file's name at this commit - differs from the requested path across a
|
|
8073
8517
|
// rename. Diff requests must echo this one back, not the current name.
|
|
8074
8518
|
path: z.string(),
|
|
8075
8519
|
previousPath: z.string().optional(),
|
|
@@ -8100,7 +8544,7 @@ export const CheckoutGitFileCommitDiffResponseSchema = z.object({
|
|
|
8100
8544
|
diff: z.string(),
|
|
8101
8545
|
// Highlighted/parsed form of the same diff, when it parsed cleanly.
|
|
8102
8546
|
structured: z.array(ParsedDiffFileSchema).optional(),
|
|
8103
|
-
// The file's previous revision
|
|
8547
|
+
// The file's previous revision - the diff's left-hand side, and the honest
|
|
8104
8548
|
// label for it. Absent when this revision created the file.
|
|
8105
8549
|
previousSha: z.string().optional(),
|
|
8106
8550
|
previousPath: z.string().optional(),
|
|
@@ -8864,7 +9308,7 @@ export const FileCreateResponseSchema = z.object({
|
|
|
8864
9308
|
});
|
|
8865
9309
|
/**
|
|
8866
9310
|
* Delete outcome. `not_empty` means the target is a directory with children and
|
|
8867
|
-
* the request did not set `recursive`
|
|
9311
|
+
* the request did not set `recursive` - nothing was removed, and the client can
|
|
8868
9312
|
* re-ask with the stronger confirmation.
|
|
8869
9313
|
*/
|
|
8870
9314
|
export const FileDeleteResultSchema = z.discriminatedUnion("status", [
|
|
@@ -8997,7 +9441,7 @@ export const CodeDefinitionLocationSchema = z.object({
|
|
|
8997
9441
|
/**
|
|
8998
9442
|
* Which registry row answered (`typescript`, `csharp`, …). The multi-hit picker
|
|
8999
9443
|
* shows it, so a user looking at two candidates can tell whether a language server
|
|
9000
|
-
* resolved them or the name index guessed
|
|
9444
|
+
* resolved them or the name index guessed - which changes how much to trust the
|
|
9001
9445
|
* list. Absent from old daemons.
|
|
9002
9446
|
*/
|
|
9003
9447
|
serverId: z.string().optional(),
|
|
@@ -9005,7 +9449,7 @@ export const CodeDefinitionLocationSchema = z.object({
|
|
|
9005
9449
|
/**
|
|
9006
9450
|
* Three-valued on purpose. `unavailable` (no server for this language on the host) and
|
|
9007
9451
|
* `indexing` (the server is up but still building its project model) are different
|
|
9008
|
-
* answers to the user, and neither is "not found"
|
|
9452
|
+
* answers to the user, and neither is "not found" - reporting either as an empty
|
|
9009
9453
|
* result is how a working feature reads as broken.
|
|
9010
9454
|
*/
|
|
9011
9455
|
export const CodeDefinitionStatusSchema = z.enum(["ok", "indexing", "unavailable"]);
|
|
@@ -9080,7 +9524,7 @@ export const CodeRenameEditSchema = z.object({
|
|
|
9080
9524
|
newText: z.string(),
|
|
9081
9525
|
/**
|
|
9082
9526
|
* The text this edit expects to replace. Carried so the dry run can show what is being
|
|
9083
|
-
* changed rather than only what it becomes
|
|
9527
|
+
* changed rather than only what it becomes - and, on the daemon side, so the run can tell
|
|
9084
9528
|
* that a file moved under the plan. For a rename this is always one identifier.
|
|
9085
9529
|
*/
|
|
9086
9530
|
oldText: z.string().default(""),
|
|
@@ -9116,7 +9560,7 @@ export const CodeRenamePreviewResponseSchema = z.object({
|
|
|
9116
9560
|
* workspace. Collapsing them into one failure is how "nothing happened" becomes unexplainable.
|
|
9117
9561
|
*/
|
|
9118
9562
|
/**
|
|
9119
|
-
* Whether the run HAPPENED
|
|
9563
|
+
* Whether the run HAPPENED - deliberately not whether everything applied.
|
|
9120
9564
|
*
|
|
9121
9565
|
* A run where two of fourteen edits no longer fit is still a run that took place, and the
|
|
9122
9566
|
* twelve that landed are real. Collapsing that into a failure would hide them, and hiding a
|
|
@@ -9233,7 +9677,7 @@ export const LspServerStopResponseSchema = z.object({
|
|
|
9233
9677
|
export const SolutionFormatSchema = z.enum(["sln", "slnx"]);
|
|
9234
9678
|
/** One solution a workspace contains. Enough to populate the switcher's picker, nothing more. */
|
|
9235
9679
|
export const SolutionRefSchema = z.object({
|
|
9236
|
-
/** Workspace-relative, forward slashes
|
|
9680
|
+
/** Workspace-relative, forward slashes - the identity used by every later request. */
|
|
9237
9681
|
path: z.string(),
|
|
9238
9682
|
/** File name without the extension, which is what a .NET developer calls the solution. */
|
|
9239
9683
|
name: z.string(),
|
|
@@ -9246,7 +9690,7 @@ export const CodeSolutionListResponseSchema = z.object({
|
|
|
9246
9690
|
/**
|
|
9247
9691
|
* Empty means the switcher never appears and the Files tab behaves exactly as it does today.
|
|
9248
9692
|
* That is also what a disabled feature, a host with no .NET SDK, and a workspace with no
|
|
9249
|
-
* solution all return
|
|
9693
|
+
* solution all return - the client has one silent case to handle, not four.
|
|
9250
9694
|
*/
|
|
9251
9695
|
solutions: z.array(SolutionRefSchema),
|
|
9252
9696
|
error: z.string().nullable(),
|
|
@@ -9276,8 +9720,8 @@ export const SolutionTreeProjectSchema = z.object({
|
|
|
9276
9720
|
*/
|
|
9277
9721
|
path: z.string(),
|
|
9278
9722
|
/**
|
|
9279
|
-
* A project the solution names outside the workspace root. Shown and opened like any other
|
|
9280
|
-
* the solution file is the authority naming it, so this is not free browsing
|
|
9723
|
+
* A project the solution names outside the workspace root. Shown and opened like any other -
|
|
9724
|
+
* the solution file is the authority naming it, so this is not free browsing - but editing one
|
|
9281
9725
|
* warns, and it is absent from every git surface. See docs/solution-view.md.
|
|
9282
9726
|
*/
|
|
9283
9727
|
outsideWorkspace: z.boolean(),
|
|
@@ -9295,7 +9739,7 @@ export const CodeSolutionGetTreeResponseSchema = z.object({
|
|
|
9295
9739
|
format: SolutionFormatSchema.default("sln"),
|
|
9296
9740
|
folders: z.array(SolutionTreeFolderSchema),
|
|
9297
9741
|
projects: z.array(SolutionTreeProjectSchema),
|
|
9298
|
-
/** Solution configurations and platforms
|
|
9742
|
+
/** Solution configurations and platforms - first-class .NET concepts no CLI surfaces. */
|
|
9299
9743
|
buildTypes: z.array(z.string()),
|
|
9300
9744
|
platforms: z.array(z.string()),
|
|
9301
9745
|
error: z.string().nullable(),
|
|
@@ -9332,7 +9776,7 @@ export const SolutionProjectNodeSchema = z.discriminatedUnion("kind", [
|
|
|
9332
9776
|
name: z.string(),
|
|
9333
9777
|
path: z.string(),
|
|
9334
9778
|
outsideWorkspace: z.boolean(),
|
|
9335
|
-
/** `Compile`, `Content`, `EmbeddedResource`, …
|
|
9779
|
+
/** `Compile`, `Content`, `EmbeddedResource`, … - MSBuild's own item type. */
|
|
9336
9780
|
itemType: z.string(),
|
|
9337
9781
|
isImplicit: z.boolean(),
|
|
9338
9782
|
}),
|
|
@@ -9388,7 +9832,7 @@ export const FileSearchResultEventSchema = z.object({
|
|
|
9388
9832
|
cwd: z.string(),
|
|
9389
9833
|
searchId: z.string(),
|
|
9390
9834
|
path: z.string(),
|
|
9391
|
-
/** File content hash at match time
|
|
9835
|
+
/** File content hash at match time - the replace precondition. */
|
|
9392
9836
|
hash: z.string(),
|
|
9393
9837
|
matches: z.array(FileSearchMatchSchema),
|
|
9394
9838
|
}),
|
|
@@ -9894,6 +10338,9 @@ export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
9894
10338
|
GetDaemonConfigResponseMessageSchema,
|
|
9895
10339
|
SetDaemonConfigResponseMessageSchema,
|
|
9896
10340
|
ConnectorsListToolsResponseSchema,
|
|
10341
|
+
ConnectorsOauthAuthorizeResponseSchema,
|
|
10342
|
+
ConnectorsOauthDisconnectResponseSchema,
|
|
10343
|
+
ConnectorsOauthStatusMessageSchema,
|
|
9897
10344
|
SpeechSettingsGetOptionsResponseSchema,
|
|
9898
10345
|
SpeechTtsPreviewResponseSchema,
|
|
9899
10346
|
SpeechTtsSpeakResponseSchema,
|
|
@@ -9963,6 +10410,14 @@ export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
9963
10410
|
BrainHfSearchResponseSchema,
|
|
9964
10411
|
BrainHfQuantsResponseSchema,
|
|
9965
10412
|
BrainModelsAddResponseSchema,
|
|
10413
|
+
BrainModelsInventoryResponseSchema,
|
|
10414
|
+
BrainModelProfileGetResponseSchema,
|
|
10415
|
+
BrainModelProfileSetResponseSchema,
|
|
10416
|
+
BrainModelBudgetGetResponseSchema,
|
|
10417
|
+
BrainModelLoadResponseSchema,
|
|
10418
|
+
BrainModelUnloadResponseSchema,
|
|
10419
|
+
BrainModelDeleteResponseSchema,
|
|
10420
|
+
BrainLogsTailResponseSchema,
|
|
9966
10421
|
AgentArchivedMessageSchema,
|
|
9967
10422
|
CloseItemsResponseSchema,
|
|
9968
10423
|
CheckoutStatusResponseSchema,
|