@otto-code/protocol 0.7.2 → 0.7.4

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
@@ -2143,6 +2143,27 @@ export const AgentDetachResponseMessageSchema = z.object({
2143
2143
  type: z.literal("agent.detach.response"),
2144
2144
  payload: AgentActionResponsePayloadSchema,
2145
2145
  });
2146
+ // Move a chat into another workspace, in the same project or a different one.
2147
+ //
2148
+ // Ownership is one field (see the agent snapshot's `workspaceId`), independent of
2149
+ // cwd, so re-stamping it is all a move takes: nothing on disk is keyed by
2150
+ // workspace, and clients derive which workspace shows a chat from that field
2151
+ // alone.
2152
+ //
2153
+ // The chat's `cwd` does not change, and does not have to match the target
2154
+ // workspace's directory. The daemon has never required those to agree (an
2155
+ // agent's cwd can already be a subdirectory of its workspace, and nothing
2156
+ // validates one against the other), and a session already rooted on disk cannot
2157
+ // honestly be re-rooted. So a moved chat keeps running where it was started.
2158
+ //
2159
+ // Gated by server_info.features.agentWorkspaceTransfer.
2160
+ export const AgentWorkspaceTransferRequestMessageSchema = z.object({
2161
+ type: z.literal("agent.workspace.transfer.request"),
2162
+ agentId: z.string(),
2163
+ // The workspace that should own the chat from now on.
2164
+ workspaceId: z.string(),
2165
+ requestId: z.string(),
2166
+ });
2146
2167
  // Stop a running observed subagent (Claude Task / ultracode fan-out). The
2147
2168
  // agentId is the observed subagent's id; the daemon resolves it to the owning
2148
2169
  // provider session's task and calls stopTask. Only observed subagents accept
@@ -2767,6 +2788,20 @@ export const WorkspaceTitleSetResponseSchema = z.object({
2767
2788
  type: z.literal("workspace.title.set.response"),
2768
2789
  payload: WorkspaceTitleSetResponsePayloadSchema,
2769
2790
  });
