@getpaseo/server 0.1.63 → 0.1.66

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.
Files changed (265) hide show
  1. package/dist/server/client/daemon-client-transport-types.d.ts +2 -0
  2. package/dist/server/client/daemon-client-transport-types.d.ts.map +1 -1
  3. package/dist/server/client/daemon-client-websocket-transport.d.ts +2 -1
  4. package/dist/server/client/daemon-client-websocket-transport.d.ts.map +1 -1
  5. package/dist/server/client/daemon-client-websocket-transport.js +4 -4
  6. package/dist/server/client/daemon-client-websocket-transport.js.map +1 -1
  7. package/dist/server/client/daemon-client.d.ts +30 -20
  8. package/dist/server/client/daemon-client.d.ts.map +1 -1
  9. package/dist/server/client/daemon-client.js +206 -98
  10. package/dist/server/client/daemon-client.js.map +1 -1
  11. package/dist/server/client/terminal-stream-router.d.ts +24 -0
  12. package/dist/server/client/terminal-stream-router.d.ts.map +1 -0
  13. package/dist/server/client/terminal-stream-router.js +100 -0
  14. package/dist/server/client/terminal-stream-router.js.map +1 -0
  15. package/dist/server/server/agent/activity-curator.d.ts +6 -3
  16. package/dist/server/server/agent/activity-curator.d.ts.map +1 -1
  17. package/dist/server/server/agent/activity-curator.js +45 -138
  18. package/dist/server/server/agent/activity-curator.js.map +1 -1
  19. package/dist/server/server/agent/agent-manager.d.ts +3 -14
  20. package/dist/server/server/agent/agent-manager.d.ts.map +1 -1
  21. package/dist/server/server/agent/agent-manager.js +75 -140
  22. package/dist/server/server/agent/agent-manager.js.map +1 -1
  23. package/dist/server/server/agent/agent-metadata-generator.d.ts +0 -5
  24. package/dist/server/server/agent/agent-metadata-generator.d.ts.map +1 -1
  25. package/dist/server/server/agent/agent-metadata-generator.js +3 -93
  26. package/dist/server/server/agent/agent-metadata-generator.js.map +1 -1
  27. package/dist/server/server/agent/agent-sdk-types.d.ts +15 -1
  28. package/dist/server/server/agent/agent-sdk-types.d.ts.map +1 -1
  29. package/dist/server/server/agent/agent-stream-coalescer.d.ts +1 -1
  30. package/dist/server/server/agent/agent-stream-coalescer.d.ts.map +1 -1
  31. package/dist/server/server/agent/agent-stream-coalescer.js +1 -1
  32. package/dist/server/server/agent/agent-stream-coalescer.js.map +1 -1
  33. package/dist/server/server/agent/agent-timeline-store.d.ts.map +1 -1
  34. package/dist/server/server/agent/agent-timeline-store.js +29 -32
  35. package/dist/server/server/agent/agent-timeline-store.js.map +1 -1
  36. package/dist/server/server/agent/foreground-run-state.d.ts +50 -0
  37. package/dist/server/server/agent/foreground-run-state.d.ts.map +1 -0
  38. package/dist/server/server/agent/foreground-run-state.js +162 -0
  39. package/dist/server/server/agent/foreground-run-state.js.map +1 -0
  40. package/dist/server/server/agent/mcp-server.d.ts +5 -3
  41. package/dist/server/server/agent/mcp-server.d.ts.map +1 -1
  42. package/dist/server/server/agent/mcp-server.js +110 -99
  43. package/dist/server/server/agent/mcp-server.js.map +1 -1
  44. package/dist/server/server/agent/mcp-shared.d.ts.map +1 -1
  45. package/dist/server/server/agent/mcp-shared.js +7 -1
  46. package/dist/server/server/agent/mcp-shared.js.map +1 -1
  47. package/dist/server/server/agent/prompt-attachments.d.ts +4 -3
  48. package/dist/server/server/agent/prompt-attachments.d.ts.map +1 -1
  49. package/dist/server/server/agent/prompt-attachments.js +43 -4
  50. package/dist/server/server/agent/prompt-attachments.js.map +1 -1
  51. package/dist/server/server/agent/provider-manifest.d.ts.map +1 -1
  52. package/dist/server/server/agent/provider-manifest.js +7 -0
  53. package/dist/server/server/agent/provider-manifest.js.map +1 -1
  54. package/dist/server/server/agent/providers/acp-agent.d.ts +38 -1
  55. package/dist/server/server/agent/providers/acp-agent.d.ts.map +1 -1
  56. package/dist/server/server/agent/providers/acp-agent.js +257 -140
  57. package/dist/server/server/agent/providers/acp-agent.js.map +1 -1
  58. package/dist/server/server/agent/providers/claude/sidechain-tracker.d.ts.map +1 -1
  59. package/dist/server/server/agent/providers/claude/sidechain-tracker.js +1 -1
  60. package/dist/server/server/agent/providers/claude/sidechain-tracker.js.map +1 -1
  61. package/dist/server/server/agent/providers/claude/tool-call-mapper.d.ts.map +1 -1
  62. package/dist/server/server/agent/providers/claude/tool-call-mapper.js +68 -198
  63. package/dist/server/server/agent/providers/claude/tool-call-mapper.js.map +1 -1
  64. package/dist/server/server/agent/providers/claude-agent.d.ts.map +1 -1
  65. package/dist/server/server/agent/providers/claude-agent.js +52 -102
  66. package/dist/server/server/agent/providers/claude-agent.js.map +1 -1
  67. package/dist/server/server/agent/providers/codex/tool-call-mapper.d.ts.map +1 -1
  68. package/dist/server/server/agent/providers/codex/tool-call-mapper.js +125 -141
  69. package/dist/server/server/agent/providers/codex/tool-call-mapper.js.map +1 -1
  70. package/dist/server/server/agent/providers/codex-app-server-agent.d.ts +36 -6
  71. package/dist/server/server/agent/providers/codex-app-server-agent.d.ts.map +1 -1
  72. package/dist/server/server/agent/providers/codex-app-server-agent.js +374 -219
  73. package/dist/server/server/agent/providers/codex-app-server-agent.js.map +1 -1
  74. package/dist/server/server/agent/providers/mock-load-test-agent.d.ts +6 -2
  75. package/dist/server/server/agent/providers/mock-load-test-agent.d.ts.map +1 -1
  76. package/dist/server/server/agent/providers/mock-load-test-agent.js +294 -113
  77. package/dist/server/server/agent/providers/mock-load-test-agent.js.map +1 -1
  78. package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.d.ts +1 -1
  79. package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.d.ts.map +1 -1
  80. package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.js +94 -2
  81. package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.js.map +1 -1
  82. package/dist/server/server/agent/providers/opencode/tool-call-mapper.d.ts.map +1 -1
  83. package/dist/server/server/agent/providers/opencode/tool-call-mapper.js +24 -115
  84. package/dist/server/server/agent/providers/opencode/tool-call-mapper.js.map +1 -1
  85. package/dist/server/server/agent/providers/opencode-agent.d.ts +102 -1
  86. package/dist/server/server/agent/providers/opencode-agent.d.ts.map +1 -1
  87. package/dist/server/server/agent/providers/opencode-agent.js +416 -158
  88. package/dist/server/server/agent/providers/opencode-agent.js.map +1 -1
  89. package/dist/server/server/agent/providers/provider-runner.d.ts +27 -0
  90. package/dist/server/server/agent/providers/provider-runner.d.ts.map +1 -0
  91. package/dist/server/server/agent/providers/provider-runner.js +80 -0
  92. package/dist/server/server/agent/providers/provider-runner.js.map +1 -0
  93. package/dist/server/server/agent/providers/tool-call-detail-primitives.d.ts +6 -3
  94. package/dist/server/server/agent/providers/tool-call-detail-primitives.d.ts.map +1 -1
  95. package/dist/server/server/agent/providers/tool-call-mapper-utils.d.ts +2 -0
  96. package/dist/server/server/agent/providers/tool-call-mapper-utils.d.ts.map +1 -1
  97. package/dist/server/server/agent/providers/tool-call-mapper-utils.js +31 -0
  98. package/dist/server/server/agent/providers/tool-call-mapper-utils.js.map +1 -1
  99. package/dist/server/server/agent/timeline-projection.d.ts +21 -5
  100. package/dist/server/server/agent/timeline-projection.d.ts.map +1 -1
  101. package/dist/server/server/agent/timeline-projection.js +59 -9
  102. package/dist/server/server/agent/timeline-projection.js.map +1 -1
  103. package/dist/server/server/auth.d.ts +25 -0
  104. package/dist/server/server/auth.d.ts.map +1 -0
  105. package/dist/server/server/auth.js +93 -0
  106. package/dist/server/server/auth.js.map +1 -0
  107. package/dist/server/server/bootstrap.d.ts +3 -1
  108. package/dist/server/server/bootstrap.d.ts.map +1 -1
  109. package/dist/server/server/bootstrap.js +87 -30
  110. package/dist/server/server/bootstrap.js.map +1 -1
  111. package/dist/server/server/config.d.ts.map +1 -1
  112. package/dist/server/server/config.js +11 -0
  113. package/dist/server/server/config.js.map +1 -1
  114. package/dist/server/server/exports.d.ts +7 -1
  115. package/dist/server/server/exports.d.ts.map +1 -1
  116. package/dist/server/server/exports.js +6 -1
  117. package/dist/server/server/exports.js.map +1 -1
  118. package/dist/server/server/file-explorer/service.d.ts +10 -0
  119. package/dist/server/server/file-explorer/service.d.ts.map +1 -1
  120. package/dist/server/server/file-explorer/service.js +38 -4
  121. package/dist/server/server/file-explorer/service.js.map +1 -1
  122. package/dist/server/server/index.js +9 -6
  123. package/dist/server/server/index.js.map +1 -1
  124. package/dist/server/server/logger.d.ts.map +1 -1
  125. package/dist/server/server/logger.js +15 -1
  126. package/dist/server/server/logger.js.map +1 -1
  127. package/dist/server/server/pagination/cursor.d.ts +16 -0
  128. package/dist/server/server/pagination/cursor.d.ts.map +1 -0
  129. package/dist/server/server/pagination/cursor.js +62 -0
  130. package/dist/server/server/pagination/cursor.js.map +1 -0
  131. package/dist/server/server/pagination/sortable-pager.d.ts +24 -0
  132. package/dist/server/server/pagination/sortable-pager.d.ts.map +1 -0
  133. package/dist/server/server/pagination/sortable-pager.js +68 -0
  134. package/dist/server/server/pagination/sortable-pager.js.map +1 -0
  135. package/dist/server/server/paseo-worktree-archive-service.d.ts +3 -1
  136. package/dist/server/server/paseo-worktree-archive-service.d.ts.map +1 -1
  137. package/dist/server/server/paseo-worktree-archive-service.js +61 -53
  138. package/dist/server/server/paseo-worktree-archive-service.js.map +1 -1
  139. package/dist/server/server/paseo-worktree-service.d.ts +13 -0
  140. package/dist/server/server/paseo-worktree-service.d.ts.map +1 -1
  141. package/dist/server/server/paseo-worktree-service.js +72 -3
  142. package/dist/server/server/paseo-worktree-service.js.map +1 -1
  143. package/dist/server/server/persisted-config.d.ts +25 -0
  144. package/dist/server/server/persisted-config.d.ts.map +1 -1
  145. package/dist/server/server/persisted-config.js +9 -0
  146. package/dist/server/server/persisted-config.js.map +1 -1
  147. package/dist/server/server/relay-transport.d.ts.map +1 -1
  148. package/dist/server/server/relay-transport.js +16 -4
  149. package/dist/server/server/relay-transport.js.map +1 -1
  150. package/dist/server/server/resolve-worktree-creation-intent.d.ts +0 -10
  151. package/dist/server/server/resolve-worktree-creation-intent.d.ts.map +1 -1
  152. package/dist/server/server/resolve-worktree-creation-intent.js +1 -45
  153. package/dist/server/server/resolve-worktree-creation-intent.js.map +1 -1
  154. package/dist/server/server/script-status-projection.d.ts +6 -1
  155. package/dist/server/server/script-status-projection.d.ts.map +1 -1
  156. package/dist/server/server/script-status-projection.js +12 -3
  157. package/dist/server/server/script-status-projection.js.map +1 -1
  158. package/dist/server/server/session.d.ts +19 -51
  159. package/dist/server/server/session.d.ts.map +1 -1
  160. package/dist/server/server/session.js +354 -1069
  161. package/dist/server/server/session.js.map +1 -1
  162. package/dist/server/server/websocket-server.d.ts +4 -2
  163. package/dist/server/server/websocket-server.d.ts.map +1 -1
  164. package/dist/server/server/websocket-server.js +65 -12
  165. package/dist/server/server/websocket-server.js.map +1 -1
  166. package/dist/server/server/workspace-directory.d.ts +69 -0
  167. package/dist/server/server/workspace-directory.d.ts.map +1 -0
  168. package/dist/server/server/workspace-directory.js +229 -0
  169. package/dist/server/server/workspace-directory.js.map +1 -0
  170. package/dist/server/server/worktree-bootstrap.d.ts.map +1 -1
  171. package/dist/server/server/worktree-bootstrap.js +6 -2
  172. package/dist/server/server/worktree-bootstrap.js.map +1 -1
  173. package/dist/server/server/worktree-core.d.ts +2 -0
  174. package/dist/server/server/worktree-core.d.ts.map +1 -1
  175. package/dist/server/server/worktree-core.js.map +1 -1
  176. package/dist/server/server/worktree-errors.d.ts +1 -1
  177. package/dist/server/server/worktree-errors.d.ts.map +1 -1
  178. package/dist/server/server/worktree-errors.js +1 -4
  179. package/dist/server/server/worktree-errors.js.map +1 -1
  180. package/dist/server/server/worktree-session.d.ts +47 -20
  181. package/dist/server/server/worktree-session.d.ts.map +1 -1
  182. package/dist/server/server/worktree-session.js +68 -25
  183. package/dist/server/server/worktree-session.js.map +1 -1
  184. package/dist/server/shared/binary-frames/file-transfer.d.ts +56 -0
  185. package/dist/server/shared/binary-frames/file-transfer.d.ts.map +1 -0
  186. package/dist/server/shared/binary-frames/file-transfer.js +108 -0
  187. package/dist/server/shared/binary-frames/file-transfer.js.map +1 -0
  188. package/dist/server/shared/binary-frames/index.d.ts +3 -0
  189. package/dist/server/shared/binary-frames/index.d.ts.map +1 -0
  190. package/dist/server/shared/binary-frames/index.js +3 -0
  191. package/dist/server/shared/binary-frames/index.js.map +1 -0
  192. package/dist/server/shared/{terminal-stream-protocol.d.ts → binary-frames/terminal.d.ts} +2 -2
  193. package/dist/server/shared/binary-frames/terminal.d.ts.map +1 -0
  194. package/dist/server/shared/{terminal-stream-protocol.js → binary-frames/terminal.js} +2 -2
  195. package/dist/server/shared/binary-frames/terminal.js.map +1 -0
  196. package/dist/server/shared/client-capabilities.d.ts +5 -0
  197. package/dist/server/shared/client-capabilities.d.ts.map +1 -0
  198. package/dist/server/shared/client-capabilities.js +4 -0
  199. package/dist/server/shared/client-capabilities.js.map +1 -0
  200. package/dist/server/shared/connection-offer.d.ts +8 -0
  201. package/dist/server/shared/connection-offer.d.ts.map +1 -1
  202. package/dist/server/shared/connection-offer.js +35 -0
  203. package/dist/server/shared/connection-offer.js.map +1 -1
  204. package/dist/server/shared/daemon-endpoints.d.ts +16 -1
  205. package/dist/server/shared/daemon-endpoints.d.ts.map +1 -1
  206. package/dist/server/shared/daemon-endpoints.js +65 -6
  207. package/dist/server/shared/daemon-endpoints.js.map +1 -1
  208. package/dist/server/shared/host-connection-schema.d.ts +23 -0
  209. package/dist/server/shared/host-connection-schema.d.ts.map +1 -0
  210. package/dist/server/shared/host-connection-schema.js +9 -0
  211. package/dist/server/shared/host-connection-schema.js.map +1 -0
  212. package/dist/server/shared/messages.d.ts +3242 -535
  213. package/dist/server/shared/messages.d.ts.map +1 -1
  214. package/dist/server/shared/messages.js +73 -34
  215. package/dist/server/shared/messages.js.map +1 -1
  216. package/dist/server/terminal/terminal-manager-factory.d.ts +7 -0
  217. package/dist/server/terminal/terminal-manager-factory.d.ts.map +1 -0
  218. package/dist/server/terminal/terminal-manager-factory.js +13 -0
  219. package/dist/server/terminal/terminal-manager-factory.js.map +1 -0
  220. package/dist/server/terminal/terminal-manager.d.ts +7 -1
  221. package/dist/server/terminal/terminal-manager.d.ts.map +1 -1
  222. package/dist/server/terminal/terminal-manager.js +14 -1
  223. package/dist/server/terminal/terminal-manager.js.map +1 -1
  224. package/dist/server/terminal/terminal-session-controller.d.ts +63 -0
  225. package/dist/server/terminal/terminal-session-controller.d.ts.map +1 -0
  226. package/dist/server/terminal/terminal-session-controller.js +615 -0
  227. package/dist/server/terminal/terminal-session-controller.js.map +1 -0
  228. package/dist/server/terminal/terminal-ts-loader.mjs +20 -0
  229. package/dist/server/terminal/terminal-worker-process.d.ts +2 -0
  230. package/dist/server/terminal/terminal-worker-process.d.ts.map +1 -0
  231. package/dist/server/terminal/terminal-worker-process.js +221 -0
  232. package/dist/server/terminal/terminal-worker-process.js.map +1 -0
  233. package/dist/server/terminal/terminal-worker-protocol.d.ts +113 -0
  234. package/dist/server/terminal/terminal-worker-protocol.d.ts.map +1 -0
  235. package/dist/server/terminal/terminal-worker-protocol.js +2 -0
  236. package/dist/server/terminal/terminal-worker-protocol.js.map +1 -0
  237. package/dist/server/terminal/terminal.d.ts +7 -0
  238. package/dist/server/terminal/terminal.d.ts.map +1 -1
  239. package/dist/server/terminal/terminal.js +45 -9
  240. package/dist/server/terminal/terminal.js.map +1 -1
  241. package/dist/server/terminal/worker-terminal-manager.d.ts +19 -0
  242. package/dist/server/terminal/worker-terminal-manager.d.ts.map +1 -0
  243. package/dist/server/terminal/worker-terminal-manager.js +466 -0
  244. package/dist/server/terminal/worker-terminal-manager.js.map +1 -0
  245. package/dist/server/utils/directory-suggestions.d.ts.map +1 -1
  246. package/dist/server/utils/directory-suggestions.js +10 -1
  247. package/dist/server/utils/directory-suggestions.js.map +1 -1
  248. package/dist/server/utils/process-tree.d.ts +25 -0
  249. package/dist/server/utils/process-tree.d.ts.map +1 -0
  250. package/dist/server/utils/process-tree.js +96 -0
  251. package/dist/server/utils/process-tree.js.map +1 -0
  252. package/dist/server/utils/windows-command.d.ts.map +1 -1
  253. package/dist/server/utils/windows-command.js +5 -1
  254. package/dist/server/utils/windows-command.js.map +1 -1
  255. package/dist/server/utils/worktree-metadata.d.ts +44 -0
  256. package/dist/server/utils/worktree-metadata.d.ts.map +1 -1
  257. package/dist/server/utils/worktree-metadata.js +58 -0
  258. package/dist/server/utils/worktree-metadata.js.map +1 -1
  259. package/dist/server/utils/worktree.d.ts +14 -2
  260. package/dist/server/utils/worktree.d.ts.map +1 -1
  261. package/dist/server/utils/worktree.js +22 -13
  262. package/dist/server/utils/worktree.js.map +1 -1
  263. package/package.json +5 -4
  264. package/dist/server/shared/terminal-stream-protocol.d.ts.map +0 -1
  265. package/dist/server/shared/terminal-stream-protocol.js.map +0 -1
