@oh-my-pi/pi-coding-agent 17.0.9 → 17.1.1

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 (349) hide show
  1. package/CHANGELOG.md +78 -0
  2. package/README.md +1 -1
  3. package/dist/cli.js +4685 -4614
  4. package/dist/types/async/job-manager.d.ts +37 -1
  5. package/dist/types/cli/args.d.ts +2 -0
  6. package/dist/types/cli/bench-cli.d.ts +41 -0
  7. package/dist/types/commands/bench.d.ts +15 -3
  8. package/dist/types/commands/launch.d.ts +4 -0
  9. package/dist/types/config/model-registry.d.ts +3 -1
  10. package/dist/types/config/models-config-schema.d.ts +18 -6
  11. package/dist/types/config/models-config.d.ts +14 -5
  12. package/dist/types/config/provider-globals.d.ts +2 -2
  13. package/dist/types/config/service-tier.d.ts +5 -1
  14. package/dist/types/config/settings-schema.d.ts +374 -47
  15. package/dist/types/config/settings.d.ts +7 -0
  16. package/dist/types/dap/client.d.ts +20 -0
  17. package/dist/types/exec/bash-executor.d.ts +38 -0
  18. package/dist/types/exec/direnv.d.ts +33 -0
  19. package/dist/types/export/html/args.d.ts +15 -0
  20. package/dist/types/export/html/index.d.ts +11 -26
  21. package/dist/types/export/html/web-palette.d.ts +55 -116
  22. package/dist/types/extensibility/extensions/loader.d.ts +3 -0
  23. package/dist/types/extensibility/extensions/types.d.ts +17 -2
  24. package/dist/types/extensibility/legacy-pi-coding-agent-shim.d.ts +3 -0
  25. package/dist/types/extensibility/plugins/legacy-pi-compat.d.ts +13 -0
  26. package/dist/types/live/attestation.d.ts +2 -0
  27. package/dist/types/live/controller.d.ts +48 -0
  28. package/dist/types/live/protocol.d.ts +85 -0
  29. package/dist/types/live/protocol.test.d.ts +1 -0
  30. package/dist/types/live/transport.d.ts +35 -0
  31. package/dist/types/live/visualizer.d.ts +30 -0
  32. package/dist/types/lsp/client.d.ts +16 -1
  33. package/dist/types/mcp/config-writer.test.d.ts +1 -0
  34. package/dist/types/mcp/oauth-discovery.d.ts +2 -0
  35. package/dist/types/mcp/smithery-auth.d.ts +1 -1
  36. package/dist/types/mcp/smithery-auth.test.d.ts +1 -0
  37. package/dist/types/memory-backend/tool-names.d.ts +2 -0
  38. package/dist/types/modes/components/assistant-message.d.ts +1 -0
  39. package/dist/types/modes/components/custom-message.d.ts +1 -1
  40. package/dist/types/modes/components/login-dialog.d.ts +2 -2
  41. package/dist/types/modes/components/message-frame.d.ts +8 -4
  42. package/dist/types/modes/components/plan-review-overlay.d.ts +26 -0
  43. package/dist/types/modes/components/session-account-selector.d.ts +11 -0
  44. package/dist/types/modes/components/settings-defs.d.ts +7 -1
  45. package/dist/types/modes/components/status-line/component.jj-cache.test.d.ts +1 -0
  46. package/dist/types/modes/components/tool-execution.d.ts +9 -1
  47. package/dist/types/modes/controllers/command-controller.d.ts +1 -1
  48. package/dist/types/modes/controllers/event-controller.d.ts +6 -1
  49. package/dist/types/modes/controllers/live-command-controller.d.ts +14 -0
  50. package/dist/types/modes/controllers/selector-controller.d.ts +1 -0
  51. package/dist/types/modes/interactive-mode.d.ts +6 -0
  52. package/dist/types/modes/theme/theme.d.ts +1 -1
  53. package/dist/types/modes/types.d.ts +4 -1
  54. package/dist/types/modes/utils/context-usage.d.ts +12 -2
  55. package/dist/types/plan-mode/plan-files.d.ts +10 -0
  56. package/dist/types/registry/agent-lifecycle.d.ts +21 -9
  57. package/dist/types/registry/agent-registry.d.ts +11 -4
  58. package/dist/types/sdk.d.ts +15 -1
  59. package/dist/types/secrets/index.d.ts +15 -2
  60. package/dist/types/secrets/obfuscator.d.ts +113 -15
  61. package/dist/types/session/acp-permission-gate.d.ts +19 -0
  62. package/dist/types/session/agent-session-events.d.ts +84 -0
  63. package/dist/types/session/agent-session-types.d.ts +321 -0
  64. package/dist/types/session/agent-session.d.ts +135 -753
  65. package/dist/types/session/async-job-delivery.d.ts +28 -0
  66. package/dist/types/session/auth-storage.d.ts +1 -1
  67. package/dist/types/session/bash-runner.d.ts +75 -0
  68. package/dist/types/session/blob-store.d.ts +11 -1
  69. package/dist/types/session/blob-store.test.d.ts +1 -0
  70. package/dist/types/session/checkpoint-entries.d.ts +28 -0
  71. package/dist/types/session/eval-runner.d.ts +51 -0
  72. package/dist/types/session/irc-bridge.d.ts +46 -0
  73. package/dist/types/session/messages.d.ts +24 -0
  74. package/dist/types/session/model-controls.d.ts +180 -0
  75. package/dist/types/session/prewalk.d.ts +46 -0
  76. package/dist/types/session/queued-messages.d.ts +22 -0
  77. package/dist/types/session/redis-session-storage.d.ts +1 -0
  78. package/dist/types/session/retry-fallback-chains.d.ts +74 -0
  79. package/dist/types/session/role-models.d.ts +15 -0
  80. package/dist/types/session/session-advisors.d.ts +228 -0
  81. package/dist/types/session/session-entries.d.ts +8 -0
  82. package/dist/types/session/session-handoff.d.ts +70 -0
  83. package/dist/types/session/session-history-format.d.ts +6 -1
  84. package/dist/types/session/session-maintenance.d.ts +246 -0
  85. package/dist/types/session/session-manager.d.ts +41 -0
  86. package/dist/types/session/session-memory.d.ts +56 -0
  87. package/dist/types/session/session-provider-boundary.d.ts +62 -0
  88. package/dist/types/session/session-stats.d.ts +48 -0
  89. package/dist/types/session/session-tools.d.ts +158 -0
  90. package/dist/types/session/session-workspace.d.ts +32 -0
  91. package/dist/types/session/stream-guards.d.ts +44 -0
  92. package/dist/types/session/streaming-output.d.ts +8 -0
  93. package/dist/types/session/todo-tracker.d.ts +56 -0
  94. package/dist/types/session/ttsr-coordinator.d.ts +51 -0
  95. package/dist/types/session/turn-recovery.d.ts +225 -0
  96. package/dist/types/slash-commands/helpers/session-pin.d.ts +9 -0
  97. package/dist/types/stt/index.d.ts +0 -2
  98. package/dist/types/stt/stt-controller.d.ts +7 -0
  99. package/dist/types/system-prompt.d.ts +2 -0
  100. package/dist/types/task/executor.d.ts +4 -1
  101. package/dist/types/task/output-manager.d.ts +3 -1
  102. package/dist/types/tiny/title-client.d.ts +10 -0
  103. package/dist/types/tools/approval.d.ts +1 -0
  104. package/dist/types/tools/browser/launch.d.ts +5 -0
  105. package/dist/types/tools/builtin-names.d.ts +1 -1
  106. package/dist/types/tools/computer/protocol.d.ts +43 -0
  107. package/dist/types/tools/computer/supervisor.d.ts +32 -0
  108. package/dist/types/tools/computer/worker-entry.d.ts +1 -0
  109. package/dist/types/tools/computer/worker.d.ts +15 -0
  110. package/dist/types/tools/computer-renderer.d.ts +22 -0
  111. package/dist/types/tools/computer.d.ts +71 -0
  112. package/dist/types/tools/context.d.ts +2 -0
  113. package/dist/types/tools/default-renderer.d.ts +21 -0
  114. package/dist/types/tools/image-gen.d.ts +4 -4
  115. package/dist/types/tools/image-providers.d.ts +38 -0
  116. package/dist/types/tools/index.d.ts +7 -0
  117. package/dist/types/tools/path-utils.d.ts +8 -0
  118. package/dist/types/tools/todo.d.ts +10 -4
  119. package/dist/types/tools/xdev.d.ts +5 -1
  120. package/dist/types/tts/streaming-player.d.ts +10 -29
  121. package/dist/types/tts/vocalizer.d.ts +5 -0
  122. package/dist/types/utils/jj.d.ts +29 -0
  123. package/dist/types/utils/lang-from-path.d.ts +1 -0
  124. package/dist/types/utils/title-generator.d.ts +30 -0
  125. package/dist/types/utils/tools-manager.d.ts +1 -2
  126. package/dist/types/vibe/runtime.d.ts +36 -8
  127. package/dist/types/web/search/index.d.ts +1 -1
  128. package/dist/types/web/search/provider.d.ts +15 -5
  129. package/dist/types/web/search/types.d.ts +94 -0
  130. package/package.json +12 -12
  131. package/scripts/generate-share-viewer.ts +4 -6
  132. package/src/advisor/__tests__/advisor.test.ts +643 -0
  133. package/src/advisor/runtime.ts +144 -43
  134. package/src/async/job-manager.ts +90 -2
  135. package/src/cli/args.ts +3 -0
  136. package/src/cli/auth-gateway-cli.ts +18 -3
  137. package/src/cli/bench-cli.ts +395 -29
  138. package/src/cli/flag-tables.ts +3 -0
  139. package/src/cli/gc-cli.ts +2 -2
  140. package/src/cli/setup-cli.ts +2 -14
  141. package/src/cli/usage-cli.ts +10 -1
  142. package/src/cli.ts +8 -0
  143. package/src/collab/host.ts +3 -2
  144. package/src/commands/bench.ts +18 -4
  145. package/src/commands/launch.ts +4 -0
  146. package/src/config/model-registry.ts +16 -2
  147. package/src/config/models-config-schema.ts +15 -4
  148. package/src/config/provider-globals.ts +9 -9
  149. package/src/config/service-tier.ts +26 -1
  150. package/src/config/settings-schema.ts +270 -51
  151. package/src/config/settings.ts +81 -2
  152. package/src/dap/client.ts +37 -4
  153. package/src/edit/index.ts +49 -12
  154. package/src/eval/executor-base.ts +1 -0
  155. package/src/eval/js/executor.ts +2 -0
  156. package/src/eval/py/executor.ts +103 -33
  157. package/src/exec/bash-executor.ts +90 -6
  158. package/src/exec/direnv.ts +145 -0
  159. package/src/export/html/args.ts +20 -0
  160. package/src/export/html/index.ts +45 -47
  161. package/src/export/html/template.css +19 -1
  162. package/src/export/html/template.html +6 -0
  163. package/src/export/html/template.js +21 -0
  164. package/src/export/html/tool-views.generated.js +31 -31
  165. package/src/export/html/web-palette.ts +116 -132
  166. package/src/export/share.ts +249 -49
  167. package/src/extensibility/extensions/loader.ts +29 -1
  168. package/src/extensibility/extensions/runner.ts +6 -0
  169. package/src/extensibility/extensions/types.ts +33 -2
  170. package/src/extensibility/extensions/wrapper.ts +68 -12
  171. package/src/extensibility/legacy-pi-coding-agent-shim.ts +7 -1
  172. package/src/extensibility/plugins/legacy-pi-compat.ts +19 -1
  173. package/src/hindsight/state.ts +64 -6
  174. package/src/internal-urls/local-protocol.ts +2 -1
  175. package/src/internal-urls/memory-protocol.ts +2 -2
  176. package/src/internal-urls/skill-protocol.ts +2 -2
  177. package/src/internal-urls/ssh-protocol.ts +2 -1
  178. package/src/internal-urls/vault-protocol.ts +2 -1
  179. package/src/live/attestation.ts +91 -0
  180. package/src/live/controller.ts +517 -0
  181. package/src/live/prompts/agent-final-message.md +3 -0
  182. package/src/live/prompts/live-instructions.md +23 -0
  183. package/src/live/protocol.test.ts +140 -0
  184. package/src/live/protocol.ts +233 -0
  185. package/src/live/transport.ts +422 -0
  186. package/src/live/visualizer.ts +214 -0
  187. package/src/lsp/client.ts +29 -9
  188. package/src/lsp/index.ts +19 -4
  189. package/src/main.ts +8 -1
  190. package/src/mcp/config-writer.test.ts +43 -0
  191. package/src/mcp/config-writer.ts +109 -82
  192. package/src/mcp/oauth-discovery.ts +10 -2
  193. package/src/mcp/smithery-auth.test.ts +29 -0
  194. package/src/mcp/smithery-auth.ts +3 -2
  195. package/src/memories/index.ts +40 -20
  196. package/src/memory-backend/tool-names.ts +2 -0
  197. package/src/mnemopi/backend.ts +24 -7
  198. package/src/modes/acp/acp-agent.ts +56 -10
  199. package/src/modes/acp/acp-event-mapper.ts +8 -1
  200. package/src/modes/components/agent-hub.ts +1 -1
  201. package/src/modes/components/assistant-message.ts +7 -2
  202. package/src/modes/components/custom-message.ts +4 -1
  203. package/src/modes/components/login-dialog.ts +14 -4
  204. package/src/modes/components/message-frame.ts +14 -8
  205. package/src/modes/components/plan-review-overlay.ts +350 -35
  206. package/src/modes/components/session-account-selector.ts +62 -0
  207. package/src/modes/components/settings-defs.ts +23 -1
  208. package/src/modes/components/settings-selector.ts +169 -1
  209. package/src/modes/components/status-line/component.jj-cache.test.ts +229 -0
  210. package/src/modes/components/status-line/component.ts +123 -2
  211. package/src/modes/components/tool-execution.ts +28 -112
  212. package/src/modes/controllers/command-controller.ts +56 -15
  213. package/src/modes/controllers/event-controller.ts +111 -16
  214. package/src/modes/controllers/extension-ui-controller.test.ts +1 -0
  215. package/src/modes/controllers/extension-ui-controller.ts +20 -4
  216. package/src/modes/controllers/input-controller.ts +47 -39
  217. package/src/modes/controllers/live-command-controller.ts +255 -0
  218. package/src/modes/controllers/mcp-command-controller.ts +10 -1
  219. package/src/modes/controllers/omfg-controller.ts +44 -40
  220. package/src/modes/controllers/selector-controller.ts +80 -10
  221. package/src/modes/controllers/session-focus-controller.ts +6 -1
  222. package/src/modes/interactive-mode.ts +176 -38
  223. package/src/modes/runtime-init.ts +2 -0
  224. package/src/modes/setup-wizard/scenes/web-search.ts +17 -9
  225. package/src/modes/theme/theme.ts +1 -1
  226. package/src/modes/types.ts +4 -1
  227. package/src/modes/utils/context-usage.ts +23 -7
  228. package/src/modes/utils/ui-helpers.ts +10 -5
  229. package/src/plan-mode/plan-files.ts +40 -0
  230. package/src/prompts/bench/cache-prefix-chunk.md +1 -0
  231. package/src/prompts/bench/cache-prefix.md +3 -0
  232. package/src/prompts/bench/cache-suffix.md +1 -0
  233. package/src/prompts/system/computer-safety.md +14 -0
  234. package/src/prompts/system/custom-system-prompt.md +1 -1
  235. package/src/prompts/system/project-prompt.md +8 -1
  236. package/src/prompts/system/subagent-async-pending.md +6 -0
  237. package/src/prompts/system/system-prompt.md +1 -1
  238. package/src/prompts/system/workflow-notice.md +48 -40
  239. package/src/prompts/system/xdev-mount-notice.md +4 -0
  240. package/src/prompts/tools/computer.md +26 -0
  241. package/src/prompts/tools/todo.md +3 -1
  242. package/src/registry/agent-lifecycle.ts +116 -46
  243. package/src/registry/agent-registry.ts +35 -8
  244. package/src/registry/persisted-agents.ts +26 -2
  245. package/src/sdk.ts +215 -136
  246. package/src/secrets/index.ts +127 -4
  247. package/src/secrets/obfuscator.ts +2328 -105
  248. package/src/session/acp-permission-gate.ts +165 -0
  249. package/src/session/agent-session-error-log.test.ts +1 -1
  250. package/src/session/agent-session-events.ts +66 -0
  251. package/src/session/agent-session-types.ts +343 -0
  252. package/src/session/agent-session.ts +1940 -12218
  253. package/src/session/artifacts.ts +6 -5
  254. package/src/session/async-job-delivery.ts +74 -0
  255. package/src/session/auth-storage.ts +1 -0
  256. package/src/session/bash-runner.ts +326 -0
  257. package/src/session/blob-store.test.ts +56 -0
  258. package/src/session/blob-store.ts +18 -2
  259. package/src/session/checkpoint-entries.ts +81 -0
  260. package/src/session/eval-runner.ts +217 -0
  261. package/src/session/indexed-session-storage.ts +9 -2
  262. package/src/session/irc-bridge.ts +203 -0
  263. package/src/session/messages.ts +266 -1
  264. package/src/session/model-controls.ts +714 -0
  265. package/src/session/prewalk.ts +252 -0
  266. package/src/session/queued-messages.ts +93 -0
  267. package/src/session/redis-session-storage.ts +51 -11
  268. package/src/session/retry-fallback-chains.ts +455 -0
  269. package/src/session/role-models.ts +85 -0
  270. package/src/session/session-advisors.ts +1679 -0
  271. package/src/session/session-context.ts +6 -3
  272. package/src/session/session-entries.ts +8 -0
  273. package/src/session/session-handoff.ts +308 -0
  274. package/src/session/session-history-format.ts +20 -9
  275. package/src/session/session-loader.ts +0 -46
  276. package/src/session/session-maintenance.ts +2983 -0
  277. package/src/session/session-manager.ts +390 -30
  278. package/src/session/session-memory.ts +222 -0
  279. package/src/session/session-provider-boundary.ts +307 -0
  280. package/src/session/session-stats.ts +293 -0
  281. package/src/session/session-tools.ts +980 -0
  282. package/src/session/session-workspace.ts +53 -0
  283. package/src/session/stream-guards.ts +417 -0
  284. package/src/session/streaming-output.ts +52 -5
  285. package/src/session/todo-tracker.ts +380 -0
  286. package/src/session/ttsr-coordinator.ts +496 -0
  287. package/src/session/turn-recovery.ts +1629 -0
  288. package/src/slash-commands/builtin-registry.ts +257 -20
  289. package/src/slash-commands/helpers/session-pin.ts +44 -0
  290. package/src/slash-commands/helpers/usage-report.ts +22 -3
  291. package/src/stt/downloader.ts +0 -2
  292. package/src/stt/index.ts +0 -2
  293. package/src/stt/stt-controller.ts +57 -146
  294. package/src/system-prompt.ts +45 -17
  295. package/src/task/executor.ts +285 -70
  296. package/src/task/index.ts +98 -105
  297. package/src/task/output-manager.ts +25 -3
  298. package/src/task/persisted-revive.ts +4 -3
  299. package/src/task/structured-subagent.ts +1 -0
  300. package/src/tiny/title-client.ts +22 -0
  301. package/src/tools/approval.ts +55 -10
  302. package/src/tools/bash-interactive.ts +116 -86
  303. package/src/tools/bash-skill-urls.ts +28 -2
  304. package/src/tools/bash.ts +339 -123
  305. package/src/tools/browser/launch.ts +9 -1
  306. package/src/tools/browser/tab-supervisor.ts +8 -5
  307. package/src/tools/browser.ts +94 -47
  308. package/src/tools/builtin-names.ts +1 -0
  309. package/src/tools/computer/protocol.ts +28 -0
  310. package/src/tools/computer/supervisor.ts +258 -0
  311. package/src/tools/computer/worker-entry.ts +25 -0
  312. package/src/tools/computer/worker.ts +135 -0
  313. package/src/tools/computer-renderer.ts +108 -0
  314. package/src/tools/computer.ts +433 -0
  315. package/src/tools/context.ts +2 -0
  316. package/src/tools/default-renderer.ts +139 -0
  317. package/src/tools/essential-tools.ts +1 -0
  318. package/src/tools/image-gen.ts +20 -28
  319. package/src/tools/image-providers.ts +50 -0
  320. package/src/tools/index.ts +14 -0
  321. package/src/tools/path-utils.ts +49 -2
  322. package/src/tools/read.ts +156 -88
  323. package/src/tools/renderers.ts +9 -1
  324. package/src/tools/todo.ts +101 -11
  325. package/src/tools/vibe.ts +1 -2
  326. package/src/tools/write.ts +51 -1
  327. package/src/tools/xdev.ts +121 -29
  328. package/src/tts/streaming-player.ts +82 -283
  329. package/src/tts/vocalizer.ts +18 -1
  330. package/src/utils/clipboard.ts +1 -30
  331. package/src/utils/jj.ts +125 -4
  332. package/src/utils/lang-from-path.ts +7 -0
  333. package/src/utils/mac-file-urls.applescript +37 -0
  334. package/src/utils/title-generator.ts +137 -1
  335. package/src/utils/tool-choice.ts +14 -0
  336. package/src/utils/tools-manager.ts +1 -19
  337. package/src/vibe/runtime.ts +852 -72
  338. package/src/web/search/index.ts +3 -6
  339. package/src/web/search/provider.ts +31 -16
  340. package/src/web/search/providers/xai.ts +7 -1
  341. package/src/web/search/types.ts +3 -0
  342. package/dist/types/stt/recorder.d.ts +0 -30
  343. package/dist/types/stt/transcriber.d.ts +0 -14
  344. package/dist/types/stt/wav.d.ts +0 -29
  345. package/dist/types/tts/player.d.ts +0 -32
  346. package/src/stt/recorder.ts +0 -551
  347. package/src/stt/transcriber.ts +0 -60
  348. package/src/stt/wav.ts +0 -173
  349. package/src/tts/player.ts +0 -137
