apex-code 0.0.1-alpha.1 → 0.0.1-alpha.11

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 (798) hide show
  1. package/CHANGELOG.md +482 -0
  2. package/README.md +75 -680
  3. package/dist/cli/args.d.ts +21 -1
  4. package/dist/cli/args.d.ts.map +1 -1
  5. package/dist/cli/args.js +119 -15
  6. package/dist/cli/args.js.map +1 -1
  7. package/dist/cli/auth-command.d.ts.map +1 -1
  8. package/dist/cli/auth-command.js +3 -3
  9. package/dist/cli/auth-command.js.map +1 -1
  10. package/dist/cli/concurrent-session.d.ts +3 -0
  11. package/dist/cli/concurrent-session.d.ts.map +1 -0
  12. package/dist/cli/concurrent-session.js +13 -0
  13. package/dist/cli/concurrent-session.js.map +1 -0
  14. package/dist/cli/cost-command.d.ts +19 -0
  15. package/dist/cli/cost-command.d.ts.map +1 -0
  16. package/dist/cli/cost-command.js +107 -0
  17. package/dist/cli/cost-command.js.map +1 -0
  18. package/dist/cli/file-processor.d.ts.map +1 -1
  19. package/dist/cli/file-processor.js +2 -1
  20. package/dist/cli/file-processor.js.map +1 -1
  21. package/dist/cli/startup-ui.d.ts +1 -1
  22. package/dist/cli/startup-ui.d.ts.map +1 -1
  23. package/dist/cli/startup-ui.js +1 -2
  24. package/dist/cli/startup-ui.js.map +1 -1
  25. package/dist/cli.d.ts.map +1 -1
  26. package/dist/cli.js +99 -16
  27. package/dist/cli.js.map +1 -1
  28. package/dist/config.d.ts +5 -4
  29. package/dist/config.d.ts.map +1 -1
  30. package/dist/config.js +58 -24
  31. package/dist/config.js.map +1 -1
  32. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  33. package/dist/core/agent-session-runtime.js +2 -0
  34. package/dist/core/agent-session-runtime.js.map +1 -1
  35. package/dist/core/agent-session-services.d.ts +28 -0
  36. package/dist/core/agent-session-services.d.ts.map +1 -1
  37. package/dist/core/agent-session-services.js +140 -4
  38. package/dist/core/agent-session-services.js.map +1 -1
  39. package/dist/core/agent-session.d.ts +147 -9
  40. package/dist/core/agent-session.d.ts.map +1 -1
  41. package/dist/core/agent-session.js +440 -123
  42. package/dist/core/agent-session.js.map +1 -1
  43. package/dist/core/auth-storage.d.ts +4 -1
  44. package/dist/core/auth-storage.d.ts.map +1 -1
  45. package/dist/core/auth-storage.js +17 -14
  46. package/dist/core/auth-storage.js.map +1 -1
  47. package/dist/core/bash-executor.d.ts.map +1 -1
  48. package/dist/core/bash-executor.js +18 -10
  49. package/dist/core/bash-executor.js.map +1 -1
  50. package/dist/core/checkpoints/git-checkpoints.d.ts +33 -0
  51. package/dist/core/checkpoints/git-checkpoints.d.ts.map +1 -0
  52. package/dist/core/checkpoints/git-checkpoints.js +230 -0
  53. package/dist/core/checkpoints/git-checkpoints.js.map +1 -0
  54. package/dist/core/checkpoints/session-checkpoints.d.ts +23 -0
  55. package/dist/core/checkpoints/session-checkpoints.d.ts.map +1 -0
  56. package/dist/core/checkpoints/session-checkpoints.js +29 -0
  57. package/dist/core/checkpoints/session-checkpoints.js.map +1 -0
  58. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  59. package/dist/core/compaction/branch-summarization.js +3 -0
  60. package/dist/core/compaction/branch-summarization.js.map +1 -1
  61. package/dist/core/compaction/compaction.d.ts +4 -3
  62. package/dist/core/compaction/compaction.d.ts.map +1 -1
  63. package/dist/core/compaction/compaction.js +41 -32
  64. package/dist/core/compaction/compaction.js.map +1 -1
  65. package/dist/core/context/deferred-schemas.d.ts +92 -0
  66. package/dist/core/context/deferred-schemas.d.ts.map +1 -0
  67. package/dist/core/context/deferred-schemas.js +74 -0
  68. package/dist/core/context/deferred-schemas.js.map +1 -0
  69. package/dist/core/context/eviction.d.ts +47 -0
  70. package/dist/core/context/eviction.d.ts.map +1 -0
  71. package/dist/core/context/eviction.js +83 -0
  72. package/dist/core/context/eviction.js.map +1 -0
  73. package/dist/core/context/pipeline.d.ts +90 -0
  74. package/dist/core/context/pipeline.d.ts.map +1 -0
  75. package/dist/core/context/pipeline.js +109 -0
  76. package/dist/core/context/pipeline.js.map +1 -0
  77. package/dist/core/credential-failover.d.ts +30 -0
  78. package/dist/core/credential-failover.d.ts.map +1 -0
  79. package/dist/core/credential-failover.js +46 -0
  80. package/dist/core/credential-failover.js.map +1 -0
  81. package/dist/core/credential-pool.d.ts +60 -0
  82. package/dist/core/credential-pool.d.ts.map +1 -0
  83. package/dist/core/credential-pool.js +84 -0
  84. package/dist/core/credential-pool.js.map +1 -0
  85. package/dist/core/defaults.d.ts +1 -0
  86. package/dist/core/defaults.d.ts.map +1 -1
  87. package/dist/core/defaults.js +9 -0
  88. package/dist/core/defaults.js.map +1 -1
  89. package/dist/core/delegation/agents.d.ts +15 -0
  90. package/dist/core/delegation/agents.d.ts.map +1 -0
  91. package/dist/core/delegation/agents.js +55 -0
  92. package/dist/core/delegation/agents.js.map +1 -0
  93. package/dist/core/delegation/ceiling.d.ts +29 -0
  94. package/dist/core/delegation/ceiling.d.ts.map +1 -0
  95. package/dist/core/delegation/ceiling.js +34 -0
  96. package/dist/core/delegation/ceiling.js.map +1 -0
  97. package/dist/core/delegation/runtime.d.ts +94 -0
  98. package/dist/core/delegation/runtime.d.ts.map +1 -0
  99. package/dist/core/delegation/runtime.js +117 -0
  100. package/dist/core/delegation/runtime.js.map +1 -0
  101. package/dist/core/durable-state/daemon.d.ts +37 -0
  102. package/dist/core/durable-state/daemon.d.ts.map +1 -0
  103. package/dist/core/durable-state/daemon.js +62 -0
  104. package/dist/core/durable-state/daemon.js.map +1 -0
  105. package/dist/core/durable-state/provenance.d.ts +7 -0
  106. package/dist/core/durable-state/provenance.d.ts.map +1 -0
  107. package/dist/core/durable-state/provenance.js +24 -0
  108. package/dist/core/durable-state/provenance.js.map +1 -0
  109. package/dist/core/durable-state/sqlite.d.ts +84 -0
  110. package/dist/core/durable-state/sqlite.d.ts.map +1 -0
  111. package/dist/core/durable-state/sqlite.js +355 -0
  112. package/dist/core/durable-state/sqlite.js.map +1 -0
  113. package/dist/core/environment.d.ts +12 -0
  114. package/dist/core/environment.d.ts.map +1 -0
  115. package/dist/core/environment.js +69 -0
  116. package/dist/core/environment.js.map +1 -0
  117. package/dist/core/evidence-policy.d.ts +17 -0
  118. package/dist/core/evidence-policy.d.ts.map +1 -0
  119. package/dist/core/evidence-policy.js +25 -0
  120. package/dist/core/evidence-policy.js.map +1 -0
  121. package/dist/core/evidence.d.ts +16 -0
  122. package/dist/core/evidence.d.ts.map +1 -0
  123. package/dist/core/evidence.js +51 -0
  124. package/dist/core/evidence.js.map +1 -0
  125. package/dist/core/exec.d.ts.map +1 -1
  126. package/dist/core/exec.js +5 -2
  127. package/dist/core/exec.js.map +1 -1
  128. package/dist/core/experimental.d.ts +4 -0
  129. package/dist/core/experimental.d.ts.map +1 -1
  130. package/dist/core/experimental.js +6 -1
  131. package/dist/core/experimental.js.map +1 -1
  132. package/dist/core/extensions/index.d.ts +2 -2
  133. package/dist/core/extensions/index.d.ts.map +1 -1
  134. package/dist/core/extensions/index.js +1 -1
  135. package/dist/core/extensions/index.js.map +1 -1
  136. package/dist/core/extensions/loader.d.ts.map +1 -1
  137. package/dist/core/extensions/loader.js +122 -49
  138. package/dist/core/extensions/loader.js.map +1 -1
  139. package/dist/core/extensions/types.d.ts +44 -9
  140. package/dist/core/extensions/types.d.ts.map +1 -1
  141. package/dist/core/extensions/types.js +3 -0
  142. package/dist/core/extensions/types.js.map +1 -1
  143. package/dist/core/footer-data-provider.d.ts +1 -1
  144. package/dist/core/footer-data-provider.d.ts.map +1 -1
  145. package/dist/core/footer-data-provider.js +1 -1
  146. package/dist/core/footer-data-provider.js.map +1 -1
  147. package/dist/core/http-dispatcher.d.ts +1 -2
  148. package/dist/core/http-dispatcher.d.ts.map +1 -1
  149. package/dist/core/http-dispatcher.js +2 -17
  150. package/dist/core/http-dispatcher.js.map +1 -1
  151. package/dist/core/http-idle-timeout.d.ts +12 -0
  152. package/dist/core/http-idle-timeout.d.ts.map +1 -0
  153. package/dist/core/http-idle-timeout.js +27 -0
  154. package/dist/core/http-idle-timeout.js.map +1 -0
  155. package/dist/core/index.d.ts +1 -0
  156. package/dist/core/index.d.ts.map +1 -1
  157. package/dist/core/index.js +1 -0
  158. package/dist/core/index.js.map +1 -1
  159. package/dist/core/keybindings.d.ts +38 -13
  160. package/dist/core/keybindings.d.ts.map +1 -1
  161. package/dist/core/keybindings.js +26 -5
  162. package/dist/core/keybindings.js.map +1 -1
  163. package/dist/core/lsp/client.d.ts +78 -0
  164. package/dist/core/lsp/client.d.ts.map +1 -0
  165. package/dist/core/lsp/client.js +494 -0
  166. package/dist/core/lsp/client.js.map +1 -0
  167. package/dist/core/lsp/diagnostics.d.ts +47 -0
  168. package/dist/core/lsp/diagnostics.d.ts.map +1 -0
  169. package/dist/core/lsp/diagnostics.js +224 -0
  170. package/dist/core/lsp/diagnostics.js.map +1 -0
  171. package/dist/core/lsp/pool.d.ts +48 -0
  172. package/dist/core/lsp/pool.d.ts.map +1 -0
  173. package/dist/core/lsp/pool.js +150 -0
  174. package/dist/core/lsp/pool.js.map +1 -0
  175. package/dist/core/lsp/registry.d.ts +49 -0
  176. package/dist/core/lsp/registry.d.ts.map +1 -0
  177. package/dist/core/lsp/registry.js +215 -0
  178. package/dist/core/lsp/registry.js.map +1 -0
  179. package/dist/core/lsp/status.d.ts +23 -0
  180. package/dist/core/lsp/status.d.ts.map +1 -0
  181. package/dist/core/lsp/status.js +35 -0
  182. package/dist/core/lsp/status.js.map +1 -0
  183. package/dist/core/lsp/sync.d.ts +13 -0
  184. package/dist/core/lsp/sync.d.ts.map +1 -0
  185. package/dist/core/lsp/sync.js +71 -0
  186. package/dist/core/lsp/sync.js.map +1 -0
  187. package/dist/core/mcp/config.d.ts +16 -0
  188. package/dist/core/mcp/config.d.ts.map +1 -0
  189. package/dist/core/mcp/config.js +152 -0
  190. package/dist/core/mcp/config.js.map +1 -0
  191. package/dist/core/mcp/connector.d.ts +10 -0
  192. package/dist/core/mcp/connector.d.ts.map +1 -0
  193. package/dist/core/mcp/connector.js +70 -0
  194. package/dist/core/mcp/connector.js.map +1 -0
  195. package/dist/core/mcp/contract.d.ts +19 -0
  196. package/dist/core/mcp/contract.d.ts.map +1 -0
  197. package/dist/core/mcp/contract.js +89 -0
  198. package/dist/core/mcp/contract.js.map +1 -0
  199. package/dist/core/mcp/mcp-tool.d.ts +32 -0
  200. package/dist/core/mcp/mcp-tool.d.ts.map +1 -0
  201. package/dist/core/mcp/mcp-tool.js +165 -0
  202. package/dist/core/mcp/mcp-tool.js.map +1 -0
  203. package/dist/core/mcp/metadata-cache.d.ts +29 -0
  204. package/dist/core/mcp/metadata-cache.d.ts.map +1 -0
  205. package/dist/core/mcp/metadata-cache.js +99 -0
  206. package/dist/core/mcp/metadata-cache.js.map +1 -0
  207. package/dist/core/mcp/runtime.d.ts +18 -0
  208. package/dist/core/mcp/runtime.d.ts.map +1 -0
  209. package/dist/core/mcp/runtime.js +35 -0
  210. package/dist/core/mcp/runtime.js.map +1 -0
  211. package/dist/core/mcp/schema.d.ts +22 -0
  212. package/dist/core/mcp/schema.d.ts.map +1 -0
  213. package/dist/core/mcp/schema.js +20 -0
  214. package/dist/core/mcp/schema.js.map +1 -0
  215. package/dist/core/mcp/server-manager.d.ts +43 -0
  216. package/dist/core/mcp/server-manager.d.ts.map +1 -0
  217. package/dist/core/mcp/server-manager.js +142 -0
  218. package/dist/core/mcp/server-manager.js.map +1 -0
  219. package/dist/core/mcp/types.d.ts +98 -0
  220. package/dist/core/mcp/types.d.ts.map +1 -0
  221. package/dist/core/mcp/types.js +8 -0
  222. package/dist/core/mcp/types.js.map +1 -0
  223. package/dist/core/model-config.d.ts +18 -0
  224. package/dist/core/model-config.d.ts.map +1 -1
  225. package/dist/core/model-config.js +25 -6
  226. package/dist/core/model-config.js.map +1 -1
  227. package/dist/core/model-resolver.d.ts +21 -0
  228. package/dist/core/model-resolver.d.ts.map +1 -1
  229. package/dist/core/model-resolver.js +73 -8
  230. package/dist/core/model-resolver.js.map +1 -1
  231. package/dist/core/model-runtime.d.ts +73 -0
  232. package/dist/core/model-runtime.d.ts.map +1 -1
  233. package/dist/core/model-runtime.js +225 -8
  234. package/dist/core/model-runtime.js.map +1 -1
  235. package/dist/core/models-store.d.ts.map +1 -1
  236. package/dist/core/models-store.js +2 -1
  237. package/dist/core/models-store.js.map +1 -1
  238. package/dist/core/observability/aggregate.d.ts +21 -0
  239. package/dist/core/observability/aggregate.d.ts.map +1 -0
  240. package/dist/core/observability/aggregate.js +36 -0
  241. package/dist/core/observability/aggregate.js.map +1 -0
  242. package/dist/core/observability/otlp.d.ts +66 -0
  243. package/dist/core/observability/otlp.d.ts.map +1 -0
  244. package/dist/core/observability/otlp.js +95 -0
  245. package/dist/core/observability/otlp.js.map +1 -0
  246. package/dist/core/package-manager.d.ts.map +1 -1
  247. package/dist/core/package-manager.js +40 -16
  248. package/dist/core/package-manager.js.map +1 -1
  249. package/dist/core/permissions/gate.d.ts +42 -0
  250. package/dist/core/permissions/gate.d.ts.map +1 -0
  251. package/dist/core/permissions/gate.js +72 -0
  252. package/dist/core/permissions/gate.js.map +1 -0
  253. package/dist/core/permissions/modes.d.ts +18 -0
  254. package/dist/core/permissions/modes.d.ts.map +1 -0
  255. package/dist/core/permissions/modes.js +57 -0
  256. package/dist/core/permissions/modes.js.map +1 -0
  257. package/dist/core/permissions/responder.d.ts +30 -0
  258. package/dist/core/permissions/responder.d.ts.map +1 -0
  259. package/dist/core/permissions/responder.js +32 -0
  260. package/dist/core/permissions/responder.js.map +1 -0
  261. package/dist/core/permissions/rules.d.ts +34 -0
  262. package/dist/core/permissions/rules.d.ts.map +1 -0
  263. package/dist/core/permissions/rules.js +74 -0
  264. package/dist/core/permissions/rules.js.map +1 -0
  265. package/dist/core/permissions/startup.d.ts +45 -0
  266. package/dist/core/permissions/startup.d.ts.map +1 -0
  267. package/dist/core/permissions/startup.js +63 -0
  268. package/dist/core/permissions/startup.js.map +1 -0
  269. package/dist/core/permissions/store.d.ts +114 -0
  270. package/dist/core/permissions/store.d.ts.map +1 -0
  271. package/dist/core/permissions/store.js +229 -0
  272. package/dist/core/permissions/store.js.map +1 -0
  273. package/dist/core/pi-manifest.d.ts.map +1 -1
  274. package/dist/core/pi-manifest.js +2 -1
  275. package/dist/core/pi-manifest.js.map +1 -1
  276. package/dist/core/project-trust.d.ts.map +1 -1
  277. package/dist/core/project-trust.js +1 -1
  278. package/dist/core/project-trust.js.map +1 -1
  279. package/dist/core/provider-attribution.d.ts.map +1 -1
  280. package/dist/core/provider-attribution.js +6 -7
  281. package/dist/core/provider-attribution.js.map +1 -1
  282. package/dist/core/remote-catalog-provider.d.ts +2 -2
  283. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  284. package/dist/core/remote-catalog-provider.js +22 -17
  285. package/dist/core/remote-catalog-provider.js.map +1 -1
  286. package/dist/core/resource-loader.d.ts.map +1 -1
  287. package/dist/core/resource-loader.js +3 -2
  288. package/dist/core/resource-loader.js.map +1 -1
  289. package/dist/core/sandbox/bwrap-arguments.d.ts +52 -0
  290. package/dist/core/sandbox/bwrap-arguments.d.ts.map +1 -0
  291. package/dist/core/sandbox/bwrap-arguments.js +86 -0
  292. package/dist/core/sandbox/bwrap-arguments.js.map +1 -0
  293. package/dist/core/sandbox/child-entry.d.ts +2 -0
  294. package/dist/core/sandbox/child-entry.d.ts.map +1 -0
  295. package/dist/core/sandbox/child-entry.js +22 -0
  296. package/dist/core/sandbox/child-entry.js.map +1 -0
  297. package/dist/core/sandbox/cli-launch.d.ts +88 -0
  298. package/dist/core/sandbox/cli-launch.d.ts.map +1 -0
  299. package/dist/core/sandbox/cli-launch.js +272 -0
  300. package/dist/core/sandbox/cli-launch.js.map +1 -0
  301. package/dist/core/sandbox/cli-supervisor.d.ts +30 -0
  302. package/dist/core/sandbox/cli-supervisor.d.ts.map +1 -0
  303. package/dist/core/sandbox/cli-supervisor.js +123 -0
  304. package/dist/core/sandbox/cli-supervisor.js.map +1 -0
  305. package/dist/core/sandbox/default-hosts.d.ts +28 -0
  306. package/dist/core/sandbox/default-hosts.d.ts.map +1 -0
  307. package/dist/core/sandbox/default-hosts.js +69 -0
  308. package/dist/core/sandbox/default-hosts.js.map +1 -0
  309. package/dist/core/sandbox/full-access.d.ts +28 -0
  310. package/dist/core/sandbox/full-access.d.ts.map +1 -0
  311. package/dist/core/sandbox/full-access.js +63 -0
  312. package/dist/core/sandbox/full-access.js.map +1 -0
  313. package/dist/core/sandbox/git-identity.d.ts +57 -0
  314. package/dist/core/sandbox/git-identity.d.ts.map +1 -0
  315. package/dist/core/sandbox/git-identity.js +78 -0
  316. package/dist/core/sandbox/git-identity.js.map +1 -0
  317. package/dist/core/sandbox/host-approval.d.ts +42 -0
  318. package/dist/core/sandbox/host-approval.d.ts.map +1 -0
  319. package/dist/core/sandbox/host-approval.js +99 -0
  320. package/dist/core/sandbox/host-approval.js.map +1 -0
  321. package/dist/core/sandbox/linux-backend.d.ts +46 -0
  322. package/dist/core/sandbox/linux-backend.d.ts.map +1 -0
  323. package/dist/core/sandbox/linux-backend.js +304 -0
  324. package/dist/core/sandbox/linux-backend.js.map +1 -0
  325. package/dist/core/sandbox/macos-backend.d.ts +28 -0
  326. package/dist/core/sandbox/macos-backend.d.ts.map +1 -0
  327. package/dist/core/sandbox/macos-backend.js +313 -0
  328. package/dist/core/sandbox/macos-backend.js.map +1 -0
  329. package/dist/core/sandbox/network-proxy.d.ts +38 -0
  330. package/dist/core/sandbox/network-proxy.d.ts.map +1 -0
  331. package/dist/core/sandbox/network-proxy.js +153 -0
  332. package/dist/core/sandbox/network-proxy.js.map +1 -0
  333. package/dist/core/sandbox/network-refusal.d.ts +24 -0
  334. package/dist/core/sandbox/network-refusal.d.ts.map +1 -0
  335. package/dist/core/sandbox/network-refusal.js +72 -0
  336. package/dist/core/sandbox/network-refusal.js.map +1 -0
  337. package/dist/core/sandbox/policy.d.ts +40 -0
  338. package/dist/core/sandbox/policy.d.ts.map +1 -0
  339. package/dist/core/sandbox/policy.js +55 -0
  340. package/dist/core/sandbox/policy.js.map +1 -0
  341. package/dist/core/sandbox/profiles.d.ts +25 -0
  342. package/dist/core/sandbox/profiles.d.ts.map +1 -0
  343. package/dist/core/sandbox/profiles.js +23 -0
  344. package/dist/core/sandbox/profiles.js.map +1 -0
  345. package/dist/core/sandbox/rpc/command-client.d.ts +28 -0
  346. package/dist/core/sandbox/rpc/command-client.d.ts.map +1 -0
  347. package/dist/core/sandbox/rpc/command-client.js +86 -0
  348. package/dist/core/sandbox/rpc/command-client.js.map +1 -0
  349. package/dist/core/sandbox/rpc/command-proxy.d.ts +48 -0
  350. package/dist/core/sandbox/rpc/command-proxy.d.ts.map +1 -0
  351. package/dist/core/sandbox/rpc/command-proxy.js +120 -0
  352. package/dist/core/sandbox/rpc/command-proxy.js.map +1 -0
  353. package/dist/core/sandbox/rpc/credential-client.d.ts +20 -0
  354. package/dist/core/sandbox/rpc/credential-client.d.ts.map +1 -0
  355. package/dist/core/sandbox/rpc/credential-client.js +170 -0
  356. package/dist/core/sandbox/rpc/credential-client.js.map +1 -0
  357. package/dist/core/sandbox/rpc/credential-proxy.d.ts +44 -0
  358. package/dist/core/sandbox/rpc/credential-proxy.d.ts.map +1 -0
  359. package/dist/core/sandbox/rpc/credential-proxy.js +287 -0
  360. package/dist/core/sandbox/rpc/credential-proxy.js.map +1 -0
  361. package/dist/core/sandbox/rpc/framing.d.ts +35 -0
  362. package/dist/core/sandbox/rpc/framing.d.ts.map +1 -0
  363. package/dist/core/sandbox/rpc/framing.js +114 -0
  364. package/dist/core/sandbox/rpc/framing.js.map +1 -0
  365. package/dist/core/sandbox/rpc/git-credential-helper.d.ts +40 -0
  366. package/dist/core/sandbox/rpc/git-credential-helper.d.ts.map +1 -0
  367. package/dist/core/sandbox/rpc/git-credential-helper.js +152 -0
  368. package/dist/core/sandbox/rpc/git-credential-helper.js.map +1 -0
  369. package/dist/core/sandbox/rpc/git-credential-proxy.d.ts +48 -0
  370. package/dist/core/sandbox/rpc/git-credential-proxy.d.ts.map +1 -0
  371. package/dist/core/sandbox/rpc/git-credential-proxy.js +142 -0
  372. package/dist/core/sandbox/rpc/git-credential-proxy.js.map +1 -0
  373. package/dist/core/sandbox/supervisor-temp.d.ts +18 -0
  374. package/dist/core/sandbox/supervisor-temp.d.ts.map +1 -0
  375. package/dist/core/sandbox/supervisor-temp.js +21 -0
  376. package/dist/core/sandbox/supervisor-temp.js.map +1 -0
  377. package/dist/core/sandbox/supervisor.d.ts +51 -0
  378. package/dist/core/sandbox/supervisor.d.ts.map +1 -0
  379. package/dist/core/sandbox/supervisor.js +18 -0
  380. package/dist/core/sandbox/supervisor.js.map +1 -0
  381. package/dist/core/sandbox/terminal-handoff.d.ts +45 -0
  382. package/dist/core/sandbox/terminal-handoff.d.ts.map +1 -0
  383. package/dist/core/sandbox/terminal-handoff.js +176 -0
  384. package/dist/core/sandbox/terminal-handoff.js.map +1 -0
  385. package/dist/core/sandbox/terminal-size.d.ts +40 -0
  386. package/dist/core/sandbox/terminal-size.d.ts.map +1 -0
  387. package/dist/core/sandbox/terminal-size.js +105 -0
  388. package/dist/core/sandbox/terminal-size.js.map +1 -0
  389. package/dist/core/sandbox/violations.d.ts +23 -0
  390. package/dist/core/sandbox/violations.d.ts.map +1 -0
  391. package/dist/core/sandbox/violations.js +30 -0
  392. package/dist/core/sandbox/violations.js.map +1 -0
  393. package/dist/core/sdk.d.ts +32 -41
  394. package/dist/core/sdk.d.ts.map +1 -1
  395. package/dist/core/sdk.js +174 -6
  396. package/dist/core/sdk.js.map +1 -1
  397. package/dist/core/session-export.d.ts +4 -0
  398. package/dist/core/session-export.d.ts.map +1 -0
  399. package/dist/core/session-export.js +32 -0
  400. package/dist/core/session-export.js.map +1 -0
  401. package/dist/core/session-lease.d.ts +31 -0
  402. package/dist/core/session-lease.d.ts.map +1 -0
  403. package/dist/core/session-lease.js +138 -0
  404. package/dist/core/session-lease.js.map +1 -0
  405. package/dist/core/session-manager.d.ts +58 -2
  406. package/dist/core/session-manager.d.ts.map +1 -1
  407. package/dist/core/session-manager.js +92 -7
  408. package/dist/core/session-manager.js.map +1 -1
  409. package/dist/core/session-share.d.ts +31 -0
  410. package/dist/core/session-share.d.ts.map +1 -0
  411. package/dist/core/session-share.js +45 -0
  412. package/dist/core/session-share.js.map +1 -0
  413. package/dist/core/settings-diagnostics.d.ts +9 -0
  414. package/dist/core/settings-diagnostics.d.ts.map +1 -0
  415. package/dist/core/settings-diagnostics.js +21 -0
  416. package/dist/core/settings-diagnostics.js.map +1 -0
  417. package/dist/core/settings-manager.d.ts +99 -9
  418. package/dist/core/settings-manager.d.ts.map +1 -1
  419. package/dist/core/settings-manager.js +141 -36
  420. package/dist/core/settings-manager.js.map +1 -1
  421. package/dist/core/skills.d.ts +19 -7
  422. package/dist/core/skills.d.ts.map +1 -1
  423. package/dist/core/skills.js +128 -52
  424. package/dist/core/skills.js.map +1 -1
  425. package/dist/core/slash-commands.d.ts.map +1 -1
  426. package/dist/core/slash-commands.js +6 -2
  427. package/dist/core/slash-commands.js.map +1 -1
  428. package/dist/core/system-prompt.d.ts +2 -2
  429. package/dist/core/system-prompt.d.ts.map +1 -1
  430. package/dist/core/system-prompt.js +59 -68
  431. package/dist/core/system-prompt.js.map +1 -1
  432. package/dist/core/timings.d.ts +1 -1
  433. package/dist/core/timings.d.ts.map +1 -1
  434. package/dist/core/timings.js +3 -2
  435. package/dist/core/timings.js.map +1 -1
  436. package/dist/core/tools/ask-user.d.ts +25 -0
  437. package/dist/core/tools/ask-user.d.ts.map +1 -0
  438. package/dist/core/tools/ask-user.js +49 -0
  439. package/dist/core/tools/ask-user.js.map +1 -0
  440. package/dist/core/tools/bash-command-segments.d.ts +22 -0
  441. package/dist/core/tools/bash-command-segments.d.ts.map +1 -0
  442. package/dist/core/tools/bash-command-segments.js +128 -0
  443. package/dist/core/tools/bash-command-segments.js.map +1 -0
  444. package/dist/core/tools/bash.d.ts +40 -4
  445. package/dist/core/tools/bash.d.ts.map +1 -1
  446. package/dist/core/tools/bash.js +183 -32
  447. package/dist/core/tools/bash.js.map +1 -1
  448. package/dist/core/tools/contract-snapshot.d.ts +58 -0
  449. package/dist/core/tools/contract-snapshot.d.ts.map +1 -0
  450. package/dist/core/tools/contract-snapshot.js +51 -0
  451. package/dist/core/tools/contract-snapshot.js.map +1 -0
  452. package/dist/core/tools/contract.d.ts +185 -0
  453. package/dist/core/tools/contract.d.ts.map +1 -0
  454. package/dist/core/tools/contract.js +50 -0
  455. package/dist/core/tools/contract.js.map +1 -0
  456. package/dist/core/tools/delegate.d.ts +38 -0
  457. package/dist/core/tools/delegate.d.ts.map +1 -0
  458. package/dist/core/tools/delegate.js +90 -0
  459. package/dist/core/tools/delegate.js.map +1 -0
  460. package/dist/core/tools/diagnostics.d.ts +39 -0
  461. package/dist/core/tools/diagnostics.d.ts.map +1 -0
  462. package/dist/core/tools/diagnostics.js +62 -0
  463. package/dist/core/tools/diagnostics.js.map +1 -0
  464. package/dist/core/tools/edit-diff.d.ts +0 -5
  465. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  466. package/dist/core/tools/edit-diff.js +2 -5
  467. package/dist/core/tools/edit-diff.js.map +1 -1
  468. package/dist/core/tools/edit.d.ts +12 -2
  469. package/dist/core/tools/edit.d.ts.map +1 -1
  470. package/dist/core/tools/edit.js +61 -10
  471. package/dist/core/tools/edit.js.map +1 -1
  472. package/dist/core/tools/find.d.ts +2 -2
  473. package/dist/core/tools/find.d.ts.map +1 -1
  474. package/dist/core/tools/find.js +13 -1
  475. package/dist/core/tools/find.js.map +1 -1
  476. package/dist/core/tools/grep.d.ts +4 -2
  477. package/dist/core/tools/grep.d.ts.map +1 -1
  478. package/dist/core/tools/grep.js +47 -10
  479. package/dist/core/tools/grep.js.map +1 -1
  480. package/dist/core/tools/index.d.ts +60 -6
  481. package/dist/core/tools/index.d.ts.map +1 -1
  482. package/dist/core/tools/index.js +148 -2
  483. package/dist/core/tools/index.js.map +1 -1
  484. package/dist/core/tools/ls.d.ts +4 -2
  485. package/dist/core/tools/ls.d.ts.map +1 -1
  486. package/dist/core/tools/ls.js +17 -1
  487. package/dist/core/tools/ls.js.map +1 -1
  488. package/dist/core/tools/lsp.d.ts +62 -0
  489. package/dist/core/tools/lsp.d.ts.map +1 -0
  490. package/dist/core/tools/lsp.js +216 -0
  491. package/dist/core/tools/lsp.js.map +1 -0
  492. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  493. package/dist/core/tools/output-accumulator.js +1 -1
  494. package/dist/core/tools/output-accumulator.js.map +1 -1
  495. package/dist/core/tools/path-permission.d.ts +18 -0
  496. package/dist/core/tools/path-permission.d.ts.map +1 -0
  497. package/dist/core/tools/path-permission.js +28 -0
  498. package/dist/core/tools/path-permission.js.map +1 -0
  499. package/dist/core/tools/plan-present.d.ts +27 -0
  500. package/dist/core/tools/plan-present.d.ts.map +1 -0
  501. package/dist/core/tools/plan-present.js +55 -0
  502. package/dist/core/tools/plan-present.js.map +1 -0
  503. package/dist/core/tools/powershell.d.ts +16 -0
  504. package/dist/core/tools/powershell.d.ts.map +1 -0
  505. package/dist/core/tools/powershell.js +39 -0
  506. package/dist/core/tools/powershell.js.map +1 -0
  507. package/dist/core/tools/read.d.ts +2 -2
  508. package/dist/core/tools/read.d.ts.map +1 -1
  509. package/dist/core/tools/read.js +14 -0
  510. package/dist/core/tools/read.js.map +1 -1
  511. package/dist/core/tools/skill-search.d.ts +32 -0
  512. package/dist/core/tools/skill-search.d.ts.map +1 -0
  513. package/dist/core/tools/skill-search.js +56 -0
  514. package/dist/core/tools/skill-search.js.map +1 -0
  515. package/dist/core/tools/test.d.ts +34 -0
  516. package/dist/core/tools/test.d.ts.map +1 -0
  517. package/dist/core/tools/test.js +75 -0
  518. package/dist/core/tools/test.js.map +1 -0
  519. package/dist/core/tools/todo-write.d.ts +31 -0
  520. package/dist/core/tools/todo-write.d.ts.map +1 -0
  521. package/dist/core/tools/todo-write.js +51 -0
  522. package/dist/core/tools/todo-write.js.map +1 -0
  523. package/dist/core/tools/tool-definition-wrapper.d.ts +13 -2
  524. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  525. package/dist/core/tools/tool-definition-wrapper.js +11 -1
  526. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  527. package/dist/core/tools/tool-schema.d.ts +22 -0
  528. package/dist/core/tools/tool-schema.d.ts.map +1 -0
  529. package/dist/core/tools/tool-schema.js +45 -0
  530. package/dist/core/tools/tool-schema.js.map +1 -0
  531. package/dist/core/tools/web-fetch.d.ts +26 -0
  532. package/dist/core/tools/web-fetch.d.ts.map +1 -0
  533. package/dist/core/tools/web-fetch.js +62 -0
  534. package/dist/core/tools/web-fetch.js.map +1 -0
  535. package/dist/core/tools/web-search-exa.d.ts +33 -0
  536. package/dist/core/tools/web-search-exa.d.ts.map +1 -0
  537. package/dist/core/tools/web-search-exa.js +128 -0
  538. package/dist/core/tools/web-search-exa.js.map +1 -0
  539. package/dist/core/tools/web-search.d.ts +26 -0
  540. package/dist/core/tools/web-search.d.ts.map +1 -0
  541. package/dist/core/tools/web-search.js +53 -0
  542. package/dist/core/tools/web-search.js.map +1 -0
  543. package/dist/core/tools/write.d.ts +16 -2
  544. package/dist/core/tools/write.d.ts.map +1 -1
  545. package/dist/core/tools/write.js +48 -2
  546. package/dist/core/tools/write.js.map +1 -1
  547. package/dist/core/trust-manager.d.ts.map +1 -1
  548. package/dist/core/trust-manager.js +2 -1
  549. package/dist/core/trust-manager.js.map +1 -1
  550. package/dist/core/usage-performance-store.d.ts +56 -0
  551. package/dist/core/usage-performance-store.d.ts.map +1 -0
  552. package/dist/core/usage-performance-store.js +85 -0
  553. package/dist/core/usage-performance-store.js.map +1 -0
  554. package/dist/core/web-search-provider.d.ts +64 -0
  555. package/dist/core/web-search-provider.d.ts.map +1 -0
  556. package/dist/core/web-search-provider.js +149 -0
  557. package/dist/core/web-search-provider.js.map +1 -0
  558. package/dist/extensions/llama/index.d.ts.map +1 -1
  559. package/dist/extensions/llama/index.js +2 -0
  560. package/dist/extensions/llama/index.js.map +1 -1
  561. package/dist/extensions/llama/provider.d.ts.map +1 -1
  562. package/dist/extensions/llama/provider.js +6 -2
  563. package/dist/extensions/llama/provider.js.map +1 -1
  564. package/dist/index.d.ts +9 -6
  565. package/dist/index.d.ts.map +1 -1
  566. package/dist/index.js +7 -4
  567. package/dist/index.js.map +1 -1
  568. package/dist/main.d.ts +5 -0
  569. package/dist/main.d.ts.map +1 -1
  570. package/dist/main.js +87 -22
  571. package/dist/main.js.map +1 -1
  572. package/dist/migrations.d.ts.map +1 -1
  573. package/dist/migrations.js +6 -5
  574. package/dist/migrations.js.map +1 -1
  575. package/dist/modes/interactive/components/assistant-message.d.ts +29 -0
  576. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  577. package/dist/modes/interactive/components/assistant-message.js +182 -23
  578. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  579. package/dist/modes/interactive/components/bash-execution.d.ts +7 -0
  580. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  581. package/dist/modes/interactive/components/bash-execution.js +20 -0
  582. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  583. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  584. package/dist/modes/interactive/components/config-selector.js +9 -6
  585. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  586. package/dist/modes/interactive/components/custom-editor.d.ts +72 -1
  587. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  588. package/dist/modes/interactive/components/custom-editor.js +338 -1
  589. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  590. package/dist/modes/interactive/components/dynamic-border.d.ts +7 -1
  591. package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
  592. package/dist/modes/interactive/components/dynamic-border.js +11 -2
  593. package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  594. package/dist/modes/interactive/components/extension-selector.d.ts +4 -0
  595. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  596. package/dist/modes/interactive/components/extension-selector.js +24 -6
  597. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  598. package/dist/modes/interactive/components/first-time-setup.d.ts +1 -4
  599. package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -1
  600. package/dist/modes/interactive/components/first-time-setup.js +17 -41
  601. package/dist/modes/interactive/components/first-time-setup.js.map +1 -1
  602. package/dist/modes/interactive/components/first-use-hints.d.ts +8 -0
  603. package/dist/modes/interactive/components/first-use-hints.d.ts.map +1 -0
  604. package/dist/modes/interactive/components/first-use-hints.js +22 -0
  605. package/dist/modes/interactive/components/first-use-hints.js.map +1 -0
  606. package/dist/modes/interactive/components/footer.d.ts +31 -1
  607. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  608. package/dist/modes/interactive/components/footer.js +205 -24
  609. package/dist/modes/interactive/components/footer.js.map +1 -1
  610. package/dist/modes/interactive/components/index.d.ts +2 -0
  611. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  612. package/dist/modes/interactive/components/index.js +2 -0
  613. package/dist/modes/interactive/components/index.js.map +1 -1
  614. package/dist/modes/interactive/components/model-selector.d.ts +31 -9
  615. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  616. package/dist/modes/interactive/components/model-selector.js +236 -96
  617. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  618. package/dist/modes/interactive/components/settings-selector.d.ts +25 -5
  619. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  620. package/dist/modes/interactive/components/settings-selector.js +226 -58
  621. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  622. package/dist/modes/interactive/components/settings-submenu.d.ts +72 -0
  623. package/dist/modes/interactive/components/settings-submenu.d.ts.map +1 -0
  624. package/dist/modes/interactive/components/settings-submenu.js +165 -0
  625. package/dist/modes/interactive/components/settings-submenu.js.map +1 -0
  626. package/dist/modes/interactive/components/splash-header.d.ts +66 -0
  627. package/dist/modes/interactive/components/splash-header.d.ts.map +1 -0
  628. package/dist/modes/interactive/components/splash-header.js +180 -0
  629. package/dist/modes/interactive/components/splash-header.js.map +1 -0
  630. package/dist/modes/interactive/components/thinking-selector.d.ts +15 -3
  631. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  632. package/dist/modes/interactive/components/thinking-selector.js +74 -17
  633. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  634. package/dist/modes/interactive/components/tool-execution.d.ts +28 -1
  635. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  636. package/dist/modes/interactive/components/tool-execution.js +144 -35
  637. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  638. package/dist/modes/interactive/components/tool-panel.d.ts +30 -0
  639. package/dist/modes/interactive/components/tool-panel.d.ts.map +1 -0
  640. package/dist/modes/interactive/components/tool-panel.js +130 -0
  641. package/dist/modes/interactive/components/tool-panel.js.map +1 -0
  642. package/dist/modes/interactive/external-editor.d.ts.map +1 -1
  643. package/dist/modes/interactive/external-editor.js +60 -10
  644. package/dist/modes/interactive/external-editor.js.map +1 -1
  645. package/dist/modes/interactive/interactive-mode.d.ts +90 -5
  646. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  647. package/dist/modes/interactive/interactive-mode.js +729 -206
  648. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  649. package/dist/modes/interactive/model-catalog-refresh.d.ts +7 -0
  650. package/dist/modes/interactive/model-catalog-refresh.d.ts.map +1 -0
  651. package/dist/modes/interactive/model-catalog-refresh.js +34 -0
  652. package/dist/modes/interactive/model-catalog-refresh.js.map +1 -0
  653. package/dist/modes/interactive/theme/apex.json +93 -0
  654. package/dist/modes/interactive/theme/dark.json +2 -0
  655. package/dist/modes/interactive/theme/light.json +3 -1
  656. package/dist/modes/interactive/theme/theme-controller.d.ts +10 -2
  657. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
  658. package/dist/modes/interactive/theme/theme-controller.js +25 -11
  659. package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
  660. package/dist/modes/interactive/theme/theme-schema.json +11 -3
  661. package/dist/modes/interactive/theme/theme.d.ts +14 -3
  662. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  663. package/dist/modes/interactive/theme/theme.js +65 -10
  664. package/dist/modes/interactive/theme/theme.js.map +1 -1
  665. package/dist/modes/json-event.d.ts +18 -12
  666. package/dist/modes/json-event.d.ts.map +1 -1
  667. package/dist/modes/json-event.js +22 -5
  668. package/dist/modes/json-event.js.map +1 -1
  669. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  670. package/dist/modes/rpc/rpc-mode.js +2 -1
  671. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  672. package/dist/package-manager-cli.d.ts +1 -0
  673. package/dist/package-manager-cli.d.ts.map +1 -1
  674. package/dist/package-manager-cli.js +210 -19
  675. package/dist/package-manager-cli.js.map +1 -1
  676. package/dist/rpc-entry.d.ts.map +1 -1
  677. package/dist/rpc-entry.js +2 -1
  678. package/dist/rpc-entry.js.map +1 -1
  679. package/dist/testing/replay/metrics.d.ts +24 -0
  680. package/dist/testing/replay/metrics.d.ts.map +1 -0
  681. package/dist/testing/replay/metrics.js +35 -0
  682. package/dist/testing/replay/metrics.js.map +1 -0
  683. package/dist/testing/replay/recorded-provider.d.ts +10 -0
  684. package/dist/testing/replay/recorded-provider.d.ts.map +1 -0
  685. package/dist/testing/replay/recorded-provider.js +108 -0
  686. package/dist/testing/replay/recorded-provider.js.map +1 -0
  687. package/dist/testing/replay/runner.d.ts +56 -0
  688. package/dist/testing/replay/runner.d.ts.map +1 -0
  689. package/dist/testing/replay/runner.js +406 -0
  690. package/dist/testing/replay/runner.js.map +1 -0
  691. package/dist/themes/apex-logo.d.ts +41 -0
  692. package/dist/themes/apex-logo.d.ts.map +1 -0
  693. package/dist/themes/apex-logo.js +35 -0
  694. package/dist/themes/apex-logo.js.map +1 -0
  695. package/dist/utils/apex-code-user-agent.d.ts +2 -0
  696. package/dist/utils/apex-code-user-agent.d.ts.map +1 -0
  697. package/dist/utils/apex-code-user-agent.js +5 -0
  698. package/dist/utils/apex-code-user-agent.js.map +1 -0
  699. package/dist/utils/changelog.d.ts +7 -2
  700. package/dist/utils/changelog.d.ts.map +1 -1
  701. package/dist/utils/changelog.js +82 -13
  702. package/dist/utils/changelog.js.map +1 -1
  703. package/dist/utils/clipboard-image.d.ts.map +1 -1
  704. package/dist/utils/clipboard-image.js +1 -1
  705. package/dist/utils/clipboard-image.js.map +1 -1
  706. package/dist/utils/frontmatter.d.ts.map +1 -1
  707. package/dist/utils/frontmatter.js +2 -1
  708. package/dist/utils/frontmatter.js.map +1 -1
  709. package/dist/utils/management-http.d.ts +5 -3
  710. package/dist/utils/management-http.d.ts.map +1 -1
  711. package/dist/utils/management-http.js +14 -10
  712. package/dist/utils/management-http.js.map +1 -1
  713. package/dist/utils/shell.d.ts +3 -0
  714. package/dist/utils/shell.d.ts.map +1 -1
  715. package/dist/utils/shell.js +17 -5
  716. package/dist/utils/shell.js.map +1 -1
  717. package/dist/utils/syntax-highlight.d.ts +1 -0
  718. package/dist/utils/syntax-highlight.d.ts.map +1 -1
  719. package/dist/utils/syntax-highlight.js +60 -1
  720. package/dist/utils/syntax-highlight.js.map +1 -1
  721. package/dist/utils/text.d.ts +8 -0
  722. package/dist/utils/text.d.ts.map +1 -0
  723. package/dist/utils/text.js +9 -0
  724. package/dist/utils/text.js.map +1 -0
  725. package/dist/utils/tools-manager.d.ts +70 -2
  726. package/dist/utils/tools-manager.d.ts.map +1 -1
  727. package/dist/utils/tools-manager.js +280 -124
  728. package/dist/utils/tools-manager.js.map +1 -1
  729. package/dist/utils/version-check.d.ts +7 -5
  730. package/dist/utils/version-check.d.ts.map +1 -1
  731. package/dist/utils/version-check.js +27 -14
  732. package/dist/utils/version-check.js.map +1 -1
  733. package/dist/utils/windows-self-update.d.ts.map +1 -1
  734. package/dist/utils/windows-self-update.js +1 -1
  735. package/dist/utils/windows-self-update.js.map +1 -1
  736. package/docs/compaction.md +41 -24
  737. package/docs/containerization.md +24 -21
  738. package/docs/custom-provider.md +15 -12
  739. package/docs/development.md +11 -11
  740. package/docs/environment-variables.md +37 -77
  741. package/docs/extensions.md +68 -54
  742. package/docs/index.md +12 -24
  743. package/docs/json.md +18 -11
  744. package/docs/keybindings.md +18 -12
  745. package/docs/llama-cpp.md +9 -7
  746. package/docs/models.md +17 -11
  747. package/docs/packages.md +47 -43
  748. package/docs/prompt-templates.md +3 -3
  749. package/docs/providers.md +10 -10
  750. package/docs/quickstart.md +49 -32
  751. package/docs/rpc.md +35 -18
  752. package/docs/sdk.md +20 -6
  753. package/docs/security.md +18 -18
  754. package/docs/session-format.md +9 -9
  755. package/docs/sessions.md +13 -13
  756. package/docs/settings.md +83 -16
  757. package/docs/shell-aliases.md +1 -1
  758. package/docs/skills.md +66 -15
  759. package/docs/terminal-setup.md +44 -19
  760. package/docs/termux.md +4 -4
  761. package/docs/themes.md +32 -11
  762. package/docs/tmux.md +4 -4
  763. package/docs/tui.md +5 -5
  764. package/docs/usage.md +61 -53
  765. package/docs/windows.md +24 -2
  766. package/examples/extensions/border-status-editor.ts +1 -1
  767. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  768. package/examples/extensions/custom-provider-anthropic/package.json +2 -2
  769. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  770. package/examples/extensions/git-checkpoint.ts +24 -36
  771. package/examples/extensions/gondolin/package-lock.json +2 -2
  772. package/examples/extensions/gondolin/package.json +1 -1
  773. package/examples/extensions/notify.ts +3 -1
  774. package/examples/extensions/sandbox/package-lock.json +2 -2
  775. package/examples/extensions/sandbox/package.json +1 -1
  776. package/examples/extensions/subagent/README.md +3 -1
  777. package/examples/extensions/subagent/agents.ts +40 -9
  778. package/examples/extensions/subagent/index.ts +27 -4
  779. package/examples/extensions/titlebar-spinner.ts +1 -1
  780. package/examples/extensions/with-deps/package-lock.json +2 -2
  781. package/examples/extensions/with-deps/package.json +1 -1
  782. package/examples/rpc-extension-ui.ts +1 -1
  783. package/examples/sdk/06-extensions.ts +1 -1
  784. package/examples/sdk/README.md +1 -1
  785. package/npm-shrinkwrap.json +435 -452
  786. package/package.json +17 -18
  787. package/dist/core/telemetry.d.ts +0 -3
  788. package/dist/core/telemetry.d.ts.map +0 -1
  789. package/dist/core/telemetry.js +0 -9
  790. package/dist/core/telemetry.js.map +0 -1
  791. package/dist/server/create-harness.d.ts +0 -26
  792. package/dist/server/create-harness.d.ts.map +0 -1
  793. package/dist/server/create-harness.js +0 -104
  794. package/dist/server/create-harness.js.map +0 -1
  795. package/dist/utils/pi-user-agent.d.ts +0 -2
  796. package/dist/utils/pi-user-agent.d.ts.map +0 -1
  797. package/dist/utils/pi-user-agent.js +0 -5
  798. package/dist/utils/pi-user-agent.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../src/migrations.ts"],"names":[],"mappings":"AAAA;;GAEG;AAaH;;;;GAIG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,EAAE,CAoDhD;AAED;;;;;;;;GAQG;AACH,wBAAgB,4BAA4B,IAAI,IAAI,CA+CnD;AA+ID;;GAEG;AACH,wBAAsB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAqB/E;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG;IAC3C,qBAAqB,EAAE,MAAM,EAAE,CAAC;IAChC,mBAAmB,EAAE,MAAM,EAAE,CAAC;CAC9B,CAOA","sourcesContent":["/**\n * One-time migrations that run on startup.\n */\n\nimport chalk from \"chalk\";\nimport { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync } from \"fs\";\nimport { dirname, join } from \"path\";\nimport { CONFIG_DIR_NAME, getAgentDir, getBinDir } from \"./config.ts\";\nimport { migrateKeybindingsConfig } from \"./core/keybindings.ts\";\n\nconst MIGRATION_GUIDE_URL =\n\t\"https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/CHANGELOG.md#extensions-migration\";\nconst EXTENSIONS_DOC_URL =\n\t\"https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/docs/extensions.md\";\n\n/**\n * Migrate legacy oauth.json and settings.json apiKeys to auth.json.\n *\n * @returns Array of provider names that were migrated\n */\nexport function migrateAuthToAuthJson(): string[] {\n\tconst agentDir = getAgentDir();\n\tconst authPath = join(agentDir, \"auth.json\");\n\tconst oauthPath = join(agentDir, \"oauth.json\");\n\tconst settingsPath = join(agentDir, \"settings.json\");\n\n\t// Skip if auth.json already exists\n\tif (existsSync(authPath)) return [];\n\n\tconst migrated: Record<string, unknown> = {};\n\tconst providers: string[] = [];\n\n\t// Migrate oauth.json\n\tif (existsSync(oauthPath)) {\n\t\ttry {\n\t\t\tconst oauth = JSON.parse(readFileSync(oauthPath, \"utf-8\"));\n\t\t\tfor (const [provider, cred] of Object.entries(oauth)) {\n\t\t\t\tmigrated[provider] = { type: \"oauth\", ...(cred as object) };\n\t\t\t\tproviders.push(provider);\n\t\t\t}\n\t\t\trenameSync(oauthPath, `${oauthPath}.migrated`);\n\t\t} catch {\n\t\t\t// Skip on error\n\t\t}\n\t}\n\n\t// Migrate settings.json apiKeys\n\tif (existsSync(settingsPath)) {\n\t\ttry {\n\t\t\tconst content = readFileSync(settingsPath, \"utf-8\");\n\t\t\tconst settings = JSON.parse(content);\n\t\t\tif (settings.apiKeys && typeof settings.apiKeys === \"object\") {\n\t\t\t\tfor (const [provider, key] of Object.entries(settings.apiKeys)) {\n\t\t\t\t\tif (!migrated[provider] && typeof key === \"string\") {\n\t\t\t\t\t\tmigrated[provider] = { type: \"api_key\", key };\n\t\t\t\t\t\tproviders.push(provider);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdelete settings.apiKeys;\n\t\t\t\twriteFileSync(settingsPath, JSON.stringify(settings, null, 2));\n\t\t\t}\n\t\t} catch {\n\t\t\t// Skip on error\n\t\t}\n\t}\n\n\tif (Object.keys(migrated).length > 0) {\n\t\tmkdirSync(dirname(authPath), { recursive: true });\n\t\twriteFileSync(authPath, JSON.stringify(migrated, null, 2), { mode: 0o600 });\n\t}\n\n\treturn providers;\n}\n\n/**\n * Migrate sessions from ~/.pi/agent/*.jsonl to proper session directories.\n *\n * Bug in v0.30.0: Sessions were saved to ~/.pi/agent/ instead of\n * ~/.pi/agent/sessions/<encoded-cwd>/. This migration moves them\n * to the correct location based on the cwd in their session header.\n *\n * See: https://github.com/earendil-works/pi-mono/issues/320\n */\nexport function migrateSessionsFromAgentRoot(): void {\n\tconst agentDir = getAgentDir();\n\n\t// Find all .jsonl files directly in agentDir (not in subdirectories)\n\tlet files: string[];\n\ttry {\n\t\tfiles = readdirSync(agentDir)\n\t\t\t.filter((f) => f.endsWith(\".jsonl\"))\n\t\t\t.map((f) => join(agentDir, f));\n\t} catch {\n\t\treturn;\n\t}\n\n\tif (files.length === 0) return;\n\n\tfor (const file of files) {\n\t\ttry {\n\t\t\t// Read first line to get session header\n\t\t\tconst content = readFileSync(file, \"utf8\");\n\t\t\tconst firstLine = content.split(\"\\n\")[0];\n\t\t\tif (!firstLine?.trim()) continue;\n\n\t\t\tconst header = JSON.parse(firstLine);\n\t\t\tif (header.type !== \"session\" || !header.cwd) continue;\n\n\t\t\tconst cwd: string = header.cwd;\n\n\t\t\t// Compute the correct session directory (same encoding as session-manager.ts)\n\t\t\tconst safePath = `--${cwd.replace(/^[/\\\\]/, \"\").replace(/[/\\\\:]/g, \"-\")}--`;\n\t\t\tconst correctDir = join(agentDir, \"sessions\", safePath);\n\n\t\t\t// Create directory if needed\n\t\t\tif (!existsSync(correctDir)) {\n\t\t\t\tmkdirSync(correctDir, { recursive: true });\n\t\t\t}\n\n\t\t\t// Move the file\n\t\t\tconst fileName = file.split(\"/\").pop() || file.split(\"\\\\\").pop();\n\t\t\tconst newPath = join(correctDir, fileName!);\n\n\t\t\tif (existsSync(newPath)) continue; // Skip if target exists\n\n\t\t\trenameSync(file, newPath);\n\t\t} catch {\n\t\t\t// Skip files that can't be migrated\n\t\t}\n\t}\n}\n\n/**\n * Migrate commands/ to prompts/ if needed.\n * Works for both regular directories and symlinks.\n */\nfunction migrateCommandsToPrompts(baseDir: string, label: string): boolean {\n\tconst commandsDir = join(baseDir, \"commands\");\n\tconst promptsDir = join(baseDir, \"prompts\");\n\n\tif (existsSync(commandsDir) && !existsSync(promptsDir)) {\n\t\ttry {\n\t\t\trenameSync(commandsDir, promptsDir);\n\t\t\tconsole.log(chalk.green(`Migrated ${label} commands/ → prompts/`));\n\t\t\treturn true;\n\t\t} catch (err) {\n\t\t\tconsole.log(\n\t\t\t\tchalk.yellow(\n\t\t\t\t\t`Warning: Could not migrate ${label} commands/ to prompts/: ${err instanceof Error ? err.message : err}`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\treturn false;\n}\n\nfunction migrateKeybindingsConfigFile(): void {\n\tconst configPath = join(getAgentDir(), \"keybindings.json\");\n\tif (!existsSync(configPath)) return;\n\n\ttry {\n\t\tconst parsed = JSON.parse(readFileSync(configPath, \"utf-8\")) as unknown;\n\t\tif (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n\t\t\treturn;\n\t\t}\n\t\tconst { config, migrated } = migrateKeybindingsConfig(parsed as Record<string, unknown>);\n\t\tif (!migrated) return;\n\t\twriteFileSync(configPath, `${JSON.stringify(config, null, 2)}\\n`, \"utf-8\");\n\t} catch {\n\t\t// Ignore malformed files during migration\n\t}\n}\n\n/**\n * Move fd/rg binaries from tools/ to bin/ if they exist.\n */\nfunction migrateToolsToBin(): void {\n\tconst agentDir = getAgentDir();\n\tconst toolsDir = join(agentDir, \"tools\");\n\tconst binDir = getBinDir();\n\n\tif (!existsSync(toolsDir)) return;\n\n\tconst binaries = [\"fd\", \"rg\", \"fd.exe\", \"rg.exe\"];\n\tlet movedAny = false;\n\n\tfor (const bin of binaries) {\n\t\tconst oldPath = join(toolsDir, bin);\n\t\tconst newPath = join(binDir, bin);\n\n\t\tif (existsSync(oldPath)) {\n\t\t\tif (!existsSync(binDir)) {\n\t\t\t\tmkdirSync(binDir, { recursive: true });\n\t\t\t}\n\t\t\tif (!existsSync(newPath)) {\n\t\t\t\ttry {\n\t\t\t\t\trenameSync(oldPath, newPath);\n\t\t\t\t\tmovedAny = true;\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore errors\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Target exists, just delete the old one\n\t\t\t\ttry {\n\t\t\t\t\trmSync?.(oldPath, { force: true });\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (movedAny) {\n\t\tconsole.log(chalk.green(`Migrated managed binaries tools/ → bin/`));\n\t}\n}\n\n/**\n * Check for deprecated hooks/ and tools/ directories.\n * Note: tools/ may contain fd/rg binaries extracted by pi, so only warn if it has other files.\n */\nfunction checkDeprecatedExtensionDirs(baseDir: string, label: string): string[] {\n\tconst hooksDir = join(baseDir, \"hooks\");\n\tconst toolsDir = join(baseDir, \"tools\");\n\tconst warnings: string[] = [];\n\n\tif (existsSync(hooksDir)) {\n\t\twarnings.push(`${label} hooks/ directory found. Hooks have been renamed to extensions.`);\n\t}\n\n\tif (existsSync(toolsDir)) {\n\t\t// Check if tools/ contains anything other than fd/rg (which are auto-extracted binaries)\n\t\ttry {\n\t\t\tconst entries = readdirSync(toolsDir);\n\t\t\tconst customTools = entries.filter((e) => {\n\t\t\t\tconst lower = e.toLowerCase();\n\t\t\t\treturn (\n\t\t\t\t\tlower !== \"fd\" && lower !== \"rg\" && lower !== \"fd.exe\" && lower !== \"rg.exe\" && !e.startsWith(\".\") // Ignore .DS_Store and other hidden files\n\t\t\t\t);\n\t\t\t});\n\t\t\tif (customTools.length > 0) {\n\t\t\t\twarnings.push(\n\t\t\t\t\t`${label} tools/ directory contains custom tools. Custom tools have been merged into extensions.`,\n\t\t\t\t);\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore read errors\n\t\t}\n\t}\n\n\treturn warnings;\n}\n\n/**\n * Run extension system migrations (commands→prompts) and collect warnings about deprecated directories.\n */\nfunction migrateExtensionSystem(cwd: string): string[] {\n\tconst agentDir = getAgentDir();\n\tconst projectDir = join(cwd, CONFIG_DIR_NAME);\n\n\t// Migrate commands/ to prompts/\n\tmigrateCommandsToPrompts(agentDir, \"Global\");\n\tmigrateCommandsToPrompts(projectDir, \"Project\");\n\n\t// Check for deprecated directories\n\tconst warnings = [\n\t\t...checkDeprecatedExtensionDirs(agentDir, \"Global\"),\n\t\t...checkDeprecatedExtensionDirs(projectDir, \"Project\"),\n\t];\n\n\treturn warnings;\n}\n\n/**\n * Print deprecation warnings and wait for keypress.\n */\nexport async function showDeprecationWarnings(warnings: string[]): Promise<void> {\n\tif (warnings.length === 0) return;\n\n\tfor (const warning of warnings) {\n\t\tconsole.log(chalk.yellow(`Warning: ${warning}`));\n\t}\n\tconsole.log(chalk.yellow(`\\nMove your extensions to the extensions/ directory.`));\n\tconsole.log(chalk.yellow(`Migration guide: ${MIGRATION_GUIDE_URL}`));\n\tconsole.log(chalk.yellow(`Documentation: ${EXTENSIONS_DOC_URL}`));\n\tconsole.log(chalk.dim(`\\nPress any key to continue...`));\n\n\tawait new Promise<void>((resolve) => {\n\t\tprocess.stdin.setRawMode?.(true);\n\t\tprocess.stdin.resume();\n\t\tprocess.stdin.once(\"data\", () => {\n\t\t\tprocess.stdin.setRawMode?.(false);\n\t\t\tprocess.stdin.pause();\n\t\t\tresolve();\n\t\t});\n\t});\n\tconsole.log();\n}\n\n/**\n * Run all migrations. Called once on startup.\n *\n * @returns Object with migration results and deprecation warnings\n */\nexport function runMigrations(cwd: string): {\n\tmigratedAuthProviders: string[];\n\tdeprecationWarnings: string[];\n} {\n\tconst migratedAuthProviders = migrateAuthToAuthJson();\n\tmigrateSessionsFromAgentRoot();\n\tmigrateToolsToBin();\n\tmigrateKeybindingsConfigFile();\n\tconst deprecationWarnings = migrateExtensionSystem(cwd);\n\treturn { migratedAuthProviders, deprecationWarnings };\n}\n"]}
