@hyperspaceng/neural-coding-agent 0.62.1 → 0.63.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (374) hide show
  1. package/CHANGELOG.md +143 -0
  2. package/README.md +10 -0
  3. package/dist/bun/register-bedrock.d.ts.map +1 -1
  4. package/dist/bun/register-bedrock.js +2 -2
  5. package/dist/bun/register-bedrock.js.map +1 -1
  6. package/dist/cli/args.d.ts +1 -1
  7. package/dist/cli/args.d.ts.map +1 -1
  8. package/dist/cli/args.js.map +1 -1
  9. package/dist/cli/config-selector.d.ts.map +1 -1
  10. package/dist/cli/config-selector.js +1 -1
  11. package/dist/cli/config-selector.js.map +1 -1
  12. package/dist/cli/file-processor.d.ts +1 -1
  13. package/dist/cli/file-processor.d.ts.map +1 -1
  14. package/dist/cli/file-processor.js +4 -0
  15. package/dist/cli/file-processor.js.map +1 -1
  16. package/dist/cli/initial-message.d.ts +1 -1
  17. package/dist/cli/initial-message.d.ts.map +1 -1
  18. package/dist/cli/initial-message.js.map +1 -1
  19. package/dist/cli/list-models.d.ts.map +1 -1
  20. package/dist/cli/list-models.js +1 -1
  21. package/dist/cli/list-models.js.map +1 -1
  22. package/dist/cli/session-picker.d.ts.map +1 -1
  23. package/dist/cli/session-picker.js +1 -1
  24. package/dist/cli/session-picker.js.map +1 -1
  25. package/dist/core/agent-session.d.ts +21 -11
  26. package/dist/core/agent-session.d.ts.map +1 -1
  27. package/dist/core/agent-session.js +159 -101
  28. package/dist/core/agent-session.js.map +1 -1
  29. package/dist/core/auth-storage.d.ts +5 -3
  30. package/dist/core/auth-storage.d.ts.map +1 -1
  31. package/dist/core/auth-storage.js +7 -4
  32. package/dist/core/auth-storage.js.map +1 -1
  33. package/dist/core/compaction/branch-summarization.d.ts +4 -2
  34. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  35. package/dist/core/compaction/branch-summarization.js +3 -3
  36. package/dist/core/compaction/branch-summarization.js.map +1 -1
  37. package/dist/core/compaction/compaction.d.ts +5 -5
  38. package/dist/core/compaction/compaction.d.ts.map +1 -1
  39. package/dist/core/compaction/compaction.js +28 -27
  40. package/dist/core/compaction/compaction.js.map +1 -1
  41. package/dist/core/compaction/utils.d.ts +2 -2
  42. package/dist/core/compaction/utils.d.ts.map +1 -1
  43. package/dist/core/compaction/utils.js.map +1 -1
  44. package/dist/core/defaults.d.ts +1 -1
  45. package/dist/core/defaults.d.ts.map +1 -1
  46. package/dist/core/defaults.js.map +1 -1
  47. package/dist/core/export-html/index.d.ts +3 -3
  48. package/dist/core/export-html/index.d.ts.map +1 -1
  49. package/dist/core/export-html/index.js +7 -6
  50. package/dist/core/export-html/index.js.map +1 -1
  51. package/dist/core/export-html/tool-renderer.d.ts +2 -2
  52. package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
  53. package/dist/core/export-html/tool-renderer.js +41 -16
  54. package/dist/core/export-html/tool-renderer.js.map +1 -1
  55. package/dist/core/extensions/index.d.ts +3 -2
  56. package/dist/core/extensions/index.d.ts.map +1 -1
  57. package/dist/core/extensions/index.js.map +1 -1
  58. package/dist/core/extensions/loader.d.ts.map +1 -1
  59. package/dist/core/extensions/loader.js +27 -17
  60. package/dist/core/extensions/loader.js.map +1 -1
  61. package/dist/core/extensions/runner.d.ts +7 -10
  62. package/dist/core/extensions/runner.d.ts.map +1 -1
  63. package/dist/core/extensions/runner.js +27 -38
  64. package/dist/core/extensions/runner.js.map +1 -1
  65. package/dist/core/extensions/types.d.ts +56 -15
  66. package/dist/core/extensions/types.d.ts.map +1 -1
  67. package/dist/core/extensions/types.js.map +1 -1
  68. package/dist/core/extensions/wrapper.d.ts +1 -1
  69. package/dist/core/extensions/wrapper.d.ts.map +1 -1
  70. package/dist/core/extensions/wrapper.js +2 -8
  71. package/dist/core/extensions/wrapper.js.map +1 -1
  72. package/dist/core/index.d.ts +2 -1
  73. package/dist/core/index.d.ts.map +1 -1
  74. package/dist/core/index.js +1 -0
  75. package/dist/core/index.js.map +1 -1
  76. package/dist/core/keybindings.d.ts +2 -2
  77. package/dist/core/keybindings.d.ts.map +1 -1
  78. package/dist/core/keybindings.js +1 -1
  79. package/dist/core/keybindings.js.map +1 -1
  80. package/dist/core/messages.d.ts +3 -3
  81. package/dist/core/messages.d.ts.map +1 -1
  82. package/dist/core/messages.js.map +1 -1
  83. package/dist/core/model-registry.d.ts +19 -3
  84. package/dist/core/model-registry.d.ts.map +1 -1
  85. package/dist/core/model-registry.js +85 -71
  86. package/dist/core/model-registry.js.map +1 -1
  87. package/dist/core/model-resolver.d.ts +2 -2
  88. package/dist/core/model-resolver.d.ts.map +1 -1
  89. package/dist/core/model-resolver.js +5 -5
  90. package/dist/core/model-resolver.js.map +1 -1
  91. package/dist/core/output-guard.d.ts +6 -0
  92. package/dist/core/output-guard.d.ts.map +1 -0
  93. package/dist/core/output-guard.js +59 -0
  94. package/dist/core/output-guard.js.map +1 -0
  95. package/dist/core/package-manager.d.ts +3 -0
  96. package/dist/core/package-manager.d.ts.map +1 -1
  97. package/dist/core/package-manager.js +153 -29
  98. package/dist/core/package-manager.js.map +1 -1
  99. package/dist/core/prompt-templates.d.ts +2 -1
  100. package/dist/core/prompt-templates.d.ts.map +1 -1
  101. package/dist/core/prompt-templates.js +30 -32
  102. package/dist/core/prompt-templates.js.map +1 -1
  103. package/dist/core/resolve-config-value.d.ts +6 -0
  104. package/dist/core/resolve-config-value.d.ts.map +1 -1
  105. package/dist/core/resolve-config-value.js +37 -5
  106. package/dist/core/resolve-config-value.js.map +1 -1
  107. package/dist/core/resource-loader.d.ts +6 -5
  108. package/dist/core/resource-loader.d.ts.map +1 -1
  109. package/dist/core/resource-loader.js +136 -108
  110. package/dist/core/resource-loader.js.map +1 -1
  111. package/dist/core/sdk.d.ts +4 -4
  112. package/dist/core/sdk.d.ts.map +1 -1
  113. package/dist/core/sdk.js +15 -24
  114. package/dist/core/sdk.js.map +1 -1
  115. package/dist/core/session-manager.d.ts +2 -2
  116. package/dist/core/session-manager.d.ts.map +1 -1
  117. package/dist/core/session-manager.js.map +1 -1
  118. package/dist/core/settings-manager.d.ts +3 -1
  119. package/dist/core/settings-manager.d.ts.map +1 -1
  120. package/dist/core/settings-manager.js +3 -0
  121. package/dist/core/settings-manager.js.map +1 -1
  122. package/dist/core/skills.d.ts +2 -1
  123. package/dist/core/skills.d.ts.map +1 -1
  124. package/dist/core/skills.js +25 -1
  125. package/dist/core/skills.js.map +1 -1
  126. package/dist/core/slash-commands.d.ts +2 -3
  127. package/dist/core/slash-commands.d.ts.map +1 -1
  128. package/dist/core/slash-commands.js.map +1 -1
  129. package/dist/core/source-info.d.ts +18 -0
  130. package/dist/core/source-info.d.ts.map +1 -0
  131. package/dist/core/source-info.js +19 -0
  132. package/dist/core/source-info.js.map +1 -0
  133. package/dist/core/system-prompt.d.ts.map +1 -1
  134. package/dist/core/system-prompt.js +3 -38
  135. package/dist/core/system-prompt.js.map +1 -1
  136. package/dist/core/timings.d.ts +1 -0
  137. package/dist/core/timings.d.ts.map +1 -1
  138. package/dist/core/timings.js +6 -0
  139. package/dist/core/timings.js.map +1 -1
  140. package/dist/core/tools/bash.d.ts +20 -10
  141. package/dist/core/tools/bash.d.ts.map +1 -1
  142. package/dist/core/tools/bash.js +151 -59
  143. package/dist/core/tools/bash.js.map +1 -1
  144. package/dist/core/tools/edit-diff.d.ts +23 -1
  145. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  146. package/dist/core/tools/edit-diff.js +150 -57
  147. package/dist/core/tools/edit-diff.js.map +1 -1
  148. package/dist/core/tools/edit.d.ts +31 -7
  149. package/dist/core/tools/edit.d.ts.map +1 -1
  150. package/dist/core/tools/edit.js +179 -59
  151. package/dist/core/tools/edit.js.map +1 -1
  152. package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
  153. package/dist/core/tools/file-mutation-queue.js +4 -4
  154. package/dist/core/tools/file-mutation-queue.js.map +1 -1
  155. package/dist/core/tools/find.d.ts +12 -5
  156. package/dist/core/tools/find.d.ts.map +1 -1
  157. package/dist/core/tools/find.js +76 -27
  158. package/dist/core/tools/find.js.map +1 -1
  159. package/dist/core/tools/grep.d.ts +16 -5
  160. package/dist/core/tools/grep.d.ts.map +1 -1
  161. package/dist/core/tools/grep.js +83 -29
  162. package/dist/core/tools/grep.js.map +1 -1
  163. package/dist/core/tools/index.d.ts +68 -22
  164. package/dist/core/tools/index.d.ts.map +1 -1
  165. package/dist/core/tools/index.js +50 -26
  166. package/dist/core/tools/index.js.map +1 -1
  167. package/dist/core/tools/ls.d.ts +10 -4
  168. package/dist/core/tools/ls.d.ts.map +1 -1
  169. package/dist/core/tools/ls.js +67 -13
  170. package/dist/core/tools/ls.js.map +1 -1
  171. package/dist/core/tools/read.d.ts +11 -4
  172. package/dist/core/tools/read.d.ts.map +1 -1
  173. package/dist/core/tools/read.js +110 -51
  174. package/dist/core/tools/read.js.map +1 -1
  175. package/dist/core/tools/render-utils.d.ts +21 -0
  176. package/dist/core/tools/render-utils.d.ts.map +1 -0
  177. package/dist/core/tools/render-utils.js +49 -0
  178. package/dist/core/tools/render-utils.js.map +1 -0
  179. package/dist/core/tools/tool-definition-wrapper.d.ts +14 -0
  180. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -0
  181. package/dist/core/tools/tool-definition-wrapper.js +30 -0
  182. package/dist/core/tools/tool-definition-wrapper.js.map +1 -0
  183. package/dist/core/tools/write.d.ts +10 -4
  184. package/dist/core/tools/write.d.ts.map +1 -1
  185. package/dist/core/tools/write.js +162 -27
  186. package/dist/core/tools/write.js.map +1 -1
  187. package/dist/index.d.ts +3 -2
  188. package/dist/index.d.ts.map +1 -1
  189. package/dist/index.js +2 -1
  190. package/dist/index.js.map +1 -1
  191. package/dist/main.d.ts.map +1 -1
  192. package/dist/main.js +57 -19
  193. package/dist/main.js.map +1 -1
  194. package/dist/modes/interactive/components/armin.d.ts +1 -1
  195. package/dist/modes/interactive/components/armin.d.ts.map +1 -1
  196. package/dist/modes/interactive/components/armin.js.map +1 -1
  197. package/dist/modes/interactive/components/assistant-message.d.ts +2 -2
  198. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  199. package/dist/modes/interactive/components/assistant-message.js +1 -1
  200. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  201. package/dist/modes/interactive/components/bash-execution.d.ts +1 -2
  202. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  203. package/dist/modes/interactive/components/bash-execution.js +19 -6
  204. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  205. package/dist/modes/interactive/components/bordered-loader.d.ts +1 -1
  206. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
  207. package/dist/modes/interactive/components/bordered-loader.js +1 -1
  208. package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
  209. package/dist/modes/interactive/components/branch-summary-message.d.ts +1 -1
  210. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  211. package/dist/modes/interactive/components/branch-summary-message.js +1 -1
  212. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  213. package/dist/modes/interactive/components/compaction-summary-message.d.ts +1 -1
  214. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  215. package/dist/modes/interactive/components/compaction-summary-message.js +1 -1
  216. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  217. package/dist/modes/interactive/components/config-selector.d.ts +1 -1
  218. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  219. package/dist/modes/interactive/components/config-selector.js +1 -1
  220. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  221. package/dist/modes/interactive/components/countdown-timer.d.ts +1 -1
  222. package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -1
  223. package/dist/modes/interactive/components/countdown-timer.js.map +1 -1
  224. package/dist/modes/interactive/components/custom-editor.d.ts +1 -1
  225. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  226. package/dist/modes/interactive/components/custom-editor.js +1 -1
  227. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  228. package/dist/modes/interactive/components/custom-message.d.ts +1 -1
  229. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  230. package/dist/modes/interactive/components/custom-message.js +1 -1
  231. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  232. package/dist/modes/interactive/components/daxnuts.d.ts +1 -1
  233. package/dist/modes/interactive/components/daxnuts.d.ts.map +1 -1
  234. package/dist/modes/interactive/components/daxnuts.js.map +1 -1
  235. package/dist/modes/interactive/components/dynamic-border.d.ts +1 -1
  236. package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
  237. package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  238. package/dist/modes/interactive/components/extension-editor.d.ts +1 -1
  239. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  240. package/dist/modes/interactive/components/extension-editor.js +1 -1
  241. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  242. package/dist/modes/interactive/components/extension-input.d.ts +1 -1
  243. package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  244. package/dist/modes/interactive/components/extension-input.js +1 -1
  245. package/dist/modes/interactive/components/extension-input.js.map +1 -1
  246. package/dist/modes/interactive/components/extension-selector.d.ts +1 -1
  247. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  248. package/dist/modes/interactive/components/extension-selector.js +1 -1
  249. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  250. package/dist/modes/interactive/components/footer.d.ts +1 -1
  251. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  252. package/dist/modes/interactive/components/footer.js +1 -1
  253. package/dist/modes/interactive/components/footer.js.map +1 -1
  254. package/dist/modes/interactive/components/keybinding-hints.d.ts +1 -1
  255. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  256. package/dist/modes/interactive/components/keybinding-hints.js +1 -1
  257. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  258. package/dist/modes/interactive/components/login-dialog.d.ts +1 -1
  259. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  260. package/dist/modes/interactive/components/login-dialog.js +2 -2
  261. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  262. package/dist/modes/interactive/components/model-selector.d.ts +2 -2
  263. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  264. package/dist/modes/interactive/components/model-selector.js +2 -2
  265. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  266. package/dist/modes/interactive/components/oauth-selector.d.ts +1 -1
  267. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  268. package/dist/modes/interactive/components/oauth-selector.js +2 -2
  269. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  270. package/dist/modes/interactive/components/scoped-models-selector.d.ts +2 -2
  271. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  272. package/dist/modes/interactive/components/scoped-models-selector.js +1 -1
  273. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  274. package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
  275. package/dist/modes/interactive/components/session-selector-search.js +1 -1
  276. package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
  277. package/dist/modes/interactive/components/session-selector.d.ts +1 -1
  278. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  279. package/dist/modes/interactive/components/session-selector.js +1 -1
  280. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  281. package/dist/modes/interactive/components/settings-selector.d.ts +3 -3
  282. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  283. package/dist/modes/interactive/components/settings-selector.js +1 -1
  284. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  285. package/dist/modes/interactive/components/show-images-selector.d.ts +1 -1
  286. package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
  287. package/dist/modes/interactive/components/show-images-selector.js +1 -1
  288. package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
  289. package/dist/modes/interactive/components/skill-invocation-message.d.ts +1 -1
  290. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  291. package/dist/modes/interactive/components/skill-invocation-message.js +1 -1
  292. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  293. package/dist/modes/interactive/components/theme-selector.d.ts +1 -1
  294. package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
  295. package/dist/modes/interactive/components/theme-selector.js +1 -1
  296. package/dist/modes/interactive/components/theme-selector.js.map +1 -1
  297. package/dist/modes/interactive/components/thinking-selector.d.ts +2 -2
  298. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  299. package/dist/modes/interactive/components/thinking-selector.js +1 -1
  300. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  301. package/dist/modes/interactive/components/tool-execution.d.ts +15 -41
  302. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  303. package/dist/modes/interactive/components/tool-execution.js +121 -679
  304. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  305. package/dist/modes/interactive/components/tree-selector.d.ts +1 -1
  306. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  307. package/dist/modes/interactive/components/tree-selector.js +1 -1
  308. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  309. package/dist/modes/interactive/components/user-message-selector.d.ts +1 -1
  310. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
  311. package/dist/modes/interactive/components/user-message-selector.js +1 -1
  312. package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
  313. package/dist/modes/interactive/components/user-message.d.ts +1 -1
  314. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  315. package/dist/modes/interactive/components/user-message.js +1 -1
  316. package/dist/modes/interactive/components/user-message.js.map +1 -1
  317. package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -1
  318. package/dist/modes/interactive/components/visual-truncate.js +1 -1
  319. package/dist/modes/interactive/components/visual-truncate.js.map +1 -1
  320. package/dist/modes/interactive/interactive-mode.d.ts +5 -13
  321. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  322. package/dist/modes/interactive/interactive-mode.js +175 -160
  323. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  324. package/dist/modes/interactive/theme/theme.d.ts +5 -2
  325. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  326. package/dist/modes/interactive/theme/theme.js +15 -1
  327. package/dist/modes/interactive/theme/theme.js.map +1 -1
  328. package/dist/modes/print-mode.d.ts +2 -2
  329. package/dist/modes/print-mode.d.ts.map +1 -1
  330. package/dist/modes/print-mode.js +84 -78
  331. package/dist/modes/print-mode.js.map +1 -1
  332. package/dist/modes/rpc/rpc-client.d.ts +2 -2
  333. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  334. package/dist/modes/rpc/rpc-client.js.map +1 -1
  335. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  336. package/dist/modes/rpc/rpc-mode.js +27 -20
  337. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  338. package/dist/modes/rpc/rpc-types.d.ts +5 -6
  339. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  340. package/dist/modes/rpc/rpc-types.js.map +1 -1
  341. package/dist/utils/image-resize.d.ts +6 -6
  342. package/dist/utils/image-resize.d.ts.map +1 -1
  343. package/dist/utils/image-resize.js +45 -94
  344. package/dist/utils/image-resize.js.map +1 -1
  345. package/docs/development.md +3 -1
  346. package/docs/extensions.md +85 -34
  347. package/docs/models.md +6 -0
  348. package/docs/rpc.md +11 -2
  349. package/docs/settings.md +12 -0
  350. package/docs/skills.md +3 -2
  351. package/docs/tui.md +2 -2
  352. package/examples/extensions/built-in-tool-renderer.ts +8 -8
  353. package/examples/extensions/commands.ts +3 -3
  354. package/examples/extensions/custom-compaction.ts +17 -4
  355. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  356. package/examples/extensions/custom-provider-anthropic/package.json +17 -17
  357. package/examples/extensions/custom-provider-gitlab-duo/package.json +14 -14
  358. package/examples/extensions/custom-provider-qwen-cli/package.json +14 -14
  359. package/examples/extensions/handoff.ts +5 -2
  360. package/examples/extensions/minimal-mode.ts +14 -14
  361. package/examples/extensions/qna.ts +5 -2
  362. package/examples/extensions/question.ts +2 -2
  363. package/examples/extensions/questionnaire.ts +2 -2
  364. package/examples/extensions/subagent/index.ts +23 -3
  365. package/examples/extensions/summarize.ts +15 -4
  366. package/examples/extensions/todo.ts +2 -2
  367. package/examples/extensions/trigger-compact.ts +11 -1
  368. package/examples/extensions/truncated-tool.ts +2 -2
  369. package/examples/extensions/with-deps/package-lock.json +2 -2
  370. package/examples/extensions/with-deps/package.json +20 -20
  371. package/examples/sdk/04-skills.ts +8 -2
  372. package/examples/sdk/08-prompt-templates.ts +2 -1
  373. package/examples/sdk/12-full-control.ts +0 -1
  374. package/package.json +5 -4