@@ -0,0 +1,165 @@
1
+ import { Patch } from "@oh-my-pi/hashline";
2
+ import { isRecord, stringProperty } from "@oh-my-pi/pi-utils";
3
+ import { expandApplyPatchToEntries } from "../edit";
4
+ import { resolveToCwd } from "../tools/path-utils";
5
+ import type { ClientBridgePermissionOption } from "./client-bridge";
6
+
7
+ /** Tools that require user permission before execution when an ACP client is connected. */
8
+ export const PERMISSION_REQUIRED_TOOLS: Record<string, true> = {
9
+ bash: true,
10
+ edit: true,
11
+ delete: true,
12
+ move: true,
13
+ };
14
+
15
+ /** Permission options presented to the client on each gated tool call. */
16
+ export const PERMISSION_OPTIONS: ClientBridgePermissionOption[] = [
17
+ { optionId: "allow_once", name: "Allow once", kind: "allow_once" },
18
+ { optionId: "allow_always", name: "Always allow", kind: "allow_always" },
19
+ { optionId: "reject_once", name: "Reject", kind: "reject_once" },
20
+ { optionId: "reject_always", name: "Always reject", kind: "reject_always" },
21
+ ];
22
+
23
+ /** Permission options indexed by their wire identifiers; unknown IDs miss and fail closed. */
24
+ export const PERMISSION_OPTIONS_BY_ID = new Map(PERMISSION_OPTIONS.map(option => [option.optionId, option]));
25
+
26
+ function getEditDestructiveIntent(args: unknown): { kind: "delete" | "move"; paths: string[] } | undefined {
27
+ if (!isRecord(args)) return undefined;
28
+
29
+ const edits = Array.isArray(args.edits) ? args.edits : undefined;
30
+ if (edits) {
31
+ const filePath = stringProperty(args, "path");
32
+ if (filePath) {
33
+ for (const edit of edits) {
34
+ if (!isRecord(edit)) continue;
35
+ if (stringProperty(edit, "op") === "delete") return { kind: "delete", paths: [filePath] };
36
+ }
37
+ }
38
+ for (const edit of edits) {
39
+ if (!isRecord(edit)) continue;
40
+ const op = stringProperty(edit, "op");
41
+ const rename = stringProperty(edit, "rename");
42
+ if (op !== "create" && rename) return { kind: "move", paths: filePath ? [filePath, rename] : [rename] };
43
+ }
44
+ }
45
+
46
+ const input = stringProperty(args, "input");
47
+ if (input) {
48
+ try {
49
+ const patch = Patch.parse(input);
50
+ for (const section of patch.sections) {
51
+ if (section.fileOp?.kind === "rem") return { kind: "delete", paths: [section.path] };
52
+ if (section.fileOp?.kind === "move") return { kind: "move", paths: [section.path, section.fileOp.dest] };
53
+ }
54
+ } catch {
55
+ // Not a hashline patch — fall through to apply_patch parsing.
56
+ }
57
+ try {
58
+ const entries = expandApplyPatchToEntries({ input });
59
+ const deleteEntry = entries.find(entry => entry.op === "delete");
60
+ if (deleteEntry) return { kind: "delete", paths: [deleteEntry.path] };
61
+ const moveEntry = entries.find(entry => entry.rename);
62
+ if (moveEntry?.rename) return { kind: "move", paths: [moveEntry.path, moveEntry.rename] };
63
+ } catch {
64
+ // If the edit input is not an apply-patch envelope, it is not a delete/move operation.
65
+ }
66
+ }
67
+
68
+ return undefined;
69
+ }
70
+
71
+ /** Describes the permission prompt required for a destructive tool call. */
72
+ export function getPermissionIntent(
73
+ toolName: string,
74
+ args: unknown,
75
+ ): { toolName: string; title: string; paths?: string[]; cacheKey: string } | undefined {
76
+ const input = isRecord(args) ? args : {};
77
+ if (toolName === "bash") {
78
+ const command = stringProperty(input, "command")?.slice(0, 80);
79
+ return { toolName, title: command || toolName, cacheKey: toolName };
80
+ }
81
+ if (toolName === "delete") {
82
+ const filePath = stringProperty(input, "path");
83
+ return {
84
+ toolName,
85
+ title: filePath ? `Delete ${filePath}` : toolName,
86
+ paths: filePath ? [filePath] : undefined,
87
+ cacheKey: toolName,
88
+ };
89
+ }
90
+ if (toolName === "move") {
91
+ const from = stringProperty(input, "oldPath") ?? stringProperty(input, "path") ?? stringProperty(input, "from");
92
+ const to =
93
+ stringProperty(input, "newPath") ?? stringProperty(input, "to") ?? stringProperty(input, "destination");
94
+ if (from && to) return { toolName, title: `Move ${from} to ${to}`, paths: [from, to], cacheKey: toolName };
95
+ return {
96
+ toolName,
97
+ title: from ? `Move ${from}` : toolName,
98
+ paths: from ? [from] : undefined,
99
+ cacheKey: toolName,
100
+ };
101
+ }
102
+ if (toolName === "edit") {
103
+ const intent = getEditDestructiveIntent(args);
104
+ if (!intent) return undefined;
105
+ if (intent.kind === "delete") {
106
+ return {
107
+ toolName,
108
+ title: `Delete ${intent.paths[0] ?? "edit target"}`,
109
+ paths: intent.paths,
110
+ cacheKey: "edit:delete",
111
+ };
112
+ }
113
+ const from = intent.paths[0];
114
+ const to = intent.paths[1];
115
+ return {
116
+ toolName,
117
+ title: from && to ? `Move ${from} to ${to}` : `Move ${from ?? to ?? "edit target"}`,
118
+ paths: intent.paths,
119
+ cacheKey: "edit:move",
120
+ };
121
+ }
122
+ return undefined;
123
+ }
124
+
125
+ /** Converts tool path arguments into absolute ACP editor locations. */
126
+ export function extractPermissionLocations(
127
+ args: unknown,
128
+ cwd: string,
129
+ explicitPaths?: string[],
130
+ ): { path: string; line?: number }[] {
131
+ if (!isRecord(args)) return [];
132
+ const out: { path: string; line?: number }[] = [];
133
+ const pushPath = (value: unknown) => {
134
+ if (typeof value !== "string" || value.length === 0) return;
135
+ // ACP locations carry file paths that the editor host will open or focus;
136
+ // they must be absolute or the client cannot resolve them. Resolve raw
137
+ // tool args (often cwd-relative) against the session cwd before sending.
138
+ let resolved: string;
139
+ try {
140
+ resolved = resolveToCwd(value, cwd);
141
+ } catch {
142
+ return;
143
+ }
144
+ if (out.some(location => location.path === resolved)) return;
145
+ out.push({ path: resolved });
146
+ };
147
+ if (explicitPaths) {
148
+ for (const filePath of explicitPaths) pushPath(filePath);
149
+ return out;
150
+ }
151
+ pushPath(args.path);
152
+ pushPath(args.file);
153
+ if (Array.isArray(args.paths)) {
154
+ for (const filePath of args.paths) {
155
+ if (typeof filePath === "string") pushPath(filePath);
156
+ }
157
+ }
158
+ pushPath(args.oldPath);
159
+ pushPath(args.newPath);
160
+ pushPath(args.from);
161
+ pushPath(args.to);
162
+ pushPath(args.source);
163
+ pushPath(args.destination);
164
+ return out;
165
+ }
@@ -7,7 +7,7 @@
7
7
  import { afterAll, afterEach, describe, expect, it } from "bun:test";