1
+ {"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../src/migrations.ts"],"names":[],"mappings":"AAAA;;GAEG;AAaH;;;;GAIG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,EAAE,CAoDhD;AAED;;;;;;;;GAQG;AACH,wBAAgB,4BAA4B,IAAI,IAAI,CA+CnD;AA+ID;;GAEG;AACH,wBAAsB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAqB/E;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG;IAC3C,qBAAqB,EAAE,MAAM,EAAE,CAAC;IAChC,mBAAmB,EAAE,MAAM,EAAE,CAAC;CAC9B,CAOA","sourcesContent":["/**\n * One-time migrations that run on startup.\n */\n\nimport chalk from \"chalk\";\nimport { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync } from \"fs\";\nimport { dirname, join } from \"path\";\nimport { CONFIG_DIR_NAME, getAgentDir, getBinDir } from \"./config.ts\";\nimport { migrateKeybindingsConfig } from \"./core/keybindings.ts\";\nimport { stripBom } from \"./utils/text.ts\";\n\nconst MIGRATION_GUIDE_URL =\n\t\"https://github.com/Fchery87/apex-code/blob/main/packages/coding-agent/CHANGELOG.md#extensions-migration\";\nconst EXTENSIONS_DOC_URL = \"https://github.com/Fchery87/apex-code/blob/main/packages/coding-agent/docs/extensions.md\";\n\n/**\n * Migrate legacy oauth.json and settings.json apiKeys to auth.json.\n *\n * @returns Array of provider names that were migrated\n */\nexport function migrateAuthToAuthJson(): string[] {\n\tconst agentDir = getAgentDir();\n\tconst authPath = join(agentDir, \"auth.json\");\n\tconst oauthPath = join(agentDir, \"oauth.json\");\n\tconst settingsPath = join(agentDir, \"settings.json\");\n\n\t// Skip if auth.json already exists\n\tif (existsSync(authPath)) return [];\n\n\tconst migrated: Record<string, unknown> = {};\n\tconst providers: string[] = [];\n\n\t// Migrate oauth.json\n\tif (existsSync(oauthPath)) {\n\t\ttry {\n\t\t\tconst oauth = JSON.parse(stripBom(readFileSync(oauthPath, \"utf-8\")));\n\t\t\tfor (const [provider, cred] of Object.entries(oauth)) {\n\t\t\t\tmigrated[provider] = { type: \"oauth\", ...(cred as object) };\n\t\t\t\tproviders.push(provider);\n\t\t\t}\n\t\t\trenameSync(oauthPath, `${oauthPath}.migrated`);\n\t\t} catch {\n\t\t\t// Skip on error\n\t\t}\n\t}\n\n\t// Migrate settings.json apiKeys\n\tif (existsSync(settingsPath)) {\n\t\ttry {\n\t\t\tconst content = readFileSync(settingsPath, \"utf-8\");\n\t\t\tconst settings = JSON.parse(stripBom(content));\n\t\t\tif (settings.apiKeys && typeof settings.apiKeys === \"object\") {\n\t\t\t\tfor (const [provider, key] of Object.entries(settings.apiKeys)) {\n\t\t\t\t\tif (!migrated[provider] && typeof key === \"string\") {\n\t\t\t\t\t\tmigrated[provider] = { type: \"api_key\", key };\n\t\t\t\t\t\tproviders.push(provider);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdelete settings.apiKeys;\n\t\t\t\twriteFileSync(settingsPath, JSON.stringify(settings, null, 2));\n\t\t\t}\n\t\t} catch {\n\t\t\t// Skip on error\n\t\t}\n\t}\n\n\tif (Object.keys(migrated).length > 0) {\n\t\tmkdirSync(dirname(authPath), { recursive: true });\n\t\twriteFileSync(authPath, JSON.stringify(migrated, null, 2), { mode: 0o600 });\n\t}\n\n\treturn providers;\n}\n\n/**\n * Migrate sessions from ~/.pi/agent/*.jsonl to proper session directories.\n *\n * Bug in v0.30.0: Sessions were saved to ~/.pi/agent/ instead of\n * ~/.pi/agent/sessions/<encoded-cwd>/. This migration moves them\n * to the correct location based on the cwd in their session header.\n *\n * See: https://github.com/earendil-works/pi-mono/issues/320\n */\nexport function migrateSessionsFromAgentRoot(): void {\n\tconst agentDir = getAgentDir();\n\n\t// Find all .jsonl files directly in agentDir (not in subdirectories)\n\tlet files: string[];\n\ttry {\n\t\tfiles = readdirSync(agentDir)\n\t\t\t.filter((f) => f.endsWith(\".jsonl\"))\n\t\t\t.map((f) => join(agentDir, f));\n\t} catch {\n\t\treturn;\n\t}\n\n\tif (files.length === 0) return;\n\n\tfor (const file of files) {\n\t\ttry {\n\t\t\t// Read first line to get session header\n\t\t\tconst content = readFileSync(file, \"utf8\");\n\t\t\tconst firstLine = content.split(\"\\n\")[0];\n\t\t\tif (!firstLine?.trim()) continue;\n\n\t\t\tconst header = JSON.parse(firstLine);\n\t\t\tif (header.type !== \"session\" || !header.cwd) continue;\n\n\t\t\tconst cwd: string = header.cwd;\n\n\t\t\t// Compute the correct session directory (same encoding as session-manager.ts)\n\t\t\tconst safePath = `--${cwd.replace(/^[/\\\\]/, \"\").replace(/[/\\\\:]/g, \"-\")}--`;\n\t\t\tconst correctDir = join(agentDir, \"sessions\", safePath);\n\n\t\t\t// Create directory if needed\n\t\t\tif (!existsSync(correctDir)) {\n\t\t\t\tmkdirSync(correctDir, { recursive: true });\n\t\t\t}\n\n\t\t\t// Move the file\n\t\t\tconst fileName = file.split(\"/\").pop() || file.split(\"\\\\\").pop();\n\t\t\tconst newPath = join(correctDir, fileName!);\n\n\t\t\tif (existsSync(newPath)) continue; // Skip if target exists\n\n\t\t\trenameSync(file, newPath);\n\t\t} catch {\n\t\t\t// Skip files that can't be migrated\n\t\t}\n\t}\n}\n\n/**\n * Migrate commands/ to prompts/ if needed.\n * Works for both regular directories and symlinks.\n */\nfunction migrateCommandsToPrompts(baseDir: string, label: string): boolean {\n\tconst commandsDir = join(baseDir, \"commands\");\n\tconst promptsDir = join(baseDir, \"prompts\");\n\n\tif (existsSync(commandsDir) && !existsSync(promptsDir)) {\n\t\ttry {\n\t\t\trenameSync(commandsDir, promptsDir);\n\t\t\tconsole.log(chalk.green(`Migrated ${label} commands/ → prompts/`));\n\t\t\treturn true;\n\t\t} catch (err) {\n\t\t\tconsole.log(\n\t\t\t\tchalk.yellow(\n\t\t\t\t\t`Warning: Could not migrate ${label} commands/ to prompts/: ${err instanceof Error ? err.message : err}`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\treturn false;\n}\n\nfunction migrateKeybindingsConfigFile(): void {\n\tconst configPath = join(getAgentDir(), \"keybindings.json\");\n\tif (!existsSync(configPath)) return;\n\n\ttry {\n\t\tconst parsed = JSON.parse(stripBom(readFileSync(configPath, \"utf-8\"))) as unknown;\n\t\tif (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n\t\t\treturn;\n\t\t}\n\t\tconst { config, migrated } = migrateKeybindingsConfig(parsed as Record<string, unknown>);\n\t\tif (!migrated) return;\n\t\twriteFileSync(configPath, `${JSON.stringify(config, null, 2)}\\n`, \"utf-8\");\n\t} catch {\n\t\t// Ignore malformed files during migration\n\t}\n}\n\n/**\n * Move fd/rg binaries from tools/ to bin/ if they exist.\n */\nfunction migrateToolsToBin(): void {\n\tconst agentDir = getAgentDir();\n\tconst toolsDir = join(agentDir, \"tools\");\n\tconst binDir = getBinDir();\n\n\tif (!existsSync(toolsDir)) return;\n\n\tconst binaries = [\"fd\", \"rg\", \"fd.exe\", \"rg.exe\"];\n\tlet movedAny = false;\n\n\tfor (const bin of binaries) {\n\t\tconst oldPath = join(toolsDir, bin);\n\t\tconst newPath = join(binDir, bin);\n\n\t\tif (existsSync(oldPath)) {\n\t\t\tif (!existsSync(binDir)) {\n\t\t\t\tmkdirSync(binDir, { recursive: true });\n\t\t\t}\n\t\t\tif (!existsSync(newPath)) {\n\t\t\t\ttry {\n\t\t\t\t\trenameSync(oldPath, newPath);\n\t\t\t\t\tmovedAny = true;\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore errors\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Target exists, just delete the old one\n\t\t\t\ttry {\n\t\t\t\t\trmSync?.(oldPath, { force: true });\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (movedAny) {\n\t\tconsole.log(chalk.green(`Migrated managed binaries tools/ → bin/`));\n\t}\n}\n\n/**\n * Check for deprecated hooks/ and tools/ directories.\n * Note: tools/ may contain fd/rg binaries extracted by pi, so only warn if it has other files.\n */\nfunction checkDeprecatedExtensionDirs(baseDir: string, label: string): string[] {\n\tconst hooksDir = join(baseDir, \"hooks\");\n\tconst toolsDir = join(baseDir, \"tools\");\n\tconst warnings: string[] = [];\n\n\tif (existsSync(hooksDir)) {\n\t\twarnings.push(`${label} hooks/ directory found. Hooks have been renamed to extensions.`);\n\t}\n\n\tif (existsSync(toolsDir)) {\n\t\t// Check if tools/ contains anything other than fd/rg (which are auto-extracted binaries)\n\t\ttry {\n\t\t\tconst entries = readdirSync(toolsDir);\n\t\t\tconst customTools = entries.filter((e) => {\n\t\t\t\tconst lower = e.toLowerCase();\n\t\t\t\treturn (\n\t\t\t\t\tlower !== \"fd\" && lower !== \"rg\" && lower !== \"fd.exe\" && lower !== \"rg.exe\" && !e.startsWith(\".\") // Ignore .DS_Store and other hidden files\n\t\t\t\t);\n\t\t\t});\n\t\t\tif (customTools.length > 0) {\n\t\t\t\twarnings.push(\n\t\t\t\t\t`${label} tools/ directory contains custom tools. Custom tools have been merged into extensions.`,\n\t\t\t\t);\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore read errors\n\t\t}\n\t}\n\n\treturn warnings;\n}\n\n/**\n * Run extension system migrations (commands→prompts) and collect warnings about deprecated directories.\n */\nfunction migrateExtensionSystem(cwd: string): string[] {\n\tconst agentDir = getAgentDir();\n\tconst projectDir = join(cwd, CONFIG_DIR_NAME);\n\n\t// Migrate commands/ to prompts/\n\tmigrateCommandsToPrompts(agentDir, \"Global\");\n\tmigrateCommandsToPrompts(projectDir, \"Project\");\n\n\t// Check for deprecated directories\n\tconst warnings = [\n\t\t...checkDeprecatedExtensionDirs(agentDir, \"Global\"),\n\t\t...checkDeprecatedExtensionDirs(projectDir, \"Project\"),\n\t];\n\n\treturn warnings;\n}\n\n/**\n * Print deprecation warnings and wait for keypress.\n */\nexport async function showDeprecationWarnings(warnings: string[]): Promise<void> {\n\tif (warnings.length === 0) return;\n\n\tfor (const warning of warnings) {\n\t\tconsole.log(chalk.yellow(`Warning: ${warning}`));\n\t}\n\tconsole.log(chalk.yellow(`\\nMove your extensions to the extensions/ directory.`));\n\tconsole.log(chalk.yellow(`Migration guide: ${MIGRATION_GUIDE_URL}`));\n\tconsole.log(chalk.yellow(`Documentation: ${EXTENSIONS_DOC_URL}`));\n\tconsole.log(chalk.dim(`\\nPress any key to continue...`));\n\n\tawait new Promise<void>((resolve) => {\n\t\tprocess.stdin.setRawMode?.(true);\n\t\tprocess.stdin.resume();\n\t\tprocess.stdin.once(\"data\", () => {\n\t\t\tprocess.stdin.setRawMode?.(false);\n\t\t\tprocess.stdin.pause();\n\t\t\tresolve();\n\t\t});\n\t});\n\tconsole.log();\n}\n\n/**\n * Run all migrations. Called once on startup.\n *\n * @returns Object with migration results and deprecation warnings\n */\nexport function runMigrations(cwd: string): {\n\tmigratedAuthProviders: string[];\n\tdeprecationWarnings: string[];\n} {\n\tconst migratedAuthProviders = migrateAuthToAuthJson();\n\tmigrateSessionsFromAgentRoot();\n\tmigrateToolsToBin();\n\tmigrateKeybindingsConfigFile();\n\tconst deprecationWarnings = migrateExtensionSystem(cwd);\n\treturn { migratedAuthProviders, deprecationWarnings };\n}\n"]}
@@ -6,8 +6,9 @@ import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, w
6
6
  import { dirname, join } from "path";