@@ -6,7 +6,7 @@ import * as crypto from "node:crypto";
6
6
  import * as fs from "node:fs";
7
7
  import * as os from "node:os";
8
8
  import * as path from "node:path";
9
- import { CombinedAutocompleteProvider, Container, fuzzyFilter, Loader, Markdown, matchesKey, ProcessTerminal, Spacer, setKeybindings, Text, TruncatedText, TUI, visibleWidth, } from "@mariozechner/pi-tui";
9
+ import { CombinedAutocompleteProvider, Container, fuzzyFilter, Loader, Markdown, matchesKey, ProcessTerminal, Spacer, setKeybindings, Text, TruncatedText, TUI, visibleWidth, } from "@hyperspaceng/neural-tui";
10
10
  import { spawn, spawnSync } from "child_process";
11
11
  import { APP_NAME, getAgentDir, getAuthPath, getDebugLogPath, getShareViewerUrl, getUpdateInstruction, VERSION, } from "../../config.js";
12
12
  import { parseSkillBlock } from "../../core/agent-session.js";
@@ -20,6 +20,7 @@ import { BUILTIN_SLASH_COMMANDS } from "../../core/slash-commands.js";
20
20
  import { getChangelogPath, getNewEntries, parseChangelog } from "../../utils/changelog.js";
