@getpaseo/protocol 0.1.110 → 0.2.0-beta.2

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
@@ -78,6 +78,7 @@ export const MutableDaemonConfigPatchSchema = z
78
78
  providers: z
79
79
  .record(z.string(), MutableDaemonProviderConfigSchema.partial().passthrough())
80
80
  .optional(),
81
+ removeProviders: z.array(z.string().min(1)).optional(),
81
82
  metadataGeneration: MutableMetadataGenerationConfigSchema.partial().optional(),
82
83
  autoArchiveAfterMerge: z.boolean().optional(),
83
84
  enableTerminalAgentHooks: z.boolean().optional(),
@@ -150,6 +151,7 @@ export const ProviderSnapshotEntrySchema = z.object({
150
151
  provider: AgentProviderSchema,
151
152
  status: ProviderStatusSchema,
152
153
  enabled: z.boolean().optional().default(true),
154
+ source: z.enum(["builtin", "custom"]).optional(),
153
155
  error: z.string().optional(),
154
156
  models: z.array(AgentModelDefinitionSchema).optional(),
155
157
  modes: z.array(AgentModeSchema).optional(),
@@ -423,6 +425,7 @@ export const AgentTimelineItemPayloadSchema = z.union([
423
425
  type: z.literal("user_message"),
424
426
  text: z.string(),
425
427
  messageId: z.string().optional(),
428
+ clientMessageId: z.string().optional(),
426
429
  }),
427
430
  z.object({
428
431
  type: z.literal("assistant_message"),
@@ -661,6 +664,16 @@ export const WorkspacePinSetRequestSchema = z.object({
661
664
  pinned: z.boolean(),
662
665
  requestId: z.string(),
663
666
  });
667
+ export const WorkspaceRecoveryInspectRequestSchema = z.object({
668
+ type: z.literal("workspace.recovery.inspect.request"),
669
+ workspaceId: z.string(),
670
+ requestId: z.string(),
671
+ });
672
+ export const WorkspaceRecoveryRestoreRequestSchema = z.object({
673
+ type: z.literal("workspace.recovery.restore.request"),
674
+ workspaceId: z.string(),
675
+ requestId: z.string(),
676
+ });
664
677
  export const SetVoiceModeMessageSchema = z.object({
665
678
  type: z.literal("set_voice_mode"),
666
679
  enabled: z.boolean(),
@@ -677,6 +690,18 @@ export const GitHubPrAttachmentSchema = z.object({
677
690
  baseRefName: z.string().nullable().optional(),
678
691
  headRefName: z.string().nullable().optional(),
679
692
  });
693
+ export const ForgeChangeRequestAttachmentSchema = z.object({
694
+ type: z.literal("forge_change_request"),
695
+ mimeType: z.literal("application/paseo-forge-change-request"),
696
+ forge: z.string().optional().default("github"),
697
+ number: z.number().int().positive(),
698
+ title: z.string(),
699
+ url: z.string(),
700
+ body: z.string().nullable().optional(),
701
+ projectPath: z.string().optional(),
702
+ baseRefName: z.string().nullable().optional(),
703
+ headRefName: z.string().nullable().optional(),
704
+ });
680
705
  export const GitHubIssueAttachmentSchema = z.object({
681
706
  type: z.literal("github_issue"),
682
707
  mimeType: z.literal("application/github-issue"),
@@ -685,6 +710,16 @@ export const GitHubIssueAttachmentSchema = z.object({
685
710
  url: z.string(),
686
711
  body: z.string().nullable().optional(),
687
712
  });
713
+ export const ForgeIssueAttachmentSchema = z.object({
714
+ type: z.literal("forge_issue"),
715
+ mimeType: z.literal("application/paseo-forge-issue"),
716
+ forge: z.string().optional().default("github"),
717
+ number: z.number().int().positive(),
718
+ title: z.string(),
719
+ url: z.string(),
720
+ body: z.string().nullable().optional(),
721
+ projectPath: z.string().optional(),
722
+ });
688
723
  export const TextAttachmentSchema = z
689
724
  .object({
690
725
  type: z.literal("text"),
@@ -731,6 +766,8 @@ export const UploadedFileAttachmentSchema = z.object({
731
766
  path: z.string(),
732
767
  });
733
768
  export const AgentAttachmentSchema = z.discriminatedUnion("type", [
769
+ ForgeChangeRequestAttachmentSchema,
770
+ ForgeIssueAttachmentSchema,
734
771
  GitHubPrAttachmentSchema,
735
772
  GitHubIssueAttachmentSchema,
736
773
  TextAttachmentSchema,
@@ -751,6 +788,12 @@ function normalizeAgentAttachments(input) {
751
788
  return normalized;
752
789
  }
753
790
  const AgentAttachmentsSchema = z.unknown().transform(normalizeAgentAttachments).optional();
791
+ export const ChangeRequestCheckoutSourceSchema = z.object({
792
+ kind: z.literal("change_request"),
793
+ forge: z.string().optional(),
794
+ number: z.number().int().positive(),
795
+ projectPath: z.string().optional(),
796
+ });
754
797
  const ImageAttachmentSchema = z.object({
755
798
  data: z.string(), // base64 encoded image
756
799
  mimeType: z.string(), // e.g., "image/jpeg", "image/png"
@@ -881,6 +924,21 @@ export const DaemonGetPairingOfferRequestSchema = z.object({
881
924
  type: z.literal("daemon.get_pairing_offer.request"),
882
925
  requestId: z.string(),
883
926
  });
927
+ export const HubManagementDaemonConnectRequestSchema = z.object({
928
+ type: z.literal("hub.management.daemon.connect.request"),
929
+ requestId: z.string(),
930
+ hubUrl: z.string(),
931
+ token: z.string(),
932
+ });
933
+ export const HubManagementDaemonGetStatusRequestSchema = z.object({
934
+ type: z.literal("hub.management.daemon.get_status.request"),
935
+ requestId: z.string(),
936
+ });
937
+ export const HubManagementDaemonDisconnectRequestSchema = z.object({
938
+ type: z.literal("hub.management.daemon.disconnect.request"),
939
+ requestId: z.string(),
940
+ force: z.boolean().optional(),
941
+ });
884
942
  export const DiagnosticsRequestSchema = z.object({
885
943
  type: z.literal("diagnostics.request"),
886
944
  requestId: z.string(),
@@ -938,6 +996,9 @@ const GitSetupOptionsSchema = z.object({
938
996
  worktreeSlug: z.string().optional(),
939
997
  refName: z.string().min(1).optional(),
940
998
  action: z.enum(["branch-off", "checkout"]).optional(),
999
+ checkoutSource: ChangeRequestCheckoutSourceSchema.optional(),
1000
+ // COMPAT(githubPrNumber): added in v0.1.106, remove after 2026-12-28 once
1001
+ // clients send checkoutSource.
941
1002
  githubPrNumber: z.number().int().positive().optional(),
942
1003
  });
943
1004
  export const CreateAgentWorktreeTargetSchema = z.discriminatedUnion("mode", [
@@ -960,6 +1021,9 @@ export const CreateAgentRequestMessageSchema = z.object({
960
1021
  config: AgentSessionConfigSchema,
961
1022
  env: z.record(z.string(), z.string()).optional(),
962
1023
  workspaceId: z.string().optional(),
1024
+ // Optional caller context lets managed CLI invocations use the same daemon-owned
1025
+ // workspace and parentage policy as agent-scoped MCP creation.
1026
+ callerAgentId: z.string().optional(),
963
1027
  worktreeName: z.string().optional(),
964
1028
  initialPrompt: z.string().optional(),
965
1029
  clientMessageId: z.string().optional(),
@@ -1021,6 +1085,7 @@ export const ImportAgentRequestMessageSchema = z.object({
1021
1085
  sessionId: z.string().optional(),
1022
1086
  providerHandleId: z.string().optional(),
1023
1087
  cwd: z.string().optional(),
1088
+ workspaceId: z.string().optional(),
1024
1089
  labels: z.record(z.string(), z.string()).optional(),
1025
1090
  requestId: z.string(),
1026
1091
  });
@@ -1076,6 +1141,11 @@ export const ProviderSubagentTimelineRequestMessageSchema = z.object({
1076
1141
  cursor: AgentTimelineCursorSchema.optional(),
1077
1142
  limit: z.number().int().nonnegative().optional(),
1078
1143
  });
1144
+ export const SetAgentTimelineSubscriptionRequestMessageSchema = z.object({
1145
+ type: z.literal("agent.timeline.set_subscription.request"),
1146
+ agentIds: z.array(z.string()),
1147
+ requestId: z.string(),
1148
+ });
1079
1149
  export const AgentForkContextRequestMessageSchema = z.object({
1080
1150
  type: z.literal("agent.fork_context.request"),
1081
1151
  agentId: z.string(),
@@ -1205,6 +1275,37 @@ export const WorkspacePinSetResponseSchema = z.object({
1205
1275
  type: z.literal("workspace.pin.set.response"),
1206
1276
  payload: WorkspacePinSetResponsePayloadSchema,
1207
1277
  });
1278
+ export const WorkspaceRecoveryStateSchema = z.discriminatedUnion("kind", [
1279
+ z.object({
1280
+ kind: z.literal("recoverable"),
1281
+ workspaceId: z.string(),
1282
+ workspaceName: z.string(),
1283
+ action: z.string(),
1284
+ branch: z.string().nullable(),
1285
+ }),
1286
+ z.object({
1287
+ kind: z.literal("unavailable"),
1288
+ workspaceId: z.string(),
1289
+ reason: z.string(),
1290
+ message: z.string(),
1291
+ }),
1292
+ ]);
1293
+ export const WorkspaceRecoveryInspectResponseSchema = z.object({
1294
+ type: z.literal("workspace.recovery.inspect.response"),
1295
+ payload: z.object({
1296
+ requestId: z.string(),
1297
+ state: WorkspaceRecoveryStateSchema,
1298
+ }),
1299
+ });
1300
+ export const WorkspaceRecoveryRestoreResponseSchema = z.object({
1301
+ type: z.literal("workspace.recovery.restore.response"),
1302
+ payload: z.object({
1303
+ requestId: z.string(),
1304
+ workspaceId: z.string(),
1305
+ accepted: z.boolean(),
1306
+ error: z.string().nullable(),
1307
+ }),
1308
+ });
1208
1309
  export const SetVoiceModeResponseMessageSchema = z.object({
1209
1310
  type: z.literal("set_voice_mode_response"),
1210
1311
  payload: z.object({
@@ -1306,6 +1407,15 @@ export const CheckoutPrMergeRequestSchema = z.object({
1306
1407
  mergeMethod: z.enum(["merge", "squash", "rebase"]),
1307
1408
  requestId: z.string(),
1308
1409
  });
1410
+ export const CheckoutForgeSetAutoMergeRequestSchema = z.object({
1411
+ type: z.literal("checkout.forge.set_auto_merge.request"),
1412
+ cwd: z.string(),
1413
+ enabled: z.boolean(),
1414
+ mergeMethod: z.enum(["merge", "squash", "rebase"]).optional(),
1415
+ requestId: z.string(),
1416
+ });
1417
+ // COMPAT(githubAutoMergeRpc): added in v0.1.106, remove after 2026-12-28 once
1418
+ // all supported clients use checkout.forge.set_auto_merge.*.
1309
1419
  export const CheckoutGithubSetAutoMergeRequestSchema = z.object({
1310
1420
  type: z.literal("checkout.github.set_auto_merge.request"),
1311
1421
  cwd: z.string(),
@@ -1313,16 +1423,61 @@ export const CheckoutGithubSetAutoMergeRequestSchema = z.object({
1313
1423
  mergeMethod: z.enum(["merge", "squash", "rebase"]).optional(),
1314
1424
  requestId: z.string(),
1315
1425
  });
1426
+ const CheckoutCommitFileSchema = z.object({
1427
+ path: z.string(),
1428
+ additions: z.number(),
1429
+ deletions: z.number(),
1430
+ status: z.enum(["added", "modified", "deleted", "renamed"]).optional(),
1431
+ });
1432
+ const CheckoutCommitSchema = z.object({
1433
+ sha: z.string(),
1434
+ shortSha: z.string(),
1435
+ subject: z.string(),
1436
+ authorName: z.string(),
1437
+ authorDate: z.string(), // ISO 8601
1438
+ isOnRemote: z.boolean(), // false = local-only (unpushed)
1439
+ files: z.array(CheckoutCommitFileSchema),
1440
+ });
1441
+ export const CheckoutCommitsListRequestSchema = z.object({
1442
+ type: z.literal("checkout.commits.list.request"),
1443
+ cwd: z.string(),
1444
+ requestId: z.string(),
1445
+ });
1446
+ export const CheckoutCommitFileDiffRequestSchema = z.object({
1447
+ type: z.literal("checkout.commits.file_diff.request"),
1448
+ cwd: z.string(),
1449
+ sha: z.string(),
1450
+ path: z.string(),
1451
+ requestId: z.string(),
1452
+ });
1316
1453
  const GitHubRepoSegmentSchema = z.string().regex(/^[A-Za-z0-9._-]+$/);
1317
- export const CheckoutGithubGetCheckDetailsRequestSchema = z.object({
1318
- type: z.literal("checkout.github.get_check_details.request"),
1454
+ const CheckoutCheckDetailsRequestPayloadSchema = z.object({
1319
1455
  cwd: z.string(),
1320
- repoOwner: GitHubRepoSegmentSchema,
1321
- repoName: GitHubRepoSegmentSchema,
1322
- checkRunId: z.number().int().positive(),
1456
+ // GitHub addresses check runs by owner/name. GitLab resolves the project from
1457
+ // cwd and omits these GitHub-only single-segment fields.
1458
+ repoOwner: GitHubRepoSegmentSchema.optional(),
1459
+ repoName: GitHubRepoSegmentSchema.optional(),
1460
+ // Permanently optional: a check addressed only by workflowRunId (Gitea
1461
+ // Actions runs carry no check-run id) is fetchable. Callers send at least one
1462
+ // of checkRunId/workflowRunId; the gated forge RPC only reaches daemons that
1463
+ // understand this.
1464
+ checkRunId: z.number().int().positive().optional(),
1323
1465
  workflowRunId: z.number().int().positive().optional(),
1466
+ // Permanent forge-routing field, optional because only some forges need it:
1467
+ // GitLab routes check details to the MR's head pipeline; Gitea-family adapters
1468
+ // resolve the PR head SHA by number, including after merge/close. GitHub
1469
+ // ignores it.
1470
+ changeRequestNumber: z.number().int().positive().optional(),
1324
1471
  requestId: z.string(),
1325
1472
  });
1473
+ export const CheckoutForgeGetCheckDetailsRequestSchema = CheckoutCheckDetailsRequestPayloadSchema.extend({
1474
+ type: z.literal("checkout.forge.get_check_details.request"),
1475
+ });
1476
+ // COMPAT(githubCheckDetailsRpc): added in v0.1.106, remove after 2026-12-28 once
1477
+ // all supported clients use checkout.forge.get_check_details.*.
1478
+ export const CheckoutGithubGetCheckDetailsRequestSchema = CheckoutCheckDetailsRequestPayloadSchema.extend({
1479
+ type: z.literal("checkout.github.get_check_details.request"),
1480
+ });
1326
1481
  export const CheckoutPrStatusRequestSchema = z.object({
1327
1482
  type: z.literal("checkout_pr_status_request"),
1328
1483
  cwd: z.string(),
@@ -1384,17 +1539,41 @@ export const BranchSuggestionsRequestSchema = z.object({
1384
1539
  });
1385
1540
  export const GitHubSearchItemSchema = z.object({
1386
1541
  kind: z.enum(["issue", "pr"]),
1542
+ forge: z.string().optional(),
1387
1543
  number: z.number(),
1388
1544
  title: z.string(),
1389
1545
  url: z.string(),
1390
1546
  state: z.string(),
1391
1547
  body: z.string().nullable(),
1392
1548
  labels: z.array(z.string()),
1549
+ projectPath: z.string().optional(),
1393
1550
  baseRefName: z.string().nullable().optional(),
1394
1551
  headRefName: z.string().nullable().optional(),
1395
1552
  updatedAt: z.string().optional(),
1396
1553
  });
1397
- export const GitHubSearchKindSchema = z.enum(["github-issue", "github-pr"]);
1554
+ export const ForgeSearchItemSchema = GitHubSearchItemSchema.extend({
1555
+ kind: z.enum(["issue", "change_request"]),
1556
+ });
1557
+ // COMPAT(githubSearchKind): added in v0.1.106, remove with the legacy
1558
+ // github_search_request RPC after 2026-12-28.
1559
+ export const ForgeSearchKindSchema = z.enum([
1560
+ "issue",
1561
+ "change_request",
1562
+ "github-issue",
1563
+ "github-pr",
1564
+ "pr",
1565
+ ]);
1566
+ export const GitHubSearchKindSchema = ForgeSearchKindSchema;
1567
+ export const ForgeSearchRequestSchema = z.object({
1568
+ type: z.literal("forge.search.request"),
1569
+ cwd: z.string(),
1570
+ query: z.string(),
1571
+ limit: z.number().int().min(1).max(50).optional(),
1572
+ kinds: z.array(ForgeSearchKindSchema).optional(),
1573
+ requestId: z.string(),
1574
+ });
1575
+ // COMPAT(githubSearchRpc): added in v0.1.106, remove after 2026-12-28 once
1576
+ // clients use forge.search.*.
1398
1577
  export const GitHubSearchRequestSchema = z.object({
1399
1578
  type: z.literal("github_search_request"),
1400
1579
  cwd: z.string(),
@@ -1456,6 +1635,9 @@ export const CreatePaseoWorktreeRequestSchema = z.object({
1456
1635
  firstAgentContext: FirstAgentContextSchema.optional(),
1457
1636
  refName: z.string().min(1).optional(),
1458
1637
  action: z.enum(["branch-off", "checkout"]).optional(),
1638
+ checkoutSource: ChangeRequestCheckoutSourceSchema.optional(),
1639
+ // COMPAT(githubPrNumber): added in v0.1.106, remove after 2026-12-28 once
1640
+ // clients send checkoutSource: { kind: "change_request", forge, number }.
1459
1641
  githubPrNumber: z.number().int().positive().optional(),
1460
1642
  requestId: z.string(),
1461
1643
  });
@@ -1547,9 +1729,14 @@ export const WorkspaceCreateRequestSchema = z.object({
1547
1729
  cwd: z.string().optional(),
1548
1730
  projectId: z.string().optional(),
1549
1731
  action: z.enum(["branch-off", "checkout"]).optional(),
1550
- // Target branch name for checkout, or new branch name for branch-off.
1732
+ // Target branch for checkout, or base ref for branch-off.
1551
1733
  refName: z.string().min(1).optional(),
1552
1734
  baseBranch: z.string().optional(),
1735
+ // New branch name for branch-off. The worktree path may use a different slug.
1736
+ branchName: z.string().min(1).optional(),
1737
+ checkoutSource: ChangeRequestCheckoutSourceSchema.optional(),
1738
+ // COMPAT(githubPrNumber): added in v0.1.106, remove after 2026-12-28 once
1739
+ // clients send checkoutSource.
1553
1740
  githubPrNumber: z.number().int().positive().optional(),
1554
1741
  worktreeSlug: z.string().optional(),
1555
1742
  }),
@@ -1602,6 +1789,7 @@ const FileExplorerFileSchema = z.object({
1602
1789
  mimeType: z.string().optional(),
1603
1790
  size: z.number(),
1604
1791
  modifiedAt: z.string(),
1792
+ revision: z.string().optional(),
1605
1793
  });
1606
1794
  const FileExplorerDirectorySchema = z.object({
1607
1795
  path: z.string(),
@@ -1615,6 +1803,48 @@ export const FileExplorerRequestSchema = z.object({
1615
1803
  requestId: z.string(),
1616
1804
  acceptBinary: z.boolean().optional(),
1617
1805
  });
1806
+ export const FileVersionSchema = z.discriminatedUnion("status", [
1807
+ z.object({
1808
+ status: z.literal("ready"),
1809
+ cwd: z.string(),
1810
+ path: z.string(),
1811
+ size: z.number().int().nonnegative(),
1812
+ modifiedAt: z.string(),
1813
+ revision: z.string().optional(),
1814
+ }),
1815
+ z.object({
1816
+ status: z.literal("missing"),
1817
+ cwd: z.string(),
1818
+ path: z.string(),
1819
+ }),
1820
+ z.object({
1821
+ status: z.literal("error"),
1822
+ cwd: z.string(),
1823
+ path: z.string(),
1824
+ error: z.string(),
1825
+ }),
1826
+ ]);
1827
+ export const FileSubscribeRequestSchema = z.object({
1828
+ type: z.literal("fs.file.subscribe.request"),
1829
+ cwd: z.string(),
1830
+ path: z.string(),
1831
+ subscriptionId: z.string(),
1832
+ requestId: z.string(),
1833
+ });
1834
+ export const FileUnsubscribeRequestSchema = z.object({
1835
+ type: z.literal("fs.file.unsubscribe.request"),
1836
+ subscriptionId: z.string(),
1837
+ requestId: z.string(),
1838
+ });
1839
+ export const FileWriteRequestSchema = z.object({
1840
+ type: z.literal("fs.file.write.request"),
1841
+ cwd: z.string(),
1842
+ path: z.string(),
1843
+ content: z.string(),
1844
+ expectedModifiedAt: z.string(),
1845
+ expectedRevision: z.string().optional(),
1846
+ requestId: z.string(),
1847
+ });
1618
1848
  export const ProjectIconRequestSchema = z.object({
1619
1849
  type: z.literal("project_icon_request"),
1620
1850
  cwd: z.string(),
@@ -1704,10 +1934,10 @@ export const CreateTerminalRequestSchema = z.object({
1704
1934
  agentId: z.string().optional(),
1705
1935
  command: z.string().optional(),
1706
1936
  args: z.array(z.string()).optional(),
1707
- // COMPAT(createTerminalSize): added in v0.1.107, drop the optional gate when floor >= v0.1.107.
1708
- // The client seeds the PTY with its measured viewport size so a new terminal isn't born at the
1709
- // 80x24 default and then visibly reflowed. Old daemons ignore this field and start at 80x24;
1710
- // the client's first resize corrects it as before.
1937
+ // Initial PTY size. Added in v0.1.107; the app no longer sends it (the estimate cache that fed
1938
+ // it was removed the pane-focus resize claim sizes the PTY instead). Kept and honored
1939
+ // permanently: released v0.1.107 clients still send it, and programmatic callers may pass an
1940
+ // exact size. Daemons without it start at 80x24 and the first resize corrects that.
1711
1941
  size: z
1712
1942
  .object({
1713
1943
  rows: z.number().int().positive(),
@@ -1778,7 +2008,24 @@ export const CaptureTerminalRequestSchema = z.object({
1778
2008
  stripAnsi: z.boolean().default(true),
1779
2009
  requestId: z.string(),
1780
2010
  });
2011
+ export const HubExecutionAgentCreateRequestSchema = z.object({
2012
+ type: z.literal("hub.execution.agent.create.request"),
2013
+ requestId: z.string(),
2014
+ executionId: z.string(),
2015
+ provider: z.string(),
2016
+ cwd: z.string(),
2017
+ prompt: z.string(),
2018
+ workspaceId: z.string().optional(),
2019
+ model: z.string().optional(),
2020
+ modeId: z.string().optional(),
2021
+ thinkingOptionId: z.string().optional(),
2022
+ featureValues: z.record(z.string(), z.unknown()).optional(),
2023
+ env: z.record(z.string(), z.string()).optional(),
2024
+ worktree: CreateAgentWorktreeTargetSchema.optional(),
2025
+ autoArchive: z.boolean().optional(),
2026
+ });
1781
2027
  export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
2028
+ HubExecutionAgentCreateRequestSchema,
1782
2029
  BrowserAutomationExecuteResponseSchema,
1783
2030
  VoiceAudioChunkMessageSchema,
1784
2031
  AbortRequestMessageSchema,
@@ -1796,11 +2043,16 @@ export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
1796
2043
  ProjectRemoveRequestSchema,
1797
2044
  WorkspaceTitleSetRequestSchema,
1798
2045
  WorkspacePinSetRequestSchema,
2046
+ WorkspaceRecoveryInspectRequestSchema,
2047
+ WorkspaceRecoveryRestoreRequestSchema,
1799
2048
  SetVoiceModeMessageSchema,
1800
2049
  SendAgentMessageRequestSchema,
1801
2050
  WaitForFinishRequestSchema,
1802
2051
  DaemonGetStatusRequestSchema,
1803
2052
  DaemonGetPairingOfferRequestSchema,
2053
+ HubManagementDaemonConnectRequestSchema,
2054
+ HubManagementDaemonGetStatusRequestSchema,
2055
+ HubManagementDaemonDisconnectRequestSchema,
1804
2056
  DiagnosticsRequestSchema,
1805
2057
  GetDaemonConfigRequestMessageSchema,
1806
2058
  SetDaemonConfigRequestMessageSchema,
@@ -1829,6 +2081,7 @@ export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
1829
2081
  FetchAgentTimelineRequestMessageSchema,
1830
2082
  ProviderSubagentListRequestMessageSchema,
1831
2083
  ProviderSubagentTimelineRequestMessageSchema,
2084
+ SetAgentTimelineSubscriptionRequestMessageSchema,
1832
2085
  AgentForkContextRequestMessageSchema,
1833
2086
  SetAgentModeRequestMessageSchema,
1834
2087
  SetAgentModelRequestMessageSchema,
@@ -1848,7 +2101,11 @@ export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
1848
2101
  CheckoutRefreshRequestSchema,
1849
2102
  CheckoutPrCreateRequestSchema,
1850
2103
  CheckoutPrMergeRequestSchema,
2104
+ CheckoutForgeSetAutoMergeRequestSchema,
1851
2105
  CheckoutGithubSetAutoMergeRequestSchema,
2106
+ CheckoutCommitsListRequestSchema,
2107
+ CheckoutCommitFileDiffRequestSchema,
2108
+ CheckoutForgeGetCheckDetailsRequestSchema,
1852
2109
  CheckoutGithubGetCheckDetailsRequestSchema,
1853
2110
  CheckoutPrStatusRequestSchema,
1854
2111
  PullRequestTimelineRequestSchema,
@@ -1859,6 +2116,7 @@ export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
1859
2116
  StashListRequestSchema,
1860
2117
  ValidateBranchRequestSchema,
1861
2118
  BranchSuggestionsRequestSchema,
2119
+ ForgeSearchRequestSchema,
1862
2120
  GitHubSearchRequestSchema,
1863
2121
  DirectorySuggestionsRequestSchema,
1864
2122
  PaseoWorktreeListRequestSchema,
@@ -1876,6 +2134,9 @@ export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
1876
2134
  WorkspaceCreateRequestSchema,
1877
2135
  WorkspaceClearAttentionRequestSchema,
1878
2136
  FileExplorerRequestSchema,
2137
+ FileSubscribeRequestSchema,
2138
+ FileUnsubscribeRequestSchema,
2139
+ FileWriteRequestSchema,
1879
2140
  ProjectIconRequestSchema,
1880
2141
  FileDownloadTokenRequestSchema,
1881
2142
  FileUploadRequestSchema,
@@ -2055,14 +2316,23 @@ export const ServerInfoStatusPayloadSchema = z
2055
2316
  serverId: z.string().trim().min(1),
2056
2317
  hostname: ServerInfoHostnameSchema.optional(),
2057
2318
  version: ServerInfoVersionSchema.optional(),
2319
+ // COMPAT(desktopManaged): added in v0.1.X, remove optional parsing after 2027-01-16.
2320
+ desktopManaged: z.boolean().optional(),
2058
2321
  capabilities: ServerCapabilitiesFromUnknownSchema.optional(),
2059
2322
  // COMPAT(providersSnapshot): added in v0.1.48, remove gating when all clients use snapshot
2060
2323
  features: z
2061
2324
  .object({
2062
2325
  providersSnapshot: z.boolean().optional(),
2326
+ // COMPAT(checkoutForgeSetAutoMerge): added in v0.1.106, remove old
2327
+ // checkoutGithubSetAutoMerge fallback after 2026-12-28.
2328
+ checkoutForgeSetAutoMerge: z.boolean().optional(),
2063
2329
  checkoutGithubSetAutoMerge: z.boolean().optional(),
2064
2330
  // COMPAT(githubCheckDetails): added in v0.1.92, remove gate after 2026-12-08.
2065
2331
  githubCheckDetails: z.boolean().optional(),
2332
+ // COMPAT(forgeCheckDetails): added in v0.1.106, remove githubCheckDetails fallback after 2026-12-28.
2333
+ forgeCheckDetails: z.boolean().optional(),
2334
+ // COMPAT(forgeSearch): added in v0.1.106, remove github_search fallback after 2026-12-28.
2335
+ forgeSearch: z.boolean().optional(),
2066
2336
  // COMPAT(daemonStatusRpc): added in v0.1.76, remove gate after 2026-11-18.
2067
2337
  daemonStatusRpc: z.boolean().optional(),
2068
2338
  // COMPAT(terminalRestoreModes): added in v0.1.81, remove gate after 2026-11-23.
@@ -2079,6 +2349,10 @@ export const ServerInfoStatusPayloadSchema = z
2079
2349
  projectAdd: z.boolean().optional(),
2080
2350
  // COMPAT(worktreeRestore): added in v0.1.97, drop the gate when floor >= v0.1.97
2081
2351
  worktreeRestore: z.boolean().optional(),
2352
+ // COMPAT(workspaceRecovery): added in v0.1.105, remove after 2027-01-11 once daemon floor >= v0.1.105.
2353
+ workspaceRecovery: z.boolean().optional(),
2354
+ // COMPAT(workspaceFileEditing): added in v0.2.0, remove after 2027-01-18 once daemon floor >= v0.2.0.
2355
+ workspaceFileEditing: z.boolean().optional(),
2082
2356
  // COMPAT(providerUsageList): added in v0.1.98, drop the gate when daemon floor >= v0.1.98.
2083
2357
  providerUsageList: z.boolean().optional(),
2084
2358
  // COMPAT(agentDetach): added in v0.1.98, remove gate after 2026-12-19 once daemon floor >= v0.1.98.
@@ -2095,12 +2369,28 @@ export const ServerInfoStatusPayloadSchema = z
2095
2369
  providerSubagents: z.boolean().optional(),
2096
2370
  // COMPAT(workspacePinning): added in v0.1.107, remove gate after 2027-01-12.
2097
2371
  workspacePinning: z.boolean().optional(),
2372
+ // COMPAT(hubRelationship): added in v0.1.X, drop the gate when floor >= v0.1.X.
2373
+ hubRelationship: z.boolean().optional(),
2098
2374
  // COMPAT(projectGithubClone): added in v0.1.108, remove gate after 2027-01-15.
2099
2375
  projectGithubClone: z.boolean().optional(),
2100
2376
  // COMPAT(workspaceGithubRepositorySearch): added in v0.1.108, remove gate after 2027-01-15.
2101
2377
  workspaceGithubRepositorySearch: z.boolean().optional(),
2102
2378
  // COMPAT(projectCreateDirectory): added in v0.1.108, remove gate after 2027-01-15.
2103
2379
  projectCreateDirectory: z.boolean().optional(),
2380
+ // COMPAT(commitsList): added in v0.1.110, remove gate after 2027-01-16.
2381
+ commitsList: z.boolean().optional(),
2382
+ // COMPAT(providerRemoval): added in v0.1.105, drop the gate when floor >= v0.1.105.
2383
+ providerRemoval: z.boolean().optional(),
2384
+ // COMPAT(importSessionWorkspaceTarget): added in v0.1.110, remove gate after 2027-01-16.
2385
+ importSessionWorkspaceTarget: z.boolean().optional(),
2386
+ // COMPAT(forgeProviders): added in v0.1.106, drop the gate when daemon floor >= v0.1.106.
2387
+ // Daemon advertises pluggable non-GitHub forge support (the forge registry);
2388
+ // the client gates non-GitHub setup UI on it.
2389
+ forgeProviders: z.boolean().optional(),
2390
+ // COMPAT(selectiveAgentTimeline): added in v0.1.106, remove after 2027-01-12.
2391
+ selectiveAgentTimeline: z.boolean().optional(),
2392
+ // COMPAT(stableProjectIdentity): added in v0.1.109, remove gate after 2027-01-15.
2393
+ stableProjectIdentity: z.boolean().optional(),
2104
2394
  })
2105
2395
  .optional(),
2106
2396
  })
@@ -2374,6 +2664,10 @@ export const WorkspaceDescriptorPayloadSchema = z
2374
2664
  scripts: z.array(WorkspaceScriptPayloadSchema).default([]),
2375
2665
  gitRuntime: WorkspaceGitRuntimePayloadSchema,
2376
2666
  githubRuntime: WorkspaceGitHubRuntimePayloadSchema,
2667
+ // COMPAT(forge): added in v0.1.106, remove after 2026-12-27. The forge resolved
2668
+ // for this workspace, so the sidebar/hover-card render the right brand mark.
2669
+ // Old daemons omit it; absent means the client falls back to GitHub.
2670
+ forge: z.string().optional(),
2377
2671
  project: ProjectPlacementPayloadSchema.optional(),
2378
2672
  })
2379
2673
  .transform((workspace) => ({
@@ -2504,6 +2798,13 @@ export const WorkspaceUpdateMessageSchema = z.object({
2504
2798
  }),
2505
2799
  ]),
2506
2800
  });
2801
+ export const ProjectUpdateMessageSchema = z.object({
2802
+ type: z.literal("project.update"),
2803
+ payload: z.discriminatedUnion("kind", [
2804
+ z.object({ kind: z.literal("upsert"), project: WorkspaceProjectDescriptorPayloadSchema }),
2805
+ z.object({ kind: z.literal("remove"), projectId: z.string() }),
2806
+ ]),
2807
+ });
2507
2808
  export const ScriptStatusUpdateMessageSchema = z.object({
2508
2809
  type: z.literal("script_status_update"),
2509
2810
  payload: z.object({
@@ -2773,6 +3074,33 @@ export const ProviderSubagentUpdateMessageSchema = z.object({
2773
3074
  }),
2774
3075
  ]),
2775
3076
  });
3077
+ export const SetAgentTimelineSubscriptionResponseMessageSchema = z.object({
3078
+ type: z.literal("agent.timeline.set_subscription.response"),
3079
+ payload: z.object({
3080
+ agentIds: z.array(z.string()),
3081
+ requestId: z.string(),
3082
+ }),
3083
+ });
3084
+ export const AgentAttentionRequiredMessageSchema = z.object({
3085
+ type: z.literal("agent_attention_required"),
3086
+ payload: z.object({
3087
+ agentId: z.string(),
3088
+ reason: z.enum(["finished", "error", "permission"]),
3089
+ timestamp: z.string(),
3090
+ shouldNotify: z.boolean(),
3091
+ notification: z
3092
+ .object({
3093
+ title: z.string(),
3094
+ body: z.string(),
3095
+ data: z.object({
3096
+ serverId: z.string(),
3097
+ agentId: z.string(),
3098
+ reason: z.enum(["finished", "error", "permission"]),
3099
+ }),
3100
+ })
3101
+ .optional(),
3102
+ }),
3103
+ });
2776
3104
  export const AgentForkContextResponseMessageSchema = z.object({
2777
3105
  type: z.literal("agent.fork_context.response"),
2778
3106
  payload: z.object({
@@ -2885,6 +3213,37 @@ export const DaemonGetStatusResponseSchema = z.object({
2885
3213
  })
2886
3214
  .passthrough(),
2887
3215
  });
3216
+ export const HubRelationshipStatusSchema = z.object({
3217
+ state: z.enum([
3218
+ "not_connected",
3219
+ "connecting",
3220
+ "connected",
3221
+ "reconnecting",
3222
+ "disconnecting",
3223
+ "revoked",
3224
+ ]),
3225
+ daemonId: z.string().nullable(),
3226
+ hubOrigin: z.string().nullable(),
3227
+ scopes: z.array(z.string()),
3228
+ connectedAt: z.string().nullable(),
3229
+ lastError: z.string().nullable(),
3230
+ });
3231
+ export const HubManagementDaemonConnectResponseSchema = z.object({
3232
+ type: z.literal("hub.management.daemon.connect.response"),
3233
+ payload: z.object({ requestId: z.string(), status: HubRelationshipStatusSchema }),
3234
+ });
3235
+ export const HubManagementDaemonGetStatusResponseSchema = z.object({
3236
+ type: z.literal("hub.management.daemon.get_status.response"),
3237
+ payload: z.object({ requestId: z.string(), status: HubRelationshipStatusSchema }),
3238
+ });
3239
+ export const HubManagementDaemonDisconnectResponseSchema = z.object({
3240
+ type: z.literal("hub.management.daemon.disconnect.response"),
3241
+ payload: z.object({
3242
+ requestId: z.string(),
3243
+ status: HubRelationshipStatusSchema,
3244
+ warning: z.string().optional(),
3245
+ }),
3246
+ });
2888
3247
  export const DaemonGetPairingOfferResponseSchema = z.object({
2889
3248
  type: z.literal("daemon.get_pairing_offer.response"),
2890
3249
  payload: z
@@ -3083,8 +3442,7 @@ const CheckoutPrGithubRepositoryPolicySchema = z
3083
3442
  rebaseMergeAllowed: false,
3084
3443
  viewerDefaultMergeMethod: null,
3085
3444
  });
3086
- const CheckoutPrGithubStatusSchema = z
3087
- .object({
3445
+ const CheckoutPrGithubStatusObjectSchema = z.object({
3088
3446
  mergeStateStatus: z.string().nullable().optional().default(null),
3089
3447
  autoMergeRequest: CheckoutPrGithubAutoMergeRequestSchema,
3090
3448
  viewerCanEnableAutoMerge: z.boolean().optional().default(false),
@@ -3094,9 +3452,23 @@ const CheckoutPrGithubStatusSchema = z
3094
3452
  repository: CheckoutPrGithubRepositoryPolicySchema,
3095
3453
  isMergeQueueEnabled: z.boolean().optional().default(false),
3096
3454
  isInMergeQueue: z.boolean().optional().default(false),
3097
- })
3098
- .optional();
3455
+ });
3456
+ const CheckoutPrGithubStatusSchema = CheckoutPrGithubStatusObjectSchema.optional();
3457
+ // The open facts envelope for forge-specific PR facts. Permanent — non-GitHub
3458
+ // forges deliver their native facts through it. The transitional piece is the
3459
+ // `github` mirror above, which stays populated for clients predating this
3460
+ // envelope; see COMPAT(forgeSpecific) in status-projection.ts for the shim.
3461
+ //
3462
+ // NOTE: `forgeSpecific.forge` is a FACTS-FAMILY tag, not the workspace brand id.
3463
+ // The whole Gitea family (gitea, forgejo, codeberg) emits `forge: "gitea"` here
3464
+ // because they share one facts shape, while the top-level `forge` above carries
3465
+ // the specific brand. Validation of family-specific payloads happens at runtime
3466
+ // in the consumer that knows that forge family.
3467
+ const CheckoutPrForgeSpecificSchema = z.unknown().optional();
3099
3468
  export const CheckoutPrStatusSchema = z.object({
3469
+ // COMPAT(forge): added in v0.1.106, remove the default after 2026-12-27 once daemon floor >= v0.1.106.
3470
+ forge: z.string().optional().default("github"),
3471
+ projectPath: z.string().optional(),
3100
3472
  number: z.number().optional(),
3101
3473
  url: z.string(),
3102
3474
  title: z.string(),
@@ -3127,11 +3499,20 @@ export const CheckoutPrStatusSchema = z.object({
3127
3499
  repoOwner: z.string().optional(),
3128
3500
  repoName: z.string().optional(),
3129
3501
  github: CheckoutPrGithubStatusSchema,
3502
+ forgeSpecific: CheckoutPrForgeSpecificSchema,
3130
3503
  });
3504
+ export const ForgeAuthStateSchema = z.unknown().optional();
3131
3505
  const CheckoutPrStatusPayloadSchema = z.object({
3132
3506
  cwd: z.string(),
3133
3507
  status: CheckoutPrStatusSchema.nullable(),
3134
3508
  githubFeaturesEnabled: z.boolean(),
3509
+ // COMPAT(forgeAuthState): added in v0.1.106, remove after 2026-12-27. Optional richer
3510
+ // signal that supersedes githubFeaturesEnabled. The legacy boolean stays for old clients
3511
+ // and may remain true for non-auth error payloads so old clients still show the error.
3512
+ // Drop the boolean once the daemon floor >= v0.1.106.
3513
+ authState: ForgeAuthStateSchema,
3514
+ // COMPAT(forge): added in v0.1.106, remove the default after 2026-12-27 once daemon floor >= v0.1.106.
3515
+ forge: z.string().optional().default("github"),
3135
3516
  error: CheckoutErrorSchema.nullable(),
3136
3517
  requestId: z.string(),
3137
3518
  });
@@ -3237,6 +3618,18 @@ export const CheckoutPrMergeResponseSchema = z.object({
3237
3618
  requestId: z.string(),
3238
3619
  }),
3239
3620
  });
3621
+ export const CheckoutForgeSetAutoMergeResponseSchema = z.object({
3622
+ type: z.literal("checkout.forge.set_auto_merge.response"),
3623
+ payload: z.object({
3624
+ cwd: z.string(),
3625
+ enabled: z.boolean(),
3626
+ success: z.boolean(),
3627
+ error: CheckoutErrorSchema.nullable(),
3628
+ requestId: z.string(),
3629
+ }),
3630
+ });
3631
+ // COMPAT(githubAutoMergeRpc): added in v0.1.106, remove after 2026-12-28 once
3632
+ // all supported clients use checkout.forge.set_auto_merge.*.
3240
3633
  export const CheckoutGithubSetAutoMergeResponseSchema = z.object({
3241
3634
  type: z.literal("checkout.github.set_auto_merge.response"),
3242
3635
  payload: z.object({
@@ -3247,6 +3640,29 @@ export const CheckoutGithubSetAutoMergeResponseSchema = z.object({
3247
3640
  requestId: z.string(),
3248
3641
  }),
3249
3642
  });
3643
+ export const CheckoutCommitsListResponseSchema = z.object({
3644
+ type: z.literal("checkout.commits.list.response"),
3645
+ payload: z.object({
3646
+ cwd: z.string(),
3647
+ baseRef: z.string().nullable(),
3648
+ commits: z.array(CheckoutCommitSchema),
3649
+ error: CheckoutErrorSchema.nullable(),
3650
+ requestId: z.string(),
3651
+ }),
3652
+ });
3653
+ export const CheckoutCommitFileDiffResponseSchema = z.object({
3654
+ type: z.literal("checkout.commits.file_diff.response"),
3655
+ payload: z.object({
3656
+ cwd: z.string(),
3657
+ sha: z.string(),
3658
+ path: z.string(),
3659
+ // null when the file is absent from the commit or carries no textual diff
3660
+ // (e.g. binary-only changes).
3661
+ file: ParsedDiffFileSchema.nullable(),
3662
+ error: CheckoutErrorSchema.nullable(),
3663
+ requestId: z.string(),
3664
+ }),
3665
+ });
3250
3666
  const CheckoutGithubCheckAnnotationSchema = z.object({
3251
3667
  path: z.string().optional(),
3252
3668
  startLine: z.number().optional(),
@@ -3265,6 +3681,31 @@ const CheckoutGithubCheckJobSchema = z.object({
3265
3681
  logTail: z.string().optional(),
3266
3682
  logTruncated: z.boolean().optional(),
3267
3683
  });
3684
+ // Statuses stay open strings so future forge values cannot break parsing.
3685
+ const CheckoutPipelineJobSchema = z.object({
3686
+ id: z.number(),
3687
+ name: z.string(),
3688
+ stage: z.string(),
3689
+ status: z.string(),
3690
+ rawStatus: z.string(),
3691
+ url: z.string().nullable().optional().default(null),
3692
+ allowFailure: z.boolean().optional().default(false),
3693
+ durationSeconds: z.number().nullable().optional().default(null),
3694
+ });
3695
+ const CheckoutPipelineStageSchema = z.object({
3696
+ name: z.string(),
3697
+ status: z.string(),
3698
+ jobs: z.array(CheckoutPipelineJobSchema).optional().default([]),
3699
+ });
3700
+ const CheckoutPipelineSchema = z.object({
3701
+ id: z.number(),
3702
+ status: z.string(),
3703
+ rawStatus: z.string(),
3704
+ url: z.string().nullable().optional().default(null),
3705
+ ref: z.string().nullable().optional().default(null),
3706
+ sha: z.string().nullable().optional().default(null),
3707
+ stages: z.array(CheckoutPipelineStageSchema).optional().default([]),
3708
+ });
3268
3709
  export const CheckoutGithubCheckDetailsSchema = z.object({
3269
3710
  checkRunId: z.number(),
3270
3711
  workflowRunId: z.number().nullable().optional(),
@@ -3284,13 +3725,28 @@ export const CheckoutGithubCheckDetailsSchema = z.object({
3284
3725
  annotations: z.array(CheckoutGithubCheckAnnotationSchema).optional().default([]),
3285
3726
  failedJobs: z.array(CheckoutGithubCheckJobSchema).optional().default([]),
3286
3727
  truncated: z.boolean().optional().default(false),
3728
+ // No default: server CheckDetails keeps this optional and GitHub leaves it absent.
3729
+ pipeline: CheckoutPipelineSchema.nullable().optional(),
3730
+ });
3731
+ export const CheckoutCheckDetailsSchema = CheckoutGithubCheckDetailsSchema;
3732
+ export const CheckoutForgeGetCheckDetailsResponseSchema = z.object({
3733
+ type: z.literal("checkout.forge.get_check_details.response"),
3734
+ payload: z.object({
3735
+ cwd: z.string(),
3736
+ success: z.boolean(),
3737
+ details: CheckoutCheckDetailsSchema.nullable().optional().default(null),
3738
+ error: CheckoutErrorSchema.nullable(),
3739
+ requestId: z.string(),
3740
+ }),
3287
3741
  });
3742
+ // COMPAT(githubCheckDetailsRpc): added in v0.1.106, remove after 2026-12-28 once
3743
+ // all supported clients use checkout.forge.get_check_details.*.
3288
3744
  export const CheckoutGithubGetCheckDetailsResponseSchema = z.object({
3289
3745
  type: z.literal("checkout.github.get_check_details.response"),
3290
3746
  payload: z.object({
3291
3747
  cwd: z.string(),
3292
3748
  success: z.boolean(),
3293
- details: CheckoutGithubCheckDetailsSchema.nullable().optional().default(null),
3749
+ details: CheckoutCheckDetailsSchema.nullable().optional().default(null),
3294
3750
  error: CheckoutErrorSchema.nullable(),
3295
3751
  requestId: z.string(),
3296
3752
  }),
@@ -3350,6 +3806,16 @@ const PullRequestTimelineCommentItemSchema = z.object({
3350
3806
  // threads under their parent review. Absent on issue comments and on
3351
3807
  // timelines from daemons that predate the field.
3352
3808
  reviewId: z.string().optional(),
3809
+ // Forge-neutral discussion/thread id this comment belongs to, independent of a
3810
+ // file position. GitLab maps its discussion id here so general (non-file)
3811
+ // reply chains group into one thread; file-position threads also carry it.
3812
+ // Absent on standalone comments and on timelines from daemons that predate it.
3813
+ threadId: z.string().optional(),
3814
+ // Forge-neutral resolution state for a thread that has no file position, e.g. a
3815
+ // GitLab general (non-file) discussion that is resolvable. File-position threads
3816
+ // carry their resolution under `location.isResolved` instead. Absent on ordinary
3817
+ // comments, on forges that expose no thread resolution, and on older timelines.
3818
+ threadIsResolved: z.boolean().optional(),
3353
3819
  location: z
3354
3820
  .object({
3355
3821
  path: z.string(),
@@ -3385,6 +3851,10 @@ export const PullRequestTimelineResponseSchema = z.object({
3385
3851
  error: PullRequestTimelineErrorSchema.nullable().optional().default(null),
3386
3852
  requestId: z.string().optional().default(""),
3387
3853
  githubFeaturesEnabled: z.boolean().optional().default(true),
3854
+ // COMPAT(forgeAuthState): added in v0.1.106, remove after 2026-12-27. Optional richer
3855
+ // signal that supersedes githubFeaturesEnabled, mirroring CheckoutPrStatusPayloadSchema.
3856
+ // Drop the boolean once the daemon floor >= v0.1.106.
3857
+ authState: ForgeAuthStateSchema,
3388
3858
  })
3389
3859
  .optional()
3390
3860
  .prefault({}),
@@ -3469,14 +3939,29 @@ export const BranchSuggestionsResponseSchema = z.object({
3469
3939
  requestId: z.string(),
3470
3940
  }),
3471
3941
  });
3942
+ const ForgeSearchResponsePayloadSchema = z.object({
3943
+ items: z.array(z.unknown()),
3944
+ authState: z.unknown().optional(),
3945
+ error: z.string().nullable(),
3946
+ requestId: z.string(),
3947
+ });
3948
+ const GitHubSearchResponsePayloadSchema = z.object({
3949
+ items: z.array(z.unknown()),
3950
+ featuresEnabled: z.boolean().optional(),
3951
+ authState: z.unknown().optional(),
3952
+ githubFeaturesEnabled: z.boolean().optional(),
3953
+ error: z.string().nullable(),
3954
+ requestId: z.string(),
3955
+ });
3956
+ export const ForgeSearchResponseSchema = z.object({
3957
+ type: z.literal("forge.search.response"),
3958
+ payload: ForgeSearchResponsePayloadSchema,
3959
+ });
3960
+ // COMPAT(githubSearchRpc): added in v0.1.106, remove after 2026-12-28 once
3961
+ // clients use forge.search.*.
3472
3962
  export const GitHubSearchResponseSchema = z.object({
3473
3963
  type: z.literal("github_search_response"),
3474
- payload: z.object({
3475
- items: z.array(GitHubSearchItemSchema),
3476
- githubFeaturesEnabled: z.boolean(),
3477
- error: z.string().nullable(),
3478
- requestId: z.string(),
3479
- }),
3964
+ payload: GitHubSearchResponsePayloadSchema,
3480
3965
  });
3481
3966
  export const DirectorySuggestionsResponseSchema = z.object({
3482
3967
  type: z.literal("directory_suggestions_response"),
@@ -3538,6 +4023,45 @@ export const FileExplorerResponseSchema = z.object({
3538
4023
  requestId: z.string(),
3539
4024
  }),
3540
4025
  });
4026
+ export const FileSubscribeResponseSchema = z.object({
4027
+ type: z.literal("fs.file.subscribe.response"),
4028
+ payload: z.object({
4029
+ subscriptionId: z.string(),
4030
+ initial: FileVersionSchema,
4031
+ requestId: z.string(),
4032
+ }),
4033
+ });
4034
+ export const FileUnsubscribeResponseSchema = z.object({
4035
+ type: z.literal("fs.file.unsubscribe.response"),
4036
+ payload: z.object({
4037
+ subscriptionId: z.string(),
4038
+ requestId: z.string(),
4039
+ }),
4040
+ });
4041
+ export const FileWriteResultSchema = z.discriminatedUnion("status", [
4042
+ z.object({
4043
+ status: z.literal("written"),
4044
+ modifiedAt: z.string(),
4045
+ size: z.number(),
4046
+ revision: z.string().optional(),
4047
+ }),
4048
+ z.object({ status: z.literal("conflict"), version: FileVersionSchema }),
4049
+ z.object({ status: z.literal("error"), error: z.string() }),
4050
+ ]);
4051
+ export const FileWriteResponseSchema = z.object({
4052
+ type: z.literal("fs.file.write.response"),
4053
+ payload: z.object({
4054
+ result: FileWriteResultSchema,
4055
+ requestId: z.string(),
4056
+ }),
4057
+ });
4058
+ export const FileUpdateSchema = z.object({
4059
+ type: z.literal("fs.file.update"),
4060
+ payload: z.object({
4061
+ subscriptionId: z.string(),
4062
+ version: FileVersionSchema,
4063
+ }),
4064
+ });
3541
4065
  const ProjectIconSchema = z.object({
3542
4066
  data: z.string(),
3543
4067
  mimeType: z.string(),
@@ -3862,7 +4386,60 @@ export const DaemonUpdateProgressMessageSchema = z.object({
3862
4386
  phase: z.enum(["starting", "downloading", "installing", "complete"]),
3863
4387
  }),
3864
4388
  });
4389
+ export const HubExecutionAgentCreateResponseSchema = z.object({
4390
+ type: z.literal("hub.execution.agent.create.response"),
4391
+ payload: z.object({
4392
+ requestId: z.string(),
4393
+ executionId: z.string(),
4394
+ agentId: z.string().nullable(),
4395
+ agent: AgentSnapshotPayloadSchema.nullable(),
4396
+ success: z.boolean(),
4397
+ error: z.string().nullable(),
4398
+ }),
4399
+ });
4400
+ export const HubExecutionAgentUpdateSchema = z.object({
4401
+ type: z.literal("hub.execution.agent.update"),
4402
+ payload: z.object({
4403
+ executionId: z.string(),
4404
+ agentId: z.string(),
4405
+ agent: AgentSnapshotPayloadSchema,
4406
+ }),
4407
+ });
4408
+ export const HubExecutionAgentStreamSchema = z.object({
4409
+ type: z.literal("hub.execution.agent.stream"),
4410
+ payload: z.object({
4411
+ executionId: z.string(),
4412
+ agentId: z.string(),
4413
+ event: AgentStreamEventPayloadSchema,
4414
+ }),
4415
+ });
4416
+ export const HubExecutionOutboundMessageSchema = z.discriminatedUnion("type", [
4417
+ HubExecutionAgentCreateResponseSchema,
4418
+ HubExecutionAgentUpdateSchema,
4419
+ HubExecutionAgentStreamSchema,
4420
+ ]);
4421
+ export class HubMessageCorrelationError extends Error {
4422
+ constructor(messageType) {
4423
+ super(`Hub message ${messageType} has mismatched agent correlation`);
4424
+ this.name = "HubMessageCorrelationError";
4425
+ }
4426
+ }
4427
+ export function parseHubExecutionOutboundMessage(value) {
4428
+ const message = HubExecutionOutboundMessageSchema.parse(value);
4429
+ const payload = message.payload;
4430
+ if ("agent" in payload &&
4431
+ payload.agent !== null &&
4432
+ "agentId" in payload &&
4433
+ payload.agentId !== null &&
4434
+ payload.agent.id !== payload.agentId) {
4435
+ throw new HubMessageCorrelationError(message.type);
4436
+ }
4437
+ return message;
4438
+ }
3865
4439
  export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
4440
+ HubExecutionAgentCreateResponseSchema,
4441
+ HubExecutionAgentUpdateSchema,
4442
+ HubExecutionAgentStreamSchema,
3866
4443
  BrowserAutomationExecuteRequestSchema,
3867
4444
  ActivityLogMessageSchema,
3868
4445
  AssistantChunkMessageSchema,
@@ -3880,6 +4457,7 @@ export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
3880
4457
  ArtifactMessageSchema,
3881
4458
  AgentUpdateMessageSchema,
3882
4459
  WorkspaceUpdateMessageSchema,
4460
+ ProjectUpdateMessageSchema,
3883
4461
  ScriptStatusUpdateMessageSchema,
3884
4462
  WorkspaceSetupProgressMessageSchema,
3885
4463
  WorkspaceSetupStatusResponseMessageSchema,
@@ -3903,6 +4481,8 @@ export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
3903
4481
  ProviderSubagentListResponseMessageSchema,
3904
4482
  ProviderSubagentTimelineResponseMessageSchema,
3905
4483
  ProviderSubagentUpdateMessageSchema,
4484
+ SetAgentTimelineSubscriptionResponseMessageSchema,
4485
+ AgentAttentionRequiredMessageSchema,
3906
4486
  AgentForkContextResponseMessageSchema,
3907
4487
  CancelAgentResponseMessageSchema,
3908
4488
  ClearAgentAttentionResponseMessageSchema,
@@ -3912,6 +4492,9 @@ export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
3912
4492
  SetVoiceModeResponseMessageSchema,
3913
4493
  DaemonGetStatusResponseSchema,
3914
4494
  DaemonGetPairingOfferResponseSchema,
4495
+ HubManagementDaemonConnectResponseSchema,
4496
+ HubManagementDaemonGetStatusResponseSchema,
4497
+ HubManagementDaemonDisconnectResponseSchema,
3915
4498
  DiagnosticsResponseSchema,
3916
4499
  GetDaemonConfigResponseMessageSchema,
3917
4500
  SetDaemonConfigResponseMessageSchema,
@@ -3928,6 +4511,8 @@ export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
3928
4511
  ProjectRemoveResponseSchema,
3929
4512
  WorkspaceTitleSetResponseSchema,
3930
4513
  WorkspacePinSetResponseSchema,
4514
+ WorkspaceRecoveryInspectResponseSchema,
4515
+ WorkspaceRecoveryRestoreResponseSchema,
3931
4516
  WaitForFinishResponseMessageSchema,
3932
4517
  AgentPermissionRequestMessageSchema,
3933
4518
  AgentPermissionResolvedMessageSchema,
@@ -3946,7 +4531,11 @@ export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
3946
4531
  CheckoutRefreshResponseSchema,
3947
4532
  CheckoutPrCreateResponseSchema,
3948
4533
  CheckoutPrMergeResponseSchema,
4534
+ CheckoutForgeSetAutoMergeResponseSchema,
3949
4535
  CheckoutGithubSetAutoMergeResponseSchema,
4536
+ CheckoutCommitsListResponseSchema,
4537
+ CheckoutCommitFileDiffResponseSchema,
4538
+ CheckoutForgeGetCheckDetailsResponseSchema,
3950
4539
  CheckoutGithubGetCheckDetailsResponseSchema,
3951
4540
  CheckoutPrStatusResponseSchema,
3952
4541
  PullRequestTimelineResponseSchema,
@@ -3957,12 +4546,17 @@ export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
3957
4546
  StashListResponseSchema,
3958
4547
  ValidateBranchResponseSchema,
3959
4548
  BranchSuggestionsResponseSchema,
4549
+ ForgeSearchResponseSchema,
3960
4550
  GitHubSearchResponseSchema,
3961
4551
  DirectorySuggestionsResponseSchema,
3962
4552
  PaseoWorktreeListResponseSchema,
3963
4553
  PaseoWorktreeArchiveResponseSchema,
3964
4554
  CreatePaseoWorktreeResponseSchema,
3965
4555
  FileExplorerResponseSchema,
4556
+ FileSubscribeResponseSchema,
4557
+ FileUnsubscribeResponseSchema,
4558
+ FileWriteResponseSchema,
4559
+ FileUpdateSchema,
3966
4560
  ProjectIconResponseSchema,
3967
4561
  FileDownloadTokenResponseSchema,
3968
4562
  FileUploadResponseSchema,
@@ -4030,9 +4624,11 @@ export const WSHelloMessageSchema = z.object({
4030
4624
  voice: z.boolean().optional(),
4031
4625
  pushNotifications: z.boolean().optional(),
4032
4626
  [CLIENT_CAPS.reasoningMergeEnum]: z.boolean().optional(),
4627
+ [CLIENT_CAPS.selectiveAgentTimeline]: z.boolean().optional(),
4033
4628
  [CLIENT_CAPS.customModeIcons]: z.boolean().optional(),
4034
4629
  [CLIENT_CAPS.terminalReflowableSnapshot]: z.boolean().optional(),
4035
4630
  [CLIENT_CAPS.providerSubagents]: z.boolean().optional(),
4631
+ [CLIENT_CAPS.projectUpdates]: z.boolean().optional(),
4036
4632
  [CLIENT_CAPS.browserHost]: BrowserAutomationHostCapabilitySchema.optional(),
4037
4633
  })
4038
4634
  .passthrough()