7
7
  import { CONFIG_DIR_NAME, getAgentDir, getBinDir } from "./config.js";
8
8
  import { migrateKeybindingsConfig } from "./core/keybindings.js";
9
- const MIGRATION_GUIDE_URL = "https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/CHANGELOG.md#extensions-migration";
10
- const EXTENSIONS_DOC_URL = "https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/docs/extensions.md";
9
+ import { stripBom } from "./utils/text.js";
10
+ const MIGRATION_GUIDE_URL = "https://github.com/Fchery87/apex-code/blob/main/packages/coding-agent/CHANGELOG.md#extensions-migration";
11
+ const EXTENSIONS_DOC_URL = "https://github.com/Fchery87/apex-code/blob/main/packages/coding-agent/docs/extensions.md";
11
12
  /**
12
13
  * Migrate legacy oauth.json and settings.json apiKeys to auth.json.
13
14
  *
@@ -26,7 +27,7 @@ export function migrateAuthToAuthJson() {
26
27
  // Migrate oauth.json
27
28
  if (existsSync(oauthPath)) {
28
29
  try {
29
- const oauth = JSON.parse(readFileSync(oauthPath, "utf-8"));
30
+ const oauth = JSON.parse(stripBom(readFileSync(oauthPath, "utf-8")));
30
31
  for (const [provider, cred] of Object.entries(oauth)) {
31
32
  migrated[provider] = { type: "oauth", ...cred };
32
33
  providers.push(provider);
@@ -41,7 +42,7 @@ export function migrateAuthToAuthJson() {
41
42
  if (existsSync(settingsPath)) {
42
43
  try {
43
44
  const content = readFileSync(settingsPath, "utf-8");
44
- const settings = JSON.parse(content);
45
+ const settings = JSON.parse(stripBom(content));
45
46
  if (settings.apiKeys && typeof settings.apiKeys === "object") {
46
47
  for (const [provider, key] of Object.entries(settings.apiKeys)) {
47
48
  if (!migrated[provider] && typeof key === "string") {
@@ -140,7 +141,7 @@ function migrateKeybindingsConfigFile() {
140
141
  if (!existsSync(configPath))
141
142
  return;
142
143
  try {
143
- const parsed = JSON.parse(readFileSync(configPath, "utf-8"));
144
+ const parsed = JSON.parse(stripBom(readFileSync(configPath, "utf-8")));
144
145
  if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
145
146
  return;
146
147
  }
@@ -1 +1 @@
1
- {"version":3,"file":"migrations.js","sourceRoot":"","sources":["../src/migrations.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * One-time migrations that run on startup.\n */\n\nimport chalk from \"chalk\";\nimport { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync } from \"fs\";\nimport { dirname, join } from \"path\";\nimport { CONFIG_DIR_NAME, getAgentDir, getBinDir } from \"./config.ts\";\nimport { migrateKeybindingsConfig } from \"./core/keybindings.ts\";\n\nconst MIGRATION_GUIDE_URL =\n\t\"https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/CHANGELOG.md#extensions-migration\";\nconst EXTENSIONS_DOC_URL =\n\t\"https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/docs/extensions.md\";\n\n/**\n * Migrate legacy oauth.json and settings.json apiKeys to auth.json.\n *\n * @returns Array of provider names that were migrated\n */\nexport function migrateAuthToAuthJson(): string[] {\n\tconst agentDir = getAgentDir();\n\tconst authPath = join(agentDir, \"auth.json\");\n\tconst oauthPath = join(agentDir, \"oauth.json\");\n\tconst settingsPath = join(agentDir, \"settings.json\");\n\n\t// Skip if auth.json already exists\n\tif (existsSync(authPath)) return [];\n\n\tconst migrated: Record<string, unknown> = {};\n\tconst providers: string[] = [];\n\n\t// Migrate oauth.json\n\tif (existsSync(oauthPath)) {\n\t\ttry {\n\t\t\tconst oauth = JSON.parse(readFileSync(oauthPath, \"utf-8\"));\n\t\t\tfor (const [provider, cred] of Object.entries(oauth)) {\n\t\t\t\tmigrated[provider] = { type: \"oauth\", ...(cred as object) };\n\t\t\t\tproviders.push(provider);\n\t\t\t}\n\t\t\trenameSync(oauthPath, `${oauthPath}.migrated`);\n\t\t} catch {\n\t\t\t// Skip on error\n\t\t}\n\t}\n\n\t// Migrate settings.json apiKeys\n\tif (existsSync(settingsPath)) {\n\t\ttry {\n\t\t\tconst content = readFileSync(settingsPath, \"utf-8\");\n\t\t\tconst settings = JSON.parse(content);\n\t\t\tif (settings.apiKeys && typeof settings.apiKeys === \"object\") {\n\t\t\t\tfor (const [provider, key] of Object.entries(settings.apiKeys)) {\n\t\t\t\t\tif (!migrated[provider] && typeof key === \"string\") {\n\t\t\t\t\t\tmigrated[provider] = { type: \"api_key\", key };\n\t\t\t\t\t\tproviders.push(provider);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdelete settings.apiKeys;\n\t\t\t\twriteFileSync(settingsPath, JSON.stringify(settings, null, 2));\n\t\t\t}\n\t\t} catch {\n\t\t\t// Skip on error\n\t\t}\n\t}\n\n\tif (Object.keys(migrated).length > 0) {\n\t\tmkdirSync(dirname(authPath), { recursive: true });\n\t\twriteFileSync(authPath, JSON.stringify(migrated, null, 2), { mode: 0o600 });\n\t}\n\n\treturn providers;\n}\n\n/**\n * Migrate sessions from ~/.pi/agent/*.jsonl to proper session directories.\n *\n * Bug in v0.30.0: Sessions were saved to ~/.pi/agent/ instead of\n * ~/.pi/agent/sessions/<encoded-cwd>/. This migration moves them\n * to the correct location based on the cwd in their session header.\n *\n * See: https://github.com/earendil-works/pi-mono/issues/320\n */\nexport function migrateSessionsFromAgentRoot(): void {\n\tconst agentDir = getAgentDir();\n\n\t// Find all .jsonl files directly in agentDir (not in subdirectories)\n\tlet files: string[];\n\ttry {\n\t\tfiles = readdirSync(agentDir)\n\t\t\t.filter((f) => f.endsWith(\".jsonl\"))\n\t\t\t.map((f) => join(agentDir, f));\n\t} catch {\n\t\treturn;\n\t}\n\n\tif (files.length === 0) return;\n\n\tfor (const file of files) {\n\t\ttry {\n\t\t\t// Read first line to get session header\n\t\t\tconst content = readFileSync(file, \"utf8\");\n\t\t\tconst firstLine = content.split(\"\\n\")[0];\n\t\t\tif (!firstLine?.trim()) continue;\n\n\t\t\tconst header = JSON.parse(firstLine);\n\t\t\tif (header.type !== \"session\" || !header.cwd) continue;\n\n\t\t\tconst cwd: string = header.cwd;\n\n\t\t\t// Compute the correct session directory (same encoding as session-manager.ts)\n\t\t\tconst safePath = `--${cwd.replace(/^[/\\\\]/, \"\").replace(/[/\\\\:]/g, \"-\")}--`;\n\t\t\tconst correctDir = join(agentDir, \"sessions\", safePath);\n\n\t\t\t// Create directory if needed\n\t\t\tif (!existsSync(correctDir)) {\n\t\t\t\tmkdirSync(correctDir, { recursive: true });\n\t\t\t}\n\n\t\t\t// Move the file\n\t\t\tconst fileName = file.split(\"/\").pop() || file.split(\"\\\\\").pop();\n\t\t\tconst newPath = join(correctDir, fileName!);\n\n\t\t\tif (existsSync(newPath)) continue; // Skip if target exists\n\n\t\t\trenameSync(file, newPath);\n\t\t} catch {\n\t\t\t// Skip files that can't be migrated\n\t\t}\n\t}\n}\n\n/**\n * Migrate commands/ to prompts/ if needed.\n * Works for both regular directories and symlinks.\n */\nfunction migrateCommandsToPrompts(baseDir: string, label: string): boolean {\n\tconst commandsDir = join(baseDir, \"commands\");\n\tconst promptsDir = join(baseDir, \"prompts\");\n\n\tif (existsSync(commandsDir) && !existsSync(promptsDir)) {\n\t\ttry {\n\t\t\trenameSync(commandsDir, promptsDir);\n\t\t\tconsole.log(chalk.green(`Migrated ${label} commands/ → prompts/`));\n\t\t\treturn true;\n\t\t} catch (err) {\n\t\t\tconsole.log(\n\t\t\t\tchalk.yellow(\n\t\t\t\t\t`Warning: Could not migrate ${label} commands/ to prompts/: ${err instanceof Error ? err.message : err}`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\treturn false;\n}\n\nfunction migrateKeybindingsConfigFile(): void {\n\tconst configPath = join(getAgentDir(), \"keybindings.json\");\n\tif (!existsSync(configPath)) return;\n\n\ttry {\n\t\tconst parsed = JSON.parse(readFileSync(configPath, \"utf-8\")) as unknown;\n\t\tif (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n\t\t\treturn;\n\t\t}\n\t\tconst { config, migrated } = migrateKeybindingsConfig(parsed as Record<string, unknown>);\n\t\tif (!migrated) return;\n\t\twriteFileSync(configPath, `${JSON.stringify(config, null, 2)}\\n`, \"utf-8\");\n\t} catch {\n\t\t// Ignore malformed files during migration\n\t}\n}\n\n/**\n * Move fd/rg binaries from tools/ to bin/ if they exist.\n */\nfunction migrateToolsToBin(): void {\n\tconst agentDir = getAgentDir();\n\tconst toolsDir = join(agentDir, \"tools\");\n\tconst binDir = getBinDir();\n\n\tif (!existsSync(toolsDir)) return;\n\n\tconst binaries = [\"fd\", \"rg\", \"fd.exe\", \"rg.exe\"];\n\tlet movedAny = false;\n\n\tfor (const bin of binaries) {\n\t\tconst oldPath = join(toolsDir, bin);\n\t\tconst newPath = join(binDir, bin);\n\n\t\tif (existsSync(oldPath)) {\n\t\t\tif (!existsSync(binDir)) {\n\t\t\t\tmkdirSync(binDir, { recursive: true });\n\t\t\t}\n\t\t\tif (!existsSync(newPath)) {\n\t\t\t\ttry {\n\t\t\t\t\trenameSync(oldPath, newPath);\n\t\t\t\t\tmovedAny = true;\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore errors\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Target exists, just delete the old one\n\t\t\t\ttry {\n\t\t\t\t\trmSync?.(oldPath, { force: true });\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (movedAny) {\n\t\tconsole.log(chalk.green(`Migrated managed binaries tools/ → bin/`));\n\t}\n}\n\n/**\n * Check for deprecated hooks/ and tools/ directories.\n * Note: tools/ may contain fd/rg binaries extracted by pi, so only warn if it has other files.\n */\nfunction checkDeprecatedExtensionDirs(baseDir: string, label: string): string[] {\n\tconst hooksDir = join(baseDir, \"hooks\");\n\tconst toolsDir = join(baseDir, \"tools\");\n\tconst warnings: string[] = [];\n\n\tif (existsSync(hooksDir)) {\n\t\twarnings.push(`${label} hooks/ directory found. Hooks have been renamed to extensions.`);\n\t}\n\n\tif (existsSync(toolsDir)) {\n\t\t// Check if tools/ contains anything other than fd/rg (which are auto-extracted binaries)\n\t\ttry {\n\t\t\tconst entries = readdirSync(toolsDir);\n\t\t\tconst customTools = entries.filter((e) => {\n\t\t\t\tconst lower = e.toLowerCase();\n\t\t\t\treturn (\n\t\t\t\t\tlower !== \"fd\" && lower !== \"rg\" && lower !== \"fd.exe\" && lower !== \"rg.exe\" && !e.startsWith(\".\") // Ignore .DS_Store and other hidden files\n\t\t\t\t);\n\t\t\t});\n\t\t\tif (customTools.length > 0) {\n\t\t\t\twarnings.push(\n\t\t\t\t\t`${label} tools/ directory contains custom tools. Custom tools have been merged into extensions.`,\n\t\t\t\t);\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore read errors\n\t\t}\n\t}\n\n\treturn warnings;\n}\n\n/**\n * Run extension system migrations (commands→prompts) and collect warnings about deprecated directories.\n */\nfunction migrateExtensionSystem(cwd: string): string[] {\n\tconst agentDir = getAgentDir();\n\tconst projectDir = join(cwd, CONFIG_DIR_NAME);\n\n\t// Migrate commands/ to prompts/\n\tmigrateCommandsToPrompts(agentDir, \"Global\");\n\tmigrateCommandsToPrompts(projectDir, \"Project\");\n\n\t// Check for deprecated directories\n\tconst warnings = [\n\t\t...checkDeprecatedExtensionDirs(agentDir, \"Global\"),\n\t\t...checkDeprecatedExtensionDirs(projectDir, \"Project\"),\n\t];\n\n\treturn warnings;\n}\n\n/**\n * Print deprecation warnings and wait for keypress.\n */\nexport async function showDeprecationWarnings(warnings: string[]): Promise<void> {\n\tif (warnings.length === 0) return;\n\n\tfor (const warning of warnings) {\n\t\tconsole.log(chalk.yellow(`Warning: ${warning}`));\n\t}\n\tconsole.log(chalk.yellow(`\\nMove your extensions to the extensions/ directory.`));\n\tconsole.log(chalk.yellow(`Migration guide: ${MIGRATION_GUIDE_URL}`));\n\tconsole.log(chalk.yellow(`Documentation: ${EXTENSIONS_DOC_URL}`));\n\tconsole.log(chalk.dim(`\\nPress any key to continue...`));\n\n\tawait new Promise<void>((resolve) => {\n\t\tprocess.stdin.setRawMode?.(true);\n\t\tprocess.stdin.resume();\n\t\tprocess.stdin.once(\"data\", () => {\n\t\t\tprocess.stdin.setRawMode?.(false);\n\t\t\tprocess.stdin.pause();\n\t\t\tresolve();\n\t\t});\n\t});\n\tconsole.log();\n}\n\n/**\n * Run all migrations. Called once on startup.\n *\n * @returns Object with migration results and deprecation warnings\n */\nexport function runMigrations(cwd: string): {\n\tmigratedAuthProviders: string[];\n\tdeprecationWarnings: string[];\n} {\n\tconst migratedAuthProviders = migrateAuthToAuthJson();\n\tmigrateSessionsFromAgentRoot();\n\tmigrateToolsToBin();\n\tmigrateKeybindingsConfigFile();\n\tconst deprecationWarnings = migrateExtensionSystem(cwd);\n\treturn { migratedAuthProviders, deprecationWarnings };\n}\n"]}
1
+ {"version":3,"file":"migrations.js","sourceRoot":"","sources":["../src/migrations.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * One-time migrations that run on startup.\n */\n\nimport chalk from \"chalk\";\nimport { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync } from \"fs\";\nimport { dirname, join } from \"path\";\nimport { CONFIG_DIR_NAME, getAgentDir, getBinDir } from \"./config.ts\";\nimport { migrateKeybindingsConfig } from \"./core/keybindings.ts\";\nimport { stripBom } from \"./utils/text.ts\";\n\nconst MIGRATION_GUIDE_URL =\n\t\"https://github.com/Fchery87/apex-code/blob/main/packages/coding-agent/CHANGELOG.md#extensions-migration\";\nconst EXTENSIONS_DOC_URL = \"https://github.com/Fchery87/apex-code/blob/main/packages/coding-agent/docs/extensions.md\";\n\n/**\n * Migrate legacy oauth.json and settings.json apiKeys to auth.json.\n *\n * @returns Array of provider names that were migrated\n */\nexport function migrateAuthToAuthJson(): string[] {\n\tconst agentDir = getAgentDir();\n\tconst authPath = join(agentDir, \"auth.json\");\n\tconst oauthPath = join(agentDir, \"oauth.json\");\n\tconst settingsPath = join(agentDir, \"settings.json\");\n\n\t// Skip if auth.json already exists\n\tif (existsSync(authPath)) return [];\n\n\tconst migrated: Record<string, unknown> = {};\n\tconst providers: string[] = [];\n\n\t// Migrate oauth.json\n\tif (existsSync(oauthPath)) {\n\t\ttry {\n\t\t\tconst oauth = JSON.parse(stripBom(readFileSync(oauthPath, \"utf-8\")));\n\t\t\tfor (const [provider, cred] of Object.entries(oauth)) {\n\t\t\t\tmigrated[provider] = { type: \"oauth\", ...(cred as object) };\n\t\t\t\tproviders.push(provider);\n\t\t\t}\n\t\t\trenameSync(oauthPath, `${oauthPath}.migrated`);\n\t\t} catch {\n\t\t\t// Skip on error\n\t\t}\n\t}\n\n\t// Migrate settings.json apiKeys\n\tif (existsSync(settingsPath)) {\n\t\ttry {\n\t\t\tconst content = readFileSync(settingsPath, \"utf-8\");\n\t\t\tconst settings = JSON.parse(stripBom(content));\n\t\t\tif (settings.apiKeys && typeof settings.apiKeys === \"object\") {\n\t\t\t\tfor (const [provider, key] of Object.entries(settings.apiKeys)) {\n\t\t\t\t\tif (!migrated[provider] && typeof key === \"string\") {\n\t\t\t\t\t\tmigrated[provider] = { type: \"api_key\", key };\n\t\t\t\t\t\tproviders.push(provider);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdelete settings.apiKeys;\n\t\t\t\twriteFileSync(settingsPath, JSON.stringify(settings, null, 2));\n\t\t\t}\n\t\t} catch {\n\t\t\t// Skip on error\n\t\t}\n\t}\n\n\tif (Object.keys(migrated).length > 0) {\n\t\tmkdirSync(dirname(authPath), { recursive: true });\n\t\twriteFileSync(authPath, JSON.stringify(migrated, null, 2), { mode: 0o600 });\n\t}\n\n\treturn providers;\n}\n\n/**\n * Migrate sessions from ~/.pi/agent/*.jsonl to proper session directories.\n *\n * Bug in v0.30.0: Sessions were saved to ~/.pi/agent/ instead of\n * ~/.pi/agent/sessions/<encoded-cwd>/. This migration moves them\n * to the correct location based on the cwd in their session header.\n *\n * See: https://github.com/earendil-works/pi-mono/issues/320\n */\nexport function migrateSessionsFromAgentRoot(): void {\n\tconst agentDir = getAgentDir();\n\n\t// Find all .jsonl files directly in agentDir (not in subdirectories)\n\tlet files: string[];\n\ttry {\n\t\tfiles = readdirSync(agentDir)\n\t\t\t.filter((f) => f.endsWith(\".jsonl\"))\n\t\t\t.map((f) => join(agentDir, f));\n\t} catch {\n\t\treturn;\n\t}\n\n\tif (files.length === 0) return;\n\n\tfor (const file of files) {\n\t\ttry {\n\t\t\t// Read first line to get session header\n\t\t\tconst content = readFileSync(file, \"utf8\");\n\t\t\tconst firstLine = content.split(\"\\n\")[0];\n\t\t\tif (!firstLine?.trim()) continue;\n\n\t\t\tconst header = JSON.parse(firstLine);\n\t\t\tif (header.type !== \"session\" || !header.cwd) continue;\n\n\t\t\tconst cwd: string = header.cwd;\n\n\t\t\t// Compute the correct session directory (same encoding as session-manager.ts)\n\t\t\tconst safePath = `--${cwd.replace(/^[/\\\\]/, \"\").replace(/[/\\\\:]/g, \"-\")}--`;\n\t\t\tconst correctDir = join(agentDir, \"sessions\", safePath);\n\n\t\t\t// Create directory if needed\n\t\t\tif (!existsSync(correctDir)) {\n\t\t\t\tmkdirSync(correctDir, { recursive: true });\n\t\t\t}\n\n\t\t\t// Move the file\n\t\t\tconst fileName = file.split(\"/\").pop() || file.split(\"\\\\\").pop();\n\t\t\tconst newPath = join(correctDir, fileName!);\n\n\t\t\tif (existsSync(newPath)) continue; // Skip if target exists\n\n\t\t\trenameSync(file, newPath);\n\t\t} catch {\n\t\t\t// Skip files that can't be migrated\n\t\t}\n\t}\n}\n\n/**\n * Migrate commands/ to prompts/ if needed.\n * Works for both regular directories and symlinks.\n */\nfunction migrateCommandsToPrompts(baseDir: string, label: string): boolean {\n\tconst commandsDir = join(baseDir, \"commands\");\n\tconst promptsDir = join(baseDir, \"prompts\");\n\n\tif (existsSync(commandsDir) && !existsSync(promptsDir)) {\n\t\ttry {\n\t\t\trenameSync(commandsDir, promptsDir);\n\t\t\tconsole.log(chalk.green(`Migrated ${label} commands/ → prompts/`));\n\t\t\treturn true;\n\t\t} catch (err) {\n\t\t\tconsole.log(\n\t\t\t\tchalk.yellow(\n\t\t\t\t\t`Warning: Could not migrate ${label} commands/ to prompts/: ${err instanceof Error ? err.message : err}`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\treturn false;\n}\n\nfunction migrateKeybindingsConfigFile(): void {\n\tconst configPath = join(getAgentDir(), \"keybindings.json\");\n\tif (!existsSync(configPath)) return;\n\n\ttry {\n\t\tconst parsed = JSON.parse(stripBom(readFileSync(configPath, \"utf-8\"))) as unknown;\n\t\tif (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n\t\t\treturn;\n\t\t}\n\t\tconst { config, migrated } = migrateKeybindingsConfig(parsed as Record<string, unknown>);\n\t\tif (!migrated) return;\n\t\twriteFileSync(configPath, `${JSON.stringify(config, null, 2)}\\n`, \"utf-8\");\n\t} catch {\n\t\t// Ignore malformed files during migration\n\t}\n}\n\n/**\n * Move fd/rg binaries from tools/ to bin/ if they exist.\n */\nfunction migrateToolsToBin(): void {\n\tconst agentDir = getAgentDir();\n\tconst toolsDir = join(agentDir, \"tools\");\n\tconst binDir = getBinDir();\n\n\tif (!existsSync(toolsDir)) return;\n\n\tconst binaries = [\"fd\", \"rg\", \"fd.exe\", \"rg.exe\"];\n\tlet movedAny = false;\n\n\tfor (const bin of binaries) {\n\t\tconst oldPath = join(toolsDir, bin);\n\t\tconst newPath = join(binDir, bin);\n\n\t\tif (existsSync(oldPath)) {\n\t\t\tif (!existsSync(binDir)) {\n\t\t\t\tmkdirSync(binDir, { recursive: true });\n\t\t\t}\n\t\t\tif (!existsSync(newPath)) {\n\t\t\t\ttry {\n\t\t\t\t\trenameSync(oldPath, newPath);\n\t\t\t\t\tmovedAny = true;\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore errors\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Target exists, just delete the old one\n\t\t\t\ttry {\n\t\t\t\t\trmSync?.(oldPath, { force: true });\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (movedAny) {\n\t\tconsole.log(chalk.green(`Migrated managed binaries tools/ → bin/`));\n\t}\n}\n\n/**\n * Check for deprecated hooks/ and tools/ directories.\n * Note: tools/ may contain fd/rg binaries extracted by pi, so only warn if it has other files.\n */\nfunction checkDeprecatedExtensionDirs(baseDir: string, label: string): string[] {\n\tconst hooksDir = join(baseDir, \"hooks\");\n\tconst toolsDir = join(baseDir, \"tools\");\n\tconst warnings: string[] = [];\n\n\tif (existsSync(hooksDir)) {\n\t\twarnings.push(`${label} hooks/ directory found. Hooks have been renamed to extensions.`);\n\t}\n\n\tif (existsSync(toolsDir)) {\n\t\t// Check if tools/ contains anything other than fd/rg (which are auto-extracted binaries)\n\t\ttry {\n\t\t\tconst entries = readdirSync(toolsDir);\n\t\t\tconst customTools = entries.filter((e) => {\n\t\t\t\tconst lower = e.toLowerCase();\n\t\t\t\treturn (\n\t\t\t\t\tlower !== \"fd\" && lower !== \"rg\" && lower !== \"fd.exe\" && lower !== \"rg.exe\" && !e.startsWith(\".\") // Ignore .DS_Store and other hidden files\n\t\t\t\t);\n\t\t\t});\n\t\t\tif (customTools.length > 0) {\n\t\t\t\twarnings.push(\n\t\t\t\t\t`${label} tools/ directory contains custom tools. Custom tools have been merged into extensions.`,\n\t\t\t\t);\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore read errors\n\t\t}\n\t}\n\n\treturn warnings;\n}\n\n/**\n * Run extension system migrations (commands→prompts) and collect warnings about deprecated directories.\n */\nfunction migrateExtensionSystem(cwd: string): string[] {\n\tconst agentDir = getAgentDir();\n\tconst projectDir = join(cwd, CONFIG_DIR_NAME);\n\n\t// Migrate commands/ to prompts/\n\tmigrateCommandsToPrompts(agentDir, \"Global\");\n\tmigrateCommandsToPrompts(projectDir, \"Project\");\n\n\t// Check for deprecated directories\n\tconst warnings = [\n\t\t...checkDeprecatedExtensionDirs(agentDir, \"Global\"),\n\t\t...checkDeprecatedExtensionDirs(projectDir, \"Project\"),\n\t];\n\n\treturn warnings;\n}\n\n/**\n * Print deprecation warnings and wait for keypress.\n */\nexport async function showDeprecationWarnings(warnings: string[]): Promise<void> {\n\tif (warnings.length === 0) return;\n\n\tfor (const warning of warnings) {\n\t\tconsole.log(chalk.yellow(`Warning: ${warning}`));\n\t}\n\tconsole.log(chalk.yellow(`\\nMove your extensions to the extensions/ directory.`));\n\tconsole.log(chalk.yellow(`Migration guide: ${MIGRATION_GUIDE_URL}`));\n\tconsole.log(chalk.yellow(`Documentation: ${EXTENSIONS_DOC_URL}`));\n\tconsole.log(chalk.dim(`\\nPress any key to continue...`));\n\n\tawait new Promise<void>((resolve) => {\n\t\tprocess.stdin.setRawMode?.(true);\n\t\tprocess.stdin.resume();\n\t\tprocess.stdin.once(\"data\", () => {\n\t\t\tprocess.stdin.setRawMode?.(false);\n\t\t\tprocess.stdin.pause();\n\t\t\tresolve();\n\t\t});\n\t});\n\tconsole.log();\n}\n\n/**\n * Run all migrations. Called once on startup.\n *\n * @returns Object with migration results and deprecation warnings\n */\nexport function runMigrations(cwd: string): {\n\tmigratedAuthProviders: string[];\n\tdeprecationWarnings: string[];\n} {\n\tconst migratedAuthProviders = migrateAuthToAuthJson();\n\tmigrateSessionsFromAgentRoot();\n\tmigrateToolsToBin();\n\tmigrateKeybindingsConfigFile();\n\tconst deprecationWarnings = migrateExtensionSystem(cwd);\n\treturn { migratedAuthProviders, deprecationWarnings };\n}\n"]}
@@ -1,6 +1,16 @@
1
1
  import type { AssistantMessage } from "@earendil-works/pi-ai";
