@otto-code/protocol 0.7.4 → 0.7.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-attention-notification.d.ts +2 -0
- package/dist/agent-attention-notification.js +1 -0
- package/dist/agent-deep-link.d.ts +8 -0
- package/dist/agent-deep-link.js +49 -0
- package/dist/agent-types.d.ts +14 -0
- package/dist/binary-frames/file-transfer.d.ts +1 -0
- package/dist/binary-frames/file-transfer.js +1 -0
- package/dist/browser-automation/rpc-schemas.d.ts +21 -0
- package/dist/browser-automation/rpc-schemas.js +10 -0
- package/dist/client-capabilities.d.ts +3 -0
- package/dist/client-capabilities.js +9 -0
- package/dist/forge-manifest.d.ts +66 -0
- package/dist/forge-manifest.js +92 -0
- package/dist/generated/validation/ws-outbound.aot.js +74267 -48747
- package/dist/git-remote.d.ts +17 -0
- package/dist/git-remote.js +23 -2
- package/dist/messages.d.ts +12983 -1065
- package/dist/messages.js +1928 -24
- package/dist/otto-config-schema.d.ts +21 -0
- package/dist/otto-config-schema.js +22 -0
- package/dist/provider-config.d.ts +81 -0
- package/dist/provider-config.js +42 -0
- package/dist/provider-manifest.d.ts +2 -0
- package/dist/provider-manifest.js +32 -4
- package/dist/schedule/cadence.d.ts +6 -0
- package/dist/schedule/cadence.js +28 -0
- package/dist/validation/ws-outbound-schema-metadata.d.ts +2097 -48
- package/package.json +1 -1
package/dist/messages.js
CHANGED
|
@@ -7,7 +7,7 @@ import { CLIENT_CAPS } from "./client-capabilities.js";
|
|
|
7
7
|
import { AGENT_LIFECYCLE_STATUSES } from "./agent-lifecycle.js";
|
|
8
8
|
import { MAX_EXPLICIT_AGENT_TITLE_CHARS } from "./agent-title-limits.js";
|
|
9
9
|
import { AgentProviderSchema } from "./provider-manifest.js";
|
|
10
|
-
import { McpServerConfigSchema, OTTO_TOOL_GROUPS } from "./provider-config.js";
|
|
10
|
+
import { ConnectorConfigSchema, McpServerConfigSchema, OTTO_TOOL_GROUPS, } from "./provider-config.js";
|
|
11
11
|
import { TOOL_CALL_ICON_NAMES } from "./agent-types.js";
|
|
12
12
|
import { ChatCreateRequestSchema, ChatListRequestSchema, ChatInspectRequestSchema, ChatDeleteRequestSchema, ChatPostRequestSchema, ChatReadRequestSchema, ChatWaitRequestSchema, ChatCreateResponseSchema, ChatListResponseSchema, ChatInspectResponseSchema, ChatDeleteResponseSchema, ChatPostResponseSchema, ChatReadResponseSchema, ChatWaitResponseSchema, } from "./chat/rpc-schemas.js";
|
|
13
13
|
import { ScheduleCreateRequestSchema, ScheduleListRequestSchema, ScheduleInspectRequestSchema, ScheduleLogsRequestSchema, SchedulePauseRequestSchema, ScheduleResumeRequestSchema, ScheduleDeleteRequestSchema, ScheduleRunOnceRequestSchema, ScheduleUpdateRequestSchema, ScheduleCreateResponseSchema, ScheduleListResponseSchema, ScheduleInspectResponseSchema, ScheduleLogsResponseSchema, SchedulePauseResponseSchema, ScheduleResumeResponseSchema, ScheduleDeleteResponseSchema, ScheduleRunOnceResponseSchema, ScheduleUpdateResponseSchema, } from "./schedule/rpc-schemas.js";
|
|
@@ -68,6 +68,17 @@ const MutableAgentBehaviorsConfigSchema = z
|
|
|
68
68
|
// Default value of an agent's notifyOnFinish when the spawn path leaves it
|
|
69
69
|
// unspecified (the current implicit default).
|
|
70
70
|
notifyOnFinishDefault: z.boolean().default(true),
|
|
71
|
+
// Provider-agnostic task-list reminders. Otto renders every provider's
|
|
72
|
+
// native todo list into one timeline UI; when an agent leaves that list with
|
|
73
|
+
// unfinished items, these keep it from going stale (the user shouldn't have
|
|
74
|
+
// to dismiss a half-checked list themselves).
|
|
75
|
+
// Passive: while a stale list is open, attach a reminder to the agent's next
|
|
76
|
+
// turn (mirrors the harness's own "your todo list looks stale" nudge).
|
|
77
|
+
todoNudge: z.boolean().default(true),
|
|
78
|
+
// Active: when the agent goes idle with a stale list, inject a one-shot
|
|
79
|
+
// reconcile pass so it marks done what's done (or states what's genuinely
|
|
80
|
+
// left) before the turn truly ends.
|
|
81
|
+
todoReconcileOnIdle: z.boolean().default(true),
|
|
71
82
|
})
|
|
72
83
|
.passthrough();
|
|
73
84
|
export const TerminalProfileSchema = z
|
|
@@ -397,6 +408,161 @@ export const SavedProviderEndpointSchema = z
|
|
|
397
408
|
savedAt: z.number().optional(),
|
|
398
409
|
})
|
|
399
410
|
.passthrough();
|
|
411
|
+
// The editable projection of @otto-code/brain's own config (the brain's
|
|
412
|
+
// config.json stays the source of truth on disk; the daemon writes changes
|
|
413
|
+
// through). Every field is defaulted so a new client parsing an old daemon's
|
|
414
|
+
// config sees a well-formed, OFF section.
|
|
415
|
+
export const MutableBrainTlsConfigSchema = z
|
|
416
|
+
.object({
|
|
417
|
+
mode: z.enum(["off", "files", "self-signed", "tailscale"]).default("off"),
|
|
418
|
+
certFile: z.string().nullable().default(null),
|
|
419
|
+
keyFile: z.string().nullable().default(null),
|
|
420
|
+
hostname: z.string().nullable().default(null),
|
|
421
|
+
certDir: z.string().nullable().default(null),
|
|
422
|
+
renewBeforeDays: z.number().int().min(1).default(21),
|
|
423
|
+
})
|
|
424
|
+
.passthrough();
|
|
425
|
+
// Where a remote brain lives, when brain.mode is "remote". Every field is
|
|
426
|
+
// defaulted so an old daemon's config parses as a well-formed, empty target.
|
|
427
|
+
export const MutableBrainRemoteConfigSchema = z
|
|
428
|
+
.object({
|
|
429
|
+
host: z.string().default(""),
|
|
430
|
+
port: z.number().int().default(1234),
|
|
431
|
+
secure: z.boolean().default(false),
|
|
432
|
+
// Secret: masked with DAEMON_CONFIG_SECRET_SENTINEL on the way out.
|
|
433
|
+
authToken: z.string().nullable().default(null),
|
|
434
|
+
// SHA-256 fingerprint of the remote brain's TLS certificate (openssl's
|
|
435
|
+
// "AB:CD:..." form; colons optional). When set, the daemon pins HTTPS
|
|
436
|
+
// connections to exactly this certificate instead of the system trust
|
|
437
|
+
// store — required for a brain serving tls.mode=self-signed. When null,
|
|
438
|
+
// the certificate must validate against the system trust store.
|
|
439
|
+
certFingerprint: z.string().nullable().default(null),
|
|
440
|
+
})
|
|
441
|
+
.passthrough();
|
|
442
|
+
export const MutableBrainConfigSchema = z
|
|
443
|
+
.object({
|
|
444
|
+
enabled: z.boolean().default(false),
|
|
445
|
+
autoStart: z.boolean().default(false),
|
|
446
|
+
// "local": the daemon spawns and supervises the brain on this host.
|
|
447
|
+
// "remote": the daemon connects to a brain running on another Otto host
|
|
448
|
+
// (read-only: status/evals/config, no lifecycle). Gated by features.brainRemote.
|
|
449
|
+
mode: z.enum(["local", "remote"]).default("local"),
|
|
450
|
+
remote: MutableBrainRemoteConfigSchema.default({
|
|
451
|
+
host: "",
|
|
452
|
+
port: 1234,
|
|
453
|
+
secure: false,
|
|
454
|
+
authToken: null,
|
|
455
|
+
certFingerprint: null,
|
|
456
|
+
}),
|
|
457
|
+
listen: z
|
|
458
|
+
.object({
|
|
459
|
+
host: z.string().default("127.0.0.1"),
|
|
460
|
+
port: z.number().int().default(1234),
|
|
461
|
+
})
|
|
462
|
+
.passthrough()
|
|
463
|
+
.default({ host: "127.0.0.1", port: 1234 }),
|
|
464
|
+
defaultModel: z.string().nullable().default(null),
|
|
465
|
+
// Pin the host to one model: serve only the default/resident model and
|
|
466
|
+
// refuse completion requests that ask for a different one.
|
|
467
|
+
lockModel: z.boolean().default(false),
|
|
468
|
+
// Sharing gates (off by default). allowRemoteConfig: key holders may CHANGE
|
|
469
|
+
// config over the network (POST /__host/config), not just use it.
|
|
470
|
+
// allowInsecureBind: permit a non-loopback bind with no token (open share).
|
|
471
|
+
allowRemoteConfig: z.boolean().default(false),
|
|
472
|
+
allowInsecureBind: z.boolean().default(false),
|
|
473
|
+
authMode: z.enum(["none", "token"]).default("none"),
|
|
474
|
+
// Secret: masked with DAEMON_CONFIG_SECRET_SENTINEL on the way out; an
|
|
475
|
+
// unchanged sentinel is stripped from inbound patches.
|
|
476
|
+
authToken: z.string().nullable().default(null),
|
|
477
|
+
tls: MutableBrainTlsConfigSchema.default({
|
|
478
|
+
mode: "off",
|
|
479
|
+
certFile: null,
|
|
480
|
+
keyFile: null,
|
|
481
|
+
hostname: null,
|
|
482
|
+
certDir: null,
|
|
483
|
+
renewBeforeDays: 21,
|
|
484
|
+
}),
|
|
485
|
+
})
|
|
486
|
+
.passthrough();
|
|
487
|
+
// The brain PATCH schema — deliberately NOT `MutableBrainConfigSchema.partial()`.
|
|
488
|
+
// Every field of the full schema carries a `.default()` (so an old daemon's
|
|
489
|
+
// half-written config still parses as a well-formed OFF section), and Zod keeps
|
|
490
|
+
// those defaults through `.partial()`: `MutableBrainConfigSchema.partial().parse(
|
|
491
|
+
// { allowRemoteConfig: true })` expands to the FULL object with every other field
|
|
492
|
+
// defaulted. The daemon deep-merges the parsed patch over the stored config, so a
|
|
493
|
+
// single-field patch would silently reset the entire brain block to defaults —
|
|
494
|
+
// turning sharing off (host back to loopback), wiping the auth token, and
|
|
495
|
+
// disabling the server. Mirroring the shape WITHOUT defaults keeps an omitted
|
|
496
|
+
// field omitted, so the deep-merge preserves it. Every level is deep-partial so a
|
|
497
|
+
// nested patch (e.g. just `listen.host`) preserves its siblings too. Keep the
|
|
498
|
+
// field set in sync with MutableBrainConfigSchema; `.passthrough()` carries any
|
|
499
|
+
// field a newer daemon adds through untouched in the meantime.
|
|
500
|
+
const MutableBrainTlsPatchSchema = z
|
|
501
|
+
.object({
|
|
502
|
+
mode: z.enum(["off", "files", "self-signed", "tailscale"]),
|
|
503
|
+
certFile: z.string().nullable(),
|
|
504
|
+
keyFile: z.string().nullable(),
|
|
505
|
+
hostname: z.string().nullable(),
|
|
506
|
+
certDir: z.string().nullable(),
|
|
507
|
+
renewBeforeDays: z.number().int().min(1),
|
|
508
|
+
})
|
|
509
|
+
.partial()
|
|
510
|
+
.passthrough();
|
|
511
|
+
const MutableBrainRemotePatchSchema = z
|
|
512
|
+
.object({
|
|
513
|
+
host: z.string(),
|
|
514
|
+
port: z.number().int(),
|
|
515
|
+
secure: z.boolean(),
|
|
516
|
+
authToken: z.string().nullable(),
|
|
517
|
+
certFingerprint: z.string().nullable(),
|
|
518
|
+
})
|
|
519
|
+
.partial()
|
|
520
|
+
.passthrough();
|
|
521
|
+
const MutableBrainListenPatchSchema = z
|
|
522
|
+
.object({
|
|
523
|
+
host: z.string(),
|
|
524
|
+
port: z.number().int(),
|
|
525
|
+
})
|
|
526
|
+
.partial()
|
|
527
|
+
.passthrough();
|
|
528
|
+
export const MutableBrainConfigPatchSchema = z
|
|
529
|
+
.object({
|
|
530
|
+
enabled: z.boolean(),
|
|
531
|
+
autoStart: z.boolean(),
|
|
532
|
+
mode: z.enum(["local", "remote"]),
|
|
533
|
+
remote: MutableBrainRemotePatchSchema,
|
|
534
|
+
listen: MutableBrainListenPatchSchema,
|
|
535
|
+
defaultModel: z.string().nullable(),
|
|
536
|
+
lockModel: z.boolean(),
|
|
537
|
+
allowRemoteConfig: z.boolean(),
|
|
538
|
+
allowInsecureBind: z.boolean(),
|
|
539
|
+
authMode: z.enum(["none", "token"]),
|
|
540
|
+
authToken: z.string().nullable(),
|
|
541
|
+
tls: MutableBrainTlsPatchSchema,
|
|
542
|
+
})
|
|
543
|
+
.partial()
|
|
544
|
+
.passthrough();
|
|
545
|
+
export const DEFAULT_MUTABLE_BRAIN_CONFIG = {
|
|
546
|
+
enabled: false,
|
|
547
|
+
autoStart: false,
|
|
548
|
+
mode: "local",
|
|
549
|
+
remote: { host: "", port: 1234, secure: false, authToken: null, certFingerprint: null },
|
|
550
|
+
listen: { host: "127.0.0.1", port: 1234 },
|
|
551
|
+
defaultModel: null,
|
|
552
|
+
lockModel: false,
|
|
553
|
+
allowRemoteConfig: false,
|
|
554
|
+
allowInsecureBind: false,
|
|
555
|
+
authMode: "none",
|
|
556
|
+
authToken: null,
|
|
557
|
+
tls: {
|
|
558
|
+
mode: "off",
|
|
559
|
+
certFile: null,
|
|
560
|
+
keyFile: null,
|
|
561
|
+
hostname: null,
|
|
562
|
+
certDir: null,
|
|
563
|
+
renewBeforeDays: 21,
|
|
564
|
+
},
|
|
565
|
+
};
|
|
400
566
|
export const MutableDaemonConfigSchema = z
|
|
401
567
|
.object({
|
|
402
568
|
mcp: z
|
|
@@ -418,6 +584,8 @@ export const MutableDaemonConfigSchema = z
|
|
|
418
584
|
promptSuggestions: true,
|
|
419
585
|
agentProgressSummaries: true,
|
|
420
586
|
notifyOnFinishDefault: true,
|
|
587
|
+
todoNudge: true,
|
|
588
|
+
todoReconcileOnIdle: true,
|
|
421
589
|
}),
|
|
422
590
|
providers: z.record(z.string(), MutableDaemonProviderConfigSchema).default({}),
|
|
423
591
|
metadataGeneration: MutableMetadataGenerationConfigSchema.default({
|
|
@@ -481,6 +649,15 @@ export const MutableDaemonConfigSchema = z
|
|
|
481
649
|
maxRunningProbes: 2,
|
|
482
650
|
idleMinutes: 10,
|
|
483
651
|
}),
|
|
652
|
+
// Local AI host (otto-brain) management. Gated by server_info features.brainControl;
|
|
653
|
+
// defaults OFF and well-formed so a new client parsing an old daemon's config renders
|
|
654
|
+
// the row without ever implying the brain is running.
|
|
655
|
+
brain: MutableBrainConfigSchema.default(DEFAULT_MUTABLE_BRAIN_CONFIG),
|
|
656
|
+
// Host-wide connector registry (MCP servers surfaced as named, toggle-able
|
|
657
|
+
// integrations). Gated by server_info features.connectors; defaults to an
|
|
658
|
+
// empty roster so a new client parsing an old daemon's config still sees a
|
|
659
|
+
// well-formed section.
|
|
660
|
+
connectors: z.array(ConnectorConfigSchema).default([]),
|
|
484
661
|
})
|
|
485
662
|
.passthrough();
|
|
486
663
|
export const MutableDaemonConfigPatchSchema = z
|
|
@@ -495,6 +672,7 @@ export const MutableDaemonConfigPatchSchema = z
|
|
|
495
672
|
providers: z
|
|
496
673
|
.record(z.string(), MutableDaemonProviderConfigSchema.partial().passthrough().nullable())
|
|
497
674
|
.optional(),
|
|
675
|
+
removeProviders: z.array(z.string().min(1)).optional(),
|
|
498
676
|
metadataGeneration: MutableMetadataGenerationConfigSchema.partial().optional(),
|
|
499
677
|
autoArchiveAfterMerge: z.boolean().optional(),
|
|
500
678
|
// Gated by server_info features.hideMergeIntoBaseSetting.
|
|
@@ -529,6 +707,15 @@ export const MutableDaemonConfigPatchSchema = z
|
|
|
529
707
|
lsp: MutableLspConfigSchema.partial().optional(),
|
|
530
708
|
// Gated by server_info features.solutionView; patches deep-merge.
|
|
531
709
|
dotnetSolutionManagement: MutableDotnetSolutionConfigSchema.partial().optional(),
|
|
710
|
+
// Gated by server_info features.brainControl; patches deep-merge. Uses the
|
|
711
|
+
// dedicated no-default patch schema (see MutableBrainConfigPatchSchema): a
|
|
712
|
+
// plain `.partial()` here keeps every field's default and resets the whole
|
|
713
|
+
// block on a single-field patch.
|
|
714
|
+
brain: MutableBrainConfigPatchSchema.optional(),
|
|
715
|
+
// Gated by server_info features.connectors. Replaces the full array
|
|
716
|
+
// (read-modify-write), matching modelTierOverrides/savedProviderEndpoints, so
|
|
717
|
+
// enabling/disabling a connector or a tool is a whole-array rewrite.
|
|
718
|
+
connectors: z.array(ConnectorConfigSchema).optional(),
|
|
532
719
|
})
|
|
533
720
|
.partial()
|
|
534
721
|
.passthrough();
|
|
@@ -618,6 +805,7 @@ export const ProviderSnapshotEntrySchema = z.object({
|
|
|
618
805
|
provider: AgentProviderSchema,
|
|
619
806
|
status: ProviderStatusSchema,
|
|
620
807
|
enabled: z.boolean().optional().default(true),
|
|
808
|
+
source: z.enum(["builtin", "custom"]).optional(),
|
|
621
809
|
error: z.string().optional(),
|
|
622
810
|
models: z.array(AgentModelDefinitionSchema).optional(),
|
|
623
811
|
modes: z.array(AgentModeSchema).optional(),
|
|
@@ -891,6 +1079,7 @@ export const AgentTimelineItemPayloadSchema = z.union([
|
|
|
891
1079
|
type: z.literal("user_message"),
|
|
892
1080
|
text: z.string(),
|
|
893
1081
|
messageId: z.string().optional(),
|
|
1082
|
+
clientMessageId: z.string().optional(),
|
|
894
1083
|
}),
|
|
895
1084
|
z.object({
|
|
896
1085
|
type: z.literal("assistant_message"),
|
|
@@ -918,6 +1107,8 @@ export const AgentTimelineItemPayloadSchema = z.union([
|
|
|
918
1107
|
// COMPAT(compactionFailedStatus): "failed" added in v0.4.3. Clients older
|
|
919
1108
|
// than that drop the whole timeline event on parse and keep showing the
|
|
920
1109
|
// loading row — exactly their pre-"failed" behavior, so no gate is needed.
|
|
1110
|
+
// Nothing to remove: this tag records why the enum could be widened without
|
|
1111
|
+
// a shim, so it has no cleanup date by design.
|
|
921
1112
|
status: z.enum(["loading", "completed", "failed"]),
|
|
922
1113
|
trigger: z.enum(["auto", "manual"]).optional(),
|
|
923
1114
|
preTokens: z.number().optional(),
|
|
@@ -979,6 +1170,7 @@ export const AgentStreamEventPayloadSchema = z.discriminatedUnion("type", [
|
|
|
979
1170
|
body: z.string(),
|
|
980
1171
|
data: z.object({
|
|
981
1172
|
serverId: z.string(),
|
|
1173
|
+
workspaceId: z.string().optional(),
|
|
982
1174
|
agentId: z.string(),
|
|
983
1175
|
reason: z.enum(["finished", "error", "permission"]),
|
|
984
1176
|
}),
|
|
@@ -1030,6 +1222,13 @@ export const QueuedAgentMessagePayloadSchema = z.object({
|
|
|
1030
1222
|
preview: z.string(),
|
|
1031
1223
|
enqueuedAt: z.string(),
|
|
1032
1224
|
attachmentCount: z.number().int().nonnegative().optional(),
|
|
1225
|
+
/**
|
|
1226
|
+
* Who parked the message. Absent (from an older daemon) or "user" is a normal
|
|
1227
|
+
* user turn; "system" marks a system-injected entry (a chat mention, a
|
|
1228
|
+
* scheduled fire) that the daemon's drain never merges into a user turn — the
|
|
1229
|
+
* client must likewise exclude it from "Send all".
|
|
1230
|
+
*/
|
|
1231
|
+
source: z.enum(["user", "system"]).optional(),
|
|
1033
1232
|
});
|
|
1034
1233
|
/**
|
|
1035
1234
|
* An agent's LIFETIME SPEND, kept as the real token split plus the provider's
|
|
@@ -1106,7 +1305,9 @@ export const AgentSnapshotPayloadSchema = z.object({
|
|
|
1106
1305
|
// a finished agent isn't "running Bash"). Both are purely additive optional
|
|
1107
1306
|
// leaves: a provider that can't report them leaves them absent and the row
|
|
1108
1307
|
// omits the readout rather than showing a wrong value.
|
|
1109
|
-
// COMPAT(subagentLiveness): added in v0.6.7
|
|
1308
|
+
// COMPAT(subagentLiveness): added in v0.6.7, drop the optional gate when the
|
|
1309
|
+
// floor is >= v0.6.7. Old clients ignore both fields and show the row without
|
|
1310
|
+
// its liveness readouts, which is their pre-v0.6.7 behaviour.
|
|
1110
1311
|
// See docs/chat-lifecycle.md (the subagents track).
|
|
1111
1312
|
toolUseCount: z.number().optional(),
|
|
1112
1313
|
currentTool: z.string().optional(),
|
|
@@ -1129,6 +1330,14 @@ export const AgentSnapshotPayloadSchema = z.object({
|
|
|
1129
1330
|
// COMPAT(observedSubagents): added in v0.4.3; absent ⇒ "attended". Drop the
|
|
1130
1331
|
// gate when daemon floor >= v0.4.3. See projects/observed-subagents/observed-subagents.md.
|
|
1131
1332
|
attend: z.enum(["attended", "observed"]).optional(),
|
|
1333
|
+
// True when an observed sub-agent run outlives an interrupt of the parent's
|
|
1334
|
+
// turn: a backgrounded Task/Agent (its tool_result was only a launch ack) or
|
|
1335
|
+
// a Workflow orchestration run. The client uses it to stop claiming that
|
|
1336
|
+
// interrupting the parent stops work it will not actually stop.
|
|
1337
|
+
// COMPAT(backgroundedObservedSubagents): added in v0.7.5; absent ⇒ treated as
|
|
1338
|
+
// foreground, which is the pre-existing behavior. Drop the gate when daemon
|
|
1339
|
+
// floor >= v0.7.5. See docs/chat-lifecycle.md.
|
|
1340
|
+
backgrounded: z.boolean().optional(),
|
|
1132
1341
|
// Spinner colors from the Agent Personality this agent was spawned from, so
|
|
1133
1342
|
// its live thinking indicator renders in the personality's identity. Absent ⇒
|
|
1134
1343
|
// the client falls back to the theme's default spinner colors. Purely additive
|
|
@@ -1313,6 +1522,459 @@ export const AttachmentsImagesClearResponseSchema = z.object({
|
|
|
1313
1522
|
requestId: z.string(),
|
|
1314
1523
|
}),
|
|
1315
1524
|
});
|
|
1525
|
+
// --- Local AI host (otto-brain) management -------------------------------
|
|
1526
|
+
// Lifecycle + evals are correlated request/response RPCs. Gated by
|
|
1527
|
+
// server_info.features.brainControl (lifecycle) and features.brainStatus
|
|
1528
|
+
// (evals). Live status streaming (subscribe_brain_status + brain_status_changed)
|
|
1529
|
+
// is added alongside its client/daemon consumers.
|
|
1530
|
+
// The brain's host status, as the daemon derives it: liveness plus the fields
|
|
1531
|
+
// proxied from the brain's own `/__host/status`. Passthrough on the opaque
|
|
1532
|
+
// sub-objects so the brain can evolve them without a protocol bump.
|
|
1533
|
+
export const BrainHostStatusSchema = z
|
|
1534
|
+
.object({
|
|
1535
|
+
running: z.boolean(),
|
|
1536
|
+
pid: z.number().nullable().optional(),
|
|
1537
|
+
version: z.string().nullable().optional(),
|
|
1538
|
+
host: z.string().nullable().optional(),
|
|
1539
|
+
port: z.number().nullable().optional(),
|
|
1540
|
+
displayHost: z.string().nullable().optional(),
|
|
1541
|
+
secure: z.boolean().optional(),
|
|
1542
|
+
state: z.string().nullable().optional(),
|
|
1543
|
+
model: z.string().nullable().optional(),
|
|
1544
|
+
modelId: z.string().nullable().optional(),
|
|
1545
|
+
vramBytes: z.number().nullable().optional(),
|
|
1546
|
+
loadSeconds: z.number().nullable().optional(),
|
|
1547
|
+
startedAt: z.string().nullable().optional(),
|
|
1548
|
+
lastError: z.string().nullable().optional(),
|
|
1549
|
+
telemetry: z.record(z.string(), z.unknown()).nullable().optional(),
|
|
1550
|
+
scheduler: z.record(z.string(), z.unknown()).nullable().optional(),
|
|
1551
|
+
recent: z.array(z.record(z.string(), z.unknown())).optional(),
|
|
1552
|
+
})
|
|
1553
|
+
.passthrough();
|
|
1554
|
+
const BrainHostStatusResultSchema = z.object({
|
|
1555
|
+
status: BrainHostStatusSchema,
|
|
1556
|
+
error: z.string().nullable(),
|
|
1557
|
+
requestId: z.string(),
|
|
1558
|
+
});
|
|
1559
|
+
export const BrainHostStatusRequestSchema = z.object({
|
|
1560
|
+
type: z.literal("brain.host.status.request"),
|
|
1561
|
+
requestId: z.string(),
|
|
1562
|
+
});
|
|
1563
|
+
export const BrainHostStatusResponseSchema = z.object({
|
|
1564
|
+
type: z.literal("brain.host.status.response"),
|
|
1565
|
+
payload: BrainHostStatusResultSchema,
|
|
1566
|
+
});
|
|
1567
|
+
export const BrainHostStartRequestSchema = z.object({
|
|
1568
|
+
type: z.literal("brain.host.start.request"),
|
|
1569
|
+
// Optional model fragment/id to load on start; null = the brain's default.
|
|
1570
|
+
model: z.string().nullable().default(null),
|
|
1571
|
+
requestId: z.string(),
|
|
1572
|
+
});
|
|
1573
|
+
export const BrainHostStartResponseSchema = z.object({
|
|
1574
|
+
type: z.literal("brain.host.start.response"),
|
|
1575
|
+
payload: BrainHostStatusResultSchema,
|
|
1576
|
+
});
|
|
1577
|
+
export const BrainHostStopRequestSchema = z.object({
|
|
1578
|
+
type: z.literal("brain.host.stop.request"),
|
|
1579
|
+
requestId: z.string(),
|
|
1580
|
+
});
|
|
1581
|
+
export const BrainHostStopResponseSchema = z.object({
|
|
1582
|
+
type: z.literal("brain.host.stop.response"),
|
|
1583
|
+
payload: BrainHostStatusResultSchema,
|
|
1584
|
+
});
|
|
1585
|
+
export const BrainHostRestartRequestSchema = z.object({
|
|
1586
|
+
type: z.literal("brain.host.restart.request"),
|
|
1587
|
+
model: z.string().nullable().default(null),
|
|
1588
|
+
requestId: z.string(),
|
|
1589
|
+
});
|
|
1590
|
+
export const BrainHostRestartResponseSchema = z.object({
|
|
1591
|
+
type: z.literal("brain.host.restart.response"),
|
|
1592
|
+
payload: BrainHostStatusResultSchema,
|
|
1593
|
+
});
|
|
1594
|
+
// Benchmark rankings/variance/latest, proxied from the brain's `/__host/evals`.
|
|
1595
|
+
export const BrainEvalsSchema = z
|
|
1596
|
+
.object({
|
|
1597
|
+
rankings: z.array(z.record(z.string(), z.unknown())).default([]),
|
|
1598
|
+
latest: z.array(z.record(z.string(), z.unknown())).default([]),
|
|
1599
|
+
variance: z.array(z.record(z.string(), z.unknown())).default([]),
|
|
1600
|
+
runCount: z.number().default(0),
|
|
1601
|
+
})
|
|
1602
|
+
.passthrough();
|
|
1603
|
+
export const BrainEvalsGetRequestSchema = z.object({
|
|
1604
|
+
type: z.literal("brain.evals.get.request"),
|
|
1605
|
+
requestId: z.string(),
|
|
1606
|
+
});
|
|
1607
|
+
export const BrainEvalsGetResponseSchema = z.object({
|
|
1608
|
+
type: z.literal("brain.evals.get.response"),
|
|
1609
|
+
payload: z.object({
|
|
1610
|
+
evals: BrainEvalsSchema.nullable(),
|
|
1611
|
+
error: z.string().nullable(),
|
|
1612
|
+
requestId: z.string(),
|
|
1613
|
+
}),
|
|
1614
|
+
});
|
|
1615
|
+
// Brain network auto-discovery: the daemon enumerates this host's bind
|
|
1616
|
+
// addresses and probes the local `tailscale` CLI so the client can offer the
|
|
1617
|
+
// operator a pick-list of likely listen hosts (and pre-fill the tailscale TLS
|
|
1618
|
+
// mode) instead of asking them to hunt for IPs by hand.
|
|
1619
|
+
// Gated by server_info.features.brainNetworkDiscovery.
|
|
1620
|
+
export const BrainTailscaleInfoSchema = z
|
|
1621
|
+
.object({
|
|
1622
|
+
// Whether the tailscale CLI is present and its daemon answers.
|
|
1623
|
+
available: z.boolean(),
|
|
1624
|
+
// This machine's MagicDNS name, e.g. greyskull.tail279562.ts.net.
|
|
1625
|
+
hostname: z.string().nullable().optional(),
|
|
1626
|
+
// The tailnet IPv4 address, for a tailnet-only bind.
|
|
1627
|
+
ipv4: z.string().nullable().optional(),
|
|
1628
|
+
// The default directory the brain writes issued certificates to.
|
|
1629
|
+
certDir: z.string().nullable().optional(),
|
|
1630
|
+
})
|
|
1631
|
+
.passthrough();
|
|
1632
|
+
// One candidate value for `listen.host`, with a human label for the pick-list.
|
|
1633
|
+
export const BrainBindAddressSchema = z
|
|
1634
|
+
.object({
|
|
1635
|
+
// The literal value written to listen.host (an IP, 0.0.0.0, or "tailscale").
|
|
1636
|
+
value: z.string(),
|
|
1637
|
+
// Display label, e.g. "Local only", "All interfaces", "192.168.1.42 (en0)".
|
|
1638
|
+
label: z.string(),
|
|
1639
|
+
kind: z.enum(["loopback", "all", "lan", "tailscale"]),
|
|
1640
|
+
})
|
|
1641
|
+
.passthrough();
|
|
1642
|
+
export const BrainNetworkInfoSchema = z
|
|
1643
|
+
.object({
|
|
1644
|
+
addresses: z.array(BrainBindAddressSchema).default([]),
|
|
1645
|
+
tailscale: BrainTailscaleInfoSchema.nullable().optional(),
|
|
1646
|
+
})
|
|
1647
|
+
.passthrough();
|
|
1648
|
+
// Detected model names for the settings pickers. Read from the brain's
|
|
1649
|
+
// /v1/models when it is reachable (local child up, or remote); empty otherwise,
|
|
1650
|
+
// which the client renders as a disabled picker. Gated by features.brainStatus.
|
|
1651
|
+
export const BrainModelsListRequestSchema = z.object({
|
|
1652
|
+
type: z.literal("brain.models.list.request"),
|
|
1653
|
+
requestId: z.string(),
|
|
1654
|
+
});
|
|
1655
|
+
export const BrainModelsListResponseSchema = z.object({
|
|
1656
|
+
type: z.literal("brain.models.list.response"),
|
|
1657
|
+
payload: z.object({
|
|
1658
|
+
models: z.array(z.string()).default([]),
|
|
1659
|
+
error: z.string().nullable(),
|
|
1660
|
+
requestId: z.string(),
|
|
1661
|
+
}),
|
|
1662
|
+
});
|
|
1663
|
+
// Read/write a *remote* brain's own config (its /__host/config). Only valid in
|
|
1664
|
+
// brain.mode "remote"; the config is the remote brain's effective config with
|
|
1665
|
+
// secrets redacted. Editable fields are model-related (defaultModel, lockModel);
|
|
1666
|
+
// network/TLS/auth stay host-owned. Gated by features.brainRemote.
|
|
1667
|
+
export const BrainRemoteConfigSchema = z.record(z.string(), z.unknown());
|
|
1668
|
+
export const BrainRemoteConfigGetRequestSchema = z.object({
|
|
1669
|
+
type: z.literal("brain.remote.config.get.request"),
|
|
1670
|
+
requestId: z.string(),
|
|
1671
|
+
});
|
|
1672
|
+
export const BrainRemoteConfigGetResponseSchema = z.object({
|
|
1673
|
+
type: z.literal("brain.remote.config.get.response"),
|
|
1674
|
+
payload: z.object({
|
|
1675
|
+
config: BrainRemoteConfigSchema.nullable(),
|
|
1676
|
+
error: z.string().nullable(),
|
|
1677
|
+
requestId: z.string(),
|
|
1678
|
+
}),
|
|
1679
|
+
});
|
|
1680
|
+
export const BrainRemoteConfigPatchRequestSchema = z.object({
|
|
1681
|
+
type: z.literal("brain.remote.config.patch.request"),
|
|
1682
|
+
patch: BrainRemoteConfigSchema,
|
|
1683
|
+
requestId: z.string(),
|
|
1684
|
+
});
|
|
1685
|
+
export const BrainRemoteConfigPatchResponseSchema = z.object({
|
|
1686
|
+
type: z.literal("brain.remote.config.patch.response"),
|
|
1687
|
+
payload: z.object({
|
|
1688
|
+
config: BrainRemoteConfigSchema.nullable(),
|
|
1689
|
+
error: z.string().nullable(),
|
|
1690
|
+
requestId: z.string(),
|
|
1691
|
+
}),
|
|
1692
|
+
});
|
|
1693
|
+
export const BrainNetworkDiscoverRequestSchema = z.object({
|
|
1694
|
+
type: z.literal("brain.network.discover.request"),
|
|
1695
|
+
requestId: z.string(),
|
|
1696
|
+
});
|
|
1697
|
+
export const BrainNetworkDiscoverResponseSchema = z.object({
|
|
1698
|
+
type: z.literal("brain.network.discover.response"),
|
|
1699
|
+
payload: z.object({
|
|
1700
|
+
info: BrainNetworkInfoSchema.nullable(),
|
|
1701
|
+
error: z.string().nullable(),
|
|
1702
|
+
requestId: z.string(),
|
|
1703
|
+
}),
|
|
1704
|
+
});
|
|
1705
|
+
// --- Brain model management (runtimes, catalog, downloads, ops) ----------
|
|
1706
|
+
// The daemon drives these by shelling out to `otto-brain <verb> --json` (it
|
|
1707
|
+
// never imports the brain's runtime modules in-process). Reads (scan, catalog,
|
|
1708
|
+
// runtime list) are correlated request/response; long operations (pull, runtime
|
|
1709
|
+
// install, calibrate, sweep, bench) run as tracked JOBS the client polls via
|
|
1710
|
+
// brain.jobs.list. All gated by server_info.features.brainManage.
|
|
1711
|
+
// An installed local model, from `otto-brain scan`. Passthrough so the brain's
|
|
1712
|
+
// scan row can grow fields without a protocol bump.
|
|
1713
|
+
export const BrainInstalledModelSchema = z
|
|
1714
|
+
.object({
|
|
1715
|
+
model: z.string().default(""),
|
|
1716
|
+
arch: z.string().default(""),
|
|
1717
|
+
quant: z.string().default(""),
|
|
1718
|
+
size: z.string().default(""),
|
|
1719
|
+
ctx: z.string().default(""),
|
|
1720
|
+
vision: z.string().default(""),
|
|
1721
|
+
calibrated: z.string().default(""),
|
|
1722
|
+
features: z.string().default(""),
|
|
1723
|
+
source: z.string().default(""),
|
|
1724
|
+
})
|
|
1725
|
+
.passthrough();
|
|
1726
|
+
// A downloadable catalog model, annotated with whether it is already installed
|
|
1727
|
+
// (the daemon reuses the brain's authoritative catalog↔model join). Passthrough
|
|
1728
|
+
// over the catalog entry's optional metadata.
|
|
1729
|
+
export const BrainCatalogModelSchema = z
|
|
1730
|
+
.object({
|
|
1731
|
+
id: z.string(),
|
|
1732
|
+
name: z.string().default(""),
|
|
1733
|
+
installed: z.boolean().default(false),
|
|
1734
|
+
publisher: z.string().default(""),
|
|
1735
|
+
repo: z.string().default(""),
|
|
1736
|
+
quant: z.string().default(""),
|
|
1737
|
+
params: z.string().default(""),
|
|
1738
|
+
sizeBytes: z.number().nullable().optional(),
|
|
1739
|
+
size: z.string().default(""),
|
|
1740
|
+
vision: z.boolean().default(false),
|
|
1741
|
+
thinking: z.boolean().default(false),
|
|
1742
|
+
contextMax: z.number().nullable().optional(),
|
|
1743
|
+
tier: z.string().default(""),
|
|
1744
|
+
useCases: z.array(z.string()).default([]),
|
|
1745
|
+
why: z.string().default(""),
|
|
1746
|
+
})
|
|
1747
|
+
.passthrough();
|
|
1748
|
+
// An installed llama.cpp runtime, from `otto-brain runtime list`.
|
|
1749
|
+
export const BrainRuntimeSchema = z
|
|
1750
|
+
.object({
|
|
1751
|
+
label: z.string().default(""),
|
|
1752
|
+
version: z.string().default(""),
|
|
1753
|
+
source: z.string().default(""),
|
|
1754
|
+
dir: z.string().default(""),
|
|
1755
|
+
})
|
|
1756
|
+
.passthrough();
|
|
1757
|
+
// A tracked long-running brain operation. The client polls brain.jobs.list and
|
|
1758
|
+
// renders progress. `percent` is null when the job reports no measurable
|
|
1759
|
+
// progress (indeterminate). Terminal jobs linger briefly so the UI can show
|
|
1760
|
+
// the outcome before they are pruned.
|
|
1761
|
+
export const BrainJobKindSchema = z.enum([
|
|
1762
|
+
"pull",
|
|
1763
|
+
"runtime-install",
|
|
1764
|
+
"calibrate",
|
|
1765
|
+
"sweep",
|
|
1766
|
+
"bench",
|
|
1767
|
+
]);
|
|
1768
|
+
export const BrainJobStatusSchema = z.enum(["running", "succeeded", "failed", "canceled"]);
|
|
1769
|
+
export const BrainJobSchema = z
|
|
1770
|
+
.object({
|
|
1771
|
+
id: z.string(),
|
|
1772
|
+
kind: BrainJobKindSchema,
|
|
1773
|
+
// A short human label, e.g. "Download Phi-4 (14B)".
|
|
1774
|
+
label: z.string().default(""),
|
|
1775
|
+
// The subject id (catalog id, model name, or build tag) this job acts on.
|
|
1776
|
+
target: z.string().nullable().default(null),
|
|
1777
|
+
status: BrainJobStatusSchema.default("running"),
|
|
1778
|
+
percent: z.number().nullable().default(null),
|
|
1779
|
+
// The latest progress line (e.g. "extracting…", "budget 512: done").
|
|
1780
|
+
message: z.string().nullable().default(null),
|
|
1781
|
+
error: z.string().nullable().default(null),
|
|
1782
|
+
startedAt: z.string().default(""),
|
|
1783
|
+
finishedAt: z.string().nullable().default(null),
|
|
1784
|
+
})
|
|
1785
|
+
.passthrough();
|
|
1786
|
+
// Every job-starting RPC returns the created (or refused) job under this shape.
|
|
1787
|
+
const BrainJobResultSchema = z.object({
|
|
1788
|
+
job: BrainJobSchema.nullable(),
|
|
1789
|
+
error: z.string().nullable(),
|
|
1790
|
+
requestId: z.string(),
|
|
1791
|
+
});
|
|
1792
|
+
// Every job-listing RPC returns the active + recently-finished jobs.
|
|
1793
|
+
const BrainJobsResultSchema = z.object({
|
|
1794
|
+
jobs: z.array(BrainJobSchema).default([]),
|
|
1795
|
+
error: z.string().nullable(),
|
|
1796
|
+
requestId: z.string(),
|
|
1797
|
+
});
|
|
1798
|
+
// Installed models — `otto-brain scan`.
|
|
1799
|
+
export const BrainModelsScanRequestSchema = z.object({
|
|
1800
|
+
type: z.literal("brain.models.scan.request"),
|
|
1801
|
+
requestId: z.string(),
|
|
1802
|
+
});
|
|
1803
|
+
export const BrainModelsScanResponseSchema = z.object({
|
|
1804
|
+
type: z.literal("brain.models.scan.response"),
|
|
1805
|
+
payload: z.object({
|
|
1806
|
+
models: z.array(BrainInstalledModelSchema).default([]),
|
|
1807
|
+
error: z.string().nullable(),
|
|
1808
|
+
requestId: z.string(),
|
|
1809
|
+
}),
|
|
1810
|
+
});
|
|
1811
|
+
// Downloadable catalog — `otto-brain catalog`.
|
|
1812
|
+
export const BrainCatalogListRequestSchema = z.object({
|
|
1813
|
+
type: z.literal("brain.catalog.list.request"),
|
|
1814
|
+
requestId: z.string(),
|
|
1815
|
+
});
|
|
1816
|
+
export const BrainCatalogListResponseSchema = z.object({
|
|
1817
|
+
type: z.literal("brain.catalog.list.response"),
|
|
1818
|
+
payload: z.object({
|
|
1819
|
+
models: z.array(BrainCatalogModelSchema).default([]),
|
|
1820
|
+
error: z.string().nullable(),
|
|
1821
|
+
requestId: z.string(),
|
|
1822
|
+
}),
|
|
1823
|
+
});
|
|
1824
|
+
// Installed runtimes — `otto-brain runtime list`.
|
|
1825
|
+
export const BrainRuntimeListRequestSchema = z.object({
|
|
1826
|
+
type: z.literal("brain.runtime.list.request"),
|
|
1827
|
+
requestId: z.string(),
|
|
1828
|
+
});
|
|
1829
|
+
export const BrainRuntimeListResponseSchema = z.object({
|
|
1830
|
+
type: z.literal("brain.runtime.list.response"),
|
|
1831
|
+
payload: z.object({
|
|
1832
|
+
runtimes: z.array(BrainRuntimeSchema).default([]),
|
|
1833
|
+
error: z.string().nullable(),
|
|
1834
|
+
requestId: z.string(),
|
|
1835
|
+
}),
|
|
1836
|
+
});
|
|
1837
|
+
// Download a catalog model — starts a `pull` job.
|
|
1838
|
+
export const BrainModelsPullRequestSchema = z.object({
|
|
1839
|
+
type: z.literal("brain.models.pull.request"),
|
|
1840
|
+
// Catalog id or name fragment.
|
|
1841
|
+
model: z.string(),
|
|
1842
|
+
requestId: z.string(),
|
|
1843
|
+
});
|
|
1844
|
+
export const BrainModelsPullResponseSchema = z.object({
|
|
1845
|
+
type: z.literal("brain.models.pull.response"),
|
|
1846
|
+
payload: BrainJobResultSchema,
|
|
1847
|
+
});
|
|
1848
|
+
// Install a llama.cpp runtime — starts a `runtime-install` job.
|
|
1849
|
+
export const BrainRuntimeInstallRequestSchema = z.object({
|
|
1850
|
+
type: z.literal("brain.runtime.install.request"),
|
|
1851
|
+
// Optional llama.cpp release build tag; null = the brain's default.
|
|
1852
|
+
build: z.string().nullable().default(null),
|
|
1853
|
+
requestId: z.string(),
|
|
1854
|
+
});
|
|
1855
|
+
export const BrainRuntimeInstallResponseSchema = z.object({
|
|
1856
|
+
type: z.literal("brain.runtime.install.response"),
|
|
1857
|
+
payload: BrainJobResultSchema,
|
|
1858
|
+
});
|
|
1859
|
+
// Measure real KV bytes/token for a model — starts a `calibrate` job. Needs a
|
|
1860
|
+
// runtime + GPU; refused with a helpful error otherwise.
|
|
1861
|
+
export const BrainCalibrateRequestSchema = z.object({
|
|
1862
|
+
type: z.literal("brain.calibrate.request"),
|
|
1863
|
+
model: z.string(),
|
|
1864
|
+
requestId: z.string(),
|
|
1865
|
+
});
|
|
1866
|
+
export const BrainCalibrateResponseSchema = z.object({
|
|
1867
|
+
type: z.literal("brain.calibrate.response"),
|
|
1868
|
+
payload: BrainJobResultSchema,
|
|
1869
|
+
});
|
|
1870
|
+
// Find the best reasoning budget for a model — starts a `sweep` job.
|
|
1871
|
+
export const BrainSweepRequestSchema = z.object({
|
|
1872
|
+
type: z.literal("brain.sweep.request"),
|
|
1873
|
+
model: z.string(),
|
|
1874
|
+
requestId: z.string(),
|
|
1875
|
+
});
|
|
1876
|
+
export const BrainSweepResponseSchema = z.object({
|
|
1877
|
+
type: z.literal("brain.sweep.response"),
|
|
1878
|
+
payload: BrainJobResultSchema,
|
|
1879
|
+
});
|
|
1880
|
+
// Run the agentic-coding benchmark — starts a `bench` job. `model` is an
|
|
1881
|
+
// optional comma list of name fragments; null lets the brain pick.
|
|
1882
|
+
export const BrainBenchRequestSchema = z.object({
|
|
1883
|
+
type: z.literal("brain.bench.request"),
|
|
1884
|
+
model: z.string().nullable().default(null),
|
|
1885
|
+
requestId: z.string(),
|
|
1886
|
+
});
|
|
1887
|
+
export const BrainBenchResponseSchema = z.object({
|
|
1888
|
+
type: z.literal("brain.bench.response"),
|
|
1889
|
+
payload: BrainJobResultSchema,
|
|
1890
|
+
});
|
|
1891
|
+
// Poll the active + recently-finished jobs.
|
|
1892
|
+
export const BrainJobsListRequestSchema = z.object({
|
|
1893
|
+
type: z.literal("brain.jobs.list.request"),
|
|
1894
|
+
requestId: z.string(),
|
|
1895
|
+
});
|
|
1896
|
+
export const BrainJobsListResponseSchema = z.object({
|
|
1897
|
+
type: z.literal("brain.jobs.list.response"),
|
|
1898
|
+
payload: BrainJobsResultSchema,
|
|
1899
|
+
});
|
|
1900
|
+
// Cancel a running job; returns the refreshed job list.
|
|
1901
|
+
export const BrainJobsCancelRequestSchema = z.object({
|
|
1902
|
+
type: z.literal("brain.jobs.cancel.request"),
|
|
1903
|
+
jobId: z.string(),
|
|
1904
|
+
requestId: z.string(),
|
|
1905
|
+
});
|
|
1906
|
+
export const BrainJobsCancelResponseSchema = z.object({
|
|
1907
|
+
type: z.literal("brain.jobs.cancel.response"),
|
|
1908
|
+
payload: BrainJobsResultSchema,
|
|
1909
|
+
});
|
|
1910
|
+
// --- Hugging Face discovery (search + add arbitrary repos) ---------------
|
|
1911
|
+
// The daemon shells out to `otto-brain search`/`add --json`. Reads are
|
|
1912
|
+
// correlated request/response; the download runs as a `pull` job. Gated by
|
|
1913
|
+
// server_info.features.brainHfSearch. The brain resolves its own HF token (env
|
|
1914
|
+
// HF_TOKEN or its config), so no secret crosses this boundary.
|
|
1915
|
+
// One GGUF repo from a Hugging Face search. Passthrough so the brain's search
|
|
1916
|
+
// row can grow fields without a protocol bump.
|
|
1917
|
+
export const BrainHfSearchResultSchema = z
|
|
1918
|
+
.object({
|
|
1919
|
+
repo: z.string().default(""),
|
|
1920
|
+
downloads: z.number().default(0),
|
|
1921
|
+
likes: z.number().default(0),
|
|
1922
|
+
gated: z.boolean().default(false),
|
|
1923
|
+
// True when any quant of this repo is already on disk.
|
|
1924
|
+
installed: z.boolean().default(false),
|
|
1925
|
+
})
|
|
1926
|
+
.passthrough();
|
|
1927
|
+
// One downloadable quantization of a repo — `otto-brain add <repo> --list-quants`.
|
|
1928
|
+
export const BrainRepoQuantSchema = z
|
|
1929
|
+
.object({
|
|
1930
|
+
quant: z.string().default(""),
|
|
1931
|
+
size: z.string().default(""),
|
|
1932
|
+
sizeBytes: z.number().default(0),
|
|
1933
|
+
files: z.number().default(0),
|
|
1934
|
+
// True when this specific quant is already on disk.
|
|
1935
|
+
installed: z.boolean().default(false),
|
|
1936
|
+
})
|
|
1937
|
+
.passthrough();
|
|
1938
|
+
// Search Hugging Face for GGUF models — `otto-brain search <query>`.
|
|
1939
|
+
export const BrainHfSearchRequestSchema = z.object({
|
|
1940
|
+
type: z.literal("brain.hf.search.request"),
|
|
1941
|
+
query: z.string(),
|
|
1942
|
+
limit: z.number().nullable().default(null),
|
|
1943
|
+
requestId: z.string(),
|
|
1944
|
+
});
|
|
1945
|
+
export const BrainHfSearchResponseSchema = z.object({
|
|
1946
|
+
type: z.literal("brain.hf.search.response"),
|
|
1947
|
+
payload: z.object({
|
|
1948
|
+
results: z.array(BrainHfSearchResultSchema).default([]),
|
|
1949
|
+
error: z.string().nullable(),
|
|
1950
|
+
requestId: z.string(),
|
|
1951
|
+
}),
|
|
1952
|
+
});
|
|
1953
|
+
// List the quantizations a repo offers — `otto-brain add <repo> --list-quants`.
|
|
1954
|
+
export const BrainHfQuantsRequestSchema = z.object({
|
|
1955
|
+
type: z.literal("brain.hf.quants.request"),
|
|
1956
|
+
repo: z.string(),
|
|
1957
|
+
requestId: z.string(),
|
|
1958
|
+
});
|
|
1959
|
+
export const BrainHfQuantsResponseSchema = z.object({
|
|
1960
|
+
type: z.literal("brain.hf.quants.response"),
|
|
1961
|
+
payload: z.object({
|
|
1962
|
+
quants: z.array(BrainRepoQuantSchema).default([]),
|
|
1963
|
+
error: z.string().nullable(),
|
|
1964
|
+
requestId: z.string(),
|
|
1965
|
+
}),
|
|
1966
|
+
});
|
|
1967
|
+
// Download a chosen quant of an arbitrary HF repo — starts a `pull` job.
|
|
1968
|
+
export const BrainModelsAddRequestSchema = z.object({
|
|
1969
|
+
type: z.literal("brain.models.add.request"),
|
|
1970
|
+
repo: z.string(),
|
|
1971
|
+
quant: z.string(),
|
|
1972
|
+
requestId: z.string(),
|
|
1973
|
+
});
|
|
1974
|
+
export const BrainModelsAddResponseSchema = z.object({
|
|
1975
|
+
type: z.literal("brain.models.add.response"),
|
|
1976
|
+
payload: BrainJobResultSchema,
|
|
1977
|
+
});
|
|
1316
1978
|
export const ProjectRenameRequestSchema = z.object({
|
|
1317
1979
|
type: z.literal("project.rename.request"),
|
|
1318
1980
|
projectId: z.string(),
|
|
@@ -1356,6 +2018,22 @@ export const WorkspaceTitleSetRequestSchema = z.object({
|
|
|
1356
2018
|
title: z.string().nullable(),
|
|
1357
2019
|
requestId: z.string(),
|
|
1358
2020
|
});
|
|
2021
|
+
export const WorkspacePinSetRequestSchema = z.object({
|
|
2022
|
+
type: z.literal("workspace.pin.set.request"),
|
|
2023
|
+
workspaceId: z.string(),
|
|
2024
|
+
pinned: z.boolean(),
|
|
2025
|
+
requestId: z.string(),
|
|
2026
|
+
});
|
|
2027
|
+
export const WorkspaceRecoveryInspectRequestSchema = z.object({
|
|
2028
|
+
type: z.literal("workspace.recovery.inspect.request"),
|
|
2029
|
+
workspaceId: z.string(),
|
|
2030
|
+
requestId: z.string(),
|
|
2031
|
+
});
|
|
2032
|
+
export const WorkspaceRecoveryRestoreRequestSchema = z.object({
|
|
2033
|
+
type: z.literal("workspace.recovery.restore.request"),
|
|
2034
|
+
workspaceId: z.string(),
|
|
2035
|
+
requestId: z.string(),
|
|
2036
|
+
});
|
|
1359
2037
|
export const SetVoiceModeMessageSchema = z.object({
|
|
1360
2038
|
type: z.literal("set_voice_mode"),
|
|
1361
2039
|
enabled: z.boolean(),
|
|
@@ -1372,6 +2050,18 @@ export const GitHubPrAttachmentSchema = z.object({
|
|
|
1372
2050
|
baseRefName: z.string().nullable().optional(),
|
|
1373
2051
|
headRefName: z.string().nullable().optional(),
|
|
1374
2052
|
});
|
|
2053
|
+
export const ForgeChangeRequestAttachmentSchema = z.object({
|
|
2054
|
+
type: z.literal("forge_change_request"),
|
|
2055
|
+
mimeType: z.literal("application/otto-forge-change-request"),
|
|
2056
|
+
forge: z.string().optional().default("github"),
|
|
2057
|
+
number: z.number().int().positive(),
|
|
2058
|
+
title: z.string(),
|
|
2059
|
+
url: z.string(),
|
|
2060
|
+
body: z.string().nullable().optional(),
|
|
2061
|
+
projectPath: z.string().optional(),
|
|
2062
|
+
baseRefName: z.string().nullable().optional(),
|
|
2063
|
+
headRefName: z.string().nullable().optional(),
|
|
2064
|
+
});
|
|
1375
2065
|
export const GitHubIssueAttachmentSchema = z.object({
|
|
1376
2066
|
type: z.literal("github_issue"),
|
|
1377
2067
|
mimeType: z.literal("application/github-issue"),
|
|
@@ -1380,10 +2070,13 @@ export const GitHubIssueAttachmentSchema = z.object({
|
|
|
1380
2070
|
url: z.string(),
|
|
1381
2071
|
body: z.string().nullable().optional(),
|
|
1382
2072
|
});
|
|
1383
|
-
//
|
|
1384
|
-
//
|
|
1385
|
-
//
|
|
1386
|
-
// client sends
|
|
2073
|
+
// COMPAT(hostingAttachments): added in v0.7.6, remove after 2027-02-01.
|
|
2074
|
+
// These were the provider-neutral successors to github_pr/github_issue. The
|
|
2075
|
+
// forge merge replaced them with forge_change_request/forge_issue, so no
|
|
2076
|
+
// current client sends them — they stay accepted (protocol contract) purely so
|
|
2077
|
+
// a client from before that merge can still attach a PR or an issue. The
|
|
2078
|
+
// daemon renders them at
|
|
2079
|
+
// server/src/server/agent/prompt-attachments.ts; retire both halves together.
|
|
1387
2080
|
export const HostingPrAttachmentSchema = z.object({
|
|
1388
2081
|
type: z.literal("hosting_pr"),
|
|
1389
2082
|
mimeType: z.literal("application/otto-hosting-pr"),
|
|
@@ -1404,6 +2097,16 @@ export const HostingIssueAttachmentSchema = z.object({
|
|
|
1404
2097
|
url: z.string(),
|
|
1405
2098
|
body: z.string().nullable().optional(),
|
|
1406
2099
|
});
|
|
2100
|
+
export const ForgeIssueAttachmentSchema = z.object({
|
|
2101
|
+
type: z.literal("forge_issue"),
|
|
2102
|
+
mimeType: z.literal("application/otto-forge-issue"),
|
|
2103
|
+
forge: z.string().optional().default("github"),
|
|
2104
|
+
number: z.number().int().positive(),
|
|
2105
|
+
title: z.string(),
|
|
2106
|
+
url: z.string(),
|
|
2107
|
+
body: z.string().nullable().optional(),
|
|
2108
|
+
projectPath: z.string().optional(),
|
|
2109
|
+
});
|
|
1407
2110
|
export const TextAttachmentSchema = z
|
|
1408
2111
|
.object({
|
|
1409
2112
|
type: z.literal("text"),
|
|
@@ -1450,6 +2153,8 @@ export const UploadedFileAttachmentSchema = z.object({
|
|
|
1450
2153
|
path: z.string(),
|
|
1451
2154
|
});
|
|
1452
2155
|
export const AgentAttachmentSchema = z.discriminatedUnion("type", [
|
|
2156
|
+
ForgeChangeRequestAttachmentSchema,
|
|
2157
|
+
ForgeIssueAttachmentSchema,
|
|
1453
2158
|
GitHubPrAttachmentSchema,
|
|
1454
2159
|
GitHubIssueAttachmentSchema,
|
|
1455
2160
|
HostingPrAttachmentSchema,
|
|
@@ -1472,6 +2177,12 @@ function normalizeAgentAttachments(input) {
|
|
|
1472
2177
|
return normalized;
|
|
1473
2178
|
}
|
|
1474
2179
|
const AgentAttachmentsSchema = z.unknown().transform(normalizeAgentAttachments).optional();
|
|
2180
|
+
export const ChangeRequestCheckoutSourceSchema = z.object({
|
|
2181
|
+
kind: z.literal("change_request"),
|
|
2182
|
+
forge: z.string().optional(),
|
|
2183
|
+
number: z.number().int().positive(),
|
|
2184
|
+
projectPath: z.string().optional(),
|
|
2185
|
+
});
|
|
1475
2186
|
const ImageAttachmentSchema = z.object({
|
|
1476
2187
|
data: z.string(), // base64 encoded image
|
|
1477
2188
|
mimeType: z.string(), // e.g., "image/jpeg", "image/png"
|
|
@@ -1546,6 +2257,10 @@ export const FetchWorkspacesRequestMessageSchema = z.object({
|
|
|
1546
2257
|
})
|
|
1547
2258
|
.optional(),
|
|
1548
2259
|
});
|
|
2260
|
+
export const ProjectListRequestMessageSchema = z.object({
|
|
2261
|
+
type: z.literal("project.list.request"),
|
|
2262
|
+
requestId: z.string(),
|
|
2263
|
+
});
|
|
1549
2264
|
export const FetchAgentHistoryRequestMessageSchema = z.object({
|
|
1550
2265
|
type: z.literal("fetch_agent_history_request"),
|
|
1551
2266
|
requestId: z.string(),
|
|
@@ -1643,6 +2358,21 @@ export const DaemonGetPairingOfferRequestSchema = z.object({
|
|
|
1643
2358
|
type: z.literal("daemon.get_pairing_offer.request"),
|
|
1644
2359
|
requestId: z.string(),
|
|
1645
2360
|
});
|
|
2361
|
+
export const HubManagementDaemonConnectRequestSchema = z.object({
|
|
2362
|
+
type: z.literal("hub.management.daemon.connect.request"),
|
|
2363
|
+
requestId: z.string(),
|
|
2364
|
+
hubUrl: z.string(),
|
|
2365
|
+
token: z.string(),
|
|
2366
|
+
});
|
|
2367
|
+
export const HubManagementDaemonGetStatusRequestSchema = z.object({
|
|
2368
|
+
type: z.literal("hub.management.daemon.get_status.request"),
|
|
2369
|
+
requestId: z.string(),
|
|
2370
|
+
});
|
|
2371
|
+
export const HubManagementDaemonDisconnectRequestSchema = z.object({
|
|
2372
|
+
type: z.literal("hub.management.daemon.disconnect.request"),
|
|
2373
|
+
requestId: z.string(),
|
|
2374
|
+
force: z.boolean().optional(),
|
|
2375
|
+
});
|
|
1646
2376
|
export const DiagnosticsRequestSchema = z.object({
|
|
1647
2377
|
type: z.literal("diagnostics.request"),
|
|
1648
2378
|
requestId: z.string(),
|
|
@@ -1656,6 +2386,33 @@ export const SetDaemonConfigRequestMessageSchema = z.object({
|
|
|
1656
2386
|
requestId: z.string(),
|
|
1657
2387
|
config: MutableDaemonConfigPatchSchema,
|
|
1658
2388
|
});
|
|
2389
|
+
// Connectors — MCP servers surfaced as named, toggle-able integrations. The
|
|
2390
|
+
// registry itself (add/remove/enable/disable a connector or an individual tool)
|
|
2391
|
+
// lives in daemon config and is edited via set_daemon_config's `connectors`
|
|
2392
|
+
// patch. The one thing config can't answer is what tools a connector actually
|
|
2393
|
+
// exposes, which needs a live connect + listTools — that is this RPC. Gated by
|
|
2394
|
+
// features.connectors.
|
|
2395
|
+
export const ConnectorsListToolsRequestSchema = z.object({
|
|
2396
|
+
type: z.literal("connectors.list_tools.request"),
|
|
2397
|
+
requestId: z.string(),
|
|
2398
|
+
connectorId: z.string(),
|
|
2399
|
+
});
|
|
2400
|
+
export const ConnectorsListToolsResponseSchema = z.object({
|
|
2401
|
+
type: z.literal("connectors.list_tools.response"),
|
|
2402
|
+
payload: z.object({
|
|
2403
|
+
connectorId: z.string(),
|
|
2404
|
+
tools: z
|
|
2405
|
+
.array(z.object({
|
|
2406
|
+
name: z.string(),
|
|
2407
|
+
description: z.string().nullable().default(null),
|
|
2408
|
+
disabled: z.boolean().default(false),
|
|
2409
|
+
}))
|
|
2410
|
+
.default([]),
|
|
2411
|
+
// Non-null when the connector could not be reached / enumerated.
|
|
2412
|
+
error: z.string().nullable(),
|
|
2413
|
+
requestId: z.string(),
|
|
2414
|
+
}),
|
|
2415
|
+
});
|
|
1659
2416
|
export const SpeechSettingsGetOptionsRequestSchema = z.object({
|
|
1660
2417
|
type: z.literal("speech.settings.get_options.request"),
|
|
1661
2418
|
requestId: z.string(),
|
|
@@ -1737,6 +2494,29 @@ export const AgentPersonalitiesGetStatsRequestSchema = z.object({
|
|
|
1737
2494
|
type: z.literal("agentPersonalities.get_stats.request"),
|
|
1738
2495
|
requestId: z.string(),
|
|
1739
2496
|
});
|
|
2497
|
+
// COMPAT(personalityProfile): added in v0.7.5; gate lives in
|
|
2498
|
+
// features.personalityProfile. Author a personality PROFILE (the prose
|
|
2499
|
+
// `personalityPrompt` that shapes how an agent behaves) from the only things
|
|
2500
|
+
// the editor knows before one exists: the handle, the roles it will be spawned
|
|
2501
|
+
// for, and its two spinner colors. Like the voice-cue RPC this is described
|
|
2502
|
+
// inline (not a stored id) so the editor can generate for an unsaved draft, and
|
|
2503
|
+
// is an editor-time action: the result lands in the prompt field for the user to
|
|
2504
|
+
// edit, and is stored on the personality by the ordinary save.
|
|
2505
|
+
export const AgentPersonalitiesGenerateProfileRequestSchema = z.object({
|
|
2506
|
+
type: z.literal("agentPersonalities.generate_profile.request"),
|
|
2507
|
+
requestId: z.string(),
|
|
2508
|
+
name: z.string(),
|
|
2509
|
+
// Permissive strings to match the stored personality shape (forward-compatible
|
|
2510
|
+
// with roles this daemon predates); the daemon filters to its known set.
|
|
2511
|
+
roles: z.array(z.string().min(1)).optional(),
|
|
2512
|
+
// The spinner glow pair, read as a palette (temperature, energy) and never
|
|
2513
|
+
// quoted literally in the profile.
|
|
2514
|
+
glowA: z.string().optional(),
|
|
2515
|
+
glowB: z.string().optional(),
|
|
2516
|
+
// Scopes provider resolution to a workspace; omitted falls back to any
|
|
2517
|
+
// resolvable one.
|
|
2518
|
+
cwd: z.string().optional(),
|
|
2519
|
+
});
|
|
1740
2520
|
export const ReadProjectConfigRequestMessageSchema = z.object({
|
|
1741
2521
|
type: z.literal("read_project_config_request"),
|
|
1742
2522
|
requestId: z.string(),
|
|
@@ -1781,6 +2561,9 @@ const GitSetupOptionsSchema = z.object({
|
|
|
1781
2561
|
worktreeSlug: z.string().optional(),
|
|
1782
2562
|
refName: z.string().min(1).optional(),
|
|
1783
2563
|
action: z.enum(["branch-off", "checkout"]).optional(),
|
|
2564
|
+
checkoutSource: ChangeRequestCheckoutSourceSchema.optional(),
|
|
2565
|
+
// COMPAT(githubPrNumber): added in v0.1.106, remove after 2026-12-28 once
|
|
2566
|
+
// clients send checkoutSource.
|
|
1784
2567
|
githubPrNumber: z.number().int().positive().optional(),
|
|
1785
2568
|
});
|
|
1786
2569
|
export const CreateAgentWorktreeTargetSchema = z.discriminatedUnion("mode", [
|
|
@@ -1809,6 +2592,9 @@ export const CreateAgentRequestMessageSchema = z.object({
|
|
|
1809
2592
|
personality: z.string().optional(),
|
|
1810
2593
|
env: z.record(z.string(), z.string()).optional(),
|
|
1811
2594
|
workspaceId: z.string().optional(),
|
|
2595
|
+
// Optional caller context lets managed CLI invocations use the same daemon-owned
|
|
2596
|
+
// workspace and parentage policy as agent-scoped MCP creation.
|
|
2597
|
+
callerAgentId: z.string().optional(),
|
|
1812
2598
|
worktreeName: z.string().optional(),
|
|
1813
2599
|
initialPrompt: z.string().optional(),
|
|
1814
2600
|
clientMessageId: z.string().optional(),
|
|
@@ -2080,9 +2866,29 @@ export const FetchAgentTimelineRequestMessageSchema = z.object({
|
|
|
2080
2866
|
// Default should be projected for app timeline loading.
|
|
2081
2867
|
projection: z.enum(["projected", "canonical"]).optional(),
|
|
2082
2868
|
});
|
|
2869
|
+
export const ProviderSubagentListRequestMessageSchema = z.object({
|
|
2870
|
+
type: z.literal("agent.provider_subagents.list.request"),
|
|
2871
|
+
parentAgentId: z.string(),
|
|
2872
|
+
requestId: z.string(),
|
|
2873
|
+
});
|
|
2874
|
+
export const ProviderSubagentTimelineRequestMessageSchema = z.object({
|
|
2875
|
+
type: z.literal("agent.provider_subagents.timeline.get.request"),
|
|
2876
|
+
parentAgentId: z.string(),
|
|
2877
|
+
subagentId: z.string(),
|
|
2878
|
+
requestId: z.string(),
|
|
2879
|
+
direction: z.enum(["tail", "before", "after"]).optional(),
|
|
2880
|
+
cursor: AgentTimelineCursorSchema.optional(),
|
|
2881
|
+
limit: z.number().int().nonnegative().optional(),
|
|
2882
|
+
});
|
|
2883
|
+
export const SetAgentTimelineSubscriptionRequestMessageSchema = z.object({
|
|
2884
|
+
type: z.literal("agent.timeline.set_subscription.request"),
|
|
2885
|
+
agentIds: z.array(z.string()),
|
|
2886
|
+
requestId: z.string(),
|
|
2887
|
+
});
|
|
2083
2888
|
export const AgentForkContextRequestMessageSchema = z.object({
|
|
2084
2889
|
type: z.literal("agent.fork_context.request"),
|
|
2085
2890
|
agentId: z.string(),
|
|
2891
|
+
boundaryCursor: AgentTimelineCursorSchema.optional(),
|
|
2086
2892
|
boundaryMessageId: z.string().optional(),
|
|
2087
2893
|
requestId: z.string(),
|
|
2088
2894
|
});
|
|
@@ -2802,6 +3608,48 @@ export const AgentWorkspaceTransferResponseMessageSchema = z.object({
|
|
|
2802
3608
|
type: z.literal("agent.workspace.transfer.response"),
|
|
2803
3609
|
payload: AgentWorkspaceTransferResponsePayloadSchema,
|
|
2804
3610
|
});
|
|
3611
|
+
export const WorkspacePinSetResponsePayloadSchema = z.object({
|
|
3612
|
+
requestId: z.string(),
|
|
3613
|
+
workspaceId: z.string(),
|
|
3614
|
+
accepted: z.boolean(),
|
|
3615
|
+
pinnedAt: z.string().nullable(),
|
|
3616
|
+
error: z.string().nullable(),
|
|
3617
|
+
});
|
|
3618
|
+
export const WorkspacePinSetResponseSchema = z.object({
|
|
3619
|
+
type: z.literal("workspace.pin.set.response"),
|
|
3620
|
+
payload: WorkspacePinSetResponsePayloadSchema,
|
|
3621
|
+
});
|
|
3622
|
+
export const WorkspaceRecoveryStateSchema = z.discriminatedUnion("kind", [
|
|
3623
|
+
z.object({
|
|
3624
|
+
kind: z.literal("recoverable"),
|
|
3625
|
+
workspaceId: z.string(),
|
|
3626
|
+
workspaceName: z.string(),
|
|
3627
|
+
action: z.string(),
|
|
3628
|
+
branch: z.string().nullable(),
|
|
3629
|
+
}),
|
|
3630
|
+
z.object({
|
|
3631
|
+
kind: z.literal("unavailable"),
|
|
3632
|
+
workspaceId: z.string(),
|
|
3633
|
+
reason: z.string(),
|
|
3634
|
+
message: z.string(),
|
|
3635
|
+
}),
|
|
3636
|
+
]);
|
|
3637
|
+
export const WorkspaceRecoveryInspectResponseSchema = z.object({
|
|
3638
|
+
type: z.literal("workspace.recovery.inspect.response"),
|
|
3639
|
+
payload: z.object({
|
|
3640
|
+
requestId: z.string(),
|
|
3641
|
+
state: WorkspaceRecoveryStateSchema,
|
|
3642
|
+
}),
|
|
3643
|
+
});
|
|
3644
|
+
export const WorkspaceRecoveryRestoreResponseSchema = z.object({
|
|
3645
|
+
type: z.literal("workspace.recovery.restore.response"),
|
|
3646
|
+
payload: z.object({
|
|
3647
|
+
requestId: z.string(),
|
|
3648
|
+
workspaceId: z.string(),
|
|
3649
|
+
accepted: z.boolean(),
|
|
3650
|
+
error: z.string().nullable(),
|
|
3651
|
+
}),
|
|
3652
|
+
});
|
|
2805
3653
|
export const SetVoiceModeResponseMessageSchema = z.object({
|
|
2806
3654
|
type: z.literal("set_voice_mode_response"),
|
|
2807
3655
|
payload: z.object({
|
|
@@ -3262,6 +4110,15 @@ export const CheckoutPrMergeRequestSchema = z.object({
|
|
|
3262
4110
|
mergeMethod: z.enum(["merge", "squash", "rebase"]),
|
|
3263
4111
|
requestId: z.string(),
|
|
3264
4112
|
});
|
|
4113
|
+
export const CheckoutForgeSetAutoMergeRequestSchema = z.object({
|
|
4114
|
+
type: z.literal("checkout.forge.set_auto_merge.request"),
|
|
4115
|
+
cwd: z.string(),
|
|
4116
|
+
enabled: z.boolean(),
|
|
4117
|
+
mergeMethod: z.enum(["merge", "squash", "rebase"]).optional(),
|
|
4118
|
+
requestId: z.string(),
|
|
4119
|
+
});
|
|
4120
|
+
// COMPAT(githubAutoMergeRpc): added in v0.1.106, remove after 2026-12-28 once
|
|
4121
|
+
// all supported clients use checkout.forge.set_auto_merge.*.
|
|
3265
4122
|
export const CheckoutGithubSetAutoMergeRequestSchema = z.object({
|
|
3266
4123
|
type: z.literal("checkout.github.set_auto_merge.request"),
|
|
3267
4124
|
cwd: z.string(),
|
|
@@ -3269,16 +4126,63 @@ export const CheckoutGithubSetAutoMergeRequestSchema = z.object({
|
|
|
3269
4126
|
mergeMethod: z.enum(["merge", "squash", "rebase"]).optional(),
|
|
3270
4127
|
requestId: z.string(),
|
|
3271
4128
|
});
|
|
4129
|
+
const CheckoutCommitFileSchema = z.object({
|
|
4130
|
+
path: z.string(),
|
|
4131
|
+
additions: z.number(),
|
|
4132
|
+
deletions: z.number(),
|
|
4133
|
+
status: z.enum(["added", "modified", "deleted", "renamed"]).optional(),
|
|
4134
|
+
});
|
|
4135
|
+
const CheckoutCommitSchema = z.object({
|
|
4136
|
+
sha: z.string(),
|
|
4137
|
+
shortSha: z.string(),
|
|
4138
|
+
subject: z.string(),
|
|
4139
|
+
authorName: z.string(),
|
|
4140
|
+
authorDate: z.string(), // ISO 8601
|
|
4141
|
+
isOnRemote: z.boolean(), // false = local-only (unpushed)
|
|
4142
|
+
// COMPAT(commitBaseClassification): added in v0.2.0, remove optional after 2027-01-23.
|
|
4143
|
+
isOnBase: z.boolean().optional(),
|
|
4144
|
+
files: z.array(CheckoutCommitFileSchema),
|
|
4145
|
+
});
|
|
4146
|
+
export const CheckoutCommitsListRequestSchema = z.object({
|
|
4147
|
+
type: z.literal("checkout.commits.list.request"),
|
|
4148
|
+
cwd: z.string(),
|
|
4149
|
+
requestId: z.string(),
|
|
4150
|
+
});
|
|
4151
|
+
export const CheckoutCommitFileDiffRequestSchema = z.object({
|
|
4152
|
+
type: z.literal("checkout.commits.file_diff.request"),
|
|
4153
|
+
cwd: z.string(),
|
|
4154
|
+
sha: z.string(),
|
|
4155
|
+
path: z.string(),
|
|
4156
|
+
requestId: z.string(),
|
|
4157
|
+
});
|
|
3272
4158
|
const GitHubRepoSegmentSchema = z.string().regex(/^[A-Za-z0-9._-]+$/);
|
|
3273
|
-
|
|
3274
|
-
type: z.literal("checkout.github.get_check_details.request"),
|
|
4159
|
+
const CheckoutCheckDetailsRequestPayloadSchema = z.object({
|
|
3275
4160
|
cwd: z.string(),
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
4161
|
+
// GitHub addresses check runs by owner/name. GitLab resolves the project from
|
|
4162
|
+
// cwd and omits these GitHub-only single-segment fields.
|
|
4163
|
+
repoOwner: GitHubRepoSegmentSchema.optional(),
|
|
4164
|
+
repoName: GitHubRepoSegmentSchema.optional(),
|
|
4165
|
+
// Permanently optional: a check addressed only by workflowRunId (Gitea
|
|
4166
|
+
// Actions runs carry no check-run id) is fetchable. Callers send at least one
|
|
4167
|
+
// of checkRunId/workflowRunId; the gated forge RPC only reaches daemons that
|
|
4168
|
+
// understand this.
|
|
4169
|
+
checkRunId: z.number().int().positive().optional(),
|
|
3279
4170
|
workflowRunId: z.number().int().positive().optional(),
|
|
4171
|
+
// Permanent forge-routing field, optional because only some forges need it:
|
|
4172
|
+
// GitLab routes check details to the MR's head pipeline; Gitea-family adapters
|
|
4173
|
+
// resolve the PR head SHA by number, including after merge/close. GitHub
|
|
4174
|
+
// ignores it.
|
|
4175
|
+
changeRequestNumber: z.number().int().positive().optional(),
|
|
3280
4176
|
requestId: z.string(),
|
|
3281
4177
|
});
|
|
4178
|
+
export const CheckoutForgeGetCheckDetailsRequestSchema = CheckoutCheckDetailsRequestPayloadSchema.extend({
|
|
4179
|
+
type: z.literal("checkout.forge.get_check_details.request"),
|
|
4180
|
+
});
|
|
4181
|
+
// COMPAT(githubCheckDetailsRpc): added in v0.1.106, remove after 2026-12-28 once
|
|
4182
|
+
// all supported clients use checkout.forge.get_check_details.*.
|
|
4183
|
+
export const CheckoutGithubGetCheckDetailsRequestSchema = CheckoutCheckDetailsRequestPayloadSchema.extend({
|
|
4184
|
+
type: z.literal("checkout.github.get_check_details.request"),
|
|
4185
|
+
});
|
|
3282
4186
|
export const CheckoutPrStatusRequestSchema = z.object({
|
|
3283
4187
|
type: z.literal("checkout_pr_status_request"),
|
|
3284
4188
|
cwd: z.string(),
|
|
@@ -3367,17 +4271,41 @@ export const BranchSuggestionsRequestSchema = z.object({
|
|
|
3367
4271
|
});
|
|
3368
4272
|
export const GitHubSearchItemSchema = z.object({
|
|
3369
4273
|
kind: z.enum(["issue", "pr"]),
|
|
4274
|
+
forge: z.string().optional(),
|
|
3370
4275
|
number: z.number(),
|
|
3371
4276
|
title: z.string(),
|
|
3372
4277
|
url: z.string(),
|
|
3373
4278
|
state: z.string(),
|
|
3374
4279
|
body: z.string().nullable(),
|
|
3375
4280
|
labels: z.array(z.string()),
|
|
4281
|
+
projectPath: z.string().optional(),
|
|
3376
4282
|
baseRefName: z.string().nullable().optional(),
|
|
3377
4283
|
headRefName: z.string().nullable().optional(),
|
|
3378
4284
|
updatedAt: z.string().optional(),
|
|
3379
4285
|
});
|
|
3380
|
-
export const
|
|
4286
|
+
export const ForgeSearchItemSchema = GitHubSearchItemSchema.extend({
|
|
4287
|
+
kind: z.enum(["issue", "change_request"]),
|
|
4288
|
+
});
|
|
4289
|
+
// COMPAT(githubSearchKind): added in v0.1.106, remove with the legacy
|
|
4290
|
+
// github_search_request RPC after 2026-12-28.
|
|
4291
|
+
export const ForgeSearchKindSchema = z.enum([
|
|
4292
|
+
"issue",
|
|
4293
|
+
"change_request",
|
|
4294
|
+
"github-issue",
|
|
4295
|
+
"github-pr",
|
|
4296
|
+
"pr",
|
|
4297
|
+
]);
|
|
4298
|
+
export const GitHubSearchKindSchema = ForgeSearchKindSchema;
|
|
4299
|
+
export const ForgeSearchRequestSchema = z.object({
|
|
4300
|
+
type: z.literal("forge.search.request"),
|
|
4301
|
+
cwd: z.string(),
|
|
4302
|
+
query: z.string(),
|
|
4303
|
+
limit: z.number().int().min(1).max(50).optional(),
|
|
4304
|
+
kinds: z.array(ForgeSearchKindSchema).optional(),
|
|
4305
|
+
requestId: z.string(),
|
|
4306
|
+
});
|
|
4307
|
+
// COMPAT(githubSearchRpc): added in v0.1.106, remove after 2026-12-28 once
|
|
4308
|
+
// clients use forge.search.*.
|
|
3381
4309
|
export const GitHubSearchRequestSchema = z.object({
|
|
3382
4310
|
type: z.literal("github_search_request"),
|
|
3383
4311
|
cwd: z.string(),
|
|
@@ -3458,6 +4386,9 @@ export const CreateOttoWorktreeRequestSchema = z.object({
|
|
|
3458
4386
|
firstAgentContext: FirstAgentContextSchema.optional(),
|
|
3459
4387
|
refName: z.string().min(1).optional(),
|
|
3460
4388
|
action: z.enum(["branch-off", "checkout"]).optional(),
|
|
4389
|
+
checkoutSource: ChangeRequestCheckoutSourceSchema.optional(),
|
|
4390
|
+
// COMPAT(githubPrNumber): added in v0.1.106, remove after 2026-12-28 once
|
|
4391
|
+
// clients send checkoutSource: { kind: "change_request", forge, number }.
|
|
3461
4392
|
githubPrNumber: z.number().int().positive().optional(),
|
|
3462
4393
|
requestId: z.string(),
|
|
3463
4394
|
});
|
|
@@ -3485,6 +4416,8 @@ export const OpenProjectRequestSchema = z.object({
|
|
|
3485
4416
|
cwd: z.string(),
|
|
3486
4417
|
requestId: z.string(),
|
|
3487
4418
|
});
|
|
4419
|
+
// Smallest shorthand repo path is "a/b": owner, slash, repository.
|
|
4420
|
+
const MIN_REPOSITORY_PATH_LENGTH = 3;
|
|
3488
4421
|
export const ProjectAddRequestSchema = z.object({
|
|
3489
4422
|
type: z.literal("project.add.request"),
|
|
3490
4423
|
cwd: z.string(),
|
|
@@ -3580,6 +4513,35 @@ export const HostingListOwnersRequestSchema = z.object({
|
|
|
3580
4513
|
provider: GitHostingProviderIdWireSchema,
|
|
3581
4514
|
requestId: z.string(),
|
|
3582
4515
|
});
|
|
4516
|
+
export const ProjectCreateDirectoryRequestSchema = z.object({
|
|
4517
|
+
type: z.literal("project.create_directory.request"),
|
|
4518
|
+
parentPath: z.string(),
|
|
4519
|
+
name: z.string(),
|
|
4520
|
+
requestId: z.string(),
|
|
4521
|
+
});
|
|
4522
|
+
export const GithubRepositorySchema = z.object({
|
|
4523
|
+
id: z.string().min(1),
|
|
4524
|
+
name: z.string().min(1),
|
|
4525
|
+
nameWithOwner: z.string().min(MIN_REPOSITORY_PATH_LENGTH),
|
|
4526
|
+
description: z.string().nullable(),
|
|
4527
|
+
visibility: z.enum(["public", "private", "internal"]),
|
|
4528
|
+
updatedAt: z.string(),
|
|
4529
|
+
cloneUrl: z.string().min(MIN_REPOSITORY_PATH_LENGTH),
|
|
4530
|
+
});
|
|
4531
|
+
export const WorkspaceGithubSearchRepositoriesRequestSchema = z.object({
|
|
4532
|
+
type: z.literal("workspace.github.search_repositories.request"),
|
|
4533
|
+
query: z.string(),
|
|
4534
|
+
limit: z.number().int().min(1).max(50).optional(),
|
|
4535
|
+
requestId: z.string(),
|
|
4536
|
+
});
|
|
4537
|
+
export const ProjectGithubCloneProtocolSchema = z.enum(["https", "ssh"]);
|
|
4538
|
+
export const ProjectGithubCloneRequestSchema = z.object({
|
|
4539
|
+
type: z.literal("project.github.clone.request"),
|
|
4540
|
+
repo: z.string().trim().min(MIN_REPOSITORY_PATH_LENGTH),
|
|
4541
|
+
cloneProtocol: ProjectGithubCloneProtocolSchema.optional(),
|
|
4542
|
+
targetDirectory: z.string().trim().min(1),
|
|
4543
|
+
requestId: z.string(),
|
|
4544
|
+
});
|
|
3583
4545
|
export const ArchiveWorkspaceRequestSchema = z.object({
|
|
3584
4546
|
type: z.literal("archive_workspace_request"),
|
|
3585
4547
|
workspaceId: z.string(),
|
|
@@ -3654,6 +4616,11 @@ export const WorkspaceCreateRequestSchema = z.object({
|
|
|
3654
4616
|
// the repository default.
|
|
3655
4617
|
refName: z.string().min(1).optional(),
|
|
3656
4618
|
baseBranch: z.string().optional(),
|
|
4619
|
+
// New branch name for branch-off. The worktree path may use a different slug.
|
|
4620
|
+
branchName: z.string().min(1).optional(),
|
|
4621
|
+
checkoutSource: ChangeRequestCheckoutSourceSchema.optional(),
|
|
4622
|
+
// COMPAT(githubPrNumber): added in v0.1.106, remove after 2026-12-28 once
|
|
4623
|
+
// clients send checkoutSource.
|
|
3657
4624
|
githubPrNumber: z.number().int().positive().optional(),
|
|
3658
4625
|
worktreeSlug: z.string().optional(),
|
|
3659
4626
|
}),
|
|
@@ -3743,6 +4710,7 @@ const FileExplorerFileSchema = z.object({
|
|
|
3743
4710
|
// inline JSON read path only); old daemons omit both fields.
|
|
3744
4711
|
eol: FileEolSchema.optional(),
|
|
3745
4712
|
hash: z.string().optional(),
|
|
4713
|
+
revision: z.string().optional(),
|
|
3746
4714
|
});
|
|
3747
4715
|
const FileExplorerDirectorySchema = z.object({
|
|
3748
4716
|
path: z.string(),
|
|
@@ -3756,6 +4724,103 @@ export const FileExplorerRequestSchema = z.object({
|
|
|
3756
4724
|
requestId: z.string(),
|
|
3757
4725
|
acceptBinary: z.boolean().optional(),
|
|
3758
4726
|
});
|
|
4727
|
+
export const FileVersionSchema = z.discriminatedUnion("status", [
|
|
4728
|
+
z.object({
|
|
4729
|
+
status: z.literal("ready"),
|
|
4730
|
+
cwd: z.string(),
|
|
4731
|
+
path: z.string(),
|
|
4732
|
+
size: z.number().int().nonnegative(),
|
|
4733
|
+
modifiedAt: z.string(),
|
|
4734
|
+
revision: z.string().optional(),
|
|
4735
|
+
}),
|
|
4736
|
+
z.object({
|
|
4737
|
+
status: z.literal("missing"),
|
|
4738
|
+
cwd: z.string(),
|
|
4739
|
+
path: z.string(),
|
|
4740
|
+
}),
|
|
4741
|
+
z.object({
|
|
4742
|
+
status: z.literal("error"),
|
|
4743
|
+
cwd: z.string(),
|
|
4744
|
+
path: z.string(),
|
|
4745
|
+
error: z.string(),
|
|
4746
|
+
}),
|
|
4747
|
+
]);
|
|
4748
|
+
export const FileSubscribeRequestSchema = z.object({
|
|
4749
|
+
type: z.literal("fs.file.subscribe.request"),
|
|
4750
|
+
cwd: z.string(),
|
|
4751
|
+
path: z.string(),
|
|
4752
|
+
subscriptionId: z.string(),
|
|
4753
|
+
requestId: z.string(),
|
|
4754
|
+
});
|
|
4755
|
+
export const FileUnsubscribeRequestSchema = z.object({
|
|
4756
|
+
type: z.literal("fs.file.unsubscribe.request"),
|
|
4757
|
+
subscriptionId: z.string(),
|
|
4758
|
+
requestId: z.string(),
|
|
4759
|
+
});
|
|
4760
|
+
export const FsFileWriteRequestSchema = z.object({
|
|
4761
|
+
type: z.literal("fs.file.write.request"),
|
|
4762
|
+
cwd: z.string(),
|
|
4763
|
+
path: z.string(),
|
|
4764
|
+
content: z.string(),
|
|
4765
|
+
expectedModifiedAt: z.string(),
|
|
4766
|
+
expectedRevision: z.string().optional(),
|
|
4767
|
+
requestId: z.string(),
|
|
4768
|
+
});
|
|
4769
|
+
/**
|
|
4770
|
+
* Write bytes to a workspace file.
|
|
4771
|
+
*
|
|
4772
|
+
* The counterpart to `fs.file.write`, which is text only: it LF-normalizes,
|
|
4773
|
+
* re-applies the file's detected EOL, and outright refuses to overwrite a file
|
|
4774
|
+
* whose current bytes look binary. None of that can carry a PDF, an image or
|
|
4775
|
+
* any other generated artifact, so those go through here instead — the bytes
|
|
4776
|
+
* land verbatim.
|
|
4777
|
+
*
|
|
4778
|
+
* Deliberately not a conditional write. Callers are producing a generated file
|
|
4779
|
+
* from a source they already hold, so there is no "the file changed under you"
|
|
4780
|
+
* to reconcile: either the caller means to replace what is there or it does
|
|
4781
|
+
* not, and `overwrite` says which. Keeping that explicit is what stops this
|
|
4782
|
+
* from being a clobber-any-path primitive.
|
|
4783
|
+
*
|
|
4784
|
+
* Workspace-bounded, like the create/delete/rename surface and unlike
|
|
4785
|
+
* `file.write`. `file.write` is unbounded because a tab may edit a file the
|
|
4786
|
+
* user opened from anywhere; putting new bytes at an arbitrary path on the host
|
|
4787
|
+
* is a different power and does not need to be that wide.
|
|
4788
|
+
*
|
|
4789
|
+
* The bytes themselves do not ride in this message. They follow it as
|
|
4790
|
+
* `FileTransfer` binary frames correlated on `requestId` — FileBegin, then
|
|
4791
|
+
* FileChunk, then FileEnd — the same transport `file.upload` uses. This request
|
|
4792
|
+
* is the metadata half: where the bytes go and how many of them to expect.
|
|
4793
|
+
* Everything here writes multi-megabyte files (a printed PDF, a dropped image),
|
|
4794
|
+
* and base64 in a JSON message costs a third again on the wire plus the whole
|
|
4795
|
+
* encoded string allocated on both sides and walked by the validator.
|
|
4796
|
+
*/
|
|
4797
|
+
export const FsFileWriteBinaryRequestSchema = z.object({
|
|
4798
|
+
type: z.literal("fs.file.write_binary.request"),
|
|
4799
|
+
cwd: z.string(),
|
|
4800
|
+
path: z.string(),
|
|
4801
|
+
/**
|
|
4802
|
+
* Byte length of the payload to follow. The daemon refuses a transfer that
|
|
4803
|
+
* overruns it and refuses one that ends short, so a truncated stream fails
|
|
4804
|
+
* loudly instead of landing a half file. Optional only because the base64
|
|
4805
|
+
* form below predates it and carries its own length.
|
|
4806
|
+
*/
|
|
4807
|
+
size: z.number().int().nonnegative().optional(),
|
|
4808
|
+
/**
|
|
4809
|
+
* base64. Decoded and written as-is: no EOL translation, no re-encoding.
|
|
4810
|
+
*
|
|
4811
|
+
* COMPAT(binaryWriteBase64): added in v0.7.6, drop this field and its daemon
|
|
4812
|
+
* branch on 2027-02-02. Superseded by `size` plus file-transfer frames. The
|
|
4813
|
+
* daemon still reads it — a field we stopped sending is not a field we stop
|
|
4814
|
+
* accepting — and picks the branch from which of the two is present.
|
|
4815
|
+
*/
|
|
4816
|
+
contentBase64: z.string().optional(),
|
|
4817
|
+
/**
|
|
4818
|
+
* Replace an existing file. Absent (the default) an existing target comes
|
|
4819
|
+
* back as `exists` and nothing is written.
|
|
4820
|
+
*/
|
|
4821
|
+
overwrite: z.boolean().optional(),
|
|
4822
|
+
requestId: z.string(),
|
|
4823
|
+
});
|
|
3759
4824
|
export const ProjectIconRequestSchema = z.object({
|
|
3760
4825
|
type: z.literal("project_icon_request"),
|
|
3761
4826
|
cwd: z.string(),
|
|
@@ -4205,6 +5270,16 @@ export const CreateTerminalRequestSchema = z.object({
|
|
|
4205
5270
|
agentId: z.string().optional(),
|
|
4206
5271
|
command: z.string().optional(),
|
|
4207
5272
|
args: z.array(z.string()).optional(),
|
|
5273
|
+
// Initial PTY size. Added in v0.1.107; the app no longer sends it (the estimate cache that fed
|
|
5274
|
+
// it was removed — the pane-focus resize claim sizes the PTY instead). Kept and honored
|
|
5275
|
+
// permanently: released v0.1.107 clients still send it, and programmatic callers may pass an
|
|
5276
|
+
// exact size. Daemons without it start at 80x24 and the first resize corrects that.
|
|
5277
|
+
size: z
|
|
5278
|
+
.object({
|
|
5279
|
+
rows: z.number().int().positive(),
|
|
5280
|
+
cols: z.number().int().positive(),
|
|
5281
|
+
})
|
|
5282
|
+
.optional(),
|
|
4208
5283
|
requestId: z.string(),
|
|
4209
5284
|
});
|
|
4210
5285
|
export const RenameTerminalRequestSchema = z.object({
|
|
@@ -4219,6 +5294,31 @@ export const StartWorkspaceScriptRequestSchema = z.object({
|
|
|
4219
5294
|
scriptName: z.string(),
|
|
4220
5295
|
requestId: z.string(),
|
|
4221
5296
|
});
|
|
5297
|
+
export const WorkspaceScriptListRequestSchema = z.object({
|
|
5298
|
+
type: z.literal("workspace.script.list.request"),
|
|
5299
|
+
workspaceId: z.string(),
|
|
5300
|
+
requestId: z.string(),
|
|
5301
|
+
/**
|
|
5302
|
+
* Also return the Scripts the workspace's own project files declare
|
|
5303
|
+
* (`package.json` scripts, and later Makefile targets, .NET launch profiles),
|
|
5304
|
+
* each tagged with the `source` it came from. Off by default so a client that
|
|
5305
|
+
* predates discovery gets exactly the otto.json list it asked for.
|
|
5306
|
+
* COMPAT(workspaceScriptDiscovery): added in v0.7.6.
|
|
5307
|
+
*/
|
|
5308
|
+
includeDiscovered: z.boolean().optional().default(false),
|
|
5309
|
+
});
|
|
5310
|
+
export const WorkspaceScriptStartRequestSchema = z.object({
|
|
5311
|
+
type: z.literal("workspace.script.start.request"),
|
|
5312
|
+
workspaceId: z.string(),
|
|
5313
|
+
scriptName: z.string(),
|
|
5314
|
+
requestId: z.string(),
|
|
5315
|
+
});
|
|
5316
|
+
export const WorkspaceScriptStopRequestSchema = z.object({
|
|
5317
|
+
type: z.literal("workspace.script.stop.request"),
|
|
5318
|
+
workspaceId: z.string(),
|
|
5319
|
+
scriptName: z.string(),
|
|
5320
|
+
requestId: z.string(),
|
|
5321
|
+
});
|
|
4222
5322
|
export const SubscribeTerminalRequestSchema = z.object({
|
|
4223
5323
|
type: z.literal("subscribe_terminal_request"),
|
|
4224
5324
|
terminalId: z.string(),
|
|
@@ -4269,7 +5369,31 @@ export const CaptureTerminalRequestSchema = z.object({
|
|
|
4269
5369
|
stripAnsi: z.boolean().default(true),
|
|
4270
5370
|
requestId: z.string(),
|
|
4271
5371
|
});
|
|
5372
|
+
export const HubExecutionAgentCreateRequestSchema = z.object({
|
|
5373
|
+
type: z.literal("hub.execution.agent.create.request"),
|
|
5374
|
+
requestId: z.string(),
|
|
5375
|
+
executionId: z.string(),
|
|
5376
|
+
provider: z.string(),
|
|
5377
|
+
cwd: z.string(),
|
|
5378
|
+
prompt: z.string(),
|
|
5379
|
+
workspaceId: z.string().optional(),
|
|
5380
|
+
model: z.string().optional(),
|
|
5381
|
+
modeId: z.string().optional(),
|
|
5382
|
+
thinkingOptionId: z.string().optional(),
|
|
5383
|
+
featureValues: z.record(z.string(), z.unknown()).optional(),
|
|
5384
|
+
env: z.record(z.string(), z.string()).optional(),
|
|
5385
|
+
worktree: CreateAgentWorktreeTargetSchema.optional(),
|
|
5386
|
+
});
|
|
5387
|
+
export const HubExecutionControlActionSchema = z.enum(["interrupt", "archive"]);
|
|
5388
|
+
export const HubExecutionControlRequestSchema = z.object({
|
|
5389
|
+
type: z.literal("hub.execution.control.request"),
|
|
5390
|
+
requestId: z.string(),
|
|
5391
|
+
executionId: z.string(),
|
|
5392
|
+
action: HubExecutionControlActionSchema,
|
|
5393
|
+
});
|
|
4272
5394
|
export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
|
|
5395
|
+
HubExecutionAgentCreateRequestSchema,
|
|
5396
|
+
HubExecutionControlRequestSchema,
|
|
4273
5397
|
BrowserAutomationExecuteResponseSchema,
|
|
4274
5398
|
VoiceAudioChunkMessageSchema,
|
|
4275
5399
|
AbortRequestMessageSchema,
|
|
@@ -4278,6 +5402,7 @@ export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
4278
5402
|
FetchAgentHistoryRequestMessageSchema,
|
|
4279
5403
|
FetchRecentProviderSessionsRequestMessageSchema,
|
|
4280
5404
|
FetchWorkspacesRequestMessageSchema,
|
|
5405
|
+
ProjectListRequestMessageSchema,
|
|
4281
5406
|
FetchAgentRequestMessageSchema,
|
|
4282
5407
|
DeleteAgentRequestMessageSchema,
|
|
4283
5408
|
ArchiveAgentRequestMessageSchema,
|
|
@@ -4285,6 +5410,28 @@ export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
4285
5410
|
HistoryAgentsClearArchivedRequestSchema,
|
|
4286
5411
|
AttachmentsImagesStatsRequestSchema,
|
|
4287
5412
|
AttachmentsImagesClearRequestSchema,
|
|
5413
|
+
BrainHostStatusRequestSchema,
|
|
5414
|
+
BrainHostStartRequestSchema,
|
|
5415
|
+
BrainHostStopRequestSchema,
|
|
5416
|
+
BrainHostRestartRequestSchema,
|
|
5417
|
+
BrainEvalsGetRequestSchema,
|
|
5418
|
+
BrainNetworkDiscoverRequestSchema,
|
|
5419
|
+
BrainModelsListRequestSchema,
|
|
5420
|
+
BrainRemoteConfigGetRequestSchema,
|
|
5421
|
+
BrainRemoteConfigPatchRequestSchema,
|
|
5422
|
+
BrainModelsScanRequestSchema,
|
|
5423
|
+
BrainCatalogListRequestSchema,
|
|
5424
|
+
BrainRuntimeListRequestSchema,
|
|
5425
|
+
BrainModelsPullRequestSchema,
|
|
5426
|
+
BrainRuntimeInstallRequestSchema,
|
|
5427
|
+
BrainCalibrateRequestSchema,
|
|
5428
|
+
BrainSweepRequestSchema,
|
|
5429
|
+
BrainBenchRequestSchema,
|
|
5430
|
+
BrainJobsListRequestSchema,
|
|
5431
|
+
BrainJobsCancelRequestSchema,
|
|
5432
|
+
BrainHfSearchRequestSchema,
|
|
5433
|
+
BrainHfQuantsRequestSchema,
|
|
5434
|
+
BrainModelsAddRequestSchema,
|
|
4288
5435
|
UpdateAgentRequestMessageSchema,
|
|
4289
5436
|
ProjectRenameRequestSchema,
|
|
4290
5437
|
ProjectRemoveRequestSchema,
|
|
@@ -4292,20 +5439,28 @@ export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
4292
5439
|
ProjectLinksSetRequestSchema,
|
|
4293
5440
|
ProjectLinksUnsetRequestSchema,
|
|
4294
5441
|
WorkspaceTitleSetRequestSchema,
|
|
5442
|
+
WorkspacePinSetRequestSchema,
|
|
5443
|
+
WorkspaceRecoveryInspectRequestSchema,
|
|
5444
|
+
WorkspaceRecoveryRestoreRequestSchema,
|
|
4295
5445
|
SetVoiceModeMessageSchema,
|
|
4296
5446
|
SendAgentMessageRequestSchema,
|
|
4297
5447
|
WaitForFinishRequestSchema,
|
|
4298
5448
|
DaemonGetStatusRequestSchema,
|
|
4299
5449
|
DaemonGetPairingOfferRequestSchema,
|
|
5450
|
+
HubManagementDaemonConnectRequestSchema,
|
|
5451
|
+
HubManagementDaemonGetStatusRequestSchema,
|
|
5452
|
+
HubManagementDaemonDisconnectRequestSchema,
|
|
4300
5453
|
DiagnosticsRequestSchema,
|
|
4301
5454
|
GetDaemonConfigRequestMessageSchema,
|
|
4302
5455
|
SetDaemonConfigRequestMessageSchema,
|
|
5456
|
+
ConnectorsListToolsRequestSchema,
|
|
4303
5457
|
SpeechSettingsGetOptionsRequestSchema,
|
|
4304
5458
|
SpeechTtsPreviewRequestSchema,
|
|
4305
5459
|
SpeechTtsSpeakRequestSchema,
|
|
4306
5460
|
SpeechTtsSpeakCancelRequestSchema,
|
|
4307
5461
|
VisualizerVoiceCuesGenerateRequestSchema,
|
|
4308
5462
|
AgentPersonalitiesGetStatsRequestSchema,
|
|
5463
|
+
AgentPersonalitiesGenerateProfileRequestSchema,
|
|
4309
5464
|
ReadProjectConfigRequestMessageSchema,
|
|
4310
5465
|
WriteProjectConfigRequestMessageSchema,
|
|
4311
5466
|
DictationStreamStartMessageSchema,
|
|
@@ -4341,6 +5496,9 @@ export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
4341
5496
|
RestartServerRequestMessageSchema,
|
|
4342
5497
|
DaemonUpdateRequestMessageSchema,
|
|
4343
5498
|
FetchAgentTimelineRequestMessageSchema,
|
|
5499
|
+
ProviderSubagentListRequestMessageSchema,
|
|
5500
|
+
ProviderSubagentTimelineRequestMessageSchema,
|
|
5501
|
+
SetAgentTimelineSubscriptionRequestMessageSchema,
|
|
4344
5502
|
AgentForkContextRequestMessageSchema,
|
|
4345
5503
|
SetAgentModeRequestMessageSchema,
|
|
4346
5504
|
SetAgentModelRequestMessageSchema,
|
|
@@ -4390,7 +5548,11 @@ export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
4390
5548
|
CheckoutRefreshRequestSchema,
|
|
4391
5549
|
CheckoutPrCreateRequestSchema,
|
|
4392
5550
|
CheckoutPrMergeRequestSchema,
|
|
5551
|
+
CheckoutForgeSetAutoMergeRequestSchema,
|
|
4393
5552
|
CheckoutGithubSetAutoMergeRequestSchema,
|
|
5553
|
+
CheckoutCommitsListRequestSchema,
|
|
5554
|
+
CheckoutCommitFileDiffRequestSchema,
|
|
5555
|
+
CheckoutForgeGetCheckDetailsRequestSchema,
|
|
4394
5556
|
CheckoutGithubGetCheckDetailsRequestSchema,
|
|
4395
5557
|
PreviewListConfigRequestSchema,
|
|
4396
5558
|
PreviewStartRequestSchema,
|
|
@@ -4405,6 +5567,7 @@ export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
4405
5567
|
StashListRequestSchema,
|
|
4406
5568
|
ValidateBranchRequestSchema,
|
|
4407
5569
|
BranchSuggestionsRequestSchema,
|
|
5570
|
+
ForgeSearchRequestSchema,
|
|
4408
5571
|
GitHubSearchRequestSchema,
|
|
4409
5572
|
HostingSearchRequestSchema,
|
|
4410
5573
|
HostingAuthStatusRequestSchema,
|
|
@@ -4420,6 +5583,9 @@ export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
4420
5583
|
ProjectScaffoldRequestSchema,
|
|
4421
5584
|
HostingListRepositoriesRequestSchema,
|
|
4422
5585
|
HostingListOwnersRequestSchema,
|
|
5586
|
+
ProjectCreateDirectoryRequestSchema,
|
|
5587
|
+
WorkspaceGithubSearchRepositoriesRequestSchema,
|
|
5588
|
+
ProjectGithubCloneRequestSchema,
|
|
4423
5589
|
ArchiveWorkspaceRequestSchema,
|
|
4424
5590
|
WorkspaceArchivePreflightRequestSchema,
|
|
4425
5591
|
WorktreeBaseRefSetRequestSchema,
|
|
@@ -4428,6 +5594,10 @@ export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
4428
5594
|
WorkspaceCreateRequestSchema,
|
|
4429
5595
|
WorkspaceClearAttentionRequestSchema,
|
|
4430
5596
|
FileExplorerRequestSchema,
|
|
5597
|
+
FileSubscribeRequestSchema,
|
|
5598
|
+
FileUnsubscribeRequestSchema,
|
|
5599
|
+
FsFileWriteRequestSchema,
|
|
5600
|
+
FsFileWriteBinaryRequestSchema,
|
|
4431
5601
|
ProjectIconRequestSchema,
|
|
4432
5602
|
FileDownloadTokenRequestSchema,
|
|
4433
5603
|
FileUploadRequestSchema,
|
|
@@ -4467,6 +5637,9 @@ export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
4467
5637
|
CreateTerminalRequestSchema,
|
|
4468
5638
|
RenameTerminalRequestSchema,
|
|
4469
5639
|
StartWorkspaceScriptRequestSchema,
|
|
5640
|
+
WorkspaceScriptListRequestSchema,
|
|
5641
|
+
WorkspaceScriptStartRequestSchema,
|
|
5642
|
+
WorkspaceScriptStopRequestSchema,
|
|
4470
5643
|
SubscribeTerminalRequestSchema,
|
|
4471
5644
|
UnsubscribeTerminalRequestSchema,
|
|
4472
5645
|
TerminalInputSchema,
|
|
@@ -4641,14 +5814,23 @@ export const ServerInfoStatusPayloadSchema = z
|
|
|
4641
5814
|
serverId: z.string().trim().min(1),
|
|
4642
5815
|
hostname: ServerInfoHostnameSchema.optional(),
|
|
4643
5816
|
version: ServerInfoVersionSchema.optional(),
|
|
5817
|
+
// COMPAT(desktopManaged): added in v0.1.X, remove optional parsing after 2027-01-16.
|
|
5818
|
+
desktopManaged: z.boolean().optional(),
|
|
4644
5819
|
capabilities: ServerCapabilitiesFromUnknownSchema.optional(),
|
|
4645
5820
|
// COMPAT(providersSnapshot): added in v0.1.48, remove gating when all clients use snapshot
|
|
4646
5821
|
features: z
|
|
4647
5822
|
.object({
|
|
4648
5823
|
providersSnapshot: z.boolean().optional(),
|
|
5824
|
+
// COMPAT(checkoutForgeSetAutoMerge): added in v0.1.106, remove old
|
|
5825
|
+
// checkoutGithubSetAutoMerge fallback after 2026-12-28.
|
|
5826
|
+
checkoutForgeSetAutoMerge: z.boolean().optional(),
|
|
4649
5827
|
checkoutGithubSetAutoMerge: z.boolean().optional(),
|
|
4650
5828
|
// COMPAT(githubCheckDetails): added in v0.1.92, remove gate after 2026-12-08.
|
|
4651
5829
|
githubCheckDetails: z.boolean().optional(),
|
|
5830
|
+
// COMPAT(forgeCheckDetails): added in v0.1.106, remove githubCheckDetails fallback after 2026-12-28.
|
|
5831
|
+
forgeCheckDetails: z.boolean().optional(),
|
|
5832
|
+
// COMPAT(forgeSearch): added in v0.1.106, remove github_search fallback after 2026-12-28.
|
|
5833
|
+
forgeSearch: z.boolean().optional(),
|
|
4652
5834
|
// COMPAT(daemonStatusRpc): added in v0.1.76, remove gate after 2026-11-18.
|
|
4653
5835
|
daemonStatusRpc: z.boolean().optional(),
|
|
4654
5836
|
// COMPAT(terminalRestoreModes): added in v0.1.81, remove gate after 2026-11-23.
|
|
@@ -4671,14 +5853,55 @@ export const ServerInfoStatusPayloadSchema = z
|
|
|
4671
5853
|
projectScaffold: z.boolean().optional(),
|
|
4672
5854
|
// COMPAT(worktreeRestore): added in v0.1.97, drop the gate when floor >= v0.1.97
|
|
4673
5855
|
worktreeRestore: z.boolean().optional(),
|
|
5856
|
+
// COMPAT(workspaceRecovery): added in v0.1.105, remove after 2027-01-11 once daemon floor >= v0.1.105.
|
|
5857
|
+
workspaceRecovery: z.boolean().optional(),
|
|
5858
|
+
// COMPAT(workspaceFileEditing): added in v0.2.0, remove after 2027-01-18 once daemon floor >= v0.2.0.
|
|
5859
|
+
workspaceFileEditing: z.boolean().optional(),
|
|
4674
5860
|
// COMPAT(providerUsageList): added in v0.1.98, drop the gate when daemon floor >= v0.1.98.
|
|
4675
5861
|
providerUsageList: z.boolean().optional(),
|
|
4676
5862
|
// COMPAT(agentDetach): added in v0.1.98, remove gate after 2026-12-19 once daemon floor >= v0.1.98.
|
|
4677
5863
|
agentDetach: z.boolean().optional(),
|
|
5864
|
+
// COMPAT(agentThinkingUpdate): added in v0.2.4, remove gate after 2027-01-28.
|
|
5865
|
+
agentThinkingUpdate: z.boolean().optional(),
|
|
4678
5866
|
// COMPAT(daemonDiagnostics): added in v0.1.100, remove gate after 2026-12-25 once daemon floor >= v0.1.100.
|
|
4679
5867
|
daemonDiagnostics: z.boolean().optional(),
|
|
4680
5868
|
// COMPAT(daemonSelfUpdate): added in v0.1.93, remove gate after 2026-12-13.
|
|
4681
5869
|
daemonSelfUpdate: z.boolean().optional(),
|
|
5870
|
+
// Daemon manages the local AI host (otto-brain) as a child: reports
|
|
5871
|
+
// brain.host.status, serves brain.host.start/stop/restart, exposes the
|
|
5872
|
+
// editable `brain` config block, and honors kill-on-shutdown. Without it
|
|
5873
|
+
// the Local brain host UI is hidden ("update the host").
|
|
5874
|
+
// COMPAT(brainControl): added in v0.7.5, remove gate after 2026-01-30 once daemon floor >= v0.7.5.
|
|
5875
|
+
brainControl: z.boolean().optional(),
|
|
5876
|
+
// Daemon streams the brain's live status/telemetry via
|
|
5877
|
+
// subscribe_brain_status + brain_status_changed, and serves brain.evals.get.
|
|
5878
|
+
// Separate from brainControl because status/eval watching can ship after
|
|
5879
|
+
// lifecycle control. Without it the Brain dashboard falls back to a
|
|
5880
|
+
// periodic brain.host.status poll (no live feed, no eval charts).
|
|
5881
|
+
// COMPAT(brainStatus): added in v0.7.5, remove gate after 2026-01-30 once daemon floor >= v0.7.5.
|
|
5882
|
+
brainStatus: z.boolean().optional(),
|
|
5883
|
+
// Daemon serves brain.network.discover: enumerates this host's bind
|
|
5884
|
+
// addresses and probes the local `tailscale` CLI, so the client can
|
|
5885
|
+
// offer a listen-host pick-list and auto-fill the tailscale TLS mode.
|
|
5886
|
+
// COMPAT(brainNetworkDiscovery): added in v0.7.5, remove gate after 2026-07-30 once daemon floor >= v0.7.5.
|
|
5887
|
+
brainNetworkDiscovery: z.boolean().optional(),
|
|
5888
|
+
// Daemon can point the brain at a remote host (brain.mode "remote"):
|
|
5889
|
+
// status/evals/config proxied from another Otto's brain, no local spawn.
|
|
5890
|
+
// COMPAT(brainRemote): added in v0.7.5, remove gate after 2026-07-30 once daemon floor >= v0.7.5.
|
|
5891
|
+
brainRemote: z.boolean().optional(),
|
|
5892
|
+
// Daemon manages the brain's models and runtimes by shelling out to the
|
|
5893
|
+
// otto-brain CLI: serves brain.models.scan / brain.catalog.list /
|
|
5894
|
+
// brain.runtime.list (reads) and starts brain.models.pull /
|
|
5895
|
+
// brain.runtime.install / brain.calibrate / brain.sweep / brain.bench as
|
|
5896
|
+
// tracked jobs polled via brain.jobs.list. Without it the Brain "Models"
|
|
5897
|
+
// and "Operations" sections are hidden ("update the host").
|
|
5898
|
+
// COMPAT(brainManage): added in v0.7.5, remove gate after 2026-07-30 once daemon floor >= v0.7.5.
|
|
5899
|
+
brainManage: z.boolean().optional(),
|
|
5900
|
+
// Daemon serves brain.hf.search / brain.hf.quants (reads) and starts
|
|
5901
|
+
// brain.models.add (download an arbitrary HF repo's quant) as a pull job.
|
|
5902
|
+
// Without it the Brain "Models" section hides the Hugging Face search box.
|
|
5903
|
+
// COMPAT(brainHfSearch): added in v0.7.5, remove gate after 2026-07-30 once daemon floor >= v0.7.5.
|
|
5904
|
+
brainHfSearch: z.boolean().optional(),
|
|
4682
5905
|
// COMPAT(agentForkContext): added in v0.1.102, remove gate after 2026-12-28.
|
|
4683
5906
|
agentForkContext: z.boolean().optional(),
|
|
4684
5907
|
// COMPAT(providerRemove): added in v0.1.105, drop the gate when daemon floor >= v0.1.105.
|
|
@@ -4739,6 +5962,16 @@ export const ServerInfoStatusPayloadSchema = z
|
|
|
4739
5962
|
// client-side fallback could read.
|
|
4740
5963
|
// COMPAT(personalityMemory): added in v0.7.0, drop the gate when daemon floor >= v0.7.0.
|
|
4741
5964
|
personalityMemory: z.boolean().optional(),
|
|
5965
|
+
// Script discovery — the daemon scans a workspace for the Scripts its
|
|
5966
|
+
// project files already declare (package.json scripts, and later
|
|
5967
|
+
// Makefile targets, .NET launch profiles) and serves them from
|
|
5968
|
+
// `workspace.script.list` with `includeDiscovered`. Without it the
|
|
5969
|
+
// Scripts dropdown shows only what otto.json declares, which is the
|
|
5970
|
+
// pre-existing behavior and not a degraded build of this feature: only
|
|
5971
|
+
// the daemon can read the workspace's files, so there is no client-side
|
|
5972
|
+
// scan to fall back to.
|
|
5973
|
+
// COMPAT(workspaceScriptDiscovery): added in v0.7.6, drop the gate when daemon floor >= v0.7.6.
|
|
5974
|
+
workspaceScriptDiscovery: z.boolean().optional(),
|
|
4742
5975
|
// COMPAT(projectSearch): added in v0.4.4, drop the gate when daemon floor >= v0.4.4.
|
|
4743
5976
|
projectSearch: z.boolean().optional(),
|
|
4744
5977
|
// COMPAT(codeIndex): added in v0.4.4, drop the gate when daemon floor >= v0.4.4.
|
|
@@ -4779,6 +6012,10 @@ export const ServerInfoStatusPayloadSchema = z
|
|
|
4779
6012
|
ttsSpeak: z.boolean().optional(),
|
|
4780
6013
|
// COMPAT(visualizerVoiceCues): added in v0.6.3, drop the gate when daemon floor >= v0.6.3.
|
|
4781
6014
|
visualizerVoiceCues: z.boolean().optional(),
|
|
6015
|
+
// COMPAT(personalityProfile): added in v0.7.5, drop the gate when daemon floor >= v0.7.5.
|
|
6016
|
+
// Host can author a personality profile (the prompt prose) from a name,
|
|
6017
|
+
// roles, and spinner colors.
|
|
6018
|
+
personalityProfile: z.boolean().optional(),
|
|
4782
6019
|
// COMPAT(setAgentPersonality): added in v0.5.0, drop the gate when daemon floor >= v0.5.0.
|
|
4783
6020
|
setAgentPersonality: z.boolean().optional(),
|
|
4784
6021
|
// COMPAT(checkoutGitCommit): added in v0.5.1, drop the gate when daemon floor >= v0.5.1.
|
|
@@ -4872,11 +6109,23 @@ export const ServerInfoStatusPayloadSchema = z
|
|
|
4872
6109
|
// group regardless, so the client hides the categorized section instead
|
|
4873
6110
|
// of showing category switches that do nothing.
|
|
4874
6111
|
mcpToolGroups: z.boolean().optional(),
|
|
6112
|
+
// COMPAT(connectors): added in v0.7.5, drop the gate when daemon floor >= v0.7.5.
|
|
6113
|
+
// Set when the daemon persists and honors `connectors` — MCP servers
|
|
6114
|
+
// surfaced as named, toggle-able integrations with per-tool disable,
|
|
6115
|
+
// enforced today on the openai-compat path. Old daemons ignore the
|
|
6116
|
+
// section, so the client hides the Connectors settings entirely.
|
|
6117
|
+
connectors: z.boolean().optional(),
|
|
4875
6118
|
// COMPAT(agentBehaviorToggles): added in v0.6.4, drop the gate when daemon floor >= v0.6.4.
|
|
4876
6119
|
// Set when the daemon persists `agentBehaviors.*` (promptSuggestions,
|
|
4877
6120
|
// agentProgressSummaries, notifyOnFinishDefault). The reads are wired by
|
|
4878
6121
|
// Claude-tier providers (WP-E); the client gates the toggle cards on this.
|
|
4879
6122
|
agentBehaviorToggles: z.boolean().optional(),
|
|
6123
|
+
// COMPAT(todoReminders): added in v0.7.5, drop the gate when daemon floor >= v0.7.5.
|
|
6124
|
+
// Set when the daemon acts on `agentBehaviors.{todoNudge,todoReconcileOnIdle}` —
|
|
6125
|
+
// the provider-agnostic stale-todo nudge (next turn) and idle reconcile pass.
|
|
6126
|
+
// The client gates the task-list toggle cards on this so an old daemon never
|
|
6127
|
+
// shows switches that do nothing.
|
|
6128
|
+
todoReminders: z.boolean().optional(),
|
|
4880
6129
|
// COMPAT(metadataGenerationEnabled): added in v0.6.4, drop the gate when daemon floor >= v0.6.4.
|
|
4881
6130
|
// Set when the daemon persists `metadataGeneration.{enabled,preferWriterPersonalities}`.
|
|
4882
6131
|
// The generation path (WP-B) reads them; the client gates the toggle cards on this.
|
|
@@ -4914,6 +6163,13 @@ export const ServerInfoStatusPayloadSchema = z
|
|
|
4914
6163
|
// There is no client-side substitute (the client never touches the
|
|
4915
6164
|
// filesystem), so an old daemon simply does not get the menu items.
|
|
4916
6165
|
fileMutations: z.boolean().optional(),
|
|
6166
|
+
// COMPAT(binaryFileWrite): added in v0.7.6, drop the gate when daemon
|
|
6167
|
+
// floor >= v0.7.6. Set when the daemon serves
|
|
6168
|
+
// `fs.file.write_binary` — bytes to a workspace path, as opposed to
|
|
6169
|
+
// `fs.file.write`, which is text and refuses binary targets outright.
|
|
6170
|
+
// The client cannot write a workspace file itself on any platform, so
|
|
6171
|
+
// an old daemon simply does not offer the exports that produce bytes.
|
|
6172
|
+
binaryFileWrite: z.boolean().optional(),
|
|
4917
6173
|
// COMPAT(attachmentStorage): added in v0.7.1, drop the gate when daemon floor >= v0.7.1.
|
|
4918
6174
|
// Set when the daemon serves `attachments.images.get_stats` and
|
|
4919
6175
|
// `attachments.images.clear` — the readout and reclaim for the images it
|
|
@@ -4928,6 +6184,40 @@ export const ServerInfoStatusPayloadSchema = z
|
|
|
4928
6184
|
// the same directory. The client cannot restamp ownership itself (it is
|
|
4929
6185
|
// daemon state), so an old daemon simply does not get the menu item.
|
|
4930
6186
|
agentWorkspaceTransfer: z.boolean().optional(),
|
|
6187
|
+
// COMPAT(agentForkContextCursor): added in v0.1.108, remove gate after 2027-01-14.
|
|
6188
|
+
agentForkContextCursor: z.boolean().optional(),
|
|
6189
|
+
// COMPAT(providerSubagents): added in v0.1.107, remove gate after 2027-01-12.
|
|
6190
|
+
providerSubagents: z.boolean().optional(),
|
|
6191
|
+
// COMPAT(workspacePinning): added in v0.1.107, remove gate after 2027-01-12.
|
|
6192
|
+
workspacePinning: z.boolean().optional(),
|
|
6193
|
+
// COMPAT(hubRelationship): added in v0.1.X, drop the gate when floor >= v0.1.X.
|
|
6194
|
+
hubRelationship: z.boolean().optional(),
|
|
6195
|
+
// COMPAT(projectGithubClone): added in v0.1.108, remove gate after 2027-01-15.
|
|
6196
|
+
projectGithubClone: z.boolean().optional(),
|
|
6197
|
+
// COMPAT(workspaceGithubRepositorySearch): added in v0.1.108, remove gate after 2027-01-15.
|
|
6198
|
+
workspaceGithubRepositorySearch: z.boolean().optional(),
|
|
6199
|
+
// COMPAT(projectCreateDirectory): added in v0.1.108, remove gate after 2027-01-15.
|
|
6200
|
+
projectCreateDirectory: z.boolean().optional(),
|
|
6201
|
+
// COMPAT(projectList): added in v0.2.4, drop the gate when floor >= v0.2.4.
|
|
6202
|
+
projectList: z.boolean().optional(),
|
|
6203
|
+
// COMPAT(commitsList): added in v0.1.110, remove gate after 2027-01-16.
|
|
6204
|
+
commitsList: z.boolean().optional(),
|
|
6205
|
+
// COMPAT(commitBaseClassification): added in v0.2.0, remove gate after 2027-01-23.
|
|
6206
|
+
commitBaseClassification: z.boolean().optional(),
|
|
6207
|
+
// COMPAT(providerRemoval): added in v0.1.105, drop the gate when floor >= v0.1.105.
|
|
6208
|
+
providerRemoval: z.boolean().optional(),
|
|
6209
|
+
// COMPAT(importSessionWorkspaceTarget): added in v0.1.110, remove gate after 2027-01-16.
|
|
6210
|
+
importSessionWorkspaceTarget: z.boolean().optional(),
|
|
6211
|
+
// COMPAT(forgeProviders): added in v0.1.106, drop the gate when daemon floor >= v0.1.106.
|
|
6212
|
+
// Daemon advertises pluggable non-GitHub forge support (the forge registry);
|
|
6213
|
+
// the client gates non-GitHub setup UI on it.
|
|
6214
|
+
forgeProviders: z.boolean().optional(),
|
|
6215
|
+
// COMPAT(selectiveAgentTimeline): added in v0.1.106, remove after 2027-01-12.
|
|
6216
|
+
selectiveAgentTimeline: z.boolean().optional(),
|
|
6217
|
+
// COMPAT(stableProjectIdentity): added in v0.1.109, remove gate after 2027-01-15.
|
|
6218
|
+
stableProjectIdentity: z.boolean().optional(),
|
|
6219
|
+
// COMPAT(workspaceScriptManagement): added in v0.1.105, remove gate after 2027-01-10.
|
|
6220
|
+
workspaceScriptManagement: z.boolean().optional(),
|
|
4931
6221
|
})
|
|
4932
6222
|
.optional(),
|
|
4933
6223
|
})
|
|
@@ -5147,8 +6437,50 @@ export const ProjectPlacementPayloadSchema = z.object({
|
|
|
5147
6437
|
});
|
|
5148
6438
|
export const WorkspaceScriptLifecycleSchema = z.enum(["running", "stopped"]);
|
|
5149
6439
|
export const WorkspaceScriptHealthSchema = z.enum(["healthy", "unhealthy"]);
|
|
6440
|
+
export const WorkspaceScriptSourcePayloadSchema = z.object({
|
|
6441
|
+
/** Stable provider id; also the prefix of every `scriptName` it produces. */
|
|
6442
|
+
id: z.string(),
|
|
6443
|
+
/** The tool half of the dropdown's group header, e.g. "npm" or "pnpm". */
|
|
6444
|
+
label: z.string(),
|
|
6445
|
+
/**
|
|
6446
|
+
* Repo-relative file the script was read from, e.g. "package.json".
|
|
6447
|
+
*
|
|
6448
|
+
* Plain-optional rather than defaulted, matching `label` and `command` on the
|
|
6449
|
+
* payload: absent means unknown. A discovery run knows the file, but the
|
|
6450
|
+
* descriptor's orphan path recovers a source from a qualified runtime name
|
|
6451
|
+
* alone (`npm:dev`) and has no discovery behind it to ask. A `.default(null)`
|
|
6452
|
+
* here would make the field required on the output type and force that path
|
|
6453
|
+
* to invent an answer it does not have.
|
|
6454
|
+
*/
|
|
6455
|
+
file: z.string().nullable().optional(),
|
|
6456
|
+
});
|
|
5150
6457
|
export const WorkspaceScriptPayloadSchema = z.object({
|
|
6458
|
+
/**
|
|
6459
|
+
* The launch/stop key, unique within a workspace. Otto's own otto.json
|
|
6460
|
+
* scripts use their bare name; a discovered one is qualified by its source
|
|
6461
|
+
* ("npm:build") so two sources offering "build" cannot collide in the
|
|
6462
|
+
* runtime store or the service-proxy hostname.
|
|
6463
|
+
*/
|
|
5151
6464
|
scriptName: z.string(),
|
|
6465
|
+
/**
|
|
6466
|
+
* What to show instead of `scriptName` — the name the project itself uses.
|
|
6467
|
+
* COMPAT(workspaceScriptDiscovery): added in v0.7.6; absent ⇒ show `scriptName`.
|
|
6468
|
+
*/
|
|
6469
|
+
label: z.string().optional(),
|
|
6470
|
+
/**
|
|
6471
|
+
* Where this Script came from. Absent ⇒ declared in otto.json, which is the
|
|
6472
|
+
* only kind that existed before discovery and the only kind that may own a
|
|
6473
|
+
* service-proxy route.
|
|
6474
|
+
* COMPAT(workspaceScriptDiscovery): added in v0.7.6.
|
|
6475
|
+
*/
|
|
6476
|
+
source: WorkspaceScriptSourcePayloadSchema.optional(),
|
|
6477
|
+
/**
|
|
6478
|
+
* The command the Script runs, for the row's subtitle. Left plain-optional
|
|
6479
|
+
* rather than defaulted so an existing payload that never carried a command
|
|
6480
|
+
* stays valid without gaining a field it has no answer for.
|
|
6481
|
+
* COMPAT(workspaceScriptDiscovery): added in v0.7.6; absent ⇒ no subtitle.
|
|
6482
|
+
*/
|
|
6483
|
+
command: z.string().nullable().optional(),
|
|
5152
6484
|
type: z.enum(["script", "service"]).optional().default("service"),
|
|
5153
6485
|
hostname: z.string(),
|
|
5154
6486
|
port: z.number().int().positive().nullable(),
|
|
@@ -5232,7 +6564,9 @@ export const WorkspaceDescriptorPayloadSchema = z
|
|
|
5232
6564
|
projectRootPath: z.string(),
|
|
5233
6565
|
workspaceDirectory: z.string().optional(),
|
|
5234
6566
|
projectKind: z.enum(["git", "non_git", "directory"]),
|
|
5235
|
-
// COMPAT(workspaces): keep legacy directory workspace kind parseable.
|
|
6567
|
+
// COMPAT(workspaces): keep the legacy "directory" workspace kind parseable.
|
|
6568
|
+
// Persisted registries still carry it and there is no migration, so this
|
|
6569
|
+
// stays until a migration retires the kind rather than expiring on a date.
|
|
5236
6570
|
workspaceKind: z.enum(["directory", "local_checkout", "checkout", "worktree"]),
|
|
5237
6571
|
name: z.string(),
|
|
5238
6572
|
// COMPAT(workspaceTitles): added in v0.1.97, drop the optional gate when floor >= v0.1.97.
|
|
@@ -5241,6 +6575,8 @@ export const WorkspaceDescriptorPayloadSchema = z
|
|
|
5241
6575
|
// its input and offer a "reset to branch name" action. Null means the name
|
|
5242
6576
|
// is derived from the branch/directory.
|
|
5243
6577
|
title: z.string().nullable().optional(),
|
|
6578
|
+
// COMPAT(workspacePinning): added in v0.1.107, remove optional after 2027-01-12.
|
|
6579
|
+
pinnedAt: z.string().nullable().optional(),
|
|
5244
6580
|
archivingAt: z.string().nullable().optional().default(null),
|
|
5245
6581
|
status: WorkspaceStateBucketSchema,
|
|
5246
6582
|
// Best-effort workspace status entry timestamp. Old daemons omit the
|
|
@@ -5262,6 +6598,10 @@ export const WorkspaceDescriptorPayloadSchema = z
|
|
|
5262
6598
|
scripts: z.array(WorkspaceScriptPayloadSchema).default([]),
|
|
5263
6599
|
gitRuntime: WorkspaceGitRuntimePayloadSchema,
|
|
5264
6600
|
githubRuntime: WorkspaceGitHubRuntimePayloadSchema,
|
|
6601
|
+
// COMPAT(forge): added in v0.1.106, remove after 2026-12-27. The forge resolved
|
|
6602
|
+
// for this workspace, so the sidebar/hover-card render the right brand mark.
|
|
6603
|
+
// Old daemons omit it; absent means the client falls back to GitHub.
|
|
6604
|
+
forge: z.string().optional(),
|
|
5265
6605
|
project: ProjectPlacementPayloadSchema.optional(),
|
|
5266
6606
|
})
|
|
5267
6607
|
.transform((workspace) => ({
|
|
@@ -5353,6 +6693,8 @@ export const FetchRecentProviderSessionsResponseMessageSchema = z.object({
|
|
|
5353
6693
|
// workspace is archived.
|
|
5354
6694
|
export const WorkspaceProjectDescriptorPayloadSchema = z.object({
|
|
5355
6695
|
projectId: z.string(),
|
|
6696
|
+
// COMPAT(projectKey): added in v0.2.4 on 2026-07-28; remove optional after 2027-01-28.
|
|
6697
|
+
projectKey: z.string().optional(),
|
|
5356
6698
|
projectDisplayName: z.string(),
|
|
5357
6699
|
projectCustomName: z.string().nullable().optional(),
|
|
5358
6700
|
projectRootPath: z.string(),
|
|
@@ -5414,6 +6756,20 @@ export const ProjectUpdatedNotificationSchema = z.object({
|
|
|
5414
6756
|
hasActiveWorkspaces: z.boolean(),
|
|
5415
6757
|
}),
|
|
5416
6758
|
});
|
|
6759
|
+
export const ProjectUpdateMessageSchema = z.object({
|
|
6760
|
+
type: z.literal("project.update"),
|
|
6761
|
+
payload: z.discriminatedUnion("kind", [
|
|
6762
|
+
z.object({ kind: z.literal("upsert"), project: WorkspaceProjectDescriptorPayloadSchema }),
|
|
6763
|
+
z.object({ kind: z.literal("remove"), projectId: z.string() }),
|
|
6764
|
+
]),
|
|
6765
|
+
});
|
|
6766
|
+
export const ProjectListResponseMessageSchema = z.object({
|
|
6767
|
+
type: z.literal("project.list.response"),
|
|
6768
|
+
payload: z.object({
|
|
6769
|
+
requestId: z.string(),
|
|
6770
|
+
projects: z.array(WorkspaceProjectDescriptorPayloadSchema),
|
|
6771
|
+
}),
|
|
6772
|
+
});
|
|
5417
6773
|
export const ScriptStatusUpdateMessageSchema = z.object({
|
|
5418
6774
|
type: z.literal("script_status_update"),
|
|
5419
6775
|
payload: z.object({
|
|
@@ -5545,6 +6901,70 @@ export const HostingListOwnersResponseSchema = z.object({
|
|
|
5545
6901
|
error: z.string().nullable(),
|
|
5546
6902
|
}),
|
|
5547
6903
|
});
|
|
6904
|
+
export const ProjectCreateDirectoryErrorCodeSchema = z.enum([
|
|
6905
|
+
"invalid_name",
|
|
6906
|
+
"parent_directory_not_found",
|
|
6907
|
+
"directory_exists",
|
|
6908
|
+
"permission_denied",
|
|
6909
|
+
"registration_failed",
|
|
6910
|
+
"filesystem_error",
|
|
6911
|
+
]);
|
|
6912
|
+
export const ProjectCreateDirectoryResponseSchema = z.object({
|
|
6913
|
+
type: z.literal("project.create_directory.response"),
|
|
6914
|
+
payload: z.object({
|
|
6915
|
+
requestId: z.string(),
|
|
6916
|
+
directoryPath: z.string().nullable(),
|
|
6917
|
+
project: WorkspaceProjectDescriptorPayloadSchema.nullable(),
|
|
6918
|
+
error: z.string().nullable(),
|
|
6919
|
+
// Error codes are open-ended on the wire so older clients can still parse
|
|
6920
|
+
// responses after a newer daemon learns another failure reason.
|
|
6921
|
+
errorCode: z.string().nullable(),
|
|
6922
|
+
}),
|
|
6923
|
+
});
|
|
6924
|
+
export const WorkspaceGithubSearchRepositoriesResponseSchema = z.object({
|
|
6925
|
+
type: z.literal("workspace.github.search_repositories.response"),
|
|
6926
|
+
payload: z.discriminatedUnion("status", [
|
|
6927
|
+
z.object({
|
|
6928
|
+
status: z.literal("success"),
|
|
6929
|
+
requestId: z.string(),
|
|
6930
|
+
repositories: z.array(GithubRepositorySchema),
|
|
6931
|
+
available: z.literal(true),
|
|
6932
|
+
error: z.null(),
|
|
6933
|
+
}),
|
|
6934
|
+
z.object({
|
|
6935
|
+
status: z.literal("unavailable"),
|
|
6936
|
+
requestId: z.string(),
|
|
6937
|
+
repositories: z.array(GithubRepositorySchema),
|
|
6938
|
+
reason: z.literal("gh_missing"),
|
|
6939
|
+
available: z.literal(false),
|
|
6940
|
+
error: z.string(),
|
|
6941
|
+
}),
|
|
6942
|
+
z.object({
|
|
6943
|
+
status: z.literal("unauthenticated"),
|
|
6944
|
+
requestId: z.string(),
|
|
6945
|
+
repositories: z.array(GithubRepositorySchema),
|
|
6946
|
+
available: z.literal(false),
|
|
6947
|
+
error: z.string(),
|
|
6948
|
+
}),
|
|
6949
|
+
z.object({
|
|
6950
|
+
status: z.literal("error"),
|
|
6951
|
+
requestId: z.string(),
|
|
6952
|
+
repositories: z.array(GithubRepositorySchema),
|
|
6953
|
+
available: z.literal(true),
|
|
6954
|
+
error: z.string(),
|
|
6955
|
+
}),
|
|
6956
|
+
]),
|
|
6957
|
+
});
|
|
6958
|
+
export const ProjectGithubCloneResponseSchema = z.object({
|
|
6959
|
+
type: z.literal("project.github.clone.response"),
|
|
6960
|
+
payload: z.object({
|
|
6961
|
+
requestId: z.string(),
|
|
6962
|
+
repo: z.string().trim().min(MIN_REPOSITORY_PATH_LENGTH),
|
|
6963
|
+
checkoutPath: z.string().nullable(),
|
|
6964
|
+
project: WorkspaceProjectDescriptorPayloadSchema.nullable(),
|
|
6965
|
+
error: z.string().nullable(),
|
|
6966
|
+
}),
|
|
6967
|
+
});
|
|
5548
6968
|
export const StartWorkspaceScriptResponseMessageSchema = z.object({
|
|
5549
6969
|
type: z.literal("start_workspace_script_response"),
|
|
5550
6970
|
payload: z.object({
|
|
@@ -5555,6 +6975,26 @@ export const StartWorkspaceScriptResponseMessageSchema = z.object({
|
|
|
5555
6975
|
error: z.string().nullable(),
|
|
5556
6976
|
}),
|
|
5557
6977
|
});
|
|
6978
|
+
const WorkspaceScriptOperationPayloadSchema = z.object({
|
|
6979
|
+
requestId: z.string(),
|
|
6980
|
+
workspaceId: z.string(),
|
|
6981
|
+
scriptName: z.string().optional(),
|
|
6982
|
+
script: WorkspaceScriptPayloadSchema.nullable().optional(),
|
|
6983
|
+
scripts: z.array(WorkspaceScriptPayloadSchema).optional(),
|
|
6984
|
+
error: z.string().nullable(),
|
|
6985
|
+
});
|
|
6986
|
+
export const WorkspaceScriptListResponseMessageSchema = z.object({
|
|
6987
|
+
type: z.literal("workspace.script.list.response"),
|
|
6988
|
+
payload: WorkspaceScriptOperationPayloadSchema,
|
|
6989
|
+
});
|
|
6990
|
+
export const WorkspaceScriptStartResponseMessageSchema = z.object({
|
|
6991
|
+
type: z.literal("workspace.script.start.response"),
|
|
6992
|
+
payload: WorkspaceScriptOperationPayloadSchema,
|
|
6993
|
+
});
|
|
6994
|
+
export const WorkspaceScriptStopResponseMessageSchema = z.object({
|
|
6995
|
+
type: z.literal("workspace.script.stop.response"),
|
|
6996
|
+
payload: WorkspaceScriptOperationPayloadSchema,
|
|
6997
|
+
});
|
|
5558
6998
|
// COMPAT(desktopEditorBridge): added in v0.1.88, remove after 2026-12-03 once old clients no longer parse daemon editor RPC responses.
|
|
5559
6999
|
export const LegacyListAvailableEditorsResponseMessageSchema = z.object({
|
|
5560
7000
|
type: z.literal("list_available_editors_response"),
|
|
@@ -5719,6 +7159,106 @@ export const FetchAgentTimelineResponseMessageSchema = z.object({
|
|
|
5719
7159
|
error: z.string().nullable(),
|
|
5720
7160
|
}),
|
|
5721
7161
|
});
|
|
7162
|
+
export const ProviderSubagentDescriptorPayloadSchema = z.object({
|
|
7163
|
+
id: z.string(),
|
|
7164
|
+
parentAgentId: z.string(),
|
|
7165
|
+
provider: AgentProviderSchema,
|
|
7166
|
+
title: z.string().nullable(),
|
|
7167
|
+
description: z.string().nullable(),
|
|
7168
|
+
status: z.enum(["running", "completed", "failed", "canceled"]),
|
|
7169
|
+
createdAt: z.string(),
|
|
7170
|
+
updatedAt: z.string(),
|
|
7171
|
+
toolCallId: z.string().nullable(),
|
|
7172
|
+
cwd: z.string().nullable().optional(),
|
|
7173
|
+
});
|
|
7174
|
+
export const ProviderSubagentListResponseMessageSchema = z.object({
|
|
7175
|
+
type: z.literal("agent.provider_subagents.list.response"),
|
|
7176
|
+
payload: z.object({
|
|
7177
|
+
requestId: z.string(),
|
|
7178
|
+
parentAgentId: z.string(),
|
|
7179
|
+
subagents: z.array(ProviderSubagentDescriptorPayloadSchema),
|
|
7180
|
+
error: z.string().nullable(),
|
|
7181
|
+
}),
|
|
7182
|
+
});
|
|
7183
|
+
export const ProviderSubagentTimelineResponseMessageSchema = z.object({
|
|
7184
|
+
type: z.literal("agent.provider_subagents.timeline.get.response"),
|
|
7185
|
+
payload: z.object({
|
|
7186
|
+
requestId: z.string(),
|
|
7187
|
+
parentAgentId: z.string(),
|
|
7188
|
+
subagentId: z.string(),
|
|
7189
|
+
provider: AgentProviderSchema.nullable(),
|
|
7190
|
+
direction: z.enum(["tail", "before", "after"]),
|
|
7191
|
+
epoch: z.string(),
|
|
7192
|
+
reset: z.boolean(),
|
|
7193
|
+
staleCursor: z.boolean(),
|
|
7194
|
+
gap: z.boolean(),
|
|
7195
|
+
window: z.object({
|
|
7196
|
+
minSeq: z.number().int().nonnegative(),
|
|
7197
|
+
maxSeq: z.number().int().nonnegative(),
|
|
7198
|
+
nextSeq: z.number().int().nonnegative(),
|
|
7199
|
+
}),
|
|
7200
|
+
hasOlder: z.boolean(),
|
|
7201
|
+
hasNewer: z.boolean(),
|
|
7202
|
+
rows: z.array(z.object({
|
|
7203
|
+
item: AgentTimelineItemPayloadSchema,
|
|
7204
|
+
timestamp: z.string(),
|
|
7205
|
+
seq: z.number().int().nonnegative(),
|
|
7206
|
+
})),
|
|
7207
|
+
error: z.string().nullable(),
|
|
7208
|
+
}),
|
|
7209
|
+
});
|
|
7210
|
+
export const ProviderSubagentUpdateMessageSchema = z.object({
|
|
7211
|
+
type: z.literal("agent.provider_subagents.update"),
|
|
7212
|
+
payload: z.discriminatedUnion("kind", [
|
|
7213
|
+
z.object({
|
|
7214
|
+
kind: z.literal("upsert"),
|
|
7215
|
+
subagent: ProviderSubagentDescriptorPayloadSchema,
|
|
7216
|
+
}),
|
|
7217
|
+
z.object({
|
|
7218
|
+
kind: z.literal("timeline"),
|
|
7219
|
+
parentAgentId: z.string(),
|
|
7220
|
+
subagentId: z.string(),
|
|
7221
|
+
provider: AgentProviderSchema,
|
|
7222
|
+
item: AgentTimelineItemPayloadSchema,
|
|
7223
|
+
timestamp: z.string(),
|
|
7224
|
+
seq: z.number().int().nonnegative(),
|
|
7225
|
+
epoch: z.string(),
|
|
7226
|
+
}),
|
|
7227
|
+
z.object({
|
|
7228
|
+
kind: z.literal("remove"),
|
|
7229
|
+
parentAgentId: z.string(),
|
|
7230
|
+
subagentId: z.string(),
|
|
7231
|
+
}),
|
|
7232
|
+
]),
|
|
7233
|
+
});
|
|
7234
|
+
export const SetAgentTimelineSubscriptionResponseMessageSchema = z.object({
|
|
7235
|
+
type: z.literal("agent.timeline.set_subscription.response"),
|
|
7236
|
+
payload: z.object({
|
|
7237
|
+
agentIds: z.array(z.string()),
|
|
7238
|
+
requestId: z.string(),
|
|
7239
|
+
}),
|
|
7240
|
+
});
|
|
7241
|
+
export const AgentAttentionRequiredMessageSchema = z.object({
|
|
7242
|
+
type: z.literal("agent_attention_required"),
|
|
7243
|
+
payload: z.object({
|
|
7244
|
+
agentId: z.string(),
|
|
7245
|
+
reason: z.enum(["finished", "error", "permission"]),
|
|
7246
|
+
timestamp: z.string(),
|
|
7247
|
+
shouldNotify: z.boolean(),
|
|
7248
|
+
notification: z
|
|
7249
|
+
.object({
|
|
7250
|
+
title: z.string(),
|
|
7251
|
+
body: z.string(),
|
|
7252
|
+
data: z.object({
|
|
7253
|
+
serverId: z.string(),
|
|
7254
|
+
workspaceId: z.string().optional(),
|
|
7255
|
+
agentId: z.string(),
|
|
7256
|
+
reason: z.enum(["finished", "error", "permission"]),
|
|
7257
|
+
}),
|
|
7258
|
+
})
|
|
7259
|
+
.optional(),
|
|
7260
|
+
}),
|
|
7261
|
+
});
|
|
5722
7262
|
export const AgentForkContextResponseMessageSchema = z.object({
|
|
5723
7263
|
type: z.literal("agent.fork_context.response"),
|
|
5724
7264
|
payload: z.object({
|
|
@@ -5727,6 +7267,7 @@ export const AgentForkContextResponseMessageSchema = z.object({
|
|
|
5727
7267
|
attachment: TextAttachmentSchema.nullable(),
|
|
5728
7268
|
itemCount: z.number().int().nonnegative(),
|
|
5729
7269
|
boundaryMessageId: z.string().nullable(),
|
|
7270
|
+
boundaryCursor: AgentTimelineCursorSchema.nullable().optional(),
|
|
5730
7271
|
error: z.string().nullable(),
|
|
5731
7272
|
}),
|
|
5732
7273
|
});
|
|
@@ -5787,6 +7328,7 @@ export const CancelAgentResponseMessageSchema = z.object({
|
|
|
5787
7328
|
// can say "nothing to stop" instead of silently no-oping. Purely additive;
|
|
5788
7329
|
// absent ⇒ unknown (old daemon). See docs/agent-lifecycle.md (Item 2).
|
|
5789
7330
|
cancelled: z.boolean().optional(),
|
|
7331
|
+
error: z.string().nullable().optional(),
|
|
5790
7332
|
}),
|
|
5791
7333
|
});
|
|
5792
7334
|
export const ClearAgentAttentionResponseMessageSchema = z.object({
|
|
@@ -5953,6 +7495,19 @@ export const AgentPersonalitiesGetStatsResponseSchema = z.object({
|
|
|
5953
7495
|
})
|
|
5954
7496
|
.passthrough(),
|
|
5955
7497
|
});
|
|
7498
|
+
export const AgentPersonalitiesGenerateProfileResponseSchema = z.object({
|
|
7499
|
+
type: z.literal("agentPersonalities.generate_profile.response"),
|
|
7500
|
+
payload: z
|
|
7501
|
+
.object({
|
|
7502
|
+
requestId: z.string(),
|
|
7503
|
+
// The authored personality prompt, ready to drop into the editor's prompt
|
|
7504
|
+
// field. Absent when generation failed (see error) or no writer/provider
|
|
7505
|
+
// resolves on this host.
|
|
7506
|
+
profile: z.string().optional(),
|
|
7507
|
+
error: z.string().optional(),
|
|
7508
|
+
})
|
|
7509
|
+
.passthrough(),
|
|
7510
|
+
});
|
|
5956
7511
|
export const DaemonGetStatusResponseSchema = z.object({
|
|
5957
7512
|
type: z.literal("daemon.get_status.response"),
|
|
5958
7513
|
payload: z
|
|
@@ -5982,6 +7537,37 @@ export const DaemonGetStatusResponseSchema = z.object({
|
|
|
5982
7537
|
})
|
|
5983
7538
|
.passthrough(),
|
|
5984
7539
|
});
|
|
7540
|
+
export const HubRelationshipStatusSchema = z.object({
|
|
7541
|
+
state: z.enum([
|
|
7542
|
+
"not_connected",
|
|
7543
|
+
"connecting",
|
|
7544
|
+
"connected",
|
|
7545
|
+
"reconnecting",
|
|
7546
|
+
"disconnecting",
|
|
7547
|
+
"revoked",
|
|
7548
|
+
]),
|
|
7549
|
+
daemonId: z.string().nullable(),
|
|
7550
|
+
hubOrigin: z.string().nullable(),
|
|
7551
|
+
scopes: z.array(z.string()),
|
|
7552
|
+
connectedAt: z.string().nullable(),
|
|
7553
|
+
lastError: z.string().nullable(),
|
|
7554
|
+
});
|
|
7555
|
+
export const HubManagementDaemonConnectResponseSchema = z.object({
|
|
7556
|
+
type: z.literal("hub.management.daemon.connect.response"),
|
|
7557
|
+
payload: z.object({ requestId: z.string(), status: HubRelationshipStatusSchema }),
|
|
7558
|
+
});
|
|
7559
|
+
export const HubManagementDaemonGetStatusResponseSchema = z.object({
|
|
7560
|
+
type: z.literal("hub.management.daemon.get_status.response"),
|
|
7561
|
+
payload: z.object({ requestId: z.string(), status: HubRelationshipStatusSchema }),
|
|
7562
|
+
});
|
|
7563
|
+
export const HubManagementDaemonDisconnectResponseSchema = z.object({
|
|
7564
|
+
type: z.literal("hub.management.daemon.disconnect.response"),
|
|
7565
|
+
payload: z.object({
|
|
7566
|
+
requestId: z.string(),
|
|
7567
|
+
status: HubRelationshipStatusSchema,
|
|
7568
|
+
warning: z.string().optional(),
|
|
7569
|
+
}),
|
|
7570
|
+
});
|
|
5985
7571
|
export const DaemonGetPairingOfferResponseSchema = z.object({
|
|
5986
7572
|
type: z.literal("daemon.get_pairing_offer.response"),
|
|
5987
7573
|
payload: z
|
|
@@ -6195,8 +7781,7 @@ const CheckoutPrGithubRepositoryPolicySchema = z
|
|
|
6195
7781
|
rebaseMergeAllowed: false,
|
|
6196
7782
|
viewerDefaultMergeMethod: null,
|
|
6197
7783
|
});
|
|
6198
|
-
const
|
|
6199
|
-
.object({
|
|
7784
|
+
const CheckoutPrGithubStatusObjectSchema = z.object({
|
|
6200
7785
|
mergeStateStatus: z.string().nullable().optional().default(null),
|
|
6201
7786
|
autoMergeRequest: CheckoutPrGithubAutoMergeRequestSchema,
|
|
6202
7787
|
viewerCanEnableAutoMerge: z.boolean().optional().default(false),
|
|
@@ -6206,9 +7791,23 @@ const CheckoutPrGithubStatusSchema = z
|
|
|
6206
7791
|
repository: CheckoutPrGithubRepositoryPolicySchema,
|
|
6207
7792
|
isMergeQueueEnabled: z.boolean().optional().default(false),
|
|
6208
7793
|
isInMergeQueue: z.boolean().optional().default(false),
|
|
6209
|
-
})
|
|
6210
|
-
|
|
7794
|
+
});
|
|
7795
|
+
const CheckoutPrGithubStatusSchema = CheckoutPrGithubStatusObjectSchema.optional();
|
|
7796
|
+
// The open facts envelope for forge-specific PR facts. Permanent — non-GitHub
|
|
7797
|
+
// forges deliver their native facts through it. The transitional piece is the
|
|
7798
|
+
// `github` mirror above, which stays populated for clients predating this
|
|
7799
|
+
// envelope; see COMPAT(forgeSpecific) in status-projection.ts for the shim.
|
|
7800
|
+
//
|
|
7801
|
+
// NOTE: `forgeSpecific.forge` is a FACTS-FAMILY tag, not the workspace brand id.
|
|
7802
|
+
// The whole Gitea family (gitea, forgejo, codeberg) emits `forge: "gitea"` here
|
|
7803
|
+
// because they share one facts shape, while the top-level `forge` above carries
|
|
7804
|
+
// the specific brand. Validation of family-specific payloads happens at runtime
|
|
7805
|
+
// in the consumer that knows that forge family.
|
|
7806
|
+
const CheckoutPrForgeSpecificSchema = z.unknown().optional();
|
|
6211
7807
|
export const CheckoutPrStatusSchema = z.object({
|
|
7808
|
+
// COMPAT(forge): added in v0.1.106, remove the default after 2026-12-27 once daemon floor >= v0.1.106.
|
|
7809
|
+
forge: z.string().optional().default("github"),
|
|
7810
|
+
projectPath: z.string().optional(),
|
|
6212
7811
|
number: z.number().optional(),
|
|
6213
7812
|
url: z.string(),
|
|
6214
7813
|
title: z.string(),
|
|
@@ -6241,6 +7840,14 @@ export const CheckoutPrStatusSchema = z.object({
|
|
|
6241
7840
|
github: CheckoutPrGithubStatusSchema,
|
|
6242
7841
|
// Provider-neutral per-PR hosting facts. Absent from old daemons; for
|
|
6243
7842
|
// GitHub projects both this and the legacy `github` field are populated.
|
|
7843
|
+
//
|
|
7844
|
+
// NOT a shim, and deliberately untagged: this does not collapse into `forge`.
|
|
7845
|
+
// Otto registers every hosting provider into the forge registry under the
|
|
7846
|
+
// forge id `github`, which is the provider-routing facade rather than the gh
|
|
7847
|
+
// CLI (bootstrap.ts, `createGitHostingResolver`). So `forge` reads "github"
|
|
7848
|
+
// for a Bitbucket workspace and only `hosting.provider` carries the truth.
|
|
7849
|
+
// The two disagree by design; a reader wanting the real provider must use
|
|
7850
|
+
// this field.
|
|
6244
7851
|
hosting: z
|
|
6245
7852
|
.object({
|
|
6246
7853
|
provider: GitHostingProviderIdWireSchema,
|
|
@@ -6254,7 +7861,9 @@ export const CheckoutPrStatusSchema = z.object({
|
|
|
6254
7861
|
.optional(),
|
|
6255
7862
|
})
|
|
6256
7863
|
.optional(),
|
|
7864
|
+
forgeSpecific: CheckoutPrForgeSpecificSchema,
|
|
6257
7865
|
});
|
|
7866
|
+
export const ForgeAuthStateSchema = z.unknown().optional();
|
|
6258
7867
|
const CheckoutPrStatusPayloadSchema = z.object({
|
|
6259
7868
|
cwd: z.string(),
|
|
6260
7869
|
status: CheckoutPrStatusSchema.nullable(),
|
|
@@ -6264,6 +7873,9 @@ const CheckoutPrStatusPayloadSchema = z.object({
|
|
|
6264
7873
|
githubFeaturesEnabled: z.boolean(),
|
|
6265
7874
|
// Provider-neutral enablement. Present even when status is null so clients
|
|
6266
7875
|
// can drive search/create-PR affordances for the workspace's provider.
|
|
7876
|
+
// Permanent for the same reason as the `hosting` block on the PR status
|
|
7877
|
+
// schema above: `forge` is a routing-facade id and cannot answer "which
|
|
7878
|
+
// provider is this really".
|
|
6267
7879
|
hosting: z
|
|
6268
7880
|
.object({
|
|
6269
7881
|
provider: GitHostingProviderIdWireSchema,
|
|
@@ -6271,6 +7883,13 @@ const CheckoutPrStatusPayloadSchema = z.object({
|
|
|
6271
7883
|
capabilities: GitHostingCapabilitiesSchema.optional(),
|
|
6272
7884
|
})
|
|
6273
7885
|
.optional(),
|
|
7886
|
+
// COMPAT(forgeAuthState): added in v0.1.106, remove after 2026-12-27. Optional richer
|
|
7887
|
+
// signal that supersedes githubFeaturesEnabled. The legacy boolean stays for old clients
|
|
7888
|
+
// and may remain true for non-auth error payloads so old clients still show the error.
|
|
7889
|
+
// Drop the boolean once the daemon floor >= v0.1.106.
|
|
7890
|
+
authState: ForgeAuthStateSchema,
|
|
7891
|
+
// COMPAT(forge): added in v0.1.106, remove the default after 2026-12-27 once daemon floor >= v0.1.106.
|
|
7892
|
+
forge: z.string().optional().default("github"),
|
|
6274
7893
|
error: CheckoutErrorSchema.nullable(),
|
|
6275
7894
|
requestId: z.string(),
|
|
6276
7895
|
});
|
|
@@ -6298,6 +7917,8 @@ const CheckoutDiffSubscriptionPayloadSchema = z.object({
|
|
|
6298
7917
|
cwd: z.string(),
|
|
6299
7918
|
files: z.array(ParsedDiffFileSchema),
|
|
6300
7919
|
error: CheckoutErrorSchema.nullable(),
|
|
7920
|
+
// COMPAT(diffTooLarge): added in v0.2.4, keep optional until the daemon floor is v0.2.4.
|
|
7921
|
+
diffTooLarge: z.boolean().optional(),
|
|
6301
7922
|
});
|
|
6302
7923
|
export const SubscribeCheckoutDiffResponseSchema = z.object({
|
|
6303
7924
|
type: z.literal("subscribe_checkout_diff_response"),
|
|
@@ -6594,6 +8215,18 @@ export const CheckoutPrMergeResponseSchema = z.object({
|
|
|
6594
8215
|
requestId: z.string(),
|
|
6595
8216
|
}),
|
|
6596
8217
|
});
|
|
8218
|
+
export const CheckoutForgeSetAutoMergeResponseSchema = z.object({
|
|
8219
|
+
type: z.literal("checkout.forge.set_auto_merge.response"),
|
|
8220
|
+
payload: z.object({
|
|
8221
|
+
cwd: z.string(),
|
|
8222
|
+
enabled: z.boolean(),
|
|
8223
|
+
success: z.boolean(),
|
|
8224
|
+
error: CheckoutErrorSchema.nullable(),
|
|
8225
|
+
requestId: z.string(),
|
|
8226
|
+
}),
|
|
8227
|
+
});
|
|
8228
|
+
// COMPAT(githubAutoMergeRpc): added in v0.1.106, remove after 2026-12-28 once
|
|
8229
|
+
// all supported clients use checkout.forge.set_auto_merge.*.
|
|
6597
8230
|
export const CheckoutGithubSetAutoMergeResponseSchema = z.object({
|
|
6598
8231
|
type: z.literal("checkout.github.set_auto_merge.response"),
|
|
6599
8232
|
payload: z.object({
|
|
@@ -6670,6 +8303,29 @@ export const PreviewStopResponseSchema = z.object({
|
|
|
6670
8303
|
requestId: z.string(),
|
|
6671
8304
|
}),
|
|
6672
8305
|
});
|
|
8306
|
+
export const CheckoutCommitsListResponseSchema = z.object({
|
|
8307
|
+
type: z.literal("checkout.commits.list.response"),
|
|
8308
|
+
payload: z.object({
|
|
8309
|
+
cwd: z.string(),
|
|
8310
|
+
baseRef: z.string().nullable(),
|
|
8311
|
+
commits: z.array(CheckoutCommitSchema),
|
|
8312
|
+
error: CheckoutErrorSchema.nullable(),
|
|
8313
|
+
requestId: z.string(),
|
|
8314
|
+
}),
|
|
8315
|
+
});
|
|
8316
|
+
export const CheckoutCommitFileDiffResponseSchema = z.object({
|
|
8317
|
+
type: z.literal("checkout.commits.file_diff.response"),
|
|
8318
|
+
payload: z.object({
|
|
8319
|
+
cwd: z.string(),
|
|
8320
|
+
sha: z.string(),
|
|
8321
|
+
path: z.string(),
|
|
8322
|
+
// null when the file is absent from the commit or carries no textual diff
|
|
8323
|
+
// (e.g. binary-only changes).
|
|
8324
|
+
file: ParsedDiffFileSchema.nullable(),
|
|
8325
|
+
error: CheckoutErrorSchema.nullable(),
|
|
8326
|
+
requestId: z.string(),
|
|
8327
|
+
}),
|
|
8328
|
+
});
|
|
6673
8329
|
const CheckoutGithubCheckAnnotationSchema = z.object({
|
|
6674
8330
|
path: z.string().optional(),
|
|
6675
8331
|
startLine: z.number().optional(),
|
|
@@ -6688,6 +8344,31 @@ const CheckoutGithubCheckJobSchema = z.object({
|
|
|
6688
8344
|
logTail: z.string().optional(),
|
|
6689
8345
|
logTruncated: z.boolean().optional(),
|
|
6690
8346
|
});
|
|
8347
|
+
// Statuses stay open strings so future forge values cannot break parsing.
|
|
8348
|
+
const CheckoutPipelineJobSchema = z.object({
|
|
8349
|
+
id: z.number(),
|
|
8350
|
+
name: z.string(),
|
|
8351
|
+
stage: z.string(),
|
|
8352
|
+
status: z.string(),
|
|
8353
|
+
rawStatus: z.string(),
|
|
8354
|
+
url: z.string().nullable().optional().default(null),
|
|
8355
|
+
allowFailure: z.boolean().optional().default(false),
|
|
8356
|
+
durationSeconds: z.number().nullable().optional().default(null),
|
|
8357
|
+
});
|
|
8358
|
+
const CheckoutPipelineStageSchema = z.object({
|
|
8359
|
+
name: z.string(),
|
|
8360
|
+
status: z.string(),
|
|
8361
|
+
jobs: z.array(CheckoutPipelineJobSchema).optional().default([]),
|
|
8362
|
+
});
|
|
8363
|
+
const CheckoutPipelineSchema = z.object({
|
|
8364
|
+
id: z.number(),
|
|
8365
|
+
status: z.string(),
|
|
8366
|
+
rawStatus: z.string(),
|
|
8367
|
+
url: z.string().nullable().optional().default(null),
|
|
8368
|
+
ref: z.string().nullable().optional().default(null),
|
|
8369
|
+
sha: z.string().nullable().optional().default(null),
|
|
8370
|
+
stages: z.array(CheckoutPipelineStageSchema).optional().default([]),
|
|
8371
|
+
});
|
|
6691
8372
|
export const CheckoutGithubCheckDetailsSchema = z.object({
|
|
6692
8373
|
checkRunId: z.number(),
|
|
6693
8374
|
workflowRunId: z.number().nullable().optional(),
|
|
@@ -6707,13 +8388,28 @@ export const CheckoutGithubCheckDetailsSchema = z.object({
|
|
|
6707
8388
|
annotations: z.array(CheckoutGithubCheckAnnotationSchema).optional().default([]),
|
|
6708
8389
|
failedJobs: z.array(CheckoutGithubCheckJobSchema).optional().default([]),
|
|
6709
8390
|
truncated: z.boolean().optional().default(false),
|
|
8391
|
+
// No default: server CheckDetails keeps this optional and GitHub leaves it absent.
|
|
8392
|
+
pipeline: CheckoutPipelineSchema.nullable().optional(),
|
|
6710
8393
|
});
|
|
8394
|
+
export const CheckoutCheckDetailsSchema = CheckoutGithubCheckDetailsSchema;
|
|
8395
|
+
export const CheckoutForgeGetCheckDetailsResponseSchema = z.object({
|
|
8396
|
+
type: z.literal("checkout.forge.get_check_details.response"),
|
|
8397
|
+
payload: z.object({
|
|
8398
|
+
cwd: z.string(),
|
|
8399
|
+
success: z.boolean(),
|
|
8400
|
+
details: CheckoutCheckDetailsSchema.nullable().optional().default(null),
|
|
8401
|
+
error: CheckoutErrorSchema.nullable(),
|
|
8402
|
+
requestId: z.string(),
|
|
8403
|
+
}),
|
|
8404
|
+
});
|
|
8405
|
+
// COMPAT(githubCheckDetailsRpc): added in v0.1.106, remove after 2026-12-28 once
|
|
8406
|
+
// all supported clients use checkout.forge.get_check_details.*.
|
|
6711
8407
|
export const CheckoutGithubGetCheckDetailsResponseSchema = z.object({
|
|
6712
8408
|
type: z.literal("checkout.github.get_check_details.response"),
|
|
6713
8409
|
payload: z.object({
|
|
6714
8410
|
cwd: z.string(),
|
|
6715
8411
|
success: z.boolean(),
|
|
6716
|
-
details:
|
|
8412
|
+
details: CheckoutCheckDetailsSchema.nullable().optional().default(null),
|
|
6717
8413
|
error: CheckoutErrorSchema.nullable(),
|
|
6718
8414
|
requestId: z.string(),
|
|
6719
8415
|
}),
|
|
@@ -6773,6 +8469,16 @@ const PullRequestTimelineCommentItemSchema = z.object({
|
|
|
6773
8469
|
// threads under their parent review. Absent on issue comments and on
|
|
6774
8470
|
// timelines from daemons that predate the field.
|
|
6775
8471
|
reviewId: z.string().optional(),
|
|
8472
|
+
// Forge-neutral discussion/thread id this comment belongs to, independent of a
|
|
8473
|
+
// file position. GitLab maps its discussion id here so general (non-file)
|
|
8474
|
+
// reply chains group into one thread; file-position threads also carry it.
|
|
8475
|
+
// Absent on standalone comments and on timelines from daemons that predate it.
|
|
8476
|
+
threadId: z.string().optional(),
|
|
8477
|
+
// Forge-neutral resolution state for a thread that has no file position, e.g. a
|
|
8478
|
+
// GitLab general (non-file) discussion that is resolvable. File-position threads
|
|
8479
|
+
// carry their resolution under `location.isResolved` instead. Absent on ordinary
|
|
8480
|
+
// comments, on forges that expose no thread resolution, and on older timelines.
|
|
8481
|
+
threadIsResolved: z.boolean().optional(),
|
|
6776
8482
|
location: z
|
|
6777
8483
|
.object({
|
|
6778
8484
|
path: z.string(),
|
|
@@ -6808,6 +8514,10 @@ export const PullRequestTimelineResponseSchema = z.object({
|
|
|
6808
8514
|
error: PullRequestTimelineErrorSchema.nullable().optional().default(null),
|
|
6809
8515
|
requestId: z.string().optional().default(""),
|
|
6810
8516
|
githubFeaturesEnabled: z.boolean().optional().default(true),
|
|
8517
|
+
// COMPAT(forgeAuthState): added in v0.1.106, remove after 2026-12-27. Optional richer
|
|
8518
|
+
// signal that supersedes githubFeaturesEnabled, mirroring CheckoutPrStatusPayloadSchema.
|
|
8519
|
+
// Drop the boolean once the daemon floor >= v0.1.106.
|
|
8520
|
+
authState: ForgeAuthStateSchema,
|
|
6811
8521
|
})
|
|
6812
8522
|
.optional()
|
|
6813
8523
|
.prefault({}),
|
|
@@ -6897,14 +8607,29 @@ export const BranchSuggestionsResponseSchema = z.object({
|
|
|
6897
8607
|
requestId: z.string(),
|
|
6898
8608
|
}),
|
|
6899
8609
|
});
|
|
8610
|
+
const ForgeSearchResponsePayloadSchema = z.object({
|
|
8611
|
+
items: z.array(z.unknown()),
|
|
8612
|
+
authState: z.unknown().optional(),
|
|
8613
|
+
error: z.string().nullable(),
|
|
8614
|
+
requestId: z.string(),
|
|
8615
|
+
});
|
|
8616
|
+
const GitHubSearchResponsePayloadSchema = z.object({
|
|
8617
|
+
items: z.array(z.unknown()),
|
|
8618
|
+
featuresEnabled: z.boolean().optional(),
|
|
8619
|
+
authState: z.unknown().optional(),
|
|
8620
|
+
githubFeaturesEnabled: z.boolean().optional(),
|
|
8621
|
+
error: z.string().nullable(),
|
|
8622
|
+
requestId: z.string(),
|
|
8623
|
+
});
|
|
8624
|
+
export const ForgeSearchResponseSchema = z.object({
|
|
8625
|
+
type: z.literal("forge.search.response"),
|
|
8626
|
+
payload: ForgeSearchResponsePayloadSchema,
|
|
8627
|
+
});
|
|
8628
|
+
// COMPAT(githubSearchRpc): added in v0.1.106, remove after 2026-12-28 once
|
|
8629
|
+
// clients use forge.search.*.
|
|
6900
8630
|
export const GitHubSearchResponseSchema = z.object({
|
|
6901
8631
|
type: z.literal("github_search_response"),
|
|
6902
|
-
payload:
|
|
6903
|
-
items: z.array(GitHubSearchItemSchema),
|
|
6904
|
-
githubFeaturesEnabled: z.boolean(),
|
|
6905
|
-
error: z.string().nullable(),
|
|
6906
|
-
requestId: z.string(),
|
|
6907
|
-
}),
|
|
8632
|
+
payload: GitHubSearchResponsePayloadSchema,
|
|
6908
8633
|
});
|
|
6909
8634
|
export const HostingSearchResponseSchema = z.object({
|
|
6910
8635
|
type: z.literal("hosting.search.response"),
|
|
@@ -6985,6 +8710,64 @@ export const FileExplorerResponseSchema = z.object({
|
|
|
6985
8710
|
requestId: z.string(),
|
|
6986
8711
|
}),
|
|
6987
8712
|
});
|
|
8713
|
+
export const FileSubscribeResponseSchema = z.object({
|
|
8714
|
+
type: z.literal("fs.file.subscribe.response"),
|
|
8715
|
+
payload: z.object({
|
|
8716
|
+
subscriptionId: z.string(),
|
|
8717
|
+
initial: FileVersionSchema,
|
|
8718
|
+
requestId: z.string(),
|
|
8719
|
+
}),
|
|
8720
|
+
});
|
|
8721
|
+
export const FileUnsubscribeResponseSchema = z.object({
|
|
8722
|
+
type: z.literal("fs.file.unsubscribe.response"),
|
|
8723
|
+
payload: z.object({
|
|
8724
|
+
subscriptionId: z.string(),
|
|
8725
|
+
requestId: z.string(),
|
|
8726
|
+
}),
|
|
8727
|
+
});
|
|
8728
|
+
export const FsFileWriteResultSchema = z.discriminatedUnion("status", [
|
|
8729
|
+
z.object({
|
|
8730
|
+
status: z.literal("written"),
|
|
8731
|
+
modifiedAt: z.string(),
|
|
8732
|
+
size: z.number(),
|
|
8733
|
+
revision: z.string().optional(),
|
|
8734
|
+
}),
|
|
8735
|
+
z.object({ status: z.literal("conflict"), version: FileVersionSchema }),
|
|
8736
|
+
z.object({ status: z.literal("error"), error: z.string() }),
|
|
8737
|
+
]);
|
|
8738
|
+
export const FsFileWriteResponseSchema = z.object({
|
|
8739
|
+
type: z.literal("fs.file.write.response"),
|
|
8740
|
+
payload: z.object({
|
|
8741
|
+
result: FsFileWriteResultSchema,
|
|
8742
|
+
requestId: z.string(),
|
|
8743
|
+
}),
|
|
8744
|
+
});
|
|
8745
|
+
export const FsFileWriteBinaryResultSchema = z.discriminatedUnion("status", [
|
|
8746
|
+
z.object({
|
|
8747
|
+
status: z.literal("written"),
|
|
8748
|
+
modifiedAt: z.string(),
|
|
8749
|
+
size: z.number(),
|
|
8750
|
+
}),
|
|
8751
|
+
// The target is already there and the request did not ask to replace it.
|
|
8752
|
+
z.object({ status: z.literal("exists") }),
|
|
8753
|
+
z.object({ status: z.literal("error"), error: z.string() }),
|
|
8754
|
+
]);
|
|
8755
|
+
export const FsFileWriteBinaryResponseSchema = z.object({
|
|
8756
|
+
type: z.literal("fs.file.write_binary.response"),
|
|
8757
|
+
payload: z.object({
|
|
8758
|
+
cwd: z.string(),
|
|
8759
|
+
path: z.string(),
|
|
8760
|
+
result: FsFileWriteBinaryResultSchema,
|
|
8761
|
+
requestId: z.string(),
|
|
8762
|
+
}),
|
|
8763
|
+
});
|
|
8764
|
+
export const FileUpdateSchema = z.object({
|
|
8765
|
+
type: z.literal("fs.file.update"),
|
|
8766
|
+
payload: z.object({
|
|
8767
|
+
subscriptionId: z.string(),
|
|
8768
|
+
version: FileVersionSchema,
|
|
8769
|
+
}),
|
|
8770
|
+
});
|
|
6988
8771
|
const ProjectIconSchema = z.object({
|
|
6989
8772
|
data: z.string(),
|
|
6990
8773
|
mimeType: z.string(),
|
|
@@ -7975,7 +9758,72 @@ export const DaemonUpdateProgressMessageSchema = z.object({
|
|
|
7975
9758
|
phase: z.enum(["starting", "downloading", "installing", "complete"]),
|
|
7976
9759
|
}),
|
|
7977
9760
|
});
|
|
9761
|
+
export const HubExecutionAgentCreateResponseSchema = z.object({
|
|
9762
|
+
type: z.literal("hub.execution.agent.create.response"),
|
|
9763
|
+
payload: z.object({
|
|
9764
|
+
requestId: z.string(),
|
|
9765
|
+
executionId: z.string(),
|
|
9766
|
+
agentId: z.string().nullable(),
|
|
9767
|
+
agent: AgentSnapshotPayloadSchema.nullable(),
|
|
9768
|
+
success: z.boolean(),
|
|
9769
|
+
error: z.string().nullable(),
|
|
9770
|
+
}),
|
|
9771
|
+
});
|
|
9772
|
+
export const HubExecutionControlResponseSchema = z.object({
|
|
9773
|
+
type: z.literal("hub.execution.control.response"),
|
|
9774
|
+
payload: z.object({
|
|
9775
|
+
requestId: z.string(),
|
|
9776
|
+
executionId: z.string(),
|
|
9777
|
+
action: HubExecutionControlActionSchema,
|
|
9778
|
+
success: z.boolean(),
|
|
9779
|
+
error: z.string().nullable(),
|
|
9780
|
+
}),
|
|
9781
|
+
});
|
|
9782
|
+
export const HubExecutionAgentUpdateSchema = z.object({
|
|
9783
|
+
type: z.literal("hub.execution.agent.update"),
|
|
9784
|
+
payload: z.object({
|
|
9785
|
+
executionId: z.string(),
|
|
9786
|
+
agentId: z.string(),
|
|
9787
|
+
agent: AgentSnapshotPayloadSchema,
|
|
9788
|
+
}),
|
|
9789
|
+
});
|
|
9790
|
+
export const HubExecutionAgentStreamSchema = z.object({
|
|
9791
|
+
type: z.literal("hub.execution.agent.stream"),
|
|
9792
|
+
payload: z.object({
|
|
9793
|
+
executionId: z.string(),
|
|
9794
|
+
agentId: z.string(),
|
|
9795
|
+
event: AgentStreamEventPayloadSchema,
|
|
9796
|
+
}),
|
|
9797
|
+
});
|
|
9798
|
+
export const HubExecutionOutboundMessageSchema = z.discriminatedUnion("type", [
|
|
9799
|
+
HubExecutionAgentCreateResponseSchema,
|
|
9800
|
+
HubExecutionControlResponseSchema,
|
|
9801
|
+
HubExecutionAgentUpdateSchema,
|
|
9802
|
+
HubExecutionAgentStreamSchema,
|
|
9803
|
+
]);
|
|
9804
|
+
export class HubMessageCorrelationError extends Error {
|
|
9805
|
+
constructor(messageType) {
|
|
9806
|
+
super(`Hub message ${messageType} has mismatched agent correlation`);
|
|
9807
|
+
this.name = "HubMessageCorrelationError";
|
|
9808
|
+
}
|
|
9809
|
+
}
|
|
9810
|
+
export function parseHubExecutionOutboundMessage(value) {
|
|
9811
|
+
const message = HubExecutionOutboundMessageSchema.parse(value);
|
|
9812
|
+
const payload = message.payload;
|
|
9813
|
+
if ("agent" in payload &&
|
|
9814
|
+
payload.agent !== null &&
|
|
9815
|
+
"agentId" in payload &&
|
|
9816
|
+
payload.agentId !== null &&
|
|
9817
|
+
payload.agent.id !== payload.agentId) {
|
|
9818
|
+
throw new HubMessageCorrelationError(message.type);
|
|
9819
|
+
}
|
|
9820
|
+
return message;
|
|
9821
|
+
}
|
|
7978
9822
|
export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
|
|
9823
|
+
HubExecutionAgentCreateResponseSchema,
|
|
9824
|
+
HubExecutionControlResponseSchema,
|
|
9825
|
+
HubExecutionAgentUpdateSchema,
|
|
9826
|
+
HubExecutionAgentStreamSchema,
|
|
7979
9827
|
BrowserAutomationExecuteRequestSchema,
|
|
7980
9828
|
ActivityLogMessageSchema,
|
|
7981
9829
|
AssistantChunkMessageSchema,
|
|
@@ -7994,6 +9842,8 @@ export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
7994
9842
|
ArtifactUpdateMessageSchema,
|
|
7995
9843
|
AgentUpdateMessageSchema,
|
|
7996
9844
|
WorkspaceUpdateMessageSchema,
|
|
9845
|
+
ProjectUpdateMessageSchema,
|
|
9846
|
+
ProjectListResponseMessageSchema,
|
|
7997
9847
|
ScriptStatusUpdateMessageSchema,
|
|
7998
9848
|
WorkspaceSetupProgressMessageSchema,
|
|
7999
9849
|
WorkspaceSetupStatusResponseMessageSchema,
|
|
@@ -8006,8 +9856,14 @@ export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
8006
9856
|
ProjectAddResponseSchema,
|
|
8007
9857
|
ProjectScaffoldResponseSchema,
|
|
8008
9858
|
ProjectScaffoldProgressSchema,
|
|
9859
|
+
ProjectCreateDirectoryResponseSchema,
|
|
8009
9860
|
OpenProjectResponseMessageSchema,
|
|
9861
|
+
WorkspaceGithubSearchRepositoriesResponseSchema,
|
|
9862
|
+
ProjectGithubCloneResponseSchema,
|
|
8010
9863
|
StartWorkspaceScriptResponseMessageSchema,
|
|
9864
|
+
WorkspaceScriptListResponseMessageSchema,
|
|
9865
|
+
WorkspaceScriptStartResponseMessageSchema,
|
|
9866
|
+
WorkspaceScriptStopResponseMessageSchema,
|
|
8011
9867
|
LegacyListAvailableEditorsResponseMessageSchema,
|
|
8012
9868
|
LegacyOpenInEditorResponseMessageSchema,
|
|
8013
9869
|
ArchiveWorkspaceResponseMessageSchema,
|
|
@@ -8017,6 +9873,11 @@ export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
8017
9873
|
WorktreeReattachResponseSchema,
|
|
8018
9874
|
FetchAgentResponseMessageSchema,
|
|
8019
9875
|
FetchAgentTimelineResponseMessageSchema,
|
|
9876
|
+
ProviderSubagentListResponseMessageSchema,
|
|
9877
|
+
ProviderSubagentTimelineResponseMessageSchema,
|
|
9878
|
+
ProviderSubagentUpdateMessageSchema,
|
|
9879
|
+
SetAgentTimelineSubscriptionResponseMessageSchema,
|
|
9880
|
+
AgentAttentionRequiredMessageSchema,
|
|
8020
9881
|
AgentForkContextResponseMessageSchema,
|
|
8021
9882
|
CancelAgentResponseMessageSchema,
|
|
8022
9883
|
ClearAgentAttentionResponseMessageSchema,
|
|
@@ -8026,15 +9887,20 @@ export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
8026
9887
|
SetVoiceModeResponseMessageSchema,
|
|
8027
9888
|
DaemonGetStatusResponseSchema,
|
|
8028
9889
|
DaemonGetPairingOfferResponseSchema,
|
|
9890
|
+
HubManagementDaemonConnectResponseSchema,
|
|
9891
|
+
HubManagementDaemonGetStatusResponseSchema,
|
|
9892
|
+
HubManagementDaemonDisconnectResponseSchema,
|
|
8029
9893
|
DiagnosticsResponseSchema,
|
|
8030
9894
|
GetDaemonConfigResponseMessageSchema,
|
|
8031
9895
|
SetDaemonConfigResponseMessageSchema,
|
|
9896
|
+
ConnectorsListToolsResponseSchema,
|
|
8032
9897
|
SpeechSettingsGetOptionsResponseSchema,
|
|
8033
9898
|
SpeechTtsPreviewResponseSchema,
|
|
8034
9899
|
SpeechTtsSpeakResponseSchema,
|
|
8035
9900
|
SpeechTtsSpeakCancelResponseSchema,
|
|
8036
9901
|
VisualizerVoiceCuesGenerateResponseSchema,
|
|
8037
9902
|
AgentPersonalitiesGetStatsResponseSchema,
|
|
9903
|
+
AgentPersonalitiesGenerateProfileResponseSchema,
|
|
8038
9904
|
ReadProjectConfigResponseMessageSchema,
|
|
8039
9905
|
WriteProjectConfigResponseMessageSchema,
|
|
8040
9906
|
SetAgentModeResponseMessageSchema,
|
|
@@ -8065,6 +9931,9 @@ export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
8065
9931
|
ProjectLinksUnsetResponseSchema,
|
|
8066
9932
|
ProjectLinksChangedSchema,
|
|
8067
9933
|
WorkspaceTitleSetResponseSchema,
|
|
9934
|
+
WorkspacePinSetResponseSchema,
|
|
9935
|
+
WorkspaceRecoveryInspectResponseSchema,
|
|
9936
|
+
WorkspaceRecoveryRestoreResponseSchema,
|
|
8068
9937
|
WaitForFinishResponseMessageSchema,
|
|
8069
9938
|
AgentPermissionRequestMessageSchema,
|
|
8070
9939
|
AgentPermissionResolvedMessageSchema,
|
|
@@ -8072,6 +9941,28 @@ export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
8072
9941
|
HistoryAgentsClearArchivedResponseSchema,
|
|
8073
9942
|
AttachmentsImagesStatsResponseSchema,
|
|
8074
9943
|
AttachmentsImagesClearResponseSchema,
|
|
9944
|
+
BrainHostStatusResponseSchema,
|
|
9945
|
+
BrainHostStartResponseSchema,
|
|
9946
|
+
BrainHostStopResponseSchema,
|
|
9947
|
+
BrainHostRestartResponseSchema,
|
|
9948
|
+
BrainEvalsGetResponseSchema,
|
|
9949
|
+
BrainNetworkDiscoverResponseSchema,
|
|
9950
|
+
BrainModelsListResponseSchema,
|
|
9951
|
+
BrainRemoteConfigGetResponseSchema,
|
|
9952
|
+
BrainRemoteConfigPatchResponseSchema,
|
|
9953
|
+
BrainModelsScanResponseSchema,
|
|
9954
|
+
BrainCatalogListResponseSchema,
|
|
9955
|
+
BrainRuntimeListResponseSchema,
|
|
9956
|
+
BrainModelsPullResponseSchema,
|
|
9957
|
+
BrainRuntimeInstallResponseSchema,
|
|
9958
|
+
BrainCalibrateResponseSchema,
|
|
9959
|
+
BrainSweepResponseSchema,
|
|
9960
|
+
BrainBenchResponseSchema,
|
|
9961
|
+
BrainJobsListResponseSchema,
|
|
9962
|
+
BrainJobsCancelResponseSchema,
|
|
9963
|
+
BrainHfSearchResponseSchema,
|
|
9964
|
+
BrainHfQuantsResponseSchema,
|
|
9965
|
+
BrainModelsAddResponseSchema,
|
|
8075
9966
|
AgentArchivedMessageSchema,
|
|
8076
9967
|
CloseItemsResponseSchema,
|
|
8077
9968
|
CheckoutStatusResponseSchema,
|
|
@@ -8111,7 +10002,11 @@ export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
8111
10002
|
CheckoutRefreshResponseSchema,
|
|
8112
10003
|
CheckoutPrCreateResponseSchema,
|
|
8113
10004
|
CheckoutPrMergeResponseSchema,
|
|
10005
|
+
CheckoutForgeSetAutoMergeResponseSchema,
|
|
8114
10006
|
CheckoutGithubSetAutoMergeResponseSchema,
|
|
10007
|
+
CheckoutCommitsListResponseSchema,
|
|
10008
|
+
CheckoutCommitFileDiffResponseSchema,
|
|
10009
|
+
CheckoutForgeGetCheckDetailsResponseSchema,
|
|
8115
10010
|
CheckoutGithubGetCheckDetailsResponseSchema,
|
|
8116
10011
|
PreviewListConfigResponseSchema,
|
|
8117
10012
|
PreviewStartResponseSchema,
|
|
@@ -8126,6 +10021,7 @@ export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
8126
10021
|
StashListResponseSchema,
|
|
8127
10022
|
ValidateBranchResponseSchema,
|
|
8128
10023
|
BranchSuggestionsResponseSchema,
|
|
10024
|
+
ForgeSearchResponseSchema,
|
|
8129
10025
|
GitHubSearchResponseSchema,
|
|
8130
10026
|
HostingSearchResponseSchema,
|
|
8131
10027
|
HostingAuthStatusResponseSchema,
|
|
@@ -8136,6 +10032,11 @@ export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
8136
10032
|
OttoWorktreeArchiveResponseSchema,
|
|
8137
10033
|
CreateOttoWorktreeResponseSchema,
|
|
8138
10034
|
FileExplorerResponseSchema,
|
|
10035
|
+
FileSubscribeResponseSchema,
|
|
10036
|
+
FileUnsubscribeResponseSchema,
|
|
10037
|
+
FsFileWriteResponseSchema,
|
|
10038
|
+
FsFileWriteBinaryResponseSchema,
|
|
10039
|
+
FileUpdateSchema,
|
|
8139
10040
|
ProjectIconResponseSchema,
|
|
8140
10041
|
FileDownloadTokenResponseSchema,
|
|
8141
10042
|
FileUploadResponseSchema,
|
|
@@ -8255,8 +10156,11 @@ export const WSHelloMessageSchema = z.object({
|
|
|
8255
10156
|
voice: z.boolean().optional(),
|
|
8256
10157
|
pushNotifications: z.boolean().optional(),
|
|
8257
10158
|
[CLIENT_CAPS.reasoningMergeEnum]: z.boolean().optional(),
|
|
10159
|
+
[CLIENT_CAPS.selectiveAgentTimeline]: z.boolean().optional(),
|
|
8258
10160
|
[CLIENT_CAPS.customModeIcons]: z.boolean().optional(),
|
|
8259
10161
|
[CLIENT_CAPS.terminalReflowableSnapshot]: z.boolean().optional(),
|
|
10162
|
+
[CLIENT_CAPS.providerSubagents]: z.boolean().optional(),
|
|
10163
|
+
[CLIENT_CAPS.projectUpdates]: z.boolean().optional(),
|
|
8260
10164
|
[CLIENT_CAPS.browserHost]: BrowserAutomationHostCapabilitySchema.optional(),
|
|
8261
10165
|
})
|
|
8262
10166
|
.passthrough()
|