@otto-code/client 0.8.18 → 0.9.0

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.
@@ -253,6 +253,35 @@ function unwrapBrainJob(payload) {
253
253
  // A repo clone can take minutes on a large history, so it gets its own budget
254
254
  // rather than the default request timeout.
255
255
  const PROJECT_GITHUB_CLONE_TIMEOUT_MS = 5 * 60 * 1000;
256
+ function buildWorkflowStartRequest(input) {
257
+ return {
258
+ flavor: input.flavor,
259
+ cwd: input.cwd,
260
+ ...(input.workspaceId !== undefined ? { workspaceId: input.workspaceId } : {}),
261
+ ...(input.title !== undefined ? { title: input.title } : {}),
262
+ ...(input.description !== undefined ? { description: input.description } : {}),
263
+ ...(input.orchestratorPersonalityId !== undefined
264
+ ? { orchestratorPersonalityId: input.orchestratorPersonalityId }
265
+ : {}),
266
+ ...(input.orchestratorProvider !== undefined
267
+ ? { orchestratorProvider: input.orchestratorProvider }
268
+ : {}),
269
+ ...(input.orchestratorModel !== undefined
270
+ ? { orchestratorModel: input.orchestratorModel }
271
+ : {}),
272
+ ...(input.orchestratorThinkingOptionId !== undefined
273
+ ? { orchestratorThinkingOptionId: input.orchestratorThinkingOptionId }
274
+ : {}),
275
+ ...(input.prompt !== undefined ? { prompt: input.prompt } : {}),
276
+ ...(input.graphId !== undefined ? { graphId: input.graphId } : {}),
277
+ ...(input.graphInputs !== undefined ? { graphInputs: input.graphInputs } : {}),
278
+ ...(input.startConfirmationToken !== undefined
279
+ ? { startConfirmationToken: input.startConfirmationToken }
280
+ : {}),
281
+ ...(input.draft !== undefined ? { draft: input.draft } : {}),
282
+ ...(input.runId !== undefined ? { runId: input.runId } : {}),
283
+ };
284
+ }
256
285
  export class DaemonClient {
257
286
  constructor(config) {
258
287
  this.config = config;
@@ -1061,6 +1090,7 @@ export class DaemonClient {
1061
1090
  ...(options?.sort ? { sort: options.sort } : {}),
1062
1091
  ...(options?.page ? { page: options.page } : {}),
1063
1092
  ...(options?.subscribe ? { subscribe: options.subscribe } : {}),
1093
+ ...(options?.sync ? { sync: options.sync } : {}),
1064
1094
  });
1065
1095
  return this.sendRequest({
1066
1096
  requestId: resolvedRequestId,
@@ -1143,6 +1173,7 @@ export class DaemonClient {
1143
1173
  ...(options?.sort ? { sort: options.sort } : {}),
1144
1174
  ...(options?.page ? { page: options.page } : {}),
1145
1175
  ...(options?.subscribe ? { subscribe: options.subscribe } : {}),
1176
+ ...(options?.sync ? { sync: options.sync } : {}),
1146
1177
  });
1147
1178
  return this.sendRequest({
1148
1179
  requestId: resolvedRequestId,
@@ -1159,6 +1190,74 @@ export class DaemonClient {
1159
1190
  },
1160
1191
  });
1161
1192
  }
1193
+ listWorkspaceLabels(options) {
1194
+ return this.sendNamespacedCorrelatedSessionRequest({
1195
+ requestId: options.requestId,
1196
+ message: {
1197
+ type: "workspace.label.list.request",
1198
+ subscribe: { subscriptionId: options.subscriptionId },
1199
+ ...(options.sync ? { sync: options.sync } : {}),
1200
+ },
1201
+ });
1202
+ }
1203
+ setWorkspaceLabel(options) {
1204
+ return this.sendNamespacedCorrelatedSessionRequest({
1205
+ requestId: options.requestId,
1206
+ message: {
1207
+ type: "workspace.label.assignment.set.request",
1208
+ workspaceId: options.workspaceId,
1209
+ label: options.label,
1210
+ assigned: options.assigned,
1211
+ },
1212
+ });
1213
+ }
1214
+ updateWorkspaceLabel(options) {
1215
+ return this.sendNamespacedCorrelatedSessionRequest({
1216
+ requestId: options.requestId,
1217
+ message: {
1218
+ type: "workspace.label.update.request",
1219
+ name: options.name,
1220
+ ...(options.newName === undefined ? {} : { newName: options.newName }),
1221
+ ...(options.color === undefined ? {} : { color: options.color }),
1222
+ },
1223
+ });
1224
+ }
1225
+ deleteWorkspaceLabel(options) {
1226
+ return this.sendNamespacedCorrelatedSessionRequest({
1227
+ requestId: options.requestId,
1228
+ message: { type: "workspace.label.delete.request", name: options.name },
1229
+ });
1230
+ }
1231
+ inspectWorkspaceLabelDelete(options) {
1232
+ return this.sendNamespacedCorrelatedSessionRequest({
1233
+ requestId: options.requestId,
1234
+ message: {
1235
+ type: "workspace.label.delete.inspect.request",
1236
+ name: options.name,
1237
+ },
1238
+ });
1239
+ }
1240
+ async listProjects(options) {
1241
+ const requestId = typeof options === "string" ? options : options?.requestId;
1242
+ const resolvedRequestId = this.createRequestId(requestId);
1243
+ const message = SessionInboundMessageSchema.parse({
1244
+ type: "project.list.request",
1245
+ requestId: resolvedRequestId,
1246
+ ...(typeof options === "object" && options.sync ? { sync: options.sync } : {}),
1247
+ });
1248
+ return this.sendRequest({
1249
+ requestId: resolvedRequestId,
1250
+ message,
1251
+ options: { skipQueue: true },
1252
+ select: (msg) => {
1253
+ if (msg.type !== "project.list.response")
1254
+ return null;
1255
+ if (msg.payload.requestId !== resolvedRequestId)
1256
+ return null;
1257
+ return msg.payload;
1258
+ },
1259
+ });
1260
+ }
1162
1261
  async openProject(cwd, requestId) {
1163
1262
  return this.sendCorrelatedSessionRequest({
1164
1263
  requestId,
@@ -1419,6 +1518,9 @@ export class DaemonClient {
1419
1518
  ...(options.personality ? { personality: options.personality } : {}),
1420
1519
  ...(options.env ? { env: options.env } : {}),
1421
1520
  ...(options.workspaceId !== undefined ? { workspaceId: options.workspaceId } : {}),
1521
+ ...(options.architecturalViewDraft
1522
+ ? { architecturalViewDraft: options.architecturalViewDraft }
1523
+ : {}),
1422
1524
  ...(options.callerAgentId !== undefined ? { callerAgentId: options.callerAgentId } : {}),
1423
1525
  ...(options.initialPrompt ? { initialPrompt: options.initialPrompt } : {}),
1424
1526
  ...(options.clientMessageId ? { clientMessageId: options.clientMessageId } : {}),
@@ -1703,6 +1805,26 @@ export class DaemonClient {
1703
1805
  });
1704
1806
  return payload.graphs;
1705
1807
  }
1808
+ /** List saved Workflow Graphs for one project, never the legacy host library. */
1809
+ async listProjectWorkflowGraphs(cwd) {
1810
+ const payload = await this.sendNamespacedCorrelatedSessionRequest({
1811
+ message: { type: "workflows.graphs.list.request", cwd },
1812
+ });
1813
+ if (payload.error !== undefined) {
1814
+ throw new Error(payload.error);
1815
+ }
1816
+ return payload.graphs;
1817
+ }
1818
+ /** Persist a Graph in the selected project Workflow store. */
1819
+ async saveProjectWorkflowGraph(cwd, graph) {
1820
+ const payload = await this.sendNamespacedCorrelatedSessionRequest({
1821
+ message: { type: "workflows.graph.save.request", cwd, graph },
1822
+ });
1823
+ if (payload.error !== undefined || payload.graph === undefined) {
1824
+ throw new Error(payload.error ?? "Project Workflow Graph save rejected");
1825
+ }
1826
+ return payload.graph;
1827
+ }
1706
1828
  /** Orchestration: upsert a graph template. Returns the persisted graph. */
1707
1829
  async saveOrchestrationGraph(graph) {
1708
1830
  const payload = await this.sendNamespacedCorrelatedSessionRequest({
@@ -1723,6 +1845,22 @@ export class DaemonClient {
1723
1845
  }
1724
1846
  return payload.deleted;
1725
1847
  }
1848
+ async exportWorkflowGraph(graphId) {
1849
+ const payload = await this.sendNamespacedCorrelatedSessionRequest({
1850
+ message: { type: "workflows.graph.export.request", graphId },
1851
+ });
1852
+ if (!payload.export)
1853
+ throw new Error(payload.error ?? "Graph export rejected");
1854
+ return payload.export;
1855
+ }
1856
+ async importWorkflowGraph(input) {
1857
+ const payload = await this.sendNamespacedCorrelatedSessionRequest({
1858
+ message: { type: "workflows.graph.import.request", ...input },
1859
+ });
1860
+ if (!payload.result)
1861
+ throw new Error(payload.error ?? "Graph import rejected");
1862
+ return payload.result;
1863
+ }
1726
1864
  /** Orchestration: list the host's reusable prompt templates and snippets. */
1727
1865
  async listPromptTemplates() {
1728
1866
  const payload = await this.sendNamespacedCorrelatedSessionRequest({
@@ -1730,6 +1868,32 @@ export class DaemonClient {
1730
1868
  });
1731
1869
  return payload.templates;
1732
1870
  }
1871
+ async listProjectWorkflowTemplates(cwd) {
1872
+ const payload = await this.sendNamespacedCorrelatedSessionRequest({
1873
+ message: { type: "workflows.templates.list.request", cwd },
1874
+ });
1875
+ if (payload.error !== undefined)
1876
+ throw new Error(payload.error);
1877
+ return payload.templates;
1878
+ }
1879
+ async saveProjectWorkflowTemplate(cwd, template) {
1880
+ const payload = await this.sendNamespacedCorrelatedSessionRequest({
1881
+ message: { type: "workflows.template.save.request", cwd, template },
1882
+ });
1883
+ if (payload.error !== undefined || payload.template === undefined) {
1884
+ throw new Error(payload.error ?? "Project Workflow template save rejected");
1885
+ }
1886
+ return payload.template;
1887
+ }
1888
+ async transferProjectWorkflowRecord(input) {
1889
+ const payload = await this.sendNamespacedCorrelatedSessionRequest({
1890
+ message: { type: "workflows.storage.transfer.request", ...input },
1891
+ });
1892
+ if (payload.error !== undefined || payload.receipt === undefined) {
1893
+ throw new Error(payload.error ?? "Project Workflow transfer rejected");
1894
+ }
1895
+ return payload.receipt;
1896
+ }
1733
1897
  /** Orchestration: upsert a prompt template. Returns the persisted template. */
1734
1898
  async savePromptTemplate(template) {
1735
1899
  const payload = await this.sendNamespacedCorrelatedSessionRequest({
@@ -1751,37 +1915,20 @@ export class DaemonClient {
1751
1915
  return payload.deleted;
1752
1916
  }
1753
1917
  /**
1754
- * Orchestration: start (or draft) a user-initiated orchestration. Returns the
1755
- * run id (graph flavor) and the orchestrator chat's agent id to navigate to.
1918
+ * Workflow: start (or draft) a user-initiated Workflow. Returns the workflow
1919
+ * id (graph flavor) and the orchestrator chat's agent id to navigate to.
1756
1920
  */
1757
- async startOrchestration(input) {
1758
- const payload = await this.sendNamespacedCorrelatedSessionRequest({
1759
- message: {
1760
- type: "runs.start.request",
1761
- flavor: input.flavor,
1762
- cwd: input.cwd,
1763
- ...(input.workspaceId !== undefined ? { workspaceId: input.workspaceId } : {}),
1764
- ...(input.title !== undefined ? { title: input.title } : {}),
1765
- ...(input.description !== undefined ? { description: input.description } : {}),
1766
- ...(input.orchestratorPersonalityId !== undefined
1767
- ? { orchestratorPersonalityId: input.orchestratorPersonalityId }
1768
- : {}),
1769
- ...(input.orchestratorProvider !== undefined
1770
- ? { orchestratorProvider: input.orchestratorProvider }
1771
- : {}),
1772
- ...(input.orchestratorModel !== undefined
1773
- ? { orchestratorModel: input.orchestratorModel }
1774
- : {}),
1775
- ...(input.orchestratorThinkingOptionId !== undefined
1776
- ? { orchestratorThinkingOptionId: input.orchestratorThinkingOptionId }
1777
- : {}),
1778
- ...(input.prompt !== undefined ? { prompt: input.prompt } : {}),
1779
- ...(input.graphId !== undefined ? { graphId: input.graphId } : {}),
1780
- ...(input.graphInputs !== undefined ? { graphInputs: input.graphInputs } : {}),
1781
- ...(input.draft !== undefined ? { draft: input.draft } : {}),
1782
- ...(input.runId !== undefined ? { runId: input.runId } : {}),
1783
- },
1784
- });
1921
+ async startWorkflow(input) {
1922
+ const request = buildWorkflowStartRequest(input);
1923
+ // COMPAT(runsStartRpc): retain the established request against older
1924
+ // daemons until the legacy pair retires after 2027-02-28.
1925
+ const payload = this.lastServerInfoMessage?.features?.workflowStartRpc === true
1926
+ ? await this.sendNamespacedCorrelatedSessionRequest({
1927
+ message: { type: "workflows.start.request", ...request },
1928
+ })
1929
+ : await this.sendNamespacedCorrelatedSessionRequest({
1930
+ message: { type: "runs.start.request", ...request },
1931
+ });
1785
1932
  if (payload.error !== undefined) {
1786
1933
  throw new Error(payload.error);
1787
1934
  }
@@ -1789,8 +1936,19 @@ export class DaemonClient {
1789
1936
  ...(payload.runId !== undefined ? { runId: payload.runId } : {}),
1790
1937
  ...(payload.agentId !== undefined ? { agentId: payload.agentId } : {}),
1791
1938
  ...(payload.workspaceId !== undefined ? { workspaceId: payload.workspaceId } : {}),
1939
+ ...(payload.confirmation !== undefined ? { confirmation: payload.confirmation } : {}),
1940
+ ...(payload.confirmationToken !== undefined
1941
+ ? { confirmationToken: payload.confirmationToken }
1942
+ : {}),
1792
1943
  };
1793
1944
  }
1945
+ /** Answer a daemon-owned AI Workflow start confirmation. */
1946
+ async respondToWorkflowStartConfirmation(input) {
1947
+ const payload = await this.sendNamespacedCorrelatedSessionRequest({
1948
+ message: { type: "workflows.start_confirmation.respond.request", ...input },
1949
+ });
1950
+ return payload.accepted;
1951
+ }
1794
1952
  async updateAgent(agentId, updates) {
1795
1953
  const requestId = this.createRequestId();
1796
1954
  const message = SessionInboundMessageSchema.parse({
@@ -1952,36 +2110,6 @@ export class DaemonClient {
1952
2110
  }
1953
2111
  return { workspaceId: payload.workspaceId };
1954
2112
  }
1955
- async listProjectLinks(requestId) {
1956
- const payload = await this.sendNamespacedCorrelatedSessionRequest({
1957
- requestId,
1958
- message: { type: "project.links.list.request" },
1959
- });
1960
- if (payload.error) {
1961
- throw new Error(payload.error);
1962
- }
1963
- return payload.links;
1964
- }
1965
- async linkProjects(projectId, otherProjectId, requestId) {
1966
- const payload = await this.sendNamespacedCorrelatedSessionRequest({
1967
- requestId,
1968
- message: { type: "project.links.set.request", projectId, otherProjectId },
1969
- });
1970
- if (!payload.accepted) {
1971
- throw new Error(payload.error ?? "linkProjects rejected");
1972
- }
1973
- return payload.links;
1974
- }
1975
- async unlinkProjects(projectId, otherProjectId, requestId) {
1976
- const payload = await this.sendNamespacedCorrelatedSessionRequest({
1977
- requestId,
1978
- message: { type: "project.links.unset.request", projectId, otherProjectId },
1979
- });
1980
- if (!payload.accepted) {
1981
- throw new Error(payload.error ?? "unlinkProjects rejected");
1982
- }
1983
- return payload.links;
1984
- }
1985
2113
  async resumeAgent(handle, overrides) {
1986
2114
  const requestId = this.createRequestId();
1987
2115
  const message = SessionInboundMessageSchema.parse({
@@ -2243,25 +2371,6 @@ export class DaemonClient {
2243
2371
  }
2244
2372
  return { baseRef: payload.baseRef, commits: payload.commits };
2245
2373
  }
2246
- async listProjects(requestId) {
2247
- const resolvedRequestId = this.createRequestId(requestId);
2248
- const message = SessionInboundMessageSchema.parse({
2249
- type: "project.list.request",
2250
- requestId: resolvedRequestId,
2251
- });
2252
- return this.sendRequest({
2253
- requestId: resolvedRequestId,
2254
- message,
2255
- options: { skipQueue: true },
2256
- select: (msg) => {
2257
- if (msg.type !== "project.list.response")
2258
- return null;
2259
- if (msg.payload.requestId !== resolvedRequestId)
2260
- return null;
2261
- return msg.payload;
2262
- },
2263
- });
2264
- }
2265
2374
  onAgentAttentionRequired(handler) {
2266
2375
  const unsubscribeLegacy = this.on("agent_stream", (message) => {
2267
2376
  if (message.payload.event.type !== "attention_required") {
@@ -2473,6 +2582,7 @@ export class DaemonClient {
2473
2582
  agentId,
2474
2583
  text,
2475
2584
  ...(messageId ? { messageId } : {}),
2585
+ ...(options?.activeTurnBehavior ? { activeTurnBehavior: options.activeTurnBehavior } : {}),
2476
2586
  ...(options?.images ? { images: options.images } : {}),
2477
2587
  ...(options?.attachments ? { attachments: options.attachments } : {}),
2478
2588
  ...(options?.delivery ? { delivery: options.delivery } : {}),
@@ -3515,6 +3625,20 @@ export class DaemonClient {
3515
3625
  responseType: "pull_request_timeline_response",
3516
3626
  });
3517
3627
  }
3628
+ /** Requires server_info.features.forgeReviewThreads. */
3629
+ async setHostingPullRequestThreadResolved(input, requestId) {
3630
+ return this.sendNamespacedCorrelatedSessionRequest({
3631
+ requestId,
3632
+ message: { type: "hosting.pull_request_thread.set_resolved.request", ...input },
3633
+ });
3634
+ }
3635
+ /** Requires server_info.features.forgeReviewThreads. */
3636
+ async setHostingPullRequestCommentReaction(input, requestId) {
3637
+ return this.sendNamespacedCorrelatedSessionRequest({
3638
+ requestId,
3639
+ message: { type: "hosting.pull_request_comment.set_reaction.request", ...input },
3640
+ });
3641
+ }
3518
3642
  async checkoutSwitchBranch(cwd, branch, requestId) {
3519
3643
  return this.sendCorrelatedSessionRequest({
3520
3644
  requestId,
@@ -3725,7 +3849,7 @@ export class DaemonClient {
3725
3849
  // ============================================================================
3726
3850
  // File Explorer
3727
3851
  // ============================================================================
3728
- async requestFileExplorer(cwd, path, mode, requestId, acceptBinary = false) {
3852
+ async requestFileExplorer(cwd, path, mode, requestId, acceptBinary = false, maxBytes) {
3729
3853
  return this.sendCorrelatedSessionRequest({
3730
3854
  requestId,
3731
3855
  message: {
@@ -3734,6 +3858,7 @@ export class DaemonClient {
3734
3858
  path,
3735
3859
  mode,
3736
3860
  ...(acceptBinary ? { acceptBinary: true } : {}),
3861
+ ...(maxBytes ? { maxBytes } : {}),
3737
3862
  },
3738
3863
  responseType: "file_explorer_response",
3739
3864
  });
@@ -3748,11 +3873,11 @@ export class DaemonClient {
3748
3873
  }
3749
3874
  return payload.directory;
3750
3875
  }
3751
- async readFile(cwd, path, requestId) {
3876
+ async readFile(cwd, path, requestId, maxBytes) {
3752
3877
  const resolvedRequestId = this.createRequestId(requestId);
3753
- this.pendingBinaryFileReads.set(resolvedRequestId, { cwd, path });
3878
+ this.pendingBinaryFileReads.set(resolvedRequestId, { cwd, path, maxBytes });
3754
3879
  try {
3755
- const payload = await this.requestFileExplorer(cwd, path, "file", resolvedRequestId, true);
3880
+ const payload = await this.requestFileExplorer(cwd, path, "file", resolvedRequestId, true, maxBytes);
3756
3881
  if (payload.error) {
3757
3882
  throw new Error(payload.error);
3758
3883
  }
@@ -4435,6 +4560,20 @@ export class DaemonClient {
4435
4560
  message: { type: "project.knowledge.root.apply.request", ...input },
4436
4561
  });
4437
4562
  }
4563
+ /** Requires server_info.features.projectKnowledgeRefinement. */
4564
+ async applyProjectKnowledgeRefinement(input, requestId) {
4565
+ return this.sendNamespacedCorrelatedSessionRequest({
4566
+ requestId,
4567
+ message: { type: "project.knowledge.refine.apply.request", ...input },
4568
+ });
4569
+ }
4570
+ /** Requires server_info.features.projectKnowledgeAnchoredRefinement. */
4571
+ async proposeProjectKnowledgeRefinement(input, requestId) {
4572
+ return this.sendNamespacedCorrelatedSessionRequest({
4573
+ requestId,
4574
+ message: { type: "project.knowledge.refinement.propose.request", ...input },
4575
+ });
4576
+ }
4438
4577
  async deleteProjectKnowledge(input, requestId) {
4439
4578
  return this.sendNamespacedCorrelatedSessionRequest({
4440
4579
  requestId,
@@ -4612,6 +4751,37 @@ export class DaemonClient {
4612
4751
  timeout: options?.timeout,
4613
4752
  });
4614
4753
  }
4754
+ async reloadDaemonConfig(requestId) {
4755
+ this.requireDaemonConfigReloadSupport();
4756
+ return this.sendNamespacedCorrelatedSessionRequest({
4757
+ requestId,
4758
+ message: { type: "daemon.config.reload.request" },
4759
+ });
4760
+ }
4761
+ async connectHub(hubUrl, token, requestId) {
4762
+ this.requireHubRelationshipSupport();
4763
+ return this.sendCorrelatedSessionRequest({
4764
+ requestId,
4765
+ message: { type: "hub.management.daemon.connect.request", hubUrl, token },
4766
+ responseType: "hub.management.daemon.connect.response",
4767
+ });
4768
+ }
4769
+ async getHubStatus(requestId) {
4770
+ this.requireHubRelationshipSupport();
4771
+ return this.sendCorrelatedSessionRequest({
4772
+ requestId,
4773
+ message: { type: "hub.management.daemon.get_status.request" },
4774
+ responseType: "hub.management.daemon.get_status.response",
4775
+ });
4776
+ }
4777
+ async disconnectHub(force = false, requestId) {
4778
+ this.requireHubRelationshipSupport();
4779
+ return this.sendCorrelatedSessionRequest({
4780
+ requestId,
4781
+ message: { type: "hub.management.daemon.disconnect.request", force },
4782
+ responseType: "hub.management.daemon.disconnect.response",
4783
+ });
4784
+ }
4615
4785
  async getDaemonPairingOffer(options) {
4616
4786
  return this.sendCorrelatedSessionRequest({
4617
4787
  requestId: options?.requestId,
@@ -5551,6 +5721,135 @@ export class DaemonClient {
5551
5721
  response,
5552
5722
  });
5553
5723
  }
5724
+ async getPluginCatalog() {
5725
+ const requestId = this.createRequestId();
5726
+ const payload = await this.sendCorrelatedSessionRequest({
5727
+ requestId,
5728
+ message: { type: "plugin.catalog.get.request", requestId },
5729
+ responseType: "plugin.catalog.get.response",
5730
+ });
5731
+ return payload.plugins;
5732
+ }
5733
+ async listPlugins() {
5734
+ const requestId = this.createRequestId();
5735
+ const payload = await this.sendCorrelatedSessionRequest({
5736
+ requestId,
5737
+ message: { type: "plugin.list.request", requestId },
5738
+ responseType: "plugin.list.response",
5739
+ });
5740
+ return payload.plugins;
5741
+ }
5742
+ async getPluginLogs(pluginId) {
5743
+ const requestId = this.createRequestId();
5744
+ const payload = await this.sendCorrelatedSessionRequest({
5745
+ requestId,
5746
+ message: { type: "plugin.logs.get.request", requestId, pluginId },
5747
+ responseType: "plugin.logs.get.response",
5748
+ });
5749
+ return payload.entries;
5750
+ }
5751
+ async getAgentSkillsStatus() {
5752
+ const requestId = this.createRequestId();
5753
+ return this.sendCorrelatedSessionRequest({
5754
+ message: { type: "agent.skills.get_status.request", requestId },
5755
+ responseType: "agent.skills.get_status.response",
5756
+ });
5757
+ }
5758
+ async reconcileAgentSkills() {
5759
+ const requestId = this.createRequestId();
5760
+ return this.sendCorrelatedSessionRequest({
5761
+ message: { type: "agent.skills.reconcile.request", requestId },
5762
+ responseType: "agent.skills.reconcile.response",
5763
+ });
5764
+ }
5765
+ async uninstallAgentSkills() {
5766
+ const requestId = this.createRequestId();
5767
+ return this.sendCorrelatedSessionRequest({
5768
+ message: { type: "agent.skills.uninstall.request", requestId },
5769
+ responseType: "agent.skills.uninstall.response",
5770
+ });
5771
+ }
5772
+ async saveAgentSkillsSelection(selection, confirmedRemovals) {
5773
+ const requestId = this.createRequestId();
5774
+ return this.sendCorrelatedSessionRequest({
5775
+ message: {
5776
+ type: "agent.skills.save_selection.request",
5777
+ requestId,
5778
+ selection,
5779
+ ...(confirmedRemovals ? { confirmedRemovals: [...confirmedRemovals] } : {}),
5780
+ },
5781
+ responseType: "agent.skills.save_selection.response",
5782
+ });
5783
+ }
5784
+ async importLegacyAgentSkillsSelection(selection) {
5785
+ const requestId = this.createRequestId();
5786
+ return this.sendCorrelatedSessionRequest({
5787
+ message: {
5788
+ type: "agent.skills.import_legacy_selection.request",
5789
+ requestId,
5790
+ selection,
5791
+ },
5792
+ responseType: "agent.skills.import_legacy_selection.response",
5793
+ });
5794
+ }
5795
+ async installDirectoryPlugin(path, id) {
5796
+ const requestId = this.createRequestId();
5797
+ const payload = await this.sendCorrelatedSessionRequest({
5798
+ requestId,
5799
+ message: { type: "plugin.directory.install.request", requestId, path, ...(id ? { id } : {}) },
5800
+ responseType: "plugin.directory.install.response",
5801
+ });
5802
+ return payload.plugin;
5803
+ }
5804
+ async inspectDirectoryPlugin(path) {
5805
+ const requestId = this.createRequestId();
5806
+ return this.sendCorrelatedSessionRequest({
5807
+ requestId,
5808
+ message: { type: "plugin.directory.inspect.request", requestId, path },
5809
+ responseType: "plugin.directory.inspect.response",
5810
+ });
5811
+ }
5812
+ async reloadPlugin(pluginId) {
5813
+ return this.managePlugin("reload", pluginId);
5814
+ }
5815
+ async enablePlugin(pluginId) {
5816
+ return this.managePlugin("enable", pluginId);
5817
+ }
5818
+ async disablePlugin(pluginId) {
5819
+ return this.managePlugin("disable", pluginId);
5820
+ }
5821
+ async removePlugin(pluginId) {
5822
+ const requestId = this.createRequestId();
5823
+ await this.sendCorrelatedSessionRequest({
5824
+ requestId,
5825
+ message: { type: "plugin.remove.request", requestId, pluginId },
5826
+ responseType: "plugin.remove.response",
5827
+ });
5828
+ }
5829
+ async managePlugin(action, pluginId) {
5830
+ const requestId = this.createRequestId();
5831
+ const payload = await this.sendCorrelatedSessionRequest({
5832
+ requestId,
5833
+ message: { type: `plugin.${action}.request`, requestId, pluginId },
5834
+ responseType: `plugin.${action}.response`,
5835
+ });
5836
+ return payload.plugin;
5837
+ }
5838
+ async invokePluginRpc(pluginId, method, input) {
5839
+ const requestId = this.createRequestId();
5840
+ const payload = await this.sendCorrelatedSessionRequest({
5841
+ requestId,
5842
+ message: {
5843
+ type: "plugin.rpc.invoke.request",
5844
+ requestId,
5845
+ pluginId,
5846
+ method,
5847
+ input,
5848
+ },
5849
+ responseType: "plugin.rpc.invoke.response",
5850
+ });
5851
+ return payload.output;
5852
+ }
5554
5853
  async respondToPermissionAndWait(agentId, requestId, response, timeout = 15000) {
5555
5854
  const message = SessionInboundMessageSchema.parse({
5556
5855
  type: "agent_permission_response",
@@ -5976,6 +6275,32 @@ export class DaemonClient {
5976
6275
  responseType: "artifact.list.response",
5977
6276
  });
5978
6277
  }
6278
+ async setProjectArtifactStoreLocation(input) {
6279
+ const payload = await this.sendCorrelatedSessionRequest({
6280
+ requestId: input.requestId,
6281
+ message: {
6282
+ type: "project.artifact.store.set.request",
6283
+ projectId: input.projectId,
6284
+ location: input.location,
6285
+ },
6286
+ responseType: "project.artifact.store.set.response",
6287
+ });
6288
+ if (!payload.accepted)
6289
+ throw new Error(payload.error ?? "Artifact storage update rejected");
6290
+ }
6291
+ /** Requires server_info.features.categoryStorageResolver for Workflows. */
6292
+ async setProjectWorkflowStoreLocation(input) {
6293
+ const payload = await this.sendNamespacedCorrelatedSessionRequest({
6294
+ requestId: input.requestId,
6295
+ message: {
6296
+ type: "project.workflow.store.set.request",
6297
+ projectId: input.projectId,
6298
+ location: input.location,
6299
+ },
6300
+ });
6301
+ if (!payload.accepted)
6302
+ throw new Error(payload.error ?? "Workflow storage update rejected");
6303
+ }
5979
6304
  async artifactCreate(options) {
5980
6305
  return this.sendCorrelatedSessionRequest({
5981
6306
  requestId: options.requestId,
@@ -6064,6 +6389,151 @@ export class DaemonClient {
6064
6389
  responseType: "artifact.get-content.response",
6065
6390
  });
6066
6391
  }
6392
+ async artifactRepair(options) {
6393
+ return this.sendCorrelatedSessionRequest({
6394
+ requestId: options.requestId,
6395
+ message: {
6396
+ type: "artifact.repair.request",
6397
+ artifactId: options.artifactId,
6398
+ },
6399
+ responseType: "artifact.repair.response",
6400
+ });
6401
+ }
6402
+ async artifactGetData(options) {
6403
+ return this.sendCorrelatedSessionRequest({
6404
+ requestId: options.requestId,
6405
+ message: {
6406
+ type: "artifact.data.get.request",
6407
+ artifactId: options.artifactId,
6408
+ },
6409
+ responseType: "artifact.data.get.response",
6410
+ });
6411
+ }
6412
+ async artifactUpdateData(options) {
6413
+ return this.sendCorrelatedSessionRequest({
6414
+ requestId: options.requestId,
6415
+ message: {
6416
+ type: "artifact.data.update.request",
6417
+ artifactId: options.artifactId,
6418
+ data: options.data,
6419
+ },
6420
+ responseType: "artifact.data.update.response",
6421
+ });
6422
+ }
6423
+ async artifactMoveStore(options) {
6424
+ return this.sendCorrelatedSessionRequest({
6425
+ requestId: options.requestId,
6426
+ message: {
6427
+ type: "artifact.store.move.request",
6428
+ artifactId: options.artifactId,
6429
+ destination: options.destination,
6430
+ },
6431
+ responseType: "artifact.store.move.response",
6432
+ });
6433
+ }
6434
+ async deliverArchitecturalView(options) {
6435
+ return this.sendCorrelatedSessionRequest({
6436
+ requestId: options.requestId,
6437
+ message: {
6438
+ type: "architectural-views.deliver.request",
6439
+ workspaceId: options.workspaceId,
6440
+ viewId: options.viewId,
6441
+ title: options.title,
6442
+ knowledgeReferences: options.knowledgeReferences,
6443
+ sourcePath: options.sourcePath,
6444
+ ...(options.quality ? { quality: options.quality } : {}),
6445
+ },
6446
+ responseType: "architectural-views.deliver.response",
6447
+ });
6448
+ }
6449
+ async listArchitecturalViews(options) {
6450
+ return this.sendCorrelatedSessionRequest({
6451
+ requestId: options.requestId,
6452
+ message: {
6453
+ type: "architectural-views.list.request",
6454
+ workspaceId: options.workspaceId,
6455
+ ...(options.knowledgeReference ? { knowledgeReference: options.knowledgeReference } : {}),
6456
+ },
6457
+ responseType: "architectural-views.list.response",
6458
+ });
6459
+ }
6460
+ async getArchitecturalViewContent(options) {
6461
+ return this.sendCorrelatedSessionRequest({
6462
+ requestId: options.requestId,
6463
+ message: {
6464
+ type: "architectural-views.get-content.request",
6465
+ workspaceId: options.workspaceId,
6466
+ viewId: options.viewId,
6467
+ },
6468
+ responseType: "architectural-views.get-content.response",
6469
+ });
6470
+ }
6471
+ async createArchitecturalViewDraft(options) {
6472
+ return this.sendCorrelatedSessionRequest({
6473
+ requestId: options.requestId,
6474
+ message: {
6475
+ type: "architectural-views.draft.create.request",
6476
+ workspaceId: options.workspaceId,
6477
+ viewId: options.viewId,
6478
+ draftId: options.draftId,
6479
+ title: options.title,
6480
+ knowledgeReferences: options.knowledgeReferences,
6481
+ ...(options.sourcePath ? { sourcePath: options.sourcePath } : {}),
6482
+ ...(options.quality ? { quality: options.quality } : {}),
6483
+ },
6484
+ responseType: "architectural-views.draft.create.response",
6485
+ });
6486
+ }
6487
+ async publishArchitecturalViewDraft(options) {
6488
+ return this.sendCorrelatedSessionRequest({
6489
+ requestId: options.requestId,
6490
+ message: {
6491
+ type: "architectural-views.draft.publish.request",
6492
+ workspaceId: options.workspaceId,
6493
+ viewId: options.viewId,
6494
+ draftId: options.draftId,
6495
+ },
6496
+ responseType: "architectural-views.draft.publish.response",
6497
+ });
6498
+ }
6499
+ async updateArchitecturalViewDraft(options) {
6500
+ return this.sendCorrelatedSessionRequest({
6501
+ requestId: options.requestId,
6502
+ message: {
6503
+ type: "architectural-views.draft.update.request",
6504
+ workspaceId: options.workspaceId,
6505
+ viewId: options.viewId,
6506
+ draftId: options.draftId,
6507
+ sourcePath: options.sourcePath,
6508
+ ...(options.quality ? { quality: options.quality } : {}),
6509
+ },
6510
+ responseType: "architectural-views.draft.update.response",
6511
+ });
6512
+ }
6513
+ async discardArchitecturalViewDraft(options) {
6514
+ return this.sendCorrelatedSessionRequest({
6515
+ requestId: options.requestId,
6516
+ message: {
6517
+ type: "architectural-views.draft.discard.request",
6518
+ workspaceId: options.workspaceId,
6519
+ viewId: options.viewId,
6520
+ draftId: options.draftId,
6521
+ },
6522
+ responseType: "architectural-views.draft.discard.response",
6523
+ });
6524
+ }
6525
+ async getArchitecturalViewDraftContent(options) {
6526
+ return this.sendCorrelatedSessionRequest({
6527
+ requestId: options.requestId,
6528
+ message: {
6529
+ type: "architectural-views.draft.get-content.request",
6530
+ workspaceId: options.workspaceId,
6531
+ viewId: options.viewId,
6532
+ draftId: options.draftId,
6533
+ },
6534
+ responseType: "architectural-views.draft.get-content.response",
6535
+ });
6536
+ }
6067
6537
  onTerminalStreamEvent(handler) {
6068
6538
  return this.terminalStreams.onEvent(handler);
6069
6539
  }
@@ -6112,6 +6582,12 @@ export class DaemonClient {
6112
6582
  getInboundDispatchTimings(sinceMs) {
6113
6583
  return this.runtimeMetrics?.getInboundDispatchTimings(sinceMs) ?? [];
6114
6584
  }
6585
+ requireDaemonConfigReloadSupport() {
6586
+ // COMPAT(daemonConfigReload): added in v0.4.0, remove gate after 2027-02-14.
6587
+ if (this.lastServerInfoMessage?.features?.daemonConfigReload !== true) {
6588
+ throw new Error("Update the host to reload daemon configuration.");
6589
+ }
6590
+ }
6115
6591
  resolveTransportUrlForAttempt() {
6116
6592
  return this.config.url;
6117
6593
  }
@@ -6348,9 +6824,31 @@ export class DaemonClient {
6348
6824
  return;
6349
6825
  }
6350
6826
  if (frame.opcode === FileTransferOpcode.FileChunk) {
6827
+ // COMPAT(fileReadByteBudget): added in v0.5.0, remove after 2027-02-21 once daemon floor >= v0.5.0.
6828
+ // Old daemons stream despite maxBytes; discard before client-side accumulation.
6829
+ if (transfer.maxBytes && transfer.size > transfer.maxBytes) {
6830
+ return;
6831
+ }
6351
6832
  transfer.chunks.push(frame.payload);
6352
6833
  return;
6353
6834
  }
6835
+ // COMPAT(fileReadByteBudget): added in v0.5.0, remove after 2027-02-21 once daemon floor >= v0.5.0.
6836
+ if (transfer.maxBytes && transfer.size > transfer.maxBytes) {
6837
+ this.activeBinaryFileTransfers.delete(frame.requestId);
6838
+ this.handleSessionMessage({
6839
+ type: "file_explorer_response",
6840
+ payload: {
6841
+ cwd: transfer.cwd,
6842
+ path: transfer.path,
6843
+ mode: "file",
6844
+ directory: null,
6845
+ file: null,
6846
+ error: "File is too large to display",
6847
+ requestId: frame.requestId,
6848
+ },
6849
+ });
6850
+ return;
6851
+ }
6354
6852
  const bytes = concatByteChunks(transfer.chunks, transfer.size);
6355
6853
  this.activeBinaryFileTransfers.delete(frame.requestId);
6356
6854
  this.completedBinaryFileReads.set(frame.requestId, {
@@ -6754,30 +7252,6 @@ export class DaemonClient {
6754
7252
  responseType: "workspace.script.stop.response",
6755
7253
  });
6756
7254
  }
6757
- async connectHub(hubUrl, token, requestId) {
6758
- this.requireHubRelationshipSupport();
6759
- return this.sendCorrelatedSessionRequest({
6760
- requestId,
6761
- message: { type: "hub.management.daemon.connect.request", hubUrl, token },
6762
- responseType: "hub.management.daemon.connect.response",
6763
- });
6764
- }
6765
- async getHubStatus(requestId) {
6766
- this.requireHubRelationshipSupport();
6767
- return this.sendCorrelatedSessionRequest({
6768
- requestId,
6769
- message: { type: "hub.management.daemon.get_status.request" },
6770
- responseType: "hub.management.daemon.get_status.response",
6771
- });
6772
- }
6773
- async disconnectHub(force = false, requestId) {
6774
- this.requireHubRelationshipSupport();
6775
- return this.sendCorrelatedSessionRequest({
6776
- requestId,
6777
- message: { type: "hub.management.daemon.disconnect.request", force },
6778
- responseType: "hub.management.daemon.disconnect.response",
6779
- });
6780
- }
6781
7255
  requireHubRelationshipSupport() {
6782
7256
  // COMPAT(hubRelationship): added in v0.2.5, drop the gate when floor >= v0.2.5.
6783
7257
  if (this.lastServerInfoMessage?.features?.hubRelationship !== true) {