2791
+ export const AgentWorkspaceTransferResponsePayloadSchema = z.object({
2792
+ requestId: z.string(),
2793
+ agentId: z.string(),
2794
+ // Which workspace owns the chat now: the requested one when accepted, the one
2795
+ // it never left when refused. Lets a client correct its optimistic state from
2796
+ // the response alone.
2797
+ workspaceId: z.string().nullable(),
2798
+ accepted: z.boolean(),
2799
+ error: z.string().nullable(),
2800
+ });
2801
+ export const AgentWorkspaceTransferResponseMessageSchema = z.object({
2802
+ type: z.literal("agent.workspace.transfer.response"),
2803
+ payload: AgentWorkspaceTransferResponsePayloadSchema,
2804
+ });
2770
2805
  export const SetVoiceModeResponseMessageSchema = z.object({
2771
2806
  type: z.literal("set_voice_mode_response"),
2772
2807
  payload: z.object({
@@ -3567,6 +3602,11 @@ export const WorkspaceArchivePreflightRequestSchema = z.object({
3567
3602
  requestId: z.string(),
3568
3603
  workspaceId: z.string(),
3569
3604
  });
3605
+ // Where the Changes view's base branch came from. Surfaced so the chip can say *why* it is
3606
+ // comparing against this branch: an inferred parent is a heuristic over a graph that does not
3607
+ // record the answer, and it has to look like one or a wrong guess reads as a bug in the diff.
3608
+ // COMPAT(checkoutDiffBaseAnyRepo): added in v0.7.4.
3609
+ export const CheckoutBaseSourceSchema = z.enum(["user", "inferred", "worktree", "default"]);
3570
3610
  // Repoint a worktree-backed workspace's base branch — what the Changes view diffs
3571
3611
  // against, and what merge-into-base and PR creation target. On a stacked branch the
3572
3612
  // useful base is the parent branch, not the repo default, the same way a forge PR
@@ -3576,8 +3616,14 @@ export const WorktreeBaseRefSetRequestSchema = z.object({
3576
3616
  type: z.literal("worktree.baseRef.set.request"),
3577
3617
  requestId: z.string(),
3578
3618
  workspaceId: z.string(),
3579
- // Branch name, with or without an `origin/` prefix; null resets to the default branch.
3619
+ // Branch name; null resets to the default branch. An `origin/` prefix is meaningful and is
3620
+ // kept — `main` and `origin/main` are different comparisons whenever the two have drifted.
3580
3621
  baseRef: z.string().nullable(),
3622
+ // Forget the remembered base and detect the branch's parent again, ignoring `baseRef`.
3623
+ // The escape hatch for a wrong guess: parent detection is a heuristic over a graph that does
3624
+ // not record the answer, and the result is sticky, so it has to be re-runnable on demand.
3625
+ // COMPAT(checkoutDiffBaseAnyRepo): added in v0.7.4.
3626
+ redetect: z.boolean().optional(),
3581
3627
  });
3582
3628
  // Create a new workspace record. Unlike open_project, this never deduplicates by
3583
3629
  // directory: it always produces a fresh workspace. The source discriminates
@@ -3602,7 +3648,10 @@ export const WorkspaceCreateRequestSchema = z.object({
3602
3648
  cwd: z.string().optional(),
3603
3649
  projectId: z.string().optional(),
3604
3650
  action: z.enum(["branch-off", "checkout"]).optional(),
3605
- // Target branch name for checkout, or new branch name for branch-off.
3651
+ // Branch to check out for "checkout". For "branch-off" this is the BASE to
3652
+ // cut from, not the branch being created -- the new branch name comes from
3653
+ // worktreeSlug (see resolveWorktreeCreationIntent). Omit it to branch off
3654
+ // the repository default.
3606
3655
  refName: z.string().min(1).optional(),
3607
3656
  baseBranch: z.string().optional(),
3608
3657
  githubPrNumber: z.number().int().positive().optional(),
@@ -3979,12 +4028,18 @@ export const CodeRenameUndoRequestSchema = z.object({
3979
4028
  * config RPCs because none of it is configuration: which servers this machine can
3980
4029
  * actually supply, and which are running right now.
3981
4030
  *
3982
- * `cwd` scopes the availability check a server can be present in one workspace's
3983
- * `node_modules` and absent in another's.
4031
+ * Omit `cwd` for the host-wide answer, which is what the settings screen asks for: every
4032
+ * row this daemon knows, resolved against the rungs a host has (bundled, PATH). Passing a
4033
+ * `cwd` additionally probes that workspace's `node_modules/.bin`, since a server can be
4034
+ * present in one project and absent from another. Optional rather than removed because
4035
+ * older clients still send it.
4036
+ *
4037
+ * COMPAT(lspHostServers): `cwd` became optional in v0.7.3; gate lives in
4038
+ * features.lspHostServers.
3984
4039
  */
3985
4040
  export const LspServersListRequestSchema = z.object({
3986
4041
  type: z.literal("lsp.servers.list.request"),
3987
- cwd: z.string(),
4042
+ cwd: z.string().optional(),
3988
4043
  requestId: z.string(),
3989
4044
  });
3990
4045
  /** Stop one running server, so a user who suspects it of hogging memory can kill it. */
@@ -4292,6 +4347,7 @@ export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
4292
4347
  SetAgentThinkingRequestMessageSchema,
4293
4348
  SetAgentFeatureRequestMessageSchema,
4294
4349
  AgentDetachRequestMessageSchema,
4350
+ AgentWorkspaceTransferRequestMessageSchema,
4295
4351
  AgentSubagentStopRequestMessageSchema,
4296
4352
  AgentBackgroundTaskStopRequestMessageSchema,
4297
4353
  AgentBackgroundTaskClearRequestMessageSchema,
@@ -4692,6 +4748,13 @@ export const ServerInfoStatusPayloadSchema = z
4692
4748
  // the outline/fuzzy-finder source and the no-server fallback.
4693
4749
  // COMPAT(lsp): added in v0.6.8, drop the gate when daemon floor >= v0.6.8.
4694
4750
  lsp: z.boolean().optional(),
4751
+ // The daemon answers `lsp.servers.list` host-wide, with no `cwd`. The settings
4752
+ // screen is a host screen: it lists every language server this machine knows how
4753
+ // to run and whether it can supply the binary, and it must not need a workspace
4754
+ // open to say so. An older daemon rejects a request with no `cwd`, so without the
4755
+ // flag the client says to update the host rather than showing an empty screen.
4756
+ // COMPAT(lspHostServers): added in v0.7.3, drop the gate when daemon floor >= v0.7.3.
4757
+ lspHostServers: z.boolean().optional(),
4695
4758
  // The Solution view — the daemon can discover solutions and serve
4696
4759
  // `code.solution.*`. Deliberately NOT implied by `lsp`: there is no
4697
4760
  // project-structure request in LSP, so this subsystem is independent of
@@ -4747,6 +4810,13 @@ export const ServerInfoStatusPayloadSchema = z
4747
4810
  // the daemon can write the worktree's metadata.
4748
4811
  // COMPAT(worktreeDiffBase): added in v0.6.8, drop the gate when daemon floor >= v0.6.8.
4749
4812
  worktreeDiffBase: z.boolean().optional(),
4813
+ // Set when the daemon stores the diff base *per branch*, which is what lets any git
4814
+ // checkout repoint it rather than only an Otto worktree — a plain checkout's gitdir is
4815
+ // shared by every branch in it, so a single stored base would bleed across branch
4816
+ // switches. Also gates parent-branch detection, the `origin/`-qualified pin, and the
4817
+ // re-detect action. Without it the client keeps the worktree-only picker.
4818
+ // COMPAT(checkoutDiffBaseAnyRepo): added in v0.7.4, drop the gate when daemon floor >= v0.7.4.
4819
+ checkoutDiffBaseAnyRepo: z.boolean().optional(),
4750
4820
  // Set when the daemon persists the host-level hideMergeIntoBaseAction
4751
4821
  // workspace policy (read/written via the daemon config RPCs). Without
4752
4822
  // it the client hides the Workspaces toggle, since patching the field
@@ -4852,6 +4922,12 @@ export const ServerInfoStatusPayloadSchema = z
4852
4922
  // the daemon half of the Storage section; the app-side preview cache row
4853
4923
  // is local and always shown.
4854
4924
  attachmentStorage: z.boolean().optional(),
4925
+ // COMPAT(agentWorkspaceTransfer): added in v0.7.4, drop the gate when
4926
+ // daemon floor >= v0.7.4. Set when the daemon serves
4927
+ // `agent.workspace.transfer` — moving a chat to another workspace over
4928
+ // the same directory. The client cannot restamp ownership itself (it is
4929
+ // daemon state), so an old daemon simply does not get the menu item.
4930
+ agentWorkspaceTransfer: z.boolean().optional(),
4855
4931
  })
4856
4932
  .optional(),
4857
4933
  })
@@ -5556,6 +5632,9 @@ export const WorktreeBaseRefSetResponseSchema = z.object({
5556
5632
  baseRef: z.string().nullable(),
5557
5633
  // The stored base is the repository default branch (no stacked-branch override).
5558
5634
  isDefault: z.boolean(),
5635
+ // Where the resulting base came from, so the client can label it without a refetch.
5636
+ // COMPAT(checkoutDiffBaseAnyRepo): added in v0.7.4.
5637
+ baseSource: CheckoutBaseSourceSchema.optional(),
5559
5638
  error: z.string().nullable(),
5560
5639
  }),
5561
5640
  });
@@ -6032,6 +6111,15 @@ const CheckoutStatusCommonSchema = z.object({
6032
6111
  // COMPAT(checkoutStatusGitStateAt): added in v0.6.8; absent from older daemons.
6033
6112
  // Drop the optional marker when floor >= v0.6.8 (target 2027-01-24).
6034
6113
  gitStateAt: z.number().optional(),
6114
+ // Where `baseRef` came from, so the base chip can label an inferred parent as a guess rather
6115
+ // than presenting it with the same authority as an explicit pick.
6116
+ // COMPAT(checkoutDiffBaseAnyRepo): added in v0.7.4.
6117
+ baseSource: CheckoutBaseSourceSchema.optional(),
6118
+ // Whether this checkout can have its base repointed. True for any git checkout on a daemon
6119
+ // that stores the base per branch; older daemons only supported Otto worktrees, which the
6120
+ // client inferred from isOttoOwnedWorktree.
6121
+ // COMPAT(checkoutDiffBaseAnyRepo): added in v0.7.4.
6122
+ isBaseEditable: z.boolean().optional(),
6035
6123
  });
6036
6124
  const CheckoutStatusNotGitSchema = CheckoutStatusCommonSchema.extend({
6037
6125
  isGit: z.literal(false),
@@ -7316,6 +7404,14 @@ export const LspLanguageStateSchema = z.object({
7316
7404
  /** Which discovery rung supplied it (`workspaceBin` / `bundled` / `path`), or null. */
7317
7405
  rung: z.string().nullable(),
7318
7406
  bin: z.string(),
7407
+ /**
7408
+ * Every rung this row can ever be supplied from, in resolution order. A row whose only
7409
+ * rung is `workspaceBin` is supplied by the project it runs in and by nothing else, so
7410
+ * `installed: false` from a host-wide check means "the project brings it", not "missing".
7411
+ */
7412
+ discovery: z.array(z.string()).optional(),
7413
+ /** Absolute path to the resolved executable, so the toolchain behind a row is nameable. */
7414
+ path: z.string().nullable().optional(),
7319
7415
  extensions: z.array(z.string()),
7320
7416
  /** Plain-words index cost, so the toggle states its own price. */
7321
7417
  indexCost: z.string(),
@@ -7946,6 +8042,7 @@ export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
7946
8042
  SetAgentThinkingResponseMessageSchema,
7947
8043
  SetAgentFeatureResponseMessageSchema,
7948
8044
  AgentDetachResponseMessageSchema,
8045
+ AgentWorkspaceTransferResponseMessageSchema,
7949
8046
  AgentQueueRemoveResponseMessageSchema,
7950
8047
  AgentQueueReorderResponseMessageSchema,
7951
8048
  AgentQueueClearResponseMessageSchema,
@@ -2599,6 +2599,12 @@ export declare const WSOutboundMessageSchema: {
2599
2599
  workspaceId: import("zod").ZodString;
2600
2600
  baseRef: import("zod").ZodNullable<import("zod").ZodString>;
2601
2601
  isDefault: import("zod").ZodBoolean;
2602
+ baseSource: import("zod").ZodOptional<import("zod").ZodEnum<{
2603
+ default: "default";
2604
+ worktree: "worktree";
2605
+ user: "user";
2606
+ inferred: "inferred";
2607
+ }>>;
2602
2608
  error: import("zod").ZodNullable<import("zod").ZodString>;
2603
2609
  }, import("zod/v4/core").$strip>;
2604
2610
  }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
@@ -4643,6 +4649,15 @@ export declare const WSOutboundMessageSchema: {
4643
4649
  error: import("zod").ZodNullable<import("zod").ZodString>;
4644
4650
  notice: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodType<import("../agent-types.js").AgentProviderNotice, unknown, import("zod/v4/core").$ZodTypeInternals<import("../agent-types.js").AgentProviderNotice, unknown>>>>;
4645
4651
  }, import("zod/v4/core").$strip>;
4652
+ }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
4653
+ type: import("zod").ZodLiteral<"agent.workspace.transfer.response">;
4654
+ payload: import("zod").ZodObject<{
4655
+ requestId: import("zod").ZodString;
4656
+ agentId: import("zod").ZodString;
4657
+ workspaceId: import("zod").ZodNullable<import("zod").ZodString>;
4658
+ accepted: import("zod").ZodBoolean;
4659
+ error: import("zod").ZodNullable<import("zod").ZodString>;
4660
+ }, import("zod/v4/core").$strip>;
4646
4661
  }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
4647
4662
  type: import("zod").ZodLiteral<"agent.queue.remove.response">;
4648
4663
  payload: import("zod").ZodObject<{
@@ -5199,6 +5214,13 @@ export declare const WSOutboundMessageSchema: {
5199
5214
  }, import("zod/v4/core").$strip>>;
5200
5215
  requestId: import("zod").ZodString;
5201
5216
  gitStateAt: import("zod").ZodOptional<import("zod").ZodNumber>;
5217
+ baseSource: import("zod").ZodOptional<import("zod").ZodEnum<{
5218
+ default: "default";
5219
+ worktree: "worktree";
5220
+ user: "user";
5221
+ inferred: "inferred";
5222
+ }>>;
5223
+ isBaseEditable: import("zod").ZodOptional<import("zod").ZodBoolean>;
5202
5224
  isGit: import("zod").ZodLiteral<false>;
5203
5225
  isOttoOwnedWorktree: import("zod").ZodLiteral<false>;
5204
5226
  repoRoot: import("zod").ZodNull;
@@ -5223,6 +5245,13 @@ export declare const WSOutboundMessageSchema: {
5223
5245
  }, import("zod/v4/core").$strip>>;
5224
5246
  requestId: import("zod").ZodString;
5225
5247
  gitStateAt: import("zod").ZodOptional<import("zod").ZodNumber>;
5248
+ baseSource: import("zod").ZodOptional<import("zod").ZodEnum<{
5249
+ default: "default";
5250
+ worktree: "worktree";
5251
+ user: "user";
5252
+ inferred: "inferred";
5253
+ }>>;
5254
+ isBaseEditable: import("zod").ZodOptional<import("zod").ZodBoolean>;
5226
5255
  isGit: import("zod").ZodLiteral<true>;
5227
5256
  isOttoOwnedWorktree: import("zod").ZodLiteral<false>;
5228
5257
  repoRoot: import("zod").ZodString;
@@ -5251,6 +5280,13 @@ export declare const WSOutboundMessageSchema: {
5251
5280
  }, import("zod/v4/core").$strip>>;
5252
5281
  requestId: import("zod").ZodString;
5253
5282
  gitStateAt: import("zod").ZodOptional<import("zod").ZodNumber>;
5283
+ baseSource: import("zod").ZodOptional<import("zod").ZodEnum<{
5284
+ default: "default";
5285
+ worktree: "worktree";
5286
+ user: "user";
5287
+ inferred: "inferred";
5288
+ }>>;
5289
+ isBaseEditable: import("zod").ZodOptional<import("zod").ZodBoolean>;
5254
5290
  isGit: import("zod").ZodLiteral<true>;
5255
5291
  isOttoOwnedWorktree: import("zod").ZodLiteral<true>;
5256
5292
  repoRoot: import("zod").ZodString;
@@ -5282,6 +5318,13 @@ export declare const WSOutboundMessageSchema: {
5282
5318
  }, import("zod/v4/core").$strip>>;
5283
5319
  requestId: import("zod").ZodString;
5284
5320
  gitStateAt: import("zod").ZodOptional<import("zod").ZodNumber>;
5321
+ baseSource: import("zod").ZodOptional<import("zod").ZodEnum<{
5322
+ default: "default";
5323
+ worktree: "worktree";
5324
+ user: "user";
5325
+ inferred: "inferred";
5326
+ }>>;
5327
+ isBaseEditable: import("zod").ZodOptional<import("zod").ZodBoolean>;
5285
5328
  isGit: import("zod").ZodLiteral<false>;
5286
5329
  isOttoOwnedWorktree: import("zod").ZodLiteral<false>;
5287
5330
  repoRoot: import("zod").ZodNull;
@@ -5306,6 +5349,13 @@ export declare const WSOutboundMessageSchema: {
5306
5349
  }, import("zod/v4/core").$strip>>;
5307
5350
  requestId: import("zod").ZodString;
5308
5351
  gitStateAt: import("zod").ZodOptional<import("zod").ZodNumber>;
5352
+ baseSource: import("zod").ZodOptional<import("zod").ZodEnum<{
5353
+ default: "default";
5354
+ worktree: "worktree";
5355
+ user: "user";
5356
+ inferred: "inferred";
5357
+ }>>;
5358
+ isBaseEditable: import("zod").ZodOptional<import("zod").ZodBoolean>;
5309
5359
  isGit: import("zod").ZodLiteral<true>;
5310
5360
  isOttoOwnedWorktree: import("zod").ZodLiteral<false>;
5311
5361
  repoRoot: import("zod").ZodString;
@@ -5334,6 +5384,13 @@ export declare const WSOutboundMessageSchema: {
5334
5384
  }, import("zod/v4/core").$strip>>;
5335
5385
  requestId: import("zod").ZodString;
5336
5386
  gitStateAt: import("zod").ZodOptional<import("zod").ZodNumber>;
5387
+ baseSource: import("zod").ZodOptional<import("zod").ZodEnum<{
5388
+ default: "default";
5389
+ worktree: "worktree";
5390
+ user: "user";
5391
+ inferred: "inferred";
5392
+ }>>;
5393
+ isBaseEditable: import("zod").ZodOptional<import("zod").ZodBoolean>;
5337
5394
  isGit: import("zod").ZodLiteral<true>;
5338
5395
  isOttoOwnedWorktree: import("zod").ZodLiteral<true>;
5339
5396
  repoRoot: import("zod").ZodString;
@@ -7855,6 +7912,8 @@ export declare const WSOutboundMessageSchema: {
7855
7912
  running: import("zod").ZodBoolean;
7856
7913
  rung: import("zod").ZodNullable<import("zod").ZodString>;
7857
7914
  bin: import("zod").ZodString;
7915
+ discovery: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodString>>;
7916
+ path: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
7858
7917
  extensions: import("zod").ZodArray<import("zod").ZodString>;
7859
7918
  indexCost: import("zod").ZodString;
7860
7919
  }, import("zod/v4/core").$strip>>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@otto-code/protocol",
3
- "version": "0.7.2",
3
+ "version": "0.7.4",
4
4
  "description": "Otto shared protocol schemas and wire types",
5
5
  "license": "AGPL-3.0-or-later",
6
6
  "files": [