@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/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,