2
2
  import { Container, type MarkdownTheme } from "@earendil-works/pi-tui";
3
3
  import type { MarkdownTransformer } from "../../../core/extensions/types.ts";
4
+ /**
5
+ * Split streamed markdown into render units at boundaries that render
6
+ * independently: closed column-0 code fences, and blank-line block
7
+ * boundaries that cannot continue a preceding construct.
8
+ *
9
+ * The result is prefix-stable: appending text can only add units at the end,
10
+ * never change earlier ones, which is what makes the units cacheable while
11
+ * a message streams.
12
+ */
13
+ export declare function splitStreamingMarkdown(text: string): string[];
4
14
  /**
5
15
  * Component that renders a complete assistant message
6
16
  */
@@ -14,6 +24,8 @@ export declare class AssistantMessageComponent extends Container {
14
24
  private lastMessage?;
15
25
  private hasToolCalls;
16
26
  private isStreaming;
27
+ private forceFullRebuild;
28
+ private sections;
17
29
  constructor(message?: AssistantMessage, hideThinkingBlock?: boolean, markdownTheme?: MarkdownTheme, hiddenThinkingLabel?: string, outputPad?: number, markdownTransformers?: readonly MarkdownTransformer[]);
18
30
  invalidate(): void;
19
31
  setHideThinkingBlock(hide: boolean): void;
@@ -21,5 +33,22 @@ export declare class AssistantMessageComponent extends Container {
21
33
  setOutputPad(padding: number): void;
22
34
  render(width: number): string[];
23
35
  updateContent(message: AssistantMessage, isStreaming?: boolean): void;
36
+ private buildSectionSpecs;
37
+ private appendContentSpecs;
38
+ private appendStatusSpecs;
39
+ /**
40
+ * Push markdown sections for one content block. While streaming, the block
41
+ * is split at render-independent boundaries so completed units keep their
42
+ * rendered Markdown instances and only the active tail re-parses per
43
+ * chunk; otherwise the block renders whole, byte-identical to the
44
+ * pre-split behaviour.
45
+ *
46
+ * Transformers are assumed block-local (the built-in mermaid transformer
47
+ * maps tokens and preserves the rest, so per-unit application is
48
+ * equivalent). A transformer that genuinely needs whole-message context
49
+ * still gets it: a non-streaming update always renders whole blocks.
50
+ */
51
+ private pushMarkdownSpecs;
52
+ private createComponent;
24
53
  }
25
54
  //# sourceMappingURL=assistant-message.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"assistant-message.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/assistant-message.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAY,KAAK,aAAa,EAAgB,MAAM,wBAAwB,CAAC;AAC/F,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAQ7E;;GAEG;AACH,qBAAa,yBAA0B,SAAQ,SAAS;IACvD,OAAO,CAAC,gBAAgB,CAAY;IACpC,OAAO,CAAC,iBAAiB,CAAU;IACnC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,mBAAmB,CAAS;IACpC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,oBAAoB,CAAiC;IAC7D,OAAO,CAAC,WAAW,CAAC,CAAmB;IACvC,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,WAAW,CAAS;IAE5B,YACC,OAAO,CAAC,EAAE,gBAAgB,EAC1B,iBAAiB,UAAQ,EACzB,aAAa,GAAE,aAAkC,EACjD,mBAAmB,SAAgB,EACnC,SAAS,SAAI,EACb,oBAAoB,GAAE,SAAS,mBAAmB,EAAO,EAiBzD;IAEQ,UAAU,IAAI,IAAI,CAK1B;IAED,oBAAoB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAKxC;IAED,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAK1C;IAED,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAKlC;IAEQ,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CASvC;IAED,aAAa,CAAC,OAAO,EAAE,gBAAgB,EAAE,WAAW,UAAmB,GAAG,IAAI,CA2G7E;CACD","sourcesContent":["import type { AssistantMessage } from \"@earendil-works/pi-ai\";\nimport { Container, Markdown, type MarkdownTheme, Spacer, Text } from \"@earendil-works/pi-tui\";\nimport type { MarkdownTransformer } from \"../../../core/extensions/types.ts\";\nimport { getMarkdownTheme, theme } from \"../theme/theme.ts\";\nimport { createMarkdownTransform } from \"./markdown-transform.ts\";\n\nconst OSC133_ZONE_START = \"\\x1b]133;A\\x07\";\nconst OSC133_ZONE_END = \"\\x1b]133;B\\x07\";\nconst OSC133_ZONE_FINAL = \"\\x1b]133;C\\x07\";\n\n/**\n * Component that renders a complete assistant message\n */\nexport class AssistantMessageComponent extends Container {\n\tprivate contentContainer: Container;\n\tprivate hideThinkingBlock: boolean;\n\tprivate markdownTheme: MarkdownTheme;\n\tprivate hiddenThinkingLabel: string;\n\tprivate outputPad: number;\n\tprivate markdownTransformers: readonly MarkdownTransformer[];\n\tprivate lastMessage?: AssistantMessage;\n\tprivate hasToolCalls = false;\n\tprivate isStreaming = false;\n\n\tconstructor(\n\t\tmessage?: AssistantMessage,\n\t\thideThinkingBlock = false,\n\t\tmarkdownTheme: MarkdownTheme = getMarkdownTheme(),\n\t\thiddenThinkingLabel = \"Thinking...\",\n\t\toutputPad = 1,\n\t\tmarkdownTransformers: readonly MarkdownTransformer[] = [],\n\t) {\n\t\tsuper();\n\n\t\tthis.hideThinkingBlock = hideThinkingBlock;\n\t\tthis.markdownTheme = markdownTheme;\n\t\tthis.hiddenThinkingLabel = hiddenThinkingLabel;\n\t\tthis.outputPad = outputPad;\n\t\tthis.markdownTransformers = markdownTransformers;\n\n\t\t// Container for text/thinking content\n\t\tthis.contentContainer = new Container();\n\t\tthis.addChild(this.contentContainer);\n\n\t\tif (message) {\n\t\t\tthis.updateContent(message);\n\t\t}\n\t}\n\n\toverride invalidate(): void {\n\t\tsuper.invalidate();\n\t\tif (this.lastMessage) {\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\tsetHideThinkingBlock(hide: boolean): void {\n\t\tthis.hideThinkingBlock = hide;\n\t\tif (this.lastMessage) {\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\tsetHiddenThinkingLabel(label: string): void {\n\t\tthis.hiddenThinkingLabel = label;\n\t\tif (this.lastMessage) {\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\tsetOutputPad(padding: number): void {\n\t\tthis.outputPad = padding;\n\t\tif (this.lastMessage) {\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\toverride render(width: number): string[] {\n\t\tconst lines = super.render(width);\n\t\tif (this.hasToolCalls || lines.length === 0) {\n\t\t\treturn lines;\n\t\t}\n\n\t\tlines[0] = OSC133_ZONE_START + lines[0];\n\t\tlines[lines.length - 1] = OSC133_ZONE_END + OSC133_ZONE_FINAL + lines[lines.length - 1];\n\t\treturn lines;\n\t}\n\n\tupdateContent(message: AssistantMessage, isStreaming = this.isStreaming): void {\n\t\tthis.lastMessage = message;\n\t\tthis.isStreaming = isStreaming;\n\n\t\t// Clear content container\n\t\tthis.contentContainer.clear();\n\n\t\tconst hasVisibleContent = message.content.some(\n\t\t\t(c) => (c.type === \"text\" && c.text.trim()) || (c.type === \"thinking\" && c.thinking.trim()),\n\t\t);\n\n\t\tif (hasVisibleContent) {\n\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t}\n\n\t\t// Render content in order\n\t\tfor (let i = 0; i < message.content.length; i++) {\n\t\t\tconst content = message.content[i];\n\t\t\tif (content.type === \"text\" && content.text.trim()) {\n\t\t\t\t// Assistant text messages with no background - trim the text\n\t\t\t\t// Set paddingY=0 to avoid extra spacing before tool executions\n\t\t\t\tthis.contentContainer.addChild(\n\t\t\t\t\tnew Markdown(content.text.trim(), this.outputPad, 0, this.markdownTheme, undefined, {\n\t\t\t\t\t\ttransform: createMarkdownTransform(\"assistant\", this.isStreaming, this.markdownTransformers),\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t} else if (content.type === \"thinking\") {\n\t\t\t\tconst thinkingBlocks: string[] = [];\n\t\t\t\tfor (; i < message.content.length; i++) {\n\t\t\t\t\tconst thinkingContent = message.content[i];\n\t\t\t\t\tif (thinkingContent.type !== \"thinking\") {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tconst thinking = thinkingContent.thinking.trim();\n\t\t\t\t\tif (thinking) {\n\t\t\t\t\t\tthinkingBlocks.push(thinking);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\ti--;\n\n\t\t\t\tif (thinkingBlocks.length === 0) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Add spacing only when another visible assistant content block follows.\n\t\t\t\t// This avoids a superfluous blank line before separately-rendered tool execution blocks.\n\t\t\t\tconst hasVisibleContentAfter = message.content\n\t\t\t\t\t.slice(i + 1)\n\t\t\t\t\t.some((c) => (c.type === \"text\" && c.text.trim()) || (c.type === \"thinking\" && c.thinking.trim()));\n\n\t\t\t\tif (this.hideThinkingBlock) {\n\t\t\t\t\t// Show one static label for each run of thinking blocks when hidden.\n\t\t\t\t\tthis.contentContainer.addChild(\n\t\t\t\t\t\tnew Text(theme.italic(theme.fg(\"thinkingText\", this.hiddenThinkingLabel)), this.outputPad, 0),\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\t// Render each run of thinking blocks as one Markdown section.\n\t\t\t\t\tthis.contentContainer.addChild(\n\t\t\t\t\t\tnew Markdown(\n\t\t\t\t\t\t\tthinkingBlocks.join(\"\\n\\n\"),\n\t\t\t\t\t\t\tthis.outputPad,\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\tthis.markdownTheme,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcolor: (text: string) => theme.fg(\"thinkingText\", text),\n\t\t\t\t\t\t\t\titalic: true,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttransform: createMarkdownTransform(\n\t\t\t\t\t\t\t\t\t\"assistant-thinking\",\n\t\t\t\t\t\t\t\t\tthis.isStreaming,\n\t\t\t\t\t\t\t\t\tthis.markdownTransformers,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (hasVisibleContentAfter) {\n\t\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Check if incomplete/failed - show after partial content.\n\t\t// For aborted/error tool calls, tool execution components show the error.\n\t\t// Length stops can happen before a tool call is complete, so surface them here too.\n\t\tconst hasToolCalls = message.content.some((c) => c.type === \"toolCall\");\n\t\tthis.hasToolCalls = hasToolCalls;\n\t\tif (message.stopReason === \"length\") {\n\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\tthis.contentContainer.addChild(\n\t\t\t\tnew Text(theme.fg(\"error\", \"Response was truncated before completion.\"), this.outputPad, 0),\n\t\t\t);\n\t\t} else if (!hasToolCalls) {\n\t\t\tif (message.stopReason === \"aborted\") {\n\t\t\t\tconst abortMessage =\n\t\t\t\t\tmessage.errorMessage && message.errorMessage !== \"Request was aborted\"\n\t\t\t\t\t\t? message.errorMessage\n\t\t\t\t\t\t: \"Operation aborted\";\n\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\tthis.contentContainer.addChild(new Text(theme.fg(\"error\", abortMessage), this.outputPad, 0));\n\t\t\t} else if (message.stopReason === \"error\") {\n\t\t\t\tconst errorMsg = message.errorMessage || \"Unknown error\";\n\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\tthis.contentContainer.addChild(new Text(theme.fg(\"error\", `Error: ${errorMsg}`), this.outputPad, 0));\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"assistant-message.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/assistant-message.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAY,KAAK,aAAa,EAAgB,MAAM,wBAAwB,CAAC;AAC/F,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAiC7E;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAqC7D;AAcD;;GAEG;AACH,qBAAa,yBAA0B,SAAQ,SAAS;IACvD,OAAO,CAAC,gBAAgB,CAAY;IACpC,OAAO,CAAC,iBAAiB,CAAU;IACnC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,mBAAmB,CAAS;IACpC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,oBAAoB,CAAiC;IAC7D,OAAO,CAAC,WAAW,CAAC,CAAmB;IACvC,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,gBAAgB,CAAQ;IAChC,OAAO,CAAC,QAAQ,CAAiB;IAEjC,YACC,OAAO,CAAC,EAAE,gBAAgB,EAC1B,iBAAiB,UAAQ,EACzB,aAAa,GAAE,aAAkC,EACjD,mBAAmB,SAAgB,EACnC,SAAS,SAAI,EACb,oBAAoB,GAAE,SAAS,mBAAmB,EAAO,EAiBzD;IAEQ,UAAU,IAAI,IAAI,CAM1B;IAED,oBAAoB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAMxC;IAED,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAM1C;IAED,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAMlC;IAEQ,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CASvC;IAED,aAAa,CAAC,OAAO,EAAE,gBAAgB,EAAE,WAAW,UAAmB,GAAG,IAAI,CA0C7E;IAED,OAAO,CAAC,iBAAiB;IAOzB,OAAO,CAAC,kBAAkB;IAyD1B,OAAO,CAAC,iBAAiB;IAqBzB;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,iBAAiB;IAUzB,OAAO,CAAC,eAAe;CA0BvB","sourcesContent":["import type { AssistantMessage } from \"@earendil-works/pi-ai\";\nimport { Container, Markdown, type MarkdownTheme, Spacer, Text } from \"@earendil-works/pi-tui\";\nimport type { MarkdownTransformer } from \"../../../core/extensions/types.ts\";\nimport { getMarkdownTheme, theme } from \"../theme/theme.ts\";\nimport { createMarkdownTransform } from \"./markdown-transform.ts\";\n\nconst OSC133_ZONE_START = \"\\x1b]133;A\\x07\";\nconst OSC133_ZONE_END = \"\\x1b]133;B\\x07\";\nconst OSC133_ZONE_FINAL = \"\\x1b]133;C\\x07\";\n\nconst FENCE_OPENER = /^(```|~~~)/;\nconst FENCE_CLOSER = /^(```|~~~)\\s*$/;\nconst LIST_MARKER = /^([-*+]\\s|\\d+[.)]\\s)/;\nconst QUOTE_MARKER = /^>\\s?/;\nconst INDENTED_CODE = /^(?:\\t| {4})/;\n\nfunction lastNonEmpty(lines: string[]): string | undefined {\n\tfor (let i = lines.length - 1; i >= 0; i--) {\n\t\tif (lines[i].trim() !== \"\") return lines[i];\n\t}\n\treturn undefined;\n}\n\nfunction shouldSplitBefore(next: string, current: string[]): boolean {\n\t// Indented lines can continue indented code blocks; never split there.\n\tif (INDENTED_CODE.test(next)) return false;\n\tconst previous = lastNonEmpty(current);\n\tif (previous && INDENTED_CODE.test(previous)) return false;\n\t// A loose list (\"item\\n\\nitem\") and a blockquote with a blank line render\n\t// as one construct; splitting them would change the output.\n\tif (LIST_MARKER.test(next) && previous && LIST_MARKER.test(previous)) return false;\n\tif (QUOTE_MARKER.test(next) && previous && QUOTE_MARKER.test(previous)) return false;\n\treturn true;\n}\n\n/**\n * Split streamed markdown into render units at boundaries that render\n * independently: closed column-0 code fences, and blank-line block\n * boundaries that cannot continue a preceding construct.\n *\n * The result is prefix-stable: appending text can only add units at the end,\n * never change earlier ones, which is what makes the units cacheable while\n * a message streams.\n */\nexport function splitStreamingMarkdown(text: string): string[] {\n\tif (!text) return [];\n\tconst lines = text.split(\"\\n\");\n\tconst units: string[] = [];\n\tlet current: string[] = [];\n\tlet inFence = false;\n\tconst flush = (): void => {\n\t\tif (current.length > 0) {\n\t\t\tunits.push(current.join(\"\\n\"));\n\t\t\tcurrent = [];\n\t\t}\n\t};\n\tfor (let i = 0; i < lines.length; i++) {\n\t\tconst line = lines[i];\n\t\tif (!inFence && FENCE_OPENER.test(line)) {\n\t\t\tinFence = true;\n\t\t\tcurrent.push(line);\n\t\t\tcontinue;\n\t\t}\n\t\tif (inFence) {\n\t\t\tcurrent.push(line);\n\t\t\tif (FENCE_CLOSER.test(line)) {\n\t\t\t\tflush();\n\t\t\t\tinFence = false;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tcurrent.push(line);\n\t\tif (line.trim() === \"\") {\n\t\t\tconst next = lines[i + 1];\n\t\t\tif (next !== undefined && next.trim() !== \"\" && shouldSplitBefore(next, current)) {\n\t\t\t\tflush();\n\t\t\t}\n\t\t}\n\t}\n\tflush();\n\treturn units;\n}\n\ntype SectionSpec =\n\t| { kind: \"spacer\" }\n\t| { kind: \"markdown-text\"; text: string }\n\t| { kind: \"markdown-thinking\"; text: string }\n\t| { kind: \"label\"; text: string };\n\ntype Section = { spec: SectionSpec; component: Container[\"children\"][number] };\n\nfunction specText(spec: SectionSpec): string | undefined {\n\treturn spec.kind === \"spacer\" ? undefined : spec.text;\n}\n\n/**\n * Component that renders a complete assistant message\n */\nexport class AssistantMessageComponent extends Container {\n\tprivate contentContainer: Container;\n\tprivate hideThinkingBlock: boolean;\n\tprivate markdownTheme: MarkdownTheme;\n\tprivate hiddenThinkingLabel: string;\n\tprivate outputPad: number;\n\tprivate markdownTransformers: readonly MarkdownTransformer[];\n\tprivate lastMessage?: AssistantMessage;\n\tprivate hasToolCalls = false;\n\tprivate isStreaming = false;\n\tprivate forceFullRebuild = true;\n\tprivate sections: Section[] = [];\n\n\tconstructor(\n\t\tmessage?: AssistantMessage,\n\t\thideThinkingBlock = false,\n\t\tmarkdownTheme: MarkdownTheme = getMarkdownTheme(),\n\t\thiddenThinkingLabel = \"Thinking...\",\n\t\toutputPad = 1,\n\t\tmarkdownTransformers: readonly MarkdownTransformer[] = [],\n\t) {\n\t\tsuper();\n\n\t\tthis.hideThinkingBlock = hideThinkingBlock;\n\t\tthis.markdownTheme = markdownTheme;\n\t\tthis.hiddenThinkingLabel = hiddenThinkingLabel;\n\t\tthis.outputPad = outputPad;\n\t\tthis.markdownTransformers = markdownTransformers;\n\n\t\t// Container for text/thinking content\n\t\tthis.contentContainer = new Container();\n\t\tthis.addChild(this.contentContainer);\n\n\t\tif (message) {\n\t\t\tthis.updateContent(message);\n\t\t}\n\t}\n\n\toverride invalidate(): void {\n\t\tsuper.invalidate();\n\t\tif (this.lastMessage) {\n\t\t\tthis.forceFullRebuild = true;\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\tsetHideThinkingBlock(hide: boolean): void {\n\t\tthis.hideThinkingBlock = hide;\n\t\tif (this.lastMessage) {\n\t\t\tthis.forceFullRebuild = true;\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\tsetHiddenThinkingLabel(label: string): void {\n\t\tthis.hiddenThinkingLabel = label;\n\t\tif (this.lastMessage) {\n\t\t\tthis.forceFullRebuild = true;\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\tsetOutputPad(padding: number): void {\n\t\tthis.outputPad = padding;\n\t\tif (this.lastMessage) {\n\t\t\tthis.forceFullRebuild = true;\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\toverride render(width: number): string[] {\n\t\tconst lines = super.render(width);\n\t\tif (this.hasToolCalls || lines.length === 0) {\n\t\t\treturn lines;\n\t\t}\n\n\t\tlines[0] = OSC133_ZONE_START + lines[0];\n\t\tlines[lines.length - 1] = OSC133_ZONE_END + OSC133_ZONE_FINAL + lines[lines.length - 1];\n\t\treturn lines;\n\t}\n\n\tupdateContent(message: AssistantMessage, isStreaming = this.isStreaming): void {\n\t\tthis.lastMessage = message;\n\t\t// The transform closures capture isStreaming, and non-streaming updates\n\t\t// render whole blocks rather than split units, so an isStreaming flip\n\t\t// rebuilds every section.\n\t\tconst rebuildAll = this.forceFullRebuild || isStreaming !== this.isStreaming;\n\t\tthis.isStreaming = isStreaming;\n\n\t\tconst specs = this.buildSectionSpecs(message);\n\t\tconst sections: Section[] = [];\n\t\tfor (let i = 0; i < specs.length; i++) {\n\t\t\tconst spec = specs[i];\n\t\t\tconst previous = rebuildAll ? undefined : this.sections[i];\n\t\t\tconst sameKind = previous !== undefined && previous.spec.kind === spec.kind;\n\t\t\tif (sameKind && (spec.kind === \"spacer\" || specText(previous.spec) === specText(spec))) {\n\t\t\t\tsections.push({ spec, component: previous.component });\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (sameKind && spec.kind !== \"spacer\") {\n\t\t\t\t// Same slot, new content (the growing tail of a streamed\n\t\t\t\t// message): update in place so only this unit re-parses.\n\t\t\t\tconst component = previous.component as Text;\n\t\t\t\tcomponent.setText(specText(spec) ?? \"\");\n\t\t\t\tsections.push({ spec, component: previous.component });\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tsections.push({ spec, component: this.createComponent(spec) });\n\t\t}\n\n\t\tthis.forceFullRebuild = false;\n\t\tthis.sections = sections;\n\n\t\tthis.contentContainer.clear();\n\t\tfor (const section of sections) {\n\t\t\tthis.contentContainer.addChild(section.component);\n\t\t}\n\n\t\t// Check if incomplete/failed - show after partial content.\n\t\t// For aborted/error tool calls, tool execution components show the error.\n\t\t// Length stops can happen before a tool call is complete, so surface them here too.\n\t\tconst hasToolCalls = message.content.some((c) => c.type === \"toolCall\");\n\t\tthis.hasToolCalls = hasToolCalls;\n\t}\n\n\tprivate buildSectionSpecs(message: AssistantMessage): SectionSpec[] {\n\t\tconst specs: SectionSpec[] = [];\n\t\tthis.appendContentSpecs(message, specs);\n\t\tthis.appendStatusSpecs(message, specs);\n\t\treturn specs;\n\t}\n\n\tprivate appendContentSpecs(message: AssistantMessage, specs: SectionSpec[]): void {\n\t\tconst hasVisibleContent = message.content.some(\n\t\t\t(c) => (c.type === \"text\" && c.text.trim()) || (c.type === \"thinking\" && c.thinking.trim()),\n\t\t);\n\n\t\tif (hasVisibleContent) {\n\t\t\tspecs.push({ kind: \"spacer\" });\n\t\t}\n\n\t\t// Render content in order\n\t\tfor (let i = 0; i < message.content.length; i++) {\n\t\t\tconst content = message.content[i];\n\t\t\tif (content.type === \"text\" && content.text.trim()) {\n\t\t\t\t// Assistant text messages with no background - trim the text\n\t\t\t\t// Set paddingY=0 to avoid extra spacing before tool executions\n\t\t\t\tthis.pushMarkdownSpecs(specs, content.text.trim(), \"markdown-text\");\n\t\t\t} else if (content.type === \"thinking\") {\n\t\t\t\tconst thinkingBlocks: string[] = [];\n\t\t\t\tfor (; i < message.content.length; i++) {\n\t\t\t\t\tconst thinkingContent = message.content[i];\n\t\t\t\t\tif (thinkingContent.type !== \"thinking\") {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tconst thinking = thinkingContent.thinking.trim();\n\t\t\t\t\tif (thinking) {\n\t\t\t\t\t\tthinkingBlocks.push(thinking);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\ti--;\n\n\t\t\t\tif (thinkingBlocks.length === 0) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Add spacing only when another visible assistant content block follows.\n\t\t\t\t// This avoids a superfluous blank line before separately-rendered tool execution blocks.\n\t\t\t\tconst hasVisibleContentAfter = message.content\n\t\t\t\t\t.slice(i + 1)\n\t\t\t\t\t.some((c) => (c.type === \"text\" && c.text.trim()) || (c.type === \"thinking\" && c.thinking.trim()));\n\n\t\t\t\tif (this.hideThinkingBlock) {\n\t\t\t\t\t// Show one static label for each run of thinking blocks when hidden.\n\t\t\t\t\tspecs.push({\n\t\t\t\t\t\tkind: \"label\",\n\t\t\t\t\t\ttext: theme.italic(theme.fg(\"thinkingText\", this.hiddenThinkingLabel)),\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\t// Render each run of thinking blocks as one Markdown section.\n\t\t\t\t\tthis.pushMarkdownSpecs(specs, thinkingBlocks.join(\"\\n\\n\"), \"markdown-thinking\");\n\t\t\t\t}\n\t\t\t\tif (hasVisibleContentAfter) {\n\t\t\t\t\tspecs.push({ kind: \"spacer\" });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate appendStatusSpecs(message: AssistantMessage, specs: SectionSpec[]): void {\n\t\tconst hasToolCalls = message.content.some((c) => c.type === \"toolCall\");\n\t\tif (message.stopReason === \"length\") {\n\t\t\tspecs.push({ kind: \"spacer\" });\n\t\t\tspecs.push({ kind: \"label\", text: theme.fg(\"error\", \"Response was truncated before completion.\") });\n\t\t} else if (!hasToolCalls) {\n\t\t\tif (message.stopReason === \"aborted\") {\n\t\t\t\tconst abortMessage =\n\t\t\t\t\tmessage.errorMessage && message.errorMessage !== \"Request was aborted\"\n\t\t\t\t\t\t? message.errorMessage\n\t\t\t\t\t\t: \"Operation aborted\";\n\t\t\t\tspecs.push({ kind: \"spacer\" });\n\t\t\t\tspecs.push({ kind: \"label\", text: theme.fg(\"error\", abortMessage) });\n\t\t\t} else if (message.stopReason === \"error\") {\n\t\t\t\tconst errorMsg = message.errorMessage || \"Unknown error\";\n\t\t\t\tspecs.push({ kind: \"spacer\" });\n\t\t\t\tspecs.push({ kind: \"label\", text: theme.fg(\"error\", `Error: ${errorMsg}`) });\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Push markdown sections for one content block. While streaming, the block\n\t * is split at render-independent boundaries so completed units keep their\n\t * rendered Markdown instances and only the active tail re-parses per\n\t * chunk; otherwise the block renders whole, byte-identical to the\n\t * pre-split behaviour.\n\t *\n\t * Transformers are assumed block-local (the built-in mermaid transformer\n\t * maps tokens and preserves the rest, so per-unit application is\n\t * equivalent). A transformer that genuinely needs whole-message context\n\t * still gets it: a non-streaming update always renders whole blocks.\n\t */\n\tprivate pushMarkdownSpecs(specs: SectionSpec[], text: string, kind: \"markdown-text\" | \"markdown-thinking\"): void {\n\t\tif (this.isStreaming) {\n\t\t\tfor (const unit of splitStreamingMarkdown(text)) {\n\t\t\t\tspecs.push({ kind, text: unit });\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tspecs.push({ kind, text });\n\t}\n\n\tprivate createComponent(spec: SectionSpec): Section[\"component\"] {\n\t\tswitch (spec.kind) {\n\t\t\tcase \"spacer\":\n\t\t\t\treturn new Spacer(1);\n\t\t\tcase \"label\":\n\t\t\t\treturn new Text(spec.text, this.outputPad, 0);\n\t\t\tcase \"markdown-text\":\n\t\t\t\treturn new Markdown(spec.text, this.outputPad, 0, this.markdownTheme, undefined, {\n\t\t\t\t\ttransform: createMarkdownTransform(\"assistant\", this.isStreaming, this.markdownTransformers),\n\t\t\t\t});\n\t\t\tcase \"markdown-thinking\":\n\t\t\t\treturn new Markdown(\n\t\t\t\t\tspec.text,\n\t\t\t\t\tthis.outputPad,\n\t\t\t\t\t0,\n\t\t\t\t\tthis.markdownTheme,\n\t\t\t\t\t{\n\t\t\t\t\t\tcolor: (text: string) => theme.fg(\"thinkingText\", text),\n\t\t\t\t\t\titalic: true,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\ttransform: createMarkdownTransform(\"assistant-thinking\", this.isStreaming, this.markdownTransformers),\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t}\n\t}\n}\n"]}
@@ -4,6 +4,84 @@ import { createMarkdownTransform } from "./markdown-transform.js";
4
4
  const OSC133_ZONE_START = "\x1b]133;A\x07";
5
5
  const OSC133_ZONE_END = "\x1b]133;B\x07";
6
6
  const OSC133_ZONE_FINAL = "\x1b]133;C\x07";
7
+ const FENCE_OPENER = /^(```|~~~)/;
8
+ const FENCE_CLOSER = /^(```|~~~)\s*$/;
9
+ const LIST_MARKER = /^([-*+]\s|\d+[.)]\s)/;
10
+ const QUOTE_MARKER = /^>\s?/;
11
+ const INDENTED_CODE = /^(?:\t| {4})/;
12
+ function lastNonEmpty(lines) {
13
+ for (let i = lines.length - 1; i >= 0; i--) {
14
+ if (lines[i].trim() !== "")
15
+ return lines[i];
16
+ }
17
+ return undefined;
18
+ }
19
+ function shouldSplitBefore(next, current) {
20
+ // Indented lines can continue indented code blocks; never split there.
21
+ if (INDENTED_CODE.test(next))
22
+ return false;
23
+ const previous = lastNonEmpty(current);
24
+ if (previous && INDENTED_CODE.test(previous))
25
+ return false;
26
+ // A loose list ("item\n\nitem") and a blockquote with a blank line render
27
+ // as one construct; splitting them would change the output.
28
+ if (LIST_MARKER.test(next) && previous && LIST_MARKER.test(previous))
29
+ return false;
30
+ if (QUOTE_MARKER.test(next) && previous && QUOTE_MARKER.test(previous))
31
+ return false;
32
+ return true;
33
+ }
34
+ /**
35
+ * Split streamed markdown into render units at boundaries that render
36
+ * independently: closed column-0 code fences, and blank-line block
37
+ * boundaries that cannot continue a preceding construct.
38
+ *
39
+ * The result is prefix-stable: appending text can only add units at the end,
40
+ * never change earlier ones, which is what makes the units cacheable while
41
+ * a message streams.
42
+ */
43
+ export function splitStreamingMarkdown(text) {
44
+ if (!text)
45
+ return [];
46
+ const lines = text.split("\n");
47
+ const units = [];
48
+ let current = [];
49
+ let inFence = false;
50
+ const flush = () => {
51
+ if (current.length > 0) {
52
+ units.push(current.join("\n"));
53
+ current = [];
54
+ }
55
+ };
56
+ for (let i = 0; i < lines.length; i++) {
57
+ const line = lines[i];
58
+ if (!inFence && FENCE_OPENER.test(line)) {
59
+ inFence = true;
60
+ current.push(line);
61
+ continue;
62
+ }
63
+ if (inFence) {
64
+ current.push(line);
65
+ if (FENCE_CLOSER.test(line)) {
66
+ flush();
67
+ inFence = false;
68
+ }
69
+ continue;
70
+ }
71
+ current.push(line);
72
+ if (line.trim() === "") {
73
+ const next = lines[i + 1];
74
+ if (next !== undefined && next.trim() !== "" && shouldSplitBefore(next, current)) {
75
+ flush();
76
+ }
77
+ }
78
+ }
79
+ flush();
80
+ return units;
81
+ }
82
+ function specText(spec) {
83
+ return spec.kind === "spacer" ? undefined : spec.text;
84
+ }
7
85
  /**
8
86
  * Component that renders a complete assistant message
9
87
  */
