@bastani/atomic 0.9.40 → 0.9.41-alpha.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.
Files changed (323) hide show
  1. package/CHANGELOG.md +75 -0
  2. package/README.md +1 -1
  3. package/dist/builtin/intercom/CHANGELOG.md +12 -0
  4. package/dist/builtin/intercom/README.md +1 -1
  5. package/dist/builtin/intercom/broker/broker.ts +24 -21
  6. package/dist/builtin/intercom/broker/client.ts +97 -6
  7. package/dist/builtin/intercom/broker/list-reply.ts +53 -0
  8. package/dist/builtin/intercom/index.bundle.mjs +278 -46
  9. package/dist/builtin/intercom/package.json +2 -2
  10. package/dist/builtin/intercom/recoverable-disconnect.ts +27 -1
  11. package/dist/builtin/intercom/types.ts +8 -1
  12. package/dist/builtin/mcp/package.json +1 -1
  13. package/dist/builtin/subagents/CHANGELOG.md +14 -0
  14. package/dist/builtin/subagents/README.md +14 -0
  15. package/dist/builtin/subagents/package.json +3 -3
  16. package/dist/builtin/subagents/src/extension/index.bundle.mjs +99 -19
  17. package/dist/builtin/web-access/package.json +2 -2
  18. package/dist/builtin/workflows/CHANGELOG.md +33 -0
  19. package/dist/builtin/workflows/README.md +2 -0
  20. package/dist/builtin/workflows/builtin/adversarial-verification.js +2 -2
  21. package/dist/builtin/workflows/builtin/{chunk-qjqn389g.js → chunk-2jfst7e4.js} +72 -10
  22. package/dist/builtin/workflows/builtin/{chunk-4bwtzyjq.js → chunk-49kkbdpr.js} +1 -1
  23. package/dist/builtin/workflows/builtin/{chunk-qdd897wm.js → chunk-apagcs4r.js} +1 -1
  24. package/dist/builtin/workflows/builtin/{chunk-454hz1qt.js → chunk-dcxscfnb.js} +1 -1
  25. package/dist/builtin/workflows/builtin/{chunk-bjva9j5k.js → chunk-hx8v4p97.js} +1 -1
  26. package/dist/builtin/workflows/builtin/{chunk-85mx6wcf.js → chunk-k5q3t7je.js} +1 -1
  27. package/dist/builtin/workflows/builtin/{chunk-8kkv04hz.js → chunk-n2gkzkty.js} +1 -1
  28. package/dist/builtin/workflows/builtin/{chunk-y45tkftg.js → chunk-txbc93t6.js} +1 -1
  29. package/dist/builtin/workflows/builtin/{chunk-x0vvjyzg.js → chunk-w4xp1w1f.js} +1 -1
  30. package/dist/builtin/workflows/builtin/{chunk-5eh0brtd.js → chunk-z3pajrfs.js} +1 -1
  31. package/dist/builtin/workflows/builtin/classify-and-act.js +2 -2
  32. package/dist/builtin/workflows/builtin/fan-out-and-synthesize.js +2 -2
  33. package/dist/builtin/workflows/builtin/generate-and-filter.js +2 -2
  34. package/dist/builtin/workflows/builtin/goal.js +2 -2
  35. package/dist/builtin/workflows/builtin/index.js +10 -10
  36. package/dist/builtin/workflows/builtin/loop-until-done.js +2 -2
  37. package/dist/builtin/workflows/builtin/open-claude-design.js +2 -2
  38. package/dist/builtin/workflows/builtin/ralph.js +2 -2
  39. package/dist/builtin/workflows/builtin/tournament.js +2 -2
  40. package/dist/builtin/workflows/package.json +2 -2
  41. package/dist/builtin/workflows/src/authoring.d.ts +1 -1
  42. package/dist/builtin/workflows/src/durable/journal/internal.d.ts +16 -0
  43. package/dist/builtin/workflows/src/durable/journal/legacy-journal-tables.d.ts +9 -0
  44. package/dist/builtin/workflows/src/durable/journal/sql-run-journal.d.ts +6 -0
  45. package/dist/builtin/workflows/src/extension/index.bundle.mjs +950 -116
  46. package/dist/builtin/workflows/src/index.js +806 -131
  47. package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +17 -1
  48. package/dist/cli/credential-print.d.ts.map +1 -1
  49. package/dist/cli/credential-print.js +1 -1
  50. package/dist/cli/credential-print.js.map +1 -1
  51. package/dist/config.d.ts +1 -0
  52. package/dist/config.d.ts.map +1 -1
  53. package/dist/config.js +1 -0
  54. package/dist/config.js.map +1 -1
  55. package/dist/core/agent-session-extension-bindings.d.ts +2 -1
  56. package/dist/core/agent-session-extension-bindings.d.ts.map +1 -1
  57. package/dist/core/agent-session-extension-bindings.js +33 -18
  58. package/dist/core/agent-session-extension-bindings.js.map +1 -1
  59. package/dist/core/agent-session-methods.d.ts +2 -1
  60. package/dist/core/agent-session-methods.d.ts.map +1 -1
  61. package/dist/core/agent-session-methods.js.map +1 -1
  62. package/dist/core/agent-session-prompt.d.ts.map +1 -1
  63. package/dist/core/agent-session-prompt.js +114 -21
  64. package/dist/core/agent-session-prompt.js.map +1 -1
  65. package/dist/core/agent-session-runtime.d.ts +1 -1
  66. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  67. package/dist/core/agent-session-runtime.js +6 -0
  68. package/dist/core/agent-session-runtime.js.map +1 -1
  69. package/dist/core/agent-session-state.d.ts +19 -1
  70. package/dist/core/agent-session-state.d.ts.map +1 -1
  71. package/dist/core/agent-session-state.js +41 -6
  72. package/dist/core/agent-session-state.js.map +1 -1
  73. package/dist/core/auth-storage-backends.d.ts +3 -1
  74. package/dist/core/auth-storage-backends.d.ts.map +1 -1
  75. package/dist/core/auth-storage-backends.js +79 -12
  76. package/dist/core/auth-storage-backends.js.map +1 -1
  77. package/dist/core/client-identity.d.ts +8 -0
  78. package/dist/core/client-identity.d.ts.map +1 -0
  79. package/dist/core/client-identity.js +16 -0
  80. package/dist/core/client-identity.js.map +1 -0
  81. package/dist/core/compaction/planner-outcome.d.ts.map +1 -1
  82. package/dist/core/compaction/planner-outcome.js +2 -1
  83. package/dist/core/compaction/planner-outcome.js.map +1 -1
  84. package/dist/core/execution-model-router.d.ts +18 -0
  85. package/dist/core/execution-model-router.d.ts.map +1 -1
  86. package/dist/core/execution-model-router.js +14 -8
  87. package/dist/core/execution-model-router.js.map +1 -1
  88. package/dist/core/extension-oauth-refresh-rejection.d.ts +12 -0
  89. package/dist/core/extension-oauth-refresh-rejection.d.ts.map +1 -0
  90. package/dist/core/extension-oauth-refresh-rejection.js +70 -0
  91. package/dist/core/extension-oauth-refresh-rejection.js.map +1 -0
  92. package/dist/core/extension-startup-failure.d.ts +30 -0
  93. package/dist/core/extension-startup-failure.d.ts.map +1 -0
  94. package/dist/core/extension-startup-failure.js +62 -0
  95. package/dist/core/extension-startup-failure.js.map +1 -0
  96. package/dist/core/extensions/context-types.d.ts +2 -0
  97. package/dist/core/extensions/context-types.d.ts.map +1 -1
  98. package/dist/core/extensions/context-types.js.map +1 -1
  99. package/dist/core/extensions/provider-types.d.ts +2 -0
  100. package/dist/core/extensions/provider-types.d.ts.map +1 -1
  101. package/dist/core/extensions/provider-types.js.map +1 -1
  102. package/dist/core/extensions/runner-context.d.ts +1 -0
  103. package/dist/core/extensions/runner-context.d.ts.map +1 -1
  104. package/dist/core/extensions/runner-context.js +8 -0
  105. package/dist/core/extensions/runner-context.js.map +1 -1
  106. package/dist/core/extensions/runner.d.ts +1 -0
  107. package/dist/core/extensions/runner.d.ts.map +1 -1
  108. package/dist/core/extensions/runner.js +3 -0
  109. package/dist/core/extensions/runner.js.map +1 -1
  110. package/dist/core/extensions/runtime-types.d.ts +1 -0
  111. package/dist/core/extensions/runtime-types.d.ts.map +1 -1
  112. package/dist/core/extensions/runtime-types.js.map +1 -1
  113. package/dist/core/extensions/workflow-run-control-hub.d.ts +1 -0
  114. package/dist/core/extensions/workflow-run-control-hub.d.ts.map +1 -1
  115. package/dist/core/extensions/workflow-run-control-hub.js +3 -0
  116. package/dist/core/extensions/workflow-run-control-hub.js.map +1 -1
  117. package/dist/core/extensions/workflow-run-control.d.ts +8 -0
  118. package/dist/core/extensions/workflow-run-control.d.ts.map +1 -1
  119. package/dist/core/extensions/workflow-run-control.js.map +1 -1
  120. package/dist/core/model-config.d.ts +28 -0
  121. package/dist/core/model-config.d.ts.map +1 -1
  122. package/dist/core/model-fallback-failures.d.ts.map +1 -1
  123. package/dist/core/model-fallback-failures.js +12 -0
  124. package/dist/core/model-fallback-failures.js.map +1 -1
  125. package/dist/core/model-resolver-defaults.js +1 -1
  126. package/dist/core/model-resolver-defaults.js.map +1 -1
  127. package/dist/core/model-runtime-streaming.d.ts.map +1 -1
  128. package/dist/core/model-runtime-streaming.js +9 -3
  129. package/dist/core/model-runtime-streaming.js.map +1 -1
  130. package/dist/core/model-runtime.d.ts +5 -0
  131. package/dist/core/model-runtime.d.ts.map +1 -1
  132. package/dist/core/model-runtime.js +6 -0
  133. package/dist/core/model-runtime.js.map +1 -1
  134. package/dist/core/provider-composer-internal.d.ts +8 -6
  135. package/dist/core/provider-composer-internal.d.ts.map +1 -1
  136. package/dist/core/provider-composer-internal.js +21 -8
  137. package/dist/core/provider-composer-internal.js.map +1 -1
  138. package/dist/core/sdk.d.ts.map +1 -1
  139. package/dist/core/sdk.js +12 -4
  140. package/dist/core/sdk.js.map +1 -1
  141. package/dist/core/storage/session/sql-session-store.d.ts +35 -0
  142. package/dist/core/storage/session/sql-session-store.d.ts.map +1 -1
  143. package/dist/core/storage/session/sql-session-store.js +158 -42
  144. package/dist/core/storage/session/sql-session-store.js.map +1 -1
  145. package/dist/core/structured-output/deadline.d.ts +40 -0
  146. package/dist/core/structured-output/deadline.d.ts.map +1 -0
  147. package/dist/core/structured-output/deadline.js +110 -0
  148. package/dist/core/structured-output/deadline.js.map +1 -0
  149. package/dist/core/structured-output/index.d.ts.map +1 -1
  150. package/dist/core/structured-output/index.js +103 -47
  151. package/dist/core/structured-output/index.js.map +1 -1
  152. package/dist/core/structured-output/rejection-detail.d.ts +9 -0
  153. package/dist/core/structured-output/rejection-detail.d.ts.map +1 -0
  154. package/dist/core/structured-output/rejection-detail.js +129 -0
  155. package/dist/core/structured-output/rejection-detail.js.map +1 -0
  156. package/dist/core/structured-output/types.d.ts +8 -1
  157. package/dist/core/structured-output/types.d.ts.map +1 -1
  158. package/dist/core/structured-output/types.js.map +1 -1
  159. package/dist/core/tasks/completion.d.ts +7 -1
  160. package/dist/core/tasks/completion.d.ts.map +1 -1
  161. package/dist/core/tasks/completion.js +28 -6
  162. package/dist/core/tasks/completion.js.map +1 -1
  163. package/dist/core/tasks/contracts.d.ts +6 -1
  164. package/dist/core/tasks/contracts.d.ts.map +1 -1
  165. package/dist/core/tasks/contracts.js.map +1 -1
  166. package/dist/core/tasks/pause.d.ts +2 -1
  167. package/dist/core/tasks/pause.d.ts.map +1 -1
  168. package/dist/core/tasks/pause.js +3 -2
  169. package/dist/core/tasks/pause.js.map +1 -1
  170. package/dist/core/tools/bash-pty-native.d.ts.map +1 -1
  171. package/dist/core/tools/bash-pty-native.js +10 -5
  172. package/dist/core/tools/bash-pty-native.js.map +1 -1
  173. package/dist/core/tools/bash.d.ts.map +1 -1
  174. package/dist/core/tools/bash.js +16 -32
  175. package/dist/core/tools/bash.js.map +1 -1
  176. package/dist/core/tools/grep.js +1 -1
  177. package/dist/core/tools/grep.js.map +1 -1
  178. package/dist/core/tools/kill.d.ts.map +1 -1
  179. package/dist/core/tools/kill.js +17 -3
  180. package/dist/core/tools/kill.js.map +1 -1
  181. package/dist/core/tools/shell-task-render.d.ts +55 -0
  182. package/dist/core/tools/shell-task-render.d.ts.map +1 -0
  183. package/dist/core/tools/shell-task-render.js +123 -0
  184. package/dist/core/tools/shell-task-render.js.map +1 -0
  185. package/dist/core/tools/shell-task-status.d.ts +52 -0
  186. package/dist/core/tools/shell-task-status.d.ts.map +1 -0
  187. package/dist/core/tools/shell-task-status.js +184 -0
  188. package/dist/core/tools/shell-task-status.js.map +1 -0
  189. package/dist/core/tools/structured-output.d.ts +5 -0
  190. package/dist/core/tools/structured-output.d.ts.map +1 -1
  191. package/dist/core/tools/structured-output.js +3 -0
  192. package/dist/core/tools/structured-output.js.map +1 -1
  193. package/dist/extensions/codemode/execute.d.ts.map +1 -1
  194. package/dist/extensions/codemode/execute.js +134 -57
  195. package/dist/extensions/codemode/execute.js.map +1 -1
  196. package/dist/extensions/mcp/config.d.ts.map +1 -1
  197. package/dist/extensions/mcp/config.js +3 -2
  198. package/dist/extensions/mcp/config.js.map +1 -1
  199. package/dist/index-extensions.d.ts +1 -0
  200. package/dist/index-extensions.d.ts.map +1 -1
  201. package/dist/index-extensions.js +3 -0
  202. package/dist/index-extensions.js.map +1 -1
  203. package/dist/index.d.ts +3 -1
  204. package/dist/index.d.ts.map +1 -1
  205. package/dist/index.js +3 -1
  206. package/dist/index.js.map +1 -1
  207. package/dist/main.d.ts.map +1 -1
  208. package/dist/main.js +19 -6
  209. package/dist/main.js.map +1 -1
  210. package/dist/modes/interactive/components/task-row.d.ts.map +1 -1
  211. package/dist/modes/interactive/components/task-row.js +11 -1
  212. package/dist/modes/interactive/components/task-row.js.map +1 -1
  213. package/dist/modes/interactive/interactive-auth-routing.js +12 -10
  214. package/dist/modes/interactive/interactive-auth-routing.js.map +1 -1
  215. package/dist/modes/interactive/interactive-extension-custom-ui.js +20 -30
  216. package/dist/modes/interactive/interactive-extension-custom-ui.js.map +1 -1
  217. package/dist/modes/interactive/interactive-extension-dialogs.js +23 -96
  218. package/dist/modes/interactive/interactive-extension-dialogs.js.map +1 -1
  219. package/dist/modes/interactive/interactive-extension-runtime.js +7 -8
  220. package/dist/modes/interactive/interactive-extension-runtime.js.map +1 -1
  221. package/dist/modes/interactive/interactive-input-handling.d.ts.map +1 -1
  222. package/dist/modes/interactive/interactive-input-handling.js +27 -4
  223. package/dist/modes/interactive/interactive-input-handling.js.map +1 -1
  224. package/dist/modes/interactive/interactive-mode-base.d.ts +20 -10
  225. package/dist/modes/interactive/interactive-mode-base.d.ts.map +1 -1
  226. package/dist/modes/interactive/interactive-mode-base.js +40 -5
  227. package/dist/modes/interactive/interactive-mode-base.js.map +1 -1
  228. package/dist/modes/interactive/interactive-mode-deps.d.ts +1 -1
  229. package/dist/modes/interactive/interactive-mode-deps.d.ts.map +1 -1
  230. package/dist/modes/interactive/interactive-mode-deps.js +1 -1
  231. package/dist/modes/interactive/interactive-mode-deps.js.map +1 -1
  232. package/dist/modes/interactive/interactive-mode-surface.d.ts +2 -4
  233. package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
  234. package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
  235. package/dist/modes/interactive/interactive-mode-types.d.ts +4 -1
  236. package/dist/modes/interactive/interactive-mode-types.d.ts.map +1 -1
  237. package/dist/modes/interactive/interactive-mode-types.js.map +1 -1
  238. package/dist/modes/interactive/interactive-prompt-restore.d.ts +3 -0
  239. package/dist/modes/interactive/interactive-prompt-restore.d.ts.map +1 -1
  240. package/dist/modes/interactive/interactive-prompt-restore.js +9 -1
  241. package/dist/modes/interactive/interactive-prompt-restore.js.map +1 -1
  242. package/dist/modes/interactive/interactive-prompt-turn.js +30 -2
  243. package/dist/modes/interactive/interactive-prompt-turn.js.map +1 -1
  244. package/dist/modes/interactive/interactive-queueing.js +43 -8
  245. package/dist/modes/interactive/interactive-queueing.js.map +1 -1
  246. package/dist/modes/interactive/interactive-startup.d.ts.map +1 -1
  247. package/dist/modes/interactive/interactive-startup.js +12 -3
  248. package/dist/modes/interactive/interactive-startup.js.map +1 -1
  249. package/dist/modes/interactive/theme/color-utils.d.ts +6 -1
  250. package/dist/modes/interactive/theme/color-utils.d.ts.map +1 -1
  251. package/dist/modes/interactive/theme/color-utils.js +39 -17
  252. package/dist/modes/interactive/theme/color-utils.js.map +1 -1
  253. package/dist/modes/interactive/theme/theme-class.d.ts.map +1 -1
  254. package/dist/modes/interactive/theme/theme-class.js +2 -2
  255. package/dist/modes/interactive/theme/theme-class.js.map +1 -1
  256. package/dist/modes/interactive/theme/theme-tokens.d.ts +6 -0
  257. package/dist/modes/interactive/theme/theme-tokens.d.ts.map +1 -1
  258. package/dist/modes/interactive/theme/theme-tokens.js +7 -3
  259. package/dist/modes/interactive/theme/theme-tokens.js.map +1 -1
  260. package/dist/modes/interactive-engine/isolated-auth.d.ts +3 -0
  261. package/dist/modes/interactive-engine/isolated-auth.d.ts.map +1 -1
  262. package/dist/modes/interactive-engine/isolated-auth.js +13 -1
  263. package/dist/modes/interactive-engine/isolated-auth.js.map +1 -1
  264. package/dist/modes/interactive-engine/isolated-runtime.d.ts.map +1 -1
  265. package/dist/modes/interactive-engine/isolated-runtime.js +11 -2
  266. package/dist/modes/interactive-engine/isolated-runtime.js.map +1 -1
  267. package/dist/modes/interactive-engine/remote-model-catalog.d.ts +8 -0
  268. package/dist/modes/interactive-engine/remote-model-catalog.d.ts.map +1 -1
  269. package/dist/modes/interactive-engine/remote-model-catalog.js +54 -0
  270. package/dist/modes/interactive-engine/remote-model-catalog.js.map +1 -1
  271. package/dist/modes/rpc/rpc-command-handler.d.ts.map +1 -1
  272. package/dist/modes/rpc/rpc-command-handler.js +4 -13
  273. package/dist/modes/rpc/rpc-command-handler.js.map +1 -1
  274. package/dist/modes/rpc/rpc-model-catalog.d.ts +9 -0
  275. package/dist/modes/rpc/rpc-model-catalog.d.ts.map +1 -0
  276. package/dist/modes/rpc/rpc-model-catalog.js +19 -0
  277. package/dist/modes/rpc/rpc-model-catalog.js.map +1 -0
  278. package/dist/modes/rpc/rpc-provider-auth.d.ts.map +1 -1
  279. package/dist/modes/rpc/rpc-provider-auth.js +2 -6
  280. package/dist/modes/rpc/rpc-provider-auth.js.map +1 -1
  281. package/dist/modes/rpc/rpc-types.d.ts +6 -0
  282. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  283. package/dist/modes/rpc/rpc-types.js.map +1 -1
  284. package/dist/utils/changelog.d.ts +6 -0
  285. package/dist/utils/changelog.d.ts.map +1 -1
  286. package/dist/utils/changelog.js +11 -0
  287. package/dist/utils/changelog.js.map +1 -1
  288. package/dist/utils/clipboard.d.ts.map +1 -1
  289. package/dist/utils/clipboard.js +4 -0
  290. package/dist/utils/clipboard.js.map +1 -1
  291. package/dist/utils/tools-manager.d.ts.map +1 -1
  292. package/dist/utils/tools-manager.js +3 -2
  293. package/dist/utils/tools-manager.js.map +1 -1
  294. package/docs/background-tasks.md +5 -3
  295. package/docs/codemode.md +2 -2
  296. package/docs/custom-provider/oauth.md +42 -1
  297. package/docs/custom-provider/registration.md +2 -0
  298. package/docs/environment-variables.md +1 -0
  299. package/docs/extensions/api-reference.md +3 -4
  300. package/docs/extensions/authoring.md +1 -1
  301. package/docs/extensions/events.md +1 -1
  302. package/docs/models-configuration.md +9 -0
  303. package/docs/models.md +3 -1
  304. package/docs/providers.md +4 -4
  305. package/docs/rpc/protocol.md +4 -2
  306. package/docs/sdk/reference.md +2 -0
  307. package/docs/sdk/structured-decisions.md +7 -5
  308. package/docs/sdk.md +5 -2
  309. package/docs/settings.md +4 -2
  310. package/docs/subagents/reference.md +1 -1
  311. package/docs/subagents.md +15 -1
  312. package/docs/themes/reference.md +3 -1
  313. package/docs/usage.md +3 -1
  314. package/docs/workflows/api-reference.md +28 -0
  315. package/docs/workflows/authoring.md +1 -1
  316. package/docs/workflows/operations.md +2 -2
  317. package/npm-shrinkwrap.json +67 -54
  318. package/package.json +6 -6
  319. package/schemas/models.schema.json +21 -0
  320. package/dist/core/provider-attribution.d.ts +0 -4
  321. package/dist/core/provider-attribution.d.ts.map +0 -1
  322. package/dist/core/provider-attribution.js +0 -87
  323. package/dist/core/provider-attribution.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"rpc-types.js","sourceRoot":"","sources":["../../../src/modes/rpc/rpc-types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG","sourcesContent":["/**\n * RPC protocol types for headless operation.\n *\n * Commands are sent as JSON lines on stdin.\n * Responses and events are emitted as JSON lines on stdout.\n */\n\nimport type {\n\tAuthInfoLink,\n\tCredential,\n\tOAuthAuthInfo,\n\tOAuthDeviceCodeInfo,\n\tOAuthPrompt,\n\tOAuthSelectPrompt,\n} from \"@bastani/pi-ai\";\nimport type { Api, ImageContent, Model } from \"@bastani/pi-ai/compat\";\nimport type { AgentMessage, ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport type {\n\tCompactionReason,\n\tPromptDisposition,\n\tQueuedInputDisposition,\n\tSessionRecoveryReport,\n\tSessionStats,\n} from \"../../core/agent-session.js\";\nimport type { BashResult } from \"../../core/bash-executor.ts\";\nimport type { VerbatimCompactionResult } from \"../../core/compaction/index.ts\";\nimport type { ResourceOverlap } from \"../../core/diagnostics.ts\";\nimport type { SessionRecoveryReason } from \"../../core/extensions/index.js\";\nimport type {\n\tWorkflowRunDetail,\n\tWorkflowRunFilterStatus,\n\tWorkflowRunSummary,\n} from \"../../core/extensions/workflow-run-control.js\";\nimport type { ModelFallbackReason } from \"../../core/model-resolver-types.ts\";\nimport type { CredentialSynchronizationOperation } from \"../../core/model-runtime.js\";\nimport type { OAuthProviderMetadata } from \"../../core/oauth-login.ts\";\nimport type { AuthStatus } from \"../../core/provider-composer.ts\";\nimport type { SessionEntry, SessionInfo, SessionSummaryEntry, SessionTreeNode } from \"../../core/session-manager.ts\";\nimport type { SourceInfo } from \"../../core/source-info.ts\";\nimport type { ToolStatusReport } from \"../../core/tool-status.js\";\nimport type { JsonAgentSessionEvent } from \"../json-event.ts\";\n\n// ============================================================================\n// RPC Commands (stdin)\n// ============================================================================\n\nexport interface RpcModelCatalog {\n\tmodels: Model<Api>[];\n\tscopedModels: Array<{ model: Model<Api>; thinkingLevel?: ThinkingLevel }>;\n\tcustomAuthProviders: Array<{ id: string; name: string }>;\n\toauthProviders?: OAuthProviderMetadata[];\n}\n\nexport interface RpcModelRefreshResult extends RpcModelCatalog {\n\taborted: boolean;\n\terrors: Array<{ provider: string; message: string }>;\n}\n/**\n * The host supplied the API key through the login input form, so echoing it\n * back over the stdout pipe would make this response a second credential\n * egress. Only the metadata a caller needs to confirm the login travels.\n */\nexport type RpcLoginProviderResult =\n\t| (RpcModelCatalog & {\n\t\t\tprovider: string;\n\t\t\tcancelled: false;\n\t\t\ttype: \"api_key\";\n\t })\n\t| { provider: string; cancelled: true };\n\nexport type RpcOAuthLoginProviderResult =\n\t| (RpcModelCatalog & { provider: string; cancelled: false })\n\t| { provider: string; cancelled: true };\n\nexport type RpcSessionInfo = Omit<SessionInfo, \"created\" | \"modified\"> & {\n\tcreated: string;\n\tmodified: string;\n};\n\nexport type RpcCommand =\n\t// Prompting\n\t| { id?: string; type: \"prompt\"; message: string; images?: ImageContent[]; streamingBehavior?: \"steer\" | \"followUp\" }\n\t| { id?: string; type: \"steer\"; message: string; images?: ImageContent[] }\n\t| { id?: string; type: \"follow_up\"; message: string; images?: ImageContent[] }\n\t| { id?: string; type: \"abort\" }\n\t| { id?: string; type: \"new_session\"; parentSession?: string }\n\t| { id?: string; type: \"delete_session\"; sessionId?: string }\n\n\t// State\n\t| { id?: string; type: \"get_state\" }\n\t| { id?: string; type: \"get_session_summary\" }\n\t| { id?: string; type: \"list_sessions\" }\n\t| { id?: string; type: \"list_workflow_runs\"; status?: WorkflowRunFilterStatus }\n\t| { id?: string; type: \"get_workflow_run_summary\"; runId: string }\n\t| { id?: string; type: \"open_task_inspector\"; taskId?: string }\n\n\t// Model\n\t| { id?: string; type: \"set_model\"; provider: string; modelId: string; persist?: boolean }\n\t| { id?: string; type: \"cycle_model\"; direction?: \"forward\" | \"backward\"; persist?: boolean }\n\t| { id?: string; type: \"get_available_models\"; allowPartialResources?: boolean }\n\t| { id?: string; type: \"login_provider\"; provider: string; authType?: \"api_key\" | \"oauth\"; loginId?: string }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"save_provider_credential\";\n\t\t\tprovider: string;\n\t\t\tcredential: Credential;\n\t\t\t/** Fetch the remote catalog before publishing the credential. Defaults to true. */\n\t\t\trefreshCatalog?: boolean;\n\t }\n\t| { id?: string; type: \"cancel_login_provider\"; provider: string; loginId?: string }\n\t| { id?: string; type: \"logout_provider\"; provider: string }\n\t| { id?: string; type: \"refresh_models\"; timeoutMs?: number; force?: boolean; allowNetwork?: boolean }\n\n\t// Thinking\n\t| { id?: string; type: \"set_thinking_level\"; level: ThinkingLevel; persist?: boolean }\n\t| { id?: string; type: \"cycle_thinking_level\" }\n\t| { id?: string; type: \"get_available_thinking_levels\" }\n\n\t// Queue modes\n\t| { id?: string; type: \"set_steering_mode\"; mode: \"all\" | \"one-at-a-time\" }\n\t| { id?: string; type: \"set_follow_up_mode\"; mode: \"all\" | \"one-at-a-time\" }\n\n\t// Compaction\n\t| { id?: string; type: \"compact\" }\n\t| { id?: string; type: \"set_auto_compaction\"; enabled: boolean }\n\t| { id?: string; type: \"abort_compaction\" }\n\n\t// Retry\n\t| { id?: string; type: \"set_auto_retry\"; enabled: boolean }\n\t| { id?: string; type: \"abort_retry\" }\n\t| { id?: string; type: \"clear_queue\" }\n\t| { id?: string; type: \"pause_queued_messages\" }\n\t| { id?: string; type: \"resume_queued_messages\" }\n\n\t// Bash\n\t| { id?: string; type: \"bash\"; command: string; excludeFromContext?: boolean }\n\t| { id?: string; type: \"user_bash\"; command: string; excludeFromContext?: boolean }\n\t| { id?: string; type: \"abort_bash\"; requestId?: string }\n\n\t// Session\n\t| { id?: string; type: \"get_session_stats\" }\n\t| { id?: string; type: \"get_tools\" }\n\t| { id?: string; type: \"export_html\"; outputPath?: string }\n\t| { id?: string; type: \"switch_session\"; sessionId: string; cwdOverride?: string; sessionDirectory?: string }\n\t| { id?: string; type: \"import_session\"; inputPath: string; cwdOverride?: string }\n\t| { id?: string; type: \"fork\"; entryId: string }\n\t| { id?: string; type: \"clone\" }\n\t| { id?: string; type: \"get_fork_messages\" }\n\t| { id?: string; type: \"get_entries\"; since?: string }\n\t| { id?: string; type: \"get_tree\" }\n\t| { id?: string; type: \"get_last_assistant_text\" }\n\t| { id?: string; type: \"set_session_name\"; name: string }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"navigate_tree\";\n\t\t\ttargetId: string;\n\t\t\toptions?: { summarize?: boolean; customInstructions?: string; replaceInstructions?: boolean; label?: string };\n\t }\n\t| { id?: string; type: \"set_label\"; entryId: string; label?: string }\n\t| { id?: string; type: \"reload\" }\n\t| { id?: string; type: \"start_pending_recovery\"; reason?: SessionRecoveryReason }\n\t| { id?: string; type: \"get_shortcuts\" }\n\t| { id?: string; type: \"invoke_shortcut\"; key: string }\n\n\t// Messages\n\t| { id?: string; type: \"get_messages\" }\n\n\t// Commands and their live argument completions\n\t| { id?: string; type: \"get_commands\" }\n\t| { id?: string; type: \"get_command_completions\"; commandName: string; argumentPrefix: string };\n// ============================================================================\n// RPC Argument Completion\n// ============================================================================\n\nexport interface RpcAutocompleteItem {\n\tvalue: string;\n\tlabel: string;\n\tdescription?: string;\n}\n\n// RPC Slash Command (for get_commands response)\n// ============================================================================\n\n/** A command available for invocation via prompt */\nexport interface RpcSlashCommand {\n\t/** Command name (without leading slash) */\n\tname: string;\n\t/** Human-readable description */\n\tdescription?: string;\n\t/** Whether the engine can evaluate argument completions for this command. */\n\thasArgumentCompletions?: boolean;\n\t/** What kind of command this is */\n\tsource: \"extension\" | \"prompt\" | \"skill\";\n\t/** Source metadata for the owning resource */\n\tsourceInfo: SourceInfo;\n}\n\n// ============================================================================\n// RPC State\n// ============================================================================\n\nexport interface RpcResourceExtension {\n\tpath: string;\n\tsourceInfo?: SourceInfo;\n\thidden: boolean;\n}\n\nexport interface RpcSessionState {\n\tmodel?: Model<Api>;\n\tmodelFallbackMessage?: string;\n\tmodelFallbackReason?: ModelFallbackReason;\n\tthinkingLevel: ThinkingLevel;\n\tisStreaming: boolean;\n\tisCompacting: boolean;\n\tcompactionReason?: CompactionReason;\n\tsteeringMode: \"all\" | \"one-at-a-time\";\n\tfollowUpMode: \"all\" | \"one-at-a-time\";\n\tsessionLocation?: string;\n\tsessionId: string;\n\tsessionName?: string;\n\tautoCompactionEnabled: boolean;\n\tmessageCount: number;\n\tpendingMessageCount: number;\n\tqueuedMessagesPaused: boolean;\n\t/** Authoritative engine trust state; absent on older RPC peers. */\n\tprojectTrusted?: boolean;\n\tresourceOverlaps?: ResourceOverlap[];\n\tresourceExtensions?: RpcResourceExtension[];\n}\n\nexport interface RpcLogoutProviderResult {\n\tprovider: string;\n\tauthStatus: AuthStatus;\n\tmodels: Model<Api>[];\n\tscopedModels?: Array<{ model: Model<Api>; thinkingLevel?: ThinkingLevel }>;\n}\n\n// ============================================================================\n// RPC Responses (stdout)\n// ============================================================================\n\n// Success responses with data\nexport type RpcResponse =\n\t// Prompting\n\t| { id?: string; type: \"response\"; command: \"prompt\"; success: true; data: { disposition: PromptDisposition } }\n\t| { id?: string; type: \"response\"; command: \"steer\"; success: true; data: { disposition: QueuedInputDisposition } }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"follow_up\";\n\t\t\tsuccess: true;\n\t\t\tdata: { disposition: QueuedInputDisposition };\n\t }\n\t| { id?: string; type: \"response\"; command: \"abort\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"new_session\"; success: true; data: { cancelled: boolean } }\n\t| { id?: string; type: \"response\"; command: \"delete_session\"; success: true }\n\n\t// State\n\t| { id?: string; type: \"response\"; command: \"get_state\"; success: true; data: RpcSessionState }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_session_summary\";\n\t\t\tsuccess: true;\n\t\t\tdata: { summary: SessionSummaryEntry | null };\n\t }\n\t| { id?: string; type: \"response\"; command: \"list_sessions\"; success: true; data: { sessions: RpcSessionInfo[] } }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"list_workflow_runs\";\n\t\t\tsuccess: true;\n\t\t\tdata: { runs: readonly WorkflowRunSummary[] };\n\t }\n\t| { id?: string; type: \"response\"; command: \"get_workflow_run_summary\"; success: true; data: WorkflowRunDetail }\n\t| { id?: string; type: \"response\"; command: \"open_task_inspector\"; success: true }\n\n\t// Model\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"set_model\";\n\t\t\tsuccess: true;\n\t\t\tdata: Model<Api>;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"cycle_model\";\n\t\t\tsuccess: true;\n\t\t\tdata: { model: Model<Api>; thinkingLevel: ThinkingLevel; isScoped: boolean } | null;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_available_models\";\n\t\t\tsuccess: true;\n\t\t\tdata: RpcModelCatalog;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"refresh_models\";\n\t\t\tsuccess: true;\n\t\t\tdata: RpcModelRefreshResult;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"login_provider\";\n\t\t\tsuccess: true;\n\t\t\tdata: RpcLoginProviderResult | RpcOAuthLoginProviderResult;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"save_provider_credential\";\n\t\t\tsuccess: true;\n\t\t\tdata: RpcModelCatalog;\n\t }\n\t| { id?: string; type: \"response\"; command: \"cancel_login_provider\"; success: true }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"logout_provider\";\n\t\t\tsuccess: true;\n\t\t\tdata: RpcLogoutProviderResult;\n\t }\n\n\t// Thinking — data-less success remains valid for older clients; isolated persist\n\t// reads the optional ACK when present.\n\t| { id?: string; type: \"response\"; command: \"set_thinking_level\"; success: true }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"set_thinking_level\";\n\t\t\tsuccess: true;\n\t\t\tdata: { level: ThinkingLevel; provider?: string; modelId?: string };\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"cycle_thinking_level\";\n\t\t\tsuccess: true;\n\t\t\tdata: { level: ThinkingLevel } | null;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_available_thinking_levels\";\n\t\t\tsuccess: true;\n\t\t\tdata: { levels: ThinkingLevel[] };\n\t }\n\n\t// Queue modes\n\t| { id?: string; type: \"response\"; command: \"set_steering_mode\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"set_follow_up_mode\"; success: true }\n\n\t// Compaction\n\t| { id?: string; type: \"response\"; command: \"compact\"; success: true; data: VerbatimCompactionResult }\n\t| { id?: string; type: \"response\"; command: \"set_auto_compaction\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"abort_compaction\"; success: true }\n\n\t// Retry\n\t| { id?: string; type: \"response\"; command: \"set_auto_retry\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"abort_retry\"; success: true }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"clear_queue\";\n\t\t\tsuccess: true;\n\t\t\tdata: { steering: string[]; followUp: string[] };\n\t }\n\t| { id?: string; type: \"response\"; command: \"pause_queued_messages\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"resume_queued_messages\"; success: true; data: { released: boolean } }\n\n\t// Bash\n\t| { id?: string; type: \"response\"; command: \"bash\"; success: true; data: BashResult }\n\t| { id?: string; type: \"response\"; command: \"user_bash\"; success: true; data: BashResult }\n\t| { id?: string; type: \"response\"; command: \"abort_bash\"; success: true }\n\n\t// Session\n\t| { id?: string; type: \"response\"; command: \"get_session_stats\"; success: true; data: SessionStats }\n\t| { id?: string; type: \"response\"; command: \"get_tools\"; success: true; data: ToolStatusReport }\n\t| { id?: string; type: \"response\"; command: \"import_session\"; success: true; data: { cancelled: boolean } }\n\t| { id?: string; type: \"response\"; command: \"export_html\"; success: true; data: { path: string } }\n\t| { id?: string; type: \"response\"; command: \"switch_session\"; success: true; data: { cancelled: boolean } }\n\t| { id?: string; type: \"response\"; command: \"fork\"; success: true; data: { text: string; cancelled: boolean } }\n\t| { id?: string; type: \"response\"; command: \"clone\"; success: true; data: { cancelled: boolean } }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_fork_messages\";\n\t\t\tsuccess: true;\n\t\t\tdata: { messages: Array<{ entryId: string; text: string }> };\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_entries\";\n\t\t\tsuccess: true;\n\t\t\tdata: { entries: SessionEntry[]; leafId: string | null };\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_tree\";\n\t\t\tsuccess: true;\n\t\t\tdata: { tree: SessionTreeNode[]; leafId: string | null };\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_last_assistant_text\";\n\t\t\tsuccess: true;\n\t\t\tdata: { text: string | null };\n\t }\n\t| { id?: string; type: \"response\"; command: \"set_session_name\"; success: true }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"navigate_tree\";\n\t\t\tsuccess: true;\n\t\t\tdata: { cancelled: boolean; editorText?: string };\n\t }\n\t| { id?: string; type: \"response\"; command: \"set_label\"; success: true; data: { entryId: string } }\n\t| { id?: string; type: \"response\"; command: \"reload\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"start_pending_recovery\"; success: true; data: SessionRecoveryReport }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_shortcuts\";\n\t\t\tsuccess: true;\n\t\t\tdata: { shortcuts: Array<{ key: string; description?: string }> };\n\t }\n\t| { id?: string; type: \"response\"; command: \"invoke_shortcut\"; success: true }\n\n\t// Messages\n\t| { id?: string; type: \"response\"; command: \"get_messages\"; success: true; data: { messages: AgentMessage[] } }\n\n\t// Commands\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_commands\";\n\t\t\tsuccess: true;\n\t\t\tdata: { commands: RpcSlashCommand[] };\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_command_completions\";\n\t\t\tsuccess: true;\n\t\t\tdata: { completions: RpcAutocompleteItem[] | null };\n\t }\n\n\t// Error response (any command can fail)\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: string;\n\t\t\tsuccess: false;\n\t\t\terror: string;\n\t\t\terrorCode?: \"credential_synchronization\";\n\t\t\terrorDetails?: {\n\t\t\t\tproviderId: string;\n\t\t\t\toperation: CredentialSynchronizationOperation;\n\t\t\t};\n\t };\n\n// ============================================================================\n// RPC Events (stdout)\n// ============================================================================\n\n/** Events streamed by RPC mode as session activity occurs. */\nexport type RpcEvent = JsonAgentSessionEvent;\n\n// ============================================================================\n// Extension UI Events (stdout)\n// ============================================================================\ntype RpcOAuthUIEnvelope = { type: \"extension_ui_request\"; id: string; provider: string; loginId: string };\n\nexport type RpcExtensionUIRequest =\n\t| { type: \"extension_ui_request\"; id: string; method: \"select\"; title: string; options: string[]; timeout?: number }\n\t| { type: \"extension_ui_request\"; id: string; method: \"confirm\"; title: string; message: string; timeout?: number }\n\t| {\n\t\t\ttype: \"extension_ui_request\";\n\t\t\tid: string;\n\t\t\tmethod: \"input\";\n\t\t\ttitle: string;\n\t\t\tplaceholder?: string;\n\t\t\ttimeout?: number;\n\t }\n\t| { type: \"extension_ui_request\"; id: string; method: \"editor\"; title: string; prefill?: string }\n\t| {\n\t\t\ttype: \"extension_ui_request\";\n\t\t\tid: string;\n\t\t\tmethod: \"notify\";\n\t\t\tmessage: string;\n\t\t\tnotifyType?: \"info\" | \"warning\" | \"error\";\n\t }\n\t| {\n\t\t\ttype: \"extension_ui_request\";\n\t\t\tid: string;\n\t\t\tmethod: \"setStatus\";\n\t\t\tstatusKey: string;\n\t\t\tstatusText: string | undefined;\n\t }\n\t| {\n\t\t\ttype: \"extension_ui_request\";\n\t\t\tid: string;\n\t\t\tmethod: \"setWidget\";\n\t\t\twidgetKey: string;\n\t\t\twidgetLines: string[] | undefined;\n\t\t\twidgetPlacement?: \"aboveEditor\" | \"belowEditor\";\n\t\t\twidgetScroll?: { maxHeight: number; maxHeightFraction?: number };\n\t }\n\t| { type: \"extension_ui_request\"; id: string; method: \"setTitle\"; title: string }\n\t| { type: \"extension_ui_request\"; id: string; method: \"set_editor_text\"; text: string }\n\t| (RpcOAuthUIEnvelope & { method: \"oauth_auth\"; info: OAuthAuthInfo })\n\t| (RpcOAuthUIEnvelope & { method: \"oauth_device_code\"; info: OAuthDeviceCodeInfo })\n\t| (RpcOAuthUIEnvelope & { method: \"oauth_progress\"; message: string })\n\t| (RpcOAuthUIEnvelope & { method: \"oauth_info\"; message: string; links: AuthInfoLink[] })\n\t| (RpcOAuthUIEnvelope & { method: \"oauth_prompt\"; prompt: OAuthPrompt })\n\t| (RpcOAuthUIEnvelope & { method: \"oauth_select\"; prompt: OAuthSelectPrompt })\n\t| (RpcOAuthUIEnvelope & { method: \"oauth_manual_code\" })\n\t| (RpcOAuthUIEnvelope & { method: \"oauth_manual_code_cancel\" });\n\n// ============================================================================\n// Extension UI Commands (stdin)\n// ============================================================================\n\n/** Response to an extension UI request */\nexport type RpcExtensionUIResponse =\n\t| { type: \"extension_ui_response\"; id: string; value: string }\n\t| { type: \"extension_ui_response\"; id: string; confirmed: boolean }\n\t| { type: \"extension_ui_response\"; id: string; cancelled: true };\n\n// ============================================================================\n// Helper type for extracting command types\n// ============================================================================\n\nexport type RpcCommandType = RpcCommand[\"type\"];\n"]}