8
8
  import type { AssistantMessage } from "@oh-my-pi/pi-ai";
9
9
  import { logger } from "@oh-my-pi/pi-utils";
10
- import { logProviderTurnError } from "./agent-session";
10
+ import { logProviderTurnError } from "./messages";
11
11
 
12
12
  function makeMessage(overrides: Partial<AssistantMessage>): AssistantMessage {
13
13
  return {
@@ -0,0 +1,66 @@
1
+ import type { AgentEvent, ThinkingLevel } from "@oh-my-pi/pi-agent-core";
2
+ import type { CompactionResult } from "@oh-my-pi/pi-agent-core/compaction";
3
+ import type { Effort } from "@oh-my-pi/pi-ai";
4
+ import type { Rule } from "../capability/rule";
5
+ import type { RecoveredRetryError } from "../extensibility/shared-events";
6
+ import type { Goal, GoalModeState } from "../goals/state";
7
+ import type { ConfiguredThinkingLevel } from "../thinking";
8
+ import type { TodoItem } from "../tools/todo";
9
+ import type { CustomMessage } from "./messages";
10
+
11
+ /** Session-specific events that extend the core AgentEvent. */
12
+ export type AgentSessionEvent =
13
+ | Exclude<AgentEvent, { type: "agent_end" }>
14
+ | (Extract<AgentEvent, { type: "agent_end" }> & {
15
+ /** False when an async delivery will resume the session before its true final settle. */
16
+ isTerminal?: boolean;
17
+ })
18
+ | {
19
+ type: "auto_compaction_start";
20
+ reason: "threshold" | "overflow" | "idle" | "incomplete";
21
+ action: "context-full" | "handoff" | "shake" | "snapcompact";
22
+ }
23
+ | {
24
+ type: "auto_compaction_end";
25
+ action: "context-full" | "handoff" | "shake" | "snapcompact";
26
+ result: CompactionResult | undefined;
27
+ aborted: boolean;
28
+ willRetry: boolean;
29
+ errorMessage?: string;
30
+ /** True when compaction was skipped for a benign reason. */
31
+ skipped?: boolean;
32
+ }
33
+ | {
34
+ type: "auto_retry_start";
35
+ attempt: number;
36
+ maxAttempts: number;
37
+ delayMs: number;
38
+ errorMessage: string;
39
+ errorId?: number;
40
+ }
41
+ | {
42
+ type: "auto_retry_end";
43
+ success: boolean;
44
+ attempt: number;
45
+ finalError?: string;
46
+ recoveredErrors?: RecoveredRetryError[];
47
+ }
48
+ | { type: "retry_fallback_applied"; from: string; to: string; role: string }
49
+ | { type: "retry_fallback_succeeded"; model: string; role: string }
50
+ | { type: "ttsr_triggered"; rules: Rule[] }
51
+ | { type: "todo_reminder"; todos: TodoItem[]; attempt: number; maxAttempts: number }
52
+ | { type: "todo_auto_clear" }
53
+ | { type: "irc_message"; message: CustomMessage }
54
+ | { type: "notice"; level: "info" | "warning" | "error"; message: string; source?: string }
55
+ | {
56
+ type: "thinking_level_changed";
57
+ thinkingLevel: ThinkingLevel | undefined;
58
+ /** The user-configured selector when it differs from the effective level. */
59
+ configured?: ConfiguredThinkingLevel;
60
+ /** The level `auto` resolved to this turn, once classified. */
61
+ resolved?: Effort;
62
+ }
63
+ | { type: "goal_updated"; goal: Goal | null; state?: GoalModeState };
64
+
65
+ /** Listener function for agent session events. */
66
+ export type AgentSessionEventListener = (event: AgentSessionEvent) => void;
@@ -0,0 +1,343 @@
1
+ import type { Agent, AgentMessage, AgentTool, StreamFn, ThinkingLevel } from "@oh-my-pi/pi-agent-core";
2
+ import type {
3
+ Context,
4
+ ImageContent,
5
+ Message,
6
+ MessageAttribution,
7
+ Model,
8
+ OAuthAccountSummary,
9
+ ServiceTierByFamily,
10
+ SimpleStreamOptions,
11
+ ToolChoice,
12
+ } from "@oh-my-pi/pi-ai";
13
+ import type { postmortem } from "@oh-my-pi/pi-utils";
14
+ import type { AdvisorConfig } from "../advisor";
15
+ import type { AsyncJob, AsyncJobDeliveryState, AsyncJobManager } from "../async";
16
+ import type { ModelRegistry } from "../config/model-registry";
17
+ import type { PromptTemplate } from "../config/prompt-templates";
18
+ import type { Settings, SkillsSettings } from "../config/settings";
19
+ import type { RawSseDebugBuffer } from "../debug/raw-sse-buffer";
20
+ import type { TtsrManager } from "../export/ttsr";
21
+ import type { LoadedCustomCommand } from "../extensibility/custom-commands";
22
+ import type { ExtensionRunner } from "../extensibility/extensions";
23
+ import type { ContextUsage } from "../extensibility/extensions/types";
24
+ import type { Skill, SkillWarning } from "../extensibility/skills";
25
+ import type { FileSlashCommand } from "../extensibility/slash-commands";
26
+ import type { SecretObfuscator } from "../secrets/obfuscator";
27
+ import type { ConfiguredThinkingLevel } from "../thinking";
28
+ import type { XdevRegistry } from "../tools/xdev";
29
+ import type { SessionManager } from "./session-manager";
30
+
31
+ /** Maximum time the interactive shutdown path waits for Mnemopi consolidation. */
32
+ export const SHUTDOWN_CONSOLIDATE_BUDGET_MS = 1_500;
33
+
34
+ /** Options controlling session disposal. */
35
+ export interface AgentSessionDisposeOptions {
36
+ mnemopiConsolidateTimeoutMs?: number;
37
+ /**
38
+ * Postmortem reason that triggered this dispose (signal/fatal teardown
39
+ * paths). When set, the persisted `session_exit` diagnostic records it
40
+ * instead of the generic `"dispose"` used for normal programmatic disposal
41
+ * (`/quit`, test teardown, subagent completion).
42
+ */
43
+ reason?: postmortem.Reason;
44
+ }
45
+
46
+ /** Listener notified when command metadata changes. */
47
+ export type CommandMetadataChangedListener = () => void | Promise<void>;
48
+ /** Public summary of an asynchronous job. */
49
+ export type AsyncJobSnapshotItem = Pick<AsyncJob, "id" | "type" | "status" | "label" | "startTime">;
50
+
51
+ /** Snapshot of running, recent, and pending-delivery asynchronous jobs. */
52
+ export interface AsyncJobSnapshot {
53
+ running: AsyncJobSnapshotItem[];
54
+ recent: AsyncJobSnapshotItem[];
55
+ delivery: AsyncJobDeliveryState;
56
+ }
57
+
58
+ export type { ShakeMode, ShakeResult } from "./shake-types";
59
+
60
+ /**
61
+ * Prewalk switches an active session one-way from its starting model to a
62
+ * fast/cheap target after implementation begins.
63
+ */
64
+ export interface Prewalk {
65
+ target: Model;
66
+ thinkingLevel?: ConfiguredThinkingLevel;
67
+ }
68
+
69
+ /**
70
+ * PlanYolo starts in read-only plan mode, auto-approves the proposal, then
71
+ * switches to a target model for implementation.
72
+ */
73
+ export interface PlanYolo {
74
+ target: Model;
75
+ thinkingLevel?: ConfiguredThinkingLevel;
76
+ }
77
+
78
+ /** Details shown when confirming a usage-reserve-triggered model fallback. */
79
+ export interface UsageFallbackConfirmation {
80
+ from: string;
81
+ to: string;
82
+ remainingPercent: number | undefined;
83
+ }
84
+
85
+ /** Identifies a retry fallback chain already entered during startup model resolution. */
86
+ export interface InitialRetryFallbackState {
87
+ /** Role whose configured primary was unavailable. */
88
+ role: string;
89
+ /** Configured primary selector retained for restoration when it becomes available. */
90
+ originalSelector: string;
91
+ /** Thinking selector configured for the unavailable primary. */
92
+ originalThinkingLevel: ConfiguredThinkingLevel | undefined;
93
+ /** Prevent cooldown restoration when startup selected this fallback from live usage health. */
94
+ pinned?: boolean;
95
+ }
96
+
97
+ /** Dependencies and initial state used to construct an AgentSession. */
98
+ export interface AgentSessionConfig {
99
+ agent: Agent;
100
+ sessionManager: SessionManager;
101
+ settings: Settings;
102
+ /** Whether the caller explicitly requested yolo/auto-approve behavior for this session. */
103
+ autoApprove?: boolean;
104
+ /** Models to cycle through with Ctrl+P (from --models flag). */
105
+ scopedModels?: Array<{ model: Model; thinkingLevel?: ThinkingLevel }>;
106
+ /** Initial session thinking selector. */
107
+ thinkingLevel?: ConfiguredThinkingLevel;
108
+ /** Retry chain ownership when startup selected one of its fallback entries. */
109
+ initialRetryFallback?: InitialRetryFallbackState;
110
+ /** Prewalk from the starting model to a fast/cheap target after implementation begins. */
111
+ prewalk?: Prewalk;
112
+ /** Force read-only plan mode at start, auto-approve, then switch to the target. */
113
+ planYolo?: PlanYolo;
114
+ /** Initial per-family service tiers for the live session. */
115
+ serviceTierByFamily?: ServiceTierByFamily;
116
+ /** Prompt templates for expansion. */
117
+ promptTemplates?: PromptTemplate[];
118
+ /** File-based slash commands for expansion. */
119
+ slashCommands?: FileSlashCommand[];
120
+ /** Extension runner created with wrapped tools. */
121
+ extensionRunner?: ExtensionRunner;
122
+ /** Loaded skills already discovered by the SDK. */
123
+ skills?: Skill[];
124
+ /** Skill loading warnings already captured by the SDK. */
125
+ skillWarnings?: SkillWarning[];
126
+ /** Whether runtime reloads may rediscover disk-backed skills. */
127
+ skillsReloadable?: boolean;
128
+ /** Custom TypeScript slash commands. */
129
+ customCommands?: LoadedCustomCommand[];
130
+ skillsSettings?: SkillsSettings;
131
+ /** Agent directory used when changing memory backends in a live session. */
132
+ memoryAgentDir?: string;
133
+ /** Recursion depth used to suppress live backend replacement in subagents. */
134
+ memoryTaskDepth?: number;
135
+ /** Creates built-in memory tools for the current backend. */
136
+ createMemoryTools?: () => Promise<AgentTool[]>;
137
+ /** Creates the built-in `computer` tool for session-scoped runtime enablement (see {@link AgentSession.setComputerToolEnabled}). */
138
+ createComputerTool?: () => Promise<AgentTool | null>;
139
+ /** Model registry for API key resolution and model discovery. */
140
+ modelRegistry: ModelRegistry;
141
+ /** Tool registry for LSP and settings. */
142
+ toolRegistry?: Map<string, AgentTool>;
143
+ /** Creates tools registered only while vibe mode is active. */
144
+ createVibeTools?: () => AgentTool[];
145
+ /** Names whose current registry entry is the built-in implementation. */
146
+ builtInToolNames?: Iterable<string>;
147
+ /** Updates tool-session predicates from the live active tool set. */
148
+ setActiveToolNames?: (names: Iterable<string>) => void;
149
+ /** Registers the write transport when runtime xdev mounts first need it. */
150
+ ensureWriteRegistered?: () => Promise<boolean>;
151
+ /** Current session pre-LLM message transform pipeline. */
152
+ transformContext?: (messages: AgentMessage[], signal?: AbortSignal) => AgentMessage[] | Promise<AgentMessage[]>;
153
+ /** Provider request transform applied after message conversion. */
154
+ transformProviderContext?: (context: Context, model: Model) => Context | Promise<Context>;
155
+ /** Stream wrapper for side-channel requests. */
156
+ sideStreamFn?: StreamFn;
157
+ /** Stream wrapper for advisor requests. */
158
+ advisorStreamFn?: StreamFn;
159
+ /** Prefer websocket transport for OpenAI Codex requests when supported. */
160
+ preferWebsockets?: boolean;
161
+ /** Provider payload hook used by the active session request path. */
162
+ onPayload?: SimpleStreamOptions["onPayload"];
163
+ /** Provider response hook used by the active session request path. */
164
+ onResponse?: SimpleStreamOptions["onResponse"];
165
+ /** Raw SSE hook used by the active session request path. */
166
+ onSseEvent?: SimpleStreamOptions["onSseEvent"];
167
+ /** Per-session raw SSE diagnostic buffer. */
168
+ rawSseDebugBuffer?: RawSseDebugBuffer;
169
+ /** Current session message-to-LLM conversion pipeline. */
170
+ convertToLlm?: (messages: AgentMessage[]) => Message[] | Promise<Message[]>;
171
+ /** System prompt builder that can consider tool availability. */
172
+ rebuildSystemPrompt?: (toolNames: string[], tools: Map<string, AgentTool>) => Promise<{ systemPrompt: string[] }>;
173
+ /** Local calendar date provider used by prompt-cache invalidation. */
174
+ getLocalCalendarDate?: () => string;
175
+ /** Tools mounted under `xd://`, for `/tools` display. */
176
+ getXdevToolEntries?: () => Array<{ name: string; summary: string }>;
177
+ /** Session-owned `xd://` registry. */
178
+ xdevRegistry?: XdevRegistry;
179
+ /** Discoverable tools mounted under `xd://` in the initial enabled set. */
180
+ initialMountedXdevToolNames?: string[];
181
+ /** Names pinned top-level during runtime repartitioning. */
182
+ presentationPinnedToolNames?: ReadonlySet<string>;
183
+ /** Accessor for live MCP server instructions. */
184
+ getMcpServerInstructions?: () => Map<string, string> | undefined;
185
+ /** Time-traveling stream-rule manager. */
186
+ ttsrManager?: TtsrManager;
187
+ /** Secret obfuscator for provider and edit content. */
188
+ obfuscator?: SecretObfuscator;
189
+ /** Inherited eval executor session id from a parent agent. */
190
+ parentEvalSessionId?: string;
191
+ /** Logical owner for retained eval kernels created by this session. */
192
+ evalKernelOwnerId?: string;
193
+ /** Async job manager owned and disposed by this session. */
194
+ ownedAsyncJobManager?: AsyncJobManager;
195
+ /** Async job manager visible to this session. */
196
+ asyncJobManager?: AsyncJobManager;
197
+ /** Registry identity used for IRC routing. */
198
+ agentId?: string;
199
+ /** Whether this is a top-level or subagent session. */
200
+ agentKind?: "main" | "sub";
201
+ /** Provider-facing session ID override. */
202
+ providerSessionId?: string;
203
+ /** Whether the provider prompt-cache key was explicit or fork-inherited. */
204
+ providerPromptCacheKeySource?: "explicit" | "fork";
205
+ /** Full advisor toolset built against an advisor-scoped tool session. */
206
+ advisorTools?: AgentTool[];
207
+ /** Preloaded watchdog prompt content for the advisor. */
208
+ advisorWatchdogPrompt?: string;
209
+ /** Shared advisor instructions loaded from WATCHDOG.yml. */
210
+ advisorSharedInstructions?: string;
211
+ /** Project context rendered for advisor sessions. */
212
+ advisorContextPrompt?: string;
213
+ /** Advisors discovered from WATCHDOG.yml. */
214
+ advisorConfigs?: AdvisorConfig[];
215
+ /** Strip tool descriptions from provider-bound side-request tool specs. */
216
+ pruneToolDescriptions?: boolean;
217
+ /** Disconnect the MCP manager owned by this session during disposal. */
218
+ disconnectOwnedMcpManager?: () => Promise<void>;
219
+ /** System prompt used by automatic session-title generation. */
220
+ titleSystemPrompt?: string;
221
+ }
222
+
223
+ /** Options for AgentSession.prompt(). */
224
+ export interface PromptOptions {
225
+ /** Whether to expand file-based prompt templates (default: true). */
226
+ expandPromptTemplates?: boolean;
227
+ /** Image attachments. */
228
+ images?: ImageContent[];
229
+ /** Queue behavior while streaming. */
230
+ streamingBehavior?: "steer" | "followUp";
231
+ /** Optional tool choice override for the next LLM call. */
232
+ toolChoice?: ToolChoice;
233
+ /** Send as a developer/system message instead of user. */
234
+ synthetic?: boolean;
235
+ /** Whether this prompt is a deliberate user action. */
236
+ userInitiated?: boolean;
237
+ /** Explicit billing/initiator attribution. */
238
+ attribution?: MessageAttribution;
239
+ /** Skip pre-send compaction checks for this prompt. */
240
+ skipCompactionCheck?: boolean;
241
+ }
242
+
243
+ /** Options for AgentSession.followUp(). */
244
+ export interface FollowUpOptions {
245
+ /** Enqueue as a hidden developer message instead of a user follow-up. */
246
+ synthetic?: boolean;
247
+ /** Whether to expand file-based prompt templates (default: true). */
248
+ expandPromptTemplates?: boolean;
249
+ /** Explicit billing/initiator attribution. */
250
+ attribution?: MessageAttribution;
251
+ }
252
+
253
+ /** Result from a handoff operation. */
254
+ export interface HandoffResult {
255
+ document: string;
256
+ savedPath?: string;
257
+ }
258
+
259
+ /** Options controlling handoff generation. */
260
+ export interface SessionHandoffOptions {
261
+ autoTriggered?: boolean;
262
+ signal?: AbortSignal;
263
+ onSwitchCancelled?: () => void;
264
+ }
265
+
266
+ /** Result from cycleModel(). */
267
+ export interface ModelCycleResult {
268
+ model: Model;
269
+ thinkingLevel: ThinkingLevel | undefined;
270
+ /** Whether cycling through scoped models or all available models. */
271
+ isScoped: boolean;
272
+ }
273
+
274
+ /** Result from cycleRoleModels(). */
275
+ export interface RoleModelCycleResult {
276
+ model: Model;
277
+ thinkingLevel: ThinkingLevel | undefined;
278
+ role: string;
279
+ }
280
+
281
+ /** A configured role resolved to a concrete model. */
282
+ export interface ResolvedRoleModel {
283
+ role: string;
284
+ model: Model;
285
+ thinkingLevel?: ConfiguredThinkingLevel;
286
+ explicitThinkingLevel: boolean;
287
+ }
288
+
289
+ /** Resolvable role models and the currently active index. */
290
+ export interface RoleModelCycle {
291
+ models: ResolvedRoleModel[];
292
+ currentIndex: number;
293
+ }
294
+
295
+ /** Token breakdown for the current provider context. */
296
+ export interface ContextUsageBreakdown {
297
+ contextWindow: number;
298
+ anchored: boolean;
299
+ usedTokens: number;
300
+ systemPromptTokens: number;
301
+ systemToolsTokens: number;
302
+ systemContextTokens: number;
303
+ skillsTokens: number;
304
+ messagesTokens: number;
305
+ }
306
+
307
+ /** Session statistics for the `/session` command. */
308
+ export interface SessionStats {
309
+ sessionFile: string | undefined;
310
+ sessionId: string;
311
+ userMessages: number;
312
+ assistantMessages: number;
313
+ toolCalls: number;
314
+ toolResults: number;
315
+ totalMessages: number;
316
+ tokens: {
317
+ input: number;
318
+ output: number;
319
+ reasoning: number;
320
+ cacheRead: number;
321
+ cacheWrite: number;
322
+ total: number;
323
+ };
324
+ premiumRequests: number;
325
+ cost: number;
326
+ contextUsage?: ContextUsage;
327
+ }
328
+
329
+ /** Stored OAuth accounts available to the current model provider. */
330
+ export interface SessionOAuthAccountList {
331
+ provider: string;
332
+ accounts: OAuthAccountSummary[];
333
+ }
334
+
335
+ /** IDs for a newly created session and the session it replaced. */
336
+ export interface FreshSessionResult {
337
+ previousSessionId: string;
338
+ sessionId: string;
339
+ closedProviderSessions: number;
340
+ }
341
+
342
+ /** Queued user content restored to the editor. */
343
+ export type RestoredQueuedMessage = { text: string; images?: ImageContent[] };