@otto-code/protocol 0.7.4 → 0.7.5
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-types.d.ts +12 -0
- package/dist/browser-automation/rpc-schemas.d.ts +21 -0
- package/dist/browser-automation/rpc-schemas.js +10 -0
- package/dist/generated/validation/ws-outbound.aot.js +21861 -17792
- package/dist/messages.d.ts +4068 -14
- package/dist/messages.js +809 -1
- package/dist/provider-config.d.ts +81 -0
- package/dist/provider-config.js +42 -0
- package/dist/validation/ws-outbound-schema-metadata.d.ts +671 -2
- 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,153 @@ 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
|
+
})
|
|
435
|
+
.passthrough();
|
|
436
|
+
export const MutableBrainConfigSchema = z
|
|
437
|
+
.object({
|
|
438
|
+
enabled: z.boolean().default(false),
|
|
439
|
+
autoStart: z.boolean().default(false),
|
|
440
|
+
// "local": the daemon spawns and supervises the brain on this host.
|
|
441
|
+
// "remote": the daemon connects to a brain running on another Otto host
|
|
442
|
+
// (read-only: status/evals/config, no lifecycle). Gated by features.brainRemote.
|
|
443
|
+
mode: z.enum(["local", "remote"]).default("local"),
|
|
444
|
+
remote: MutableBrainRemoteConfigSchema.default({
|
|
445
|
+
host: "",
|
|
446
|
+
port: 1234,
|
|
447
|
+
secure: false,
|
|
448
|
+
authToken: null,
|
|
449
|
+
}),
|
|
450
|
+
listen: z
|
|
451
|
+
.object({
|
|
452
|
+
host: z.string().default("127.0.0.1"),
|
|
453
|
+
port: z.number().int().default(1234),
|
|
454
|
+
})
|
|
455
|
+
.passthrough()
|
|
456
|
+
.default({ host: "127.0.0.1", port: 1234 }),
|
|
457
|
+
defaultModel: z.string().nullable().default(null),
|
|
458
|
+
// Pin the host to one model: serve only the default/resident model and
|
|
459
|
+
// refuse completion requests that ask for a different one.
|
|
460
|
+
lockModel: z.boolean().default(false),
|
|
461
|
+
// Sharing gates (off by default). allowRemoteConfig: key holders may CHANGE
|
|
462
|
+
// config over the network (POST /__host/config), not just use it.
|
|
463
|
+
// allowInsecureBind: permit a non-loopback bind with no token (open share).
|
|
464
|
+
allowRemoteConfig: z.boolean().default(false),
|
|
465
|
+
allowInsecureBind: z.boolean().default(false),
|
|
466
|
+
authMode: z.enum(["none", "token"]).default("none"),
|
|
467
|
+
// Secret: masked with DAEMON_CONFIG_SECRET_SENTINEL on the way out; an
|
|
468
|
+
// unchanged sentinel is stripped from inbound patches.
|
|
469
|
+
authToken: z.string().nullable().default(null),
|
|
470
|
+
tls: MutableBrainTlsConfigSchema.default({
|
|
471
|
+
mode: "off",
|
|
472
|
+
certFile: null,
|
|
473
|
+
keyFile: null,
|
|
474
|
+
hostname: null,
|
|
475
|
+
certDir: null,
|
|
476
|
+
renewBeforeDays: 21,
|
|
477
|
+
}),
|
|
478
|
+
})
|
|
479
|
+
.passthrough();
|
|
480
|
+
// The brain PATCH schema — deliberately NOT `MutableBrainConfigSchema.partial()`.
|
|
481
|
+
// Every field of the full schema carries a `.default()` (so an old daemon's
|
|
482
|
+
// half-written config still parses as a well-formed OFF section), and Zod keeps
|
|
483
|
+
// those defaults through `.partial()`: `MutableBrainConfigSchema.partial().parse(
|
|
484
|
+
// { allowRemoteConfig: true })` expands to the FULL object with every other field
|
|
485
|
+
// defaulted. The daemon deep-merges the parsed patch over the stored config, so a
|
|
486
|
+
// single-field patch would silently reset the entire brain block to defaults —
|
|
487
|
+
// turning sharing off (host back to loopback), wiping the auth token, and
|
|
488
|
+
// disabling the server. Mirroring the shape WITHOUT defaults keeps an omitted
|
|
489
|
+
// field omitted, so the deep-merge preserves it. Every level is deep-partial so a
|
|
490
|
+
// nested patch (e.g. just `listen.host`) preserves its siblings too. Keep the
|
|
491
|
+
// field set in sync with MutableBrainConfigSchema; `.passthrough()` carries any
|
|
492
|
+
// field a newer daemon adds through untouched in the meantime.
|
|
493
|
+
const MutableBrainTlsPatchSchema = z
|
|
494
|
+
.object({
|
|
495
|
+
mode: z.enum(["off", "files", "self-signed", "tailscale"]),
|
|
496
|
+
certFile: z.string().nullable(),
|
|
497
|
+
keyFile: z.string().nullable(),
|
|
498
|
+
hostname: z.string().nullable(),
|
|
499
|
+
certDir: z.string().nullable(),
|
|
500
|
+
renewBeforeDays: z.number().int().min(1),
|
|
501
|
+
})
|
|
502
|
+
.partial()
|
|
503
|
+
.passthrough();
|
|
504
|
+
const MutableBrainRemotePatchSchema = z
|
|
505
|
+
.object({
|
|
506
|
+
host: z.string(),
|
|
507
|
+
port: z.number().int(),
|
|
508
|
+
secure: z.boolean(),
|
|
509
|
+
authToken: z.string().nullable(),
|
|
510
|
+
})
|
|
511
|
+
.partial()
|
|
512
|
+
.passthrough();
|
|
513
|
+
const MutableBrainListenPatchSchema = z
|
|
514
|
+
.object({
|
|
515
|
+
host: z.string(),
|
|
516
|
+
port: z.number().int(),
|
|
517
|
+
})
|
|
518
|
+
.partial()
|
|
519
|
+
.passthrough();
|
|
520
|
+
export const MutableBrainConfigPatchSchema = z
|
|
521
|
+
.object({
|
|
522
|
+
enabled: z.boolean(),
|
|
523
|
+
autoStart: z.boolean(),
|
|
524
|
+
mode: z.enum(["local", "remote"]),
|
|
525
|
+
remote: MutableBrainRemotePatchSchema,
|
|
526
|
+
listen: MutableBrainListenPatchSchema,
|
|
527
|
+
defaultModel: z.string().nullable(),
|
|
528
|
+
lockModel: z.boolean(),
|
|
529
|
+
allowRemoteConfig: z.boolean(),
|
|
530
|
+
allowInsecureBind: z.boolean(),
|
|
531
|
+
authMode: z.enum(["none", "token"]),
|
|
532
|
+
authToken: z.string().nullable(),
|
|
533
|
+
tls: MutableBrainTlsPatchSchema,
|
|
534
|
+
})
|
|
535
|
+
.partial()
|
|
536
|
+
.passthrough();
|
|
537
|
+
export const DEFAULT_MUTABLE_BRAIN_CONFIG = {
|
|
538
|
+
enabled: false,
|
|
539
|
+
autoStart: false,
|
|
540
|
+
mode: "local",
|
|
541
|
+
remote: { host: "", port: 1234, secure: false, authToken: null },
|
|
542
|
+
listen: { host: "127.0.0.1", port: 1234 },
|
|
543
|
+
defaultModel: null,
|
|
544
|
+
lockModel: false,
|
|
545
|
+
allowRemoteConfig: false,
|
|
546
|
+
allowInsecureBind: false,
|
|
547
|
+
authMode: "none",
|
|
548
|
+
authToken: null,
|
|
549
|
+
tls: {
|
|
550
|
+
mode: "off",
|
|
551
|
+
certFile: null,
|
|
552
|
+
keyFile: null,
|
|
553
|
+
hostname: null,
|
|
554
|
+
certDir: null,
|
|
555
|
+
renewBeforeDays: 21,
|
|
556
|
+
},
|
|
557
|
+
};
|
|
400
558
|
export const MutableDaemonConfigSchema = z
|
|
401
559
|
.object({
|
|
402
560
|
mcp: z
|
|
@@ -418,6 +576,8 @@ export const MutableDaemonConfigSchema = z
|
|
|
418
576
|
promptSuggestions: true,
|
|
419
577
|
agentProgressSummaries: true,
|
|
420
578
|
notifyOnFinishDefault: true,
|
|
579
|
+
todoNudge: true,
|
|
580
|
+
todoReconcileOnIdle: true,
|
|
421
581
|
}),
|
|
422
582
|
providers: z.record(z.string(), MutableDaemonProviderConfigSchema).default({}),
|
|
423
583
|
metadataGeneration: MutableMetadataGenerationConfigSchema.default({
|
|
@@ -481,6 +641,15 @@ export const MutableDaemonConfigSchema = z
|
|
|
481
641
|
maxRunningProbes: 2,
|
|
482
642
|
idleMinutes: 10,
|
|
483
643
|
}),
|
|
644
|
+
// Local AI host (otto-brain) management. Gated by server_info features.brainControl;
|
|
645
|
+
// defaults OFF and well-formed so a new client parsing an old daemon's config renders
|
|
646
|
+
// the row without ever implying the brain is running.
|
|
647
|
+
brain: MutableBrainConfigSchema.default(DEFAULT_MUTABLE_BRAIN_CONFIG),
|
|
648
|
+
// Host-wide connector registry (MCP servers surfaced as named, toggle-able
|
|
649
|
+
// integrations). Gated by server_info features.connectors; defaults to an
|
|
650
|
+
// empty roster so a new client parsing an old daemon's config still sees a
|
|
651
|
+
// well-formed section.
|
|
652
|
+
connectors: z.array(ConnectorConfigSchema).default([]),
|
|
484
653
|
})
|
|
485
654
|
.passthrough();
|
|
486
655
|
export const MutableDaemonConfigPatchSchema = z
|
|
@@ -529,6 +698,15 @@ export const MutableDaemonConfigPatchSchema = z
|
|
|
529
698
|
lsp: MutableLspConfigSchema.partial().optional(),
|
|
530
699
|
// Gated by server_info features.solutionView; patches deep-merge.
|
|
531
700
|
dotnetSolutionManagement: MutableDotnetSolutionConfigSchema.partial().optional(),
|
|
701
|
+
// Gated by server_info features.brainControl; patches deep-merge. Uses the
|
|
702
|
+
// dedicated no-default patch schema (see MutableBrainConfigPatchSchema): a
|
|
703
|
+
// plain `.partial()` here keeps every field's default and resets the whole
|
|
704
|
+
// block on a single-field patch.
|
|
705
|
+
brain: MutableBrainConfigPatchSchema.optional(),
|
|
706
|
+
// Gated by server_info features.connectors. Replaces the full array
|
|
707
|
+
// (read-modify-write), matching modelTierOverrides/savedProviderEndpoints, so
|
|
708
|
+
// enabling/disabling a connector or a tool is a whole-array rewrite.
|
|
709
|
+
connectors: z.array(ConnectorConfigSchema).optional(),
|
|
532
710
|
})
|
|
533
711
|
.partial()
|
|
534
712
|
.passthrough();
|
|
@@ -1030,6 +1208,13 @@ export const QueuedAgentMessagePayloadSchema = z.object({
|
|
|
1030
1208
|
preview: z.string(),
|
|
1031
1209
|
enqueuedAt: z.string(),
|
|
1032
1210
|
attachmentCount: z.number().int().nonnegative().optional(),
|
|
1211
|
+
/**
|
|
1212
|
+
* Who parked the message. Absent (from an older daemon) or "user" is a normal
|
|
1213
|
+
* user turn; "system" marks a system-injected entry (a chat mention, a
|
|
1214
|
+
* scheduled fire) that the daemon's drain never merges into a user turn — the
|
|
1215
|
+
* client must likewise exclude it from "Send all".
|
|
1216
|
+
*/
|
|
1217
|
+
source: z.enum(["user", "system"]).optional(),
|
|
1033
1218
|
});
|
|
1034
1219
|
/**
|
|
1035
1220
|
* An agent's LIFETIME SPEND, kept as the real token split plus the provider's
|
|
@@ -1129,6 +1314,14 @@ export const AgentSnapshotPayloadSchema = z.object({
|
|
|
1129
1314
|
// COMPAT(observedSubagents): added in v0.4.3; absent ⇒ "attended". Drop the
|
|
1130
1315
|
// gate when daemon floor >= v0.4.3. See projects/observed-subagents/observed-subagents.md.
|
|
1131
1316
|
attend: z.enum(["attended", "observed"]).optional(),
|
|
1317
|
+
// True when an observed sub-agent run outlives an interrupt of the parent's
|
|
1318
|
+
// turn: a backgrounded Task/Agent (its tool_result was only a launch ack) or
|
|
1319
|
+
// a Workflow orchestration run. The client uses it to stop claiming that
|
|
1320
|
+
// interrupting the parent stops work it will not actually stop.
|
|
1321
|
+
// COMPAT(backgroundedObservedSubagents): added in v0.7.5; absent ⇒ treated as
|
|
1322
|
+
// foreground, which is the pre-existing behavior. Drop the gate when daemon
|
|
1323
|
+
// floor >= v0.7.5. See docs/chat-lifecycle.md.
|
|
1324
|
+
backgrounded: z.boolean().optional(),
|
|
1132
1325
|
// Spinner colors from the Agent Personality this agent was spawned from, so
|
|
1133
1326
|
// its live thinking indicator renders in the personality's identity. Absent ⇒
|
|
1134
1327
|
// the client falls back to the theme's default spinner colors. Purely additive
|
|
@@ -1313,6 +1506,459 @@ export const AttachmentsImagesClearResponseSchema = z.object({
|
|
|
1313
1506
|
requestId: z.string(),
|
|
1314
1507
|
}),
|
|
1315
1508
|
});
|
|
1509
|
+
// --- Local AI host (otto-brain) management -------------------------------
|
|
1510
|
+
// Lifecycle + evals are correlated request/response RPCs. Gated by
|
|
1511
|
+
// server_info.features.brainControl (lifecycle) and features.brainStatus
|
|
1512
|
+
// (evals). Live status streaming (subscribe_brain_status + brain_status_changed)
|
|
1513
|
+
// is added alongside its client/daemon consumers.
|
|
1514
|
+
// The brain's host status, as the daemon derives it: liveness plus the fields
|
|
1515
|
+
// proxied from the brain's own `/__host/status`. Passthrough on the opaque
|
|
1516
|
+
// sub-objects so the brain can evolve them without a protocol bump.
|
|
1517
|
+
export const BrainHostStatusSchema = z
|
|
1518
|
+
.object({
|
|
1519
|
+
running: z.boolean(),
|
|
1520
|
+
pid: z.number().nullable().optional(),
|
|
1521
|
+
version: z.string().nullable().optional(),
|
|
1522
|
+
host: z.string().nullable().optional(),
|
|
1523
|
+
port: z.number().nullable().optional(),
|
|
1524
|
+
displayHost: z.string().nullable().optional(),
|
|
1525
|
+
secure: z.boolean().optional(),
|
|
1526
|
+
state: z.string().nullable().optional(),
|
|
1527
|
+
model: z.string().nullable().optional(),
|
|
1528
|
+
modelId: z.string().nullable().optional(),
|
|
1529
|
+
vramBytes: z.number().nullable().optional(),
|
|
1530
|
+
loadSeconds: z.number().nullable().optional(),
|
|
1531
|
+
startedAt: z.string().nullable().optional(),
|
|
1532
|
+
lastError: z.string().nullable().optional(),
|
|
1533
|
+
telemetry: z.record(z.string(), z.unknown()).nullable().optional(),
|
|
1534
|
+
scheduler: z.record(z.string(), z.unknown()).nullable().optional(),
|
|
1535
|
+
recent: z.array(z.record(z.string(), z.unknown())).optional(),
|
|
1536
|
+
})
|
|
1537
|
+
.passthrough();
|
|
1538
|
+
const BrainHostStatusResultSchema = z.object({
|
|
1539
|
+
status: BrainHostStatusSchema,
|
|
1540
|
+
error: z.string().nullable(),
|
|
1541
|
+
requestId: z.string(),
|
|
1542
|
+
});
|
|
1543
|
+
export const BrainHostStatusRequestSchema = z.object({
|
|
1544
|
+
type: z.literal("brain.host.status.request"),
|
|
1545
|
+
requestId: z.string(),
|
|
1546
|
+
});
|
|
1547
|
+
export const BrainHostStatusResponseSchema = z.object({
|
|
1548
|
+
type: z.literal("brain.host.status.response"),
|
|
1549
|
+
payload: BrainHostStatusResultSchema,
|
|
1550
|
+
});
|
|
1551
|
+
export const BrainHostStartRequestSchema = z.object({
|
|
1552
|
+
type: z.literal("brain.host.start.request"),
|
|
1553
|
+
// Optional model fragment/id to load on start; null = the brain's default.
|
|
1554
|
+
model: z.string().nullable().default(null),
|
|
1555
|
+
requestId: z.string(),
|
|
1556
|
+
});
|
|
1557
|
+
export const BrainHostStartResponseSchema = z.object({
|
|
1558
|
+
type: z.literal("brain.host.start.response"),
|
|
1559
|
+
payload: BrainHostStatusResultSchema,
|
|
1560
|
+
});
|
|
1561
|
+
export const BrainHostStopRequestSchema = z.object({
|
|
1562
|
+
type: z.literal("brain.host.stop.request"),
|
|
1563
|
+
requestId: z.string(),
|
|
1564
|
+
});
|
|
1565
|
+
export const BrainHostStopResponseSchema = z.object({
|
|
1566
|
+
type: z.literal("brain.host.stop.response"),
|
|
1567
|
+
payload: BrainHostStatusResultSchema,
|
|
1568
|
+
});
|
|
1569
|
+
export const BrainHostRestartRequestSchema = z.object({
|
|
1570
|
+
type: z.literal("brain.host.restart.request"),
|
|
1571
|
+
model: z.string().nullable().default(null),
|
|
1572
|
+
requestId: z.string(),
|
|
1573
|
+
});
|
|
1574
|
+
export const BrainHostRestartResponseSchema = z.object({
|
|
1575
|
+
type: z.literal("brain.host.restart.response"),
|
|
1576
|
+
payload: BrainHostStatusResultSchema,
|
|
1577
|
+
});
|
|
1578
|
+
// Benchmark rankings/variance/latest, proxied from the brain's `/__host/evals`.
|
|
1579
|
+
export const BrainEvalsSchema = z
|
|
1580
|
+
.object({
|
|
1581
|
+
rankings: z.array(z.record(z.string(), z.unknown())).default([]),
|
|
1582
|
+
latest: z.array(z.record(z.string(), z.unknown())).default([]),
|
|
1583
|
+
variance: z.array(z.record(z.string(), z.unknown())).default([]),
|
|
1584
|
+
runCount: z.number().default(0),
|
|
1585
|
+
})
|
|
1586
|
+
.passthrough();
|
|
1587
|
+
export const BrainEvalsGetRequestSchema = z.object({
|
|
1588
|
+
type: z.literal("brain.evals.get.request"),
|
|
1589
|
+
requestId: z.string(),
|
|
1590
|
+
});
|
|
1591
|
+
export const BrainEvalsGetResponseSchema = z.object({
|
|
1592
|
+
type: z.literal("brain.evals.get.response"),
|
|
1593
|
+
payload: z.object({
|
|
1594
|
+
evals: BrainEvalsSchema.nullable(),
|
|
1595
|
+
error: z.string().nullable(),
|
|
1596
|
+
requestId: z.string(),
|
|
1597
|
+
}),
|
|
1598
|
+
});
|
|
1599
|
+
// Brain network auto-discovery: the daemon enumerates this host's bind
|
|
1600
|
+
// addresses and probes the local `tailscale` CLI so the client can offer the
|
|
1601
|
+
// operator a pick-list of likely listen hosts (and pre-fill the tailscale TLS
|
|
1602
|
+
// mode) instead of asking them to hunt for IPs by hand.
|
|
1603
|
+
// Gated by server_info.features.brainNetworkDiscovery.
|
|
1604
|
+
export const BrainTailscaleInfoSchema = z
|
|
1605
|
+
.object({
|
|
1606
|
+
// Whether the tailscale CLI is present and its daemon answers.
|
|
1607
|
+
available: z.boolean(),
|
|
1608
|
+
// This machine's MagicDNS name, e.g. greyskull.tail279562.ts.net.
|
|
1609
|
+
hostname: z.string().nullable().optional(),
|
|
1610
|
+
// The tailnet IPv4 address, for a tailnet-only bind.
|
|
1611
|
+
ipv4: z.string().nullable().optional(),
|
|
1612
|
+
// The default directory the brain writes issued certificates to.
|
|
1613
|
+
certDir: z.string().nullable().optional(),
|
|
1614
|
+
})
|
|
1615
|
+
.passthrough();
|
|
1616
|
+
// One candidate value for `listen.host`, with a human label for the pick-list.
|
|
1617
|
+
export const BrainBindAddressSchema = z
|
|
1618
|
+
.object({
|
|
1619
|
+
// The literal value written to listen.host (an IP, 0.0.0.0, or "tailscale").
|
|
1620
|
+
value: z.string(),
|
|
1621
|
+
// Display label, e.g. "Local only", "All interfaces", "192.168.1.42 (en0)".
|
|
1622
|
+
label: z.string(),
|
|
1623
|
+
kind: z.enum(["loopback", "all", "lan", "tailscale"]),
|
|
1624
|
+
})
|
|
1625
|
+
.passthrough();
|
|
1626
|
+
export const BrainNetworkInfoSchema = z
|
|
1627
|
+
.object({
|
|
1628
|
+
addresses: z.array(BrainBindAddressSchema).default([]),
|
|
1629
|
+
tailscale: BrainTailscaleInfoSchema.nullable().optional(),
|
|
1630
|
+
})
|
|
1631
|
+
.passthrough();
|
|
1632
|
+
// Detected model names for the settings pickers. Read from the brain's
|
|
1633
|
+
// /v1/models when it is reachable (local child up, or remote); empty otherwise,
|
|
1634
|
+
// which the client renders as a disabled picker. Gated by features.brainStatus.
|
|
1635
|
+
export const BrainModelsListRequestSchema = z.object({
|
|
1636
|
+
type: z.literal("brain.models.list.request"),
|
|
1637
|
+
requestId: z.string(),
|
|
1638
|
+
});
|
|
1639
|
+
export const BrainModelsListResponseSchema = z.object({
|
|
1640
|
+
type: z.literal("brain.models.list.response"),
|
|
1641
|
+
payload: z.object({
|
|
1642
|
+
models: z.array(z.string()).default([]),
|
|
1643
|
+
error: z.string().nullable(),
|
|
1644
|
+
requestId: z.string(),
|
|
1645
|
+
}),
|
|
1646
|
+
});
|
|
1647
|
+
// Read/write a *remote* brain's own config (its /__host/config). Only valid in
|
|
1648
|
+
// brain.mode "remote"; the config is the remote brain's effective config with
|
|
1649
|
+
// secrets redacted. Editable fields are model-related (defaultModel, lockModel);
|
|
1650
|
+
// network/TLS/auth stay host-owned. Gated by features.brainRemote.
|
|
1651
|
+
export const BrainRemoteConfigSchema = z.record(z.string(), z.unknown());
|
|
1652
|
+
export const BrainRemoteConfigGetRequestSchema = z.object({
|
|
1653
|
+
type: z.literal("brain.remote.config.get.request"),
|
|
1654
|
+
requestId: z.string(),
|
|
1655
|
+
});
|
|
1656
|
+
export const BrainRemoteConfigGetResponseSchema = z.object({
|
|
1657
|
+
type: z.literal("brain.remote.config.get.response"),
|
|
1658
|
+
payload: z.object({
|
|
1659
|
+
config: BrainRemoteConfigSchema.nullable(),
|
|
1660
|
+
error: z.string().nullable(),
|
|
1661
|
+
requestId: z.string(),
|
|
1662
|
+
}),
|
|
1663
|
+
});
|
|
1664
|
+
export const BrainRemoteConfigPatchRequestSchema = z.object({
|
|
1665
|
+
type: z.literal("brain.remote.config.patch.request"),
|
|
1666
|
+
patch: BrainRemoteConfigSchema,
|
|
1667
|
+
requestId: z.string(),
|
|
1668
|
+
});
|
|
1669
|
+
export const BrainRemoteConfigPatchResponseSchema = z.object({
|
|
1670
|
+
type: z.literal("brain.remote.config.patch.response"),
|
|
1671
|
+
payload: z.object({
|
|
1672
|
+
config: BrainRemoteConfigSchema.nullable(),
|
|
1673
|
+
error: z.string().nullable(),
|
|
1674
|
+
requestId: z.string(),
|
|
1675
|
+
}),
|
|
1676
|
+
});
|
|
1677
|
+
export const BrainNetworkDiscoverRequestSchema = z.object({
|
|
1678
|
+
type: z.literal("brain.network.discover.request"),
|
|
1679
|
+
requestId: z.string(),
|
|
1680
|
+
});
|
|
1681
|
+
export const BrainNetworkDiscoverResponseSchema = z.object({
|
|
1682
|
+
type: z.literal("brain.network.discover.response"),
|
|
1683
|
+
payload: z.object({
|
|
1684
|
+
info: BrainNetworkInfoSchema.nullable(),
|
|
1685
|
+
error: z.string().nullable(),
|
|
1686
|
+
requestId: z.string(),
|
|
1687
|
+
}),
|
|
1688
|
+
});
|
|
1689
|
+
// --- Brain model management (runtimes, catalog, downloads, ops) ----------
|
|
1690
|
+
// The daemon drives these by shelling out to `otto-brain <verb> --json` (it
|
|
1691
|
+
// never imports the brain's runtime modules in-process). Reads (scan, catalog,
|
|
1692
|
+
// runtime list) are correlated request/response; long operations (pull, runtime
|
|
1693
|
+
// install, calibrate, sweep, bench) run as tracked JOBS the client polls via
|
|
1694
|
+
// brain.jobs.list. All gated by server_info.features.brainManage.
|
|
1695
|
+
// An installed local model, from `otto-brain scan`. Passthrough so the brain's
|
|
1696
|
+
// scan row can grow fields without a protocol bump.
|
|
1697
|
+
export const BrainInstalledModelSchema = z
|
|
1698
|
+
.object({
|
|
1699
|
+
model: z.string().default(""),
|
|
1700
|
+
arch: z.string().default(""),
|
|
1701
|
+
quant: z.string().default(""),
|
|
1702
|
+
size: z.string().default(""),
|
|
1703
|
+
ctx: z.string().default(""),
|
|
1704
|
+
vision: z.string().default(""),
|
|
1705
|
+
calibrated: z.string().default(""),
|
|
1706
|
+
features: z.string().default(""),
|
|
1707
|
+
source: z.string().default(""),
|
|
1708
|
+
})
|
|
1709
|
+
.passthrough();
|
|
1710
|
+
// A downloadable catalog model, annotated with whether it is already installed
|
|
1711
|
+
// (the daemon reuses the brain's authoritative catalog↔model join). Passthrough
|
|
1712
|
+
// over the catalog entry's optional metadata.
|
|
1713
|
+
export const BrainCatalogModelSchema = z
|
|
1714
|
+
.object({
|
|
1715
|
+
id: z.string(),
|
|
1716
|
+
name: z.string().default(""),
|
|
1717
|
+
installed: z.boolean().default(false),
|
|
1718
|
+
publisher: z.string().default(""),
|
|
1719
|
+
repo: z.string().default(""),
|
|
1720
|
+
quant: z.string().default(""),
|
|
1721
|
+
params: z.string().default(""),
|
|
1722
|
+
sizeBytes: z.number().nullable().optional(),
|
|
1723
|
+
size: z.string().default(""),
|
|
1724
|
+
vision: z.boolean().default(false),
|
|
1725
|
+
thinking: z.boolean().default(false),
|
|
1726
|
+
contextMax: z.number().nullable().optional(),
|
|
1727
|
+
tier: z.string().default(""),
|
|
1728
|
+
useCases: z.array(z.string()).default([]),
|
|
1729
|
+
why: z.string().default(""),
|
|
1730
|
+
})
|
|
1731
|
+
.passthrough();
|
|
1732
|
+
// An installed llama.cpp runtime, from `otto-brain runtime list`.
|
|
1733
|
+
export const BrainRuntimeSchema = z
|
|
1734
|
+
.object({
|
|
1735
|
+
label: z.string().default(""),
|
|
1736
|
+
version: z.string().default(""),
|
|
1737
|
+
source: z.string().default(""),
|
|
1738
|
+
dir: z.string().default(""),
|
|
1739
|
+
})
|
|
1740
|
+
.passthrough();
|
|
1741
|
+
// A tracked long-running brain operation. The client polls brain.jobs.list and
|
|
1742
|
+
// renders progress. `percent` is null when the job reports no measurable
|
|
1743
|
+
// progress (indeterminate). Terminal jobs linger briefly so the UI can show
|
|
1744
|
+
// the outcome before they are pruned.
|
|
1745
|
+
export const BrainJobKindSchema = z.enum([
|
|
1746
|
+
"pull",
|
|
1747
|
+
"runtime-install",
|
|
1748
|
+
"calibrate",
|
|
1749
|
+
"sweep",
|
|
1750
|
+
"bench",
|
|
1751
|
+
]);
|
|
1752
|
+
export const BrainJobStatusSchema = z.enum(["running", "succeeded", "failed", "canceled"]);
|
|
1753
|
+
export const BrainJobSchema = z
|
|
1754
|
+
.object({
|
|
1755
|
+
id: z.string(),
|
|
1756
|
+
kind: BrainJobKindSchema,
|
|
1757
|
+
// A short human label, e.g. "Download Phi-4 (14B)".
|
|
1758
|
+
label: z.string().default(""),
|
|
1759
|
+
// The subject id (catalog id, model name, or build tag) this job acts on.
|
|
1760
|
+
target: z.string().nullable().default(null),
|
|
1761
|
+
status: BrainJobStatusSchema.default("running"),
|
|
1762
|
+
percent: z.number().nullable().default(null),
|
|
1763
|
+
// The latest progress line (e.g. "extracting…", "budget 512: done").
|
|
1764
|
+
message: z.string().nullable().default(null),
|
|
1765
|
+
error: z.string().nullable().default(null),
|
|
1766
|
+
startedAt: z.string().default(""),
|
|
1767
|
+
finishedAt: z.string().nullable().default(null),
|
|
1768
|
+
})
|
|
1769
|
+
.passthrough();
|
|
1770
|
+
// Every job-starting RPC returns the created (or refused) job under this shape.
|
|
1771
|
+
const BrainJobResultSchema = z.object({
|
|
1772
|
+
job: BrainJobSchema.nullable(),
|
|
1773
|
+
error: z.string().nullable(),
|
|
1774
|
+
requestId: z.string(),
|
|
1775
|
+
});
|
|
1776
|
+
// Every job-listing RPC returns the active + recently-finished jobs.
|
|
1777
|
+
const BrainJobsResultSchema = z.object({
|
|
1778
|
+
jobs: z.array(BrainJobSchema).default([]),
|
|
1779
|
+
error: z.string().nullable(),
|
|
1780
|
+
requestId: z.string(),
|
|
1781
|
+
});
|
|
1782
|
+
// Installed models — `otto-brain scan`.
|
|
1783
|
+
export const BrainModelsScanRequestSchema = z.object({
|
|
1784
|
+
type: z.literal("brain.models.scan.request"),
|
|
1785
|
+
requestId: z.string(),
|
|
1786
|
+
});
|
|
1787
|
+
export const BrainModelsScanResponseSchema = z.object({
|
|
1788
|
+
type: z.literal("brain.models.scan.response"),
|
|
1789
|
+
payload: z.object({
|
|
1790
|
+
models: z.array(BrainInstalledModelSchema).default([]),
|
|
1791
|
+
error: z.string().nullable(),
|
|
1792
|
+
requestId: z.string(),
|
|
1793
|
+
}),
|
|
1794
|
+
});
|
|
1795
|
+
// Downloadable catalog — `otto-brain catalog`.
|
|
1796
|
+
export const BrainCatalogListRequestSchema = z.object({
|
|
1797
|
+
type: z.literal("brain.catalog.list.request"),
|
|
1798
|
+
requestId: z.string(),
|
|
1799
|
+
});
|
|
1800
|
+
export const BrainCatalogListResponseSchema = z.object({
|
|
1801
|
+
type: z.literal("brain.catalog.list.response"),
|
|
1802
|
+
payload: z.object({
|
|
1803
|
+
models: z.array(BrainCatalogModelSchema).default([]),
|
|
1804
|
+
error: z.string().nullable(),
|
|
1805
|
+
requestId: z.string(),
|
|
1806
|
+
}),
|
|
1807
|
+
});
|
|
1808
|
+
// Installed runtimes — `otto-brain runtime list`.
|
|
1809
|
+
export const BrainRuntimeListRequestSchema = z.object({
|
|
1810
|
+
type: z.literal("brain.runtime.list.request"),
|
|
1811
|
+
requestId: z.string(),
|
|
1812
|
+
});
|
|
1813
|
+
export const BrainRuntimeListResponseSchema = z.object({
|
|
1814
|
+
type: z.literal("brain.runtime.list.response"),
|
|
1815
|
+
payload: z.object({
|
|
1816
|
+
runtimes: z.array(BrainRuntimeSchema).default([]),
|
|
1817
|
+
error: z.string().nullable(),
|
|
1818
|
+
requestId: z.string(),
|
|
1819
|
+
}),
|
|
1820
|
+
});
|
|
1821
|
+
// Download a catalog model — starts a `pull` job.
|
|
1822
|
+
export const BrainModelsPullRequestSchema = z.object({
|
|
1823
|
+
type: z.literal("brain.models.pull.request"),
|
|
1824
|
+
// Catalog id or name fragment.
|
|
1825
|
+
model: z.string(),
|
|
1826
|
+
requestId: z.string(),
|
|
1827
|
+
});
|
|
1828
|
+
export const BrainModelsPullResponseSchema = z.object({
|
|
1829
|
+
type: z.literal("brain.models.pull.response"),
|
|
1830
|
+
payload: BrainJobResultSchema,
|
|
1831
|
+
});
|
|
1832
|
+
// Install a llama.cpp runtime — starts a `runtime-install` job.
|
|
1833
|
+
export const BrainRuntimeInstallRequestSchema = z.object({
|
|
1834
|
+
type: z.literal("brain.runtime.install.request"),
|
|
1835
|
+
// Optional llama.cpp release build tag; null = the brain's default.
|
|
1836
|
+
build: z.string().nullable().default(null),
|
|
1837
|
+
requestId: z.string(),
|
|
1838
|
+
});
|
|
1839
|
+
export const BrainRuntimeInstallResponseSchema = z.object({
|
|
1840
|
+
type: z.literal("brain.runtime.install.response"),
|
|
1841
|
+
payload: BrainJobResultSchema,
|
|
1842
|
+
});
|
|
1843
|
+
// Measure real KV bytes/token for a model — starts a `calibrate` job. Needs a
|
|
1844
|
+
// runtime + GPU; refused with a helpful error otherwise.
|
|
1845
|
+
export const BrainCalibrateRequestSchema = z.object({
|
|
1846
|
+
type: z.literal("brain.calibrate.request"),
|
|
1847
|
+
model: z.string(),
|
|
1848
|
+
requestId: z.string(),
|
|
1849
|
+
});
|
|
1850
|
+
export const BrainCalibrateResponseSchema = z.object({
|
|
1851
|
+
type: z.literal("brain.calibrate.response"),
|
|
1852
|
+
payload: BrainJobResultSchema,
|
|
1853
|
+
});
|
|
1854
|
+
// Find the best reasoning budget for a model — starts a `sweep` job.
|
|
1855
|
+
export const BrainSweepRequestSchema = z.object({
|
|
1856
|
+
type: z.literal("brain.sweep.request"),
|
|
1857
|
+
model: z.string(),
|
|
1858
|
+
requestId: z.string(),
|
|
1859
|
+
});
|
|
1860
|
+
export const BrainSweepResponseSchema = z.object({
|
|
1861
|
+
type: z.literal("brain.sweep.response"),
|
|
1862
|
+
payload: BrainJobResultSchema,
|
|
1863
|
+
});
|
|
1864
|
+
// Run the agentic-coding benchmark — starts a `bench` job. `model` is an
|
|
1865
|
+
// optional comma list of name fragments; null lets the brain pick.
|
|
1866
|
+
export const BrainBenchRequestSchema = z.object({
|
|
1867
|
+
type: z.literal("brain.bench.request"),
|
|
1868
|
+
model: z.string().nullable().default(null),
|
|
1869
|
+
requestId: z.string(),
|
|
1870
|
+
});
|
|
1871
|
+
export const BrainBenchResponseSchema = z.object({
|
|
1872
|
+
type: z.literal("brain.bench.response"),
|
|
1873
|
+
payload: BrainJobResultSchema,
|
|
1874
|
+
});
|
|
1875
|
+
// Poll the active + recently-finished jobs.
|
|
1876
|
+
export const BrainJobsListRequestSchema = z.object({
|
|
1877
|
+
type: z.literal("brain.jobs.list.request"),
|
|
1878
|
+
requestId: z.string(),
|
|
1879
|
+
});
|
|
1880
|
+
export const BrainJobsListResponseSchema = z.object({
|
|
1881
|
+
type: z.literal("brain.jobs.list.response"),
|
|
1882
|
+
payload: BrainJobsResultSchema,
|
|
1883
|
+
});
|
|
1884
|
+
// Cancel a running job; returns the refreshed job list.
|
|
1885
|
+
export const BrainJobsCancelRequestSchema = z.object({
|
|
1886
|
+
type: z.literal("brain.jobs.cancel.request"),
|
|
1887
|
+
jobId: z.string(),
|
|
1888
|
+
requestId: z.string(),
|
|
1889
|
+
});
|
|
1890
|
+
export const BrainJobsCancelResponseSchema = z.object({
|
|
1891
|
+
type: z.literal("brain.jobs.cancel.response"),
|
|
1892
|
+
payload: BrainJobsResultSchema,
|
|
1893
|
+
});
|
|
1894
|
+
// --- Hugging Face discovery (search + add arbitrary repos) ---------------
|
|
1895
|
+
// The daemon shells out to `otto-brain search`/`add --json`. Reads are
|
|
1896
|
+
// correlated request/response; the download runs as a `pull` job. Gated by
|
|
1897
|
+
// server_info.features.brainHfSearch. The brain resolves its own HF token (env
|
|
1898
|
+
// HF_TOKEN or its config), so no secret crosses this boundary.
|
|
1899
|
+
// One GGUF repo from a Hugging Face search. Passthrough so the brain's search
|
|
1900
|
+
// row can grow fields without a protocol bump.
|
|
1901
|
+
export const BrainHfSearchResultSchema = z
|
|
1902
|
+
.object({
|
|
1903
|
+
repo: z.string().default(""),
|
|
1904
|
+
downloads: z.number().default(0),
|
|
1905
|
+
likes: z.number().default(0),
|
|
1906
|
+
gated: z.boolean().default(false),
|
|
1907
|
+
// True when any quant of this repo is already on disk.
|
|
1908
|
+
installed: z.boolean().default(false),
|
|
1909
|
+
})
|
|
1910
|
+
.passthrough();
|
|
1911
|
+
// One downloadable quantization of a repo — `otto-brain add <repo> --list-quants`.
|
|
1912
|
+
export const BrainRepoQuantSchema = z
|
|
1913
|
+
.object({
|
|
1914
|
+
quant: z.string().default(""),
|
|
1915
|
+
size: z.string().default(""),
|
|
1916
|
+
sizeBytes: z.number().default(0),
|
|
1917
|
+
files: z.number().default(0),
|
|
1918
|
+
// True when this specific quant is already on disk.
|
|
1919
|
+
installed: z.boolean().default(false),
|
|
1920
|
+
})
|
|
1921
|
+
.passthrough();
|
|
1922
|
+
// Search Hugging Face for GGUF models — `otto-brain search <query>`.
|
|
1923
|
+
export const BrainHfSearchRequestSchema = z.object({
|
|
1924
|
+
type: z.literal("brain.hf.search.request"),
|
|
1925
|
+
query: z.string(),
|
|
1926
|
+
limit: z.number().nullable().default(null),
|
|
1927
|
+
requestId: z.string(),
|
|
1928
|
+
});
|
|
1929
|
+
export const BrainHfSearchResponseSchema = z.object({
|
|
1930
|
+
type: z.literal("brain.hf.search.response"),
|
|
1931
|
+
payload: z.object({
|
|
1932
|
+
results: z.array(BrainHfSearchResultSchema).default([]),
|
|
1933
|
+
error: z.string().nullable(),
|
|
1934
|
+
requestId: z.string(),
|
|
1935
|
+
}),
|
|
1936
|
+
});
|
|
1937
|
+
// List the quantizations a repo offers — `otto-brain add <repo> --list-quants`.
|
|
1938
|
+
export const BrainHfQuantsRequestSchema = z.object({
|
|
1939
|
+
type: z.literal("brain.hf.quants.request"),
|
|
1940
|
+
repo: z.string(),
|
|
1941
|
+
requestId: z.string(),
|
|
1942
|
+
});
|
|
1943
|
+
export const BrainHfQuantsResponseSchema = z.object({
|
|
1944
|
+
type: z.literal("brain.hf.quants.response"),
|
|
1945
|
+
payload: z.object({
|
|
1946
|
+
quants: z.array(BrainRepoQuantSchema).default([]),
|
|
1947
|
+
error: z.string().nullable(),
|
|
1948
|
+
requestId: z.string(),
|
|
1949
|
+
}),
|
|
1950
|
+
});
|
|
1951
|
+
// Download a chosen quant of an arbitrary HF repo — starts a `pull` job.
|
|
1952
|
+
export const BrainModelsAddRequestSchema = z.object({
|
|
1953
|
+
type: z.literal("brain.models.add.request"),
|
|
1954
|
+
repo: z.string(),
|
|
1955
|
+
quant: z.string(),
|
|
1956
|
+
requestId: z.string(),
|
|
1957
|
+
});
|
|
1958
|
+
export const BrainModelsAddResponseSchema = z.object({
|
|
1959
|
+
type: z.literal("brain.models.add.response"),
|
|
1960
|
+
payload: BrainJobResultSchema,
|
|
1961
|
+
});
|
|
1316
1962
|
export const ProjectRenameRequestSchema = z.object({
|
|
1317
1963
|
type: z.literal("project.rename.request"),
|
|
1318
1964
|
projectId: z.string(),
|
|
@@ -1656,6 +2302,33 @@ export const SetDaemonConfigRequestMessageSchema = z.object({
|
|
|
1656
2302
|
requestId: z.string(),
|
|
1657
2303
|
config: MutableDaemonConfigPatchSchema,
|
|
1658
2304
|
});
|
|
2305
|
+
// Connectors — MCP servers surfaced as named, toggle-able integrations. The
|
|
2306
|
+
// registry itself (add/remove/enable/disable a connector or an individual tool)
|
|
2307
|
+
// lives in daemon config and is edited via set_daemon_config's `connectors`
|
|
2308
|
+
// patch. The one thing config can't answer is what tools a connector actually
|
|
2309
|
+
// exposes, which needs a live connect + listTools — that is this RPC. Gated by
|
|
2310
|
+
// features.connectors.
|
|
2311
|
+
export const ConnectorsListToolsRequestSchema = z.object({
|
|
2312
|
+
type: z.literal("connectors.list_tools.request"),
|
|
2313
|
+
requestId: z.string(),
|
|
2314
|
+
connectorId: z.string(),
|
|
2315
|
+
});
|
|
2316
|
+
export const ConnectorsListToolsResponseSchema = z.object({
|
|
2317
|
+
type: z.literal("connectors.list_tools.response"),
|
|
2318
|
+
payload: z.object({
|
|
2319
|
+
connectorId: z.string(),
|
|
2320
|
+
tools: z
|
|
2321
|
+
.array(z.object({
|
|
2322
|
+
name: z.string(),
|
|
2323
|
+
description: z.string().nullable().default(null),
|
|
2324
|
+
disabled: z.boolean().default(false),
|
|
2325
|
+
}))
|
|
2326
|
+
.default([]),
|
|
2327
|
+
// Non-null when the connector could not be reached / enumerated.
|
|
2328
|
+
error: z.string().nullable(),
|
|
2329
|
+
requestId: z.string(),
|
|
2330
|
+
}),
|
|
2331
|
+
});
|
|
1659
2332
|
export const SpeechSettingsGetOptionsRequestSchema = z.object({
|
|
1660
2333
|
type: z.literal("speech.settings.get_options.request"),
|
|
1661
2334
|
requestId: z.string(),
|
|
@@ -1737,6 +2410,29 @@ export const AgentPersonalitiesGetStatsRequestSchema = z.object({
|
|
|
1737
2410
|
type: z.literal("agentPersonalities.get_stats.request"),
|
|
1738
2411
|
requestId: z.string(),
|
|
1739
2412
|
});
|
|
2413
|
+
// COMPAT(personalityProfile): added in v0.7.5; gate lives in
|
|
2414
|
+
// features.personalityProfile. Author a personality PROFILE (the prose
|
|
2415
|
+
// `personalityPrompt` that shapes how an agent behaves) from the only things
|
|
2416
|
+
// the editor knows before one exists: the handle, the roles it will be spawned
|
|
2417
|
+
// for, and its two spinner colors. Like the voice-cue RPC this is described
|
|
2418
|
+
// inline (not a stored id) so the editor can generate for an unsaved draft, and
|
|
2419
|
+
// is an editor-time action: the result lands in the prompt field for the user to
|
|
2420
|
+
// edit, and is stored on the personality by the ordinary save.
|
|
2421
|
+
export const AgentPersonalitiesGenerateProfileRequestSchema = z.object({
|
|
2422
|
+
type: z.literal("agentPersonalities.generate_profile.request"),
|
|
2423
|
+
requestId: z.string(),
|
|
2424
|
+
name: z.string(),
|
|
2425
|
+
// Permissive strings to match the stored personality shape (forward-compatible
|
|
2426
|
+
// with roles this daemon predates); the daemon filters to its known set.
|
|
2427
|
+
roles: z.array(z.string().min(1)).optional(),
|
|
2428
|
+
// The spinner glow pair, read as a palette (temperature, energy) and never
|
|
2429
|
+
// quoted literally in the profile.
|
|
2430
|
+
glowA: z.string().optional(),
|
|
2431
|
+
glowB: z.string().optional(),
|
|
2432
|
+
// Scopes provider resolution to a workspace; omitted falls back to any
|
|
2433
|
+
// resolvable one.
|
|
2434
|
+
cwd: z.string().optional(),
|
|
2435
|
+
});
|
|
1740
2436
|
export const ReadProjectConfigRequestMessageSchema = z.object({
|
|
1741
2437
|
type: z.literal("read_project_config_request"),
|
|
1742
2438
|
requestId: z.string(),
|
|
@@ -4285,6 +4981,28 @@ export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
4285
4981
|
HistoryAgentsClearArchivedRequestSchema,
|
|
4286
4982
|
AttachmentsImagesStatsRequestSchema,
|
|
4287
4983
|
AttachmentsImagesClearRequestSchema,
|
|
4984
|
+
BrainHostStatusRequestSchema,
|
|
4985
|
+
BrainHostStartRequestSchema,
|
|
4986
|
+
BrainHostStopRequestSchema,
|
|
4987
|
+
BrainHostRestartRequestSchema,
|
|
4988
|
+
BrainEvalsGetRequestSchema,
|
|
4989
|
+
BrainNetworkDiscoverRequestSchema,
|
|
4990
|
+
BrainModelsListRequestSchema,
|
|
4991
|
+
BrainRemoteConfigGetRequestSchema,
|
|
4992
|
+
BrainRemoteConfigPatchRequestSchema,
|
|
4993
|
+
BrainModelsScanRequestSchema,
|
|
4994
|
+
BrainCatalogListRequestSchema,
|
|
4995
|
+
BrainRuntimeListRequestSchema,
|
|
4996
|
+
BrainModelsPullRequestSchema,
|
|
4997
|
+
BrainRuntimeInstallRequestSchema,
|
|
4998
|
+
BrainCalibrateRequestSchema,
|
|
4999
|
+
BrainSweepRequestSchema,
|
|
5000
|
+
BrainBenchRequestSchema,
|
|
5001
|
+
BrainJobsListRequestSchema,
|
|
5002
|
+
BrainJobsCancelRequestSchema,
|
|
5003
|
+
BrainHfSearchRequestSchema,
|
|
5004
|
+
BrainHfQuantsRequestSchema,
|
|
5005
|
+
BrainModelsAddRequestSchema,
|
|
4288
5006
|
UpdateAgentRequestMessageSchema,
|
|
4289
5007
|
ProjectRenameRequestSchema,
|
|
4290
5008
|
ProjectRemoveRequestSchema,
|
|
@@ -4300,12 +5018,14 @@ export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
4300
5018
|
DiagnosticsRequestSchema,
|
|
4301
5019
|
GetDaemonConfigRequestMessageSchema,
|
|
4302
5020
|
SetDaemonConfigRequestMessageSchema,
|
|
5021
|
+
ConnectorsListToolsRequestSchema,
|
|
4303
5022
|
SpeechSettingsGetOptionsRequestSchema,
|
|
4304
5023
|
SpeechTtsPreviewRequestSchema,
|
|
4305
5024
|
SpeechTtsSpeakRequestSchema,
|
|
4306
5025
|
SpeechTtsSpeakCancelRequestSchema,
|
|
4307
5026
|
VisualizerVoiceCuesGenerateRequestSchema,
|
|
4308
5027
|
AgentPersonalitiesGetStatsRequestSchema,
|
|
5028
|
+
AgentPersonalitiesGenerateProfileRequestSchema,
|
|
4309
5029
|
ReadProjectConfigRequestMessageSchema,
|
|
4310
5030
|
WriteProjectConfigRequestMessageSchema,
|
|
4311
5031
|
DictationStreamStartMessageSchema,
|
|
@@ -4679,6 +5399,41 @@ export const ServerInfoStatusPayloadSchema = z
|
|
|
4679
5399
|
daemonDiagnostics: z.boolean().optional(),
|
|
4680
5400
|
// COMPAT(daemonSelfUpdate): added in v0.1.93, remove gate after 2026-12-13.
|
|
4681
5401
|
daemonSelfUpdate: z.boolean().optional(),
|
|
5402
|
+
// Daemon manages the local AI host (otto-brain) as a child: reports
|
|
5403
|
+
// brain.host.status, serves brain.host.start/stop/restart, exposes the
|
|
5404
|
+
// editable `brain` config block, and honors kill-on-shutdown. Without it
|
|
5405
|
+
// the Local brain host UI is hidden ("update the host").
|
|
5406
|
+
// COMPAT(brainControl): added in v0.7.5, remove gate after 2026-01-30 once daemon floor >= v0.7.5.
|
|
5407
|
+
brainControl: z.boolean().optional(),
|
|
5408
|
+
// Daemon streams the brain's live status/telemetry via
|
|
5409
|
+
// subscribe_brain_status + brain_status_changed, and serves brain.evals.get.
|
|
5410
|
+
// Separate from brainControl because status/eval watching can ship after
|
|
5411
|
+
// lifecycle control. Without it the Brain dashboard falls back to a
|
|
5412
|
+
// periodic brain.host.status poll (no live feed, no eval charts).
|
|
5413
|
+
// COMPAT(brainStatus): added in v0.7.5, remove gate after 2026-01-30 once daemon floor >= v0.7.5.
|
|
5414
|
+
brainStatus: z.boolean().optional(),
|
|
5415
|
+
// Daemon serves brain.network.discover: enumerates this host's bind
|
|
5416
|
+
// addresses and probes the local `tailscale` CLI, so the client can
|
|
5417
|
+
// offer a listen-host pick-list and auto-fill the tailscale TLS mode.
|
|
5418
|
+
// COMPAT(brainNetworkDiscovery): added in v0.7.5, remove gate after 2026-07-30 once daemon floor >= v0.7.5.
|
|
5419
|
+
brainNetworkDiscovery: z.boolean().optional(),
|
|
5420
|
+
// Daemon can point the brain at a remote host (brain.mode "remote"):
|
|
5421
|
+
// status/evals/config proxied from another Otto's brain, no local spawn.
|
|
5422
|
+
// COMPAT(brainRemote): added in v0.7.5, remove gate after 2026-07-30 once daemon floor >= v0.7.5.
|
|
5423
|
+
brainRemote: z.boolean().optional(),
|
|
5424
|
+
// Daemon manages the brain's models and runtimes by shelling out to the
|
|
5425
|
+
// otto-brain CLI: serves brain.models.scan / brain.catalog.list /
|
|
5426
|
+
// brain.runtime.list (reads) and starts brain.models.pull /
|
|
5427
|
+
// brain.runtime.install / brain.calibrate / brain.sweep / brain.bench as
|
|
5428
|
+
// tracked jobs polled via brain.jobs.list. Without it the Brain "Models"
|
|
5429
|
+
// and "Operations" sections are hidden ("update the host").
|
|
5430
|
+
// COMPAT(brainManage): added in v0.7.5, remove gate after 2026-07-30 once daemon floor >= v0.7.5.
|
|
5431
|
+
brainManage: z.boolean().optional(),
|
|
5432
|
+
// Daemon serves brain.hf.search / brain.hf.quants (reads) and starts
|
|
5433
|
+
// brain.models.add (download an arbitrary HF repo's quant) as a pull job.
|
|
5434
|
+
// Without it the Brain "Models" section hides the Hugging Face search box.
|
|
5435
|
+
// COMPAT(brainHfSearch): added in v0.7.5, remove gate after 2026-07-30 once daemon floor >= v0.7.5.
|
|
5436
|
+
brainHfSearch: z.boolean().optional(),
|
|
4682
5437
|
// COMPAT(agentForkContext): added in v0.1.102, remove gate after 2026-12-28.
|
|
4683
5438
|
agentForkContext: z.boolean().optional(),
|
|
4684
5439
|
// COMPAT(providerRemove): added in v0.1.105, drop the gate when daemon floor >= v0.1.105.
|
|
@@ -4779,6 +5534,10 @@ export const ServerInfoStatusPayloadSchema = z
|
|
|
4779
5534
|
ttsSpeak: z.boolean().optional(),
|
|
4780
5535
|
// COMPAT(visualizerVoiceCues): added in v0.6.3, drop the gate when daemon floor >= v0.6.3.
|
|
4781
5536
|
visualizerVoiceCues: z.boolean().optional(),
|
|
5537
|
+
// COMPAT(personalityProfile): added in v0.7.5, drop the gate when daemon floor >= v0.7.5.
|
|
5538
|
+
// Host can author a personality profile (the prompt prose) from a name,
|
|
5539
|
+
// roles, and spinner colors.
|
|
5540
|
+
personalityProfile: z.boolean().optional(),
|
|
4782
5541
|
// COMPAT(setAgentPersonality): added in v0.5.0, drop the gate when daemon floor >= v0.5.0.
|
|
4783
5542
|
setAgentPersonality: z.boolean().optional(),
|
|
4784
5543
|
// COMPAT(checkoutGitCommit): added in v0.5.1, drop the gate when daemon floor >= v0.5.1.
|
|
@@ -4872,11 +5631,23 @@ export const ServerInfoStatusPayloadSchema = z
|
|
|
4872
5631
|
// group regardless, so the client hides the categorized section instead
|
|
4873
5632
|
// of showing category switches that do nothing.
|
|
4874
5633
|
mcpToolGroups: z.boolean().optional(),
|
|
5634
|
+
// COMPAT(connectors): added in v0.7.5, drop the gate when daemon floor >= v0.7.5.
|
|
5635
|
+
// Set when the daemon persists and honors `connectors` — MCP servers
|
|
5636
|
+
// surfaced as named, toggle-able integrations with per-tool disable,
|
|
5637
|
+
// enforced today on the openai-compat path. Old daemons ignore the
|
|
5638
|
+
// section, so the client hides the Connectors settings entirely.
|
|
5639
|
+
connectors: z.boolean().optional(),
|
|
4875
5640
|
// COMPAT(agentBehaviorToggles): added in v0.6.4, drop the gate when daemon floor >= v0.6.4.
|
|
4876
5641
|
// Set when the daemon persists `agentBehaviors.*` (promptSuggestions,
|
|
4877
5642
|
// agentProgressSummaries, notifyOnFinishDefault). The reads are wired by
|
|
4878
5643
|
// Claude-tier providers (WP-E); the client gates the toggle cards on this.
|
|
4879
5644
|
agentBehaviorToggles: z.boolean().optional(),
|
|
5645
|
+
// COMPAT(todoReminders): added in v0.7.5, drop the gate when daemon floor >= v0.7.5.
|
|
5646
|
+
// Set when the daemon acts on `agentBehaviors.{todoNudge,todoReconcileOnIdle}` —
|
|
5647
|
+
// the provider-agnostic stale-todo nudge (next turn) and idle reconcile pass.
|
|
5648
|
+
// The client gates the task-list toggle cards on this so an old daemon never
|
|
5649
|
+
// shows switches that do nothing.
|
|
5650
|
+
todoReminders: z.boolean().optional(),
|
|
4880
5651
|
// COMPAT(metadataGenerationEnabled): added in v0.6.4, drop the gate when daemon floor >= v0.6.4.
|
|
4881
5652
|
// Set when the daemon persists `metadataGeneration.{enabled,preferWriterPersonalities}`.
|
|
4882
5653
|
// The generation path (WP-B) reads them; the client gates the toggle cards on this.
|
|
@@ -5953,6 +6724,19 @@ export const AgentPersonalitiesGetStatsResponseSchema = z.object({
|
|
|
5953
6724
|
})
|
|
5954
6725
|
.passthrough(),
|
|
5955
6726
|
});
|
|
6727
|
+
export const AgentPersonalitiesGenerateProfileResponseSchema = z.object({
|
|
6728
|
+
type: z.literal("agentPersonalities.generate_profile.response"),
|
|
6729
|
+
payload: z
|
|
6730
|
+
.object({
|
|
6731
|
+
requestId: z.string(),
|
|
6732
|
+
// The authored personality prompt, ready to drop into the editor's prompt
|
|
6733
|
+
// field. Absent when generation failed (see error) or no writer/provider
|
|
6734
|
+
// resolves on this host.
|
|
6735
|
+
profile: z.string().optional(),
|
|
6736
|
+
error: z.string().optional(),
|
|
6737
|
+
})
|
|
6738
|
+
.passthrough(),
|
|
6739
|
+
});
|
|
5956
6740
|
export const DaemonGetStatusResponseSchema = z.object({
|
|
5957
6741
|
type: z.literal("daemon.get_status.response"),
|
|
5958
6742
|
payload: z
|
|
@@ -8029,12 +8813,14 @@ export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
8029
8813
|
DiagnosticsResponseSchema,
|
|
8030
8814
|
GetDaemonConfigResponseMessageSchema,
|
|
8031
8815
|
SetDaemonConfigResponseMessageSchema,
|
|
8816
|
+
ConnectorsListToolsResponseSchema,
|
|
8032
8817
|
SpeechSettingsGetOptionsResponseSchema,
|
|
8033
8818
|
SpeechTtsPreviewResponseSchema,
|
|
8034
8819
|
SpeechTtsSpeakResponseSchema,
|
|
8035
8820
|
SpeechTtsSpeakCancelResponseSchema,
|
|
8036
8821
|
VisualizerVoiceCuesGenerateResponseSchema,
|
|
8037
8822
|
AgentPersonalitiesGetStatsResponseSchema,
|
|
8823
|
+
AgentPersonalitiesGenerateProfileResponseSchema,
|
|
8038
8824
|
ReadProjectConfigResponseMessageSchema,
|
|
8039
8825
|
WriteProjectConfigResponseMessageSchema,
|
|
8040
8826
|
SetAgentModeResponseMessageSchema,
|
|
@@ -8072,6 +8858,28 @@ export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
8072
8858
|
HistoryAgentsClearArchivedResponseSchema,
|
|
8073
8859
|
AttachmentsImagesStatsResponseSchema,
|
|
8074
8860
|
AttachmentsImagesClearResponseSchema,
|
|
8861
|
+
BrainHostStatusResponseSchema,
|
|
8862
|
+
BrainHostStartResponseSchema,
|
|
8863
|
+
BrainHostStopResponseSchema,
|
|
8864
|
+
BrainHostRestartResponseSchema,
|
|
8865
|
+
BrainEvalsGetResponseSchema,
|
|
8866
|
+
BrainNetworkDiscoverResponseSchema,
|
|
8867
|
+
BrainModelsListResponseSchema,
|
|
8868
|
+
BrainRemoteConfigGetResponseSchema,
|
|
8869
|
+
BrainRemoteConfigPatchResponseSchema,
|
|
8870
|
+
BrainModelsScanResponseSchema,
|
|
8871
|
+
BrainCatalogListResponseSchema,
|
|
8872
|
+
BrainRuntimeListResponseSchema,
|
|
8873
|
+
BrainModelsPullResponseSchema,
|
|
8874
|
+
BrainRuntimeInstallResponseSchema,
|
|
8875
|
+
BrainCalibrateResponseSchema,
|
|
8876
|
+
BrainSweepResponseSchema,
|
|
8877
|
+
BrainBenchResponseSchema,
|
|
8878
|
+
BrainJobsListResponseSchema,
|
|
8879
|
+
BrainJobsCancelResponseSchema,
|
|
8880
|
+
BrainHfSearchResponseSchema,
|
|
8881
|
+
BrainHfQuantsResponseSchema,
|
|
8882
|
+
BrainModelsAddResponseSchema,
|
|
8075
8883
|
AgentArchivedMessageSchema,
|
|
8076
8884
|
CloseItemsResponseSchema,
|
|
8077
8885
|
CheckoutStatusResponseSchema,
|