@otto-code/protocol 0.6.6 → 0.7.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-labels.d.ts +26 -0
- package/dist/agent-labels.js +82 -0
- package/dist/agent-types.d.ts +55 -0
- package/dist/agent-types.js +14 -0
- package/dist/browser-automation/capabilities.d.ts +1 -1
- package/dist/browser-automation/rpc-schemas.d.ts +1 -1
- package/dist/generated/validation/ws-outbound.aot.js +39721 -31424
- package/dist/git-hosting.d.ts +2 -0
- package/dist/git-hosting.js +6 -0
- package/dist/messages.d.ts +10543 -1185
- package/dist/messages.js +2013 -8
- package/dist/model-tiers.js +2 -0
- package/dist/orchestration.d.ts +271 -1
- package/dist/orchestration.js +434 -0
- package/dist/provider-config.d.ts +3 -1
- package/dist/provider-config.js +3 -0
- package/dist/validation/ws-outbound-schema-metadata.d.ts +1852 -216
- package/dist/widgets/bridge.d.ts +59 -0
- package/dist/widgets/bridge.js +87 -0
- package/dist/widgets/document.d.ts +18 -0
- package/dist/widgets/document.js +261 -0
- package/dist/widgets/icons.d.ts +20 -0
- package/dist/widgets/icons.js +90 -0
- package/dist/widgets/theme.d.ts +37 -0
- package/dist/widgets/theme.js +149 -0
- package/dist/widgets/types.d.ts +78 -0
- package/dist/widgets/types.js +88 -0
- package/package.json +1 -1
package/dist/messages.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { TerminalActivitySchema } from "./terminal-activity.js";
|
|
3
|
-
import { RunSchema } from "./orchestration.js";
|
|
3
|
+
import { OrchestrationGraphSchema, PromptTemplateSchema, RunSchema } from "./orchestration.js";
|
|
4
4
|
import { ArtifactMetadataSchema } from "./artifacts/types.js";
|
|
5
5
|
import { ArtifactListRequestSchema, ArtifactCreateRequestSchema, ArtifactUpdateRequestSchema, ArtifactRegenerateRequestSchema, ArtifactCancelRequestSchema, ArtifactDeleteRequestSchema, ArtifactStarRequestSchema, ArtifactGetContentRequestSchema, ArtifactListResponseSchema, ArtifactCreateResponseSchema, ArtifactUpdateResponseSchema, ArtifactRegenerateResponseSchema, ArtifactCancelResponseSchema, ArtifactDeleteResponseSchema, ArtifactStarResponseSchema, ArtifactGetContentResponseSchema, ArtifactCreatedNotificationSchema, ArtifactUpdatedNotificationSchema, ArtifactDeletedNotificationSchema, } from "./artifacts/rpc-schemas.js";
|
|
6
6
|
import { CLIENT_CAPS } from "./client-capabilities.js";
|
|
@@ -84,6 +84,53 @@ const MutableBrowserToolsConfigSchema = z
|
|
|
84
84
|
enabled: z.boolean().default(false),
|
|
85
85
|
})
|
|
86
86
|
.passthrough();
|
|
87
|
+
/**
|
|
88
|
+
* Language-server code intelligence, host-scoped because the servers are processes
|
|
89
|
+
* on the daemon's machine — they follow the host, not the client.
|
|
90
|
+
*
|
|
91
|
+
* `enabled` defaults **on** and that is safe: nothing spawns until a
|
|
92
|
+
* code-intelligence action needs a language in a workspace, so an unused language
|
|
93
|
+
* costs nothing. What the switch guarantees is that off means off — no server
|
|
94
|
+
* spawns for any workspace, and the ctags index still serves the outline and the
|
|
95
|
+
* fuzzy finder.
|
|
96
|
+
*
|
|
97
|
+
* `languages` keys are registry row ids (`typescript`, `python`, `csharp`, …). An
|
|
98
|
+
* absent key means "use the row's own default", so a new row ships with its
|
|
99
|
+
* intended default rather than reading as disabled.
|
|
100
|
+
*/
|
|
101
|
+
const MutableLspConfigSchema = z
|
|
102
|
+
.object({
|
|
103
|
+
enabled: z.boolean().default(true),
|
|
104
|
+
languages: z.record(z.string(), z.boolean()).default({}),
|
|
105
|
+
/** Hard LRU cap on simultaneously running servers, across all workspaces. */
|
|
106
|
+
maxRunningServers: z.number().int().positive().default(6),
|
|
107
|
+
idleMinutes: z.number().int().positive().default(10),
|
|
108
|
+
/** Shorter allowance for workspaces the user is not currently looking at. */
|
|
109
|
+
backgroundIdleMinutes: z.number().int().positive().default(2),
|
|
110
|
+
})
|
|
111
|
+
.passthrough();
|
|
112
|
+
/**
|
|
113
|
+
* "Microsoft .NET Solution Management" — the Solution view's own switch.
|
|
114
|
+
*
|
|
115
|
+
* **A sibling of `lsp`, not a member of it.** Turning C# code intelligence off does not turn
|
|
116
|
+
* this off and vice versa: they are independent capabilities that happen to share a language,
|
|
117
|
+
* and nesting this inside the LSP settings object would imply exactly the coupling that
|
|
118
|
+
* decision rejects. (It would also be wrong on the facts — LSP has no project-structure
|
|
119
|
+
* request, so nothing here rides on a language server.)
|
|
120
|
+
*
|
|
121
|
+
* Defaults **off**: the feature spawns a process and evaluates MSBuild. Disabled is genuinely
|
|
122
|
+
* off, not merely hidden — no discovery walk, no `.sln` read, no `.csproj` parse, no sidecar,
|
|
123
|
+
* no cache, no watcher, and no view switcher. The daemon reads this before scheduling any work,
|
|
124
|
+
* so a disabled feature costs exactly one boolean check.
|
|
125
|
+
*/
|
|
126
|
+
const MutableDotnetSolutionConfigSchema = z
|
|
127
|
+
.object({
|
|
128
|
+
enabled: z.boolean().default(false),
|
|
129
|
+
/** Hard cap on simultaneously running sidecars, across all workspaces. */
|
|
130
|
+
maxRunningProbes: z.number().int().positive().default(2),
|
|
131
|
+
idleMinutes: z.number().int().positive().default(10),
|
|
132
|
+
})
|
|
133
|
+
.passthrough();
|
|
87
134
|
// Speech engine ids and model ids stay plain strings on the wire so adding an
|
|
88
135
|
// engine or model never breaks an older peer; the daemon validates values
|
|
89
136
|
// against its own catalog when applying a patch.
|
|
@@ -244,6 +291,13 @@ export const AgentPersonalitySchema = z
|
|
|
244
291
|
spinner: AgentPersonalitySpinnerSchema.optional(),
|
|
245
292
|
voice: AgentPersonalityVoiceSchema.optional(),
|
|
246
293
|
voiceCues: AgentPersonalityVoiceCuesSchema.optional(),
|
|
294
|
+
// Whether this personality accrues lessons across sessions (personality
|
|
295
|
+
// memory). ABSENT MEANS ON: a personality with no lessons injects nothing
|
|
296
|
+
// and costs nothing, so an off-by-default switch would only mean the feature
|
|
297
|
+
// never starts working for anyone who did not go looking for it. The switch
|
|
298
|
+
// exists to stop a personality accruing, not to start it.
|
|
299
|
+
// See docs/agent-personalities.md § Memory.
|
|
300
|
+
memoryEnabled: z.boolean().optional(),
|
|
247
301
|
})
|
|
248
302
|
.passthrough();
|
|
249
303
|
const MutableAgentPersonalitiesConfigSchema = z
|
|
@@ -372,6 +426,12 @@ export const MutableDaemonConfigSchema = z
|
|
|
372
426
|
preferWriterPersonalities: false,
|
|
373
427
|
}),
|
|
374
428
|
autoArchiveAfterMerge: z.boolean().default(false),
|
|
429
|
+
// Drop the "Merge into <base>" action from the client's source-control menu
|
|
430
|
+
// (and stop promoting it to the primary CTA) for a pull-request-only
|
|
431
|
+
// workflow. Host-level so the whole team's clients share one policy.
|
|
432
|
+
// Defaults false so a new client parsing an old daemon's config keeps the
|
|
433
|
+
// action visible. Gated by server_info features.hideMergeIntoBaseSetting.
|
|
434
|
+
hideMergeIntoBaseAction: z.boolean().default(false),
|
|
375
435
|
enableTerminalAgentHooks: z.boolean().default(false),
|
|
376
436
|
appendSystemPrompt: z.string().default(""),
|
|
377
437
|
terminalProfiles: z.array(TerminalProfileSchema).optional(),
|
|
@@ -396,6 +456,24 @@ export const MutableDaemonConfigSchema = z
|
|
|
396
456
|
// empty so a new client parsing an old daemon's config still sees a
|
|
397
457
|
// well-formed array.
|
|
398
458
|
savedProviderEndpoints: z.array(SavedProviderEndpointSchema).default([]),
|
|
459
|
+
// Language-server code intelligence. Gated by server_info features.lsp; the
|
|
460
|
+
// default section is well-formed so a new client parsing an old daemon's config
|
|
461
|
+
// still renders the screen.
|
|
462
|
+
lsp: MutableLspConfigSchema.default({
|
|
463
|
+
enabled: true,
|
|
464
|
+
languages: {},
|
|
465
|
+
maxRunningServers: 6,
|
|
466
|
+
idleMinutes: 10,
|
|
467
|
+
backgroundIdleMinutes: 2,
|
|
468
|
+
}),
|
|
469
|
+
// The Solution view's switch. Gated by server_info features.solutionView; the default
|
|
470
|
+
// section is well-formed and OFF, so a new client parsing an old daemon's config renders
|
|
471
|
+
// the row without ever implying the feature is running.
|
|
472
|
+
dotnetSolutionManagement: MutableDotnetSolutionConfigSchema.default({
|
|
473
|
+
enabled: false,
|
|
474
|
+
maxRunningProbes: 2,
|
|
475
|
+
idleMinutes: 10,
|
|
476
|
+
}),
|
|
399
477
|
})
|
|
400
478
|
.passthrough();
|
|
401
479
|
export const MutableDaemonConfigPatchSchema = z
|
|
@@ -412,6 +490,8 @@ export const MutableDaemonConfigPatchSchema = z
|
|
|
412
490
|
.optional(),
|
|
413
491
|
metadataGeneration: MutableMetadataGenerationConfigSchema.partial().optional(),
|
|
414
492
|
autoArchiveAfterMerge: z.boolean().optional(),
|
|
493
|
+
// Gated by server_info features.hideMergeIntoBaseSetting.
|
|
494
|
+
hideMergeIntoBaseAction: z.boolean().optional(),
|
|
415
495
|
enableTerminalAgentHooks: z.boolean().optional(),
|
|
416
496
|
appendSystemPrompt: z.string().optional(),
|
|
417
497
|
terminalProfiles: z.array(TerminalProfileSchema).optional(),
|
|
@@ -434,6 +514,11 @@ export const MutableDaemonConfigPatchSchema = z
|
|
|
434
514
|
// Gated by server_info features.savedProviderEndpoints. Replaces the full
|
|
435
515
|
// array (read-modify-write), so forgetting an endpoint drops it from disk.
|
|
436
516
|
savedProviderEndpoints: z.array(SavedProviderEndpointSchema).optional(),
|
|
517
|
+
// Gated by server_info features.lsp; patches deep-merge, so a `languages`
|
|
518
|
+
// patch replaces only the keys it names.
|
|
519
|
+
lsp: MutableLspConfigSchema.partial().optional(),
|
|
520
|
+
// Gated by server_info features.solutionView; patches deep-merge.
|
|
521
|
+
dotnetSolutionManagement: MutableDotnetSolutionConfigSchema.partial().optional(),
|
|
437
522
|
})
|
|
438
523
|
.partial()
|
|
439
524
|
.passthrough();
|
|
@@ -555,6 +640,14 @@ const ContextCompositionSchema = z.object({
|
|
|
555
640
|
reasoning: z.number().optional(),
|
|
556
641
|
subagentResults: z.number().optional(),
|
|
557
642
|
});
|
|
643
|
+
// Declared above AgentUsageSchema on purpose: a schema referenced before its
|
|
644
|
+
// declaration is a build-time ReferenceError in the zod-aot output.
|
|
645
|
+
const AgentContextCategorySchema = z.object({
|
|
646
|
+
/** Provider-supplied display label, not translated and not an enum. */
|
|
647
|
+
name: z.string(),
|
|
648
|
+
tokens: z.number(),
|
|
649
|
+
isDeferred: z.boolean().optional(),
|
|
650
|
+
});
|
|
558
651
|
const AgentUsageSchema = z.object({
|
|
559
652
|
inputTokens: z.number().optional(),
|
|
560
653
|
cachedInputTokens: z.number().optional(),
|
|
@@ -567,6 +660,10 @@ const AgentUsageSchema = z.object({
|
|
|
567
660
|
// Provider-graded context breakdown for the visualizer ring/bar; absent ⇒
|
|
568
661
|
// occupancy only (pre-composition behavior). See ContextComposition.
|
|
569
662
|
contextComposition: ContextCompositionSchema.optional(),
|
|
663
|
+
// The provider's own labelled split — same accounting as
|
|
664
|
+
// `agent.context.get_usage`, pushed on the snapshot. Preferred over
|
|
665
|
+
// contextComposition; absent ⇒ fall back to the estimate, then to occupancy.
|
|
666
|
+
contextCategories: z.array(AgentContextCategorySchema).optional(),
|
|
570
667
|
});
|
|
571
668
|
const AgentSessionConfigSchema = z.object({
|
|
572
669
|
provider: AgentProviderSchema,
|
|
@@ -911,6 +1008,52 @@ const AgentRuntimeInfoSchema = z.object({
|
|
|
911
1008
|
modeId: z.string().nullable().optional(),
|
|
912
1009
|
extra: z.record(z.string(), z.unknown()).optional(),
|
|
913
1010
|
});
|
|
1011
|
+
/**
|
|
1012
|
+
* One message parked for delivery as an agent's NEXT turn (`delivery: "queue"`).
|
|
1013
|
+
* The daemon owns the queue; this is the read-only projection the Queue track
|
|
1014
|
+
* renders. Declared above AgentSnapshotPayloadSchema — zod-aot emits schemas in
|
|
1015
|
+
* source order, so a forward reference is a build-time ReferenceError.
|
|
1016
|
+
*/
|
|
1017
|
+
export const QueuedAgentMessagePayloadSchema = z.object({
|
|
1018
|
+
id: z.string(),
|
|
1019
|
+
/** Leading text of the message, truncated for display. */
|
|
1020
|
+
preview: z.string(),
|
|
1021
|
+
enqueuedAt: z.string(),
|
|
1022
|
+
attachmentCount: z.number().int().nonnegative().optional(),
|
|
1023
|
+
});
|
|
1024
|
+
/**
|
|
1025
|
+
* An agent's LIFETIME SPEND, kept as the real token split plus the provider's
|
|
1026
|
+
* own cost — the raw material for "what did this chat cost".
|
|
1027
|
+
*
|
|
1028
|
+
* Deliberately distinct from context-window occupancy (`agent.context.get_usage`
|
|
1029
|
+
* and `lastUsage.contextWindow*`), which answers "how full am I" and shares no
|
|
1030
|
+
* units with this. Conflating the two is why the numbers used to feel wrong; the
|
|
1031
|
+
* UI must never mix them. See docs/glossary.md.
|
|
1032
|
+
*
|
|
1033
|
+
* `costUsd` is only ever a provider's OWN reported cost, already de-inflated so
|
|
1034
|
+
* a parent never carries what its sub-agents reported. It is NEVER derived from
|
|
1035
|
+
* a $/M rate table — a rate keyed off a model id misprices a gateway serving
|
|
1036
|
+
* that model at its own prices (docs/subagent-accounting.md, pricing invariant).
|
|
1037
|
+
* `costCoverage` says how far it can be trusted, so a surface can show a floor
|
|
1038
|
+
* or an honest blank rather than a confident wrong figure.
|
|
1039
|
+
*
|
|
1040
|
+
* Declared above AgentSnapshotPayloadSchema — zod-aot emits schemas in source
|
|
1041
|
+
* order, so a forward reference is a build-time ReferenceError.
|
|
1042
|
+
*/
|
|
1043
|
+
export const AgentCumulativeUsageSchema = z.object({
|
|
1044
|
+
inputTokens: z.number().optional(),
|
|
1045
|
+
cachedInputTokens: z.number().optional(),
|
|
1046
|
+
cacheCreationInputTokens: z.number().optional(),
|
|
1047
|
+
outputTokens: z.number().optional(),
|
|
1048
|
+
/** Provider-reported cost booked so far. Absent ⇒ nothing was priceable. */
|
|
1049
|
+
costUsd: z.number().optional(),
|
|
1050
|
+
/**
|
|
1051
|
+
* `complete` — every token-bearing turn was priced; `costUsd` is the total.
|
|
1052
|
+
* `partial` — some turns were unpriced; `costUsd` is a FLOOR, present it as
|
|
1053
|
+
* one. `none` — nothing priceable; show tokens and a blank, never an estimate.
|
|
1054
|
+
*/
|
|
1055
|
+
costCoverage: z.enum(["complete", "partial", "none"]).optional(),
|
|
1056
|
+
});
|
|
914
1057
|
export const AgentSnapshotPayloadSchema = z.object({
|
|
915
1058
|
id: z.string(),
|
|
916
1059
|
provider: AgentProviderSchema,
|
|
@@ -938,6 +1081,30 @@ export const AgentSnapshotPayloadSchema = z.object({
|
|
|
938
1081
|
// additive; absent ⇒ no readout. Old clients ignore it.
|
|
939
1082
|
// See docs/agent-lifecycle.md (Item 3).
|
|
940
1083
|
cumulativeTokens: z.number().optional(),
|
|
1084
|
+
// The same lifetime spend as `cumulativeTokens`, but as the REAL split plus
|
|
1085
|
+
// the provider's own cost, so a chat total can be priced honestly instead of
|
|
1086
|
+
// flattened to one scalar and multiplied by a guessed rate. Its token leaves
|
|
1087
|
+
// sum to `cumulativeTokens`; a client that ignores this loses only the split
|
|
1088
|
+
// and the cost. Absent ⇒ the daemon predates the field or reported nothing.
|
|
1089
|
+
// COMPAT(cumulativeUsage): added in v0.7.0; gated on
|
|
1090
|
+
// server_info.features.cumulativeUsage, drop the gate when floor >= v0.7.0.
|
|
1091
|
+
// See docs/subagent-accounting.md (Chat totals).
|
|
1092
|
+
cumulativeUsage: AgentCumulativeUsageSchema.optional(),
|
|
1093
|
+
// Liveness signals for the sub-agents track: how much work this agent has done
|
|
1094
|
+
// (`toolUseCount`, cumulative and monotonic) and what it is doing right now
|
|
1095
|
+
// (`currentTool`, the latest tool name, cleared once the agent is terminal —
|
|
1096
|
+
// a finished agent isn't "running Bash"). Both are purely additive optional
|
|
1097
|
+
// leaves: a provider that can't report them leaves them absent and the row
|
|
1098
|
+
// omits the readout rather than showing a wrong value.
|
|
1099
|
+
// COMPAT(subagentLiveness): added in v0.6.7; old clients ignore both.
|
|
1100
|
+
// See docs/chat-lifecycle.md (the subagents track).
|
|
1101
|
+
toolUseCount: z.number().optional(),
|
|
1102
|
+
currentTool: z.string().optional(),
|
|
1103
|
+
// Messages parked for delivery as this agent's NEXT turn (delivery: "queue").
|
|
1104
|
+
// Daemon-owned and ephemeral — the composer's Queue track renders straight
|
|
1105
|
+
// from this. Absent/empty ⇒ nothing queued; old clients ignore it.
|
|
1106
|
+
// COMPAT(steerQueue): added in v0.6.8, drop the gate when floor >= v0.6.8.
|
|
1107
|
+
queuedMessages: z.array(QueuedAgentMessagePayloadSchema).optional(),
|
|
941
1108
|
lastError: z.string().optional(),
|
|
942
1109
|
title: z.string().nullable(),
|
|
943
1110
|
labels: z.record(z.string(), z.string()).default({}),
|
|
@@ -1038,6 +1205,45 @@ export const CloseItemsRequestMessageSchema = z.object({
|
|
|
1038
1205
|
terminalIds: z.array(z.string()).default([]),
|
|
1039
1206
|
requestId: z.string(),
|
|
1040
1207
|
});
|
|
1208
|
+
// ── History management ──────────────────────────────────────────────────────
|
|
1209
|
+
// Bulk counterpart to the existing flat `delete_agent_request`: hard-delete
|
|
1210
|
+
// every archived chat record at or past a cutoff in one server-side pass. It has
|
|
1211
|
+
// to be server-side because the history list is cursor-paginated across hosts,
|
|
1212
|
+
// so the client never holds the whole archived set.
|
|
1213
|
+
//
|
|
1214
|
+
// Deleting a chat removes OTTO's record only. The provider's own on-disk
|
|
1215
|
+
// transcript (Claude's `~/.claude/projects/**/<sessionId>.jsonl`, Codex threads,
|
|
1216
|
+
// OpenCode sessions) is deliberately left in place: Otto never created it,
|
|
1217
|
+
// another tool still reads it, and silently deleting another tool's state is not
|
|
1218
|
+
// ours to do. There is intentionally **no** opt-in flag for provider data on the
|
|
1219
|
+
// wire — the UI discloses what stays behind instead. See docs/chat-lifecycle.md.
|
|
1220
|
+
// Gated by server_info.features.historyDelete.
|
|
1221
|
+
export const HistoryAgentsClearArchivedRequestSchema = z.object({
|
|
1222
|
+
type: z.literal("history.agents.clear_archived.request"),
|
|
1223
|
+
// 0 = every archived chat. N = only chats archived at least N days ago.
|
|
1224
|
+
olderThanDays: z.number().int().min(0).default(0),
|
|
1225
|
+
// Safe by default: a request that omits the flag previews instead of deleting.
|
|
1226
|
+
// The client always sends it explicitly.
|
|
1227
|
+
dryRun: z.boolean().default(true),
|
|
1228
|
+
requestId: z.string(),
|
|
1229
|
+
});
|
|
1230
|
+
export const HistoryAgentsClearArchivedResponseSchema = z.object({
|
|
1231
|
+
type: z.literal("history.agents.clear_archived.response"),
|
|
1232
|
+
payload: z.object({
|
|
1233
|
+
// How many archived records the cutoff selected — the number the confirm
|
|
1234
|
+
// dialog quotes back after a dry run.
|
|
1235
|
+
matched: z.number().int().nonnegative(),
|
|
1236
|
+
deleted: z.number().int().nonnegative(),
|
|
1237
|
+
failed: z.number().int().nonnegative(),
|
|
1238
|
+
// Ids actually deleted, so the client drops exactly those rows from its
|
|
1239
|
+
// caches. Empty on a dry run. Unlike close_items_response, a destructive
|
|
1240
|
+
// batch reports per-item outcome rather than silently omitting failures.
|
|
1241
|
+
agentIds: z.array(z.string()),
|
|
1242
|
+
dryRun: z.boolean(),
|
|
1243
|
+
error: z.string().nullable(),
|
|
1244
|
+
requestId: z.string(),
|
|
1245
|
+
}),
|
|
1246
|
+
});
|
|
1041
1247
|
export const UpdateAgentRequestMessageSchema = z.object({
|
|
1042
1248
|
type: z.literal("update_agent_request"),
|
|
1043
1249
|
agentId: z.string(),
|
|
@@ -1318,6 +1524,47 @@ export const SendAgentMessageRequestSchema = z.object({
|
|
|
1318
1524
|
messageId: z.string().optional(), // Client-provided ID for deduplication
|
|
1319
1525
|
images: z.array(ImageAttachmentSchema).optional(),
|
|
1320
1526
|
attachments: AgentAttachmentsSchema,
|
|
1527
|
+
// How to reach a BUSY agent. "interrupt" (default, and what every older
|
|
1528
|
+
// client means by omitting this) cancels the in-flight turn and runs this
|
|
1529
|
+
// instead; "queue" lets the turn finish and runs this as the next one.
|
|
1530
|
+
// Against an idle agent both run immediately.
|
|
1531
|
+
// COMPAT(steerQueue): added in v0.6.8, drop the gate when floor >= v0.6.8.
|
|
1532
|
+
delivery: z.enum(["interrupt", "queue"]).optional(),
|
|
1533
|
+
});
|
|
1534
|
+
/** Pull one message back out of an agent's queue (Queue-track edit / send now). */
|
|
1535
|
+
export const AgentQueueRemoveRequestMessageSchema = z.object({
|
|
1536
|
+
type: z.literal("agent.queue.remove.request"),
|
|
1537
|
+
requestId: z.string(),
|
|
1538
|
+
/** Accepts full ID, unique prefix, or exact full title (server resolves). */
|
|
1539
|
+
agentId: z.string(),
|
|
1540
|
+
/** The queued message's `id` from `AgentSnapshotPayload.queuedMessages`. */
|
|
1541
|
+
messageId: z.string(),
|
|
1542
|
+
});
|
|
1543
|
+
/**
|
|
1544
|
+
* Move one queued message to a different position in an agent's queue.
|
|
1545
|
+
*
|
|
1546
|
+
* Order is what the queue means, so this is the edit that changes the next
|
|
1547
|
+
* turn's content without changing the queue's membership. The daemon resolves
|
|
1548
|
+
* `messageId` fresh and clamps `toIndex`, so a client acting on a snapshot that
|
|
1549
|
+
* is one drain stale reorders what is actually there or reports `moved: false`.
|
|
1550
|
+
* COMPAT(steerQueueReorder): added in v0.6.9, drop the gate when floor >= v0.6.9.
|
|
1551
|
+
*/
|
|
1552
|
+
export const AgentQueueReorderRequestMessageSchema = z.object({
|
|
1553
|
+
type: z.literal("agent.queue.reorder.request"),
|
|
1554
|
+
requestId: z.string(),
|
|
1555
|
+
/** Accepts full ID, unique prefix, or exact full title (server resolves). */
|
|
1556
|
+
agentId: z.string(),
|
|
1557
|
+
/** The queued message's `id` from `AgentSnapshotPayload.queuedMessages`. */
|
|
1558
|
+
messageId: z.string(),
|
|
1559
|
+
/** Zero-based destination, clamped to the queue's current length. */
|
|
1560
|
+
toIndex: z.number().int().nonnegative(),
|
|
1561
|
+
});
|
|
1562
|
+
/** Drop every message queued behind an agent's current turn. */
|
|
1563
|
+
export const AgentQueueClearRequestMessageSchema = z.object({
|
|
1564
|
+
type: z.literal("agent.queue.clear.request"),
|
|
1565
|
+
requestId: z.string(),
|
|
1566
|
+
/** Accepts full ID, unique prefix, or exact full title (server resolves). */
|
|
1567
|
+
agentId: z.string(),
|
|
1321
1568
|
});
|
|
1322
1569
|
export const WaitForFinishRequestSchema = z.object({
|
|
1323
1570
|
type: z.literal("wait_for_finish_request"),
|
|
@@ -1369,6 +1616,35 @@ export const SpeechTtsPreviewRequestSchema = z.object({
|
|
|
1369
1616
|
.passthrough()
|
|
1370
1617
|
.optional(),
|
|
1371
1618
|
});
|
|
1619
|
+
// Read a full assistant message aloud on demand (the per-message playback
|
|
1620
|
+
// button). Unlike the preview RPC — which truncates to a short sample and
|
|
1621
|
+
// returns one buffered clip — this synthesizes the ENTIRE text and streams it
|
|
1622
|
+
// back as `audio_output` chunks (isVoiceMode: false), one group per sentence, so
|
|
1623
|
+
// playback starts after the first sentence instead of the whole message.
|
|
1624
|
+
// `voice` (optional) is the speaking agent's personality voice, resolved on the
|
|
1625
|
+
// client from the live personality (same soft-binding semantics as the preview
|
|
1626
|
+
// button); absent uses the host default. The correlated response lands once
|
|
1627
|
+
// playback finishes, is canceled, or errors.
|
|
1628
|
+
export const SpeechTtsSpeakRequestSchema = z.object({
|
|
1629
|
+
type: z.literal("speech.tts.speak.request"),
|
|
1630
|
+
requestId: z.string(),
|
|
1631
|
+
text: z.string(),
|
|
1632
|
+
voice: z
|
|
1633
|
+
.object({
|
|
1634
|
+
provider: z.string().optional(),
|
|
1635
|
+
model: z.string().optional(),
|
|
1636
|
+
name: z.string(),
|
|
1637
|
+
})
|
|
1638
|
+
.passthrough()
|
|
1639
|
+
.optional(),
|
|
1640
|
+
});
|
|
1641
|
+
// Stop the session's in-flight message playback (the button's stop press).
|
|
1642
|
+
// Aborts synthesis on the host; the pending speak response then resolves as
|
|
1643
|
+
// canceled and the client flushes its own audio queue.
|
|
1644
|
+
export const SpeechTtsSpeakCancelRequestSchema = z.object({
|
|
1645
|
+
type: z.literal("speech.tts.speak.cancel.request"),
|
|
1646
|
+
requestId: z.string(),
|
|
1647
|
+
});
|
|
1372
1648
|
// COMPAT(visualizerVoiceCues): added in v0.6.3; gate lives in
|
|
1373
1649
|
// features.visualizerVoiceCues. Author short spoken "cue" lines for a
|
|
1374
1650
|
// personality — a handful of variations each for three Visualizer moments
|
|
@@ -1889,7 +2165,7 @@ export const SuggestedTasksChangedSchema = z.object({
|
|
|
1889
2165
|
}),
|
|
1890
2166
|
});
|
|
1891
2167
|
// Context Management — the daemon's accounting of everything a provider sends
|
|
1892
|
-
// before the user types (see
|
|
2168
|
+
// before the user types (see docs/context-management.md).
|
|
1893
2169
|
//
|
|
1894
2170
|
// Two distinctions carry the whole feature and must not be collapsed on the
|
|
1895
2171
|
// wire: an `import` edge is inlined into the request while a `reference` edge
|
|
@@ -1940,8 +2216,8 @@ export const ContextFindingSchema = z.object({
|
|
|
1940
2216
|
relatedNodeIds: z.array(z.string()).optional(),
|
|
1941
2217
|
// The node this finding is about. Redundant while the finding sits on its
|
|
1942
2218
|
// node, load-bearing once the report flattens them all into one list — that
|
|
1943
|
-
// list is the "
|
|
1944
|
-
//
|
|
2219
|
+
// list is the "Issues" tab, and without this a row cannot say where it came
|
|
2220
|
+
// from or take you there.
|
|
1945
2221
|
nodeId: z.string().optional(),
|
|
1946
2222
|
// 1-based line of `range.start` in that node's file, so the fix list can jump
|
|
1947
2223
|
// the editor without the client re-reading bytes to count newlines.
|
|
@@ -1949,6 +2225,16 @@ export const ContextFindingSchema = z.object({
|
|
|
1949
2225
|
// Last line of the range, so the client can select the whole offending span
|
|
1950
2226
|
// rather than dropping a cursor at the top of it.
|
|
1951
2227
|
lineEnd: z.number().optional(),
|
|
2228
|
+
// True for kinds a mechanical delete can resolve on its own (dead links, a
|
|
2229
|
+
// duplicate block) — false/absent for kinds that need judgment (which side
|
|
2230
|
+
// of an import cycle to cut, how to split an oversized entry). Computed
|
|
2231
|
+
// server-side, once, in `locateFinding` — the only place that knows the kind
|
|
2232
|
+
// vocabulary, so the fix-all button never has to guess.
|
|
2233
|
+
fixable: z.boolean().optional(),
|
|
2234
|
+
// The exact text at `range` when the file was scanned. `context.findings.fix`
|
|
2235
|
+
// verifies this still matches before deleting, the same staleness guard
|
|
2236
|
+
// `context.edge.convert` uses for `rawTarget`.
|
|
2237
|
+
snippet: z.string().optional(),
|
|
1952
2238
|
});
|
|
1953
2239
|
export const ContextNodeSchema = z.object({
|
|
1954
2240
|
id: z.string(),
|
|
@@ -1999,6 +2285,16 @@ export const ContextReportSchema = z.object({
|
|
|
1999
2285
|
workingRoom: z.number(),
|
|
2000
2286
|
aggregateSeverity: ContextSeveritySchema,
|
|
2001
2287
|
findings: z.array(ContextFindingSchema),
|
|
2288
|
+
// Which personality this report was evaluated FOR. Context became
|
|
2289
|
+
// personality-specific once personalities accrue memory, so a report is only
|
|
2290
|
+
// interpretable alongside the identity it was measured against.
|
|
2291
|
+
// COMPAT(personalityMemory): additive; absent = the pre-memory, personality-agnostic report.
|
|
2292
|
+
personalityId: z.string().optional(),
|
|
2293
|
+
// That personality's injected memory brief, in tokens. Folded into the
|
|
2294
|
+
// `otto_injected` category total rather than a new category: ContextCategory
|
|
2295
|
+
// is a z.enum travelling daemon->client, so a new member would make a new
|
|
2296
|
+
// daemon's report unparseable by an older client.
|
|
2297
|
+
personalityMemoryTokens: z.number().optional(),
|
|
2002
2298
|
});
|
|
2003
2299
|
// Pushed with the full current report whenever a watched context file changes.
|
|
2004
2300
|
// Full-report reconciliation, same idiom as suggested_tasks_changed.
|
|
@@ -2017,6 +2313,10 @@ export const ContextReportGetRequestMessageSchema = z.object({
|
|
|
2017
2313
|
workspaceId: z.string(),
|
|
2018
2314
|
provider: z.string().optional(),
|
|
2019
2315
|
windowTokens: z.number().optional(),
|
|
2316
|
+
// "Evaluate as if this personality were running here": folds that
|
|
2317
|
+
// personality's injected memory brief into the report's fixed weight. Omitted
|
|
2318
|
+
// means the personality-agnostic report.
|
|
2319
|
+
personalityId: z.string().optional(),
|
|
2020
2320
|
});
|
|
2021
2321
|
export const ContextReportGetResponseMessageSchema = z.object({
|
|
2022
2322
|
type: z.literal("context.report.get.response"),
|
|
@@ -2046,6 +2346,154 @@ export const ContextEdgeConvertResponseMessageSchema = z.object({
|
|
|
2046
2346
|
error: z.string().optional(),
|
|
2047
2347
|
}),
|
|
2048
2348
|
});
|
|
2349
|
+
// Deletes every mechanically-fixable finding's range in one pass — the
|
|
2350
|
+
// "Fix all" button in the Issues tab. Each item names the file, the range the
|
|
2351
|
+
// scan flagged, and the snippet expected there; a file that changed since the
|
|
2352
|
+
// scan is skipped rather than corrupted (charter §7.5).
|
|
2353
|
+
export const ContextFindingsFixRequestMessageSchema = z.object({
|
|
2354
|
+
type: z.literal("context.findings.fix.request"),
|
|
2355
|
+
requestId: z.string(),
|
|
2356
|
+
workspaceId: z.string(),
|
|
2357
|
+
findings: z.array(z.object({
|
|
2358
|
+
filePath: z.string(),
|
|
2359
|
+
range: ContextRangeSchema,
|
|
2360
|
+
snippet: z.string(),
|
|
2361
|
+
})),
|
|
2362
|
+
});
|
|
2363
|
+
export const ContextFindingsFixResponseMessageSchema = z.object({
|
|
2364
|
+
type: z.literal("context.findings.fix.response"),
|
|
2365
|
+
payload: z.object({
|
|
2366
|
+
requestId: z.string(),
|
|
2367
|
+
fixedCount: z.number(),
|
|
2368
|
+
failedCount: z.number(),
|
|
2369
|
+
errors: z.array(z.string()),
|
|
2370
|
+
}),
|
|
2371
|
+
});
|
|
2372
|
+
// ---------------------------------------------------------------------------
|
|
2373
|
+
// Personality memory — the lessons a named personality accrues across sessions.
|
|
2374
|
+
// See docs/agent-personalities.md § Memory.
|
|
2375
|
+
// ---------------------------------------------------------------------------
|
|
2376
|
+
// Plain strings on the wire, like personality roles and effort levels, so the
|
|
2377
|
+
// daemon can grow the vocabulary without breaking old peers. Logical values:
|
|
2378
|
+
// scope "project" | "global"; source "agent" | "user" | "review" | "transfer".
|
|
2379
|
+
export const PersonalityMemoryEntrySchema = z
|
|
2380
|
+
.object({
|
|
2381
|
+
id: z.string(),
|
|
2382
|
+
text: z.string(),
|
|
2383
|
+
scope: z.string(),
|
|
2384
|
+
// Absolute, daemon-side. Present only on project-scoped entries.
|
|
2385
|
+
projectRoot: z.string().optional(),
|
|
2386
|
+
createdAt: z.string(),
|
|
2387
|
+
updatedAt: z.string(),
|
|
2388
|
+
source: z.string(),
|
|
2389
|
+
// How many times the lesson has been restated. Drives injection order and
|
|
2390
|
+
// is shown in the brief, because a repeatedly-relearned gotcha is stronger
|
|
2391
|
+
// evidence than a one-off observation.
|
|
2392
|
+
reinforcedCount: z.number().optional(),
|
|
2393
|
+
transferredFrom: z.string().optional(),
|
|
2394
|
+
})
|
|
2395
|
+
.passthrough();
|
|
2396
|
+
export const PersonalityMemoryListRequestMessageSchema = z.object({
|
|
2397
|
+
type: z.literal("personality.memory.list.request"),
|
|
2398
|
+
requestId: z.string(),
|
|
2399
|
+
personalityId: z.string(),
|
|
2400
|
+
// Which project's lessons count as in-scope for the returned brief. Prefer
|
|
2401
|
+
// `workspaceId` and let the daemon resolve the root: a client computing repo
|
|
2402
|
+
// roots would disagree with the daemon the moment a worktree is involved.
|
|
2403
|
+
workspaceId: z.string().optional(),
|
|
2404
|
+
// Explicit root, for callers with no workspace. Ignored when `workspaceId`
|
|
2405
|
+
// resolves. Omitted (with no workspace) means global lessons only.
|
|
2406
|
+
projectRoot: z.string().optional(),
|
|
2407
|
+
});
|
|
2408
|
+
export const PersonalityMemoryListResponseMessageSchema = z.object({
|
|
2409
|
+
type: z.literal("personality.memory.list.response"),
|
|
2410
|
+
payload: z.object({
|
|
2411
|
+
requestId: z.string(),
|
|
2412
|
+
personalityId: z.string(),
|
|
2413
|
+
personalityName: z.string(),
|
|
2414
|
+
/** Whether this personality is accruing (the `memoryEnabled` switch). */
|
|
2415
|
+
enabled: z.boolean(),
|
|
2416
|
+
/** Every stored entry, including other projects' — the UI shows them all. */
|
|
2417
|
+
entries: z.array(PersonalityMemoryEntrySchema),
|
|
2418
|
+
// The EXACT text the daemon would inject for `projectRoot`, not a
|
|
2419
|
+
// reconstruction. Memory is only trustworthy if it is inspectable, and the
|
|
2420
|
+
// only way the shown text cannot drift from the injected text is for both
|
|
2421
|
+
// to come from one composer.
|
|
2422
|
+
brief: z.string(),
|
|
2423
|
+
briefTokens: z.number(),
|
|
2424
|
+
/** Entries the injection budget cut, so the UI can say so. */
|
|
2425
|
+
briefOmittedCount: z.number().optional(),
|
|
2426
|
+
// The root the brief was composed for, so the UI can tell a project-scoped
|
|
2427
|
+
// entry that applies here from one belonging to another project. Without it
|
|
2428
|
+
// every project entry looks the same and an empty brief next to a list of
|
|
2429
|
+
// lessons reads as a bug. Absent when the request named no workspace.
|
|
2430
|
+
projectRoot: z.string().optional(),
|
|
2431
|
+
}),
|
|
2432
|
+
});
|
|
2433
|
+
// One write RPC covers add / edit / delete: no `entryId` = add a new lesson,
|
|
2434
|
+
// `drop: true` = forget one. The user-facing editing path from Context
|
|
2435
|
+
// Management (charter §2.4).
|
|
2436
|
+
export const PersonalityMemoryUpdateRequestMessageSchema = z.object({
|
|
2437
|
+
type: z.literal("personality.memory.update.request"),
|
|
2438
|
+
requestId: z.string(),
|
|
2439
|
+
personalityId: z.string(),
|
|
2440
|
+
entryId: z.string().optional(),
|
|
2441
|
+
text: z.string().optional(),
|
|
2442
|
+
scope: z.string().optional(),
|
|
2443
|
+
// Which project a `scope: "project"` write binds to. Same rule as the list
|
|
2444
|
+
// request: prefer `workspaceId` and let the daemon resolve the root, because a
|
|
2445
|
+
// project-scoped entry whose root does not match the daemon's resolution is
|
|
2446
|
+
// filtered out of every brief and is therefore stored but never sent.
|
|
2447
|
+
workspaceId: z.string().optional(),
|
|
2448
|
+
// Explicit root, for callers with no workspace. Ignored when `workspaceId`
|
|
2449
|
+
// resolves.
|
|
2450
|
+
projectRoot: z.string().optional(),
|
|
2451
|
+
drop: z.boolean().optional(),
|
|
2452
|
+
});
|
|
2453
|
+
export const PersonalityMemoryUpdateResponseMessageSchema = z.object({
|
|
2454
|
+
type: z.literal("personality.memory.update.response"),
|
|
2455
|
+
payload: z.object({
|
|
2456
|
+
requestId: z.string(),
|
|
2457
|
+
ok: z.boolean(),
|
|
2458
|
+
error: z.string().optional(),
|
|
2459
|
+
}),
|
|
2460
|
+
});
|
|
2461
|
+
// Deleting a personality must never silently destroy what it learned, so the
|
|
2462
|
+
// delete flow resolves here first: `mode: "transfer"` moves the lessons to
|
|
2463
|
+
// `toPersonalityId` (merging near-duplicates), `mode: "delete"` discards them.
|
|
2464
|
+
export const PersonalityMemoryTransferRequestMessageSchema = z.object({
|
|
2465
|
+
type: z.literal("personality.memory.transfer.request"),
|
|
2466
|
+
requestId: z.string(),
|
|
2467
|
+
fromPersonalityId: z.string(),
|
|
2468
|
+
toPersonalityId: z.string().optional(),
|
|
2469
|
+
mode: z.string(),
|
|
2470
|
+
});
|
|
2471
|
+
export const PersonalityMemoryTransferResponseMessageSchema = z.object({
|
|
2472
|
+
type: z.literal("personality.memory.transfer.response"),
|
|
2473
|
+
payload: z.object({
|
|
2474
|
+
requestId: z.string(),
|
|
2475
|
+
ok: z.boolean(),
|
|
2476
|
+
/** Entries that landed as new rows in the destination. */
|
|
2477
|
+
transferred: z.number().optional(),
|
|
2478
|
+
/** Entries that merged into a lesson the destination already knew. */
|
|
2479
|
+
merged: z.number().optional(),
|
|
2480
|
+
error: z.string().optional(),
|
|
2481
|
+
}),
|
|
2482
|
+
});
|
|
2483
|
+
// Per-personality lesson counts. Its own RPC over its own file, mirroring
|
|
2484
|
+
// agentPersonalities.get_stats — counts must not ride the daemon-config
|
|
2485
|
+
// broadcast, or every recorded lesson would fan a config change to every client.
|
|
2486
|
+
export const PersonalityMemoryStatsRequestMessageSchema = z.object({
|
|
2487
|
+
type: z.literal("personality.memory.stats.request"),
|
|
2488
|
+
requestId: z.string(),
|
|
2489
|
+
});
|
|
2490
|
+
export const PersonalityMemoryStatsResponseMessageSchema = z.object({
|
|
2491
|
+
type: z.literal("personality.memory.stats.response"),
|
|
2492
|
+
payload: z.object({
|
|
2493
|
+
requestId: z.string(),
|
|
2494
|
+
counts: z.record(z.string(), z.number()),
|
|
2495
|
+
}),
|
|
2496
|
+
});
|
|
2049
2497
|
// Aggregate outcome for a start/dismiss over one or more tasks. `succeeded`/
|
|
2050
2498
|
// `failed` count the tasks acted on so the client can report "Started 3 tasks";
|
|
2051
2499
|
// `error` collects any per-task failure messages (the failed tasks' chips stay).
|
|
@@ -2360,14 +2808,172 @@ export const RunsClearResponseSchema = z.object({
|
|
|
2360
2808
|
requestId: z.string(),
|
|
2361
2809
|
}),
|
|
2362
2810
|
});
|
|
2811
|
+
// Delete one run by id. Terminal (done/failed/canceled) and draft runs only —
|
|
2812
|
+
// deleting an active run is refused so a cleanup click can't silently orphan
|
|
2813
|
+
// running agents; cancel it first. Gated by server_info.features.runsDelete.
|
|
2814
|
+
export const RunsDeleteRequestSchema = z.object({
|
|
2815
|
+
type: z.literal("runs.delete.request"),
|
|
2816
|
+
requestId: z.string(),
|
|
2817
|
+
runId: z.string(),
|
|
2818
|
+
});
|
|
2819
|
+
export const RunsDeleteResponseSchema = z.object({
|
|
2820
|
+
type: z.literal("runs.delete.response"),
|
|
2821
|
+
payload: z.object({
|
|
2822
|
+
// The deleted id, or absent when nothing was deleted (unknown or still
|
|
2823
|
+
// active) — `error` then carries why.
|
|
2824
|
+
runId: z.string().optional(),
|
|
2825
|
+
error: z.string().optional(),
|
|
2826
|
+
requestId: z.string(),
|
|
2827
|
+
}),
|
|
2828
|
+
});
|
|
2363
2829
|
// Broadcast to every connected client (including the requester) so all
|
|
2364
2830
|
// caches drop the same runs, mirroring runs.updated.notification's upsert.
|
|
2831
|
+
// Serves both runs.clear (many ids) and runs.delete (one).
|
|
2365
2832
|
export const RunsClearedNotificationSchema = z.object({
|
|
2366
2833
|
type: z.literal("runs.cleared.notification"),
|
|
2367
2834
|
payload: z.object({
|
|
2368
2835
|
runIds: z.array(z.string()),
|
|
2369
2836
|
}),
|
|
2370
2837
|
});
|
|
2838
|
+
// ── Orchestration graphs (user orchestrations) ──────────────────────────────
|
|
2839
|
+
// Host-level reusable graph templates + user-initiated orchestration start.
|
|
2840
|
+
// Gated by server_info.features.orchestrationGraphs. UI says "Orchestration"
|
|
2841
|
+
// and "Graph"; the wire keeps the short `runs.` namespace (see docs/glossary.md).
|
|
2842
|
+
// See projects/orchestration-graphs.
|
|
2843
|
+
export const RunsGraphsListRequestSchema = z.object({
|
|
2844
|
+
type: z.literal("runs.graphs.list.request"),
|
|
2845
|
+
requestId: z.string(),
|
|
2846
|
+
});
|
|
2847
|
+
export const RunsGraphsListResponseSchema = z.object({
|
|
2848
|
+
type: z.literal("runs.graphs.list.response"),
|
|
2849
|
+
payload: z.object({
|
|
2850
|
+
graphs: z.array(OrchestrationGraphSchema),
|
|
2851
|
+
requestId: z.string(),
|
|
2852
|
+
}),
|
|
2853
|
+
});
|
|
2854
|
+
// Upsert a graph template (create when the id is new). Built-in graphs are
|
|
2855
|
+
// copy-on-edit daemon-side: saving over a builtIn id persists a user copy.
|
|
2856
|
+
export const RunsGraphsSaveRequestSchema = z.object({
|
|
2857
|
+
type: z.literal("runs.graphs.save.request"),
|
|
2858
|
+
graph: OrchestrationGraphSchema,
|
|
2859
|
+
requestId: z.string(),
|
|
2860
|
+
});
|
|
2861
|
+
export const RunsGraphsSaveResponseSchema = z.object({
|
|
2862
|
+
type: z.literal("runs.graphs.save.response"),
|
|
2863
|
+
payload: z.object({
|
|
2864
|
+
graph: OrchestrationGraphSchema.optional(),
|
|
2865
|
+
error: z.string().optional(),
|
|
2866
|
+
requestId: z.string(),
|
|
2867
|
+
}),
|
|
2868
|
+
});
|
|
2869
|
+
export const RunsGraphsDeleteRequestSchema = z.object({
|
|
2870
|
+
type: z.literal("runs.graphs.delete.request"),
|
|
2871
|
+
graphId: z.string(),
|
|
2872
|
+
requestId: z.string(),
|
|
2873
|
+
});
|
|
2874
|
+
export const RunsGraphsDeleteResponseSchema = z.object({
|
|
2875
|
+
type: z.literal("runs.graphs.delete.response"),
|
|
2876
|
+
payload: z.object({
|
|
2877
|
+
deleted: z.boolean(),
|
|
2878
|
+
error: z.string().optional(),
|
|
2879
|
+
requestId: z.string(),
|
|
2880
|
+
}),
|
|
2881
|
+
});
|
|
2882
|
+
// Broadcast after any save/delete so every client's graph cache converges,
|
|
2883
|
+
// mirroring runs.updated.notification's role for runs.
|
|
2884
|
+
export const RunsGraphsChangedNotificationSchema = z.object({
|
|
2885
|
+
type: z.literal("runs.graphs.changed.notification"),
|
|
2886
|
+
payload: z.object({
|
|
2887
|
+
graphs: z.array(OrchestrationGraphSchema),
|
|
2888
|
+
}),
|
|
2889
|
+
});
|
|
2890
|
+
// ── Prompt templates ────────────────────────────────────────────────────────
|
|
2891
|
+
// Host-level reusable prompts and snippets a graph node can bind to. Same shape
|
|
2892
|
+
// as the graph trio above, for the same reason: one store, list/save/delete,
|
|
2893
|
+
// plus a full-list push so every client converges.
|
|
2894
|
+
export const RunsTemplatesListRequestSchema = z.object({
|
|
2895
|
+
type: z.literal("runs.templates.list.request"),
|
|
2896
|
+
requestId: z.string(),
|
|
2897
|
+
});
|
|
2898
|
+
export const RunsTemplatesListResponseSchema = z.object({
|
|
2899
|
+
type: z.literal("runs.templates.list.response"),
|
|
2900
|
+
payload: z.object({
|
|
2901
|
+
templates: z.array(PromptTemplateSchema),
|
|
2902
|
+
requestId: z.string(),
|
|
2903
|
+
}),
|
|
2904
|
+
});
|
|
2905
|
+
export const RunsTemplatesSaveRequestSchema = z.object({
|
|
2906
|
+
type: z.literal("runs.templates.save.request"),
|
|
2907
|
+
template: PromptTemplateSchema,
|
|
2908
|
+
requestId: z.string(),
|
|
2909
|
+
});
|
|
2910
|
+
export const RunsTemplatesSaveResponseSchema = z.object({
|
|
2911
|
+
type: z.literal("runs.templates.save.response"),
|
|
2912
|
+
payload: z.object({
|
|
2913
|
+
template: PromptTemplateSchema.optional(),
|
|
2914
|
+
error: z.string().optional(),
|
|
2915
|
+
requestId: z.string(),
|
|
2916
|
+
}),
|
|
2917
|
+
});
|
|
2918
|
+
export const RunsTemplatesDeleteRequestSchema = z.object({
|
|
2919
|
+
type: z.literal("runs.templates.delete.request"),
|
|
2920
|
+
templateId: z.string(),
|
|
2921
|
+
requestId: z.string(),
|
|
2922
|
+
});
|
|
2923
|
+
export const RunsTemplatesDeleteResponseSchema = z.object({
|
|
2924
|
+
type: z.literal("runs.templates.delete.response"),
|
|
2925
|
+
payload: z.object({
|
|
2926
|
+
deleted: z.boolean(),
|
|
2927
|
+
error: z.string().optional(),
|
|
2928
|
+
requestId: z.string(),
|
|
2929
|
+
}),
|
|
2930
|
+
});
|
|
2931
|
+
export const RunsTemplatesChangedNotificationSchema = z.object({
|
|
2932
|
+
type: z.literal("runs.templates.changed.notification"),
|
|
2933
|
+
payload: z.object({
|
|
2934
|
+
templates: z.array(PromptTemplateSchema),
|
|
2935
|
+
}),
|
|
2936
|
+
});
|
|
2937
|
+
// Start (or draft) a user-initiated orchestration from the New Orchestration
|
|
2938
|
+
// dialog. `flavor` is an open vocabulary: "ai" (prompt-and-go — the daemon
|
|
2939
|
+
// spawns an orchestrator agent that declares its own plan via start_run) or
|
|
2940
|
+
// "graph" (deterministic — the daemon executes `graphId` with `graphInputs`).
|
|
2941
|
+
// `draft: true` creates the record without executing (the designer flow);
|
|
2942
|
+
// `runId` executes an existing draft in place — or, with `draft: true`, re-saves
|
|
2943
|
+
// that draft in place (Edit Orchestration).
|
|
2944
|
+
export const RunsStartRequestSchema = z.object({
|
|
2945
|
+
type: z.literal("runs.start.request"),
|
|
2946
|
+
flavor: z.string(),
|
|
2947
|
+
cwd: z.string(),
|
|
2948
|
+
workspaceId: z.string().optional(),
|
|
2949
|
+
title: z.string().optional(),
|
|
2950
|
+
description: z.string().optional(),
|
|
2951
|
+
// Orchestrator seat when the active team doesn't fill it: a personality, or
|
|
2952
|
+
// a bare provider/model pair.
|
|
2953
|
+
orchestratorPersonalityId: z.string().optional(),
|
|
2954
|
+
orchestratorProvider: z.string().optional(),
|
|
2955
|
+
orchestratorModel: z.string().optional(),
|
|
2956
|
+
orchestratorThinkingOptionId: z.string().optional(),
|
|
2957
|
+
prompt: z.string().optional(),
|
|
2958
|
+
graphId: z.string().optional(),
|
|
2959
|
+
graphInputs: z.record(z.string(), z.string()).optional(),
|
|
2960
|
+
draft: z.boolean().optional(),
|
|
2961
|
+
runId: z.string().optional(),
|
|
2962
|
+
requestId: z.string(),
|
|
2963
|
+
});
|
|
2964
|
+
export const RunsStartResponseSchema = z.object({
|
|
2965
|
+
type: z.literal("runs.start.response"),
|
|
2966
|
+
payload: z.object({
|
|
2967
|
+
runId: z.string().optional(),
|
|
2968
|
+
// The root/orchestrator agent whose chat the client navigates to, and the
|
|
2969
|
+
// workspace the daemon resolved it into (the dialog only knows a project
|
|
2970
|
+
// target's cwd).
|
|
2971
|
+
agentId: z.string().optional(),
|
|
2972
|
+
workspaceId: z.string().optional(),
|
|
2973
|
+
error: z.string().optional(),
|
|
2974
|
+
requestId: z.string(),
|
|
2975
|
+
}),
|
|
2976
|
+
});
|
|
2371
2977
|
// Namespaced successor to checkout_commit_request: per-file selection and
|
|
2372
2978
|
// structured errors. Gated by server_info.features.checkoutGitCommit; the flat
|
|
2373
2979
|
// RPC stays accepted for old clients.
|
|
@@ -2729,10 +3335,129 @@ export const ProjectAddRequestSchema = z.object({
|
|
|
2729
3335
|
cwd: z.string(),
|
|
2730
3336
|
requestId: z.string(),
|
|
2731
3337
|
});
|
|
3338
|
+
// ── New project scaffolding ──────────────────────────────────────────────
|
|
3339
|
+
// project.add takes a directory that already exists. Scaffolding is the other
|
|
3340
|
+
// half: create the directory, optionally give it a git repo (fresh, or cloned
|
|
3341
|
+
// from a remote), optionally create that remote on a connected hosting
|
|
3342
|
+
// provider, then register the result as a project. One RPC rather than a
|
|
3343
|
+
// client-driven sequence so a half-finished project can never be left behind by
|
|
3344
|
+
// a dropped socket — the daemon owns the whole transaction.
|
|
3345
|
+
// COMPAT(projectScaffold): added in v0.6.9. Gated by server_info.features.projectScaffold.
|
|
3346
|
+
// Built-in .gitignore starters. Deliberately a short list of the ecosystems Otto
|
|
3347
|
+
// itself works in — this is a convenience, not a mirror of github/gitignore. The
|
|
3348
|
+
// wire field stays an open string so a newer daemon can add one without an older
|
|
3349
|
+
// client's validator rejecting the message.
|
|
3350
|
+
export const PROJECT_SCAFFOLD_GITIGNORE_TEMPLATE_IDS = [
|
|
3351
|
+
"node",
|
|
3352
|
+
"python",
|
|
3353
|
+
"go",
|
|
3354
|
+
"rust",
|
|
3355
|
+
"java",
|
|
3356
|
+
"dotnet",
|
|
3357
|
+
];
|
|
3358
|
+
// Where the working tree comes from.
|
|
3359
|
+
export const ProjectScaffoldGitSchema = z.discriminatedUnion("kind", [
|
|
3360
|
+
// A plain directory. No repository is created.
|
|
3361
|
+
z.object({ kind: z.literal("none") }),
|
|
3362
|
+
z.object({
|
|
3363
|
+
kind: z.literal("init"),
|
|
3364
|
+
// Branch the fresh repo starts on. Absent means the daemon's git default.
|
|
3365
|
+
initialBranch: z.string().optional(),
|
|
3366
|
+
// Starter files written before the first commit.
|
|
3367
|
+
addReadme: z.boolean().optional(),
|
|
3368
|
+
// Identifier of a built-in .gitignore template (see PROJECT_SCAFFOLD_GITIGNORE_TEMPLATE_IDS).
|
|
3369
|
+
gitignoreTemplate: z.string().optional(),
|
|
3370
|
+
// Commit whatever starter files were written. Required for a push.
|
|
3371
|
+
initialCommit: z.boolean().optional(),
|
|
3372
|
+
// Create the repository on a hosting provider, wire it as `origin`, and push.
|
|
3373
|
+
// Requires the provider's createRepository capability.
|
|
3374
|
+
remote: z
|
|
3375
|
+
.object({
|
|
3376
|
+
providerId: GitHostingProviderIdWireSchema,
|
|
3377
|
+
// Account/organization/workspace to create under. Null means the
|
|
3378
|
+
// provider's default for the authenticated identity.
|
|
3379
|
+
owner: z.string().nullable(),
|
|
3380
|
+
name: z.string(),
|
|
3381
|
+
description: z.string().optional(),
|
|
3382
|
+
visibility: z.enum(["private", "public"]),
|
|
3383
|
+
})
|
|
3384
|
+
.optional(),
|
|
3385
|
+
}),
|
|
3386
|
+
z.object({
|
|
3387
|
+
kind: z.literal("clone"),
|
|
3388
|
+
// Any URL `git clone` accepts (https, ssh, scp-style).
|
|
3389
|
+
url: z.string(),
|
|
3390
|
+
}),
|
|
3391
|
+
]);
|
|
3392
|
+
export const ProjectScaffoldRequestSchema = z.object({
|
|
3393
|
+
type: z.literal("project.scaffold.request"),
|
|
3394
|
+
requestId: z.string(),
|
|
3395
|
+
// Existing directory that will contain the new project folder.
|
|
3396
|
+
parentDirectory: z.string(),
|
|
3397
|
+
// Single path segment created inside parentDirectory. For a clone this may be
|
|
3398
|
+
// omitted, in which case the daemon derives it from the repository URL.
|
|
3399
|
+
folderName: z.string().optional(),
|
|
3400
|
+
git: ProjectScaffoldGitSchema,
|
|
3401
|
+
});
|
|
3402
|
+
// Steps are reported in the order the daemon runs them. New daemons may add
|
|
3403
|
+
// steps, so the wire form stays an open string and clients label unknown ids
|
|
3404
|
+
// generically instead of dropping the progress message.
|
|
3405
|
+
export const ProjectScaffoldStepIdSchema = z.string();
|
|
3406
|
+
export const ProjectScaffoldStepStatusSchema = z.enum(["running", "done", "skipped", "failed"]);
|
|
3407
|
+
export const ProjectScaffoldStepSchema = z.object({
|
|
3408
|
+
id: ProjectScaffoldStepIdSchema,
|
|
3409
|
+
status: ProjectScaffoldStepStatusSchema,
|
|
3410
|
+
detail: z.string().nullable(),
|
|
3411
|
+
});
|
|
3412
|
+
// Repository enumeration for the clone picker, and owner enumeration for the
|
|
3413
|
+
// "create a new remote" form. Both are host-level (no repo cwd exists yet), so
|
|
3414
|
+
// they address a provider directly instead of resolving one from a checkout.
|
|
3415
|
+
export const HostingListRepositoriesRequestSchema = z.object({
|
|
3416
|
+
type: z.literal("hosting.list_repositories.request"),
|
|
3417
|
+
provider: GitHostingProviderIdWireSchema,
|
|
3418
|
+
// Substring filter applied by the provider where it supports one.
|
|
3419
|
+
query: z.string().optional(),
|
|
3420
|
+
limit: z.number().int().min(1).max(100).optional(),
|
|
3421
|
+
requestId: z.string(),
|
|
3422
|
+
});
|
|
3423
|
+
export const HostingListOwnersRequestSchema = z.object({
|
|
3424
|
+
type: z.literal("hosting.list_owners.request"),
|
|
3425
|
+
provider: GitHostingProviderIdWireSchema,
|
|
3426
|
+
requestId: z.string(),
|
|
3427
|
+
});
|
|
2732
3428
|
export const ArchiveWorkspaceRequestSchema = z.object({
|
|
2733
3429
|
type: z.literal("archive_workspace_request"),
|
|
2734
3430
|
workspaceId: z.string(),
|
|
2735
3431
|
requestId: z.string(),
|
|
3432
|
+
// COMPAT(worktreeArchiveBranchCleanup): added in v0.6.7, drop the optional
|
|
3433
|
+
// gate when daemon floor >= v0.6.7. Absent means "keep" — the leftover local
|
|
3434
|
+
// branch is never touched (old-client behavior). "delete" asks the daemon to
|
|
3435
|
+
// remove the worktree's local branch after the backing directory is torn down
|
|
3436
|
+
// (only when this was the last reference to it and the branch is not checked
|
|
3437
|
+
// out elsewhere). Gated by server_info.features.worktreeArchiveBranchCleanup.
|
|
3438
|
+
branchDisposition: z.enum(["keep", "delete"]).optional(),
|
|
3439
|
+
});
|
|
3440
|
+
// Read-only pre-archive inspection for a worktree-backed workspace: what branch
|
|
3441
|
+
// it is on, whether that branch is merged into its base, and whether archiving
|
|
3442
|
+
// will actually free the branch (last reference, not checked out elsewhere). The
|
|
3443
|
+
// client uses this to render the "delete the leftover branch?" confirmation.
|
|
3444
|
+
// COMPAT(worktreeArchiveBranchCleanup): added in v0.6.7.
|
|
3445
|
+
export const WorkspaceArchivePreflightRequestSchema = z.object({
|
|
3446
|
+
type: z.literal("workspace.archive.preflight.request"),
|
|
3447
|
+
requestId: z.string(),
|
|
3448
|
+
workspaceId: z.string(),
|
|
3449
|
+
});
|
|
3450
|
+
// Repoint a worktree-backed workspace's base branch — what the Changes view diffs
|
|
3451
|
+
// against, and what merge-into-base and PR creation target. On a stacked branch the
|
|
3452
|
+
// useful base is the parent branch, not the repo default, the same way a forge PR
|
|
3453
|
+
// carries an explicit base. A null baseRef resets to the repository default branch.
|
|
3454
|
+
// COMPAT(worktreeDiffBase): added in v0.6.8.
|
|
3455
|
+
export const WorktreeBaseRefSetRequestSchema = z.object({
|
|
3456
|
+
type: z.literal("worktree.baseRef.set.request"),
|
|
3457
|
+
requestId: z.string(),
|
|
3458
|
+
workspaceId: z.string(),
|
|
3459
|
+
// Branch name, with or without an `origin/` prefix; null resets to the default branch.
|
|
3460
|
+
baseRef: z.string().nullable(),
|
|
2736
3461
|
});
|
|
2737
3462
|
// Create a new workspace record. Unlike open_project, this never deduplicates by
|
|
2738
3463
|
// directory: it always produces a fresh workspace. The source discriminates
|
|
@@ -2765,6 +3490,36 @@ export const WorkspaceCreateRequestSchema = z.object({
|
|
|
2765
3490
|
}),
|
|
2766
3491
|
]),
|
|
2767
3492
|
});
|
|
3493
|
+
// Re-attach a "left" Otto worktree as a live workspace. Two targets: revive an
|
|
3494
|
+
// archived worktree workspace record in place (recreating its backing directory
|
|
3495
|
+
// from the kept branch when it is gone), or bind a fresh workspace to an orphaned
|
|
3496
|
+
// on-disk Otto worktree that no live workspace references.
|
|
3497
|
+
// COMPAT(worktreeReattach): added in v0.6.7. Gated by server_info.features.worktreeReattach.
|
|
3498
|
+
export const WorktreeReattachTargetSchema = z.discriminatedUnion("kind", [
|
|
3499
|
+
z.object({
|
|
3500
|
+
kind: z.literal("workspace"),
|
|
3501
|
+
workspaceId: z.string(),
|
|
3502
|
+
}),
|
|
3503
|
+
z.object({
|
|
3504
|
+
kind: z.literal("orphan"),
|
|
3505
|
+
worktreePath: z.string(),
|
|
3506
|
+
projectId: z.string().optional(),
|
|
3507
|
+
}),
|
|
3508
|
+
]);
|
|
3509
|
+
export const WorktreeReattachRequestSchema = z.object({
|
|
3510
|
+
type: z.literal("worktree.reattach.request"),
|
|
3511
|
+
requestId: z.string(),
|
|
3512
|
+
target: WorktreeReattachTargetSchema,
|
|
3513
|
+
});
|
|
3514
|
+
// List re-attachable Otto worktrees for a project/repo: archived worktree
|
|
3515
|
+
// workspace records whose branch is kept, plus orphaned on-disk worktrees with no
|
|
3516
|
+
// live workspace. Either projectId or a cwd inside the repo is required.
|
|
3517
|
+
export const WorktreeReattachListRequestSchema = z.object({
|
|
3518
|
+
type: z.literal("worktree.reattach.list.request"),
|
|
3519
|
+
requestId: z.string(),
|
|
3520
|
+
projectId: z.string().optional(),
|
|
3521
|
+
cwd: z.string().optional(),
|
|
3522
|
+
});
|
|
2768
3523
|
export const WorkspaceClearAttentionRequestSchema = z.object({
|
|
2769
3524
|
type: z.literal("workspace.clear_attention.request"),
|
|
2770
3525
|
workspaceId: z.union([z.string(), z.array(z.string())]),
|
|
@@ -2805,6 +3560,8 @@ const FileExplorerEntrySchema = z.object({
|
|
|
2805
3560
|
modifiedAt: z.string(),
|
|
2806
3561
|
});
|
|
2807
3562
|
export const FileEolSchema = z.enum(["lf", "crlf"]);
|
|
3563
|
+
/** What a directory entry is. Shared by the file-mutation RPCs below. */
|
|
3564
|
+
export const FileEntryKindSchema = z.enum(["file", "directory"]);
|
|
2808
3565
|
const FileExplorerFileSchema = z.object({
|
|
2809
3566
|
path: z.string(),
|
|
2810
3567
|
kind: z.enum(["text", "image", "binary"]),
|
|
@@ -2870,6 +3627,96 @@ export const FileWriteRequestSchema = z.object({
|
|
|
2870
3627
|
eol: FileEolSchema.optional(),
|
|
2871
3628
|
requestId: z.string(),
|
|
2872
3629
|
});
|
|
3630
|
+
/**
|
|
3631
|
+
* The general file-mutation surface: create, delete, rename/move.
|
|
3632
|
+
*
|
|
3633
|
+
* Deliberately separate from `file.write.request`, which is the text editor's
|
|
3634
|
+
* conditional *content* save. These three change what exists in the directory
|
|
3635
|
+
* rather than what is inside a file, and unlike `file.write` they are
|
|
3636
|
+
* **workspace-bounded**: the daemon refuses a `cwd` outside every known Otto
|
|
3637
|
+
* workspace, the way directory listing already does. Editing a stray file the
|
|
3638
|
+
* user opened by path is one thing; unlinking one is another.
|
|
3639
|
+
*
|
|
3640
|
+
* `path` is workspace-relative throughout, matching every other file RPC.
|
|
3641
|
+
*/
|
|
3642
|
+
export const FileCreateRequestSchema = z.object({
|
|
3643
|
+
type: z.literal("file.create.request"),
|
|
3644
|
+
cwd: z.string(),
|
|
3645
|
+
path: z.string(),
|
|
3646
|
+
kind: FileEntryKindSchema,
|
|
3647
|
+
requestId: z.string(),
|
|
3648
|
+
});
|
|
3649
|
+
/**
|
|
3650
|
+
* Permanent delete — an unlink, not a move to the OS trash. The daemon may be
|
|
3651
|
+
* headless, remote, or inside WSL, where there is no reliable trash to move to;
|
|
3652
|
+
* a "deleted" file that silently stayed on disk in one environment and vanished
|
|
3653
|
+
* in another would be worse than either. The client's confirmation says so.
|
|
3654
|
+
*/
|
|
3655
|
+
export const FileDeleteRequestSchema = z.object({
|
|
3656
|
+
type: z.literal("file.delete.request"),
|
|
3657
|
+
cwd: z.string(),
|
|
3658
|
+
path: z.string(),
|
|
3659
|
+
// Required to delete a directory that has children. Absent (the default) a
|
|
3660
|
+
// non-empty directory comes back as `not_empty` and nothing is removed, so a
|
|
3661
|
+
// client that never asks can never recursively wipe a tree by accident.
|
|
3662
|
+
recursive: z.boolean().optional(),
|
|
3663
|
+
requestId: z.string(),
|
|
3664
|
+
});
|
|
3665
|
+
/**
|
|
3666
|
+
* Rename and move are the same operation — a move is a rename whose new path
|
|
3667
|
+
* has a different parent. Never clobbers: an occupied destination comes back as
|
|
3668
|
+
* `exists` and nothing moves. There is no overwrite flag on purpose, so this
|
|
3669
|
+
* RPC cannot destroy a file the user did not name.
|
|
3670
|
+
*/
|
|
3671
|
+
export const FileRenameRequestSchema = z.object({
|
|
3672
|
+
type: z.literal("file.rename.request"),
|
|
3673
|
+
cwd: z.string(),
|
|
3674
|
+
path: z.string(),
|
|
3675
|
+
newPath: z.string(),
|
|
3676
|
+
requestId: z.string(),
|
|
3677
|
+
});
|
|
3678
|
+
/**
|
|
3679
|
+
* Refine — an AI rewrite the user reviews as a diff before anything is written.
|
|
3680
|
+
* This RPC only *proposes*: it reads nothing from disk and writes nothing. The
|
|
3681
|
+
* accepted result goes back through `file.write.request` like any other save,
|
|
3682
|
+
* so the conditional-write precondition still guards it.
|
|
3683
|
+
*
|
|
3684
|
+
* `base` travels from the client rather than being re-read on the daemon, so
|
|
3685
|
+
* the model rewrites exactly the document the user is looking at and the diff
|
|
3686
|
+
* they review is the diff of what they saw.
|
|
3687
|
+
*/
|
|
3688
|
+
/**
|
|
3689
|
+
* One document in a refine request. `id` is opaque and client-minted; the model
|
|
3690
|
+
* never sees it and the daemon only echoes it back. That is deliberate: the
|
|
3691
|
+
* client maps id -> absolute path itself, so a model that mangles or invents a
|
|
3692
|
+
* filename cannot misroute a write. `label` is the only path-ish thing the
|
|
3693
|
+
* model sees, and it exists purely so the prompt can say which file is which.
|
|
3694
|
+
*/
|
|
3695
|
+
export const FileRefineDocumentSchema = z.object({
|
|
3696
|
+
id: z.string().min(1),
|
|
3697
|
+
label: z.string(),
|
|
3698
|
+
content: z.string(),
|
|
3699
|
+
});
|
|
3700
|
+
/** A file the model may read for context but must never rewrite. */
|
|
3701
|
+
export const FileRefineReferenceSchema = z.object({
|
|
3702
|
+
label: z.string(),
|
|
3703
|
+
content: z.string(),
|
|
3704
|
+
});
|
|
3705
|
+
export const FileRefineRequestSchema = z.object({
|
|
3706
|
+
type: z.literal("file.refine.request"),
|
|
3707
|
+
// Provider resolution only — which workspace's mini-task chain runs this.
|
|
3708
|
+
// Documents are NOT read from disk here; they travel on the wire.
|
|
3709
|
+
cwd: z.string(),
|
|
3710
|
+
// What the model may rewrite. The blast radius of the whole request: a file
|
|
3711
|
+
// absent from this list cannot be changed, whatever the model returns.
|
|
3712
|
+
documents: z.array(FileRefineDocumentSchema).min(1),
|
|
3713
|
+
// What it may read to understand the first list. Optional so an old client
|
|
3714
|
+
// that only sends documents still parses.
|
|
3715
|
+
references: z.array(FileRefineReferenceSchema).optional(),
|
|
3716
|
+
// The user's plain-language instruction, possibly seeded from a preset.
|
|
3717
|
+
instruction: z.string(),
|
|
3718
|
+
requestId: z.string(),
|
|
3719
|
+
});
|
|
2873
3720
|
// Subscriptions exist only for paths open in tabs; the daemon cleans them up
|
|
2874
3721
|
// when the session ends.
|
|
2875
3722
|
export const FileWatchSubscribeRequestSchema = z.object({
|
|
@@ -2904,10 +3751,179 @@ export const CodeOutlineRequestSchema = z.object({
|
|
|
2904
3751
|
requestId: z.string(),
|
|
2905
3752
|
});
|
|
2906
3753
|
/**
|
|
2907
|
-
*
|
|
2908
|
-
*
|
|
2909
|
-
*
|
|
2910
|
-
*
|
|
3754
|
+
* LSP-backed code intelligence (projects/lsp-code-intelligence). Distinct from the
|
|
3755
|
+
* ctags `code.symbols` RPC above in the only way that matters: it carries a
|
|
3756
|
+
* **position**, so the daemon can resolve the reference under the cursor instead of
|
|
3757
|
+
* matching a name.
|
|
3758
|
+
*
|
|
3759
|
+
* Line and column are **1-based** here, matching `CodeSymbolLocation` and the rest of
|
|
3760
|
+
* Otto. LSP itself is 0-based; that conversion is the daemon's business and does not
|
|
3761
|
+
* reach the wire.
|
|
3762
|
+
*/
|
|
3763
|
+
export const CodeDefinitionRequestSchema = z.object({
|
|
3764
|
+
type: z.literal("code.definition.request"),
|
|
3765
|
+
cwd: z.string(),
|
|
3766
|
+
path: z.string(),
|
|
3767
|
+
line: z.number().int().positive(),
|
|
3768
|
+
column: z.number().int().positive(),
|
|
3769
|
+
requestId: z.string(),
|
|
3770
|
+
});
|
|
3771
|
+
/**
|
|
3772
|
+
* The editor's current buffer text, so definitions resolve against unsaved edits
|
|
3773
|
+
* rather than stale disk content. Sent debounced, not per keystroke.
|
|
3774
|
+
*/
|
|
3775
|
+
export const CodeDocumentSyncRequestSchema = z.object({
|
|
3776
|
+
type: z.literal("code.document.sync.request"),
|
|
3777
|
+
cwd: z.string(),
|
|
3778
|
+
path: z.string(),
|
|
3779
|
+
text: z.string(),
|
|
3780
|
+
requestId: z.string(),
|
|
3781
|
+
});
|
|
3782
|
+
export const CodeDocumentCloseRequestSchema = z.object({
|
|
3783
|
+
type: z.literal("code.document.close.request"),
|
|
3784
|
+
cwd: z.string(),
|
|
3785
|
+
path: z.string(),
|
|
3786
|
+
requestId: z.string(),
|
|
3787
|
+
});
|
|
3788
|
+
/**
|
|
3789
|
+
* The rest of the position-based code-intelligence family. All three carry a 1-based
|
|
3790
|
+
* position like `code.definition`, and all three are answered against the mirrored
|
|
3791
|
+
* buffer rather than the file on disk.
|
|
3792
|
+
*/
|
|
3793
|
+
export const CodeHoverRequestSchema = z.object({
|
|
3794
|
+
type: z.literal("code.hover.request"),
|
|
3795
|
+
cwd: z.string(),
|
|
3796
|
+
path: z.string(),
|
|
3797
|
+
line: z.number().int().positive(),
|
|
3798
|
+
column: z.number().int().positive(),
|
|
3799
|
+
requestId: z.string(),
|
|
3800
|
+
});
|
|
3801
|
+
export const CodeReferencesRequestSchema = z.object({
|
|
3802
|
+
type: z.literal("code.references.request"),
|
|
3803
|
+
cwd: z.string(),
|
|
3804
|
+
path: z.string(),
|
|
3805
|
+
line: z.number().int().positive(),
|
|
3806
|
+
column: z.number().int().positive(),
|
|
3807
|
+
requestId: z.string(),
|
|
3808
|
+
});
|
|
3809
|
+
/**
|
|
3810
|
+
* A rename **dry run**. Deliberately not "do the rename": the daemon computes every edit
|
|
3811
|
+
* and returns them for the user to audit, because a rename's blast radius is the whole
|
|
3812
|
+
* project. Nothing is written by this request.
|
|
3813
|
+
*/
|
|
3814
|
+
export const CodeRenamePreviewRequestSchema = z.object({
|
|
3815
|
+
type: z.literal("code.rename.preview.request"),
|
|
3816
|
+
cwd: z.string(),
|
|
3817
|
+
path: z.string(),
|
|
3818
|
+
line: z.number().int().positive(),
|
|
3819
|
+
column: z.number().int().positive(),
|
|
3820
|
+
newName: z.string().min(1),
|
|
3821
|
+
requestId: z.string(),
|
|
3822
|
+
});
|
|
3823
|
+
/**
|
|
3824
|
+
* Execute a rename the user has audited. **The edits are deliberately NOT on this request.**
|
|
3825
|
+
*
|
|
3826
|
+
* The client sends back only the `planId` it was shown; the daemon recomputes the plan and
|
|
3827
|
+
* refuses unless the identity matches. A request that carried its own edit list would be a
|
|
3828
|
+
* remote arbitrary-write primitive wearing a rename's name — any client could post any text
|
|
3829
|
+
* at any path. This shape makes the daemon's own language server the sole author of what
|
|
3830
|
+
* gets written, and the plan id the proof that the user saw it.
|
|
3831
|
+
*/
|
|
3832
|
+
export const CodeRenameApplyRequestSchema = z.object({
|
|
3833
|
+
type: z.literal("code.rename.apply.request"),
|
|
3834
|
+
cwd: z.string(),
|
|
3835
|
+
path: z.string(),
|
|
3836
|
+
line: z.number().int().positive(),
|
|
3837
|
+
column: z.number().int().positive(),
|
|
3838
|
+
newName: z.string().min(1),
|
|
3839
|
+
/** From the preview response. Identity of the exact plan the user approved. */
|
|
3840
|
+
planId: z.string().min(1),
|
|
3841
|
+
requestId: z.string(),
|
|
3842
|
+
});
|
|
3843
|
+
/**
|
|
3844
|
+
* Undo a run. Carries only the run's id — the daemon holds the before-images.
|
|
3845
|
+
*
|
|
3846
|
+
* Declared here, with the other inbound rename schemas, rather than beside its response
|
|
3847
|
+
* further down: `SessionInboundMessageSchema` is a top-level const, so a schema it names
|
|
3848
|
+
* must already be initialized when that line runs. Below the union it is a
|
|
3849
|
+
* ReferenceError at import time, not a type error.
|
|
3850
|
+
*/
|
|
3851
|
+
export const CodeRenameUndoRequestSchema = z.object({
|
|
3852
|
+
type: z.literal("code.rename.undo.request"),
|
|
3853
|
+
cwd: z.string(),
|
|
3854
|
+
runId: z.string().min(1),
|
|
3855
|
+
requestId: z.string(),
|
|
3856
|
+
});
|
|
3857
|
+
/**
|
|
3858
|
+
* Live language-server state for the Daemon → Code screen. Separate from the daemon
|
|
3859
|
+
* config RPCs because none of it is configuration: which servers this machine can
|
|
3860
|
+
* actually supply, and which are running right now.
|
|
3861
|
+
*
|
|
3862
|
+
* `cwd` scopes the availability check — a server can be present in one workspace's
|
|
3863
|
+
* `node_modules` and absent in another's.
|
|
3864
|
+
*/
|
|
3865
|
+
export const LspServersListRequestSchema = z.object({
|
|
3866
|
+
type: z.literal("lsp.servers.list.request"),
|
|
3867
|
+
cwd: z.string(),
|
|
3868
|
+
requestId: z.string(),
|
|
3869
|
+
});
|
|
3870
|
+
/** Stop one running server, so a user who suspects it of hogging memory can kill it. */
|
|
3871
|
+
export const LspServerStopRequestSchema = z.object({
|
|
3872
|
+
type: z.literal("lsp.server.stop.request"),
|
|
3873
|
+
rootPath: z.string(),
|
|
3874
|
+
serverId: z.string(),
|
|
3875
|
+
requestId: z.string(),
|
|
3876
|
+
});
|
|
3877
|
+
/**
|
|
3878
|
+
* The Solution view (projects/solution-view). A second lens on the Files module showing the tree
|
|
3879
|
+
* as the build system sees it rather than as the filesystem lays it out.
|
|
3880
|
+
*
|
|
3881
|
+
* **Independent of the LSP family above, despite sharing the `code.` domain.** There is no
|
|
3882
|
+
* project-structure request in the Language Server Protocol — not one Otto has yet to wire, one
|
|
3883
|
+
* that does not exist — so this subsystem builds its own model through Microsoft's solution
|
|
3884
|
+
* libraries. Turning C# code intelligence off does not turn this off, and vice versa.
|
|
3885
|
+
*
|
|
3886
|
+
* Discovery is separate from loading on purpose: `list` decides whether the switcher appears at
|
|
3887
|
+
* all, so it runs for every workspace and must stay cheap (a directory walk, no process). Only
|
|
3888
|
+
* `get_tree` reaches the .NET sidecar.
|
|
3889
|
+
*
|
|
3890
|
+
* COMPAT(solutionView): added in v0.6.8; gate lives in features.solutionView.
|
|
3891
|
+
*/
|
|
3892
|
+
export const CodeSolutionListRequestSchema = z.object({
|
|
3893
|
+
type: z.literal("code.solution.list.request"),
|
|
3894
|
+
cwd: z.string(),
|
|
3895
|
+
requestId: z.string(),
|
|
3896
|
+
});
|
|
3897
|
+
/**
|
|
3898
|
+
* One solution's organisation: folders, the projects inside them, and the configurations. No file
|
|
3899
|
+
* membership — that is `load_project`, paid per project on expand, because evaluating fifty
|
|
3900
|
+
* projects to render a collapsed tree is the cost this design exists to avoid.
|
|
3901
|
+
*/
|
|
3902
|
+
export const CodeSolutionGetTreeRequestSchema = z.object({
|
|
3903
|
+
type: z.literal("code.solution.get_tree.request"),
|
|
3904
|
+
cwd: z.string(),
|
|
3905
|
+
/** Workspace-relative, as reported by `list`. */
|
|
3906
|
+
solutionPath: z.string(),
|
|
3907
|
+
requestId: z.string(),
|
|
3908
|
+
});
|
|
3909
|
+
/**
|
|
3910
|
+
* One project's evaluated file membership. `solutionPath` scopes the sidecar instance so two
|
|
3911
|
+
* solutions in one repo never share a warm `ProjectCollection` — and so Phase 4 has the selection
|
|
3912
|
+
* it needs for `--solution`.
|
|
3913
|
+
*/
|
|
3914
|
+
export const CodeSolutionLoadProjectRequestSchema = z.object({
|
|
3915
|
+
type: z.literal("code.solution.load_project.request"),
|
|
3916
|
+
cwd: z.string(),
|
|
3917
|
+
solutionPath: z.string(),
|
|
3918
|
+
/** Workspace-relative, or absolute when the solution names a project outside the workspace. */
|
|
3919
|
+
projectPath: z.string(),
|
|
3920
|
+
requestId: z.string(),
|
|
3921
|
+
});
|
|
3922
|
+
/**
|
|
3923
|
+
* Project-wide search ("Find in Files" semantics: explicit search, not
|
|
3924
|
+
* per-keystroke). Results stream as file.search.result events correlated by
|
|
3925
|
+
* searchId (= this requestId); a new search from the same session supersedes
|
|
3926
|
+
* any in-flight one.
|
|
2911
3927
|
*/
|
|
2912
3928
|
export const FileSearchRequestSchema = z.object({
|
|
2913
3929
|
type: z.literal("file.search.request"),
|
|
@@ -3091,6 +4107,7 @@ export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
3091
4107
|
DeleteAgentRequestMessageSchema,
|
|
3092
4108
|
ArchiveAgentRequestMessageSchema,
|
|
3093
4109
|
CloseItemsRequestMessageSchema,
|
|
4110
|
+
HistoryAgentsClearArchivedRequestSchema,
|
|
3094
4111
|
UpdateAgentRequestMessageSchema,
|
|
3095
4112
|
ProjectRenameRequestSchema,
|
|
3096
4113
|
ProjectRemoveRequestSchema,
|
|
@@ -3108,6 +4125,8 @@ export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
3108
4125
|
SetDaemonConfigRequestMessageSchema,
|
|
3109
4126
|
SpeechSettingsGetOptionsRequestSchema,
|
|
3110
4127
|
SpeechTtsPreviewRequestSchema,
|
|
4128
|
+
SpeechTtsSpeakRequestSchema,
|
|
4129
|
+
SpeechTtsSpeakCancelRequestSchema,
|
|
3111
4130
|
VisualizerVoiceCuesGenerateRequestSchema,
|
|
3112
4131
|
AgentPersonalitiesGetStatsRequestSchema,
|
|
3113
4132
|
ReadProjectConfigRequestMessageSchema,
|
|
@@ -3128,6 +4147,11 @@ export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
3128
4147
|
StatsActivityGetRequestMessageSchema,
|
|
3129
4148
|
ContextReportGetRequestMessageSchema,
|
|
3130
4149
|
ContextEdgeConvertRequestMessageSchema,
|
|
4150
|
+
ContextFindingsFixRequestMessageSchema,
|
|
4151
|
+
PersonalityMemoryListRequestMessageSchema,
|
|
4152
|
+
PersonalityMemoryUpdateRequestMessageSchema,
|
|
4153
|
+
PersonalityMemoryTransferRequestMessageSchema,
|
|
4154
|
+
PersonalityMemoryStatsRequestMessageSchema,
|
|
3131
4155
|
StatsActivityResetRequestMessageSchema,
|
|
3132
4156
|
UsageLogGetRequestMessageSchema,
|
|
3133
4157
|
AgentContextGetUsageRequestMessageSchema,
|
|
@@ -3152,6 +4176,9 @@ export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
3152
4176
|
TasksSuggestedDismissRequestMessageSchema,
|
|
3153
4177
|
AgentPersonalitySetRequestMessageSchema,
|
|
3154
4178
|
AgentRewindRequestMessageSchema,
|
|
4179
|
+
AgentQueueRemoveRequestMessageSchema,
|
|
4180
|
+
AgentQueueReorderRequestMessageSchema,
|
|
4181
|
+
AgentQueueClearRequestMessageSchema,
|
|
3155
4182
|
AgentPermissionResponseMessageSchema,
|
|
3156
4183
|
CheckoutStatusRequestSchema,
|
|
3157
4184
|
SubscribeCheckoutDiffRequestSchema,
|
|
@@ -3169,6 +4196,14 @@ export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
3169
4196
|
RunsGateRespondRequestSchema,
|
|
3170
4197
|
RunsCancelRequestSchema,
|
|
3171
4198
|
RunsClearRequestSchema,
|
|
4199
|
+
RunsDeleteRequestSchema,
|
|
4200
|
+
RunsGraphsListRequestSchema,
|
|
4201
|
+
RunsGraphsSaveRequestSchema,
|
|
4202
|
+
RunsGraphsDeleteRequestSchema,
|
|
4203
|
+
RunsTemplatesListRequestSchema,
|
|
4204
|
+
RunsTemplatesSaveRequestSchema,
|
|
4205
|
+
RunsTemplatesDeleteRequestSchema,
|
|
4206
|
+
RunsStartRequestSchema,
|
|
3172
4207
|
CheckoutMergeRequestSchema,
|
|
3173
4208
|
CheckoutMergeFromBaseRequestSchema,
|
|
3174
4209
|
CheckoutPullRequestSchema,
|
|
@@ -3203,7 +4238,14 @@ export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
3203
4238
|
LegacyOpenInEditorRequestSchema,
|
|
3204
4239
|
OpenProjectRequestSchema,
|
|
3205
4240
|
ProjectAddRequestSchema,
|
|
4241
|
+
ProjectScaffoldRequestSchema,
|
|
4242
|
+
HostingListRepositoriesRequestSchema,
|
|
4243
|
+
HostingListOwnersRequestSchema,
|
|
3206
4244
|
ArchiveWorkspaceRequestSchema,
|
|
4245
|
+
WorkspaceArchivePreflightRequestSchema,
|
|
4246
|
+
WorktreeBaseRefSetRequestSchema,
|
|
4247
|
+
WorktreeReattachListRequestSchema,
|
|
4248
|
+
WorktreeReattachRequestSchema,
|
|
3207
4249
|
WorkspaceCreateRequestSchema,
|
|
3208
4250
|
WorkspaceClearAttentionRequestSchema,
|
|
3209
4251
|
FileExplorerRequestSchema,
|
|
@@ -3211,6 +4253,10 @@ export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
3211
4253
|
FileDownloadTokenRequestSchema,
|
|
3212
4254
|
FileUploadRequestSchema,
|
|
3213
4255
|
FileWriteRequestSchema,
|
|
4256
|
+
FileCreateRequestSchema,
|
|
4257
|
+
FileDeleteRequestSchema,
|
|
4258
|
+
FileRenameRequestSchema,
|
|
4259
|
+
FileRefineRequestSchema,
|
|
3214
4260
|
FileWatchSubscribeRequestSchema,
|
|
3215
4261
|
FileWatchUnsubscribeRequestSchema,
|
|
3216
4262
|
FileSearchRequestSchema,
|
|
@@ -3218,6 +4264,19 @@ export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
3218
4264
|
CodeListFilesRequestSchema,
|
|
3219
4265
|
CodeSymbolsRequestSchema,
|
|
3220
4266
|
CodeOutlineRequestSchema,
|
|
4267
|
+
CodeDefinitionRequestSchema,
|
|
4268
|
+
CodeDocumentSyncRequestSchema,
|
|
4269
|
+
CodeDocumentCloseRequestSchema,
|
|
4270
|
+
CodeHoverRequestSchema,
|
|
4271
|
+
CodeReferencesRequestSchema,
|
|
4272
|
+
CodeRenamePreviewRequestSchema,
|
|
4273
|
+
CodeRenameApplyRequestSchema,
|
|
4274
|
+
CodeRenameUndoRequestSchema,
|
|
4275
|
+
LspServersListRequestSchema,
|
|
4276
|
+
LspServerStopRequestSchema,
|
|
4277
|
+
CodeSolutionListRequestSchema,
|
|
4278
|
+
CodeSolutionGetTreeRequestSchema,
|
|
4279
|
+
CodeSolutionLoadProjectRequestSchema,
|
|
3221
4280
|
ClearAgentAttentionMessageSchema,
|
|
3222
4281
|
ClientHeartbeatMessageSchema,
|
|
3223
4282
|
PingMessageSchema,
|
|
@@ -3425,6 +4484,12 @@ export const ServerInfoStatusPayloadSchema = z
|
|
|
3425
4484
|
projectRemove: z.boolean().optional(),
|
|
3426
4485
|
// COMPAT(projectAdd): added in v0.1.97, drop the gate when floor >= v0.1.97.
|
|
3427
4486
|
projectAdd: z.boolean().optional(),
|
|
4487
|
+
// COMPAT(projectScaffold): added in v0.6.9, drop the gate when floor >= v0.6.9.
|
|
4488
|
+
// The daemon can create a project directory from scratch (mkdir, git
|
|
4489
|
+
// init/clone, optional remote creation) instead of only adopting one
|
|
4490
|
+
// that already exists. Without it the New project page offers the
|
|
4491
|
+
// open-an-existing-folder path only.
|
|
4492
|
+
projectScaffold: z.boolean().optional(),
|
|
3428
4493
|
// COMPAT(worktreeRestore): added in v0.1.97, drop the gate when floor >= v0.1.97
|
|
3429
4494
|
worktreeRestore: z.boolean().optional(),
|
|
3430
4495
|
// COMPAT(providerUsageList): added in v0.1.98, drop the gate when daemon floor >= v0.1.98.
|
|
@@ -3453,6 +4518,25 @@ export const ServerInfoStatusPayloadSchema = z
|
|
|
3453
4518
|
retainedTranscripts: z.boolean().optional(),
|
|
3454
4519
|
// COMPAT(suggestedTasks): added in v0.5.6, drop the gate when daemon floor >= v0.5.6.
|
|
3455
4520
|
suggestedTasks: z.boolean().optional(),
|
|
4521
|
+
// COMPAT(steerQueue): added in v0.6.8, drop the gate when daemon floor >= v0.6.8.
|
|
4522
|
+
// Daemon owns a per-agent queue of steering messages, accepts
|
|
4523
|
+
// `delivery: "queue"` on send, reports `queuedMessages` on the agent
|
|
4524
|
+
// snapshot, and serves agent.queue.remove/clear. Without it the
|
|
4525
|
+
// composer keeps its own local queue — that is the pre-existing
|
|
4526
|
+
// behavior, not a degraded build of this feature.
|
|
4527
|
+
steerQueue: z.boolean().optional(),
|
|
4528
|
+
// Daemon serves agent.queue.reorder. Separate from `steerQueue`
|
|
4529
|
+
// because a daemon on 0.6.8 owns a queue but cannot re-order it;
|
|
4530
|
+
// without this the move controls are absent (the queue still works).
|
|
4531
|
+
// COMPAT(steerQueueReorder): added in v0.6.9, drop the gate when daemon floor >= v0.6.9.
|
|
4532
|
+
steerQueueReorder: z.boolean().optional(),
|
|
4533
|
+
// Daemon reports `cumulativeUsage` (the lifetime in/cached/out split
|
|
4534
|
+
// plus its own booked cost) on every agent snapshot, so a chat's total
|
|
4535
|
+
// spend can be summed and priced honestly. Without it the client shows
|
|
4536
|
+
// token totals only and no cost — NOT an estimated cost, which is the
|
|
4537
|
+
// behavior this feature exists to remove.
|
|
4538
|
+
// COMPAT(cumulativeUsage): added in v0.7.0, drop the gate when daemon floor >= v0.7.0.
|
|
4539
|
+
cumulativeUsage: z.boolean().optional(),
|
|
3456
4540
|
// Daemon can resolve and evaluate the provider's context graph, serve
|
|
3457
4541
|
// context.report.* and push context_report_changed. Without it the
|
|
3458
4542
|
// client hides both the Context Management tab and the composer
|
|
@@ -3462,10 +4546,38 @@ export const ServerInfoStatusPayloadSchema = z
|
|
|
3462
4546
|
contextManagement: z.boolean().optional(),
|
|
3463
4547
|
// COMPAT(textEditor): added in v0.4.4, drop the gate when daemon floor >= v0.4.4.
|
|
3464
4548
|
textEditor: z.boolean().optional(),
|
|
4549
|
+
// Refine — the daemon can turn a pinned document plus an instruction
|
|
4550
|
+
// into a proposed rewrite (`file.refine.*`). Without it the Refine
|
|
4551
|
+
// entry is absent: there is no client-side substitute for a model, and
|
|
4552
|
+
// a degraded "open a chat instead" path is exactly the unreviewed edit
|
|
4553
|
+
// Refine exists to replace.
|
|
4554
|
+
// COMPAT(refine): added in v0.6.9, drop the gate when daemon floor >= v0.6.9.
|
|
4555
|
+
refine: z.boolean().optional(),
|
|
4556
|
+
// Personality memory — the daemon stores per-personality lessons, injects
|
|
4557
|
+
// them at spawn, and serves personality.memory.*. Without it the client
|
|
4558
|
+
// hides the Memory tab, the accrual indicator and the transfer-on-delete
|
|
4559
|
+
// choice: storage is daemon-side by definition, so there is nothing a
|
|
4560
|
+
// client-side fallback could read.
|
|
4561
|
+
// COMPAT(personalityMemory): added in v0.7.0, drop the gate when daemon floor >= v0.7.0.
|
|
4562
|
+
personalityMemory: z.boolean().optional(),
|
|
3465
4563
|
// COMPAT(projectSearch): added in v0.4.4, drop the gate when daemon floor >= v0.4.4.
|
|
3466
4564
|
projectSearch: z.boolean().optional(),
|
|
3467
4565
|
// COMPAT(codeIndex): added in v0.4.4, drop the gate when daemon floor >= v0.4.4.
|
|
3468
4566
|
codeIndex: z.boolean().optional(),
|
|
4567
|
+
// Language-server-backed definitions (`code.definition`, `code.document.*`).
|
|
4568
|
+
// Separate from `codeIndex`: that gate covers the ctags path, which stays as
|
|
4569
|
+
// the outline/fuzzy-finder source and the no-server fallback.
|
|
4570
|
+
// COMPAT(lsp): added in v0.6.8, drop the gate when daemon floor >= v0.6.8.
|
|
4571
|
+
lsp: z.boolean().optional(),
|
|
4572
|
+
// The Solution view — the daemon can discover solutions and serve
|
|
4573
|
+
// `code.solution.*`. Deliberately NOT implied by `lsp`: there is no
|
|
4574
|
+
// project-structure request in LSP, so this subsystem is independent of
|
|
4575
|
+
// language servers and of the C# row's on/off state. Without the flag the
|
|
4576
|
+
// client never shows the view switcher and never asks — there is no
|
|
4577
|
+
// client-side substitute for reading a solution, and a hand-parsed
|
|
4578
|
+
// half-tree is exactly the mistake this design exists to avoid.
|
|
4579
|
+
// COMPAT(solutionView): added in v0.6.8, drop the gate when daemon floor >= v0.6.8.
|
|
4580
|
+
solutionView: z.boolean().optional(),
|
|
3469
4581
|
// COMPAT(artifactsToolGroup): added in v0.4.5, drop the gate when daemon floor >= v0.4.5.
|
|
3470
4582
|
artifactsToolGroup: z.boolean().optional(),
|
|
3471
4583
|
// COMPAT(speechSettings): added in v0.4.5, drop the gate when daemon floor >= v0.4.5.
|
|
@@ -3476,6 +4588,9 @@ export const ServerInfoStatusPayloadSchema = z
|
|
|
3476
4588
|
agentPersonalities: z.boolean().optional(),
|
|
3477
4589
|
// COMPAT(ttsPreview): added in v0.4.7, drop the gate when daemon floor >= v0.4.7.
|
|
3478
4590
|
ttsPreview: z.boolean().optional(),
|
|
4591
|
+
// COMPAT(ttsSpeak): added in v0.6.7, drop the gate when daemon floor >= v0.6.7.
|
|
4592
|
+
// Host can stream a full message aloud on demand (per-message playback).
|
|
4593
|
+
ttsSpeak: z.boolean().optional(),
|
|
3479
4594
|
// COMPAT(visualizerVoiceCues): added in v0.6.3, drop the gate when daemon floor >= v0.6.3.
|
|
3480
4595
|
visualizerVoiceCues: z.boolean().optional(),
|
|
3481
4596
|
// COMPAT(setAgentPersonality): added in v0.5.0, drop the gate when daemon floor >= v0.5.0.
|
|
@@ -3494,6 +4609,27 @@ export const ServerInfoStatusPayloadSchema = z
|
|
|
3494
4609
|
// once.
|
|
3495
4610
|
// COMPAT(checkoutGitFileHistory): added in v0.6.6, drop the gate when daemon floor >= v0.6.6.
|
|
3496
4611
|
checkoutGitFileHistory: z.boolean().optional(),
|
|
4612
|
+
// Set when the daemon can inspect a worktree's leftover branch before
|
|
4613
|
+
// archiving (workspace.archive.preflight.*) and delete it as part of the
|
|
4614
|
+
// archive (archive_workspace_request.branchDisposition). Without it the
|
|
4615
|
+
// client archives the worktree exactly as before and never offers to
|
|
4616
|
+
// remove the branch — no degraded client-side branch detection exists.
|
|
4617
|
+
// COMPAT(worktreeArchiveBranchCleanup): added in v0.6.7, drop the gate when daemon floor >= v0.6.7.
|
|
4618
|
+
worktreeArchiveBranchCleanup: z.boolean().optional(),
|
|
4619
|
+
// COMPAT(worktreeReattach): added in v0.6.7, drop the gate when daemon floor >= v0.6.7.
|
|
4620
|
+
worktreeReattach: z.boolean().optional(),
|
|
4621
|
+
// Set when the daemon can repoint a worktree's stored base branch
|
|
4622
|
+
// (worktree.baseRef.set.*). Without it the client renders the base as a
|
|
4623
|
+
// read-only "vs <base>" label — there is no client-side override, since only
|
|
4624
|
+
// the daemon can write the worktree's metadata.
|
|
4625
|
+
// COMPAT(worktreeDiffBase): added in v0.6.8, drop the gate when daemon floor >= v0.6.8.
|
|
4626
|
+
worktreeDiffBase: z.boolean().optional(),
|
|
4627
|
+
// Set when the daemon persists the host-level hideMergeIntoBaseAction
|
|
4628
|
+
// workspace policy (read/written via the daemon config RPCs). Without
|
|
4629
|
+
// it the client hides the Workspaces toggle, since patching the field
|
|
4630
|
+
// on an old daemon would silently fail to stick.
|
|
4631
|
+
// COMPAT(hideMergeIntoBaseSetting): added in v0.6.7, drop the gate when daemon floor >= v0.6.7.
|
|
4632
|
+
hideMergeIntoBaseSetting: z.boolean().optional(),
|
|
3497
4633
|
// COMPAT(agentTeams): added in v0.5.2, drop the gate when daemon floor >= v0.5.2.
|
|
3498
4634
|
agentTeams: z.boolean().optional(),
|
|
3499
4635
|
// COMPAT(modelTierOverrides): added in v0.5.2, drop the gate when daemon floor >= v0.5.2.
|
|
@@ -3506,6 +4642,14 @@ export const ServerInfoStatusPayloadSchema = z
|
|
|
3506
4642
|
activityStats: z.boolean().optional(),
|
|
3507
4643
|
// COMPAT(runsClear): added in v0.5.3, drop the gate when daemon floor >= v0.5.3.
|
|
3508
4644
|
runsClear: z.boolean().optional(),
|
|
4645
|
+
// COMPAT(runsDelete): added in v0.6.8, drop the gate when daemon floor >= v0.6.8.
|
|
4646
|
+
runsDelete: z.boolean().optional(),
|
|
4647
|
+
// COMPAT(runsDraftEdit): added in v0.6.8, drop the gate when daemon floor >= v0.6.8.
|
|
4648
|
+
// The daemon accepts `runs.start` with `draft: true` AND a `runId`,
|
|
4649
|
+
// re-saving that draft in place instead of minting a second one.
|
|
4650
|
+
runsDraftEdit: z.boolean().optional(),
|
|
4651
|
+
// COMPAT(orchestrationGraphs): added in v0.6.7, drop the gate when daemon floor >= v0.6.7.
|
|
4652
|
+
orchestrationGraphs: z.boolean().optional(),
|
|
3509
4653
|
// COMPAT(projectLinks): added in v0.5.6, drop the gate when daemon floor >= v0.5.6.
|
|
3510
4654
|
projectLinks: z.boolean().optional(),
|
|
3511
4655
|
// COMPAT(fileOutsideWorkspace): added in v0.5.8, drop the gate when daemon floor >= v0.5.8.
|
|
@@ -3561,6 +4705,22 @@ export const ServerInfoStatusPayloadSchema = z
|
|
|
3561
4705
|
// counters + the itemized ledger). The client gates the Metrics screen's
|
|
3562
4706
|
// "Reset" button on this; an old daemon simply doesn't offer it.
|
|
3563
4707
|
statsReset: z.boolean().optional(),
|
|
4708
|
+
// COMPAT(historyDelete): added in v0.7.0, drop the gate when daemon floor >= v0.7.0.
|
|
4709
|
+
// Set when the daemon offers hard delete for chat records: per-row via
|
|
4710
|
+
// the existing `delete_agent_request`, and in bulk via
|
|
4711
|
+
// `history.agents.clear_archived`. Archive has always been a soft delete
|
|
4712
|
+
// with no counterpart; this is the counterpart. Deleting removes Otto's
|
|
4713
|
+
// record only — provider transcripts are never touched (see the
|
|
4714
|
+
// clear_archived schema). The client hides both affordances when this is
|
|
4715
|
+
// absent rather than shipping a degraded path.
|
|
4716
|
+
historyDelete: z.boolean().optional(),
|
|
4717
|
+
// COMPAT(fileMutations): added in v0.7.0, drop the gate when daemon floor >= v0.7.0.
|
|
4718
|
+
// Set when the daemon serves `file.create`, `file.delete` and
|
|
4719
|
+
// `file.rename` — creating, removing and moving entries, as opposed to
|
|
4720
|
+
// `file.write`, which only changes what is inside an existing file.
|
|
4721
|
+
// There is no client-side substitute (the client never touches the
|
|
4722
|
+
// filesystem), so an old daemon simply does not get the menu items.
|
|
4723
|
+
fileMutations: z.boolean().optional(),
|
|
3564
4724
|
})
|
|
3565
4725
|
.optional(),
|
|
3566
4726
|
})
|
|
@@ -3643,7 +4803,70 @@ export const DaemonConfigChangedStatusPayloadSchema = z
|
|
|
3643
4803
|
config: MutableDaemonConfigSchema,
|
|
3644
4804
|
})
|
|
3645
4805
|
.passthrough();
|
|
4806
|
+
/**
|
|
4807
|
+
* Which workspaces currently have a language server starting up or indexing. Sent as
|
|
4808
|
+
* the whole busy set rather than per-workspace transitions: the only consumer is a
|
|
4809
|
+
* spinner, so an idempotent snapshot cannot drift out of sync the way a missed
|
|
4810
|
+
* transition would.
|
|
4811
|
+
*
|
|
4812
|
+
* Separate from the workspace status bucket on purpose — indexing is not the workspace
|
|
4813
|
+
* "working", and folding it in would mislabel a quiet workspace as busy with agent work.
|
|
4814
|
+
*/
|
|
4815
|
+
export const LspActivityChangedStatusPayloadSchema = z
|
|
4816
|
+
.object({
|
|
4817
|
+
status: z.literal("lsp_activity_changed"),
|
|
4818
|
+
/** Absolute workspace roots with language-server work in flight. */
|
|
4819
|
+
busyRoots: z.array(z.string()),
|
|
4820
|
+
})
|
|
4821
|
+
.passthrough();
|
|
4822
|
+
/**
|
|
4823
|
+
* Compiler severity, named rather than numbered. LSP uses 1–4; a magic number on the
|
|
4824
|
+
* wire would have every consumer re-deriving which one is a warning.
|
|
4825
|
+
*/
|
|
4826
|
+
export const CodeDiagnosticSeveritySchema = z.enum(["error", "warning", "info", "hint"]);
|
|
4827
|
+
/** One problem the language server reported, 1-based like every other position. */
|
|
4828
|
+
export const CodeDiagnosticSchema = z.object({
|
|
4829
|
+
line: z.number().int().positive(),
|
|
4830
|
+
column: z.number().int().positive(),
|
|
4831
|
+
endLine: z.number().int().positive(),
|
|
4832
|
+
endColumn: z.number().int().positive(),
|
|
4833
|
+
severity: CodeDiagnosticSeveritySchema,
|
|
4834
|
+
message: z.string(),
|
|
4835
|
+
/** Who says so — `ts`, `pyright`, a linter behind the server. */
|
|
4836
|
+
source: z.string().optional(),
|
|
4837
|
+
/** The server's own code for the rule or error, e.g. TypeScript's `2345`. */
|
|
4838
|
+
code: z.string().optional(),
|
|
4839
|
+
/** Documentation for that rule, when the server offers one — oxlint does. */
|
|
4840
|
+
codeHref: z.string().optional(),
|
|
4841
|
+
/** Which registry row published it, so two servers on one file stay attributable. */
|
|
4842
|
+
serverId: z.string().optional(),
|
|
4843
|
+
});
|
|
4844
|
+
/**
|
|
4845
|
+
* Diagnostics for one open document, pushed unsolicited.
|
|
4846
|
+
*
|
|
4847
|
+
* This is the one part of code intelligence that is not request/response:
|
|
4848
|
+
* `textDocument/publishDiagnostics` arrives whenever the server has recomputed, which is
|
|
4849
|
+
* whenever it feels like it. So it is a status broadcast, and the payload is the document's
|
|
4850
|
+
* **whole** current set — never a delta. A missed delta would leave a stale squiggle on a
|
|
4851
|
+
* line the user already fixed, and an idempotent snapshot cannot drift.
|
|
4852
|
+
*
|
|
4853
|
+
* Only documents a client has synced produce these. A server may know about every file in
|
|
4854
|
+
* the project; pushing all of it would be unbounded, and nothing can render a marker in a
|
|
4855
|
+
* file that is not open.
|
|
4856
|
+
*/
|
|
4857
|
+
export const LspDiagnosticsChangedStatusPayloadSchema = z
|
|
4858
|
+
.object({
|
|
4859
|
+
status: z.literal("lsp_diagnostics_changed"),
|
|
4860
|
+
/** Workspace root the document belongs to. */
|
|
4861
|
+
cwd: z.string(),
|
|
4862
|
+
/** Absolute path of the document these describe. */
|
|
4863
|
+
path: z.string(),
|
|
4864
|
+
diagnostics: z.array(CodeDiagnosticSchema),
|
|
4865
|
+
})
|
|
4866
|
+
.passthrough();
|
|
3646
4867
|
export const KnownStatusPayloadSchema = z.discriminatedUnion("status", [
|
|
4868
|
+
LspActivityChangedStatusPayloadSchema,
|
|
4869
|
+
LspDiagnosticsChangedStatusPayloadSchema,
|
|
3647
4870
|
AgentCreatedStatusPayloadSchema,
|
|
3648
4871
|
AgentCreateFailedStatusPayloadSchema,
|
|
3649
4872
|
AgentResumedStatusPayloadSchema,
|
|
@@ -3968,6 +5191,22 @@ export const WorkspaceUpdateMessageSchema = z.object({
|
|
|
3968
5191
|
}),
|
|
3969
5192
|
]),
|
|
3970
5193
|
});
|
|
5194
|
+
// A project's own metadata changed (today: the user renamed it). The workspace
|
|
5195
|
+
// channel can only carry a project's name inside its workspaces' descriptors, so
|
|
5196
|
+
// a project with no active workspaces had no live channel at all — its name only
|
|
5197
|
+
// refreshed on the next full workspace fetch. This is the project-level channel:
|
|
5198
|
+
// it fires whether or not the project currently has workspaces, and the daemon
|
|
5199
|
+
// fans it out to every connected session because project metadata is host-global.
|
|
5200
|
+
export const ProjectUpdatedNotificationSchema = z.object({
|
|
5201
|
+
type: z.literal("project.updated.notification"),
|
|
5202
|
+
payload: z.object({
|
|
5203
|
+
project: WorkspaceProjectDescriptorPayloadSchema,
|
|
5204
|
+
// False means the project has no active workspaces right now, so the client
|
|
5205
|
+
// keeps it in the empty-project bucket instead of expecting a workspace
|
|
5206
|
+
// descriptor to carry its name.
|
|
5207
|
+
hasActiveWorkspaces: z.boolean(),
|
|
5208
|
+
}),
|
|
5209
|
+
});
|
|
3971
5210
|
export const ScriptStatusUpdateMessageSchema = z.object({
|
|
3972
5211
|
type: z.literal("script_status_update"),
|
|
3973
5212
|
payload: z.object({
|
|
@@ -4016,6 +5255,89 @@ export const ProjectAddResponseSchema = z.object({
|
|
|
4016
5255
|
errorCode: z.enum(["directory_not_found"]).nullish().catch(null),
|
|
4017
5256
|
}),
|
|
4018
5257
|
});
|
|
5258
|
+
// COMPAT(projectScaffold): added in v0.6.9.
|
|
5259
|
+
export const ProjectScaffoldResponseSchema = z.object({
|
|
5260
|
+
type: z.literal("project.scaffold.response"),
|
|
5261
|
+
payload: z.object({
|
|
5262
|
+
requestId: z.string(),
|
|
5263
|
+
// Registered project on success. Null whenever any step failed — the
|
|
5264
|
+
// daemon does not register a half-built directory.
|
|
5265
|
+
project: WorkspaceProjectDescriptorPayloadSchema.nullable(),
|
|
5266
|
+
// Absolute path of the created directory. Non-null even on a late failure
|
|
5267
|
+
// (e.g. push rejected) so the UI can tell the user what is on disk.
|
|
5268
|
+
path: z.string().nullable(),
|
|
5269
|
+
// Remote the repo was wired to, when one was created or cloned from.
|
|
5270
|
+
remoteUrl: z.string().nullable(),
|
|
5271
|
+
error: z.string().nullable(),
|
|
5272
|
+
// Unknown codes from newer daemons degrade to null; clients fall back to `error`.
|
|
5273
|
+
errorCode: z
|
|
5274
|
+
.enum([
|
|
5275
|
+
"parent_not_found",
|
|
5276
|
+
"invalid_name",
|
|
5277
|
+
"already_exists",
|
|
5278
|
+
"git_unavailable",
|
|
5279
|
+
"git_failed",
|
|
5280
|
+
"provider_unavailable",
|
|
5281
|
+
"remote_failed",
|
|
5282
|
+
"clone_failed",
|
|
5283
|
+
"register_failed",
|
|
5284
|
+
])
|
|
5285
|
+
.nullish()
|
|
5286
|
+
.catch(null),
|
|
5287
|
+
// Terminal state of every step the daemon ran, in run order.
|
|
5288
|
+
steps: z.array(ProjectScaffoldStepSchema),
|
|
5289
|
+
}),
|
|
5290
|
+
});
|
|
5291
|
+
// Uncorrelated progress stream for an in-flight scaffold, keyed by the request's
|
|
5292
|
+
// requestId. Purely advisory: the response carries the authoritative step list,
|
|
5293
|
+
// so a client that ignores these still gets a correct result.
|
|
5294
|
+
export const ProjectScaffoldProgressSchema = z.object({
|
|
5295
|
+
type: z.literal("project.scaffold.progress"),
|
|
5296
|
+
payload: z.object({
|
|
5297
|
+
requestId: z.string(),
|
|
5298
|
+
step: ProjectScaffoldStepIdSchema,
|
|
5299
|
+
status: ProjectScaffoldStepStatusSchema,
|
|
5300
|
+
detail: z.string().nullable(),
|
|
5301
|
+
}),
|
|
5302
|
+
});
|
|
5303
|
+
export const HostingRepositorySummarySchema = z.object({
|
|
5304
|
+
// Provider-unique identifier, e.g. "owner/name" or "workspace/slug".
|
|
5305
|
+
fullName: z.string(),
|
|
5306
|
+
name: z.string(),
|
|
5307
|
+
owner: z.string(),
|
|
5308
|
+
cloneUrl: z.string(),
|
|
5309
|
+
isPrivate: z.boolean(),
|
|
5310
|
+
description: z.string().nullable(),
|
|
5311
|
+
// ISO-8601. Clients sort most-recent-first when present.
|
|
5312
|
+
updatedAt: z.string().nullable(),
|
|
5313
|
+
});
|
|
5314
|
+
export const HostingOwnerSummarySchema = z.object({
|
|
5315
|
+
// Value to send back as `owner` when creating a repository.
|
|
5316
|
+
id: z.string(),
|
|
5317
|
+
label: z.string(),
|
|
5318
|
+
// Open string: providers name this differently (org, workspace, team).
|
|
5319
|
+
kind: z.string(),
|
|
5320
|
+
});
|
|
5321
|
+
// COMPAT(projectScaffold): added in v0.6.9.
|
|
5322
|
+
export const HostingListRepositoriesResponseSchema = z.object({
|
|
5323
|
+
type: z.literal("hosting.list_repositories.response"),
|
|
5324
|
+
payload: z.object({
|
|
5325
|
+
requestId: z.string(),
|
|
5326
|
+
provider: GitHostingProviderIdWireSchema,
|
|
5327
|
+
repositories: z.array(HostingRepositorySummarySchema),
|
|
5328
|
+
error: z.string().nullable(),
|
|
5329
|
+
}),
|
|
5330
|
+
});
|
|
5331
|
+
// COMPAT(projectScaffold): added in v0.6.9.
|
|
5332
|
+
export const HostingListOwnersResponseSchema = z.object({
|
|
5333
|
+
type: z.literal("hosting.list_owners.response"),
|
|
5334
|
+
payload: z.object({
|
|
5335
|
+
requestId: z.string(),
|
|
5336
|
+
provider: GitHostingProviderIdWireSchema,
|
|
5337
|
+
owners: z.array(HostingOwnerSummarySchema),
|
|
5338
|
+
error: z.string().nullable(),
|
|
5339
|
+
}),
|
|
5340
|
+
});
|
|
4019
5341
|
export const StartWorkspaceScriptResponseMessageSchema = z.object({
|
|
4020
5342
|
type: z.literal("start_workspace_script_response"),
|
|
4021
5343
|
payload: z.object({
|
|
@@ -4052,6 +5374,92 @@ export const ArchiveWorkspaceResponseMessageSchema = z.object({
|
|
|
4052
5374
|
workspaceId: z.string(),
|
|
4053
5375
|
archivedAt: z.string().nullable(),
|
|
4054
5376
|
error: z.string().nullable(),
|
|
5377
|
+
// COMPAT(worktreeArchiveBranchCleanup): added in v0.6.7. The name of the
|
|
5378
|
+
// local branch the daemon deleted as part of this archive (when the request
|
|
5379
|
+
// asked for branchDisposition: "delete" and the branch was actually
|
|
5380
|
+
// removed), else null/absent. Old daemons omit it.
|
|
5381
|
+
deletedBranch: z.string().nullable().optional(),
|
|
5382
|
+
}),
|
|
5383
|
+
});
|
|
5384
|
+
// Whether/how a worktree-backed workspace's local branch can be cleaned up when
|
|
5385
|
+
// the workspace is archived. See WorkspaceArchivePreflightRequestSchema.
|
|
5386
|
+
export const WorktreeArchiveBranchDetectionSchema = z.object({
|
|
5387
|
+
// True only for Otto-owned worktrees whose branch we can offer to delete.
|
|
5388
|
+
// False for local checkouts, plain directories, and non-owned worktrees — the
|
|
5389
|
+
// client then skips the branch-cleanup UI entirely.
|
|
5390
|
+
isOttoWorktree: z.boolean(),
|
|
5391
|
+
// The local branch checked out in the worktree, or null when detached/unknown.
|
|
5392
|
+
branchName: z.string().nullable(),
|
|
5393
|
+
// The base ref the branch was created from (origin/ stripped), or null.
|
|
5394
|
+
baseBranch: z.string().nullable(),
|
|
5395
|
+
mergeState: z.enum(["merged", "unmerged", "unknown"]),
|
|
5396
|
+
// Commits on the branch not contained in the base ref; null when unknown.
|
|
5397
|
+
unmergedCommitCount: z.number().int().nonnegative().nullable(),
|
|
5398
|
+
// A matching origin/<branch> exists — deleting the local branch keeps the
|
|
5399
|
+
// remote copy. Purely informational for the confirmation copy.
|
|
5400
|
+
hasRemoteBranch: z.boolean(),
|
|
5401
|
+
// The branch is checked out in another worktree too, so git will refuse to
|
|
5402
|
+
// delete it even after this worktree is removed. The client hides the option.
|
|
5403
|
+
branchCheckedOutElsewhere: z.boolean(),
|
|
5404
|
+
// Archiving will actually remove the backing directory (this is the last
|
|
5405
|
+
// active workspace referencing it). Branch cleanup is only offered when true.
|
|
5406
|
+
directoryWillBeRemoved: z.boolean(),
|
|
5407
|
+
});
|
|
5408
|
+
export const WorkspaceArchivePreflightResponseSchema = z.object({
|
|
5409
|
+
type: z.literal("workspace.archive.preflight.response"),
|
|
5410
|
+
payload: z.object({
|
|
5411
|
+
requestId: z.string(),
|
|
5412
|
+
workspaceId: z.string(),
|
|
5413
|
+
// Null when detection failed (see error) or the workspace is gone.
|
|
5414
|
+
detection: WorktreeArchiveBranchDetectionSchema.nullable(),
|
|
5415
|
+
error: z.string().nullable(),
|
|
5416
|
+
}),
|
|
5417
|
+
});
|
|
5418
|
+
// COMPAT(worktreeDiffBase): added in v0.6.8.
|
|
5419
|
+
export const WorktreeBaseRefSetResponseSchema = z.object({
|
|
5420
|
+
type: z.literal("worktree.baseRef.set.response"),
|
|
5421
|
+
payload: z.object({
|
|
5422
|
+
requestId: z.string(),
|
|
5423
|
+
workspaceId: z.string(),
|
|
5424
|
+
// The stored base branch after the write; null when the write failed.
|
|
5425
|
+
baseRef: z.string().nullable(),
|
|
5426
|
+
// The stored base is the repository default branch (no stacked-branch override).
|
|
5427
|
+
isDefault: z.boolean(),
|
|
5428
|
+
error: z.string().nullable(),
|
|
5429
|
+
}),
|
|
5430
|
+
});
|
|
5431
|
+
// A re-attachable Otto worktree surfaced by worktree.reattach.list.
|
|
5432
|
+
// COMPAT(worktreeReattach): added in v0.6.7.
|
|
5433
|
+
export const WorktreeReattachCandidateSchema = z.object({
|
|
5434
|
+
// Present when an archived workspace record still backs this worktree; null for
|
|
5435
|
+
// an orphaned on-disk worktree with no record. The reattach request keys off
|
|
5436
|
+
// whichever identity is available.
|
|
5437
|
+
workspaceId: z.string().nullable(),
|
|
5438
|
+
worktreePath: z.string(),
|
|
5439
|
+
branchName: z.string().nullable(),
|
|
5440
|
+
baseBranch: z.string().nullable(),
|
|
5441
|
+
// The worktree directory currently exists on disk. False means the record was
|
|
5442
|
+
// archived away and the directory must be recreated from the branch on reattach.
|
|
5443
|
+
directoryOnDisk: z.boolean(),
|
|
5444
|
+
// The workspace's human name when we have a record, else null.
|
|
5445
|
+
displayName: z.string().nullable(),
|
|
5446
|
+
archivedAt: z.string().nullable(),
|
|
5447
|
+
});
|
|
5448
|
+
export const WorktreeReattachListResponseSchema = z.object({
|
|
5449
|
+
type: z.literal("worktree.reattach.list.response"),
|
|
5450
|
+
payload: z.object({
|
|
5451
|
+
requestId: z.string(),
|
|
5452
|
+
candidates: z.array(WorktreeReattachCandidateSchema),
|
|
5453
|
+
error: z.string().nullable(),
|
|
5454
|
+
}),
|
|
5455
|
+
});
|
|
5456
|
+
export const WorktreeReattachResponseSchema = z.object({
|
|
5457
|
+
type: z.literal("worktree.reattach.response"),
|
|
5458
|
+
payload: z.object({
|
|
5459
|
+
requestId: z.string(),
|
|
5460
|
+
// The revived/created workspace descriptor, or null on error.
|
|
5461
|
+
workspace: WorkspaceDescriptorPayloadSchema.nullable(),
|
|
5462
|
+
error: z.string().nullable(),
|
|
4055
5463
|
}),
|
|
4056
5464
|
});
|
|
4057
5465
|
export const FetchAgentResponseMessageSchema = z.object({
|
|
@@ -4112,6 +5520,52 @@ export const AgentForkContextResponseMessageSchema = z.object({
|
|
|
4112
5520
|
error: z.string().nullable(),
|
|
4113
5521
|
}),
|
|
4114
5522
|
});
|
|
5523
|
+
export const AgentQueueRemoveResponseMessageSchema = z.object({
|
|
5524
|
+
type: z.literal("agent.queue.remove.response"),
|
|
5525
|
+
payload: z.object({
|
|
5526
|
+
requestId: z.string(),
|
|
5527
|
+
agentId: z.string(),
|
|
5528
|
+
/**
|
|
5529
|
+
* The removed message's text, handed back so the composer can put it back
|
|
5530
|
+
* in the box for editing or re-send it right away. Null when the id was
|
|
5531
|
+
* already gone — the turn drained it while the tap was in flight.
|
|
5532
|
+
* Attachments are not echoed: the client that queued the message keeps its
|
|
5533
|
+
* own local copy keyed by `id` (see the composer's queued-attachment
|
|
5534
|
+
* sidecar), and a client that never queued it has nothing to restore.
|
|
5535
|
+
*/
|
|
5536
|
+
removed: z
|
|
5537
|
+
.object({
|
|
5538
|
+
id: z.string(),
|
|
5539
|
+
text: z.string(),
|
|
5540
|
+
})
|
|
5541
|
+
.nullable(),
|
|
5542
|
+
error: z.string().nullable(),
|
|
5543
|
+
}),
|
|
5544
|
+
});
|
|
5545
|
+
export const AgentQueueReorderResponseMessageSchema = z.object({
|
|
5546
|
+
type: z.literal("agent.queue.reorder.response"),
|
|
5547
|
+
payload: z.object({
|
|
5548
|
+
requestId: z.string(),
|
|
5549
|
+
agentId: z.string(),
|
|
5550
|
+
/**
|
|
5551
|
+
* False when the id was already gone (the turn drained it while the tap was
|
|
5552
|
+
* in flight) or the entry was already at that position. The authoritative
|
|
5553
|
+
* order arrives on the agent snapshot either way, so a client only needs
|
|
5554
|
+
* this to decide whether to surface an error.
|
|
5555
|
+
*/
|
|
5556
|
+
moved: z.boolean(),
|
|
5557
|
+
error: z.string().nullable(),
|
|
5558
|
+
}),
|
|
5559
|
+
});
|
|
5560
|
+
export const AgentQueueClearResponseMessageSchema = z.object({
|
|
5561
|
+
type: z.literal("agent.queue.clear.response"),
|
|
5562
|
+
payload: z.object({
|
|
5563
|
+
requestId: z.string(),
|
|
5564
|
+
agentId: z.string(),
|
|
5565
|
+
clearedCount: z.number().int().nonnegative(),
|
|
5566
|
+
error: z.string().nullable(),
|
|
5567
|
+
}),
|
|
5568
|
+
});
|
|
4115
5569
|
export const CancelAgentResponseMessageSchema = z.object({
|
|
4116
5570
|
type: z.literal("cancel_agent_response"),
|
|
4117
5571
|
payload: z.object({
|
|
@@ -4166,6 +5620,13 @@ export const SendAgentMessageResponseMessageSchema = z.object({
|
|
|
4166
5620
|
agentId: z.string(),
|
|
4167
5621
|
accepted: z.boolean(),
|
|
4168
5622
|
error: z.string().nullable(),
|
|
5623
|
+
// Set when the message was parked for the next turn rather than dispatched
|
|
5624
|
+
// (`delivery: "queue"` against a busy agent). `queuedMessageId` is the
|
|
5625
|
+
// entry's id in `AgentSnapshotPayload.queuedMessages` — the key the sender
|
|
5626
|
+
// uses to find its own entry again. Absent ⇒ dispatched now (or old daemon).
|
|
5627
|
+
// COMPAT(steerQueue): added in v0.6.8, drop the gate when floor >= v0.6.8.
|
|
5628
|
+
queued: z.boolean().optional(),
|
|
5629
|
+
queuedMessageId: z.string().optional(),
|
|
4169
5630
|
}),
|
|
4170
5631
|
});
|
|
4171
5632
|
export const WaitForFinishResponseMessageSchema = z.object({
|
|
@@ -4243,6 +5704,23 @@ export const SpeechTtsPreviewResponseSchema = z.object({
|
|
|
4243
5704
|
})
|
|
4244
5705
|
.passthrough(),
|
|
4245
5706
|
});
|
|
5707
|
+
export const SpeechTtsSpeakResponseSchema = z.object({
|
|
5708
|
+
type: z.literal("speech.tts.speak.response"),
|
|
5709
|
+
payload: z
|
|
5710
|
+
.object({
|
|
5711
|
+
requestId: z.string(),
|
|
5712
|
+
// True when the full message played to completion; absent/false when it was
|
|
5713
|
+
// canceled or produced no audio. `error` carries a human-readable failure.
|
|
5714
|
+
ok: z.boolean().optional(),
|
|
5715
|
+
canceled: z.boolean().optional(),
|
|
5716
|
+
error: z.string().optional(),
|
|
5717
|
+
})
|
|
5718
|
+
.passthrough(),
|
|
5719
|
+
});
|
|
5720
|
+
export const SpeechTtsSpeakCancelResponseSchema = z.object({
|
|
5721
|
+
type: z.literal("speech.tts.speak.cancel.response"),
|
|
5722
|
+
payload: z.object({ requestId: z.string() }).passthrough(),
|
|
5723
|
+
});
|
|
4246
5724
|
export const VisualizerVoiceCuesGenerateResponseSchema = z.object({
|
|
4247
5725
|
type: z.literal("visualizer.voiceCues.generate.response"),
|
|
4248
5726
|
payload: z
|
|
@@ -4417,6 +5895,12 @@ const CheckoutStatusCommonSchema = z.object({
|
|
|
4417
5895
|
cwd: z.string(),
|
|
4418
5896
|
error: CheckoutErrorSchema.nullable(),
|
|
4419
5897
|
requestId: z.string(),
|
|
5898
|
+
// Daemon clock (epoch ms) at which the git-tracking fields below were measured.
|
|
5899
|
+
// One writer stamps it, so clients can compare two payloads and drop an
|
|
5900
|
+
// out-of-order push instead of clobbering newer git state.
|
|
5901
|
+
// COMPAT(checkoutStatusGitStateAt): added in v0.6.8; absent from older daemons.
|
|
5902
|
+
// Drop the optional marker when floor >= v0.6.8 (target 2027-01-24).
|
|
5903
|
+
gitStateAt: z.number().optional(),
|
|
4420
5904
|
});
|
|
4421
5905
|
const CheckoutStatusNotGitSchema = CheckoutStatusCommonSchema.extend({
|
|
4422
5906
|
isGit: z.literal(false),
|
|
@@ -4573,6 +6057,12 @@ const CheckoutPrStatusPayloadSchema = z.object({
|
|
|
4573
6057
|
});
|
|
4574
6058
|
const CheckoutStatusUpdateMetadataSchema = z.object({
|
|
4575
6059
|
prStatus: CheckoutPrStatusPayloadSchema.optional(),
|
|
6060
|
+
// True when the push refreshed only PR/check state (the hosting PR-status poll).
|
|
6061
|
+
// The git block on such a payload is an unrefreshed echo of the last snapshot,
|
|
6062
|
+
// so clients must apply `prStatus` and leave their git-tracking state alone.
|
|
6063
|
+
// COMPAT(checkoutStatusPrStatusOnly): added in v0.6.8; absent from older daemons.
|
|
6064
|
+
// Drop the default when floor >= v0.6.8 (target 2027-01-24).
|
|
6065
|
+
prStatusOnly: z.boolean().optional().default(false),
|
|
4576
6066
|
});
|
|
4577
6067
|
export const CheckoutStatusUpdateSchema = z.object({
|
|
4578
6068
|
type: z.literal("checkout_status_update"),
|
|
@@ -5343,6 +6833,110 @@ export const FileWriteResponseSchema = z.object({
|
|
|
5343
6833
|
requestId: z.string(),
|
|
5344
6834
|
}),
|
|
5345
6835
|
});
|
|
6836
|
+
/**
|
|
6837
|
+
* Create outcome. `exists` is its own status rather than an error string: it is
|
|
6838
|
+
* the one failure the client can act on (offer a different name) instead of
|
|
6839
|
+
* merely reporting.
|
|
6840
|
+
*/
|
|
6841
|
+
export const FileCreateResultSchema = z.discriminatedUnion("status", [
|
|
6842
|
+
z.object({
|
|
6843
|
+
status: z.literal("ok"),
|
|
6844
|
+
// Echoed back normalized (forward slashes, workspace-relative) so the client
|
|
6845
|
+
// selects the entry it will actually see in the next listing.
|
|
6846
|
+
path: z.string(),
|
|
6847
|
+
kind: FileEntryKindSchema,
|
|
6848
|
+
modifiedAt: z.string(),
|
|
6849
|
+
size: z.number(),
|
|
6850
|
+
}),
|
|
6851
|
+
z.object({ status: z.literal("exists") }),
|
|
6852
|
+
z.object({ status: z.literal("error"), message: z.string() }),
|
|
6853
|
+
]);
|
|
6854
|
+
export const FileCreateResponseSchema = z.object({
|
|
6855
|
+
type: z.literal("file.create.response"),
|
|
6856
|
+
payload: z.object({
|
|
6857
|
+
cwd: z.string(),
|
|
6858
|
+
path: z.string(),
|
|
6859
|
+
result: FileCreateResultSchema,
|
|
6860
|
+
requestId: z.string(),
|
|
6861
|
+
}),
|
|
6862
|
+
});
|
|
6863
|
+
/**
|
|
6864
|
+
* Delete outcome. `not_empty` means the target is a directory with children and
|
|
6865
|
+
* the request did not set `recursive` — nothing was removed, and the client can
|
|
6866
|
+
* re-ask with the stronger confirmation.
|
|
6867
|
+
*/
|
|
6868
|
+
export const FileDeleteResultSchema = z.discriminatedUnion("status", [
|
|
6869
|
+
z.object({
|
|
6870
|
+
status: z.literal("ok"),
|
|
6871
|
+
path: z.string(),
|
|
6872
|
+
kind: FileEntryKindSchema,
|
|
6873
|
+
}),
|
|
6874
|
+
z.object({ status: z.literal("not_found") }),
|
|
6875
|
+
z.object({ status: z.literal("not_empty") }),
|
|
6876
|
+
z.object({ status: z.literal("error"), message: z.string() }),
|
|
6877
|
+
]);
|
|
6878
|
+
export const FileDeleteResponseSchema = z.object({
|
|
6879
|
+
type: z.literal("file.delete.response"),
|
|
6880
|
+
payload: z.object({
|
|
6881
|
+
cwd: z.string(),
|
|
6882
|
+
path: z.string(),
|
|
6883
|
+
result: FileDeleteResultSchema,
|
|
6884
|
+
requestId: z.string(),
|
|
6885
|
+
}),
|
|
6886
|
+
});
|
|
6887
|
+
/** Rename/move outcome. `exists` means the destination was occupied; nothing moved. */
|
|
6888
|
+
export const FileRenameResultSchema = z.discriminatedUnion("status", [
|
|
6889
|
+
z.object({
|
|
6890
|
+
status: z.literal("ok"),
|
|
6891
|
+
from: z.string(),
|
|
6892
|
+
to: z.string(),
|
|
6893
|
+
kind: FileEntryKindSchema,
|
|
6894
|
+
}),
|
|
6895
|
+
z.object({ status: z.literal("not_found") }),
|
|
6896
|
+
z.object({ status: z.literal("exists") }),
|
|
6897
|
+
z.object({ status: z.literal("error"), message: z.string() }),
|
|
6898
|
+
]);
|
|
6899
|
+
export const FileRenameResponseSchema = z.object({
|
|
6900
|
+
type: z.literal("file.rename.response"),
|
|
6901
|
+
payload: z.object({
|
|
6902
|
+
cwd: z.string(),
|
|
6903
|
+
path: z.string(),
|
|
6904
|
+
newPath: z.string(),
|
|
6905
|
+
result: FileRenameResultSchema,
|
|
6906
|
+
requestId: z.string(),
|
|
6907
|
+
}),
|
|
6908
|
+
});
|
|
6909
|
+
/**
|
|
6910
|
+
* A refine proposal: the whole rewritten text of each document the model chose
|
|
6911
|
+
* to change, keyed by the id the request minted. Documents it left alone are
|
|
6912
|
+
* simply absent, and ids the request never sent are dropped by the daemon.
|
|
6913
|
+
*
|
|
6914
|
+
* The client diffs each one against the base it pinned, so a truncated or
|
|
6915
|
+
* chatty answer shows up as a diff the user can refuse rather than as a
|
|
6916
|
+
* corrupted file.
|
|
6917
|
+
*/
|
|
6918
|
+
export const FileRefineFileSchema = z.object({
|
|
6919
|
+
id: z.string().min(1),
|
|
6920
|
+
content: z.string(),
|
|
6921
|
+
});
|
|
6922
|
+
export const FileRefineResultSchema = z.discriminatedUnion("status", [
|
|
6923
|
+
z.object({
|
|
6924
|
+
status: z.literal("ok"),
|
|
6925
|
+
files: z.array(FileRefineFileSchema),
|
|
6926
|
+
}),
|
|
6927
|
+
z.object({
|
|
6928
|
+
status: z.literal("error"),
|
|
6929
|
+
message: z.string(),
|
|
6930
|
+
}),
|
|
6931
|
+
]);
|
|
6932
|
+
export const FileRefineResponseSchema = z.object({
|
|
6933
|
+
type: z.literal("file.refine.response"),
|
|
6934
|
+
payload: z.object({
|
|
6935
|
+
cwd: z.string(),
|
|
6936
|
+
result: FileRefineResultSchema,
|
|
6937
|
+
requestId: z.string(),
|
|
6938
|
+
}),
|
|
6939
|
+
});
|
|
5346
6940
|
export const FileWatchSubscribeResponseSchema = z.object({
|
|
5347
6941
|
type: z.literal("file.watch.subscribe.response"),
|
|
5348
6942
|
payload: z.object({
|
|
@@ -5391,6 +6985,370 @@ export const CodeSymbolsResponseSchema = z.object({
|
|
|
5391
6985
|
requestId: z.string(),
|
|
5392
6986
|
}),
|
|
5393
6987
|
});
|
|
6988
|
+
/** 1-based, like `CodeSymbolLocation`. The end pair is present when the server gave a range. */
|
|
6989
|
+
export const CodeDefinitionLocationSchema = z.object({
|
|
6990
|
+
path: z.string(),
|
|
6991
|
+
line: z.number().int().positive(),
|
|
6992
|
+
column: z.number().int().positive(),
|
|
6993
|
+
endLine: z.number().int().positive().optional(),
|
|
6994
|
+
endColumn: z.number().int().positive().optional(),
|
|
6995
|
+
/**
|
|
6996
|
+
* Which registry row answered (`typescript`, `csharp`, …). The multi-hit picker
|
|
6997
|
+
* shows it, so a user looking at two candidates can tell whether a language server
|
|
6998
|
+
* resolved them or the name index guessed — which changes how much to trust the
|
|
6999
|
+
* list. Absent from old daemons.
|
|
7000
|
+
*/
|
|
7001
|
+
serverId: z.string().optional(),
|
|
7002
|
+
});
|
|
7003
|
+
/**
|
|
7004
|
+
* Three-valued on purpose. `unavailable` (no server for this language on the host) and
|
|
7005
|
+
* `indexing` (the server is up but still building its project model) are different
|
|
7006
|
+
* answers to the user, and neither is "not found" — reporting either as an empty
|
|
7007
|
+
* result is how a working feature reads as broken.
|
|
7008
|
+
*/
|
|
7009
|
+
export const CodeDefinitionStatusSchema = z.enum(["ok", "indexing", "unavailable"]);
|
|
7010
|
+
export const CodeDefinitionResponseSchema = z.object({
|
|
7011
|
+
type: z.literal("code.definition.response"),
|
|
7012
|
+
payload: z.object({
|
|
7013
|
+
cwd: z.string(),
|
|
7014
|
+
path: z.string(),
|
|
7015
|
+
status: CodeDefinitionStatusSchema,
|
|
7016
|
+
locations: z.array(CodeDefinitionLocationSchema),
|
|
7017
|
+
error: z.string().nullable(),
|
|
7018
|
+
requestId: z.string(),
|
|
7019
|
+
}),
|
|
7020
|
+
});
|
|
7021
|
+
export const CodeDocumentSyncResponseSchema = z.object({
|
|
7022
|
+
type: z.literal("code.document.sync.response"),
|
|
7023
|
+
payload: z.object({
|
|
7024
|
+
cwd: z.string(),
|
|
7025
|
+
path: z.string(),
|
|
7026
|
+
ok: z.boolean(),
|
|
7027
|
+
error: z.string().nullable(),
|
|
7028
|
+
requestId: z.string(),
|
|
7029
|
+
}),
|
|
7030
|
+
});
|
|
7031
|
+
export const CodeDocumentCloseResponseSchema = z.object({
|
|
7032
|
+
type: z.literal("code.document.close.response"),
|
|
7033
|
+
payload: z.object({
|
|
7034
|
+
cwd: z.string(),
|
|
7035
|
+
path: z.string(),
|
|
7036
|
+
ok: z.boolean(),
|
|
7037
|
+
error: z.string().nullable(),
|
|
7038
|
+
requestId: z.string(),
|
|
7039
|
+
}),
|
|
7040
|
+
});
|
|
7041
|
+
/** 1-based, like every other position on the wire. */
|
|
7042
|
+
export const CodeHoverRangeSchema = z.object({
|
|
7043
|
+
line: z.number().int().positive(),
|
|
7044
|
+
column: z.number().int().positive(),
|
|
7045
|
+
endLine: z.number().int().positive(),
|
|
7046
|
+
endColumn: z.number().int().positive(),
|
|
7047
|
+
});
|
|
7048
|
+
export const CodeHoverResponseSchema = z.object({
|
|
7049
|
+
type: z.literal("code.hover.response"),
|
|
7050
|
+
payload: z.object({
|
|
7051
|
+
cwd: z.string(),
|
|
7052
|
+
path: z.string(),
|
|
7053
|
+
status: CodeDefinitionStatusSchema,
|
|
7054
|
+
/** Markdown, or null when the server had nothing to say about this position. */
|
|
7055
|
+
markdown: z.string().nullable(),
|
|
7056
|
+
range: CodeHoverRangeSchema.nullable(),
|
|
7057
|
+
serverId: z.string().nullable(),
|
|
7058
|
+
error: z.string().nullable(),
|
|
7059
|
+
requestId: z.string(),
|
|
7060
|
+
}),
|
|
7061
|
+
});
|
|
7062
|
+
export const CodeReferencesResponseSchema = z.object({
|
|
7063
|
+
type: z.literal("code.references.response"),
|
|
7064
|
+
payload: z.object({
|
|
7065
|
+
cwd: z.string(),
|
|
7066
|
+
path: z.string(),
|
|
7067
|
+
status: CodeDefinitionStatusSchema,
|
|
7068
|
+
locations: z.array(CodeDefinitionLocationSchema),
|
|
7069
|
+
error: z.string().nullable(),
|
|
7070
|
+
requestId: z.string(),
|
|
7071
|
+
}),
|
|
7072
|
+
});
|
|
7073
|
+
export const CodeRenameEditSchema = z.object({
|
|
7074
|
+
line: z.number().int().positive(),
|
|
7075
|
+
column: z.number().int().positive(),
|
|
7076
|
+
endLine: z.number().int().positive(),
|
|
7077
|
+
endColumn: z.number().int().positive(),
|
|
7078
|
+
newText: z.string(),
|
|
7079
|
+
/**
|
|
7080
|
+
* The text this edit expects to replace. Carried so the dry run can show what is being
|
|
7081
|
+
* changed rather than only what it becomes — and, on the daemon side, so the run can tell
|
|
7082
|
+
* that a file moved under the plan. For a rename this is always one identifier.
|
|
7083
|
+
*/
|
|
7084
|
+
oldText: z.string().default(""),
|
|
7085
|
+
});
|
|
7086
|
+
export const CodeRenameFilePlanSchema = z.object({
|
|
7087
|
+
path: z.string(),
|
|
7088
|
+
edits: z.array(CodeRenameEditSchema),
|
|
7089
|
+
});
|
|
7090
|
+
export const CodeRenamePreviewResponseSchema = z.object({
|
|
7091
|
+
type: z.literal("code.rename.preview.response"),
|
|
7092
|
+
payload: z.object({
|
|
7093
|
+
cwd: z.string(),
|
|
7094
|
+
path: z.string(),
|
|
7095
|
+
newName: z.string(),
|
|
7096
|
+
status: CodeDefinitionStatusSchema,
|
|
7097
|
+
/** Sorted by path, and by position within each file, so an audit reads in order. */
|
|
7098
|
+
files: z.array(CodeRenameFilePlanSchema),
|
|
7099
|
+
/** Blast radius, so the dry-run tab can lead with it. */
|
|
7100
|
+
fileCount: z.number().int().nonnegative(),
|
|
7101
|
+
editCount: z.number().int().nonnegative(),
|
|
7102
|
+
/**
|
|
7103
|
+
* Identity of this exact plan, echoed back on apply. Computed by the daemon so there is
|
|
7104
|
+
* one definition of "the same plan" rather than two that can drift apart.
|
|
7105
|
+
*/
|
|
7106
|
+
planId: z.string().default(""),
|
|
7107
|
+
error: z.string().nullable(),
|
|
7108
|
+
requestId: z.string(),
|
|
7109
|
+
}),
|
|
7110
|
+
});
|
|
7111
|
+
/**
|
|
7112
|
+
* Five-valued, because the ways a rename can fail to happen are things a user needs told
|
|
7113
|
+
* apart: still loading, no server, the plan moved, or the server pointed outside the
|
|
7114
|
+
* workspace. Collapsing them into one failure is how "nothing happened" becomes unexplainable.
|
|
7115
|
+
*/
|
|
7116
|
+
/**
|
|
7117
|
+
* Whether the run HAPPENED — deliberately not whether everything applied.
|
|
7118
|
+
*
|
|
7119
|
+
* A run where two of fourteen edits no longer fit is still a run that took place, and the
|
|
7120
|
+
* twelve that landed are real. Collapsing that into a failure would hide them, and hiding a
|
|
7121
|
+
* write is the one thing an auditable edit surface must never do. Per-edit fate lives in the
|
|
7122
|
+
* file outcomes; `complete` is the single-glance answer.
|
|
7123
|
+
*/
|
|
7124
|
+
export const CodeRenameApplyStatusSchema = z.enum(["ok", "expired", "escaped"]);
|
|
7125
|
+
export const CodeRenameFileOutcomeKindSchema = z.enum(["applied", "partial", "failed"]);
|
|
7126
|
+
/** What happened to one file in a run. */
|
|
7127
|
+
export const CodeRenameFileOutcomeSchema = z.object({
|
|
7128
|
+
path: z.string(),
|
|
7129
|
+
kind: CodeRenameFileOutcomeKindSchema,
|
|
7130
|
+
appliedEdits: z.number().int().nonnegative(),
|
|
7131
|
+
skippedEdits: z.number().int().nonnegative(),
|
|
7132
|
+
/** Why, whenever anything was skipped or the file failed outright. */
|
|
7133
|
+
reason: z.string().nullable(),
|
|
7134
|
+
});
|
|
7135
|
+
export const CodeRenameUndoStatusSchema = z.enum(["ok", "expired"]);
|
|
7136
|
+
export const CodeRenameUndoFileKindSchema = z.enum(["restored", "changedSince", "failed"]);
|
|
7137
|
+
/**
|
|
7138
|
+
* What happened to one file during an undo. `changedSince` is the important one: the file was
|
|
7139
|
+
* edited after the run, so restoring would have destroyed that work and it was left alone.
|
|
7140
|
+
*/
|
|
7141
|
+
export const CodeRenameUndoFileSchema = z.object({
|
|
7142
|
+
path: z.string(),
|
|
7143
|
+
kind: CodeRenameUndoFileKindSchema,
|
|
7144
|
+
reason: z.string().nullable(),
|
|
7145
|
+
});
|
|
7146
|
+
export const CodeRenameUndoResponseSchema = z.object({
|
|
7147
|
+
type: z.literal("code.rename.undo.response"),
|
|
7148
|
+
payload: z.object({
|
|
7149
|
+
cwd: z.string(),
|
|
7150
|
+
runId: z.string(),
|
|
7151
|
+
status: CodeRenameUndoStatusSchema,
|
|
7152
|
+
files: z.array(CodeRenameUndoFileSchema),
|
|
7153
|
+
restoredFiles: z.number().int().nonnegative(),
|
|
7154
|
+
/** True only when every file the run wrote was put back. */
|
|
7155
|
+
complete: z.boolean(),
|
|
7156
|
+
error: z.string().nullable(),
|
|
7157
|
+
requestId: z.string(),
|
|
7158
|
+
}),
|
|
7159
|
+
});
|
|
7160
|
+
export const CodeRenameApplyResponseSchema = z.object({
|
|
7161
|
+
type: z.literal("code.rename.apply.response"),
|
|
7162
|
+
payload: z.object({
|
|
7163
|
+
cwd: z.string(),
|
|
7164
|
+
path: z.string(),
|
|
7165
|
+
newName: z.string(),
|
|
7166
|
+
status: CodeRenameApplyStatusSchema,
|
|
7167
|
+
/** Identity of this run, for undo. Null when nothing ran. */
|
|
7168
|
+
runId: z.string().nullable(),
|
|
7169
|
+
files: z.array(CodeRenameFileOutcomeSchema),
|
|
7170
|
+
appliedFiles: z.number().int().nonnegative(),
|
|
7171
|
+
appliedEdits: z.number().int().nonnegative(),
|
|
7172
|
+
skippedEdits: z.number().int().nonnegative(),
|
|
7173
|
+
/** True only when every planned edit landed. */
|
|
7174
|
+
complete: z.boolean(),
|
|
7175
|
+
error: z.string().nullable(),
|
|
7176
|
+
requestId: z.string(),
|
|
7177
|
+
}),
|
|
7178
|
+
});
|
|
7179
|
+
export const LspLanguageStateSchema = z.object({
|
|
7180
|
+
id: z.string(),
|
|
7181
|
+
enabled: z.boolean(),
|
|
7182
|
+
/** Whether the host can actually supply this server right now. */
|
|
7183
|
+
installed: z.boolean(),
|
|
7184
|
+
running: z.boolean(),
|
|
7185
|
+
/** Which discovery rung supplied it (`workspaceBin` / `bundled` / `path`), or null. */
|
|
7186
|
+
rung: z.string().nullable(),
|
|
7187
|
+
bin: z.string(),
|
|
7188
|
+
extensions: z.array(z.string()),
|
|
7189
|
+
/** Plain-words index cost, so the toggle states its own price. */
|
|
7190
|
+
indexCost: z.string(),
|
|
7191
|
+
});
|
|
7192
|
+
export const LspRunningServerSchema = z.object({
|
|
7193
|
+
rootPath: z.string(),
|
|
7194
|
+
serverId: z.string(),
|
|
7195
|
+
uptimeMs: z.number(),
|
|
7196
|
+
lastUsedAt: z.number(),
|
|
7197
|
+
});
|
|
7198
|
+
export const LspServersListResponseSchema = z.object({
|
|
7199
|
+
type: z.literal("lsp.servers.list.response"),
|
|
7200
|
+
payload: z.object({
|
|
7201
|
+
cwd: z.string(),
|
|
7202
|
+
languages: z.array(LspLanguageStateSchema),
|
|
7203
|
+
running: z.array(LspRunningServerSchema),
|
|
7204
|
+
error: z.string().nullable(),
|
|
7205
|
+
requestId: z.string(),
|
|
7206
|
+
}),
|
|
7207
|
+
});
|
|
7208
|
+
export const LspServerStopResponseSchema = z.object({
|
|
7209
|
+
type: z.literal("lsp.server.stop.response"),
|
|
7210
|
+
payload: z.object({
|
|
7211
|
+
rootPath: z.string(),
|
|
7212
|
+
serverId: z.string(),
|
|
7213
|
+
ok: z.boolean(),
|
|
7214
|
+
error: z.string().nullable(),
|
|
7215
|
+
requestId: z.string(),
|
|
7216
|
+
}),
|
|
7217
|
+
});
|
|
7218
|
+
/**
|
|
7219
|
+
* Solution view responses (projects/solution-view).
|
|
7220
|
+
*
|
|
7221
|
+
* COMPAT(solutionView): added in v0.6.8, drop the gate when daemon floor >= v0.6.8.
|
|
7222
|
+
*/
|
|
7223
|
+
export const SolutionFormatSchema = z.enum(["sln", "slnx"]);
|
|
7224
|
+
/** One solution a workspace contains. Enough to populate the switcher's picker, nothing more. */
|
|
7225
|
+
export const SolutionRefSchema = z.object({
|
|
7226
|
+
/** Workspace-relative, forward slashes — the identity used by every later request. */
|
|
7227
|
+
path: z.string(),
|
|
7228
|
+
/** File name without the extension, which is what a .NET developer calls the solution. */
|
|
7229
|
+
name: z.string(),
|
|
7230
|
+
format: SolutionFormatSchema,
|
|
7231
|
+
});
|
|
7232
|
+
export const CodeSolutionListResponseSchema = z.object({
|
|
7233
|
+
type: z.literal("code.solution.list.response"),
|
|
7234
|
+
payload: z.object({
|
|
7235
|
+
cwd: z.string(),
|
|
7236
|
+
/**
|
|
7237
|
+
* Empty means the switcher never appears and the Files tab behaves exactly as it does today.
|
|
7238
|
+
* That is also what a disabled feature, a host with no .NET SDK, and a workspace with no
|
|
7239
|
+
* solution all return — the client has one silent case to handle, not four.
|
|
7240
|
+
*/
|
|
7241
|
+
solutions: z.array(SolutionRefSchema),
|
|
7242
|
+
error: z.string().nullable(),
|
|
7243
|
+
requestId: z.string(),
|
|
7244
|
+
}),
|
|
7245
|
+
});
|
|
7246
|
+
/**
|
|
7247
|
+
* Solution structure is flat on the wire with parent links, not nested.
|
|
7248
|
+
*
|
|
7249
|
+
* A recursive payload would have to be walked to be used, and every consumer would write that
|
|
7250
|
+
* walk again; the file explorer already turns a flat listing plus an expanded-path set into rows,
|
|
7251
|
+
* so this hands it the same shape it already consumes.
|
|
7252
|
+
*/
|
|
7253
|
+
export const SolutionTreeFolderSchema = z.object({
|
|
7254
|
+
/** Solution-internal, e.g. `/Src/`. Folders are virtual: they have no filesystem location. */
|
|
7255
|
+
path: z.string(),
|
|
7256
|
+
name: z.string(),
|
|
7257
|
+
parentPath: z.string().nullable(),
|
|
7258
|
+
});
|
|
7259
|
+
export const SolutionTreeProjectSchema = z.object({
|
|
7260
|
+
id: z.string(),
|
|
7261
|
+
name: z.string(),
|
|
7262
|
+
/**
|
|
7263
|
+
* Workspace-relative when the project sits inside the workspace, absolute (forward-slashed)
|
|
7264
|
+
* when it does not. `outsideWorkspace` says which, so nothing has to guess by inspecting the
|
|
7265
|
+
* string.
|
|
7266
|
+
*/
|
|
7267
|
+
path: z.string(),
|
|
7268
|
+
/**
|
|
7269
|
+
* A project the solution names outside the workspace root. Shown and opened like any other —
|
|
7270
|
+
* the solution file is the authority naming it, so this is not free browsing — but editing one
|
|
7271
|
+
* warns, and it is absent from every git surface. See docs/solution-view.md.
|
|
7272
|
+
*/
|
|
7273
|
+
outsideWorkspace: z.boolean(),
|
|
7274
|
+
/** The solution folder containing it, or null for a project at the solution root. */
|
|
7275
|
+
folderPath: z.string().nullable(),
|
|
7276
|
+
/** Project type GUID, lowercased. Absent on old daemons. */
|
|
7277
|
+
typeId: z.string().optional(),
|
|
7278
|
+
});
|
|
7279
|
+
export const CodeSolutionGetTreeResponseSchema = z.object({
|
|
7280
|
+
type: z.literal("code.solution.get_tree.response"),
|
|
7281
|
+
payload: z.object({
|
|
7282
|
+
cwd: z.string(),
|
|
7283
|
+
solutionPath: z.string(),
|
|
7284
|
+
name: z.string().default(""),
|
|
7285
|
+
format: SolutionFormatSchema.default("sln"),
|
|
7286
|
+
folders: z.array(SolutionTreeFolderSchema),
|
|
7287
|
+
projects: z.array(SolutionTreeProjectSchema),
|
|
7288
|
+
/** Solution configurations and platforms — first-class .NET concepts no CLI surfaces. */
|
|
7289
|
+
buildTypes: z.array(z.string()),
|
|
7290
|
+
platforms: z.array(z.string()),
|
|
7291
|
+
error: z.string().nullable(),
|
|
7292
|
+
requestId: z.string(),
|
|
7293
|
+
}),
|
|
7294
|
+
});
|
|
7295
|
+
/**
|
|
7296
|
+
* Three-valued for the same reason the code-intelligence family is: "the host cannot supply
|
|
7297
|
+
* this", "MSBuild refused this project", and "here are its files" are different things to tell a
|
|
7298
|
+
* user, and reporting the first two as an empty file list is how a working feature reads as
|
|
7299
|
+
* broken. One project that fails must not blank the tree, so this status is per project.
|
|
7300
|
+
*/
|
|
7301
|
+
export const SolutionProjectStatusSchema = z.enum(["ok", "failed", "unavailable"]);
|
|
7302
|
+
/**
|
|
7303
|
+
* One entry in a project's evaluated membership, flat with parent links like the folders above.
|
|
7304
|
+
*
|
|
7305
|
+
* `isImplicit` is what a filesystem tree structurally cannot show and what Phase 2 turns on: an
|
|
7306
|
+
* item contributed by the SDK's default globs is one that creating the file already adds, while
|
|
7307
|
+
* an item the project file itself declares needs a real `.csproj` edit.
|
|
7308
|
+
*/
|
|
7309
|
+
export const SolutionProjectNodeSchema = z.discriminatedUnion("kind", [
|
|
7310
|
+
z.object({
|
|
7311
|
+
kind: z.literal("directory"),
|
|
7312
|
+
id: z.string(),
|
|
7313
|
+
parentId: z.string().nullable(),
|
|
7314
|
+
name: z.string(),
|
|
7315
|
+
path: z.string(),
|
|
7316
|
+
outsideWorkspace: z.boolean(),
|
|
7317
|
+
}),
|
|
7318
|
+
z.object({
|
|
7319
|
+
kind: z.literal("file"),
|
|
7320
|
+
id: z.string(),
|
|
7321
|
+
parentId: z.string().nullable(),
|
|
7322
|
+
name: z.string(),
|
|
7323
|
+
path: z.string(),
|
|
7324
|
+
outsideWorkspace: z.boolean(),
|
|
7325
|
+
/** `Compile`, `Content`, `EmbeddedResource`, … — MSBuild's own item type. */
|
|
7326
|
+
itemType: z.string(),
|
|
7327
|
+
isImplicit: z.boolean(),
|
|
7328
|
+
}),
|
|
7329
|
+
]);
|
|
7330
|
+
export const SolutionPackageReferenceSchema = z.object({
|
|
7331
|
+
name: z.string(),
|
|
7332
|
+
version: z.string().nullable(),
|
|
7333
|
+
});
|
|
7334
|
+
export const CodeSolutionLoadProjectResponseSchema = z.object({
|
|
7335
|
+
type: z.literal("code.solution.load_project.response"),
|
|
7336
|
+
payload: z.object({
|
|
7337
|
+
cwd: z.string(),
|
|
7338
|
+
solutionPath: z.string(),
|
|
7339
|
+
projectPath: z.string(),
|
|
7340
|
+
status: SolutionProjectStatusSchema,
|
|
7341
|
+
nodes: z.array(SolutionProjectNodeSchema),
|
|
7342
|
+
projectReferences: z.array(z.string()),
|
|
7343
|
+
packageReferences: z.array(SolutionPackageReferenceSchema),
|
|
7344
|
+
targetFrameworks: z.array(z.string()),
|
|
7345
|
+
outputType: z.string().nullable(),
|
|
7346
|
+
isSdkStyle: z.boolean(),
|
|
7347
|
+
/** MSBuild's own message when `status` is `failed`, verbatim. */
|
|
7348
|
+
error: z.string().nullable(),
|
|
7349
|
+
requestId: z.string(),
|
|
7350
|
+
}),
|
|
7351
|
+
});
|
|
5394
7352
|
export const CodeOutlineResponseSchema = z.object({
|
|
5395
7353
|
type: z.literal("code.outline.response"),
|
|
5396
7354
|
payload: z.object({
|
|
@@ -5819,11 +7777,17 @@ export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
5819
7777
|
FetchRecentProviderSessionsResponseMessageSchema,
|
|
5820
7778
|
FetchWorkspacesResponseMessageSchema,
|
|
5821
7779
|
ProjectAddResponseSchema,
|
|
7780
|
+
ProjectScaffoldResponseSchema,
|
|
7781
|
+
ProjectScaffoldProgressSchema,
|
|
5822
7782
|
OpenProjectResponseMessageSchema,
|
|
5823
7783
|
StartWorkspaceScriptResponseMessageSchema,
|
|
5824
7784
|
LegacyListAvailableEditorsResponseMessageSchema,
|
|
5825
7785
|
LegacyOpenInEditorResponseMessageSchema,
|
|
5826
7786
|
ArchiveWorkspaceResponseMessageSchema,
|
|
7787
|
+
WorkspaceArchivePreflightResponseSchema,
|
|
7788
|
+
WorktreeBaseRefSetResponseSchema,
|
|
7789
|
+
WorktreeReattachListResponseSchema,
|
|
7790
|
+
WorktreeReattachResponseSchema,
|
|
5827
7791
|
FetchAgentResponseMessageSchema,
|
|
5828
7792
|
FetchAgentTimelineResponseMessageSchema,
|
|
5829
7793
|
AgentForkContextResponseMessageSchema,
|
|
@@ -5840,6 +7804,8 @@ export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
5840
7804
|
SetDaemonConfigResponseMessageSchema,
|
|
5841
7805
|
SpeechSettingsGetOptionsResponseSchema,
|
|
5842
7806
|
SpeechTtsPreviewResponseSchema,
|
|
7807
|
+
SpeechTtsSpeakResponseSchema,
|
|
7808
|
+
SpeechTtsSpeakCancelResponseSchema,
|
|
5843
7809
|
VisualizerVoiceCuesGenerateResponseSchema,
|
|
5844
7810
|
AgentPersonalitiesGetStatsResponseSchema,
|
|
5845
7811
|
ReadProjectConfigResponseMessageSchema,
|
|
@@ -5849,6 +7815,9 @@ export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
5849
7815
|
SetAgentThinkingResponseMessageSchema,
|
|
5850
7816
|
SetAgentFeatureResponseMessageSchema,
|
|
5851
7817
|
AgentDetachResponseMessageSchema,
|
|
7818
|
+
AgentQueueRemoveResponseMessageSchema,
|
|
7819
|
+
AgentQueueReorderResponseMessageSchema,
|
|
7820
|
+
AgentQueueClearResponseMessageSchema,
|
|
5852
7821
|
AgentSubagentStopResponseMessageSchema,
|
|
5853
7822
|
AgentBackgroundTaskStopResponseMessageSchema,
|
|
5854
7823
|
AgentBackgroundTaskClearResponseMessageSchema,
|
|
@@ -5861,6 +7830,7 @@ export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
5861
7830
|
AgentRewindResponseMessageSchema,
|
|
5862
7831
|
UpdateAgentResponseMessageSchema,
|
|
5863
7832
|
ProjectRenameResponseSchema,
|
|
7833
|
+
ProjectUpdatedNotificationSchema,
|
|
5864
7834
|
ProjectRemoveResponseSchema,
|
|
5865
7835
|
ProjectLinksListResponseSchema,
|
|
5866
7836
|
ProjectLinksSetResponseSchema,
|
|
@@ -5871,6 +7841,7 @@ export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
5871
7841
|
AgentPermissionRequestMessageSchema,
|
|
5872
7842
|
AgentPermissionResolvedMessageSchema,
|
|
5873
7843
|
AgentDeletedMessageSchema,
|
|
7844
|
+
HistoryAgentsClearArchivedResponseSchema,
|
|
5874
7845
|
AgentArchivedMessageSchema,
|
|
5875
7846
|
CloseItemsResponseSchema,
|
|
5876
7847
|
CheckoutStatusResponseSchema,
|
|
@@ -5892,7 +7863,17 @@ export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
5892
7863
|
RunsGateRespondResponseSchema,
|
|
5893
7864
|
RunsCancelResponseSchema,
|
|
5894
7865
|
RunsClearResponseSchema,
|
|
7866
|
+
RunsDeleteResponseSchema,
|
|
5895
7867
|
RunsClearedNotificationSchema,
|
|
7868
|
+
RunsGraphsListResponseSchema,
|
|
7869
|
+
RunsGraphsSaveResponseSchema,
|
|
7870
|
+
RunsGraphsDeleteResponseSchema,
|
|
7871
|
+
RunsGraphsChangedNotificationSchema,
|
|
7872
|
+
RunsTemplatesListResponseSchema,
|
|
7873
|
+
RunsTemplatesSaveResponseSchema,
|
|
7874
|
+
RunsTemplatesDeleteResponseSchema,
|
|
7875
|
+
RunsTemplatesChangedNotificationSchema,
|
|
7876
|
+
RunsStartResponseSchema,
|
|
5896
7877
|
CheckoutMergeResponseSchema,
|
|
5897
7878
|
CheckoutMergeFromBaseResponseSchema,
|
|
5898
7879
|
CheckoutPullResponseSchema,
|
|
@@ -5918,6 +7899,8 @@ export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
5918
7899
|
GitHubSearchResponseSchema,
|
|
5919
7900
|
HostingSearchResponseSchema,
|
|
5920
7901
|
HostingAuthStatusResponseSchema,
|
|
7902
|
+
HostingListRepositoriesResponseSchema,
|
|
7903
|
+
HostingListOwnersResponseSchema,
|
|
5921
7904
|
DirectorySuggestionsResponseSchema,
|
|
5922
7905
|
OttoWorktreeListResponseSchema,
|
|
5923
7906
|
OttoWorktreeArchiveResponseSchema,
|
|
@@ -5927,6 +7910,10 @@ export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
5927
7910
|
FileDownloadTokenResponseSchema,
|
|
5928
7911
|
FileUploadResponseSchema,
|
|
5929
7912
|
FileWriteResponseSchema,
|
|
7913
|
+
FileCreateResponseSchema,
|
|
7914
|
+
FileDeleteResponseSchema,
|
|
7915
|
+
FileRenameResponseSchema,
|
|
7916
|
+
FileRefineResponseSchema,
|
|
5930
7917
|
FileWatchSubscribeResponseSchema,
|
|
5931
7918
|
FileWatchUnsubscribeResponseSchema,
|
|
5932
7919
|
FileWatchEventSchema,
|
|
@@ -5936,6 +7923,19 @@ export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
5936
7923
|
CodeListFilesResponseSchema,
|
|
5937
7924
|
CodeSymbolsResponseSchema,
|
|
5938
7925
|
CodeOutlineResponseSchema,
|
|
7926
|
+
CodeDefinitionResponseSchema,
|
|
7927
|
+
CodeDocumentSyncResponseSchema,
|
|
7928
|
+
CodeDocumentCloseResponseSchema,
|
|
7929
|
+
CodeHoverResponseSchema,
|
|
7930
|
+
CodeReferencesResponseSchema,
|
|
7931
|
+
CodeRenamePreviewResponseSchema,
|
|
7932
|
+
CodeRenameApplyResponseSchema,
|
|
7933
|
+
CodeRenameUndoResponseSchema,
|
|
7934
|
+
LspServersListResponseSchema,
|
|
7935
|
+
LspServerStopResponseSchema,
|
|
7936
|
+
CodeSolutionListResponseSchema,
|
|
7937
|
+
CodeSolutionGetTreeResponseSchema,
|
|
7938
|
+
CodeSolutionLoadProjectResponseSchema,
|
|
5939
7939
|
ListProviderModelsResponseMessageSchema,
|
|
5940
7940
|
ListProviderModesResponseMessageSchema,
|
|
5941
7941
|
ListProviderFeaturesResponseMessageSchema,
|
|
@@ -5948,6 +7948,11 @@ export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
5948
7948
|
StatsActivityGetResponseMessageSchema,
|
|
5949
7949
|
ContextReportGetResponseMessageSchema,
|
|
5950
7950
|
ContextEdgeConvertResponseMessageSchema,
|
|
7951
|
+
ContextFindingsFixResponseMessageSchema,
|
|
7952
|
+
PersonalityMemoryListResponseMessageSchema,
|
|
7953
|
+
PersonalityMemoryUpdateResponseMessageSchema,
|
|
7954
|
+
PersonalityMemoryTransferResponseMessageSchema,
|
|
7955
|
+
PersonalityMemoryStatsResponseMessageSchema,
|
|
5951
7956
|
StatsActivityResetResponseMessageSchema,
|
|
5952
7957
|
UsageLogGetResponseMessageSchema,
|
|
5953
7958
|
ActivityStatsChangedSchema,
|