@@ -5,6 +5,7 @@ import { Readable, Writable } from "node:stream";
5
5
  import { ClientSideConnection, PROTOCOL_VERSION, } from "@agentclientprotocol/sdk";
6
6
  import { createProviderEnvSpec, resolveProviderCommandPrefix, } from "../provider-launch-config.js";
7
7
  import { renderPromptAttachmentAsText } from "../prompt-attachments.js";
8
+ import { appendOrReplaceGrowingAssistantMessage, runProviderTurn } from "./provider-runner.js";
8
9
  import { findExecutable } from "../../../utils/executable.js";
9
10
  import { spawnProcess } from "../../../utils/spawn.js";
10
11
  const DEFAULT_ACP_CAPABILITIES = {
@@ -22,7 +23,6 @@ const ACP_CLIENT_CAPABILITIES = {
22
23
  },
23
24
  terminal: true,
24
25
  };
25
- const COPILOT_AUTOPILOT_MODE = "https://agentclientprotocol.com/protocol/session-modes#autopilot";
26
26
  // Suppress interactive auth side-effects (e.g. Gemini CLI opening a Google
27
27
  // sign-in URL in the browser) when probing an ACP agent for models/modes.
28
28
  // NO_BROWSER is honored by Gemini CLI; other ACP agents ignore it.