21
21
  import { copyToClipboard } from "../../utils/clipboard.js";
22
22
  import { extensionForImageMimeType, readClipboardImage } from "../../utils/clipboard-image.js";
23
+ import { parseGitUrl } from "../../utils/git.js";
23
24
  import { ensureTool } from "../../utils/tools-manager.js";
24
25
  import { ArminComponent } from "./components/armin.js";
25
26
  import { AssistantMessageComponent } from "./components/assistant-message.js";
@@ -168,6 +169,48 @@ export class InteractiveMode {
168
169
  setRegisteredThemes(this.session.resourceLoader.getThemes().themes);
169
170
  initTheme(this.settingsManager.getTheme(), true);
170
171
  }
172
+ getAutocompleteSourceTag(sourceInfo) {
173
+ if (!sourceInfo) {
174
+ return undefined;
175
+ }
176
+ const scopePrefix = sourceInfo.scope === "user" ? "u" : sourceInfo.scope === "project" ? "p" : "t";
177
+ const source = sourceInfo.source.trim();
178
+ if (source === "auto" || source === "local" || source === "cli") {
179
+ return scopePrefix;
180
+ }
181
+ if (source.startsWith("npm:")) {
182
+ return `${scopePrefix}:${source}`;
183
+ }
184
+ const gitSource = parseGitUrl(source);
185
+ if (gitSource) {
186
+ const ref = gitSource.ref ? `@${gitSource.ref}` : "";
187
+ return `${scopePrefix}:git:${gitSource.host}/${gitSource.path}${ref}`;
188
+ }
189
+ return scopePrefix;
190
+ }
191
+ prefixAutocompleteDescription(description, sourceInfo) {
192
+ const sourceTag = this.getAutocompleteSourceTag(sourceInfo);
193
+ if (!sourceTag) {
194
+ return description;
195
+ }
196
+ return description ? `[${sourceTag}] ${description}` : `[${sourceTag}]`;
197
+ }
198
+ getBuiltInCommandConflictDiagnostics(extensionRunner) {
199
+ if (!extensionRunner) {
200
+ return [];
201
+ }
202
+ const builtinNames = new Set(BUILTIN_SLASH_COMMANDS.map((command) => command.name));
203
+ return extensionRunner
204
+ .getRegisteredCommands()
205
+ .filter((command) => builtinNames.has(command.name))
206
+ .map((command) => ({
207
+ type: "warning",
208
+ message: command.invocationName === command.name
209
+ ? `Extension command '/${command.name}' conflicts with built-in interactive command. Skipping in autocomplete.`
210
+ : `Extension command '/${command.name}' conflicts with built-in interactive command. Available as '/${command.invocationName}'.`,
211
+ path: command.sourceInfo.path,
212
+ }));
213
+ }
171
214
  setupAutocomplete(fdPath) {
172
215
  // Define commands for autocomplete
173
216
  const slashCommands = BUILTIN_SLASH_COMMANDS.map((command) => ({
@@ -203,13 +246,13 @@ export class InteractiveMode {
203
246
  // Convert prompt templates to SlashCommand format for autocomplete
204
247
  const templateCommands = this.session.promptTemplates.map((cmd) => ({
205
248
  name: cmd.name,
206
- description: cmd.description,
249
+ description: this.prefixAutocompleteDescription(cmd.description, cmd.sourceInfo),
207
250
  }));
208
251
  // Convert extension commands to SlashCommand format
209
252
  const builtinCommandNames = new Set(slashCommands.map((c) => c.name));
210
- const extensionCommands = (this.session.extensionRunner?.getRegisteredCommands(builtinCommandNames) ?? []).map((cmd) => ({
211
- name: cmd.name,
212
- description: cmd.description ?? "(extension command)",
253
+ const extensionCommands = (this.session.extensionRunner?.getRegisteredCommands().filter((cmd) => !builtinCommandNames.has(cmd.name)) ?? []).map((cmd) => ({
254
+ name: cmd.invocationName,
255
+ description: this.prefixAutocompleteDescription(cmd.description, cmd.sourceInfo),
213
256
  getArgumentCompletions: cmd.getArgumentCompletions,
214
257
  }));
215
258
  // Build skill commands from session.skills (if enabled)
@@ -219,7 +262,10 @@ export class InteractiveMode {
219
262
  for (const skill of this.session.resourceLoader.getSkills().skills) {
220
263
  const commandName = `skill:${skill.name}`;
221
264
  this.skillCommands.set(commandName, skill.filePath);
222
- skillCommandList.push({ name: commandName, description: skill.description });
265
+ skillCommandList.push({
266
+ name: commandName,
267
+ description: this.prefixAutocompleteDescription(skill.description, skill.sourceInfo),
268
+ });
223
269
  }
224
270
  }
225
271
  // Setup autocomplete
@@ -266,7 +312,8 @@ export class InteractiveMode {
266
312
  hint("app.clipboard.pasteImage", "to paste image"),
267
313
  rawKeyHint("drop files", "to attach"),
268
314
  ].join("\n");
269
- this.builtInHeader = new Text(`${logo}\n${instructions}`, 1, 0);
315
+ const onboarding = theme.fg("dim", `Pi can explain its own features and look up its docs. Ask it how to use or extend Pi.`);
316
+ this.builtInHeader = new Text(`${logo}\n${instructions}\n\n${onboarding}`, 1, 0);
270
317
  // Setup UI layout
271
318
  this.headerContainer.addChild(new Spacer(1));
272
319
  this.headerContainer.addChild(this.builtInHeader);
@@ -426,7 +473,7 @@ export class InteractiveMode {
426
473
  if (process.env.PI_SKIP_VERSION_CHECK || process.env.PI_OFFLINE)
427
474
  return undefined;
428
475
  try {
429
- const response = await fetch("https://registry.npmjs.org/@mariozechner/pi-coding-agent/latest", {
476
+ const response = await fetch("https://registry.npmjs.org/@hyperspaceng/neural-coding-agent/latest", {
430
477
  signal: AbortSignal.timeout(10000),
431
478
  });
432
479
  if (!response.ok)
@@ -547,21 +594,21 @@ export class InteractiveMode {
547
594
  /**
548
595
  * Get a short path relative to the package root for display.
549
596
  */
550
- getShortPath(fullPath, source) {
551
- // For npm packages, show path relative to node_modules/pkg/
597
+ getShortPath(fullPath, sourceInfo) {
598
+ const source = sourceInfo?.source ?? "";
552
599
  const npmMatch = fullPath.match(/node_modules\/(@?[^/]+(?:\/[^/]+)?)\/(.*)/);
553
600
  if (npmMatch && source.startsWith("npm:")) {
554
601
  return npmMatch[2];
555
602
  }
556
- // For git packages, show path relative to repo root
557
603
  const gitMatch = fullPath.match(/git\/[^/]+\/[^/]+\/(.*)/);
558
604
  if (gitMatch && source.startsWith("git:")) {
559
605
  return gitMatch[1];
560
606
  }
561
- // For local/auto, just use formatDisplayPath
562
607
  return this.formatDisplayPath(fullPath);
563
608
  }
564
- getDisplaySourceInfo(source, scope) {
609
+ getDisplaySourceInfo(sourceInfo) {
610
+ const source = sourceInfo?.source ?? "local";
611
+ const scope = sourceInfo?.scope ?? "project";
565
612
  if (source === "local") {
566
613
  if (scope === "user") {
567
614
  return { label: "user", color: "muted" };
@@ -580,7 +627,9 @@ export class InteractiveMode {
580
627
  const scopeLabel = scope === "user" ? "user" : scope === "project" ? "project" : scope === "temporary" ? "temp" : undefined;
581
628
  return { label: source, scopeLabel, color: "accent" };
582
629
  }
583
- getScopeGroup(source, scope) {
630
+ getScopeGroup(sourceInfo) {
631
+ const source = sourceInfo?.source ?? "local";
632
+ const scope = sourceInfo?.scope ?? "project";
584
633
  if (source === "cli" || scope === "temporary")
585
634
  return "path";
586
635
  if (scope === "user")
@@ -589,28 +638,27 @@ export class InteractiveMode {
589
638
  return "project";
590
639
  return "path";
591
640
  }
592
- isPackageSource(source) {
641
+ isPackageSource(sourceInfo) {
642
+ const source = sourceInfo?.source ?? "";
593
643
  return source.startsWith("npm:") || source.startsWith("git:");
594
644
  }
595
- buildScopeGroups(paths, metadata) {
645
+ buildScopeGroups(items) {
596
646
  const groups = {
597
647
  user: { scope: "user", paths: [], packages: new Map() },
598
648
  project: { scope: "project", paths: [], packages: new Map() },
599
649
  path: { scope: "path", paths: [], packages: new Map() },
600
650
  };
601
- for (const p of paths) {
602
- const meta = this.findMetadata(p, metadata);
603
- const source = meta?.source ?? "local";
604
- const scope = meta?.scope ?? "project";
605
- const groupKey = this.getScopeGroup(source, scope);
651
+ for (const item of items) {
652
+ const groupKey = this.getScopeGroup(item.sourceInfo);
606
653
  const group = groups[groupKey];
607
- if (this.isPackageSource(source)) {
654
+ const source = item.sourceInfo?.source ?? "local";
655
+ if (this.isPackageSource(item.sourceInfo)) {
608
656
  const list = group.packages.get(source) ?? [];
609
- list.push(p);
657
+ list.push(item);
610
658
  group.packages.set(source, list);
611
659
  }
612
660
  else {
613
- group.paths.push(p);
661
+ group.paths.push(item);
614
662
  }
615
663
  }
616
664
  return [groups.project, groups.user, groups.path].filter((group) => group.paths.length > 0 || group.packages.size > 0);
@@ -619,57 +667,44 @@ export class InteractiveMode {
619
667
  const lines = [];
620
668
  for (const group of groups) {
621
669
  lines.push(` ${theme.fg("accent", group.scope)}`);
622
- const sortedPaths = [...group.paths].sort((a, b) => a.localeCompare(b));
623
- for (const p of sortedPaths) {
624
- lines.push(theme.fg("dim", ` ${options.formatPath(p)}`));
670
+ const sortedPaths = [...group.paths].sort((a, b) => a.path.localeCompare(b.path));
671
+ for (const item of sortedPaths) {
672
+ lines.push(theme.fg("dim", ` ${options.formatPath(item)}`));
625
673
  }
626
674
  const sortedPackages = Array.from(group.packages.entries()).sort(([a], [b]) => a.localeCompare(b));
627
- for (const [source, paths] of sortedPackages) {
675
+ for (const [source, items] of sortedPackages) {
628
676
  lines.push(` ${theme.fg("mdLink", source)}`);
629
- const sortedPackagePaths = [...paths].sort((a, b) => a.localeCompare(b));
630
- for (const p of sortedPackagePaths) {
631
- lines.push(theme.fg("dim", ` ${options.formatPackagePath(p, source)}`));
677
+ const sortedPackagePaths = [...items].sort((a, b) => a.path.localeCompare(b.path));
678
+ for (const item of sortedPackagePaths) {
679
+ lines.push(theme.fg("dim", ` ${options.formatPackagePath(item, source)}`));
632
680
  }
633
681
  }
634
682
  }
635
683
  return lines.join("\n");
636
684
  }
637
- /**
638
- * Find metadata for a path, checking parent directories if exact match fails.
639
- * Package manager stores metadata for directories, but we display file paths.
640
- */
641
- findMetadata(p, metadata) {
642
- // Try exact match first
643
- const exact = metadata.get(p);
685
+ findSourceInfoForPath(p, sourceInfos) {
686
+ const exact = sourceInfos.get(p);
644
687
  if (exact)
645
688
  return exact;
646
- // Try parent directories (package manager stores directory paths)
647
689
  let current = p;
648
690
  while (current.includes("/")) {
649
691
  current = current.substring(0, current.lastIndexOf("/"));
650
- const parent = metadata.get(current);
692
+ const parent = sourceInfos.get(current);
651
693
  if (parent)
652
694
  return parent;
653
695
  }
654
696
  return undefined;
655
697
  }
656
- /**
657
- * Format a path with its source/scope info from metadata.
658
- */
659
- formatPathWithSource(p, metadata) {
660
- const meta = this.findMetadata(p, metadata);
661
- if (meta) {
662
- const shortPath = this.getShortPath(p, meta.source);
663
- const { label, scopeLabel } = this.getDisplaySourceInfo(meta.source, meta.scope);
698
+ formatPathWithSource(p, sourceInfo) {
699
+ if (sourceInfo) {
700
+ const shortPath = this.getShortPath(p, sourceInfo);
701
+ const { label, scopeLabel } = this.getDisplaySourceInfo(sourceInfo);
664
702
  const labelText = scopeLabel ? `${label} (${scopeLabel})` : label;
665
703
  return `${labelText} ${shortPath}`;
666
704
  }
667
705
  return this.formatDisplayPath(p);
668
706
  }
669
- /**
670
- * Format resource diagnostics with nice collision display using metadata.
671
- */
672
- formatDiagnostics(diagnostics, metadata) {
707
+ formatDiagnostics(diagnostics, sourceInfos) {
673
708
  const lines = [];
674
709
  // Group collision diagnostics by name
675
710
  const collisions = new Map();
@@ -690,21 +725,17 @@ export class InteractiveMode {
690
725
  if (!first)
691
726
  continue;
692
727
  lines.push(theme.fg("warning", ` "${name}" collision:`));
693
- // Show winner
694
- lines.push(theme.fg("dim", ` ${theme.fg("success", "✓")} ${this.formatPathWithSource(first.winnerPath, metadata)}`));
695
- // Show all losers
728
+ lines.push(theme.fg("dim", ` ${theme.fg("success", "✓")} ${this.formatPathWithSource(first.winnerPath, this.findSourceInfoForPath(first.winnerPath, sourceInfos))}`));
696
729
  for (const d of collisionList) {
697
730
  if (d.collision) {
698
- lines.push(theme.fg("dim", ` ${theme.fg("warning", "✗")} ${this.formatPathWithSource(d.collision.loserPath, metadata)} (skipped)`));
731
+ lines.push(theme.fg("dim", ` ${theme.fg("warning", "✗")} ${this.formatPathWithSource(d.collision.loserPath, this.findSourceInfoForPath(d.collision.loserPath, sourceInfos))} (skipped)`));
699
732
  }
700
733
  }
701
734
  }
702
- // Format other diagnostics (skill name collisions, parse errors, etc.)
703
735
  for (const d of otherDiagnostics) {
704
736
  if (d.path) {
705
- // Use metadata-aware formatting for paths
706
- const sourceInfo = this.formatPathWithSource(d.path, metadata);
707
- lines.push(theme.fg(d.type === "error" ? "error" : "warning", ` ${sourceInfo}`));
737
+ const formattedPath = this.formatPathWithSource(d.path, this.findSourceInfoForPath(d.path, sourceInfos));
738
+ lines.push(theme.fg(d.type === "error" ? "error" : "warning", ` ${formattedPath}`));
708
739
  lines.push(theme.fg(d.type === "error" ? "error" : "warning", ` ${d.message}`));
709
740
  }
710
741
  else {
@@ -719,11 +750,36 @@ export class InteractiveMode {
719
750
  if (!showListing && !showDiagnostics) {
720
751
  return;
721
752
  }
722
- const metadata = this.session.resourceLoader.getPathMetadata();
723
753
  const sectionHeader = (name, color = "mdHeading") => theme.fg(color, `[${name}]`);
724
754
  const skillsResult = this.session.resourceLoader.getSkills();
725
755
  const promptsResult = this.session.resourceLoader.getPrompts();
726
756
  const themesResult = this.session.resourceLoader.getThemes();
757
+ const extensions = options?.extensions ??
758
+ this.session.resourceLoader.getExtensions().extensions.map((extension) => ({
759
+ path: extension.path,
760
+ sourceInfo: extension.sourceInfo,
761
+ }));
762
+ const sourceInfos = new Map();
763
+ for (const extension of extensions) {
764
+ if (extension.sourceInfo) {
765
+ sourceInfos.set(extension.path, extension.sourceInfo);
766
+ }
767
+ }
768
+ for (const skill of skillsResult.skills) {
769
+ if (skill.sourceInfo) {
770
+ sourceInfos.set(skill.filePath, skill.sourceInfo);
771
+ }
772
+ }
773
+ for (const prompt of promptsResult.prompts) {
774
+ if (prompt.sourceInfo) {
775
+ sourceInfos.set(prompt.filePath, prompt.sourceInfo);
776
+ }
777
+ }
778
+ for (const loadedTheme of themesResult.themes) {
779
+ if (loadedTheme.sourcePath && loadedTheme.sourceInfo) {
780
+ sourceInfos.set(loadedTheme.sourcePath, loadedTheme.sourceInfo);
781
+ }
782
+ }
727
783
  if (showListing) {
728
784
  const contextFiles = this.session.resourceLoader.getAgentsFiles().agentsFiles;
729
785
  if (contextFiles.length > 0) {
@@ -736,39 +792,36 @@ export class InteractiveMode {
736
792
  }
737
793
  const skills = skillsResult.skills;
738
794
  if (skills.length > 0) {
739
- const skillPaths = skills.map((s) => s.filePath);
740
- const groups = this.buildScopeGroups(skillPaths, metadata);
795
+ const groups = this.buildScopeGroups(skills.map((skill) => ({ path: skill.filePath, sourceInfo: skill.sourceInfo })));
741
796
  const skillList = this.formatScopeGroups(groups, {
742
- formatPath: (p) => this.formatDisplayPath(p),
743
- formatPackagePath: (p, source) => this.getShortPath(p, source),
797
+ formatPath: (item) => this.formatDisplayPath(item.path),
798
+ formatPackagePath: (item) => this.getShortPath(item.path, item.sourceInfo),
744
799
  });
745
800
  this.chatContainer.addChild(new Text(`${sectionHeader("Skills")}\n${skillList}`, 0, 0));
746
801
  this.chatContainer.addChild(new Spacer(1));
747
802
  }
748
803
  const templates = this.session.promptTemplates;
749
804
  if (templates.length > 0) {
750
- const templatePaths = templates.map((t) => t.filePath);
751
- const groups = this.buildScopeGroups(templatePaths, metadata);
805
+ const groups = this.buildScopeGroups(templates.map((template) => ({ path: template.filePath, sourceInfo: template.sourceInfo })));
752
806
  const templateByPath = new Map(templates.map((t) => [t.filePath, t]));
753
807
  const templateList = this.formatScopeGroups(groups, {
754
- formatPath: (p) => {
755
- const template = templateByPath.get(p);
756
- return template ? `/${template.name}` : this.formatDisplayPath(p);
808
+ formatPath: (item) => {
809
+ const template = templateByPath.get(item.path);
810
+ return template ? `/${template.name}` : this.formatDisplayPath(item.path);
757
811
  },
758
- formatPackagePath: (p) => {
759
- const template = templateByPath.get(p);
760
- return template ? `/${template.name}` : this.formatDisplayPath(p);
812
+ formatPackagePath: (item) => {
813
+ const template = templateByPath.get(item.path);
814
+ return template ? `/${template.name}` : this.formatDisplayPath(item.path);
761
815
  },
762
816
  });
763
817
  this.chatContainer.addChild(new Text(`${sectionHeader("Prompts")}\n${templateList}`, 0, 0));
764
818
  this.chatContainer.addChild(new Spacer(1));
765
819
  }
766
- const extensionPaths = options?.extensionPaths ?? [];
767
- if (extensionPaths.length > 0) {
768
- const groups = this.buildScopeGroups(extensionPaths, metadata);
820
+ if (extensions.length > 0) {
821
+ const groups = this.buildScopeGroups(extensions);
769
822
  const extList = this.formatScopeGroups(groups, {
770
- formatPath: (p) => this.formatDisplayPath(p),
771
- formatPackagePath: (p, source) => this.getShortPath(p, source),
823
+ formatPath: (item) => this.formatDisplayPath(item.path),
824
+ formatPackagePath: (item) => this.getShortPath(item.path, item.sourceInfo),
772
825
  });
773
826
  this.chatContainer.addChild(new Text(`${sectionHeader("Extensions", "mdHeading")}\n${extList}`, 0, 0));
774
827
  this.chatContainer.addChild(new Spacer(1));
@@ -777,11 +830,13 @@ export class InteractiveMode {
777
830
  const loadedThemes = themesResult.themes;
778
831
  const customThemes = loadedThemes.filter((t) => t.sourcePath);
779
832
  if (customThemes.length > 0) {
780
- const themePaths = customThemes.map((t) => t.sourcePath);
781
- const groups = this.buildScopeGroups(themePaths, metadata);
833
+ const groups = this.buildScopeGroups(customThemes.map((loadedTheme) => ({
834
+ path: loadedTheme.sourcePath,
835
+ sourceInfo: loadedTheme.sourceInfo,
836
+ })));
782
837
  const themeList = this.formatScopeGroups(groups, {
783
- formatPath: (p) => this.formatDisplayPath(p),
784
- formatPackagePath: (p, source) => this.getShortPath(p, source),
838
+ formatPath: (item) => this.formatDisplayPath(item.path),
839
+ formatPackagePath: (item) => this.getShortPath(item.path, item.sourceInfo),
785
840
  });
786
841
  this.chatContainer.addChild(new Text(`${sectionHeader("Themes")}\n${themeList}`, 0, 0));
787
842
  this.chatContainer.addChild(new Spacer(1));
@@ -790,13 +845,13 @@ export class InteractiveMode {
790
845
  if (showDiagnostics) {
791
846
  const skillDiagnostics = skillsResult.diagnostics;
792
847
  if (skillDiagnostics.length > 0) {
793
- const warningLines = this.formatDiagnostics(skillDiagnostics, metadata);
848
+ const warningLines = this.formatDiagnostics(skillDiagnostics, sourceInfos);
794
849
  this.chatContainer.addChild(new Text(`${theme.fg("warning", "[Skill conflicts]")}\n${warningLines}`, 0, 0));
795
850
  this.chatContainer.addChild(new Spacer(1));
796
851
  }
797
852
  const promptDiagnostics = promptsResult.diagnostics;
798
853
  if (promptDiagnostics.length > 0) {
799
- const warningLines = this.formatDiagnostics(promptDiagnostics, metadata);
854
+ const warningLines = this.formatDiagnostics(promptDiagnostics, sourceInfos);
800
855
  this.chatContainer.addChild(new Text(`${theme.fg("warning", "[Prompt conflicts]")}\n${warningLines}`, 0, 0));
801
856
  this.chatContainer.addChild(new Spacer(1));
802
857
  }
@@ -809,16 +864,17 @@ export class InteractiveMode {
809
864
  }
810
865
  const commandDiagnostics = this.session.extensionRunner?.getCommandDiagnostics() ?? [];
811
866
  extensionDiagnostics.push(...commandDiagnostics);
867
+ extensionDiagnostics.push(...this.getBuiltInCommandConflictDiagnostics(this.session.extensionRunner));
812
868
  const shortcutDiagnostics = this.session.extensionRunner?.getShortcutDiagnostics() ?? [];
813
869
  extensionDiagnostics.push(...shortcutDiagnostics);
814
870
  if (extensionDiagnostics.length > 0) {
815
- const warningLines = this.formatDiagnostics(extensionDiagnostics, metadata);
871
+ const warningLines = this.formatDiagnostics(extensionDiagnostics, sourceInfos);
816
872
  this.chatContainer.addChild(new Text(`${theme.fg("warning", "[Extension issues]")}\n${warningLines}`, 0, 0));
817
873
  this.chatContainer.addChild(new Spacer(1));
818
874
  }
819
875
  const themeDiagnostics = themesResult.diagnostics;
820
876
  if (themeDiagnostics.length > 0) {
821
- const warningLines = this.formatDiagnostics(themeDiagnostics, metadata);
877
+ const warningLines = this.formatDiagnostics(themeDiagnostics, sourceInfos);
822
878
  this.chatContainer.addChild(new Text(`${theme.fg("warning", "[Theme conflicts]")}\n${warningLines}`, 0, 0));
823
879
  this.chatContainer.addChild(new Spacer(1));
824
880
  }
@@ -907,19 +963,17 @@ export class InteractiveMode {
907
963
  this.setupAutocomplete(this.fdPath);
908
964
  const extensionRunner = this.session.extensionRunner;
909
965
  if (!extensionRunner) {
910
- this.showLoadedResources({ extensionPaths: [], force: false });
966
+ this.showLoadedResources({ extensions: [], force: false });
911
967
  return;
912
968
  }
913
969
  this.setupExtensionShortcuts(extensionRunner);
914
- this.showLoadedResources({ extensionPaths: extensionRunner.getExtensionPaths(), force: false });
970
+ this.showLoadedResources({ force: false });
915
971
  }
916
972
  /**
917
973
  * Get a registered tool definition by name (for custom rendering).
918
974
  */
919
975
  getRegisteredToolDefinition(toolName) {
920
- const tools = this.session.extensionRunner?.getAllRegisteredTools() ?? [];
921
- const registeredTool = tools.find((t) => t.definition.name === toolName);
922
- return registeredTool?.definition;
976
+ return this.session.getToolDefinition(toolName);
923
977
  }
924
978
  /**
925
979
  * Set up keyboard shortcuts registered by extensions.
@@ -946,10 +1000,8 @@ export class InteractiveMode {
946
1000
  compact: (options) => {
947
1001
  void (async () => {
948
1002
  try {
949
- const result = await this.executeCompaction(options?.customInstructions, false);
950
- if (result) {
951
- options?.onComplete?.(result);
952
- }
1003
+ const result = await this.session.compact(options?.customInstructions);
1004
+ options?.onComplete?.(result);
953
1005
  }
954
1006
  catch (error) {
955
1007
  const err = error instanceof Error ? error : new Error(String(error));
@@ -1809,7 +1861,7 @@ export class InteractiveMode {
1809
1861
  for (const content of this.streamingMessage.content) {
1810
1862
  if (content.type === "toolCall") {
1811
1863
  if (!this.pendingTools.has(content.id)) {
1812
- const component = new ToolExecutionComponent(content.name, content.arguments, {
1864
+ const component = new ToolExecutionComponent(content.name, content.id, content.arguments, {
1813
1865
  showImages: this.settingsManager.getShowImages(),
1814
1866
  }, this.getRegisteredToolDefinition(content.name), this.ui);
1815
1867
  component.setExpanded(this.toolOutputExpanded);
@@ -1869,7 +1921,7 @@ export class InteractiveMode {
1869
1921
  case "tool_execution_start": {
1870
1922
  let component = this.pendingTools.get(event.toolCallId);
1871
1923
  if (!component) {
1872
- component = new ToolExecutionComponent(event.toolName, event.args, {
1924
+ component = new ToolExecutionComponent(event.toolName, event.toolCallId, event.args, {
1873
1925
  showImages: this.settingsManager.getShowImages(),
1874
1926
  }, this.getRegisteredToolDefinition(event.toolName), this.ui);
1875
1927
  component.setExpanded(this.toolOutputExpanded);
@@ -1912,54 +1964,54 @@ export class InteractiveMode {
1912
1964
  await this.checkShutdownRequested();
1913
1965
  this.ui.requestRender();
1914
1966
  break;
1915
- case "auto_compaction_start": {
1967
+ case "compaction_start": {
1916
1968
  // Keep editor active; submissions are queued during compaction.
1917
- // Set up escape to abort auto-compaction
1918
1969
  this.autoCompactionEscapeHandler = this.defaultEditor.onEscape;
1919
1970
  this.defaultEditor.onEscape = () => {
1920
1971
  this.session.abortCompaction();
1921
1972
  };
1922
- // Show compacting indicator with reason
1923
1973
  this.statusContainer.clear();
1924
- const reasonText = event.reason === "overflow" ? "Context overflow detected, " : "";
1925
- this.autoCompactionLoader = new Loader(this.ui, (spinner) => theme.fg("accent", spinner), (text) => theme.fg("muted", text), `${reasonText}Auto-compacting... (${keyText("app.interrupt")} to cancel)`);
1974
+ const cancelHint = `(${keyText("app.interrupt")} to cancel)`;
1975
+ const label = event.reason === "manual"
1976
+ ? `Compacting context... ${cancelHint}`
1977
+ : `${event.reason === "overflow" ? "Context overflow detected, " : ""}Auto-compacting... ${cancelHint}`;
1978
+ this.autoCompactionLoader = new Loader(this.ui, (spinner) => theme.fg("accent", spinner), (text) => theme.fg("muted", text), label);
1926
1979
  this.statusContainer.addChild(this.autoCompactionLoader);
1927
1980
  this.ui.requestRender();
1928
1981
  break;
1929
1982
  }
1930
- case "auto_compaction_end": {
1931
- // Restore escape handler
1983
+ case "compaction_end": {
1932
1984
  if (this.autoCompactionEscapeHandler) {
1933
1985
  this.defaultEditor.onEscape = this.autoCompactionEscapeHandler;
1934
1986
  this.autoCompactionEscapeHandler = undefined;
1935
1987
  }
1936
- // Stop loader
1937
1988
  if (this.autoCompactionLoader) {
1938
1989
  this.autoCompactionLoader.stop();
1939
1990
  this.autoCompactionLoader = undefined;
1940
1991
  this.statusContainer.clear();
1941
1992
  }
1942
- // Handle result
1943
1993
  if (event.aborted) {
1944
- this.showStatus("Auto-compaction cancelled");
1994
+ if (event.reason === "manual") {
1995
+ this.showError("Compaction cancelled");
1996
+ }
1997
+ else {
1998
+ this.showStatus("Auto-compaction cancelled");
1999
+ }
1945
2000
  }
1946
2001
  else if (event.result) {
1947
- // Rebuild chat to show compacted state
1948
2002
  this.chatContainer.clear();
1949
2003
  this.rebuildChatFromMessages();
1950
- // Add compaction component at bottom so user sees it without scrolling
1951
- this.addMessageToChat({
1952
- role: "compactionSummary",
1953
- tokensBefore: event.result.tokensBefore,
1954
- summary: event.result.summary,
1955
- timestamp: Date.now(),
1956
- });
2004
+ this.addMessageToChat(createCompactionSummaryMessage(event.result.summary, event.result.tokensBefore, new Date().toISOString()));
1957
2005
  this.footer.invalidate();
1958
2006
  }
1959
2007
  else if (event.errorMessage) {
1960
- // Compaction failed (e.g., quota exceeded, API error)
1961
- this.chatContainer.addChild(new Spacer(1));
1962
- this.chatContainer.addChild(new Text(theme.fg("error", event.errorMessage), 1, 0));
2008
+ if (event.reason === "manual") {
2009
+ this.showError(event.errorMessage);
2010
+ }
2011
+ else {
2012
+ this.chatContainer.addChild(new Spacer(1));
2013
+ this.chatContainer.addChild(new Text(theme.fg("error", event.errorMessage), 1, 0));
2014
+ }
1963
2015
  }
1964
2016
  void this.flushCompactionQueue({ willRetry: event.willRetry });
1965
2017
  this.ui.requestRender();
@@ -2125,7 +2177,7 @@ export class InteractiveMode {
2125
2177
  // Render tool call components
2126
2178
  for (const content of message.content) {
2127
2179
  if (content.type === "toolCall") {
2128
- const component = new ToolExecutionComponent(content.name, content.arguments, { showImages: this.settingsManager.getShowImages() }, this.getRegisteredToolDefinition(content.name), this.ui);
2180
+ const component = new ToolExecutionComponent(content.name, content.id, content.arguments, { showImages: this.settingsManager.getShowImages() }, this.getRegisteredToolDefinition(content.name), this.ui);
2129
2181
  component.setExpanded(this.toolOutputExpanded);
2130
2182
  this.chatContainer.addChild(component);
2131
2183
  if (message.stopReason === "aborted" || message.stopReason === "error") {
@@ -2434,7 +2486,7 @@ export class InteractiveMode {
2434
2486
  this.ui.requestRender();
2435
2487
  }
2436
2488
  showNewVersionNotification(newVersion) {
2437
- const action = theme.fg("accent", getUpdateInstruction("@mariozechner/pi-coding-agent"));
2489
+ const action = theme.fg("accent", getUpdateInstruction("@hyperspaceng/neural-coding-agent"));
2438
2490
  const updateInstruction = theme.fg("muted", `New version ${newVersion} is available. `) + action;
2439
2491
  const changelogUrl = theme.fg("accent", "https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/CHANGELOG.md");
2440
2492
  const changelogLine = theme.fg("muted", "Changelog: ") + changelogUrl;
@@ -3286,7 +3338,6 @@ export class InteractiveMode {
3286
3338
  this.rebuildChatFromMessages();
3287
3339
  dismissLoader(this.editor);
3288
3340
  this.showLoadedResources({
3289
- extensionPaths: runner?.getExtensionPaths() ?? [],
3290
3341
  force: false,
3291
3342
  showDiagnosticsWhenQuiet: true,
3292
3343
  });
@@ -3800,53 +3851,17 @@ export class InteractiveMode {
3800
3851
  this.showWarning("Nothing to compact (no messages yet)");
3801
3852
  return;
3802
3853
  }
3803
- await this.executeCompaction(customInstructions, false);
3804
- }
3805
- async executeCompaction(customInstructions, isAuto = false) {
3806
- // Stop loading animation
3807
3854
  if (this.loadingAnimation) {
3808
3855
  this.loadingAnimation.stop();
3809
3856
  this.loadingAnimation = undefined;
3810
3857
  }
3811
3858
  this.statusContainer.clear();
3812
- // Set up escape handler during compaction
3813
- const originalOnEscape = this.defaultEditor.onEscape;
3814
- this.defaultEditor.onEscape = () => {
3815
- this.session.abortCompaction();
3816
- };
3817
- // Show compacting status
3818
- this.chatContainer.addChild(new Spacer(1));
3819
- const cancelHint = `(${keyText("app.interrupt")} to cancel)`;
3820
- const label = isAuto ? `Auto-compacting context... ${cancelHint}` : `Compacting context... ${cancelHint}`;
3821
- const compactingLoader = new Loader(this.ui, (spinner) => theme.fg("accent", spinner), (text) => theme.fg("muted", text), label);
3822
- this.statusContainer.addChild(compactingLoader);
3823
- this.ui.requestRender();
3824
- let result;
3825
3859
  try {
3826
- result = await this.session.compact(customInstructions);
3827
- // Rebuild UI
3828
- this.rebuildChatFromMessages();
3829
- // Add compaction component at bottom so user sees it without scrolling
3830
- const msg = createCompactionSummaryMessage(result.summary, result.tokensBefore, new Date().toISOString());
3831
- this.addMessageToChat(msg);
3832
- this.footer.invalidate();
3833
- }
3834
- catch (error) {
3835
- const message = error instanceof Error ? error.message : String(error);
3836
- if (message === "Compaction cancelled" || (error instanceof Error && error.name === "AbortError")) {
3837
- this.showError("Compaction cancelled");
3838
- }
3839
- else {
3840
- this.showError(`Compaction failed: ${message}`);
3841
- }
3860
+ await this.session.compact(customInstructions);
3842
3861
  }
3843
- finally {
3844
- compactingLoader.stop();
3845
- this.statusContainer.clear();
3846
- this.defaultEditor.onEscape = originalOnEscape;
3862
+ catch {
3863
+ // Ignore, will be emitted as an event
3847
3864
  }
3848
- void this.flushCompactionQueue({ willRetry: false });
3849
- return result;
3850
3865
  }
3851
3866
  stop() {
3852
3867
  if (this.loadingAnimation) {