@@ -17,6 +95,8 @@ export class AssistantMessageComponent extends Container {
17
95
  lastMessage;
18
96
  hasToolCalls = false;
19
97
  isStreaming = false;
98
+ forceFullRebuild = true;
99
+ sections = [];
20
100
  constructor(message, hideThinkingBlock = false, markdownTheme = getMarkdownTheme(), hiddenThinkingLabel = "Thinking...", outputPad = 1, markdownTransformers = []) {
21
101
  super();
22
102
  this.hideThinkingBlock = hideThinkingBlock;
@@ -34,24 +114,28 @@ export class AssistantMessageComponent extends Container {
34
114
  invalidate() {
35
115
  super.invalidate();
36
116
  if (this.lastMessage) {
117
+ this.forceFullRebuild = true;
37
118
  this.updateContent(this.lastMessage);
38
119
  }
39
120
  }
40
121
  setHideThinkingBlock(hide) {
41
122
  this.hideThinkingBlock = hide;
42
123
  if (this.lastMessage) {
124
+ this.forceFullRebuild = true;
43
125
  this.updateContent(this.lastMessage);
44
126
  }
45
127
  }
46
128
  setHiddenThinkingLabel(label) {
47
129
  this.hiddenThinkingLabel = label;
48
130
  if (this.lastMessage) {
131
+ this.forceFullRebuild = true;
49
132
  this.updateContent(this.lastMessage);
50
133
  }
51
134
  }
52
135
  setOutputPad(padding) {
53
136
  this.outputPad = padding;
54
137
  if (this.lastMessage) {
138
+ this.forceFullRebuild = true;
55
139
  this.updateContent(this.lastMessage);
56
140
  }
57
141
  }
@@ -66,12 +150,53 @@ export class AssistantMessageComponent extends Container {
66
150
  }
67
151
  updateContent(message, isStreaming = this.isStreaming) {
68
152
  this.lastMessage = message;
153
+ // The transform closures capture isStreaming, and non-streaming updates
154
+ // render whole blocks rather than split units, so an isStreaming flip
155
+ // rebuilds every section.
156
+ const rebuildAll = this.forceFullRebuild || isStreaming !== this.isStreaming;
69
157
  this.isStreaming = isStreaming;
70
- // Clear content container
158
+ const specs = this.buildSectionSpecs(message);
159
+ const sections = [];
160
+ for (let i = 0; i < specs.length; i++) {
161
+ const spec = specs[i];
162
+ const previous = rebuildAll ? undefined : this.sections[i];
163
+ const sameKind = previous !== undefined && previous.spec.kind === spec.kind;
164
+ if (sameKind && (spec.kind === "spacer" || specText(previous.spec) === specText(spec))) {
165
+ sections.push({ spec, component: previous.component });
166
+ continue;
167
+ }
168
+ if (sameKind && spec.kind !== "spacer") {
169
+ // Same slot, new content (the growing tail of a streamed
170
+ // message): update in place so only this unit re-parses.
171
+ const component = previous.component;
172
+ component.setText(specText(spec) ?? "");
173
+ sections.push({ spec, component: previous.component });
174
+ continue;
175
+ }
176
+ sections.push({ spec, component: this.createComponent(spec) });
177
+ }
178
+ this.forceFullRebuild = false;
179
+ this.sections = sections;
71
180
  this.contentContainer.clear();
181
+ for (const section of sections) {
182
+ this.contentContainer.addChild(section.component);
183
+ }
184
+ // Check if incomplete/failed - show after partial content.
185
+ // For aborted/error tool calls, tool execution components show the error.
186
+ // Length stops can happen before a tool call is complete, so surface them here too.
187
+ const hasToolCalls = message.content.some((c) => c.type === "toolCall");
188
+ this.hasToolCalls = hasToolCalls;
189
+ }
190
+ buildSectionSpecs(message) {
191
+ const specs = [];
192
+ this.appendContentSpecs(message, specs);
193
+ this.appendStatusSpecs(message, specs);
194
+ return specs;
195
+ }
196
+ appendContentSpecs(message, specs) {
72
197
  const hasVisibleContent = message.content.some((c) => (c.type === "text" && c.text.trim()) || (c.type === "thinking" && c.thinking.trim()));
73
198
  if (hasVisibleContent) {
74
- this.contentContainer.addChild(new Spacer(1));
199
+ specs.push({ kind: "spacer" });
75
200
  }
76
201
  // Render content in order
77
202
  for (let i = 0; i < message.content.length; i++) {
@@ -79,9 +204,7 @@ export class AssistantMessageComponent extends Container {
79
204
  if (content.type === "text" && content.text.trim()) {
80
205
  // Assistant text messages with no background - trim the text
81
206
  // Set paddingY=0 to avoid extra spacing before tool executions
82
- this.contentContainer.addChild(new Markdown(content.text.trim(), this.outputPad, 0, this.markdownTheme, undefined, {
83
- transform: createMarkdownTransform("assistant", this.isStreaming, this.markdownTransformers),
84
- }));
207
+ this.pushMarkdownSpecs(specs, content.text.trim(), "markdown-text");
85
208
  }
86
209
  else if (content.type === "thinking") {
87
210
  const thinkingBlocks = [];
@@ -106,45 +229,81 @@ export class AssistantMessageComponent extends Container {
106
229
  .some((c) => (c.type === "text" && c.text.trim()) || (c.type === "thinking" && c.thinking.trim()));
107
230
  if (this.hideThinkingBlock) {
108
231
  // Show one static label for each run of thinking blocks when hidden.
109
- this.contentContainer.addChild(new Text(theme.italic(theme.fg("thinkingText", this.hiddenThinkingLabel)), this.outputPad, 0));
232
+ specs.push({
233
+ kind: "label",
234
+ text: theme.italic(theme.fg("thinkingText", this.hiddenThinkingLabel)),
235
+ });
110
236
  }
111
237
  else {
112
238
  // Render each run of thinking blocks as one Markdown section.
113
- this.contentContainer.addChild(new Markdown(thinkingBlocks.join("\n\n"), this.outputPad, 0, this.markdownTheme, {
114
- color: (text) => theme.fg("thinkingText", text),
115
- italic: true,
116
- }, {
117
- transform: createMarkdownTransform("assistant-thinking", this.isStreaming, this.markdownTransformers),
118
- }));
239
+ this.pushMarkdownSpecs(specs, thinkingBlocks.join("\n\n"), "markdown-thinking");
119
240
  }
120
241
  if (hasVisibleContentAfter) {
121
- this.contentContainer.addChild(new Spacer(1));
242
+ specs.push({ kind: "spacer" });
122
243
  }
123
244
  }
124
245
  }
125
- // Check if incomplete/failed - show after partial content.
126
- // For aborted/error tool calls, tool execution components show the error.
127
- // Length stops can happen before a tool call is complete, so surface them here too.
246
+ }
247
+ appendStatusSpecs(message, specs) {
128
248
  const hasToolCalls = message.content.some((c) => c.type === "toolCall");
129
- this.hasToolCalls = hasToolCalls;
130
249
  if (message.stopReason === "length") {
131
- this.contentContainer.addChild(new Spacer(1));
132
- this.contentContainer.addChild(new Text(theme.fg("error", "Response was truncated before completion."), this.outputPad, 0));
250
+ specs.push({ kind: "spacer" });
251
+ specs.push({ kind: "label", text: theme.fg("error", "Response was truncated before completion.") });
133
252
  }
134
253
  else if (!hasToolCalls) {
135
254
  if (message.stopReason === "aborted") {
136
255
  const abortMessage = message.errorMessage && message.errorMessage !== "Request was aborted"
137
256
  ? message.errorMessage
138
257
  : "Operation aborted";
139
- this.contentContainer.addChild(new Spacer(1));
140
- this.contentContainer.addChild(new Text(theme.fg("error", abortMessage), this.outputPad, 0));
258
+ specs.push({ kind: "spacer" });
259
+ specs.push({ kind: "label", text: theme.fg("error", abortMessage) });
141
260
  }
142
261
  else if (message.stopReason === "error") {
143
262
  const errorMsg = message.errorMessage || "Unknown error";
144
- this.contentContainer.addChild(new Spacer(1));
145
- this.contentContainer.addChild(new Text(theme.fg("error", `Error: ${errorMsg}`), this.outputPad, 0));
263
+ specs.push({ kind: "spacer" });
264
+ specs.push({ kind: "label", text: theme.fg("error", `Error: ${errorMsg}`) });
146
265
  }
147
266
  }
148
267
  }
268
+ /**
269
+ * Push markdown sections for one content block. While streaming, the block
270
+ * is split at render-independent boundaries so completed units keep their
271
+ * rendered Markdown instances and only the active tail re-parses per
272
+ * chunk; otherwise the block renders whole, byte-identical to the
273
+ * pre-split behaviour.
274
+ *
275
+ * Transformers are assumed block-local (the built-in mermaid transformer
276
+ * maps tokens and preserves the rest, so per-unit application is
277
+ * equivalent). A transformer that genuinely needs whole-message context
278
+ * still gets it: a non-streaming update always renders whole blocks.
279
+ */
280
+ pushMarkdownSpecs(specs, text, kind) {
281
+ if (this.isStreaming) {
282
+ for (const unit of splitStreamingMarkdown(text)) {
283
+ specs.push({ kind, text: unit });
284
+ }
285
+ return;
286
+ }
287
+ specs.push({ kind, text });
288
+ }
289
+ createComponent(spec) {
290
+ switch (spec.kind) {
291
+ case "spacer":
292
+ return new Spacer(1);
293
+ case "label":
294
+ return new Text(spec.text, this.outputPad, 0);
295
+ case "markdown-text":
296
+ return new Markdown(spec.text, this.outputPad, 0, this.markdownTheme, undefined, {
297
+ transform: createMarkdownTransform("assistant", this.isStreaming, this.markdownTransformers),
298
+ });
299
+ case "markdown-thinking":
300
+ return new Markdown(spec.text, this.outputPad, 0, this.markdownTheme, {
301
+ color: (text) => theme.fg("thinkingText", text),
302
+ italic: true,
303
+ }, {
304
+ transform: createMarkdownTransform("assistant-thinking", this.isStreaming, this.markdownTransformers),
305
+ });
306
+ }
307
+ }
149
308
  }
150
309
  //# sourceMappingURL=assistant-message.js.map