1
+ {"version":3,"file":"rpc-types.js","sourceRoot":"","sources":["../../../src/modes/rpc/rpc-types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG","sourcesContent":["/**\n * RPC protocol types for headless operation.\n *\n * Commands are sent as JSON lines on stdin.\n * Responses and events are emitted as JSON lines on stdout.\n */\n\nimport type {\n\tAuthInfoLink,\n\tCredential,\n\tOAuthAuthInfo,\n\tOAuthDeviceCodeInfo,\n\tOAuthPrompt,\n\tOAuthSelectPrompt,\n} from \"@bastani/pi-ai\";\nimport type { Api, ImageContent, Model } from \"@bastani/pi-ai/compat\";\nimport type { AgentMessage, ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport type {\n\tCompactionReason,\n\tPromptDisposition,\n\tQueuedInputDisposition,\n\tSessionRecoveryReport,\n\tSessionStats,\n} from \"../../core/agent-session.js\";\nimport type { BashResult } from \"../../core/bash-executor.ts\";\nimport type { VerbatimCompactionResult } from \"../../core/compaction/index.ts\";\nimport type { ResourceOverlap } from \"../../core/diagnostics.ts\";\nimport type { SessionRecoveryReason } from \"../../core/extensions/index.js\";\nimport type {\n\tWorkflowRunDetail,\n\tWorkflowRunFilterStatus,\n\tWorkflowRunSummary,\n} from \"../../core/extensions/workflow-run-control.js\";\nimport type { ModelFallbackReason } from \"../../core/model-resolver-types.ts\";\nimport type { CredentialSynchronizationOperation } from \"../../core/model-runtime.js\";\nimport type { OAuthProviderMetadata } from \"../../core/oauth-login.ts\";\nimport type { AuthStatus } from \"../../core/provider-composer.ts\";\nimport type { SessionEntry, SessionInfo, SessionSummaryEntry, SessionTreeNode } from \"../../core/session-manager.ts\";\nimport type { SourceInfo } from \"../../core/source-info.ts\";\nimport type { ToolStatusReport } from \"../../core/tool-status.js\";\nimport type { JsonAgentSessionEvent } from \"../json-event.ts\";\n\n// ============================================================================\n// RPC Commands (stdin)\n// ============================================================================\n\nexport interface RpcModelCatalog {\n\tmodels: Model<Api>[];\n\tscopedModels: Array<{ model: Model<Api>; thinkingLevel?: ThinkingLevel }>;\n\t/** Extension-registered providers that offer API-key login (`login_provider`). */\n\tcustomAuthProviders: Array<{ id: string; name: string }>;\n\toauthProviders?: OAuthProviderMetadata[];\n\t/** Auth status of extension-registered providers that is not a stored credential (environment, configured key, runtime key). */\n\tproviderAuthStatuses?: Array<{ provider: string; status: AuthStatus }>;\n}\n\nexport interface RpcModelRefreshResult extends RpcModelCatalog {\n\taborted: boolean;\n\terrors: Array<{ provider: string; message: string }>;\n}\n/**\n * The host supplied the API key through the login input form, so echoing it\n * back over the stdout pipe would make this response a second credential\n * egress. Only the metadata a caller needs to confirm the login travels.\n */\nexport type RpcLoginProviderResult =\n\t| (RpcModelCatalog & {\n\t\t\tprovider: string;\n\t\t\tcancelled: false;\n\t\t\ttype: \"api_key\";\n\t })\n\t| { provider: string; cancelled: true };\n\nexport type RpcOAuthLoginProviderResult =\n\t| (RpcModelCatalog & { provider: string; cancelled: false })\n\t| { provider: string; cancelled: true };\n\nexport type RpcSessionInfo = Omit<SessionInfo, \"created\" | \"modified\"> & {\n\tcreated: string;\n\tmodified: string;\n};\n\nexport type RpcCommand =\n\t// Prompting\n\t| { id?: string; type: \"prompt\"; message: string; images?: ImageContent[]; streamingBehavior?: \"steer\" | \"followUp\" }\n\t| { id?: string; type: \"steer\"; message: string; images?: ImageContent[] }\n\t| { id?: string; type: \"follow_up\"; message: string; images?: ImageContent[] }\n\t| { id?: string; type: \"abort\" }\n\t| { id?: string; type: \"new_session\"; parentSession?: string }\n\t| { id?: string; type: \"delete_session\"; sessionId?: string }\n\n\t// State\n\t| { id?: string; type: \"get_state\" }\n\t| { id?: string; type: \"get_session_summary\" }\n\t| { id?: string; type: \"list_sessions\" }\n\t| { id?: string; type: \"list_workflow_runs\"; status?: WorkflowRunFilterStatus }\n\t| { id?: string; type: \"get_workflow_run_summary\"; runId: string }\n\t| { id?: string; type: \"open_task_inspector\"; taskId?: string }\n\n\t// Model\n\t| { id?: string; type: \"set_model\"; provider: string; modelId: string; persist?: boolean }\n\t| { id?: string; type: \"cycle_model\"; direction?: \"forward\" | \"backward\"; persist?: boolean }\n\t| { id?: string; type: \"get_available_models\"; allowPartialResources?: boolean }\n\t| { id?: string; type: \"login_provider\"; provider: string; authType?: \"api_key\" | \"oauth\"; loginId?: string }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"save_provider_credential\";\n\t\t\tprovider: string;\n\t\t\tcredential: Credential;\n\t\t\t/** Fetch the remote catalog before publishing the credential. Defaults to true. */\n\t\t\trefreshCatalog?: boolean;\n\t }\n\t| { id?: string; type: \"cancel_login_provider\"; provider: string; loginId?: string }\n\t| { id?: string; type: \"logout_provider\"; provider: string }\n\t| { id?: string; type: \"refresh_models\"; timeoutMs?: number; force?: boolean; allowNetwork?: boolean }\n\n\t// Thinking\n\t| { id?: string; type: \"set_thinking_level\"; level: ThinkingLevel; persist?: boolean }\n\t| { id?: string; type: \"cycle_thinking_level\" }\n\t| { id?: string; type: \"get_available_thinking_levels\" }\n\n\t// Queue modes\n\t| { id?: string; type: \"set_steering_mode\"; mode: \"all\" | \"one-at-a-time\" }\n\t| { id?: string; type: \"set_follow_up_mode\"; mode: \"all\" | \"one-at-a-time\" }\n\n\t// Compaction\n\t| { id?: string; type: \"compact\" }\n\t| { id?: string; type: \"set_auto_compaction\"; enabled: boolean }\n\t| { id?: string; type: \"abort_compaction\" }\n\n\t// Retry\n\t| { id?: string; type: \"set_auto_retry\"; enabled: boolean }\n\t| { id?: string; type: \"abort_retry\" }\n\t| { id?: string; type: \"clear_queue\" }\n\t| { id?: string; type: \"pause_queued_messages\" }\n\t| { id?: string; type: \"resume_queued_messages\" }\n\n\t// Bash\n\t| { id?: string; type: \"bash\"; command: string; excludeFromContext?: boolean }\n\t| { id?: string; type: \"user_bash\"; command: string; excludeFromContext?: boolean }\n\t| { id?: string; type: \"abort_bash\"; requestId?: string }\n\n\t// Session\n\t| { id?: string; type: \"get_session_stats\" }\n\t| { id?: string; type: \"get_tools\" }\n\t| { id?: string; type: \"export_html\"; outputPath?: string }\n\t| { id?: string; type: \"switch_session\"; sessionId: string; cwdOverride?: string; sessionDirectory?: string }\n\t| { id?: string; type: \"import_session\"; inputPath: string; cwdOverride?: string }\n\t| { id?: string; type: \"fork\"; entryId: string }\n\t| { id?: string; type: \"clone\" }\n\t| { id?: string; type: \"get_fork_messages\" }\n\t| { id?: string; type: \"get_entries\"; since?: string }\n\t| { id?: string; type: \"get_tree\" }\n\t| { id?: string; type: \"get_last_assistant_text\" }\n\t| { id?: string; type: \"set_session_name\"; name: string }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"navigate_tree\";\n\t\t\ttargetId: string;\n\t\t\toptions?: { summarize?: boolean; customInstructions?: string; replaceInstructions?: boolean; label?: string };\n\t }\n\t| { id?: string; type: \"set_label\"; entryId: string; label?: string }\n\t| { id?: string; type: \"reload\" }\n\t| { id?: string; type: \"start_pending_recovery\"; reason?: SessionRecoveryReason }\n\t| { id?: string; type: \"get_shortcuts\" }\n\t| { id?: string; type: \"invoke_shortcut\"; key: string }\n\n\t// Messages\n\t| { id?: string; type: \"get_messages\" }\n\n\t// Commands and their live argument completions\n\t| { id?: string; type: \"get_commands\" }\n\t| { id?: string; type: \"get_command_completions\"; commandName: string; argumentPrefix: string };\n// ============================================================================\n// RPC Argument Completion\n// ============================================================================\n\nexport interface RpcAutocompleteItem {\n\tvalue: string;\n\tlabel: string;\n\tdescription?: string;\n}\n\n// RPC Slash Command (for get_commands response)\n// ============================================================================\n\n/** A command available for invocation via prompt */\nexport interface RpcSlashCommand {\n\t/** Command name (without leading slash) */\n\tname: string;\n\t/** Human-readable description */\n\tdescription?: string;\n\t/** Whether the engine can evaluate argument completions for this command. */\n\thasArgumentCompletions?: boolean;\n\t/** What kind of command this is */\n\tsource: \"extension\" | \"prompt\" | \"skill\";\n\t/** Source metadata for the owning resource */\n\tsourceInfo: SourceInfo;\n}\n\n// ============================================================================\n// RPC State\n// ============================================================================\n\nexport interface RpcResourceExtension {\n\tpath: string;\n\tsourceInfo?: SourceInfo;\n\thidden: boolean;\n}\n\nexport interface RpcSessionState {\n\tmodel?: Model<Api>;\n\tmodelFallbackMessage?: string;\n\tmodelFallbackReason?: ModelFallbackReason;\n\tthinkingLevel: ThinkingLevel;\n\tisStreaming: boolean;\n\tisCompacting: boolean;\n\tcompactionReason?: CompactionReason;\n\tsteeringMode: \"all\" | \"one-at-a-time\";\n\tfollowUpMode: \"all\" | \"one-at-a-time\";\n\tsessionLocation?: string;\n\tsessionId: string;\n\tsessionName?: string;\n\tautoCompactionEnabled: boolean;\n\tmessageCount: number;\n\tpendingMessageCount: number;\n\tqueuedMessagesPaused: boolean;\n\t/** Authoritative engine trust state; absent on older RPC peers. */\n\tprojectTrusted?: boolean;\n\tresourceOverlaps?: ResourceOverlap[];\n\tresourceExtensions?: RpcResourceExtension[];\n}\n\nexport interface RpcLogoutProviderResult {\n\tprovider: string;\n\tauthStatus: AuthStatus;\n\tmodels: Model<Api>[];\n\tscopedModels?: Array<{ model: Model<Api>; thinkingLevel?: ThinkingLevel }>;\n}\n\n// ============================================================================\n// RPC Responses (stdout)\n// ============================================================================\n\n// Success responses with data\nexport type RpcResponse =\n\t// Prompting\n\t| { id?: string; type: \"response\"; command: \"prompt\"; success: true; data: { disposition: PromptDisposition } }\n\t| { id?: string; type: \"response\"; command: \"steer\"; success: true; data: { disposition: QueuedInputDisposition } }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"follow_up\";\n\t\t\tsuccess: true;\n\t\t\tdata: { disposition: QueuedInputDisposition };\n\t }\n\t| { id?: string; type: \"response\"; command: \"abort\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"new_session\"; success: true; data: { cancelled: boolean } }\n\t| { id?: string; type: \"response\"; command: \"delete_session\"; success: true }\n\n\t// State\n\t| { id?: string; type: \"response\"; command: \"get_state\"; success: true; data: RpcSessionState }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_session_summary\";\n\t\t\tsuccess: true;\n\t\t\tdata: { summary: SessionSummaryEntry | null };\n\t }\n\t| { id?: string; type: \"response\"; command: \"list_sessions\"; success: true; data: { sessions: RpcSessionInfo[] } }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"list_workflow_runs\";\n\t\t\tsuccess: true;\n\t\t\tdata: { runs: readonly WorkflowRunSummary[] };\n\t }\n\t| { id?: string; type: \"response\"; command: \"get_workflow_run_summary\"; success: true; data: WorkflowRunDetail }\n\t| { id?: string; type: \"response\"; command: \"open_task_inspector\"; success: true }\n\n\t// Model\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"set_model\";\n\t\t\tsuccess: true;\n\t\t\tdata: Model<Api>;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"cycle_model\";\n\t\t\tsuccess: true;\n\t\t\tdata: { model: Model<Api>; thinkingLevel: ThinkingLevel; isScoped: boolean } | null;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_available_models\";\n\t\t\tsuccess: true;\n\t\t\tdata: RpcModelCatalog;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"refresh_models\";\n\t\t\tsuccess: true;\n\t\t\tdata: RpcModelRefreshResult;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"login_provider\";\n\t\t\tsuccess: true;\n\t\t\tdata: RpcLoginProviderResult | RpcOAuthLoginProviderResult;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"save_provider_credential\";\n\t\t\tsuccess: true;\n\t\t\tdata: RpcModelCatalog;\n\t }\n\t| { id?: string; type: \"response\"; command: \"cancel_login_provider\"; success: true }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"logout_provider\";\n\t\t\tsuccess: true;\n\t\t\tdata: RpcLogoutProviderResult;\n\t }\n\n\t// Thinking — data-less success remains valid for older clients; isolated persist\n\t// reads the optional ACK when present.\n\t| { id?: string; type: \"response\"; command: \"set_thinking_level\"; success: true }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"set_thinking_level\";\n\t\t\tsuccess: true;\n\t\t\tdata: { level: ThinkingLevel; provider?: string; modelId?: string };\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"cycle_thinking_level\";\n\t\t\tsuccess: true;\n\t\t\tdata: { level: ThinkingLevel } | null;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_available_thinking_levels\";\n\t\t\tsuccess: true;\n\t\t\tdata: { levels: ThinkingLevel[] };\n\t }\n\n\t// Queue modes\n\t| { id?: string; type: \"response\"; command: \"set_steering_mode\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"set_follow_up_mode\"; success: true }\n\n\t// Compaction\n\t| { id?: string; type: \"response\"; command: \"compact\"; success: true; data: VerbatimCompactionResult }\n\t| { id?: string; type: \"response\"; command: \"set_auto_compaction\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"abort_compaction\"; success: true }\n\n\t// Retry\n\t| { id?: string; type: \"response\"; command: \"set_auto_retry\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"abort_retry\"; success: true }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"clear_queue\";\n\t\t\tsuccess: true;\n\t\t\tdata: { steering: string[]; followUp: string[] };\n\t }\n\t| { id?: string; type: \"response\"; command: \"pause_queued_messages\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"resume_queued_messages\"; success: true; data: { released: boolean } }\n\n\t// Bash\n\t| { id?: string; type: \"response\"; command: \"bash\"; success: true; data: BashResult }\n\t| { id?: string; type: \"response\"; command: \"user_bash\"; success: true; data: BashResult }\n\t| { id?: string; type: \"response\"; command: \"abort_bash\"; success: true }\n\n\t// Session\n\t| { id?: string; type: \"response\"; command: \"get_session_stats\"; success: true; data: SessionStats }\n\t| { id?: string; type: \"response\"; command: \"get_tools\"; success: true; data: ToolStatusReport }\n\t| { id?: string; type: \"response\"; command: \"import_session\"; success: true; data: { cancelled: boolean } }\n\t| { id?: string; type: \"response\"; command: \"export_html\"; success: true; data: { path: string } }\n\t| { id?: string; type: \"response\"; command: \"switch_session\"; success: true; data: { cancelled: boolean } }\n\t| { id?: string; type: \"response\"; command: \"fork\"; success: true; data: { text: string; cancelled: boolean } }\n\t| { id?: string; type: \"response\"; command: \"clone\"; success: true; data: { cancelled: boolean } }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_fork_messages\";\n\t\t\tsuccess: true;\n\t\t\tdata: { messages: Array<{ entryId: string; text: string }> };\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_entries\";\n\t\t\tsuccess: true;\n\t\t\tdata: { entries: SessionEntry[]; leafId: string | null };\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_tree\";\n\t\t\tsuccess: true;\n\t\t\tdata: { tree: SessionTreeNode[]; leafId: string | null };\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_last_assistant_text\";\n\t\t\tsuccess: true;\n\t\t\tdata: { text: string | null };\n\t }\n\t| { id?: string; type: \"response\"; command: \"set_session_name\"; success: true }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"navigate_tree\";\n\t\t\tsuccess: true;\n\t\t\tdata: { cancelled: boolean; editorText?: string };\n\t }\n\t| { id?: string; type: \"response\"; command: \"set_label\"; success: true; data: { entryId: string } }\n\t| { id?: string; type: \"response\"; command: \"reload\"; success: true }\n\t| { id?: string; type: \"response\"; command: \"start_pending_recovery\"; success: true; data: SessionRecoveryReport }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_shortcuts\";\n\t\t\tsuccess: true;\n\t\t\tdata: { shortcuts: Array<{ key: string; description?: string }> };\n\t }\n\t| { id?: string; type: \"response\"; command: \"invoke_shortcut\"; success: true }\n\n\t// Messages\n\t| { id?: string; type: \"response\"; command: \"get_messages\"; success: true; data: { messages: AgentMessage[] } }\n\n\t// Commands\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_commands\";\n\t\t\tsuccess: true;\n\t\t\tdata: { commands: RpcSlashCommand[] };\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: \"get_command_completions\";\n\t\t\tsuccess: true;\n\t\t\tdata: { completions: RpcAutocompleteItem[] | null };\n\t }\n\n\t// Error response (any command can fail)\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"response\";\n\t\t\tcommand: string;\n\t\t\tsuccess: false;\n\t\t\terror: string;\n\t\t\terrorCode?: \"credential_synchronization\";\n\t\t\terrorDetails?: {\n\t\t\t\tproviderId: string;\n\t\t\t\toperation: CredentialSynchronizationOperation;\n\t\t\t};\n\t };\n\n// ============================================================================\n// RPC Events (stdout)\n// ============================================================================\n\n/** Events streamed by RPC mode as session activity occurs. */\nexport type RpcEvent = JsonAgentSessionEvent;\n\n// ============================================================================\n// Extension UI Events (stdout)\n// ============================================================================\ntype RpcOAuthUIEnvelope = { type: \"extension_ui_request\"; id: string; provider: string; loginId: string };\n\nexport type RpcExtensionUIRequest =\n\t| { type: \"extension_ui_request\"; id: string; method: \"select\"; title: string; options: string[]; timeout?: number }\n\t| { type: \"extension_ui_request\"; id: string; method: \"confirm\"; title: string; message: string; timeout?: number }\n\t| {\n\t\t\ttype: \"extension_ui_request\";\n\t\t\tid: string;\n\t\t\tmethod: \"input\";\n\t\t\ttitle: string;\n\t\t\tplaceholder?: string;\n\t\t\ttimeout?: number;\n\t }\n\t| { type: \"extension_ui_request\"; id: string; method: \"editor\"; title: string; prefill?: string }\n\t| {\n\t\t\ttype: \"extension_ui_request\";\n\t\t\tid: string;\n\t\t\tmethod: \"notify\";\n\t\t\tmessage: string;\n\t\t\tnotifyType?: \"info\" | \"warning\" | \"error\";\n\t }\n\t| {\n\t\t\ttype: \"extension_ui_request\";\n\t\t\tid: string;\n\t\t\tmethod: \"setStatus\";\n\t\t\tstatusKey: string;\n\t\t\tstatusText: string | undefined;\n\t }\n\t| {\n\t\t\ttype: \"extension_ui_request\";\n\t\t\tid: string;\n\t\t\tmethod: \"setWidget\";\n\t\t\twidgetKey: string;\n\t\t\twidgetLines: string[] | undefined;\n\t\t\twidgetPlacement?: \"aboveEditor\" | \"belowEditor\";\n\t\t\twidgetScroll?: { maxHeight: number; maxHeightFraction?: number };\n\t }\n\t| { type: \"extension_ui_request\"; id: string; method: \"setTitle\"; title: string }\n\t| { type: \"extension_ui_request\"; id: string; method: \"set_editor_text\"; text: string }\n\t| (RpcOAuthUIEnvelope & { method: \"oauth_auth\"; info: OAuthAuthInfo })\n\t| (RpcOAuthUIEnvelope & { method: \"oauth_device_code\"; info: OAuthDeviceCodeInfo })\n\t| (RpcOAuthUIEnvelope & { method: \"oauth_progress\"; message: string })\n\t| (RpcOAuthUIEnvelope & { method: \"oauth_info\"; message: string; links: AuthInfoLink[] })\n\t| (RpcOAuthUIEnvelope & { method: \"oauth_prompt\"; prompt: OAuthPrompt })\n\t| (RpcOAuthUIEnvelope & { method: \"oauth_select\"; prompt: OAuthSelectPrompt })\n\t| (RpcOAuthUIEnvelope & { method: \"oauth_manual_code\" })\n\t| (RpcOAuthUIEnvelope & { method: \"oauth_manual_code_cancel\" });\n\n// ============================================================================\n// Extension UI Commands (stdin)\n// ============================================================================\n\n/** Response to an extension UI request */\nexport type RpcExtensionUIResponse =\n\t| { type: \"extension_ui_response\"; id: string; value: string }\n\t| { type: \"extension_ui_response\"; id: string; confirmed: boolean }\n\t| { type: \"extension_ui_response\"; id: string; cancelled: true };\n\n// ============================================================================\n// Helper type for extracting command types\n// ============================================================================\n\nexport type RpcCommandType = RpcCommand[\"type\"];\n"]}
@@ -9,6 +9,12 @@ export interface ChangelogEntry extends VersionParts {
9
9
  content: string;
10
10
  }
11
11
  export declare function normalizeChangelogLinks(markdown: string, version: string | ChangelogEntry): string;
12
+ /**
13
+ * The human-readable summary a release section opens with: the prose between the
14
+ * `## [x.y.z]` heading and its first `###` section. Undefined when there is none,
15
+ * so callers fall back to the full entry.
16
+ */
17
+ export declare function getChangelogHighlights(entry: ChangelogEntry): string | undefined;
12
18
  /**
13
19
  * Parse changelog entries from CHANGELOG.md
14
20
  * Scans for ## lines and collects content until next ## or EOF
@@ -1 +1 @@
1
- {"version":3,"file":"changelog.d.ts","sourceRoot":"","sources":["../../src/utils/changelog.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,YAAY;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,cAAe,SAAQ,YAAY;IACnD,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CAChB;AA2HD,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,cAAc,GAAG,MAAM,CAKlG;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,aAAa,EAAE,MAAM,GAAG,cAAc,EAAE,CA+CtE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,YAAY,GAAG,MAAM,CAQ1E;AAmBD,wBAAgB,aAAa,CAC5B,OAAO,EAAE,cAAc,EAAE,EACzB,WAAW,EAAE,MAAM,EACnB,cAAc,CAAC,EAAE,MAAM,GACrB,cAAc,EAAE,CAgBlB;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,cAAc,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,cAAc,EAAE,CAIjG;AAGD,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"changelog.d.ts","sourceRoot":"","sources":["../../src/utils/changelog.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,YAAY;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,cAAe,SAAQ,YAAY;IACnD,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CAChB;AA2HD,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,cAAc,GAAG,MAAM,CAKlG;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,GAAG,SAAS,CAKhF;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,aAAa,EAAE,MAAM,GAAG,cAAc,EAAE,CA+CtE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,YAAY,GAAG,MAAM,CAQ1E;AAmBD,wBAAgB,aAAa,CAC5B,OAAO,EAAE,cAAc,EAAE,EACzB,WAAW,EAAE,MAAM,EACnB,cAAc,CAAC,EAAE,MAAM,GACrB,cAAc,EAAE,CAgBlB;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,cAAc,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,cAAc,EAAE,CAIjG;AAGD,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC"}
@@ -105,6 +105,17 @@ export function normalizeChangelogLinks(markdown, version) {
105
105
  return `${prefix}${normalizeChangelogLinkTarget(target, tag)}${suffix}`;
106
106
  });
107
107
  }
108
+ /**
109
+ * The human-readable summary a release section opens with: the prose between the
110
+ * `## [x.y.z]` heading and its first `###` section. Undefined when there is none,
111
+ * so callers fall back to the full entry.
112
+ */
113
+ export function getChangelogHighlights(entry) {
114
+ const [, ...body] = entry.content.split("\n");
115
+ const sectionStart = body.findIndex((line) => line.startsWith("### "));
116
+ const highlights = (sectionStart === -1 ? body : body.slice(0, sectionStart)).join("\n").trim();
117
+ return highlights.length > 0 ? highlights : undefined;
118
+ }
108
119
  /**
109
120
  * Parse changelog entries from CHANGELOG.md
110
121
  * Scans for ## lines and collects content until next ## or EOF
@@ -1 +1 @@
1
- {"version":3,"file":"changelog.js","sourceRoot":"","sources":["../../src/utils/changelog.ts"],"names":[],"mappings":"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","sourcesContent":["import path from \"node:path\";\nimport { existsSync, readFileSync } from \"fs\";\n\nexport interface VersionParts {\n\tmajor: number;\n\tminor: number;\n\tpatch: number;\n\tprerelease: number | null;\n}\n\nexport interface ChangelogEntry extends VersionParts {\n\tversion: string;\n\tcontent: string;\n}\n\n// The prerelease group accepts BOTH the legacy numeric form (`-N`) and the new\n// `-alpha.N` convention while capturing the numeric revision. The outer capture\n// group preserves the raw version substring so each entry's `version` round-trips\n// faithfully (a `0.8.1-0` header stays `0.8.1-0`; a `0.8.2-alpha.1` header stays\n// `0.8.2-alpha.1`).\nconst RELEASE_VERSION_RE = /^(?:v)?((0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-(?:alpha\\.)?(0|[1-9]\\d*))?)$/;\nconst CHANGELOG_VERSION_HEADER_RE =\n\t/^##\\s+\\[?((0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-(?:alpha\\.)?(0|[1-9]\\d*))?)\\]?/;\nconst GITHUB_REPO = \"bastani-inc/atomic\";\nconst CHANGELOG_LINK_BASE_PATH = \"packages/coding-agent\";\nconst LEGACY_REPO_RE = /^https:\\/\\/github\\.com\\/(?:badlogic|earendil-works)\\/pi-mono(?=\\/|$)/;\nconst URL_SCHEME_RE = /^[a-z][a-z0-9+.-]*:/i;\nconst INLINE_MARKDOWN_LINK_RE = /(!?\\[[^\\]\\n]+\\]\\()([^\\s)]+)((?:\\s+[^)]*)?\\))/g;\n\ninterface ParsedVersion extends VersionParts {\n\tversion: string;\n}\n\nfunction parsedVersionFromMatch(match: RegExpMatchArray): ParsedVersion {\n\treturn {\n\t\tversion: match[1] as string,\n\t\tmajor: Number.parseInt(match[2] as string, 10),\n\t\tminor: Number.parseInt(match[3] as string, 10),\n\t\tpatch: Number.parseInt(match[4] as string, 10),\n\t\tprerelease: match[5] === undefined ? null : Number.parseInt(match[5], 10),\n\t};\n}\n\nfunction parseVersion(version: string): VersionParts | null {\n\tconst match = version.trim().match(RELEASE_VERSION_RE);\n\treturn match ? parsedVersionFromMatch(match) : null;\n}\n\nfunction parseVersionHeader(line: string): ParsedVersion | null {\n\tconst match = line.match(CHANGELOG_VERSION_HEADER_RE);\n\treturn match ? parsedVersionFromMatch(match) : null;\n}\n\nfunction createChangelogEntry(version: ParsedVersion, lines: string[]): ChangelogEntry {\n\treturn {\n\t\tmajor: version.major,\n\t\tminor: version.minor,\n\t\tpatch: version.patch,\n\t\tprerelease: version.prerelease,\n\t\tversion: version.version,\n\t\tcontent: lines.join(\"\\n\").trim(),\n\t};\n}\n\nfunction normalizeTag(version: string | ChangelogEntry): string {\n\tconst versionString = typeof version === \"string\" ? version : version.version;\n\treturn versionString.startsWith(\"v\") ? versionString.slice(1) : versionString;\n}\n\nfunction splitLocalTarget(target: string): { fragment: string; pathPart: string; query: string } {\n\tconst hashIndex = target.indexOf(\"#\");\n\tconst beforeHash = hashIndex === -1 ? target : target.slice(0, hashIndex);\n\tconst fragment = hashIndex === -1 ? \"\" : target.slice(hashIndex);\n\tconst queryIndex = beforeHash.indexOf(\"?\");\n\n\tif (queryIndex === -1) {\n\t\treturn { fragment, pathPart: beforeHash, query: \"\" };\n\t}\n\n\treturn {\n\t\tfragment,\n\t\tpathPart: beforeHash.slice(0, queryIndex),\n\t\tquery: beforeHash.slice(queryIndex),\n\t};\n}\n\nfunction normalizePathPart(value: string): string {\n\treturn value.replaceAll(\"\\\\\", \"/\");\n}\n\nfunction resolveRepositoryPath(targetPath: string): string | undefined {\n\tconst normalizedTarget = normalizePathPart(targetPath);\n\tconst joined = normalizedTarget.startsWith(\"/\")\n\t\t? path.posix.normalize(normalizedTarget.replace(/^\\/+/, \"\"))\n\t\t: path.posix.normalize(path.posix.join(CHANGELOG_LINK_BASE_PATH, normalizedTarget));\n\n\tif (joined === \".\" || joined.startsWith(\"../\") || joined === \"..\") {\n\t\treturn undefined;\n\t}\n\n\treturn joined;\n}\n\nfunction isDirectoryTarget(originalPath: string, repositoryPath: string): boolean {\n\tif (originalPath.endsWith(\"/\")) return true;\n\tconst basename = path.posix.basename(repositoryPath);\n\treturn !basename.includes(\".\");\n}\n\nfunction normalizeChangelogLinkTarget(target: string, tag: string): string {\n\tlet canonicalTarget = target.replace(LEGACY_REPO_RE, `https://github.com/${GITHUB_REPO}`);\n\tconst repoUrl = `https://github.com/${GITHUB_REPO}`;\n\n\tfor (const route of [\"blob\", \"tree\"]) {\n\t\tfor (const branch of [\"main\", \"master\"]) {\n\t\t\tconst floatingRefPrefix = `${repoUrl}/${route}/${branch}/`;\n\t\t\tif (canonicalTarget.startsWith(floatingRefPrefix)) {\n\t\t\t\tcanonicalTarget = `${repoUrl}/${route}/${tag}/${canonicalTarget.slice(floatingRefPrefix.length)}`;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (canonicalTarget.startsWith(\"#\") || canonicalTarget.startsWith(\"//\") || URL_SCHEME_RE.test(canonicalTarget)) {\n\t\treturn canonicalTarget;\n\t}\n\n\tconst { fragment, pathPart, query } = splitLocalTarget(canonicalTarget);\n\tif (!pathPart) return canonicalTarget;\n\n\tconst repositoryPath = resolveRepositoryPath(pathPart);\n\tif (!repositoryPath) return canonicalTarget;\n\n\tconst route = isDirectoryTarget(pathPart, repositoryPath) ? \"tree\" : \"blob\";\n\treturn `https://github.com/${GITHUB_REPO}/${route}/${tag}/${encodeURI(repositoryPath)}${query}${fragment}`;\n}\n\nexport function normalizeChangelogLinks(markdown: string, version: string | ChangelogEntry): string {\n\tconst tag = normalizeTag(version);\n\treturn markdown.replace(INLINE_MARKDOWN_LINK_RE, (_match, prefix, target, suffix) => {\n\t\treturn `${prefix}${normalizeChangelogLinkTarget(target, tag)}${suffix}`;\n\t});\n}\n\n/**\n * Parse changelog entries from CHANGELOG.md\n * Scans for ## lines and collects content until next ## or EOF\n */\nexport function parseChangelog(changelogPath: string): ChangelogEntry[] {\n\tif (!existsSync(changelogPath)) {\n\t\treturn [];\n\t}\n\n\ttry {\n\t\tconst content = readFileSync(changelogPath, \"utf-8\");\n\t\tconst lines = content.split(\"\\n\");\n\t\tconst entries: ChangelogEntry[] = [];\n\n\t\tlet currentLines: string[] = [];\n\t\tlet currentVersion: ParsedVersion | null = null;\n\n\t\tfor (const line of lines) {\n\t\t\t// Check if this is a version header (## [x.y.z] ...)\n\t\t\tif (line.startsWith(\"## \")) {\n\t\t\t\t// Save previous entry if exists\n\t\t\t\tif (currentVersion && currentLines.length > 0) {\n\t\t\t\t\tentries.push(createChangelogEntry(currentVersion, currentLines));\n\t\t\t\t}\n\n\t\t\t\t// Try to parse version from this line\n\t\t\t\tconst versionParts = parseVersionHeader(line);\n\t\t\t\tif (versionParts) {\n\t\t\t\t\tcurrentVersion = versionParts;\n\t\t\t\t\tcurrentLines = [line];\n\t\t\t\t} else {\n\t\t\t\t\t// Reset if we can't parse version\n\t\t\t\t\tcurrentVersion = null;\n\t\t\t\t\tcurrentLines = [];\n\t\t\t\t}\n\t\t\t} else if (currentVersion) {\n\t\t\t\t// Collect lines for current version\n\t\t\t\tcurrentLines.push(line);\n\t\t\t}\n\t\t}\n\n\t\t// Save last entry\n\t\tif (currentVersion && currentLines.length > 0) {\n\t\t\tentries.push(createChangelogEntry(currentVersion, currentLines));\n\t\t}\n\n\t\treturn entries;\n\t} catch (error) {\n\t\tconsole.error(`Warning: Could not parse changelog: ${error}`);\n\t\treturn [];\n\t}\n}\n\n/**\n * Compare versions. Returns: -1 if v1 < v2, 0 if v1 === v2, 1 if v1 > v2\n */\nexport function compareVersions(v1: VersionParts, v2: VersionParts): number {\n\tif (v1.major !== v2.major) return v1.major - v2.major;\n\tif (v1.minor !== v2.minor) return v1.minor - v2.minor;\n\tif (v1.patch !== v2.patch) return v1.patch - v2.patch;\n\tif (v1.prerelease === v2.prerelease) return 0;\n\tif (v1.prerelease === null) return 1;\n\tif (v2.prerelease === null) return -1;\n\treturn v1.prerelease - v2.prerelease;\n}\n\n/**\n * Get entries newer than lastVersion, optionally bounded by currentVersion.\n *\n * Atomic uses alpha prereleases (for example, 0.8.2-alpha.1, with the revision\n * starting at 1) while legacy numeric prerelease entries (for example, 0.8.1-0)\n * remain parseable, and started its own\n * version line above the upstream Pi changelog history. When currentVersion is\n * provided, changelog order wins over semantic version filtering so historical\n * upstream entries like 0.74.0 or an old 0.10.0 section are not treated as\n * newer Atomic releases.\n */\nfunction findVersionIndex(entries: ChangelogEntry[], version: string): number {\n\tconst target = parseVersion(version);\n\tif (!target) return -1;\n\treturn entries.findIndex((entry) => compareVersions(entry, target) === 0);\n}\n\nexport function getNewEntries(\n\tentries: ChangelogEntry[],\n\tlastVersion: string,\n\tcurrentVersion?: string,\n): ChangelogEntry[] {\n\tif (currentVersion) {\n\t\tconst currentIndex = findVersionIndex(entries, currentVersion);\n\t\tif (currentIndex === -1) return [];\n\n\t\tconst lastIndex = findVersionIndex(entries, lastVersion);\n\t\tif (lastIndex !== -1) {\n\t\t\treturn currentIndex < lastIndex ? entries.slice(currentIndex, lastIndex) : [];\n\t\t}\n\n\t\tconst currentEntry = entries[currentIndex];\n\t\treturn currentIndex === 0 && currentEntry ? [currentEntry] : [];\n\t}\n\n\tconst last = parseVersion(lastVersion) ?? { major: 0, minor: 0, patch: 0, prerelease: null };\n\treturn entries.filter((entry) => compareVersions(entry, last) > 0);\n}\n\nexport function getEntriesForVersion(entries: ChangelogEntry[], version: string): ChangelogEntry[] {\n\tconst target = parseVersion(version);\n\tif (!target) return [];\n\treturn entries.filter((entry) => compareVersions(entry, target) === 0);\n}\n\n// Re-export getChangelogPath from paths.ts for convenience\nexport { getChangelogPath } from \"../config.js\";\n"]}
1
+ {"version":3,"file":"changelog.js","sourceRoot":"","sources":["../../src/utils/changelog.ts"],"names":[],"mappings":"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","sourcesContent":["import path from \"node:path\";\nimport { existsSync, readFileSync } from \"fs\";\n\nexport interface VersionParts {\n\tmajor: number;\n\tminor: number;\n\tpatch: number;\n\tprerelease: number | null;\n}\n\nexport interface ChangelogEntry extends VersionParts {\n\tversion: string;\n\tcontent: string;\n}\n\n// The prerelease group accepts BOTH the legacy numeric form (`-N`) and the new\n// `-alpha.N` convention while capturing the numeric revision. The outer capture\n// group preserves the raw version substring so each entry's `version` round-trips\n// faithfully (a `0.8.1-0` header stays `0.8.1-0`; a `0.8.2-alpha.1` header stays\n// `0.8.2-alpha.1`).\nconst RELEASE_VERSION_RE = /^(?:v)?((0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-(?:alpha\\.)?(0|[1-9]\\d*))?)$/;\nconst CHANGELOG_VERSION_HEADER_RE =\n\t/^##\\s+\\[?((0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-(?:alpha\\.)?(0|[1-9]\\d*))?)\\]?/;\nconst GITHUB_REPO = \"bastani-inc/atomic\";\nconst CHANGELOG_LINK_BASE_PATH = \"packages/coding-agent\";\nconst LEGACY_REPO_RE = /^https:\\/\\/github\\.com\\/(?:badlogic|earendil-works)\\/pi-mono(?=\\/|$)/;\nconst URL_SCHEME_RE = /^[a-z][a-z0-9+.-]*:/i;\nconst INLINE_MARKDOWN_LINK_RE = /(!?\\[[^\\]\\n]+\\]\\()([^\\s)]+)((?:\\s+[^)]*)?\\))/g;\n\ninterface ParsedVersion extends VersionParts {\n\tversion: string;\n}\n\nfunction parsedVersionFromMatch(match: RegExpMatchArray): ParsedVersion {\n\treturn {\n\t\tversion: match[1] as string,\n\t\tmajor: Number.parseInt(match[2] as string, 10),\n\t\tminor: Number.parseInt(match[3] as string, 10),\n\t\tpatch: Number.parseInt(match[4] as string, 10),\n\t\tprerelease: match[5] === undefined ? null : Number.parseInt(match[5], 10),\n\t};\n}\n\nfunction parseVersion(version: string): VersionParts | null {\n\tconst match = version.trim().match(RELEASE_VERSION_RE);\n\treturn match ? parsedVersionFromMatch(match) : null;\n}\n\nfunction parseVersionHeader(line: string): ParsedVersion | null {\n\tconst match = line.match(CHANGELOG_VERSION_HEADER_RE);\n\treturn match ? parsedVersionFromMatch(match) : null;\n}\n\nfunction createChangelogEntry(version: ParsedVersion, lines: string[]): ChangelogEntry {\n\treturn {\n\t\tmajor: version.major,\n\t\tminor: version.minor,\n\t\tpatch: version.patch,\n\t\tprerelease: version.prerelease,\n\t\tversion: version.version,\n\t\tcontent: lines.join(\"\\n\").trim(),\n\t};\n}\n\nfunction normalizeTag(version: string | ChangelogEntry): string {\n\tconst versionString = typeof version === \"string\" ? version : version.version;\n\treturn versionString.startsWith(\"v\") ? versionString.slice(1) : versionString;\n}\n\nfunction splitLocalTarget(target: string): { fragment: string; pathPart: string; query: string } {\n\tconst hashIndex = target.indexOf(\"#\");\n\tconst beforeHash = hashIndex === -1 ? target : target.slice(0, hashIndex);\n\tconst fragment = hashIndex === -1 ? \"\" : target.slice(hashIndex);\n\tconst queryIndex = beforeHash.indexOf(\"?\");\n\n\tif (queryIndex === -1) {\n\t\treturn { fragment, pathPart: beforeHash, query: \"\" };\n\t}\n\n\treturn {\n\t\tfragment,\n\t\tpathPart: beforeHash.slice(0, queryIndex),\n\t\tquery: beforeHash.slice(queryIndex),\n\t};\n}\n\nfunction normalizePathPart(value: string): string {\n\treturn value.replaceAll(\"\\\\\", \"/\");\n}\n\nfunction resolveRepositoryPath(targetPath: string): string | undefined {\n\tconst normalizedTarget = normalizePathPart(targetPath);\n\tconst joined = normalizedTarget.startsWith(\"/\")\n\t\t? path.posix.normalize(normalizedTarget.replace(/^\\/+/, \"\"))\n\t\t: path.posix.normalize(path.posix.join(CHANGELOG_LINK_BASE_PATH, normalizedTarget));\n\n\tif (joined === \".\" || joined.startsWith(\"../\") || joined === \"..\") {\n\t\treturn undefined;\n\t}\n\n\treturn joined;\n}\n\nfunction isDirectoryTarget(originalPath: string, repositoryPath: string): boolean {\n\tif (originalPath.endsWith(\"/\")) return true;\n\tconst basename = path.posix.basename(repositoryPath);\n\treturn !basename.includes(\".\");\n}\n\nfunction normalizeChangelogLinkTarget(target: string, tag: string): string {\n\tlet canonicalTarget = target.replace(LEGACY_REPO_RE, `https://github.com/${GITHUB_REPO}`);\n\tconst repoUrl = `https://github.com/${GITHUB_REPO}`;\n\n\tfor (const route of [\"blob\", \"tree\"]) {\n\t\tfor (const branch of [\"main\", \"master\"]) {\n\t\t\tconst floatingRefPrefix = `${repoUrl}/${route}/${branch}/`;\n\t\t\tif (canonicalTarget.startsWith(floatingRefPrefix)) {\n\t\t\t\tcanonicalTarget = `${repoUrl}/${route}/${tag}/${canonicalTarget.slice(floatingRefPrefix.length)}`;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (canonicalTarget.startsWith(\"#\") || canonicalTarget.startsWith(\"//\") || URL_SCHEME_RE.test(canonicalTarget)) {\n\t\treturn canonicalTarget;\n\t}\n\n\tconst { fragment, pathPart, query } = splitLocalTarget(canonicalTarget);\n\tif (!pathPart) return canonicalTarget;\n\n\tconst repositoryPath = resolveRepositoryPath(pathPart);\n\tif (!repositoryPath) return canonicalTarget;\n\n\tconst route = isDirectoryTarget(pathPart, repositoryPath) ? \"tree\" : \"blob\";\n\treturn `https://github.com/${GITHUB_REPO}/${route}/${tag}/${encodeURI(repositoryPath)}${query}${fragment}`;\n}\n\nexport function normalizeChangelogLinks(markdown: string, version: string | ChangelogEntry): string {\n\tconst tag = normalizeTag(version);\n\treturn markdown.replace(INLINE_MARKDOWN_LINK_RE, (_match, prefix, target, suffix) => {\n\t\treturn `${prefix}${normalizeChangelogLinkTarget(target, tag)}${suffix}`;\n\t});\n}\n\n/**\n * The human-readable summary a release section opens with: the prose between the\n * `## [x.y.z]` heading and its first `###` section. Undefined when there is none,\n * so callers fall back to the full entry.\n */\nexport function getChangelogHighlights(entry: ChangelogEntry): string | undefined {\n\tconst [, ...body] = entry.content.split(\"\\n\");\n\tconst sectionStart = body.findIndex((line) => line.startsWith(\"### \"));\n\tconst highlights = (sectionStart === -1 ? body : body.slice(0, sectionStart)).join(\"\\n\").trim();\n\treturn highlights.length > 0 ? highlights : undefined;\n}\n\n/**\n * Parse changelog entries from CHANGELOG.md\n * Scans for ## lines and collects content until next ## or EOF\n */\nexport function parseChangelog(changelogPath: string): ChangelogEntry[] {\n\tif (!existsSync(changelogPath)) {\n\t\treturn [];\n\t}\n\n\ttry {\n\t\tconst content = readFileSync(changelogPath, \"utf-8\");\n\t\tconst lines = content.split(\"\\n\");\n\t\tconst entries: ChangelogEntry[] = [];\n\n\t\tlet currentLines: string[] = [];\n\t\tlet currentVersion: ParsedVersion | null = null;\n\n\t\tfor (const line of lines) {\n\t\t\t// Check if this is a version header (## [x.y.z] ...)\n\t\t\tif (line.startsWith(\"## \")) {\n\t\t\t\t// Save previous entry if exists\n\t\t\t\tif (currentVersion && currentLines.length > 0) {\n\t\t\t\t\tentries.push(createChangelogEntry(currentVersion, currentLines));\n\t\t\t\t}\n\n\t\t\t\t// Try to parse version from this line\n\t\t\t\tconst versionParts = parseVersionHeader(line);\n\t\t\t\tif (versionParts) {\n\t\t\t\t\tcurrentVersion = versionParts;\n\t\t\t\t\tcurrentLines = [line];\n\t\t\t\t} else {\n\t\t\t\t\t// Reset if we can't parse version\n\t\t\t\t\tcurrentVersion = null;\n\t\t\t\t\tcurrentLines = [];\n\t\t\t\t}\n\t\t\t} else if (currentVersion) {\n\t\t\t\t// Collect lines for current version\n\t\t\t\tcurrentLines.push(line);\n\t\t\t}\n\t\t}\n\n\t\t// Save last entry\n\t\tif (currentVersion && currentLines.length > 0) {\n\t\t\tentries.push(createChangelogEntry(currentVersion, currentLines));\n\t\t}\n\n\t\treturn entries;\n\t} catch (error) {\n\t\tconsole.error(`Warning: Could not parse changelog: ${error}`);\n\t\treturn [];\n\t}\n}\n\n/**\n * Compare versions. Returns: -1 if v1 < v2, 0 if v1 === v2, 1 if v1 > v2\n */\nexport function compareVersions(v1: VersionParts, v2: VersionParts): number {\n\tif (v1.major !== v2.major) return v1.major - v2.major;\n\tif (v1.minor !== v2.minor) return v1.minor - v2.minor;\n\tif (v1.patch !== v2.patch) return v1.patch - v2.patch;\n\tif (v1.prerelease === v2.prerelease) return 0;\n\tif (v1.prerelease === null) return 1;\n\tif (v2.prerelease === null) return -1;\n\treturn v1.prerelease - v2.prerelease;\n}\n\n/**\n * Get entries newer than lastVersion, optionally bounded by currentVersion.\n *\n * Atomic uses alpha prereleases (for example, 0.8.2-alpha.1, with the revision\n * starting at 1) while legacy numeric prerelease entries (for example, 0.8.1-0)\n * remain parseable, and started its own\n * version line above the upstream Pi changelog history. When currentVersion is\n * provided, changelog order wins over semantic version filtering so historical\n * upstream entries like 0.74.0 or an old 0.10.0 section are not treated as\n * newer Atomic releases.\n */\nfunction findVersionIndex(entries: ChangelogEntry[], version: string): number {\n\tconst target = parseVersion(version);\n\tif (!target) return -1;\n\treturn entries.findIndex((entry) => compareVersions(entry, target) === 0);\n}\n\nexport function getNewEntries(\n\tentries: ChangelogEntry[],\n\tlastVersion: string,\n\tcurrentVersion?: string,\n): ChangelogEntry[] {\n\tif (currentVersion) {\n\t\tconst currentIndex = findVersionIndex(entries, currentVersion);\n\t\tif (currentIndex === -1) return [];\n\n\t\tconst lastIndex = findVersionIndex(entries, lastVersion);\n\t\tif (lastIndex !== -1) {\n\t\t\treturn currentIndex < lastIndex ? entries.slice(currentIndex, lastIndex) : [];\n\t\t}\n\n\t\tconst currentEntry = entries[currentIndex];\n\t\treturn currentIndex === 0 && currentEntry ? [currentEntry] : [];\n\t}\n\n\tconst last = parseVersion(lastVersion) ?? { major: 0, minor: 0, patch: 0, prerelease: null };\n\treturn entries.filter((entry) => compareVersions(entry, last) > 0);\n}\n\nexport function getEntriesForVersion(entries: ChangelogEntry[], version: string): ChangelogEntry[] {\n\tconst target = parseVersion(version);\n\tif (!target) return [];\n\treturn entries.filter((entry) => compareVersions(entry, target) === 0);\n}\n\n// Re-export getChangelogPath from paths.ts for convenience\nexport { getChangelogPath } from \"../config.js\";\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"clipboard.d.ts","sourceRoot":"","sources":["../../src/utils/clipboard.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,KAAK,eAAe,EAAa,MAAM,uBAAuB,CAAC;AAqFxE,wBAAsB,iBAAiB,CACtC,MAAM,GAAE;IAAE,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,CAAA;CAAE,GAAG,IAAgB,GACvD,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAWxB;AAeD;;;;GAIG;AACH,wBAAsB,sBAAsB,CAC3C,MAAM,GAAE,IAAI,CAAC,eAAe,EAAE,kBAAkB,CAAC,GAAG,IAAgB,EACpE,eAAe,GAAE,MAAM,CAAC,QAA2B,GACjD,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAqB1B;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAyIjE"}
1
+ {"version":3,"file":"clipboard.d.ts","sourceRoot":"","sources":["../../src/utils/clipboard.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,KAAK,eAAe,EAAa,MAAM,uBAAuB,CAAC;AAsFxE,wBAAsB,iBAAiB,CACtC,MAAM,GAAE;IAAE,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,CAAA;CAAE,GAAG,IAAgB,GACvD,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAWxB;AAeD;;;;GAIG;AACH,wBAAsB,sBAAsB,CAC3C,MAAM,GAAE,IAAI,CAAC,eAAe,EAAE,kBAAkB,CAAC,GAAG,IAAgB,EACpE,eAAe,GAAE,MAAM,CAAC,QAA2B,GACjD,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAqB1B;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA6IjE"}
@@ -163,6 +163,9 @@ export async function copyToClipboard(text) {
163
163
  timeout: 5000,
164
164
  stdio: ["pipe", "ignore", "ignore"],
165
165
  env: createChildProcessEnvironment(),
166
+ // Clipboard writers can daemonize. Detach on POSIX so the daemon leaves Atomic's process group
167
+ // and Ctrl+Z suspend (SIGTSTP to the group) does not stop the clipboard owner (earendil-works/pi#11179).
168
+ detached: p !== "win32",
166
169
  };
167
170
  if (!copied) {
168
171
  try {
@@ -199,6 +202,7 @@ export async function copyToClipboard(text) {
199
202
  const proc = spawn("wl-copy", [], {
200
203
  stdio: ["pipe", "ignore", "ignore"],
201
204
  env: createChildProcessEnvironment(),
205
+ detached: options.detached,
202
206
  });
203
207
  let settled = false;
204
208
  const finish = (code) => {
@@ -1 +1 @@
1
- {"version":3,"file":"clipboard.js","sourceRoot":"","sources":["../../src/utils/clipboard.ts"],"names":[],"mappings":"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","sourcesContent":["import { execFile, execFileSync, execSync, spawn } from \"child_process\";\nimport { randomUUID } from \"crypto\";\nimport { unlinkSync, writeFileSync } from \"fs\";\nimport { platform, tmpdir } from \"os\";\nimport { join } from \"path\";\nimport { ENV_CLIPBOARD_OSC52, getEnvNames } from \"../config.js\";\nimport { createChildProcessEnvironment } from \"./child-process.ts\";\nimport { isWaylandSession } from \"./clipboard-image.ts\";\nimport { type ClipboardModule, clipboard } from \"./clipboard-native.ts\";\nimport { isWSL } from \"./wsl.ts\";\n\ntype NativeClipboardExecOptions = {\n\tinput: string;\n\ttimeout: number;\n\tstdio: [\"pipe\", \"ignore\", \"ignore\"];\n\tenv: NodeJS.ProcessEnv;\n};\n\nfunction copyToX11Clipboard(options: NativeClipboardExecOptions): void {\n\ttry {\n\t\texecSync(\"xclip -selection clipboard\", options);\n\t} catch {\n\t\texecSync(\"xsel --clipboard --input\", options);\n\t}\n}\n\nconst MAX_OSC52_ENCODED_LENGTH = 100_000;\n\n/**\n * Remote sessions also emit OSC 52 so the client terminal receives the copy. ATOMIC_CLIPBOARD_OSC52=1\n * (or its PI_CLIPBOARD_OSC52 alias) covers remote clients that leave no SSH markers, such as\n * multiplexer attaches or remote IDE daemons.\n */\nfunction isRemoteSession(env: NodeJS.ProcessEnv): boolean {\n\tconst forceOsc52 = getEnvNames(ENV_CLIPBOARD_OSC52)\n\t\t.map((name) => env[name])\n\t\t.find((value) => value !== undefined);\n\treturn Boolean(env.SSH_CONNECTION || env.SSH_CLIENT || env.MOSH_CONNECTION || forceOsc52 === \"1\");\n}\n\nfunction emitOsc52(text: string): boolean {\n\tconst encoded = Buffer.from(text).toString(\"base64\");\n\tif (encoded.length > MAX_OSC52_ENCODED_LENGTH) {\n\t\treturn false;\n\t}\n\tprocess.stdout.write(`\\x1b]52;c;${encoded}\\x07`);\n\treturn true;\n}\n\n/**\n * WSL without WSLg has no Linux display, so the Windows clipboard is written through\n * interop. PowerShell reads the text from a file because `clip.exe` and PowerShell stdin\n * decode piped bytes with the console code page, which mangles non-ASCII UTF-8.\n */\nfunction copyViaWindowsClipboard(text: string): boolean {\n\tconst tmpFile = join(tmpdir(), `pi-wsl-clip-${randomUUID()}.txt`);\n\tconst env = createChildProcessEnvironment();\n\ttry {\n\t\twriteFileSync(tmpFile, text, { encoding: \"utf8\", mode: 0o600 });\n\t\tconst winPath = execFileSync(\"wslpath\", [\"-w\", tmpFile], {\n\t\t\ttimeout: 1000,\n\t\t\tstdio: [\"ignore\", \"pipe\", \"ignore\"],\n\t\t\tenv,\n\t\t})\n\t\t\t.toString(\"utf8\")\n\t\t\t.trim();\n\t\tif (!winPath) return false;\n\t\tconst script = `Set-Clipboard -Value ([System.IO.File]::ReadAllText('${winPath.replaceAll(\"'\", \"''\")}', [System.Text.Encoding]::UTF8))`;\n\t\texecFileSync(\"powershell.exe\", [\"-NoProfile\", \"-Command\", script], {\n\t\t\ttimeout: 5000,\n\t\t\tstdio: [\"ignore\", \"ignore\", \"ignore\"],\n\t\t\tenv,\n\t\t});\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t} finally {\n\t\ttry {\n\t\t\tunlinkSync(tmpFile);\n\t\t} catch {\n\t\t\t// The file may not have been created.\n\t\t}\n\t}\n}\n\nfunction readTermuxClipboardText(): Promise<string | undefined> {\n\treturn new Promise((resolve) => {\n\t\texecFile(\"termux-clipboard-get\", [], { timeout: 5000, env: createChildProcessEnvironment() }, (error, stdout) =>\n\t\t\tresolve(error ? undefined : stdout),\n\t\t);\n\t});\n}\n\nexport async function readClipboardText(\n\tsource: { getText(): Promise<string> } | null = clipboard,\n): Promise<string | null> {\n\tif (process.env.TERMUX_VERSION) {\n\t\tconst text = await readTermuxClipboardText();\n\t\tif (text !== undefined) return text || null;\n\t}\n\ttry {\n\t\tif (!source) return null;\n\t\treturn await source.getText();\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/** Pasteboard type that Finder and other macOS apps publish for copied files. */\nconst FILE_URL_PASTEBOARD_TYPE = \"public.file-url\";\n\n/** Prints the POSIX paths of the file URLs on the general pasteboard as a JSON array. */\nconst READ_FILE_URLS_SCRIPT = `ObjC.import(\"AppKit\");\nconst urls = $.NSPasteboard.generalPasteboard.readObjectsForClassesOptions(\n\t$.NSArray.arrayWithObject($.NSURL),\n\t$.NSDictionary.dictionaryWithObjectForKey($.NSNumber.numberWithBool(true), $.NSPasteboardURLReadingFileURLsOnlyKey)\n);\nconst paths = [];\nfor (let i = 0; i < urls.count; i++) paths.push(ObjC.unwrap(urls.objectAtIndex(i).path));\nJSON.stringify(paths);`;\n\n/**\n * Read file paths, such as Finder file copies, from the macOS clipboard. The native clipboard\n * module reports whether file URLs are present; AppKit is read through JavaScript for Automation\n * only then, because the module cannot read file URLs itself.\n */\nexport async function readClipboardFilePaths(\n\tsource: Pick<ClipboardModule, \"availableFormats\"> | null = clipboard,\n\tcurrentPlatform: NodeJS.Platform = process.platform,\n): Promise<string[] | null> {\n\tif (currentPlatform !== \"darwin\" || !source?.availableFormats?.().includes(FILE_URL_PASTEBOARD_TYPE)) return null;\n\tconst stdout = await new Promise<string>((resolve, reject) => {\n\t\texecFile(\n\t\t\t\"osascript\",\n\t\t\t[\"-l\", \"JavaScript\", \"-e\", READ_FILE_URLS_SCRIPT],\n\t\t\t{ timeout: 5000, env: createChildProcessEnvironment() },\n\t\t\t(error, output, stderr) => {\n\t\t\t\tif (error) {\n\t\t\t\t\t// The default error message repeats the whole script; report what osascript printed instead.\n\t\t\t\t\tconst detail = stderr.trim();\n\t\t\t\t\treject(new Error(`osascript could not read the copied files${detail ? `: ${detail}` : \"\"}`));\n\t\t\t\t} else resolve(output);\n\t\t\t},\n\t\t);\n\t});\n\tconst paths = JSON.parse(stdout) as string[] | null;\n\tif (!Array.isArray(paths) || paths.some((path) => typeof path !== \"string\")) {\n\t\tthrow new Error(\"Unexpected clipboard file path output\");\n\t}\n\treturn paths.length > 0 ? paths : null;\n}\n\nexport async function copyToClipboard(text: string): Promise<void> {\n\tlet copied = false;\n\n\tconst p = platform();\n\tconst env = process.env;\n\t// Prefer direct clipboard writes. Emitting OSC 52 first can make terminals\n\t// write the same native clipboard concurrently with the addon, and very large\n\t// OSC 52 payloads can desynchronize terminal rendering.\n\t//\n\t// On Linux, skip the native addon. The underlying `clipboard-rs` crate is\n\t// X11-only and does not retain selection ownership after `set_text`\n\t// resolves, so on Wayland-only compositors (Hyprland, Niri, ...) and even\n\t// some X11 sessions the call resolves successfully without populating the\n\t// clipboard. The platform tools below (wl-copy, xclip, xsel) properly\n\t// daemonize and keep ownership.\n\ttry {\n\t\tif (clipboard && p !== \"linux\") {\n\t\t\tawait clipboard.setText(text);\n\t\t\tcopied = true;\n\t\t}\n\t} catch {\n\t\t// Fall through to platform-specific clipboard tools.\n\t}\n\n\tconst remote = isRemoteSession(env);\n\tif (copied && !remote) {\n\t\treturn;\n\t}\n\n\tconst options: NativeClipboardExecOptions = {\n\t\tinput: text,\n\t\ttimeout: 5000,\n\t\tstdio: [\"pipe\", \"ignore\", \"ignore\"],\n\t\tenv: createChildProcessEnvironment(),\n\t};\n\n\tif (!copied) {\n\t\ttry {\n\t\t\tif (p === \"darwin\") {\n\t\t\t\texecSync(\"pbcopy\", options);\n\t\t\t\tcopied = true;\n\t\t\t} else if (p === \"win32\") {\n\t\t\t\texecSync(\"clip\", options);\n\t\t\t\tcopied = true;\n\t\t\t} else {\n\t\t\t\t// Linux. Try Termux, Wayland, or X11 clipboard tools.\n\t\t\t\tif (env.TERMUX_VERSION) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\texecSync(\"termux-clipboard-set\", options);\n\t\t\t\t\t\tcopied = true;\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Fall back to Wayland or X11 tools.\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (!copied) {\n\t\t\t\t\tconst hasWaylandDisplay = Boolean(env.WAYLAND_DISPLAY);\n\t\t\t\t\tconst hasX11Display = Boolean(env.DISPLAY);\n\t\t\t\t\tconst isWayland = isWaylandSession();\n\t\t\t\t\tif (isWayland && hasWaylandDisplay) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// Verify wl-copy exists (spawn errors are async and won't be caught)\n\t\t\t\t\t\t\texecSync(\"which wl-copy\", { stdio: \"ignore\", env: createChildProcessEnvironment() });\n\t\t\t\t\t\t\t// wl-copy with execSync hangs due to fork behavior; use spawn instead.\n\t\t\t\t\t\t\t// Await its terminal event so failures can fall through to X11 or OSC 52.\n\t\t\t\t\t\t\tconst exitCode = await new Promise<number>((resolve) => {\n\t\t\t\t\t\t\t\tconst proc = spawn(\"wl-copy\", [], {\n\t\t\t\t\t\t\t\t\tstdio: [\"pipe\", \"ignore\", \"ignore\"],\n\t\t\t\t\t\t\t\t\tenv: createChildProcessEnvironment(),\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tlet settled = false;\n\t\t\t\t\t\t\t\tconst finish = (code: number) => {\n\t\t\t\t\t\t\t\t\tif (settled) return;\n\t\t\t\t\t\t\t\t\tsettled = true;\n\t\t\t\t\t\t\t\t\tresolve(code);\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\tproc.once(\"error\", () => finish(1));\n\t\t\t\t\t\t\t\tproc.once(\"close\", (code) => finish(code ?? 1));\n\t\t\t\t\t\t\t\tproc.stdin.on(\"error\", () => {});\n\t\t\t\t\t\t\t\tproc.stdin.end(text);\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (exitCode === 0) copied = true;\n\t\t\t\t\t\t\telse if (hasX11Display) {\n\t\t\t\t\t\t\t\tcopyToX11Clipboard(options);\n\t\t\t\t\t\t\t\tcopied = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\tif (hasX11Display) {\n\t\t\t\t\t\t\t\tcopyToX11Clipboard(options);\n\t\t\t\t\t\t\t\tcopied = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (hasX11Display) {\n\t\t\t\t\t\tcopyToX11Clipboard(options);\n\t\t\t\t\t\tcopied = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Fall through to OSC 52 fallback.\n\t\t}\n\t}\n\n\tlet osc52Emitted = false;\n\t// A remote session skips the Windows clipboard: the copied text belongs on the connected\n\t// client, which the OSC 52 fallback below reaches, not on the remote host.\n\tif (!copied && !remote && p === \"linux\" && isWSL(env)) {\n\t\t// Windows Terminal supports OSC 52; prefer it over the slower PowerShell round trip.\n\t\tif (env.WT_SESSION) osc52Emitted = emitOsc52(text);\n\t\tcopied = osc52Emitted || copyViaWindowsClipboard(text);\n\t}\n\t// OSC 52 cannot be verified, so a desktop session with a display reports the failure\n\t// instead. Without a display the terminal is the only clipboard route (containers,\n\t// WSL without WSLg). A remote session emits it even after a successful local write:\n\t// that write reached the remote host's display clipboard, while the user is at the\n\t// client, which only the terminal can reach. The Windows interop fallback above is\n\t// different because it is a last resort that a remote session gains nothing from.\n\tconst headless = p === \"linux\" && !env.DISPLAY && !env.WAYLAND_DISPLAY && !env.TERMUX_VERSION;\n\tlet oversized = false;\n\tif (!osc52Emitted && (remote || (!copied && headless))) {\n\t\tif (emitOsc52(text)) copied = true;\n\t\telse oversized = true;\n\t}\n\tif (copied) return;\n\tif (oversized) throw new Error(\"Clipboard unavailable: text exceeds the OSC 52 size limit\");\n\tif (env.TERMUX_VERSION) {\n\t\tthrow new Error(\"Clipboard unavailable: install the Termux:API app and `termux-api` package\");\n\t}\n\tif (p === \"linux\") {\n\t\tif (env.WAYLAND_DISPLAY) {\n\t\t\tthrow new Error(\"Clipboard unavailable: install `wl-clipboard` (`wl-copy`) or check Wayland access\");\n\t\t}\n\t\tif (env.DISPLAY) {\n\t\t\tthrow new Error(\"Clipboard unavailable: install `xclip` or `xsel`, or check X11 access\");\n\t\t}\n\t}\n\tthrow new Error(\"Clipboard unavailable\");\n}\n"]}
1
+ {"version":3,"file":"clipboard.js","sourceRoot":"","sources":["../../src/utils/clipboard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,EAAE,6BAA6B,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAwB,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACxE,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAUjC,SAAS,kBAAkB,CAAC,OAAmC;IAC9D,IAAI,CAAC;QACJ,QAAQ,CAAC,4BAA4B,EAAE,OAAO,CAAC,CAAC;IACjD,CAAC;IAAC,MAAM,CAAC;QACR,QAAQ,CAAC,0BAA0B,EAAE,OAAO,CAAC,CAAC;IAC/C,CAAC;AACF,CAAC;AAED,MAAM,wBAAwB,GAAG,OAAO,CAAC;AAEzC;;;;GAIG;AACH,SAAS,eAAe,CAAC,GAAsB;IAC9C,MAAM,UAAU,GAAG,WAAW,CAAC,mBAAmB,CAAC;SACjD,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;SACxB,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC;IACvC,OAAO,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,eAAe,IAAI,UAAU,KAAK,GAAG,CAAC,CAAC;AACnG,CAAC;AAED,SAAS,SAAS,CAAC,IAAY;IAC9B,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACrD,IAAI,OAAO,CAAC,MAAM,GAAG,wBAAwB,EAAE,CAAC;QAC/C,OAAO,KAAK,CAAC;IACd,CAAC;IACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,OAAO,MAAM,CAAC,CAAC;IACjD,OAAO,IAAI,CAAC;AACb,CAAC;AAED;;;;GAIG;AACH,SAAS,uBAAuB,CAAC,IAAY;IAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,eAAe,UAAU,EAAE,MAAM,CAAC,CAAC;IAClE,MAAM,GAAG,GAAG,6BAA6B,EAAE,CAAC;IAC5C,IAAI,CAAC;QACJ,aAAa,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAChE,MAAM,OAAO,GAAG,YAAY,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE;YACxD,OAAO,EAAE,IAAI;YACb,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC;YACnC,GAAG;SACH,CAAC;aACA,QAAQ,CAAC,MAAM,CAAC;aAChB,IAAI,EAAE,CAAC;QACT,IAAI,CAAC,OAAO;YAAE,OAAO,KAAK,CAAC;QAC3B,MAAM,MAAM,GAAG,wDAAwD,OAAO,CAAC,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,mCAAmC,CAAC;QACxI,YAAY,CAAC,gBAAgB,EAAE,CAAC,YAAY,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE;YAClE,OAAO,EAAE,IAAI;YACb,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC;YACrC,GAAG;SACH,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACb,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,KAAK,CAAC;IACd,CAAC;YAAS,CAAC;QACV,IAAI,CAAC;YACJ,UAAU,CAAC,OAAO,CAAC,CAAC;QACrB,CAAC;QAAC,MAAM,CAAC;YACR,sCAAsC;QACvC,CAAC;IACF,CAAC;AACF,CAAC;AAED,SAAS,uBAAuB;IAC/B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC9B,QAAQ,CAAC,sBAAsB,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,6BAA6B,EAAE,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAC/G,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CACnC,CAAC;IACH,CAAC,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACtC,MAAM,GAA0C,SAAS;IAEzD,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC;QAChC,MAAM,IAAI,GAAG,MAAM,uBAAuB,EAAE,CAAC;QAC7C,IAAI,IAAI,KAAK,SAAS;YAAE,OAAO,IAAI,IAAI,IAAI,CAAC;IAC7C,CAAC;IACD,IAAI,CAAC;QACJ,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QACzB,OAAO,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,IAAI,CAAC;IACb,CAAC;AACF,CAAC;AAED,iFAAiF;AACjF,MAAM,wBAAwB,GAAG,iBAAiB,CAAC;AAEnD,yFAAyF;AACzF,MAAM,qBAAqB,GAAG;;;;;;;uBAOP,CAAC;AAExB;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC3C,MAAM,GAAqD,SAAS,EACpE,eAAe,GAAoB,OAAO,CAAC,QAAQ;IAEnD,IAAI,eAAe,KAAK,QAAQ,IAAI,CAAC,MAAM,EAAE,gBAAgB,EAAE,EAAE,CAAC,QAAQ,CAAC,wBAAwB,CAAC;QAAE,OAAO,IAAI,CAAC;IAClH,MAAM,MAAM,GAAG,MAAM,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC5D,QAAQ,CACP,WAAW,EACX,CAAC,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,qBAAqB,CAAC,EACjD,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,6BAA6B,EAAE,EAAE,EACvD,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;YACzB,IAAI,KAAK,EAAE,CAAC;gBACX,6FAA6F;gBAC7F,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;gBAC7B,MAAM,CAAC,IAAI,KAAK,CAAC,4CAA4C,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;YAC9F,CAAC;;gBAAM,OAAO,CAAC,MAAM,CAAC,CAAC;QACxB,CAAC,CACD,CAAC;IACH,CAAC,CAAC,CAAC;IACH,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAoB,CAAC;IACpD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC,EAAE,CAAC;QAC7E,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AACxC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAY;IACjD,IAAI,MAAM,GAAG,KAAK,CAAC;IAEnB,MAAM,CAAC,GAAG,QAAQ,EAAE,CAAC;IACrB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IACxB,2EAA2E;IAC3E,8EAA8E;IAC9E,wDAAwD;IACxD,EAAE;IACF,0EAA0E;IAC1E,oEAAoE;IACpE,0EAA0E;IAC1E,0EAA0E;IAC1E,sEAAsE;IACtE,gCAAgC;IAChC,IAAI,CAAC;QACJ,IAAI,SAAS,IAAI,CAAC,KAAK,OAAO,EAAE,CAAC;YAChC,MAAM,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAC9B,MAAM,GAAG,IAAI,CAAC;QACf,CAAC;IACF,CAAC;IAAC,MAAM,CAAC;QACR,qDAAqD;IACtD,CAAC;IAED,MAAM,MAAM,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;IACpC,IAAI,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;QACvB,OAAO;IACR,CAAC;IAED,MAAM,OAAO,GAA+B;QAC3C,KAAK,EAAE,IAAI;QACX,OAAO,EAAE,IAAI;QACb,KAAK,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC;QACnC,GAAG,EAAE,6BAA6B,EAAE;QACpC,+FAA+F;QAC/F,yGAAyG;QACzG,QAAQ,EAAE,CAAC,KAAK,OAAO;KACvB,CAAC;IAEF,IAAI,CAAC,MAAM,EAAE,CAAC;QACb,IAAI,CAAC;YACJ,IAAI,CAAC,KAAK,QAAQ,EAAE,CAAC;gBACpB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBAC5B,MAAM,GAAG,IAAI,CAAC;YACf,CAAC;iBAAM,IAAI,CAAC,KAAK,OAAO,EAAE,CAAC;gBAC1B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAC1B,MAAM,GAAG,IAAI,CAAC;YACf,CAAC;iBAAM,CAAC;gBACP,sDAAsD;gBACtD,IAAI,GAAG,CAAC,cAAc,EAAE,CAAC;oBACxB,IAAI,CAAC;wBACJ,QAAQ,CAAC,sBAAsB,EAAE,OAAO,CAAC,CAAC;wBAC1C,MAAM,GAAG,IAAI,CAAC;oBACf,CAAC;oBAAC,MAAM,CAAC;wBACR,qCAAqC;oBACtC,CAAC;gBACF,CAAC;gBAED,IAAI,CAAC,MAAM,EAAE,CAAC;oBACb,MAAM,iBAAiB,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;oBACvD,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;oBAC3C,MAAM,SAAS,GAAG,gBAAgB,EAAE,CAAC;oBACrC,IAAI,SAAS,IAAI,iBAAiB,EAAE,CAAC;wBACpC,IAAI,CAAC;4BACJ,qEAAqE;4BACrE,QAAQ,CAAC,eAAe,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,6BAA6B,EAAE,EAAE,CAAC,CAAC;4BACrF,uEAAuE;4BACvE,0EAA0E;4BAC1E,MAAM,QAAQ,GAAG,MAAM,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,EAAE;gCACtD,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,EAAE,EAAE,EAAE;oCACjC,KAAK,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC;oCACnC,GAAG,EAAE,6BAA6B,EAAE;oCACpC,QAAQ,EAAE,OAAO,CAAC,QAAQ;iCAC1B,CAAC,CAAC;gCACH,IAAI,OAAO,GAAG,KAAK,CAAC;gCACpB,MAAM,MAAM,GAAG,CAAC,IAAY,EAAE,EAAE;oCAC/B,IAAI,OAAO;wCAAE,OAAO;oCACpB,OAAO,GAAG,IAAI,CAAC;oCACf,OAAO,CAAC,IAAI,CAAC,CAAC;gCACf,CAAC,CAAC;gCACF,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;gCACpC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;gCAChD,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;gCACjC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;4BACtB,CAAC,CAAC,CAAC;4BACH,IAAI,QAAQ,KAAK,CAAC;gCAAE,MAAM,GAAG,IAAI,CAAC;iCAC7B,IAAI,aAAa,EAAE,CAAC;gCACxB,kBAAkB,CAAC,OAAO,CAAC,CAAC;gCAC5B,MAAM,GAAG,IAAI,CAAC;4BACf,CAAC;wBACF,CAAC;wBAAC,MAAM,CAAC;4BACR,IAAI,aAAa,EAAE,CAAC;gCACnB,kBAAkB,CAAC,OAAO,CAAC,CAAC;gCAC5B,MAAM,GAAG,IAAI,CAAC;4BACf,CAAC;wBACF,CAAC;oBACF,CAAC;yBAAM,IAAI,aAAa,EAAE,CAAC;wBAC1B,kBAAkB,CAAC,OAAO,CAAC,CAAC;wBAC5B,MAAM,GAAG,IAAI,CAAC;oBACf,CAAC;gBACF,CAAC;YACF,CAAC;QACF,CAAC;QAAC,MAAM,CAAC;YACR,mCAAmC;QACpC,CAAC;IACF,CAAC;IAED,IAAI,YAAY,GAAG,KAAK,CAAC;IACzB,yFAAyF;IACzF,2EAA2E;IAC3E,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK,OAAO,IAAI,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACvD,qFAAqF;QACrF,IAAI,GAAG,CAAC,UAAU;YAAE,YAAY,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QACnD,MAAM,GAAG,YAAY,IAAI,uBAAuB,CAAC,IAAI,CAAC,CAAC;IACxD,CAAC;IACD,qFAAqF;IACrF,mFAAmF;IACnF,oFAAoF;IACpF,mFAAmF;IACnF,mFAAmF;IACnF,kFAAkF;IAClF,MAAM,QAAQ,GAAG,CAAC,KAAK,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,eAAe,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC;IAC9F,IAAI,SAAS,GAAG,KAAK,CAAC;IACtB,IAAI,CAAC,YAAY,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,MAAM,IAAI,QAAQ,CAAC,CAAC,EAAE,CAAC;QACxD,IAAI,SAAS,CAAC,IAAI,CAAC;YAAE,MAAM,GAAG,IAAI,CAAC;;YAC9B,SAAS,GAAG,IAAI,CAAC;IACvB,CAAC;IACD,IAAI,MAAM;QAAE,OAAO;IACnB,IAAI,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;IAC5F,IAAI,GAAG,CAAC,cAAc,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,4EAA4E,CAAC,CAAC;IAC/F,CAAC;IACD,IAAI,CAAC,KAAK,OAAO,EAAE,CAAC;QACnB,IAAI,GAAG,CAAC,eAAe,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,mFAAmF,CAAC,CAAC;QACtG,CAAC;QACD,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,uEAAuE,CAAC,CAAC;QAC1F,CAAC;IACF,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;AAC1C,CAAC","sourcesContent":["import { execFile, execFileSync, execSync, spawn } from \"child_process\";\nimport { randomUUID } from \"crypto\";\nimport { unlinkSync, writeFileSync } from \"fs\";\nimport { platform, tmpdir } from \"os\";\nimport { join } from \"path\";\nimport { ENV_CLIPBOARD_OSC52, getEnvNames } from \"../config.js\";\nimport { createChildProcessEnvironment } from \"./child-process.ts\";\nimport { isWaylandSession } from \"./clipboard-image.ts\";\nimport { type ClipboardModule, clipboard } from \"./clipboard-native.ts\";\nimport { isWSL } from \"./wsl.ts\";\n\ntype NativeClipboardExecOptions = {\n\tinput: string;\n\ttimeout: number;\n\tstdio: [\"pipe\", \"ignore\", \"ignore\"];\n\tenv: NodeJS.ProcessEnv;\n\tdetached: boolean;\n};\n\nfunction copyToX11Clipboard(options: NativeClipboardExecOptions): void {\n\ttry {\n\t\texecSync(\"xclip -selection clipboard\", options);\n\t} catch {\n\t\texecSync(\"xsel --clipboard --input\", options);\n\t}\n}\n\nconst MAX_OSC52_ENCODED_LENGTH = 100_000;\n\n/**\n * Remote sessions also emit OSC 52 so the client terminal receives the copy. ATOMIC_CLIPBOARD_OSC52=1\n * (or its PI_CLIPBOARD_OSC52 alias) covers remote clients that leave no SSH markers, such as\n * multiplexer attaches or remote IDE daemons.\n */\nfunction isRemoteSession(env: NodeJS.ProcessEnv): boolean {\n\tconst forceOsc52 = getEnvNames(ENV_CLIPBOARD_OSC52)\n\t\t.map((name) => env[name])\n\t\t.find((value) => value !== undefined);\n\treturn Boolean(env.SSH_CONNECTION || env.SSH_CLIENT || env.MOSH_CONNECTION || forceOsc52 === \"1\");\n}\n\nfunction emitOsc52(text: string): boolean {\n\tconst encoded = Buffer.from(text).toString(\"base64\");\n\tif (encoded.length > MAX_OSC52_ENCODED_LENGTH) {\n\t\treturn false;\n\t}\n\tprocess.stdout.write(`\\x1b]52;c;${encoded}\\x07`);\n\treturn true;\n}\n\n/**\n * WSL without WSLg has no Linux display, so the Windows clipboard is written through\n * interop. PowerShell reads the text from a file because `clip.exe` and PowerShell stdin\n * decode piped bytes with the console code page, which mangles non-ASCII UTF-8.\n */\nfunction copyViaWindowsClipboard(text: string): boolean {\n\tconst tmpFile = join(tmpdir(), `pi-wsl-clip-${randomUUID()}.txt`);\n\tconst env = createChildProcessEnvironment();\n\ttry {\n\t\twriteFileSync(tmpFile, text, { encoding: \"utf8\", mode: 0o600 });\n\t\tconst winPath = execFileSync(\"wslpath\", [\"-w\", tmpFile], {\n\t\t\ttimeout: 1000,\n\t\t\tstdio: [\"ignore\", \"pipe\", \"ignore\"],\n\t\t\tenv,\n\t\t})\n\t\t\t.toString(\"utf8\")\n\t\t\t.trim();\n\t\tif (!winPath) return false;\n\t\tconst script = `Set-Clipboard -Value ([System.IO.File]::ReadAllText('${winPath.replaceAll(\"'\", \"''\")}', [System.Text.Encoding]::UTF8))`;\n\t\texecFileSync(\"powershell.exe\", [\"-NoProfile\", \"-Command\", script], {\n\t\t\ttimeout: 5000,\n\t\t\tstdio: [\"ignore\", \"ignore\", \"ignore\"],\n\t\t\tenv,\n\t\t});\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t} finally {\n\t\ttry {\n\t\t\tunlinkSync(tmpFile);\n\t\t} catch {\n\t\t\t// The file may not have been created.\n\t\t}\n\t}\n}\n\nfunction readTermuxClipboardText(): Promise<string | undefined> {\n\treturn new Promise((resolve) => {\n\t\texecFile(\"termux-clipboard-get\", [], { timeout: 5000, env: createChildProcessEnvironment() }, (error, stdout) =>\n\t\t\tresolve(error ? undefined : stdout),\n\t\t);\n\t});\n}\n\nexport async function readClipboardText(\n\tsource: { getText(): Promise<string> } | null = clipboard,\n): Promise<string | null> {\n\tif (process.env.TERMUX_VERSION) {\n\t\tconst text = await readTermuxClipboardText();\n\t\tif (text !== undefined) return text || null;\n\t}\n\ttry {\n\t\tif (!source) return null;\n\t\treturn await source.getText();\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/** Pasteboard type that Finder and other macOS apps publish for copied files. */\nconst FILE_URL_PASTEBOARD_TYPE = \"public.file-url\";\n\n/** Prints the POSIX paths of the file URLs on the general pasteboard as a JSON array. */\nconst READ_FILE_URLS_SCRIPT = `ObjC.import(\"AppKit\");\nconst urls = $.NSPasteboard.generalPasteboard.readObjectsForClassesOptions(\n\t$.NSArray.arrayWithObject($.NSURL),\n\t$.NSDictionary.dictionaryWithObjectForKey($.NSNumber.numberWithBool(true), $.NSPasteboardURLReadingFileURLsOnlyKey)\n);\nconst paths = [];\nfor (let i = 0; i < urls.count; i++) paths.push(ObjC.unwrap(urls.objectAtIndex(i).path));\nJSON.stringify(paths);`;\n\n/**\n * Read file paths, such as Finder file copies, from the macOS clipboard. The native clipboard\n * module reports whether file URLs are present; AppKit is read through JavaScript for Automation\n * only then, because the module cannot read file URLs itself.\n */\nexport async function readClipboardFilePaths(\n\tsource: Pick<ClipboardModule, \"availableFormats\"> | null = clipboard,\n\tcurrentPlatform: NodeJS.Platform = process.platform,\n): Promise<string[] | null> {\n\tif (currentPlatform !== \"darwin\" || !source?.availableFormats?.().includes(FILE_URL_PASTEBOARD_TYPE)) return null;\n\tconst stdout = await new Promise<string>((resolve, reject) => {\n\t\texecFile(\n\t\t\t\"osascript\",\n\t\t\t[\"-l\", \"JavaScript\", \"-e\", READ_FILE_URLS_SCRIPT],\n\t\t\t{ timeout: 5000, env: createChildProcessEnvironment() },\n\t\t\t(error, output, stderr) => {\n\t\t\t\tif (error) {\n\t\t\t\t\t// The default error message repeats the whole script; report what osascript printed instead.\n\t\t\t\t\tconst detail = stderr.trim();\n\t\t\t\t\treject(new Error(`osascript could not read the copied files${detail ? `: ${detail}` : \"\"}`));\n\t\t\t\t} else resolve(output);\n\t\t\t},\n\t\t);\n\t});\n\tconst paths = JSON.parse(stdout) as string[] | null;\n\tif (!Array.isArray(paths) || paths.some((path) => typeof path !== \"string\")) {\n\t\tthrow new Error(\"Unexpected clipboard file path output\");\n\t}\n\treturn paths.length > 0 ? paths : null;\n}\n\nexport async function copyToClipboard(text: string): Promise<void> {\n\tlet copied = false;\n\n\tconst p = platform();\n\tconst env = process.env;\n\t// Prefer direct clipboard writes. Emitting OSC 52 first can make terminals\n\t// write the same native clipboard concurrently with the addon, and very large\n\t// OSC 52 payloads can desynchronize terminal rendering.\n\t//\n\t// On Linux, skip the native addon. The underlying `clipboard-rs` crate is\n\t// X11-only and does not retain selection ownership after `set_text`\n\t// resolves, so on Wayland-only compositors (Hyprland, Niri, ...) and even\n\t// some X11 sessions the call resolves successfully without populating the\n\t// clipboard. The platform tools below (wl-copy, xclip, xsel) properly\n\t// daemonize and keep ownership.\n\ttry {\n\t\tif (clipboard && p !== \"linux\") {\n\t\t\tawait clipboard.setText(text);\n\t\t\tcopied = true;\n\t\t}\n\t} catch {\n\t\t// Fall through to platform-specific clipboard tools.\n\t}\n\n\tconst remote = isRemoteSession(env);\n\tif (copied && !remote) {\n\t\treturn;\n\t}\n\n\tconst options: NativeClipboardExecOptions = {\n\t\tinput: text,\n\t\ttimeout: 5000,\n\t\tstdio: [\"pipe\", \"ignore\", \"ignore\"],\n\t\tenv: createChildProcessEnvironment(),\n\t\t// Clipboard writers can daemonize. Detach on POSIX so the daemon leaves Atomic's process group\n\t\t// and Ctrl+Z suspend (SIGTSTP to the group) does not stop the clipboard owner (earendil-works/pi#11179).\n\t\tdetached: p !== \"win32\",\n\t};\n\n\tif (!copied) {\n\t\ttry {\n\t\t\tif (p === \"darwin\") {\n\t\t\t\texecSync(\"pbcopy\", options);\n\t\t\t\tcopied = true;\n\t\t\t} else if (p === \"win32\") {\n\t\t\t\texecSync(\"clip\", options);\n\t\t\t\tcopied = true;\n\t\t\t} else {\n\t\t\t\t// Linux. Try Termux, Wayland, or X11 clipboard tools.\n\t\t\t\tif (env.TERMUX_VERSION) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\texecSync(\"termux-clipboard-set\", options);\n\t\t\t\t\t\tcopied = true;\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Fall back to Wayland or X11 tools.\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (!copied) {\n\t\t\t\t\tconst hasWaylandDisplay = Boolean(env.WAYLAND_DISPLAY);\n\t\t\t\t\tconst hasX11Display = Boolean(env.DISPLAY);\n\t\t\t\t\tconst isWayland = isWaylandSession();\n\t\t\t\t\tif (isWayland && hasWaylandDisplay) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// Verify wl-copy exists (spawn errors are async and won't be caught)\n\t\t\t\t\t\t\texecSync(\"which wl-copy\", { stdio: \"ignore\", env: createChildProcessEnvironment() });\n\t\t\t\t\t\t\t// wl-copy with execSync hangs due to fork behavior; use spawn instead.\n\t\t\t\t\t\t\t// Await its terminal event so failures can fall through to X11 or OSC 52.\n\t\t\t\t\t\t\tconst exitCode = await new Promise<number>((resolve) => {\n\t\t\t\t\t\t\t\tconst proc = spawn(\"wl-copy\", [], {\n\t\t\t\t\t\t\t\t\tstdio: [\"pipe\", \"ignore\", \"ignore\"],\n\t\t\t\t\t\t\t\t\tenv: createChildProcessEnvironment(),\n\t\t\t\t\t\t\t\t\tdetached: options.detached,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tlet settled = false;\n\t\t\t\t\t\t\t\tconst finish = (code: number) => {\n\t\t\t\t\t\t\t\t\tif (settled) return;\n\t\t\t\t\t\t\t\t\tsettled = true;\n\t\t\t\t\t\t\t\t\tresolve(code);\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\tproc.once(\"error\", () => finish(1));\n\t\t\t\t\t\t\t\tproc.once(\"close\", (code) => finish(code ?? 1));\n\t\t\t\t\t\t\t\tproc.stdin.on(\"error\", () => {});\n\t\t\t\t\t\t\t\tproc.stdin.end(text);\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (exitCode === 0) copied = true;\n\t\t\t\t\t\t\telse if (hasX11Display) {\n\t\t\t\t\t\t\t\tcopyToX11Clipboard(options);\n\t\t\t\t\t\t\t\tcopied = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\tif (hasX11Display) {\n\t\t\t\t\t\t\t\tcopyToX11Clipboard(options);\n\t\t\t\t\t\t\t\tcopied = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (hasX11Display) {\n\t\t\t\t\t\tcopyToX11Clipboard(options);\n\t\t\t\t\t\tcopied = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Fall through to OSC 52 fallback.\n\t\t}\n\t}\n\n\tlet osc52Emitted = false;\n\t// A remote session skips the Windows clipboard: the copied text belongs on the connected\n\t// client, which the OSC 52 fallback below reaches, not on the remote host.\n\tif (!copied && !remote && p === \"linux\" && isWSL(env)) {\n\t\t// Windows Terminal supports OSC 52; prefer it over the slower PowerShell round trip.\n\t\tif (env.WT_SESSION) osc52Emitted = emitOsc52(text);\n\t\tcopied = osc52Emitted || copyViaWindowsClipboard(text);\n\t}\n\t// OSC 52 cannot be verified, so a desktop session with a display reports the failure\n\t// instead. Without a display the terminal is the only clipboard route (containers,\n\t// WSL without WSLg). A remote session emits it even after a successful local write:\n\t// that write reached the remote host's display clipboard, while the user is at the\n\t// client, which only the terminal can reach. The Windows interop fallback above is\n\t// different because it is a last resort that a remote session gains nothing from.\n\tconst headless = p === \"linux\" && !env.DISPLAY && !env.WAYLAND_DISPLAY && !env.TERMUX_VERSION;\n\tlet oversized = false;\n\tif (!osc52Emitted && (remote || (!copied && headless))) {\n\t\tif (emitOsc52(text)) copied = true;\n\t\telse oversized = true;\n\t}\n\tif (copied) return;\n\tif (oversized) throw new Error(\"Clipboard unavailable: text exceeds the OSC 52 size limit\");\n\tif (env.TERMUX_VERSION) {\n\t\tthrow new Error(\"Clipboard unavailable: install the Termux:API app and `termux-api` package\");\n\t}\n\tif (p === \"linux\") {\n\t\tif (env.WAYLAND_DISPLAY) {\n\t\t\tthrow new Error(\"Clipboard unavailable: install `wl-clipboard` (`wl-copy`) or check Wayland access\");\n\t\t}\n\t\tif (env.DISPLAY) {\n\t\t\tthrow new Error(\"Clipboard unavailable: install `xclip` or `xsel`, or check X11 access\");\n\t\t}\n\t}\n\tthrow new Error(\"Clipboard unavailable\");\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"tools-manager.d.ts","sourceRoot":"","sources":["../../src/utils/tools-manager.ts"],"names":[],"mappings":"AAkFA,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAmB5D;AAID,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAkBpE;AAwMD,0EAA0E;AAC1E,MAAM,WAAW,UAAU;IAC1B,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;GASG;AACH,wBAAsB,UAAU,CAC/B,IAAI,EAAE,IAAI,GAAG,IAAI,EACjB,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,GACrC,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAgD7B"}
1
+ {"version":3,"file":"tools-manager.d.ts","sourceRoot":"","sources":["../../src/utils/tools-manager.ts"],"names":[],"mappings":"AAmFA,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAmB5D;AAID,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAkBpE;AAwMD,0EAA0E;AAC1E,MAAM,WAAW,UAAU;IAC1B,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;GASG;AACH,wBAAsB,UAAU,CAC/B,IAAI,EAAE,IAAI,GAAG,IAAI,EACjB,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,GACrC,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAgD7B"}
@@ -3,9 +3,10 @@ import { chmodSync, existsSync, mkdirSync, readdirSync, renameSync, rmSync } fro
3
3
  import { writeFile } from "fs/promises";
4
4
  import { arch, platform } from "os";
5
5
  import { join } from "path";
6
- import { APP_NAME, ENV_OFFLINE, getBinDir, getEnvValue } from "../config.js";
6
+ import { ENV_OFFLINE, getBinDir, getEnvValue, VERSION } from "../config.js";
7
7
  import { createChildProcessEnvironment } from "./child-process.js";
8
8
  import { fetchWithRetry } from "./management-http.js";
9
+ import { getPiUserAgent } from "./pi-user-agent.js";
9
10
  const TOOLS_DIR = getBinDir();
10
11
  const NETWORK_TIMEOUT_MS = 10_000;
11
12
  const DOWNLOAD_TIMEOUT_MS = 120_000;
@@ -93,7 +94,7 @@ export function getToolPath(tool) {
93
94
  // Resolve the latest release version from the release page redirect, avoiding
94
95
  // the anonymous api.github.com quota shared by corporate proxies and CI runners.
95
96
  export async function getLatestVersion(repo) {
96
- const response = await fetchWithRetry(`https://github.com/${repo}/releases/latest`, { headers: { "User-Agent": APP_NAME }, redirect: "manual" }, { timeoutMs: NETWORK_TIMEOUT_MS });
97
+ const response = await fetchWithRetry(`https://github.com/${repo}/releases/latest`, { headers: { "User-Agent": getPiUserAgent(VERSION) }, redirect: "manual" }, { timeoutMs: NETWORK_TIMEOUT_MS });
97
98
  try {
98
99
  await response.body?.cancel();
99
100
  }
@@ -1 +1 @@
1
- {"version":3,"file":"tools-manager.js","sourceRoot":"","sources":["../../src/utils/tools-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import { type SpawnSyncReturns, spawnSync } from \"child_process\";\nimport { chmodSync, existsSync, mkdirSync, readdirSync, renameSync, rmSync } from \"fs\";\nimport { writeFile } from \"fs/promises\";\nimport { arch, platform } from \"os\";\nimport { join } from \"path\";\nimport { APP_NAME, ENV_OFFLINE, getBinDir, getEnvValue } from \"../config.js\";\nimport { createChildProcessEnvironment } from \"./child-process.ts\";\nimport { fetchWithRetry } from \"./management-http.ts\";\n\nconst TOOLS_DIR = getBinDir();\nconst NETWORK_TIMEOUT_MS = 10_000;\nconst DOWNLOAD_TIMEOUT_MS = 120_000;\n\nfunction isOfflineModeEnabled(): boolean {\n\tconst value = getEnvValue(ENV_OFFLINE);\n\tif (!value) return false;\n\treturn value === \"1\" || value.toLowerCase() === \"true\" || value.toLowerCase() === \"yes\";\n}\n\ninterface ToolConfig {\n\tname: string;\n\trepo: string; // GitHub repo (e.g., \"sharkdp/fd\")\n\tbinaryName: string; // Name of the binary inside the archive\n\tsystemBinaryNames?: string[]; // Alternative system command names to try before downloading\n\ttagPrefix: string; // Prefix for tags (e.g., \"v\" for v1.0.0, \"\" for 1.0.0)\n\tgetAssetName: (version: string, plat: string, architecture: string) => string | null;\n}\n\nconst TOOLS: Record<string, ToolConfig> = {\n\tfd: {\n\t\tname: \"fd\",\n\t\trepo: \"sharkdp/fd\",\n\t\tbinaryName: \"fd\",\n\t\tsystemBinaryNames: [\"fd\", \"fdfind\"],\n\t\ttagPrefix: \"v\",\n\t\tgetAssetName: (version, plat, architecture) => {\n\t\t\tif (plat === \"darwin\") {\n\t\t\t\tconst archStr = architecture === \"arm64\" ? \"aarch64\" : \"x86_64\";\n\t\t\t\treturn `fd-v${version}-${archStr}-apple-darwin.tar.gz`;\n\t\t\t} else if (plat === \"linux\") {\n\t\t\t\tconst archStr = architecture === \"arm64\" ? \"aarch64\" : \"x86_64\";\n\t\t\t\treturn `fd-v${version}-${archStr}-unknown-linux-musl.tar.gz`;\n\t\t\t} else if (plat === \"win32\") {\n\t\t\t\tconst archStr = architecture === \"arm64\" ? \"aarch64\" : \"x86_64\";\n\t\t\t\treturn `fd-v${version}-${archStr}-pc-windows-msvc.zip`;\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\t},\n\trg: {\n\t\tname: \"ripgrep\",\n\t\trepo: \"BurntSushi/ripgrep\",\n\t\tbinaryName: \"rg\",\n\t\ttagPrefix: \"\",\n\t\tgetAssetName: (version, plat, architecture) => {\n\t\t\tif (plat === \"darwin\") {\n\t\t\t\tconst archStr = architecture === \"arm64\" ? \"aarch64\" : \"x86_64\";\n\t\t\t\treturn `ripgrep-${version}-${archStr}-apple-darwin.tar.gz`;\n\t\t\t} else if (plat === \"linux\") {\n\t\t\t\tconst archStr = architecture === \"arm64\" ? \"aarch64\" : \"x86_64\";\n\t\t\t\treturn `ripgrep-${version}-${archStr}-unknown-linux-musl.tar.gz`;\n\t\t\t} else if (plat === \"win32\") {\n\t\t\t\tconst archStr = architecture === \"arm64\" ? \"aarch64\" : \"x86_64\";\n\t\t\t\treturn `ripgrep-${version}-${archStr}-pc-windows-msvc.zip`;\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\t},\n};\n\n// Check if a command exists in PATH by trying to run it\nfunction commandExists(cmd: string): boolean {\n\ttry {\n\t\tconst result = spawnSync(cmd, [\"--version\"], { stdio: \"pipe\", env: createChildProcessEnvironment() });\n\t\t// Check for ENOENT error (command not found)\n\t\treturn result.error === undefined || result.error === null;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n// Get the path to a tool (system-wide or in our tools dir)\nexport function getToolPath(tool: \"fd\" | \"rg\"): string | null {\n\tconst config = TOOLS[tool];\n\tif (!config) return null;\n\n\t// Check our tools directory first\n\tconst localPath = join(TOOLS_DIR, config.binaryName + (platform() === \"win32\" ? \".exe\" : \"\"));\n\tif (existsSync(localPath)) {\n\t\treturn localPath;\n\t}\n\n\t// Check system PATH - if found, just return the command name (it's in PATH)\n\tconst systemBinaryNames = config.systemBinaryNames ?? [config.binaryName];\n\tfor (const systemBinaryName of systemBinaryNames) {\n\t\tif (commandExists(systemBinaryName)) {\n\t\t\treturn systemBinaryName;\n\t\t}\n\t}\n\n\treturn null;\n}\n\n// Resolve the latest release version from the release page redirect, avoiding\n// the anonymous api.github.com quota shared by corporate proxies and CI runners.\nexport async function getLatestVersion(repo: string): Promise<string> {\n\tconst response = await fetchWithRetry(\n\t\t`https://github.com/${repo}/releases/latest`,\n\t\t{ headers: { \"User-Agent\": APP_NAME }, redirect: \"manual\" },\n\t\t{ timeoutMs: NETWORK_TIMEOUT_MS },\n\t);\n\ttry {\n\t\tawait response.body?.cancel();\n\t} catch {\n\t\t// Discarding the redirect body is best-effort.\n\t}\n\tconst location = response.status >= 300 && response.status < 400 ? response.headers.get(\"location\") : null;\n\tif (!location) throw new Error(`Failed to resolve latest ${repo} release: HTTP ${response.status} without redirect`);\n\tconst tag = new URL(location, \"https://github.com\").pathname.split(\"/\").pop();\n\tif (!tag || !location.includes(\"/releases/tag/\")) {\n\t\tthrow new Error(`Failed to resolve latest ${repo} release: unexpected redirect to ${location}`);\n\t}\n\treturn decodeURIComponent(tag).replace(/^v/, \"\");\n}\n\n// Download a file from URL\nasync function downloadFile(url: string, dest: string): Promise<void> {\n\tconst response = await fetchWithRetry(url, undefined, { timeoutMs: DOWNLOAD_TIMEOUT_MS });\n\n\tif (!response.ok) {\n\t\tthrow new Error(`Download failed with HTTP ${response.status}: ${url}`);\n\t}\n\n\tif (!response.body) {\n\t\tthrow new Error(\"No response body\");\n\t}\n\n\tawait writeFile(dest, Buffer.from(await response.arrayBuffer()));\n}\n\nfunction findBinaryRecursively(rootDir: string, binaryFileName: string): string | null {\n\tconst stack: string[] = [rootDir];\n\n\twhile (stack.length > 0) {\n\t\tconst currentDir = stack.pop();\n\t\tif (!currentDir) continue;\n\n\t\tconst entries = readdirSync(currentDir, { withFileTypes: true });\n\t\tfor (const entry of entries) {\n\t\t\tconst fullPath = join(currentDir, entry.name);\n\t\t\tif (entry.isFile() && entry.name === binaryFileName) {\n\t\t\t\treturn fullPath;\n\t\t\t}\n\t\t\tif (entry.isDirectory()) {\n\t\t\t\tstack.push(fullPath);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn null;\n}\n\nfunction formatSpawnFailure(result: SpawnSyncReturns<Buffer>): string {\n\tif (result.error?.message) {\n\t\treturn result.error.message;\n\t}\n\tconst stderr = result.stderr?.toString().trim();\n\tif (stderr) {\n\t\treturn stderr;\n\t}\n\tconst stdout = result.stdout?.toString().trim();\n\tif (stdout) {\n\t\treturn stdout;\n\t}\n\treturn `exit status ${result.status ?? \"unknown\"}`;\n}\n\nfunction runExtractionCommand(command: string, args: string[]): string | null {\n\tconst result = spawnSync(command, args, { stdio: \"pipe\", env: createChildProcessEnvironment() });\n\tif (!result.error && result.status === 0) {\n\t\treturn null;\n\t}\n\treturn `${command}: ${formatSpawnFailure(result)}`;\n}\n\nfunction extractTarGzArchive(archivePath: string, extractDir: string, assetName: string): void {\n\tconst failure = runExtractionCommand(\"tar\", [\"xzf\", archivePath, \"-C\", extractDir]);\n\tif (failure) {\n\t\tthrow new Error(`Failed to extract ${assetName}: ${failure}`);\n\t}\n}\n\nfunction getWindowsTarCommand(): string {\n\tconst systemRoot = process.env.SystemRoot;\n\tif (systemRoot) {\n\t\tconst systemTar = join(systemRoot, \"System32\", \"tar.exe\");\n\t\tif (existsSync(systemTar)) {\n\t\t\treturn systemTar;\n\t\t}\n\t}\n\treturn \"tar.exe\";\n}\n\nfunction extractZipArchive(archivePath: string, extractDir: string, assetName: string): void {\n\tconst failures: string[] = [];\n\n\tif (platform() === \"win32\") {\n\t\t// Windows ships bsdtar as tar.exe, which supports zip files. Prefer the\n\t\t// System32 binary over Git Bash's GNU tar, which does not handle zip archives.\n\t\tconst tarFailure = runExtractionCommand(getWindowsTarCommand(), [\"xf\", archivePath, \"-C\", extractDir]);\n\t\tif (!tarFailure) return;\n\t\tfailures.push(tarFailure);\n\n\t\tconst script =\n\t\t\t\"& { param($archive, $destination) $ErrorActionPreference = 'Stop'; Expand-Archive -LiteralPath $archive -DestinationPath $destination -Force }\";\n\t\tconst powershellFailure = runExtractionCommand(\"powershell.exe\", [\n\t\t\t\"-NoLogo\",\n\t\t\t\"-NoProfile\",\n\t\t\t\"-NonInteractive\",\n\t\t\t\"-ExecutionPolicy\",\n\t\t\t\"Bypass\",\n\t\t\t\"-Command\",\n\t\t\tscript,\n\t\t\tarchivePath,\n\t\t\textractDir,\n\t\t]);\n\t\tif (!powershellFailure) return;\n\t\tfailures.push(powershellFailure);\n\t} else {\n\t\tconst unzipFailure = runExtractionCommand(\"unzip\", [\"-q\", archivePath, \"-d\", extractDir]);\n\t\tif (!unzipFailure) return;\n\t\tfailures.push(unzipFailure);\n\n\t\tconst tarFailure = runExtractionCommand(\"tar\", [\"xf\", archivePath, \"-C\", extractDir]);\n\t\tif (!tarFailure) return;\n\t\tfailures.push(tarFailure);\n\t}\n\n\tthrow new Error(`Failed to extract ${assetName}: ${failures.join(\"; \")}`);\n}\n\n// Download and install a tool\nasync function downloadTool(tool: \"fd\" | \"rg\"): Promise<string> {\n\tconst config = TOOLS[tool];\n\tif (!config) throw new Error(`Unknown tool: ${tool}`);\n\n\tconst plat = platform();\n\tconst architecture = arch();\n\n\t// fd is pinned on darwin/x64; skip the version lookup there.\n\tconst version =\n\t\ttool === \"fd\" && plat === \"darwin\" && architecture === \"x64\" ? \"10.3.0\" : await getLatestVersion(config.repo);\n\n\t// Get asset name for this platform\n\tconst assetName = config.getAssetName(version, plat, architecture);\n\tif (!assetName) {\n\t\tthrow new Error(`Unsupported platform: ${plat}/${architecture}`);\n\t}\n\n\t// Create tools directory\n\tmkdirSync(TOOLS_DIR, { recursive: true });\n\n\tconst downloadUrl = `https://github.com/${config.repo}/releases/download/${config.tagPrefix}${version}/${assetName}`;\n\tconst archivePath = join(TOOLS_DIR, assetName);\n\tconst binaryExt = plat === \"win32\" ? \".exe\" : \"\";\n\tconst binaryPath = join(TOOLS_DIR, config.binaryName + binaryExt);\n\n\t// Download\n\tawait downloadFile(downloadUrl, archivePath);\n\n\t// Extract into a unique temp directory. fd and rg downloads can run concurrently\n\t// during startup, so sharing a fixed directory causes races.\n\tconst extractDir = join(\n\t\tTOOLS_DIR,\n\t\t`extract_tmp_${config.binaryName}_${process.pid}_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`,\n\t);\n\tmkdirSync(extractDir, { recursive: true });\n\n\ttry {\n\t\tif (assetName.endsWith(\".tar.gz\")) {\n\t\t\textractTarGzArchive(archivePath, extractDir, assetName);\n\t\t} else if (assetName.endsWith(\".zip\")) {\n\t\t\textractZipArchive(archivePath, extractDir, assetName);\n\t\t} else {\n\t\t\tthrow new Error(`Unsupported archive format: ${assetName}`);\n\t\t}\n\n\t\t// Find the binary in extracted files. Some archives contain files directly\n\t\t// at root, others nest under a versioned subdirectory.\n\t\tconst binaryFileName = config.binaryName + binaryExt;\n\t\tconst extractedDir = join(extractDir, assetName.replace(/\\.(tar\\.gz|zip)$/, \"\"));\n\t\tconst extractedBinaryCandidates = [join(extractedDir, binaryFileName), join(extractDir, binaryFileName)];\n\t\tlet extractedBinary = extractedBinaryCandidates.find((candidate) => existsSync(candidate));\n\n\t\tif (!extractedBinary) {\n\t\t\textractedBinary = findBinaryRecursively(extractDir, binaryFileName) ?? undefined;\n\t\t}\n\n\t\tif (extractedBinary) {\n\t\t\trenameSync(extractedBinary, binaryPath);\n\t\t} else {\n\t\t\tthrow new Error(`Binary not found in archive: expected ${binaryFileName} under ${extractDir}`);\n\t\t}\n\n\t\t// Make executable (Unix only)\n\t\tif (plat !== \"win32\") {\n\t\t\tchmodSync(binaryPath, 0o755);\n\t\t}\n\t} finally {\n\t\t// Cleanup\n\t\trmSync(archivePath, { force: true });\n\t\trmSync(extractDir, { recursive: true, force: true });\n\t}\n\n\treturn binaryPath;\n}\n\n// Termux package names for tools\nconst TERMUX_PACKAGES: Record<string, string> = {\n\tfd: \"fd\",\n\trg: \"ripgrep\",\n};\n\n/** A managed-tool readiness update, reported to the caller that asked. */\nexport interface ToolStatus {\n\ttype: \"info\" | \"warning\";\n\tmessage: string;\n}\n\n/**\n * Ensure a tool is available, downloading if necessary.\n *\n * Progress and problems are reported through `onStatus`; the function never\n * writes to the console itself, because in a fullscreen session a console\n * write lands in the alternate screen and corrupts the frame. Callers without\n * a status sink stay silent.\n *\n * Returns the tool path, or undefined if unavailable.\n */\nexport async function ensureTool(\n\ttool: \"fd\" | \"rg\",\n\tonStatus?: (status: ToolStatus) => void,\n): Promise<string | undefined> {\n\tconst existingPath = getToolPath(tool);\n\tif (existingPath) {\n\t\treturn existingPath;\n\t}\n\n\tconst config = TOOLS[tool];\n\tif (!config) return undefined;\n\n\tif (isOfflineModeEnabled()) {\n\t\tonStatus?.({ type: \"warning\", message: `${config.name} not found. Offline mode enabled, skipping download.` });\n\t\treturn undefined;\n\t}\n\n\t// On Android/Termux, Linux binaries don't work due to Bionic libc incompatibility.\n\t// Users must install via pkg.\n\tif (platform() === \"android\") {\n\t\tconst pkgName = TERMUX_PACKAGES[tool] ?? tool;\n\t\tonStatus?.({ type: \"warning\", message: `${config.name} not found. Install with: pkg install ${pkgName}` });\n\t\treturn undefined;\n\t}\n\n\t// Tool not found - download it\n\tonStatus?.({ type: \"info\", message: `${config.name} not found. Downloading...` });\n\n\ttry {\n\t\tconst path = await downloadTool(tool);\n\t\tonStatus?.({ type: \"info\", message: `${config.name} installed to ${path}` });\n\t\treturn path;\n\t} catch (e) {\n\t\t// Include the error cause chain: fetch failures surface as a bare\n\t\t// \"fetch failed\" TypeError with the actionable detail (DNS, TLS,\n\t\t// timeout) hidden in the cause. Depth-capped to guard against\n\t\t// circular cause chains.\n\t\tconst messages: string[] = [];\n\t\tfor (\n\t\t\tlet current: unknown = e, depth = 0;\n\t\t\tcurrent instanceof Error && depth < 5;\n\t\t\tcurrent = current.cause, depth++\n\t\t) {\n\t\t\tif (!messages.includes(current.message)) messages.push(current.message);\n\t\t}\n\t\tonStatus?.({\n\t\t\ttype: \"warning\",\n\t\t\tmessage: `Failed to download ${config.name}: ${messages.length > 0 ? messages.join(\": \") : String(e)}`,\n\t\t});\n\t\treturn undefined;\n\t}\n}\n"]}
1
+ {"version":3,"file":"tools-manager.js","sourceRoot":"","sources":["../../src/utils/tools-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import { type SpawnSyncReturns, spawnSync } from \"child_process\";\nimport { chmodSync, existsSync, mkdirSync, readdirSync, renameSync, rmSync } from \"fs\";\nimport { writeFile } from \"fs/promises\";\nimport { arch, platform } from \"os\";\nimport { join } from \"path\";\nimport { ENV_OFFLINE, getBinDir, getEnvValue, VERSION } from \"../config.js\";\nimport { createChildProcessEnvironment } from \"./child-process.ts\";\nimport { fetchWithRetry } from \"./management-http.ts\";\nimport { getPiUserAgent } from \"./pi-user-agent.ts\";\n\nconst TOOLS_DIR = getBinDir();\nconst NETWORK_TIMEOUT_MS = 10_000;\nconst DOWNLOAD_TIMEOUT_MS = 120_000;\n\nfunction isOfflineModeEnabled(): boolean {\n\tconst value = getEnvValue(ENV_OFFLINE);\n\tif (!value) return false;\n\treturn value === \"1\" || value.toLowerCase() === \"true\" || value.toLowerCase() === \"yes\";\n}\n\ninterface ToolConfig {\n\tname: string;\n\trepo: string; // GitHub repo (e.g., \"sharkdp/fd\")\n\tbinaryName: string; // Name of the binary inside the archive\n\tsystemBinaryNames?: string[]; // Alternative system command names to try before downloading\n\ttagPrefix: string; // Prefix for tags (e.g., \"v\" for v1.0.0, \"\" for 1.0.0)\n\tgetAssetName: (version: string, plat: string, architecture: string) => string | null;\n}\n\nconst TOOLS: Record<string, ToolConfig> = {\n\tfd: {\n\t\tname: \"fd\",\n\t\trepo: \"sharkdp/fd\",\n\t\tbinaryName: \"fd\",\n\t\tsystemBinaryNames: [\"fd\", \"fdfind\"],\n\t\ttagPrefix: \"v\",\n\t\tgetAssetName: (version, plat, architecture) => {\n\t\t\tif (plat === \"darwin\") {\n\t\t\t\tconst archStr = architecture === \"arm64\" ? \"aarch64\" : \"x86_64\";\n\t\t\t\treturn `fd-v${version}-${archStr}-apple-darwin.tar.gz`;\n\t\t\t} else if (plat === \"linux\") {\n\t\t\t\tconst archStr = architecture === \"arm64\" ? \"aarch64\" : \"x86_64\";\n\t\t\t\treturn `fd-v${version}-${archStr}-unknown-linux-musl.tar.gz`;\n\t\t\t} else if (plat === \"win32\") {\n\t\t\t\tconst archStr = architecture === \"arm64\" ? \"aarch64\" : \"x86_64\";\n\t\t\t\treturn `fd-v${version}-${archStr}-pc-windows-msvc.zip`;\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\t},\n\trg: {\n\t\tname: \"ripgrep\",\n\t\trepo: \"BurntSushi/ripgrep\",\n\t\tbinaryName: \"rg\",\n\t\ttagPrefix: \"\",\n\t\tgetAssetName: (version, plat, architecture) => {\n\t\t\tif (plat === \"darwin\") {\n\t\t\t\tconst archStr = architecture === \"arm64\" ? \"aarch64\" : \"x86_64\";\n\t\t\t\treturn `ripgrep-${version}-${archStr}-apple-darwin.tar.gz`;\n\t\t\t} else if (plat === \"linux\") {\n\t\t\t\tconst archStr = architecture === \"arm64\" ? \"aarch64\" : \"x86_64\";\n\t\t\t\treturn `ripgrep-${version}-${archStr}-unknown-linux-musl.tar.gz`;\n\t\t\t} else if (plat === \"win32\") {\n\t\t\t\tconst archStr = architecture === \"arm64\" ? \"aarch64\" : \"x86_64\";\n\t\t\t\treturn `ripgrep-${version}-${archStr}-pc-windows-msvc.zip`;\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\t},\n};\n\n// Check if a command exists in PATH by trying to run it\nfunction commandExists(cmd: string): boolean {\n\ttry {\n\t\tconst result = spawnSync(cmd, [\"--version\"], { stdio: \"pipe\", env: createChildProcessEnvironment() });\n\t\t// Check for ENOENT error (command not found)\n\t\treturn result.error === undefined || result.error === null;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n// Get the path to a tool (system-wide or in our tools dir)\nexport function getToolPath(tool: \"fd\" | \"rg\"): string | null {\n\tconst config = TOOLS[tool];\n\tif (!config) return null;\n\n\t// Check our tools directory first\n\tconst localPath = join(TOOLS_DIR, config.binaryName + (platform() === \"win32\" ? \".exe\" : \"\"));\n\tif (existsSync(localPath)) {\n\t\treturn localPath;\n\t}\n\n\t// Check system PATH - if found, just return the command name (it's in PATH)\n\tconst systemBinaryNames = config.systemBinaryNames ?? [config.binaryName];\n\tfor (const systemBinaryName of systemBinaryNames) {\n\t\tif (commandExists(systemBinaryName)) {\n\t\t\treturn systemBinaryName;\n\t\t}\n\t}\n\n\treturn null;\n}\n\n// Resolve the latest release version from the release page redirect, avoiding\n// the anonymous api.github.com quota shared by corporate proxies and CI runners.\nexport async function getLatestVersion(repo: string): Promise<string> {\n\tconst response = await fetchWithRetry(\n\t\t`https://github.com/${repo}/releases/latest`,\n\t\t{ headers: { \"User-Agent\": getPiUserAgent(VERSION) }, redirect: \"manual\" },\n\t\t{ timeoutMs: NETWORK_TIMEOUT_MS },\n\t);\n\ttry {\n\t\tawait response.body?.cancel();\n\t} catch {\n\t\t// Discarding the redirect body is best-effort.\n\t}\n\tconst location = response.status >= 300 && response.status < 400 ? response.headers.get(\"location\") : null;\n\tif (!location) throw new Error(`Failed to resolve latest ${repo} release: HTTP ${response.status} without redirect`);\n\tconst tag = new URL(location, \"https://github.com\").pathname.split(\"/\").pop();\n\tif (!tag || !location.includes(\"/releases/tag/\")) {\n\t\tthrow new Error(`Failed to resolve latest ${repo} release: unexpected redirect to ${location}`);\n\t}\n\treturn decodeURIComponent(tag).replace(/^v/, \"\");\n}\n\n// Download a file from URL\nasync function downloadFile(url: string, dest: string): Promise<void> {\n\tconst response = await fetchWithRetry(url, undefined, { timeoutMs: DOWNLOAD_TIMEOUT_MS });\n\n\tif (!response.ok) {\n\t\tthrow new Error(`Download failed with HTTP ${response.status}: ${url}`);\n\t}\n\n\tif (!response.body) {\n\t\tthrow new Error(\"No response body\");\n\t}\n\n\tawait writeFile(dest, Buffer.from(await response.arrayBuffer()));\n}\n\nfunction findBinaryRecursively(rootDir: string, binaryFileName: string): string | null {\n\tconst stack: string[] = [rootDir];\n\n\twhile (stack.length > 0) {\n\t\tconst currentDir = stack.pop();\n\t\tif (!currentDir) continue;\n\n\t\tconst entries = readdirSync(currentDir, { withFileTypes: true });\n\t\tfor (const entry of entries) {\n\t\t\tconst fullPath = join(currentDir, entry.name);\n\t\t\tif (entry.isFile() && entry.name === binaryFileName) {\n\t\t\t\treturn fullPath;\n\t\t\t}\n\t\t\tif (entry.isDirectory()) {\n\t\t\t\tstack.push(fullPath);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn null;\n}\n\nfunction formatSpawnFailure(result: SpawnSyncReturns<Buffer>): string {\n\tif (result.error?.message) {\n\t\treturn result.error.message;\n\t}\n\tconst stderr = result.stderr?.toString().trim();\n\tif (stderr) {\n\t\treturn stderr;\n\t}\n\tconst stdout = result.stdout?.toString().trim();\n\tif (stdout) {\n\t\treturn stdout;\n\t}\n\treturn `exit status ${result.status ?? \"unknown\"}`;\n}\n\nfunction runExtractionCommand(command: string, args: string[]): string | null {\n\tconst result = spawnSync(command, args, { stdio: \"pipe\", env: createChildProcessEnvironment() });\n\tif (!result.error && result.status === 0) {\n\t\treturn null;\n\t}\n\treturn `${command}: ${formatSpawnFailure(result)}`;\n}\n\nfunction extractTarGzArchive(archivePath: string, extractDir: string, assetName: string): void {\n\tconst failure = runExtractionCommand(\"tar\", [\"xzf\", archivePath, \"-C\", extractDir]);\n\tif (failure) {\n\t\tthrow new Error(`Failed to extract ${assetName}: ${failure}`);\n\t}\n}\n\nfunction getWindowsTarCommand(): string {\n\tconst systemRoot = process.env.SystemRoot;\n\tif (systemRoot) {\n\t\tconst systemTar = join(systemRoot, \"System32\", \"tar.exe\");\n\t\tif (existsSync(systemTar)) {\n\t\t\treturn systemTar;\n\t\t}\n\t}\n\treturn \"tar.exe\";\n}\n\nfunction extractZipArchive(archivePath: string, extractDir: string, assetName: string): void {\n\tconst failures: string[] = [];\n\n\tif (platform() === \"win32\") {\n\t\t// Windows ships bsdtar as tar.exe, which supports zip files. Prefer the\n\t\t// System32 binary over Git Bash's GNU tar, which does not handle zip archives.\n\t\tconst tarFailure = runExtractionCommand(getWindowsTarCommand(), [\"xf\", archivePath, \"-C\", extractDir]);\n\t\tif (!tarFailure) return;\n\t\tfailures.push(tarFailure);\n\n\t\tconst script =\n\t\t\t\"& { param($archive, $destination) $ErrorActionPreference = 'Stop'; Expand-Archive -LiteralPath $archive -DestinationPath $destination -Force }\";\n\t\tconst powershellFailure = runExtractionCommand(\"powershell.exe\", [\n\t\t\t\"-NoLogo\",\n\t\t\t\"-NoProfile\",\n\t\t\t\"-NonInteractive\",\n\t\t\t\"-ExecutionPolicy\",\n\t\t\t\"Bypass\",\n\t\t\t\"-Command\",\n\t\t\tscript,\n\t\t\tarchivePath,\n\t\t\textractDir,\n\t\t]);\n\t\tif (!powershellFailure) return;\n\t\tfailures.push(powershellFailure);\n\t} else {\n\t\tconst unzipFailure = runExtractionCommand(\"unzip\", [\"-q\", archivePath, \"-d\", extractDir]);\n\t\tif (!unzipFailure) return;\n\t\tfailures.push(unzipFailure);\n\n\t\tconst tarFailure = runExtractionCommand(\"tar\", [\"xf\", archivePath, \"-C\", extractDir]);\n\t\tif (!tarFailure) return;\n\t\tfailures.push(tarFailure);\n\t}\n\n\tthrow new Error(`Failed to extract ${assetName}: ${failures.join(\"; \")}`);\n}\n\n// Download and install a tool\nasync function downloadTool(tool: \"fd\" | \"rg\"): Promise<string> {\n\tconst config = TOOLS[tool];\n\tif (!config) throw new Error(`Unknown tool: ${tool}`);\n\n\tconst plat = platform();\n\tconst architecture = arch();\n\n\t// fd is pinned on darwin/x64; skip the version lookup there.\n\tconst version =\n\t\ttool === \"fd\" && plat === \"darwin\" && architecture === \"x64\" ? \"10.3.0\" : await getLatestVersion(config.repo);\n\n\t// Get asset name for this platform\n\tconst assetName = config.getAssetName(version, plat, architecture);\n\tif (!assetName) {\n\t\tthrow new Error(`Unsupported platform: ${plat}/${architecture}`);\n\t}\n\n\t// Create tools directory\n\tmkdirSync(TOOLS_DIR, { recursive: true });\n\n\tconst downloadUrl = `https://github.com/${config.repo}/releases/download/${config.tagPrefix}${version}/${assetName}`;\n\tconst archivePath = join(TOOLS_DIR, assetName);\n\tconst binaryExt = plat === \"win32\" ? \".exe\" : \"\";\n\tconst binaryPath = join(TOOLS_DIR, config.binaryName + binaryExt);\n\n\t// Download\n\tawait downloadFile(downloadUrl, archivePath);\n\n\t// Extract into a unique temp directory. fd and rg downloads can run concurrently\n\t// during startup, so sharing a fixed directory causes races.\n\tconst extractDir = join(\n\t\tTOOLS_DIR,\n\t\t`extract_tmp_${config.binaryName}_${process.pid}_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`,\n\t);\n\tmkdirSync(extractDir, { recursive: true });\n\n\ttry {\n\t\tif (assetName.endsWith(\".tar.gz\")) {\n\t\t\textractTarGzArchive(archivePath, extractDir, assetName);\n\t\t} else if (assetName.endsWith(\".zip\")) {\n\t\t\textractZipArchive(archivePath, extractDir, assetName);\n\t\t} else {\n\t\t\tthrow new Error(`Unsupported archive format: ${assetName}`);\n\t\t}\n\n\t\t// Find the binary in extracted files. Some archives contain files directly\n\t\t// at root, others nest under a versioned subdirectory.\n\t\tconst binaryFileName = config.binaryName + binaryExt;\n\t\tconst extractedDir = join(extractDir, assetName.replace(/\\.(tar\\.gz|zip)$/, \"\"));\n\t\tconst extractedBinaryCandidates = [join(extractedDir, binaryFileName), join(extractDir, binaryFileName)];\n\t\tlet extractedBinary = extractedBinaryCandidates.find((candidate) => existsSync(candidate));\n\n\t\tif (!extractedBinary) {\n\t\t\textractedBinary = findBinaryRecursively(extractDir, binaryFileName) ?? undefined;\n\t\t}\n\n\t\tif (extractedBinary) {\n\t\t\trenameSync(extractedBinary, binaryPath);\n\t\t} else {\n\t\t\tthrow new Error(`Binary not found in archive: expected ${binaryFileName} under ${extractDir}`);\n\t\t}\n\n\t\t// Make executable (Unix only)\n\t\tif (plat !== \"win32\") {\n\t\t\tchmodSync(binaryPath, 0o755);\n\t\t}\n\t} finally {\n\t\t// Cleanup\n\t\trmSync(archivePath, { force: true });\n\t\trmSync(extractDir, { recursive: true, force: true });\n\t}\n\n\treturn binaryPath;\n}\n\n// Termux package names for tools\nconst TERMUX_PACKAGES: Record<string, string> = {\n\tfd: \"fd\",\n\trg: \"ripgrep\",\n};\n\n/** A managed-tool readiness update, reported to the caller that asked. */\nexport interface ToolStatus {\n\ttype: \"info\" | \"warning\";\n\tmessage: string;\n}\n\n/**\n * Ensure a tool is available, downloading if necessary.\n *\n * Progress and problems are reported through `onStatus`; the function never\n * writes to the console itself, because in a fullscreen session a console\n * write lands in the alternate screen and corrupts the frame. Callers without\n * a status sink stay silent.\n *\n * Returns the tool path, or undefined if unavailable.\n */\nexport async function ensureTool(\n\ttool: \"fd\" | \"rg\",\n\tonStatus?: (status: ToolStatus) => void,\n): Promise<string | undefined> {\n\tconst existingPath = getToolPath(tool);\n\tif (existingPath) {\n\t\treturn existingPath;\n\t}\n\n\tconst config = TOOLS[tool];\n\tif (!config) return undefined;\n\n\tif (isOfflineModeEnabled()) {\n\t\tonStatus?.({ type: \"warning\", message: `${config.name} not found. Offline mode enabled, skipping download.` });\n\t\treturn undefined;\n\t}\n\n\t// On Android/Termux, Linux binaries don't work due to Bionic libc incompatibility.\n\t// Users must install via pkg.\n\tif (platform() === \"android\") {\n\t\tconst pkgName = TERMUX_PACKAGES[tool] ?? tool;\n\t\tonStatus?.({ type: \"warning\", message: `${config.name} not found. Install with: pkg install ${pkgName}` });\n\t\treturn undefined;\n\t}\n\n\t// Tool not found - download it\n\tonStatus?.({ type: \"info\", message: `${config.name} not found. Downloading...` });\n\n\ttry {\n\t\tconst path = await downloadTool(tool);\n\t\tonStatus?.({ type: \"info\", message: `${config.name} installed to ${path}` });\n\t\treturn path;\n\t} catch (e) {\n\t\t// Include the error cause chain: fetch failures surface as a bare\n\t\t// \"fetch failed\" TypeError with the actionable detail (DNS, TLS,\n\t\t// timeout) hidden in the cause. Depth-capped to guard against\n\t\t// circular cause chains.\n\t\tconst messages: string[] = [];\n\t\tfor (\n\t\t\tlet current: unknown = e, depth = 0;\n\t\t\tcurrent instanceof Error && depth < 5;\n\t\t\tcurrent = current.cause, depth++\n\t\t) {\n\t\t\tif (!messages.includes(current.message)) messages.push(current.message);\n\t\t}\n\t\tonStatus?.({\n\t\t\ttype: \"warning\",\n\t\t\tmessage: `Failed to download ${config.name}: ${messages.length > 0 ? messages.join(\": \") : String(e)}`,\n\t\t});\n\t\treturn undefined;\n\t}\n}\n"]}
@@ -129,6 +129,8 @@ Supervisor progress messages are labelled **Historical supervisor update** with
129
129
 
130
130
  Stopping a subagent through `/tasks` (`x`, then `y`) delivers a **stopped** card and stop context to the parent model. The notice arrives only after termination is confirmed, not while the task is **Stopping**. It requires no final response from the child. Cancelling queued work sends the notice without starting it. A subagent stopped this way cannot be resumed; to stop one and keep it resumable, use `subagent({ action: "quit", id })` (see [Run control](/subagents#run-control)).
131
131
 
132
+ A subagent stopped with `subagent({ action: "pause" | "quit", id })`, or by its workflow stage pausing, is not ended. Its notice reads **paused · awaiting resume** (for a quit child, `Subagent <agent> quit · paused, awaiting resume`), gives `Stop reason: pause` or `quit`, and names the call that continues it, `subagent({ action: "resume", id: "<child-id>" })`, instead of telling the model the execution has ended. Its `/tasks` row shows **Paused · awaiting resume**.
133
+
132
134
  Repeated stop requests or late child results do not duplicate the notice or overwrite the recorded outcome. A task that finished before cancellation keeps its actual result. Closing the owning session or workflow stage still suppresses late notices.
133
135
 
134
136
  Restored completions may have only an outcome and task identity if the original live task or transcript is unavailable. Atomic does not invent missing output. Excerpts are bounded; inspect retained history for more detail.
@@ -196,9 +198,9 @@ bash({ action: "wait", id: taskId })
196
198
  powershell({ action: "wait", id: taskId })
197
199
  ```
198
200
 
199
- Use the original task ID from the same owning session or workflow stage. Omit `budgetMs` to use the owner's command observation policy, or pass `0` to poll. A wait returns retained output and a yielded or settled observation; settled results include available exit and failure details. While running, successive yielded waits advance through retained output in bounded pages, including after a session reload. A caught-up wait returns no output until more arrives. Settled waits return all retained output again, subject to labelled gaps and truncation, so they may repeat output you have already seen.
201
+ Use the original task ID from the same owning session or workflow stage. Omit `budgetMs` to use the owner's command observation policy, or pass `0` to poll. A wait returns retained output and a yielded or settled observation; settled results include available exit and failure details. The transcript shows one status line above the output: `✓ completed · exit 0`, `✗ exited 1`, `● still running · showing output so far`, or `○ cancelled`. When the output was cut short, a dim line below it gives the path to the full output. The agent receives the same facts as one sentence after the output, and the structured observation stays in the result details. While running, successive yielded waits advance through retained output in bounded pages, including after a session reload. A caught-up wait returns no output until more arrives. Settled waits return all retained output again, subject to labelled gaps and truncation, so they may repeat output you have already seen.
200
202
 
201
- Do not combine `action: "wait"` with `command`, `timeout`, `wait`, `env`, `cwd`, or `pty`. Existing-task waits require a supported task owner, even with custom execution adapters. Unknown or foreign IDs are rejected. Cancelling a wait or admitting user/Intercom messages releases observation only, not the command. Waiting never extends the original execution timeout or the owner's lifetime.
203
+ Do not combine `action: "wait"` with `command`, `timeout`, `wait`, `env`, `cwd`, or `pty`. Existing-task waits require a supported task owner, even with custom execution adapters. Unknown or foreign IDs are rejected with `No background task "<id>" in this session` and a hint to run `/tasks`. Cancelling a wait or admitting user/Intercom messages releases observation only, not the command. Waiting never extends the original execution timeout or the owner's lifetime.
202
204
 
203
205
  ### Stop a shell task from a tool call
204
206
 
@@ -210,7 +212,7 @@ kill({ id: taskId })
210
212
 
211
213
  The same command works in main and workflow-stage chat. It selects the existing owned shell task; do not supply a process ID, shell name, or another owner's task ID. Unknown, malformed, foreign-owner, and subagent IDs are rejected. `/tasks` stop controls remain available.
212
214
 
213
- The response includes `taskId`, `decision`, `execution`, and `cleanup`. `cancellation-requested` means cancellation was requested, not that termination or cleanup has finished. A repeated call preserves that decision while reporting current state. `already-settled` means the task finished before cancellation and keeps its original outcome. Confirm `execution.kind: "settled"` and `cleanup.kind: "reaped"` before treating termination and cleanup as complete. Cleanup failures remain errors, not successful stops. Output and completion notifications remain available; killing a task does not erase its history.
215
+ The transcript shows a status line such as `● stopping · cancellation requested`, `○ cancelled`, or `✓ already completed · exit 0`, and the agent receives the same facts as a sentence. The structured result keeps `taskId`, `decision`, `execution`, and `cleanup`. `cancellation-requested` means cancellation was requested, not that termination or cleanup has finished. A repeated call preserves that decision while reporting current state. `already-settled` means the task finished before cancellation and keeps its original outcome. Confirm `execution.kind: "settled"` and `cleanup.kind: "reaped"` before treating termination and cleanup as complete. Cleanup failures remain errors, not successful stops. Output and completion notifications remain available; killing a task does not erase its history.
214
216
 
215
217
  Shell completions use the same shaded card as subagents, with a retained output preview and available exit code. Nonzero shell exits are shown as failures even though the process itself reached a terminal state. Cancellation shows Stopped. The card and below-prompt count update in the owning main or workflow-stage chat.
216
218