@@ -99,6 +99,24 @@ export function mapACPUsage(usage) {
99
99
  cachedInputTokens: usage.cachedReadTokens ?? undefined,
100
100
  };
101
101
  }
102
+ export function resolveACPModeSelection({ modeId, availableModes, configOptions, }) {
103
+ const configOption = findSelectConfigOption({ configOptions, category: "mode" });
104
+ return {
105
+ availableMode: availableModes.find((mode) => mode.id === modeId) ?? null,
106
+ configOption,
107
+ configChoice: findSelectConfigChoice({ option: configOption, value: modeId }),
108
+ hasAvailableModes: availableModes.length > 0,
109
+ };
110
+ }
111
+ export function resolveACPModelSelection({ modelId, availableModels, configOptions, }) {
112
+ const configOption = findSelectConfigOption({ configOptions, category: "model" });
113
+ return {
114
+ availableModel: availableModels?.find((model) => model.modelId === modelId) ?? null,
115
+ configOption,
116
+ configChoice: findSelectConfigChoice({ option: configOption, value: modelId }),
117
+ hasAvailableModels: Boolean(availableModels?.length),
118
+ };
119
+ }
102
120
  export function deriveModesFromACP(fallbackModes, modeState, configOptions) {
103
121
  if (modeState?.availableModes?.length) {
104
122
  return {
@@ -110,8 +128,8 @@ export function deriveModesFromACP(fallbackModes, modeState, configOptions) {
110
128
  currentModeId: modeState.currentModeId ?? null,
111
129
  };
112
130
  }
113
- const modeOption = configOptions?.find((option) => option.type === "select" && option.category === "mode");
114
- if (modeOption?.type === "select") {
131
+ const modeOption = findSelectConfigOption({ configOptions, category: "mode" });
132
+ if (modeOption) {
115
133
  const flatOptions = flattenSelectOptions(modeOption.options);
116
134
  return {
117
135
  modes: flatOptions.map((option) => ({
@@ -407,6 +425,7 @@ export class ACPAgentSession {
407
425
  this.sessionId = null;
408
426
  this.currentMode = null;
409
427
  this.currentModel = null;
428
+ this.availableModels = null;
410
429
  this.thinkingOptionId = null;
411
430
  this.currentTitle = null;
412
431
  this.lastActivityAt = null;
@@ -496,79 +515,18 @@ export class ACPAgentSession {
496
515
  await this.applyConfiguredOverrides();
497
516
  }
498
517
  async run(prompt, options) {
499
- const timeline = [];
500
- let finalText = "";
501
- let usage;
502
- let turnId = null;
503
- let settled = false;
504
- let resolveCompletion;
505
- let rejectCompletion;
506
- const buffered = [];
507
- const completion = new Promise((resolve, reject) => {
508
- resolveCompletion = resolve;
509
- rejectCompletion = reject;
518
+ const result = await runProviderTurn({
519
+ prompt,
520
+ runOptions: options,
521
+ startTurn: (p, o) => this.startTurn(p, o),
522
+ subscribe: (callback) => this.subscribe(callback),
523
+ getSessionId: () => this.sessionId ?? "",
524
+ reduceFinalText: appendOrReplaceGrowingAssistantMessage,
510
525
  });
511
- const processEvent = (event) => {
512
- if (settled) {
513
- return;
514
- }
515
- if (turnId && "turnId" in event && event.turnId && event.turnId !== turnId) {
516
- return;
517
- }
518
- if (event.type === "timeline") {
519
- timeline.push(event.item);
520
- if (event.item.type === "assistant_message") {
521
- finalText = event.item.text.startsWith(finalText)
522
- ? event.item.text
523
- : `${finalText}${event.item.text}`;
524
- }
525
- return;
526
- }
527
- if (event.type === "turn_completed") {
528
- usage = event.usage;
529
- settled = true;
530
- resolveCompletion();
531
- return;
532
- }
533
- if (event.type === "turn_failed") {
534
- settled = true;
535
- rejectCompletion(new Error(event.error));
536
- return;
537
- }
538
- if (event.type === "turn_canceled") {
539
- settled = true;
540
- resolveCompletion();
541
- }
542
- };
543
- const unsubscribe = this.subscribe((event) => {
544
- if (!turnId) {
545
- buffered.push(event);
546
- return;
547
- }
548
- processEvent(event);
549
- });
550
- try {
551
- const started = await this.startTurn(prompt, options);
552
- turnId = started.turnId;
553
- for (const event of buffered) {
554
- processEvent(event);
555
- }
556
- if (!settled) {
557
- await completion;
558
- }
559
- }
560
- finally {
561
- unsubscribe();
562
- }
563
526
  if (!this.sessionId) {
564
527
  throw new Error("ACP session did not expose a session id");
565
528
  }
566
- return {
567
- sessionId: this.sessionId,
568
- finalText,
569
- usage,
570
- timeline,
571
- };
529
+ return result;
572
530
  }
573
531
  async startTurn(prompt, _options) {
574
532
  if (this.closed) {
@@ -634,17 +592,7 @@ export class ACPAgentSession {
634
592
  }
635
593
  }
636
594
  async getRuntimeInfo() {
637
- return {
638
- provider: this.provider,
639
- sessionId: this.sessionId,
640
- model: this.currentModel,
641
- thinkingOptionId: this.thinkingOptionId,
642
- modeId: this.currentMode,
643
- extra: {
644
- title: this.currentTitle,
645
- updatedAt: this.lastActivityAt,
646
- },
647
- };
595
+ return this.runtimeInfo();
648
596
  }
649
597
  async getAvailableModes() {
650
598
  return [...this.availableModes];
@@ -706,25 +654,64 @@ export class ACPAgentSession {
706
654
  if (!this.connection || !this.sessionId) {
707
655
  throw new Error("ACP session not initialized");
708
656
  }
709
- const modeExists = this.availableModes.some((mode) => mode.id === modeId);
710
- if (!modeExists && this.availableModes.length > 0) {
711
- throw new Error(`Unknown ${this.provider} mode '${modeId}'`);
657
+ const selection = resolveACPModeSelection({
658
+ modeId,
659
+ availableModes: this.availableModes,
660
+ configOptions: this.configOptions,
661
+ });
662
+ await this.setModeWithSelection({ modeId, selection });
663
+ }
664
+ // Mode/model selection updates stay after ACP RPC success; this intentionally diverges from Zed's optimistic rollback path (acp.rs:3080-3104).
665
+ async setModeWithSelection({ modeId, selection, }) {
666
+ if (!this.connection || !this.sessionId) {
667
+ throw new Error("ACP session not initialized");
712
668
  }
713
- if (this.availableModes.length > 0) {
669
+ if (selection.hasAvailableModes) {
670
+ if (!selection.availableMode) {
671
+ this.warnInvalidSelection(modeId, `is not valid ${this.provider} mode. Available options: ${this.availableModes
672
+ .map((mode) => mode.id)
673
+ .join(", ")}`);
674
+ return;
675
+ }
714
676
  await this.connection.setSessionMode({ sessionId: this.sessionId, modeId });
715
677
  this.currentMode = modeId;
678
+ this.pushEvent({
679
+ type: "mode_changed",
680
+ provider: this.provider,
681
+ currentModeId: this.currentMode,
682
+ availableModes: [...this.availableModes],
683
+ });
716
684
  return;
717
685
  }
718
- const modeOption = this.getSelectConfigOption("mode");
686
+ const modeOption = selection.configOption;
719
687
  if (!modeOption) {
720
688
  throw new Error(`${this.provider} does not expose ACP mode switching`);
721
689
  }
722
- await this.connection.setSessionConfigOption({
690
+ if (!selection.configChoice) {
691
+ this.warnInvalidSelection(modeId, `is not valid ${this.provider} mode config option. Available options: ${flattenSelectOptions(modeOption.options)
692
+ .map((option) => option.value)
693
+ .join(", ")}`);
694
+ return;
695
+ }
696
+ const response = await this.connection.setSessionConfigOption({
723
697
  sessionId: this.sessionId,
724
698
  configId: modeOption.id,
725
699
  value: modeId,
726
700
  });
727
- this.currentMode = modeId;
701
+ this.currentMode = this.applyConfigOptionResponse({
702
+ response,
703
+ configId: modeOption.id,
704
+ category: "mode",
705
+ requestedValue: modeId,
706
+ label: "mode",
707
+ });
708
+ this.availableModes = deriveModesFromACP(this.defaultModes, null, this.configOptions).modes;
709
+ this.pushEvent({
710
+ type: "mode_changed",
711
+ provider: this.provider,
712
+ currentModeId: this.currentMode,
713
+ availableModes: [...this.availableModes],
714
+ });
728
715
  }
729
716
  async setModel(modelId) {
730
717
  if (!this.connection || !this.sessionId) {
@@ -734,29 +721,71 @@ export class ACPAgentSession {
734
721
  this.currentModel = null;
735
722
  return;
736
723
  }
737
- if ("unstable_setSessionModel" in this.connection) {
724
+ const selection = resolveACPModelSelection({
725
+ modelId,
726
+ availableModels: this.availableModels,
727
+ configOptions: this.configOptions,
728
+ });
729
+ await this.setModelWithSelection({ modelId, selection });
730
+ }
731
+ async setModelWithSelection({ modelId, selection, }) {
732
+ if (!this.connection || !this.sessionId) {
733
+ throw new Error("ACP session not initialized");
734
+ }
735
+ if (selection.hasAvailableModels) {
736
+ if (!selection.availableModel) {
737
+ this.warnInvalidSelection(modelId, `is not a valid ${this.provider} model. Available options: ${this.availableModels
738
+ ?.map((model) => model.modelId)
739
+ .join(", ")}`);
740
+ return;
741
+ }
742
+ if (typeof this.connection.unstable_setSessionModel !== "function") {
743
+ throw new Error(`${this.provider} does not expose ACP model selection`);
744
+ }
738
745
  try {
739
746
  await this.connection.unstable_setSessionModel({
740
747
  sessionId: this.sessionId,
741
748
  modelId,
742
749
  });
743
750
  this.currentModel = modelId;
751
+ this.pushEvent({
752
+ type: "model_changed",
753
+ provider: this.provider,
754
+ runtimeInfo: this.runtimeInfo(),
755
+ });
744
756
  return;
745
757
  }
746
758
  catch {
747
759
  // Fall through to config option path.
748
760
  }
749
761
  }
750
- const modelOption = this.getSelectConfigOption("model");
762
+ const modelOption = selection.configOption;
751
763
  if (!modelOption) {
752
764
  throw new Error(`${this.provider} does not expose ACP model selection`);
753
765
  }
754
- await this.connection.setSessionConfigOption({
766
+ if (!selection.configChoice) {
767
+ this.warnInvalidSelection(modelId, `is not a valid ${this.provider} model config option. Available options: ${flattenSelectOptions(modelOption.options)
768
+ .map((option) => option.value)
769
+ .join(", ")}`);
770
+ return;
771
+ }
772
+ const response = await this.connection.setSessionConfigOption({
755
773
  sessionId: this.sessionId,
756
774
  configId: modelOption.id,
757
775
  value: modelId,
758
776
  });
759
- this.currentModel = modelId;
777
+ this.currentModel = this.applyConfigOptionResponse({
778
+ response,
779
+ configId: modelOption.id,
780
+ category: "model",
781
+ requestedValue: modelId,
782
+ label: "model",
783
+ });
784
+ this.pushEvent({
785
+ type: "model_changed",
786
+ provider: this.provider,
787
+ runtimeInfo: this.runtimeInfo(),
788
+ });
760
789
  }
761
790
  async setThinkingOption(thinkingOptionId) {
762
791
  if (!this.connection || !this.sessionId) {
@@ -769,18 +798,50 @@ export class ACPAgentSession {
769
798
  if (this.thinkingOptionWriter) {
770
799
  await this.thinkingOptionWriter(this.connection, this.sessionId, thinkingOptionId);
771
800
  this.thinkingOptionId = thinkingOptionId;
801
+ this.pushEvent({
802
+ type: "thinking_option_changed",
803
+ provider: this.provider,
804
+ thinkingOptionId: this.thinkingOptionId,
805
+ });
772
806
  return;
773
807
  }
774
- const option = this.getSelectConfigOption("thought_level");
808
+ const option = findSelectConfigOption({
809
+ configOptions: this.configOptions,
810
+ category: "thought_level",
811
+ });
775
812
  if (!option) {
776
813
  throw new Error(`${this.provider} does not expose ACP thought-level selection`);
777
814
  }
778
- await this.connection.setSessionConfigOption({
815
+ const response = await this.connection.setSessionConfigOption({
779
816
  sessionId: this.sessionId,
780
817
  configId: option.id,
781
818
  value: thinkingOptionId,
782
819
  });
783
- this.thinkingOptionId = thinkingOptionId;
820
+ this.thinkingOptionId = this.applyConfigOptionResponse({
821
+ response,
822
+ configId: option.id,
823
+ category: "thought_level",
824
+ requestedValue: thinkingOptionId,
825
+ label: "thought-level",
826
+ });
827
+ this.pushEvent({
828
+ type: "thinking_option_changed",
829
+ provider: this.provider,
830
+ thinkingOptionId: this.thinkingOptionId,
831
+ });
832
+ }
833
+ applyConfigOptionResponse({ response, configId, category, requestedValue, label, }) {
834
+ this.configOptions = response.configOptions;
835
+ const responseOption = findSelectConfigOption({
836
+ configOptions: response.configOptions,
837
+ category,
838
+ id: configId,
839
+ });
840
+ if (responseOption?.currentValue != null) {
841
+ return responseOption.currentValue;
842
+ }
843
+ this.logger.warn({ configId, value: requestedValue }, `ACP setSessionConfigOption response did not include the requested ${label} option currentValue; using requested value`);
844
+ return requestedValue;
784
845
  }
785
846
  getPendingPermissions() {
786
847
  return Array.from(this.pendingPermissions.values(), (entry) => entry.request);
@@ -877,17 +938,7 @@ export class ACPAgentSession {
877
938
  this.activeForegroundTurnId = null;
878
939
  }
879
940
  async requestPermission(params) {
880
- if (shouldAutoApprovePermissionRequest(this.provider, this.currentMode)) {
881
- const selectedOption = selectPermissionOption(params.options, { behavior: "allow" });
882
- return selectedOption
883
- ? {
884
- outcome: {
885
- outcome: "selected",
886
- optionId: selectedOption.optionId,
887
- },
888
- }
889
- : { outcome: { outcome: "cancelled" } };
890
- }
941
+ // Match Zed acp.rs:3189-3220 — pure pass-through. Accepted UX regression: Copilot Autopilot will now prompt the user for every tool request.
891
942
  const requestId = randomUUID();
892
943
  let toolSnapshot = this.toolCalls.get(params.toolCall.toolCallId) ??
893
944
  mergeToolSnapshot(params.toolCall.toolCallId, params.toolCall);
@@ -1066,22 +1117,38 @@ export class ACPAgentSession {
1066
1117
  const modeInfo = deriveModesFromACP(this.defaultModes, transformed.modes, this.configOptions);
1067
1118
  this.availableModes = modeInfo.modes;
1068
1119
  this.currentMode = modeInfo.currentModeId ?? this.currentMode;
1120
+ this.availableModels = transformed.models?.availableModels ?? null;
1069
1121
  this.currentModel =
1070
1122
  transformed.models?.currentModelId ?? deriveCurrentConfigValue(this.configOptions, "model");
1071
1123
  this.thinkingOptionId =
1072
1124
  deriveCurrentConfigValue(this.configOptions, "thought_level") ?? this.thinkingOptionId;
1073
1125
  }
1074
1126
  async applyConfiguredOverrides() {
1075
- if (this.config.modeId && this.config.modeId !== this.currentMode) {
1076
- await this.setMode(this.config.modeId);
1077
- }
1078
- if (this.config.model && this.config.model !== this.currentModel) {
1079
- await this.setModel(this.config.model);
1127
+ const configuredModeId = this.config.modeId;
1128
+ if (configuredModeId && configuredModeId !== this.currentMode) {
1129
+ const selection = resolveACPModeSelection({
1130
+ modeId: configuredModeId,
1131
+ availableModes: this.availableModes,
1132
+ configOptions: this.configOptions,
1133
+ });
1134
+ await this.setModeWithSelection({ modeId: configuredModeId, selection });
1135
+ }
1136
+ const configuredModelId = this.config.model;
1137
+ if (configuredModelId && configuredModelId !== this.currentModel) {
1138
+ const selection = resolveACPModelSelection({
1139
+ modelId: configuredModelId,
1140
+ availableModels: this.availableModels,
1141
+ configOptions: this.configOptions,
1142
+ });
1143
+ await this.setModelWithSelection({ modelId: configuredModelId, selection });
1080
1144
  }
1081
1145
  if (this.config.thinkingOptionId && this.config.thinkingOptionId !== this.thinkingOptionId) {
1082
1146
  await this.setThinkingOption(this.config.thinkingOptionId);
1083
1147
  }
1084
1148
  }
1149
+ warnInvalidSelection(value, message) {
1150
+ this.logger.warn(value, message);
1151
+ }
1085
1152
  translateSessionUpdate(update) {
1086
1153
  switch (update.sessionUpdate) {
1087
1154
  case "user_message_chunk": {
@@ -1114,10 +1181,16 @@ export class ACPAgentSession {
1114
1181
  return [this.wrapTimeline(mapPlanToTimeline(update))];
1115
1182
  case "current_mode_update":
1116
1183
  this.handleCurrentModeUpdate(update);
1117
- return [];
1184
+ return [
1185
+ {
1186
+ type: "mode_changed",
1187
+ provider: this.provider,
1188
+ currentModeId: this.currentMode,
1189
+ availableModes: [...this.availableModes],
1190
+ },
1191
+ ];
1118
1192
  case "config_option_update":
1119
- this.handleConfigOptionUpdate(update);
1120
- return [];
1193
+ return this.handleConfigOptionUpdate(update);
1121
1194
  case "session_info_update":
1122
1195
  this.handleSessionInfoUpdate(update);
1123
1196
  return [];
@@ -1167,11 +1240,37 @@ export class ACPAgentSession {
1167
1240
  handleConfigOptionUpdate(update) {
1168
1241
  this.configOptions = update.configOptions;
1169
1242
  const modeInfo = deriveModesFromACP(this.defaultModes, null, this.configOptions);
1243
+ const nextMode = modeInfo.currentModeId;
1244
+ const nextModel = deriveCurrentConfigValue(this.configOptions, "model");
1245
+ const nextThinkingOptionId = deriveCurrentConfigValue(this.configOptions, "thought_level");
1170
1246
  this.availableModes = modeInfo.modes;
1171
- this.currentMode = modeInfo.currentModeId ?? this.currentMode;
1172
- this.currentModel = deriveCurrentConfigValue(this.configOptions, "model") ?? this.currentModel;
1173
- this.thinkingOptionId =
1174
- deriveCurrentConfigValue(this.configOptions, "thought_level") ?? this.thinkingOptionId;
1247
+ this.currentMode = nextMode ?? this.currentMode;
1248
+ this.currentModel = nextModel ?? this.currentModel;
1249
+ this.thinkingOptionId = nextThinkingOptionId ?? this.thinkingOptionId;
1250
+ const events = [];
1251
+ if (nextMode !== null) {
1252
+ events.push({
1253
+ type: "mode_changed",
1254
+ provider: this.provider,
1255
+ currentModeId: this.currentMode,
1256
+ availableModes: [...this.availableModes],
1257
+ });
1258
+ }
1259
+ if (nextModel !== null) {
1260
+ events.push({
1261
+ type: "model_changed",
1262
+ provider: this.provider,
1263
+ runtimeInfo: this.runtimeInfo(),
1264
+ });
1265
+ }
1266
+ if (nextThinkingOptionId !== null) {
1267
+ events.push({
1268
+ type: "thinking_option_changed",
1269
+ provider: this.provider,
1270
+ thinkingOptionId: this.thinkingOptionId,
1271
+ });
1272
+ }
1273
+ return events;
1175
1274
  }
1176
1275
  handleSessionInfoUpdate(update) {
1177
1276
  if ("title" in update) {
@@ -1223,6 +1322,19 @@ export class ACPAgentSession {
1223
1322
  subscriber(event);
1224
1323
  }
1225
1324
  }
1325
+ runtimeInfo() {
1326
+ return {
1327
+ provider: this.provider,
1328
+ sessionId: this.sessionId,
1329
+ model: this.currentModel,
1330
+ thinkingOptionId: this.thinkingOptionId,
1331
+ modeId: this.currentMode,
1332
+ extra: {
1333
+ title: this.currentTitle,
1334
+ updatedAt: this.lastActivityAt,
1335
+ },
1336
+ };
1337
+ }
1226
1338
  finishTurn(event) {
1227
1339
  this.activeForegroundTurnId = null;
1228
1340
  this.suppressUserEchoMessageId = null;
@@ -1262,10 +1374,6 @@ export class ACPAgentSession {
1262
1374
  }
1263
1375
  return parts.length > 0 ? parts.join(" | ") : undefined;
1264
1376
  }
1265
- getSelectConfigOption(category) {
1266
- const option = this.configOptions.find((entry) => entry.type === "select" && entry.category === category);
1267
- return option ?? null;
1268
- }
1269
1377
  getTerminalEntry(terminalId) {
1270
1378
  const entry = this.terminalEntries.get(terminalId);
1271
1379
  if (!entry) {
@@ -1274,6 +1382,16 @@ export class ACPAgentSession {
1274
1382
  return entry;
1275
1383
  }
1276
1384
  }
1385
+ function findSelectConfigOption({ configOptions, category, id, }) {
1386
+ const option = configOptions?.find((entry) => entry.type === "select" && entry.category === category && (!id || entry.id === id));
1387
+ return option ?? null;
1388
+ }
1389
+ function findSelectConfigChoice({ option, value, }) {
1390
+ if (!option) {
1391
+ return null;
1392
+ }
1393
+ return flattenSelectOptions(option.options).find((choice) => choice.value === value) ?? null;
1394
+ }
1277
1395
  function flattenSelectOptions(options) {
1278
1396
  const flattened = [];
1279
1397
  for (const option of options) {
@@ -1288,7 +1406,7 @@ function flattenSelectOptions(options) {
1288
1406
  return flattened;
1289
1407
  }
1290
1408
  function deriveSelectorOptions(configOptions, category) {
1291
- const option = configOptions?.find((entry) => entry.type === "select" && entry.category === category);
1409
+ const option = findSelectConfigOption({ configOptions, category });
1292
1410
  if (!option) {
1293
1411
  return [];
1294
1412
  }
@@ -1346,19 +1464,21 @@ function toACPContentBlocks(prompt) {
1346
1464
  if (typeof prompt === "string") {
1347
1465
  return [{ type: "text", text: prompt }];
1348
1466
  }
1349
- return prompt.map((block) => {
1350
- if (block.type === "text") {
1351
- return { type: "text", text: block.text };
1352
- }
1353
- if (block.type === "github_pr" || block.type === "github_issue") {
1354
- return { type: "text", text: renderPromptAttachmentAsText(block) };
1467
+ const contentBlocks = [];
1468
+ for (const block of prompt) {
1469
+ switch (block.type) {
1470
+ case "text":
1471
+ contentBlocks.push({ type: "text", text: block.text });
1472
+ break;
1473
+ case "image":
1474
+ contentBlocks.push({ type: "image", data: block.data, mimeType: block.mimeType });
1475
+ break;
1476
+ default:
1477
+ contentBlocks.push({ type: "text", text: renderPromptAttachmentAsText(block) });
1478
+ break;
1355
1479
  }
1356
- return {
1357
- type: "image",
1358
- data: block.data,
1359
- mimeType: block.mimeType,
1360
- };
1361
- });
1480
+ }
1481
+ return contentBlocks;
1362
1482
  }
1363
1483
  function extractPromptText(prompt) {
1364
1484
  if (typeof prompt === "string") {
@@ -1631,9 +1751,6 @@ function mapPermissionRequest(provider, requestId, params, snapshot) {
1631
1751
  },
1632
1752
  };
1633
1753
  }
1634
- function shouldAutoApprovePermissionRequest(provider, currentMode) {
1635
- return provider === "copilot" && currentMode === COPILOT_AUTOPILOT_MODE;
1636
- }
1637
1754
  function selectPermissionOption(options, response) {
1638
1755
  const order = response.behavior === "allow"
1639
1756
  ? ["allow_once", "allow_always"]