@draht/coding-agent 2026.3.11-1 → 2026.3.25-1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (380) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/README.md +45 -30
  3. package/bin/draht-tools.cjs +187 -32
  4. package/dist/bun/cli.d.ts +3 -0
  5. package/dist/bun/cli.d.ts.map +1 -0
  6. package/dist/bun/cli.js +7 -0
  7. package/dist/bun/cli.js.map +1 -0
  8. package/dist/bun/register-bedrock.d.ts +2 -0
  9. package/dist/bun/register-bedrock.d.ts.map +1 -0
  10. package/dist/bun/register-bedrock.js +4 -0
  11. package/dist/bun/register-bedrock.js.map +1 -0
  12. package/dist/cli/args.d.ts +1 -0
  13. package/dist/cli/args.d.ts.map +1 -1
  14. package/dist/cli/args.js +11 -6
  15. package/dist/cli/args.js.map +1 -1
  16. package/dist/cli/file-processor.d.ts.map +1 -1
  17. package/dist/cli/file-processor.js +4 -0
  18. package/dist/cli/file-processor.js.map +1 -1
  19. package/dist/cli/initial-message.d.ts +18 -0
  20. package/dist/cli/initial-message.d.ts.map +1 -0
  21. package/dist/cli/initial-message.js +22 -0
  22. package/dist/cli/initial-message.js.map +1 -0
  23. package/dist/cli/session-picker.d.ts.map +1 -1
  24. package/dist/cli/session-picker.js +2 -1
  25. package/dist/cli/session-picker.js.map +1 -1
  26. package/dist/cli.d.ts.map +1 -1
  27. package/dist/cli.js +1 -3
  28. package/dist/cli.js.map +1 -1
  29. package/dist/config.d.ts.map +1 -1
  30. package/dist/config.js +2 -2
  31. package/dist/config.js.map +1 -1
  32. package/dist/core/agent-session.d.ts +38 -5
  33. package/dist/core/agent-session.d.ts.map +1 -1
  34. package/dist/core/agent-session.js +201 -73
  35. package/dist/core/agent-session.js.map +1 -1
  36. package/dist/core/bash-executor.d.ts +6 -7
  37. package/dist/core/bash-executor.d.ts.map +1 -1
  38. package/dist/core/bash-executor.js +8 -107
  39. package/dist/core/bash-executor.js.map +1 -1
  40. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  41. package/dist/core/compaction/branch-summarization.js +1 -0
  42. package/dist/core/compaction/branch-summarization.js.map +1 -1
  43. package/dist/core/compaction/compaction.d.ts.map +1 -1
  44. package/dist/core/compaction/compaction.js +2 -0
  45. package/dist/core/compaction/compaction.js.map +1 -1
  46. package/dist/core/exec.d.ts.map +1 -1
  47. package/dist/core/exec.js +7 -3
  48. package/dist/core/exec.js.map +1 -1
  49. package/dist/core/export-html/index.d.ts +2 -2
  50. package/dist/core/export-html/index.d.ts.map +1 -1
  51. package/dist/core/export-html/index.js +7 -6
  52. package/dist/core/export-html/index.js.map +1 -1
  53. package/dist/core/export-html/template.css +43 -13
  54. package/dist/core/export-html/template.html +1 -0
  55. package/dist/core/export-html/template.js +107 -0
  56. package/dist/core/export-html/tool-renderer.d.ts +2 -2
  57. package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
  58. package/dist/core/export-html/tool-renderer.js +41 -16
  59. package/dist/core/export-html/tool-renderer.js.map +1 -1
  60. package/dist/core/extensions/index.d.ts +4 -3
  61. package/dist/core/extensions/index.d.ts.map +1 -1
  62. package/dist/core/extensions/index.js +1 -1
  63. package/dist/core/extensions/index.js.map +1 -1
  64. package/dist/core/extensions/loader.d.ts.map +1 -1
  65. package/dist/core/extensions/loader.js +16 -6
  66. package/dist/core/extensions/loader.js.map +1 -1
  67. package/dist/core/extensions/runner.d.ts +9 -9
  68. package/dist/core/extensions/runner.d.ts.map +1 -1
  69. package/dist/core/extensions/runner.js +89 -71
  70. package/dist/core/extensions/runner.js.map +1 -1
  71. package/dist/core/extensions/types.d.ts +49 -13
  72. package/dist/core/extensions/types.d.ts.map +1 -1
  73. package/dist/core/extensions/types.js.map +1 -1
  74. package/dist/core/extensions/wrapper.d.ts +4 -11
  75. package/dist/core/extensions/wrapper.d.ts.map +1 -1
  76. package/dist/core/extensions/wrapper.js +6 -86
  77. package/dist/core/extensions/wrapper.js.map +1 -1
  78. package/dist/core/footer-data-provider.d.ts +13 -1
  79. package/dist/core/footer-data-provider.d.ts.map +1 -1
  80. package/dist/core/footer-data-provider.js +155 -37
  81. package/dist/core/footer-data-provider.js.map +1 -1
  82. package/dist/core/index.d.ts +2 -1
  83. package/dist/core/index.d.ts.map +1 -1
  84. package/dist/core/index.js +2 -1
  85. package/dist/core/index.js.map +1 -1
  86. package/dist/core/keybindings.d.ts +270 -50
  87. package/dist/core/keybindings.d.ts.map +1 -1
  88. package/dist/core/keybindings.js +222 -134
  89. package/dist/core/keybindings.js.map +1 -1
  90. package/dist/core/model-registry.d.ts +1 -0
  91. package/dist/core/model-registry.d.ts.map +1 -1
  92. package/dist/core/model-registry.js +49 -23
  93. package/dist/core/model-registry.js.map +1 -1
  94. package/dist/core/model-resolver.d.ts +6 -0
  95. package/dist/core/model-resolver.d.ts.map +1 -1
  96. package/dist/core/model-resolver.js +41 -17
  97. package/dist/core/model-resolver.js.map +1 -1
  98. package/dist/core/output-guard.d.ts +6 -0
  99. package/dist/core/output-guard.d.ts.map +1 -0
  100. package/dist/core/output-guard.js +59 -0
  101. package/dist/core/output-guard.js.map +1 -0
  102. package/dist/core/package-manager.d.ts +22 -1
  103. package/dist/core/package-manager.d.ts.map +1 -1
  104. package/dist/core/package-manager.js +374 -54
  105. package/dist/core/package-manager.js.map +1 -1
  106. package/dist/core/prompt-templates.d.ts +2 -1
  107. package/dist/core/prompt-templates.d.ts.map +1 -1
  108. package/dist/core/prompt-templates.js +39 -39
  109. package/dist/core/prompt-templates.js.map +1 -1
  110. package/dist/core/resolve-config-value.d.ts.map +1 -1
  111. package/dist/core/resolve-config-value.js +43 -8
  112. package/dist/core/resolve-config-value.js.map +1 -1
  113. package/dist/core/resource-loader.d.ts +6 -7
  114. package/dist/core/resource-loader.d.ts.map +1 -1
  115. package/dist/core/resource-loader.js +141 -118
  116. package/dist/core/resource-loader.js.map +1 -1
  117. package/dist/core/sdk.d.ts +3 -3
  118. package/dist/core/sdk.d.ts.map +1 -1
  119. package/dist/core/sdk.js +4 -4
  120. package/dist/core/sdk.js.map +1 -1
  121. package/dist/core/session-manager.d.ts +6 -0
  122. package/dist/core/session-manager.d.ts.map +1 -1
  123. package/dist/core/session-manager.js +9 -10
  124. package/dist/core/session-manager.js.map +1 -1
  125. package/dist/core/settings-manager.d.ts +3 -0
  126. package/dist/core/settings-manager.d.ts.map +1 -1
  127. package/dist/core/settings-manager.js +8 -0
  128. package/dist/core/settings-manager.js.map +1 -1
  129. package/dist/core/skills.d.ts +5 -3
  130. package/dist/core/skills.d.ts.map +1 -1
  131. package/dist/core/skills.js +54 -9
  132. package/dist/core/skills.js.map +1 -1
  133. package/dist/core/slash-commands.d.ts +2 -3
  134. package/dist/core/slash-commands.d.ts.map +1 -1
  135. package/dist/core/slash-commands.js +3 -2
  136. package/dist/core/slash-commands.js.map +1 -1
  137. package/dist/core/source-info.d.ts +18 -0
  138. package/dist/core/source-info.d.ts.map +1 -0
  139. package/dist/core/source-info.js +19 -0
  140. package/dist/core/source-info.js.map +1 -0
  141. package/dist/core/system-prompt.d.ts.map +1 -1
  142. package/dist/core/system-prompt.js +17 -60
  143. package/dist/core/system-prompt.js.map +1 -1
  144. package/dist/core/tools/bash.d.ts +24 -6
  145. package/dist/core/tools/bash.d.ts.map +1 -1
  146. package/dist/core/tools/bash.js +210 -110
  147. package/dist/core/tools/bash.js.map +1 -1
  148. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  149. package/dist/core/tools/edit-diff.js +1 -0
  150. package/dist/core/tools/edit-diff.js.map +1 -1
  151. package/dist/core/tools/edit.d.ts +14 -2
  152. package/dist/core/tools/edit.d.ts.map +1 -1
  153. package/dist/core/tools/edit.js +95 -23
  154. package/dist/core/tools/edit.js.map +1 -1
  155. package/dist/core/tools/file-mutation-queue.d.ts +6 -0
  156. package/dist/core/tools/file-mutation-queue.d.ts.map +1 -0
  157. package/dist/core/tools/file-mutation-queue.js +37 -0
  158. package/dist/core/tools/file-mutation-queue.js.map +1 -0
  159. package/dist/core/tools/find.d.ts +11 -4
  160. package/dist/core/tools/find.d.ts.map +1 -1
  161. package/dist/core/tools/find.js +82 -30
  162. package/dist/core/tools/find.js.map +1 -1
  163. package/dist/core/tools/grep.d.ts +15 -4
  164. package/dist/core/tools/grep.d.ts.map +1 -1
  165. package/dist/core/tools/grep.js +83 -29
  166. package/dist/core/tools/grep.js.map +1 -1
  167. package/dist/core/tools/index.d.ts +58 -19
  168. package/dist/core/tools/index.d.ts.map +1 -1
  169. package/dist/core/tools/index.js +51 -26
  170. package/dist/core/tools/index.js.map +1 -1
  171. package/dist/core/tools/ls.d.ts +9 -3
  172. package/dist/core/tools/ls.d.ts.map +1 -1
  173. package/dist/core/tools/ls.js +67 -13
  174. package/dist/core/tools/ls.js.map +1 -1
  175. package/dist/core/tools/read.d.ts +10 -3
  176. package/dist/core/tools/read.d.ts.map +1 -1
  177. package/dist/core/tools/read.js +110 -51
  178. package/dist/core/tools/read.js.map +1 -1
  179. package/dist/core/tools/render-utils.d.ts +21 -0
  180. package/dist/core/tools/render-utils.d.ts.map +1 -0
  181. package/dist/core/tools/render-utils.js +49 -0
  182. package/dist/core/tools/render-utils.js.map +1 -0
  183. package/dist/core/tools/tool-definition-wrapper.d.ts +14 -0
  184. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -0
  185. package/dist/core/tools/tool-definition-wrapper.js +30 -0
  186. package/dist/core/tools/tool-definition-wrapper.js.map +1 -0
  187. package/dist/core/tools/write.d.ts +9 -3
  188. package/dist/core/tools/write.d.ts.map +1 -1
  189. package/dist/core/tools/write.js +168 -30
  190. package/dist/core/tools/write.js.map +1 -1
  191. package/dist/gsd/domain.d.ts +5 -1
  192. package/dist/gsd/domain.d.ts.map +1 -1
  193. package/dist/gsd/domain.js +71 -1
  194. package/dist/gsd/domain.js.map +1 -1
  195. package/dist/gsd/git.d.ts.map +1 -1
  196. package/dist/gsd/git.js +18 -0
  197. package/dist/gsd/git.js.map +1 -1
  198. package/dist/gsd/index.d.ts +1 -0
  199. package/dist/gsd/index.d.ts.map +1 -1
  200. package/dist/gsd/index.js.map +1 -1
  201. package/dist/index.d.ts +5 -4
  202. package/dist/index.d.ts.map +1 -1
  203. package/dist/index.js +4 -3
  204. package/dist/index.js.map +1 -1
  205. package/dist/main.d.ts.map +1 -1
  206. package/dist/main.js +105 -226
  207. package/dist/main.js.map +1 -1
  208. package/dist/modes/interactive/components/bash-execution.d.ts +0 -1
  209. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  210. package/dist/modes/interactive/components/bash-execution.js +22 -9
  211. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  212. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
  213. package/dist/modes/interactive/components/bordered-loader.js +1 -1
  214. package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
  215. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  216. package/dist/modes/interactive/components/branch-summary-message.js +2 -2
  217. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  218. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  219. package/dist/modes/interactive/components/compaction-summary-message.js +2 -2
  220. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  221. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  222. package/dist/modes/interactive/components/config-selector.js +8 -8
  223. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  224. package/dist/modes/interactive/components/custom-editor.d.ts +3 -3
  225. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  226. package/dist/modes/interactive/components/custom-editor.js +6 -6
  227. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  228. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  229. package/dist/modes/interactive/components/extension-editor.js +9 -9
  230. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  231. package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  232. package/dist/modes/interactive/components/extension-input.js +5 -5
  233. package/dist/modes/interactive/components/extension-input.js.map +1 -1
  234. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  235. package/dist/modes/interactive/components/extension-selector.js +8 -8
  236. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  237. package/dist/modes/interactive/components/index.d.ts +1 -1
  238. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  239. package/dist/modes/interactive/components/index.js +1 -1
  240. package/dist/modes/interactive/components/index.js.map +1 -1
  241. package/dist/modes/interactive/components/keybinding-hints.d.ts +3 -36
  242. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  243. package/dist/modes/interactive/components/keybinding-hints.js +5 -44
  244. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  245. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  246. package/dist/modes/interactive/components/login-dialog.js +6 -6
  247. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  248. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  249. package/dist/modes/interactive/components/model-selector.js +13 -9
  250. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  251. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  252. package/dist/modes/interactive/components/oauth-selector.js +6 -6
  253. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  254. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  255. package/dist/modes/interactive/components/scoped-models-selector.js +4 -4
  256. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  257. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  258. package/dist/modes/interactive/components/session-selector.js +32 -35
  259. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  260. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  261. package/dist/modes/interactive/components/settings-selector.js +5 -1
  262. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  263. package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
  264. package/dist/modes/interactive/components/show-images-selector.js +5 -1
  265. package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
  266. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  267. package/dist/modes/interactive/components/skill-invocation-message.js +2 -2
  268. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  269. package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
  270. package/dist/modes/interactive/components/theme-selector.js +5 -1
  271. package/dist/modes/interactive/components/theme-selector.js.map +1 -1
  272. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  273. package/dist/modes/interactive/components/thinking-selector.js +5 -1
  274. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  275. package/dist/modes/interactive/components/tool-execution.d.ts +16 -34
  276. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  277. package/dist/modes/interactive/components/tool-execution.js +128 -636
  278. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  279. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  280. package/dist/modes/interactive/components/tree-selector.js +27 -16
  281. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  282. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
  283. package/dist/modes/interactive/components/user-message-selector.js +6 -6
  284. package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
  285. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  286. package/dist/modes/interactive/components/user-message.js +2 -1
  287. package/dist/modes/interactive/components/user-message.js.map +1 -1
  288. package/dist/modes/interactive/interactive-mode.d.ts +7 -11
  289. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  290. package/dist/modes/interactive/interactive-mode.js +353 -212
  291. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  292. package/dist/modes/interactive/theme/theme.d.ts +3 -0
  293. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  294. package/dist/modes/interactive/theme/theme.js +63 -37
  295. package/dist/modes/interactive/theme/theme.js.map +1 -1
  296. package/dist/modes/print-mode.d.ts.map +1 -1
  297. package/dist/modes/print-mode.js +5 -11
  298. package/dist/modes/print-mode.js.map +1 -1
  299. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  300. package/dist/modes/rpc/rpc-mode.js +27 -17
  301. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  302. package/dist/modes/rpc/rpc-types.d.ts +3 -4
  303. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  304. package/dist/modes/rpc/rpc-types.js.map +1 -1
  305. package/dist/prompts/commands/execute-phase.md +2 -2
  306. package/dist/prompts/commands/fix.md +2 -2
  307. package/dist/prompts/commands/plan-phase.md +5 -1
  308. package/dist/prompts/commands/quick.md +5 -1
  309. package/dist/utils/changelog.d.ts +12 -0
  310. package/dist/utils/changelog.d.ts.map +1 -1
  311. package/dist/utils/changelog.js +25 -14
  312. package/dist/utils/changelog.js.map +1 -1
  313. package/dist/utils/child-process.d.ts +11 -0
  314. package/dist/utils/child-process.d.ts.map +1 -0
  315. package/dist/utils/child-process.js +78 -0
  316. package/dist/utils/child-process.js.map +1 -0
  317. package/dist/utils/clipboard-image.d.ts.map +1 -1
  318. package/dist/utils/clipboard-image.js +94 -11
  319. package/dist/utils/clipboard-image.js.map +1 -1
  320. package/dist/utils/clipboard-native.d.ts +1 -0
  321. package/dist/utils/clipboard-native.d.ts.map +1 -1
  322. package/dist/utils/clipboard-native.js.map +1 -1
  323. package/dist/utils/clipboard.d.ts +1 -1
  324. package/dist/utils/clipboard.d.ts.map +1 -1
  325. package/dist/utils/clipboard.js +27 -16
  326. package/dist/utils/clipboard.js.map +1 -1
  327. package/dist/utils/exif-orientation.d.ts +5 -0
  328. package/dist/utils/exif-orientation.d.ts.map +1 -0
  329. package/dist/utils/exif-orientation.js +158 -0
  330. package/dist/utils/exif-orientation.js.map +1 -0
  331. package/dist/utils/image-convert.d.ts.map +1 -1
  332. package/dist/utils/image-convert.js +5 -1
  333. package/dist/utils/image-convert.js.map +1 -1
  334. package/dist/utils/image-resize.d.ts +5 -5
  335. package/dist/utils/image-resize.d.ts.map +1 -1
  336. package/dist/utils/image-resize.js +51 -95
  337. package/dist/utils/image-resize.js.map +1 -1
  338. package/dist/utils/notify.d.ts +12 -0
  339. package/dist/utils/notify.d.ts.map +1 -0
  340. package/dist/utils/notify.js +41 -0
  341. package/dist/utils/notify.js.map +1 -0
  342. package/dist/utils/tools-manager.d.ts.map +1 -1
  343. package/dist/utils/tools-manager.js +5 -4
  344. package/dist/utils/tools-manager.js.map +1 -1
  345. package/docs/custom-provider.md +6 -2
  346. package/docs/extensions.md +108 -21
  347. package/docs/keybindings.md +103 -112
  348. package/docs/models.md +39 -1
  349. package/docs/packages.md +9 -0
  350. package/docs/providers.md +7 -0
  351. package/docs/rpc.md +15 -6
  352. package/docs/sdk.md +2 -2
  353. package/docs/settings.md +9 -0
  354. package/docs/terminal-setup.md +11 -0
  355. package/docs/tui.md +2 -2
  356. package/examples/extensions/README.md +2 -2
  357. package/examples/extensions/antigravity-image-gen.ts +9 -6
  358. package/examples/extensions/built-in-tool-renderer.ts +8 -8
  359. package/examples/extensions/commands.ts +3 -3
  360. package/examples/extensions/custom-provider-gitlab-duo/test.ts +2 -2
  361. package/examples/extensions/minimal-mode.ts +14 -14
  362. package/examples/extensions/notify.ts +9 -2
  363. package/examples/extensions/preset.ts +2 -3
  364. package/examples/extensions/question.ts +2 -2
  365. package/examples/extensions/questionnaire.ts +2 -2
  366. package/examples/extensions/sandbox/index.ts +2 -3
  367. package/examples/extensions/subagent/index.ts +30 -8
  368. package/examples/extensions/titlebar-spinner.ts +2 -2
  369. package/examples/extensions/todo.ts +2 -2
  370. package/examples/extensions/tool-override.ts +10 -9
  371. package/examples/extensions/truncated-tool.ts +8 -5
  372. package/examples/sdk/04-skills.ts +8 -2
  373. package/examples/sdk/08-prompt-templates.ts +8 -2
  374. package/examples/sdk/12-full-control.ts +0 -1
  375. package/examples/sdk/README.md +1 -1
  376. package/package.json +4 -4
  377. package/prompts/commands/execute-phase.md +2 -2
  378. package/prompts/commands/fix.md +2 -2
  379. package/prompts/commands/plan-phase.md +5 -1
  380. package/prompts/commands/quick.md +5 -1
@@ -60,10 +60,10 @@ export default function commandsExtension(pi: ExtensionAPI) {
60
60
  if (selected && !selected.startsWith("---")) {
61
61
  const cmdName = selected.split(" - ")[0].slice(1); // Remove leading /
62
62
  const cmd = commands.find((c) => c.name === cmdName);
63
- if (cmd?.path) {
64
- const showPath = await ctx.ui.confirm(cmd.name, `View source path?\n${cmd.path}`);
63
+ if (cmd?.sourceInfo.path) {
64
+ const showPath = await ctx.ui.confirm(cmd.name, `View source path?\n${cmd.sourceInfo.path}`);
65
65
  if (showPath) {
66
- ctx.ui.notify(cmd.path, "info");
66
+ ctx.ui.notify(cmd.sourceInfo.path, "info");
67
67
  }
68
68
  }
69
69
  }
@@ -10,7 +10,7 @@
10
10
 
11
11
  import { type Api, type Context, type Model, registerApiProvider, streamSimple } from "@draht/ai";
12
12
  import { readFileSync } from "fs";
13
- import { homedir } from "os";
13
+ import { getAgentDir } from "packages/coding-agent/src/config.js";
14
14
  import { join } from "path";
15
15
  import { MODELS, streamGitLabDuo } from "./index.js";
16
16
 
@@ -28,7 +28,7 @@ async function main() {
28
28
  }
29
29
 
30
30
  // Read auth
31
- const authPath = join(homedir(), ".pi", "agent", "auth.json");
31
+ const authPath = join(getAgentDir(), "extensions", "auth.json");
32
32
  const authData = JSON.parse(readFileSync(authPath, "utf-8"));
33
33
  const gitlabCred = authData["gitlab-duo"];
34
34
  if (!gitlabCred?.access) {
@@ -80,7 +80,7 @@ export default function (pi: ExtensionAPI) {
80
80
  return tools.read.execute(toolCallId, params, signal, onUpdate);
81
81
  },
82
82
 
83
- renderCall(args, theme) {
83
+ renderCall(args, theme, _context) {
84
84
  const path = shortenPath(args.path || "");
85
85
  let pathDisplay = path ? theme.fg("accent", path) : theme.fg("toolOutput", "...");
86
86
 
@@ -94,7 +94,7 @@ export default function (pi: ExtensionAPI) {
94
94
  return new Text(`${theme.fg("toolTitle", theme.bold("read"))} ${pathDisplay}`, 0, 0);
95
95
  },
96
96
 
97
- renderResult(result, { expanded }, theme) {
97
+ renderResult(result, { expanded }, theme, _context) {
98
98
  // Minimal mode: show nothing in collapsed state
99
99
  if (!expanded) {
100
100
  return new Text("", 0, 0);
@@ -127,7 +127,7 @@ export default function (pi: ExtensionAPI) {
127
127
  return tools.bash.execute(toolCallId, params, signal, onUpdate);
128
128
  },
129
129
 
130
- renderCall(args, theme) {
130
+ renderCall(args, theme, _context) {
131
131
  const command = args.command || "...";
132
132
  const timeout = args.timeout as number | undefined;
133
133
  const timeoutSuffix = timeout ? theme.fg("muted", ` (timeout ${timeout}s)`) : "";
@@ -135,7 +135,7 @@ export default function (pi: ExtensionAPI) {
135
135
  return new Text(theme.fg("toolTitle", theme.bold(`$ ${command}`)) + timeoutSuffix, 0, 0);
136
136
  },
137
137
 
138
- renderResult(result, { expanded }, theme) {
138
+ renderResult(result, { expanded }, theme, _context) {
139
139
  // Minimal mode: show nothing in collapsed state
140
140
  if (!expanded) {
141
141
  return new Text("", 0, 0);
@@ -176,7 +176,7 @@ export default function (pi: ExtensionAPI) {
176
176
  return tools.write.execute(toolCallId, params, signal, onUpdate);
177
177
  },
178
178
 
179
- renderCall(args, theme) {
179
+ renderCall(args, theme, _context) {
180
180
  const path = shortenPath(args.path || "");
181
181
  const pathDisplay = path ? theme.fg("accent", path) : theme.fg("toolOutput", "...");
182
182
  const lineCount = args.content ? args.content.split("\n").length : 0;
@@ -185,7 +185,7 @@ export default function (pi: ExtensionAPI) {
185
185
  return new Text(`${theme.fg("toolTitle", theme.bold("write"))} ${pathDisplay}${lineInfo}`, 0, 0);
186
186
  },
187
187
 
188
- renderResult(result, { expanded }, theme) {
188
+ renderResult(result, { expanded }, theme, _context) {
189
189
  // Minimal mode: show nothing (file was written)
190
190
  if (!expanded) {
191
191
  return new Text("", 0, 0);
@@ -218,14 +218,14 @@ export default function (pi: ExtensionAPI) {
218
218
  return tools.edit.execute(toolCallId, params, signal, onUpdate);
219
219
  },
220
220
 
221
- renderCall(args, theme) {
221
+ renderCall(args, theme, _context) {
222
222
  const path = shortenPath(args.path || "");
223
223
  const pathDisplay = path ? theme.fg("accent", path) : theme.fg("toolOutput", "...");
224
224
 
225
225
  return new Text(`${theme.fg("toolTitle", theme.bold("edit"))} ${pathDisplay}`, 0, 0);
226
226
  },
227
227
 
228
- renderResult(result, { expanded }, theme) {
228
+ renderResult(result, { expanded }, theme, _context) {
229
229
  // Minimal mode: show nothing in collapsed state
230
230
  if (!expanded) {
231
231
  return new Text("", 0, 0);
@@ -263,7 +263,7 @@ export default function (pi: ExtensionAPI) {
263
263
  return tools.find.execute(toolCallId, params, signal, onUpdate);
264
264
  },
265
265
 
266
- renderCall(args, theme) {
266
+ renderCall(args, theme, _context) {
267
267
  const pattern = args.pattern || "";
268
268
  const path = shortenPath(args.path || ".");
269
269
  const limit = args.limit;
@@ -277,7 +277,7 @@ export default function (pi: ExtensionAPI) {
277
277
  return new Text(text, 0, 0);
278
278
  },
279
279
 
280
- renderResult(result, { expanded }, theme) {
280
+ renderResult(result, { expanded }, theme, _context) {
281
281
  if (!expanded) {
282
282
  // Minimal: just show count
283
283
  const textContent = result.content.find((c) => c.type === "text");
@@ -321,7 +321,7 @@ export default function (pi: ExtensionAPI) {
321
321
  return tools.grep.execute(toolCallId, params, signal, onUpdate);
322
322
  },
323
323
 
324
- renderCall(args, theme) {
324
+ renderCall(args, theme, _context) {
325
325
  const pattern = args.pattern || "";
326
326
  const path = shortenPath(args.path || ".");
327
327
  const glob = args.glob;
@@ -339,7 +339,7 @@ export default function (pi: ExtensionAPI) {
339
339
  return new Text(text, 0, 0);
340
340
  },
341
341
 
342
- renderResult(result, { expanded }, theme) {
342
+ renderResult(result, { expanded }, theme, _context) {
343
343
  if (!expanded) {
344
344
  // Minimal: just show match count
345
345
  const textContent = result.content.find((c) => c.type === "text");
@@ -383,7 +383,7 @@ export default function (pi: ExtensionAPI) {
383
383
  return tools.ls.execute(toolCallId, params, signal, onUpdate);
384
384
  },
385
385
 
386
- renderCall(args, theme) {
386
+ renderCall(args, theme, _context) {
387
387
  const path = shortenPath(args.path || ".");
388
388
  const limit = args.limit;
389
389
 
@@ -395,7 +395,7 @@ export default function (pi: ExtensionAPI) {
395
395
  return new Text(text, 0, 0);
396
396
  },
397
397
 
398
- renderResult(result, { expanded }, theme) {
398
+ renderResult(result, { expanded }, theme, _context) {
399
399
  if (!expanded) {
400
400
  // Minimal: just show entry count
401
401
  const textContent = result.content.find((c) => c.type === "text");
@@ -3,12 +3,14 @@
3
3
  *
4
4
  * Sends a native terminal notification when Pi agent is done and waiting for input.
5
5
  * Supports multiple terminal protocols:
6
+ * - cmux: uses `cmux notify` CLI
6
7
  * - OSC 777: Ghostty, iTerm2, WezTerm, rxvt-unicode
7
8
  * - OSC 99: Kitty
8
9
  * - Windows toast: Windows Terminal (WSL)
9
10
  */
10
11
 
11
12
  import type { ExtensionAPI } from "@draht/coding-agent";
13
+ import { execFile } from "child_process";
12
14
 
13
15
  function windowsToastScript(title: string, body: string): string {
14
16
  const type = "Windows.UI.Notifications";
@@ -33,13 +35,18 @@ function notifyOSC99(title: string, body: string): void {
33
35
  process.stdout.write(`\x1b]99;i=1:p=body;${body}\x1b\\`);
34
36
  }
35
37
 
38
+ function notifyCmux(title: string, body: string): void {
39
+ execFile("cmux", ["notify", "--title", title, "--body", body]);
40
+ }
41
+
36
42
  function notifyWindows(title: string, body: string): void {
37
- const { execFile } = require("child_process");
38
43
  execFile("powershell.exe", ["-NoProfile", "-Command", windowsToastScript(title, body)]);
39
44
  }
40
45
 
41
46
  function notify(title: string, body: string): void {
42
- if (process.env.WT_SESSION) {
47
+ if (process.env.CMUX_BUNDLE_ID) {
48
+ notifyCmux(title, body);
49
+ } else if (process.env.WT_SESSION) {
43
50
  notifyWindows(title, body);
44
51
  } else if (process.env.KITTY_WINDOW_ID) {
45
52
  notifyOSC99(title, body);
@@ -39,10 +39,9 @@
39
39
  */
40
40
 
41
41
  import { existsSync, readFileSync } from "node:fs";
42
- import { homedir } from "node:os";
43
42
  import { join } from "node:path";
44
43
  import type { ExtensionAPI, ExtensionContext } from "@draht/coding-agent";
45
- import { DynamicBorder } from "@draht/coding-agent";
44
+ import { DynamicBorder, getAgentDir } from "@draht/coding-agent";
46
45
  import { Container, Key, type SelectItem, SelectList, Text } from "@draht/tui";
47
46
 
48
47
  // Preset configuration
@@ -68,7 +67,7 @@ interface PresetsConfig {
68
67
  * Project-local presets override global presets with the same name.
69
68
  */
70
69
  function loadPresets(cwd: string): PresetsConfig {
71
- const globalPath = join(homedir(), ".pi", "agent", "presets.json");
70
+ const globalPath = join(getAgentDir(), "presets.json");
72
71
  const projectPath = join(cwd, ".pi", "presets.json");
73
72
 
74
73
  let globalPresets: PresetsConfig = {};
@@ -227,7 +227,7 @@ export default function question(pi: ExtensionAPI) {
227
227
  };
228
228
  },
229
229
 
230
- renderCall(args, theme) {
230
+ renderCall(args, theme, _context) {
231
231
  let text = theme.fg("toolTitle", theme.bold("question ")) + theme.fg("muted", args.question);
232
232
  const opts = Array.isArray(args.options) ? args.options : [];
233
233
  if (opts.length) {
@@ -238,7 +238,7 @@ export default function question(pi: ExtensionAPI) {
238
238
  return new Text(text, 0, 0);
239
239
  },
240
240
 
241
- renderResult(result, _options, theme) {
241
+ renderResult(result, _options, theme, _context) {
242
242
  const details = result.details as QuestionDetails | undefined;
243
243
  if (!details) {
244
244
  const text = result.content[0];
@@ -393,7 +393,7 @@ export default function questionnaire(pi: ExtensionAPI) {
393
393
  };
394
394
  },
395
395
 
396
- renderCall(args, theme) {
396
+ renderCall(args, theme, _context) {
397
397
  const qs = (args.questions as Question[]) || [];
398
398
  const count = qs.length;
399
399
  const labels = qs.map((q) => q.label || q.id).join(", ");
@@ -405,7 +405,7 @@ export default function questionnaire(pi: ExtensionAPI) {
405
405
  return new Text(text, 0, 0);
406
406
  },
407
407
 
408
- renderResult(result, _options, theme) {
408
+ renderResult(result, _options, theme, _context) {
409
409
  const details = result.details as QuestionnaireResult | undefined;
410
410
  if (!details) {
411
411
  const text = result.content[0];
@@ -39,11 +39,10 @@
39
39
 
40
40
  import { spawn } from "node:child_process";
41
41
  import { existsSync, readFileSync } from "node:fs";
42
- import { homedir } from "node:os";
43
42
  import { join } from "node:path";
44
43
  import { SandboxManager, type SandboxRuntimeConfig } from "@anthropic-ai/sandbox-runtime";
45
44
  import type { ExtensionAPI } from "@draht/coding-agent";
46
- import { type BashOperations, createBashTool } from "@draht/coding-agent";
45
+ import { type BashOperations, createBashTool, getAgentDir } from "@draht/coding-agent";
47
46
 
48
47
  interface SandboxConfig extends SandboxRuntimeConfig {
49
48
  enabled?: boolean;
@@ -75,7 +74,7 @@ const DEFAULT_CONFIG: SandboxConfig = {
75
74
 
76
75
  function loadConfig(cwd: string): SandboxConfig {
77
76
  const projectConfigPath = join(cwd, ".pi", "sandbox.json");
78
- const globalConfigPath = join(homedir(), ".pi", "agent", "sandbox.json");
77
+ const globalConfigPath = join(getAgentDir(), "extensions", "sandbox.json");
79
78
 
80
79
  let globalConfig: Partial<SandboxConfig> = {};
81
80
  let projectConfig: Partial<SandboxConfig> = {};
@@ -19,7 +19,7 @@ import * as path from "node:path";
19
19
  import type { AgentToolResult } from "@draht/agent-core";
20
20
  import type { Message } from "@draht/ai";
21
21
  import { StringEnum } from "@draht/ai";
22
- import { type ExtensionAPI, getMarkdownTheme } from "@draht/coding-agent";
22
+ import { type ExtensionAPI, getMarkdownTheme, withFileMutationQueue } from "@draht/coding-agent";
23
23
  import { Container, Markdown, Spacer, Text } from "@draht/tui";
24
24
  import { Type } from "@sinclair/typebox";
25
25
  import { type AgentConfig, type AgentScope, discoverAgents } from "./agents.js";
@@ -207,14 +207,31 @@ async function mapWithConcurrencyLimit<TIn, TOut>(
207
207
  return results;
208
208
  }
209
209
 
210
- function writePromptToTempFile(agentName: string, prompt: string): { dir: string; filePath: string } {
211
- const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-subagent-"));
210
+ async function writePromptToTempFile(agentName: string, prompt: string): Promise<{ dir: string; filePath: string }> {
211
+ const tmpDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), "pi-subagent-"));
212
212
  const safeName = agentName.replace(/[^\w.-]+/g, "_");
213
213
  const filePath = path.join(tmpDir, `prompt-${safeName}.md`);
214
- fs.writeFileSync(filePath, prompt, { encoding: "utf-8", mode: 0o600 });
214
+ await withFileMutationQueue(filePath, async () => {
215
+ await fs.promises.writeFile(filePath, prompt, { encoding: "utf-8", mode: 0o600 });
216
+ });
215
217
  return { dir: tmpDir, filePath };
216
218
  }
217
219
 
220
+ function getPiInvocation(args: string[]): { command: string; args: string[] } {
221
+ const currentScript = process.argv[1];
222
+ if (currentScript && fs.existsSync(currentScript)) {
223
+ return { command: process.execPath, args: [currentScript, ...args] };
224
+ }
225
+
226
+ const execName = path.basename(process.execPath).toLowerCase();
227
+ const isGenericRuntime = /^(node|bun)(\.exe)?$/.test(execName);
228
+ if (!isGenericRuntime) {
229
+ return { command: process.execPath, args };
230
+ }
231
+
232
+ return { command: "pi", args };
233
+ }
234
+
218
235
  type OnUpdateCallback = (partial: AgentToolResult<SubagentDetails>) => void;
219
236
 
220
237
  async function runSingleAgent(
@@ -274,7 +291,7 @@ async function runSingleAgent(
274
291
 
275
292
  try {
276
293
  if (agent.systemPrompt.trim()) {
277
- const tmp = writePromptToTempFile(agent.name, agent.systemPrompt);
294
+ const tmp = await writePromptToTempFile(agent.name, agent.systemPrompt);
278
295
  tmpPromptDir = tmp.dir;
279
296
  tmpPromptPath = tmp.filePath;
280
297
  args.push("--append-system-prompt", tmpPromptPath);
@@ -284,7 +301,12 @@ async function runSingleAgent(
284
301
  let wasAborted = false;
285
302
 
286
303
  const exitCode = await new Promise<number>((resolve) => {
287
- const proc = spawn("pi", args, { cwd: cwd ?? defaultCwd, shell: false, stdio: ["ignore", "pipe", "pipe"] });
304
+ const invocation = getPiInvocation(args);
305
+ const proc = spawn(invocation.command, invocation.args, {
306
+ cwd: cwd ?? defaultCwd,
307
+ shell: false,
308
+ stdio: ["ignore", "pipe", "pipe"],
309
+ });
288
310
  let buffer = "";
289
311
 
290
312
  const processLine = (line: string) => {
@@ -646,7 +668,7 @@ export default function (pi: ExtensionAPI) {
646
668
  };
647
669
  },
648
670
 
649
- renderCall(args, theme) {
671
+ renderCall(args, theme, _context) {
650
672
  const scope: AgentScope = args.agentScope ?? "user";
651
673
  if (args.chain && args.chain.length > 0) {
652
674
  let text =
@@ -690,7 +712,7 @@ export default function (pi: ExtensionAPI) {
690
712
  return new Text(text, 0, 0);
691
713
  },
692
714
 
693
- renderResult(result, { expanded }, theme) {
715
+ renderResult(result, { expanded }, theme, _context) {
694
716
  const details = result.details as SubagentDetails | undefined;
695
717
  if (!details || details.results.length === 0) {
696
718
  const text = result.content[0];
@@ -16,7 +16,7 @@ const BRAILLE_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧",
16
16
  function getBaseTitle(pi: ExtensionAPI): string {
17
17
  const cwd = path.basename(process.cwd());
18
18
  const session = pi.getSessionName();
19
- return session ? - ${session} - ${cwd}` : - ${cwd}`;
19
+ return session ? `D - ${session} - ${cwd}` : `D - ${cwd}`;
20
20
  }
21
21
 
22
22
  export default function (pi: ExtensionAPI) {
@@ -38,7 +38,7 @@ export default function (pi: ExtensionAPI) {
38
38
  const frame = BRAILLE_FRAMES[frameIndex % BRAILLE_FRAMES.length];
39
39
  const cwd = path.basename(process.cwd());
40
40
  const session = pi.getSessionName();
41
- const title = session ? `${frame} π - ${session} - ${cwd}` : `${frame} π - ${cwd}`;
41
+ const title = session ? `${frame} D - ${session} - ${cwd}` : `${frame} D - ${cwd}`;
42
42
  ctx.ui.setTitle(title);
43
43
  frameIndex++;
44
44
  }, 80);
@@ -220,14 +220,14 @@ export default function (pi: ExtensionAPI) {
220
220
  }
221
221
  },
222
222
 
223
- renderCall(args, theme) {
223
+ renderCall(args, theme, _context) {
224
224
  let text = theme.fg("toolTitle", theme.bold("todo ")) + theme.fg("muted", args.action);
225
225
  if (args.text) text += ` ${theme.fg("dim", `"${args.text}"`)}`;
226
226
  if (args.id !== undefined) text += ` ${theme.fg("accent", `#${args.id}`)}`;
227
227
  return new Text(text, 0, 0);
228
228
  },
229
229
 
230
- renderResult(result, { expanded }, theme) {
230
+ renderResult(result, { expanded }, theme, _context) {
231
231
  const details = result.details as TodoDetails | undefined;
232
232
  if (!details) {
233
233
  const text = result.content[0];
@@ -21,14 +21,13 @@
21
21
  */
22
22
 
23
23
  import type { TextContent } from "@draht/ai";
24
- import type { ExtensionAPI } from "@draht/coding-agent";
24
+ import { type ExtensionAPI, getAgentDir, withFileMutationQueue } from "@draht/coding-agent";
25
25
  import { Type } from "@sinclair/typebox";
26
- import { appendFileSync, constants, readFileSync } from "fs";
27
- import { access, readFile } from "fs/promises";
28
- import { homedir } from "os";
26
+ import { constants, readFileSync } from "fs";
27
+ import { access, appendFile, readFile } from "fs/promises";
29
28
  import { join, resolve } from "path";
30
29
 
31
- const LOG_FILE = join(homedir(), ".pi", "agent", "read-access.log");
30
+ const LOG_FILE = join(getAgentDir(), "read-access.log");
32
31
 
33
32
  // Paths that are blocked from reading
34
33
  const BLOCKED_PATTERNS = [
@@ -45,14 +44,16 @@ function isBlockedPath(path: string): boolean {
45
44
  return BLOCKED_PATTERNS.some((pattern) => pattern.test(path));
46
45
  }
47
46
 
48
- function logAccess(path: string, allowed: boolean, reason?: string) {
47
+ async function logAccess(path: string, allowed: boolean, reason?: string) {
49
48
  const timestamp = new Date().toISOString();
50
49
  const status = allowed ? "ALLOWED" : "BLOCKED";
51
50
  const msg = reason ? ` (${reason})` : "";
52
51
  const line = `[${timestamp}] ${status}: ${path}${msg}\n`;
53
52
 
54
53
  try {
55
- appendFileSync(LOG_FILE, line);
54
+ await withFileMutationQueue(LOG_FILE, async () => {
55
+ await appendFile(LOG_FILE, line);
56
+ });
56
57
  } catch {
57
58
  // Ignore logging errors
58
59
  }
@@ -78,7 +79,7 @@ export default function (pi: ExtensionAPI) {
78
79
 
79
80
  // Check if path is blocked
80
81
  if (isBlockedPath(absolutePath)) {
81
- logAccess(absolutePath, false, "matches blocked pattern");
82
+ await logAccess(absolutePath, false, "matches blocked pattern");
82
83
  return {
83
84
  content: [
84
85
  {
@@ -91,7 +92,7 @@ export default function (pi: ExtensionAPI) {
91
92
  }
92
93
 
93
94
  // Log allowed access
94
- logAccess(absolutePath, true);
95
+ await logAccess(absolutePath, true);
95
96
 
96
97
  // Perform the actual read (simplified implementation)
97
98
  try {
@@ -14,6 +14,7 @@
14
14
  * built-in `grep` tool in src/core/tools/grep.ts for a more complete implementation.
15
15
  */
16
16
 
17
+ import { mkdtemp, writeFile } from "node:fs/promises";
17
18
  import type { ExtensionAPI } from "@draht/coding-agent";
18
19
  import {
19
20
  DEFAULT_MAX_BYTES,
@@ -21,11 +22,11 @@ import {
21
22
  formatSize,
22
23
  type TruncationResult,
23
24
  truncateHead,
25
+ withFileMutationQueue,
24
26
  } from "@draht/coding-agent";
25
27
  import { Text } from "@draht/tui";
26
28
  import { Type } from "@sinclair/typebox";
27
29
  import { execSync } from "child_process";
28
- import { mkdtempSync, writeFileSync } from "fs";
29
30
  import { tmpdir } from "os";
30
31
  import { join } from "path";
31
32
 
@@ -108,9 +109,11 @@ export default function (pi: ExtensionAPI) {
108
109
 
109
110
  if (truncation.truncated) {
110
111
  // Save full output to a temp file so LLM can access it if needed
111
- const tempDir = mkdtempSync(join(tmpdir(), "pi-rg-"));
112
+ const tempDir = await mkdtemp(join(tmpdir(), "pi-rg-"));
112
113
  const tempFile = join(tempDir, "output.txt");
113
- writeFileSync(tempFile, output);
114
+ await withFileMutationQueue(tempFile, async () => {
115
+ await writeFile(tempFile, output, "utf8");
116
+ });
114
117
 
115
118
  details.truncation = truncation;
116
119
  details.fullOutputPath = tempFile;
@@ -132,7 +135,7 @@ export default function (pi: ExtensionAPI) {
132
135
  },
133
136
 
134
137
  // Custom rendering of the tool call (shown before/during execution)
135
- renderCall(args, theme) {
138
+ renderCall(args, theme, _context) {
136
139
  let text = theme.fg("toolTitle", theme.bold("rg "));
137
140
  text += theme.fg("accent", `"${args.pattern}"`);
138
141
  if (args.path) {
@@ -145,7 +148,7 @@ export default function (pi: ExtensionAPI) {
145
148
  },
146
149
 
147
150
  // Custom rendering of the tool result
148
- renderResult(result, { expanded, isPartial }, theme) {
151
+ renderResult(result, { expanded, isPartial }, theme, _context) {
149
152
  const details = result.details as RgDetails | undefined;
150
153
 
151
154
  // Handle streaming/partial results
@@ -5,7 +5,13 @@
5
5
  * Discover, filter, merge, or replace them.
6
6
  */
7
7
 
8
- import { createAgentSession, DefaultResourceLoader, SessionManager, type Skill } from "@draht/coding-agent";
8
+ import {
9
+ createAgentSession,
10
+ createSyntheticSourceInfo,
11
+ DefaultResourceLoader,
12
+ SessionManager,
13
+ type Skill,
14
+ } from "@draht/coding-agent";
9
15
 
10
16
  // Or define custom skills inline
11
17
  const customSkill: Skill = {
@@ -13,7 +19,7 @@ const customSkill: Skill = {
13
19
  description: "Custom project instructions",
14
20
  filePath: "/virtual/SKILL.md",
15
21
  baseDir: "/virtual",
16
- source: "path",
22
+ sourceInfo: createSyntheticSourceInfo("/virtual/SKILL.md", { source: "sdk" }),
17
23
  disableModelInvocation: false,
18
24
  };
19
25
 
@@ -4,14 +4,20 @@
4
4
  * File-based templates that inject content when invoked with /templatename.
5
5
  */
6
6
 
7
- import { createAgentSession, DefaultResourceLoader, type PromptTemplate, SessionManager } from "@draht/coding-agent";
7
+ import {
8
+ createAgentSession,
9
+ createSyntheticSourceInfo,
10
+ DefaultResourceLoader,
11
+ type PromptTemplate,
12
+ SessionManager,
13
+ } from "@draht/coding-agent";
8
14
 
9
15
  // Define custom templates
10
16
  const deployTemplate: PromptTemplate = {
11
17
  name: "deploy",
12
18
  description: "Deploy the application",
13
- source: "path",
14
19
  filePath: "/virtual/prompts/deploy.md",
20
+ sourceInfo: createSyntheticSourceInfo("/virtual/prompts/deploy.md", { source: "sdk" }),
15
21
  content: `# Deploy Instructions
16
22
 
17
23
  1. Build: npm run build
@@ -53,7 +53,6 @@ const resourceLoader: ResourceLoader = {
53
53
  getSystemPrompt: () => `You are a minimal assistant.
54
54
  Available: read, bash. Be concise.`,
55
55
  getAppendSystemPrompt: () => [],
56
- getPathMetadata: () => new Map(),
57
56
  extendResources: () => {},
58
57
  reload: async () => {},
59
58
  };
@@ -1,6 +1,6 @@
1
1
  # SDK Examples
2
2
 
3
- Programmatic usage of pi-coding-agent via `createAgentSession()`.
3
+ Programmatic usage of @draht/coding-agent via `createAgentSession()`.
4
4
 
5
5
  ## Examples
6
6
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@draht/coding-agent",
3
- "version": "2026.3.11-1",
3
+ "version": "2026.3.25-1",
4
4
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
5
5
  "type": "module",
6
6
  "drahtConfig": {
@@ -48,9 +48,9 @@
48
48
  "@mariozechner/jiti": "^2.6.2",
49
49
  "@sinclair/typebox": "^0.34.41",
50
50
  "ajv": "^8.17.1",
51
- "@draht/agent-core": "2026.3.11-1",
52
- "@draht/ai": "2026.3.11-1",
53
- "@draht/tui": "2026.3.11-1",
51
+ "@draht/agent-core": "2026.3.25-1",
52
+ "@draht/ai": "2026.3.25-1",
53
+ "@draht/tui": "2026.3.25-1",
54
54
  "@silvia-odwyer/photon-node": "^0.3.4",
55
55
  "chalk": "^5.5.0",
56
56
  "cli-highlight": "^2.1.11",
@@ -41,8 +41,8 @@ Execute this plan. Here is the full plan content:
41
41
  <paste full plan XML here>
42
42
 
43
43
  For each <task> in the plan, follow this TDD cycle:
44
- 1. RED — Write failing tests from <test>. Run the test runner, confirm they FAIL. Commit with: git add <test-files> && git commit -m "red: <description>"
45
- 2. GREEN — Write minimal implementation from <action> to make tests pass. Run tests, confirm PASS. Commit with: git add <files> && git commit -m "green: <task name>"
44
+ 1. RED — Write failing tests from <test>. Run the test runner, confirm they FAIL. Commit with: git add <test-files> && git commit -m "test: <description>"
45
+ 2. GREEN — Write minimal implementation from <action> to make tests pass. Run tests, confirm PASS. Commit with: git add <files> && git commit -m "feat: <task name>"
46
46
  3. REFACTOR — Apply <refactor> improvements if any. Tests must stay green after each change. Commit with: git add <files> && git commit -m "refactor: <description>"
47
47
  4. VERIFY — Run the <verify> step, confirm <done> criteria are met.
48
48
 
@@ -18,12 +18,12 @@ Issue: $ARGUMENTS
18
18
  "Diagnose this issue: $ARGUMENTS. Reproduce the bug by running the relevant test or command. Trace the root cause by reading the code. Identify the exact files and lines involved. Do NOT fix it yet — only report the diagnosis with: root cause, affected files, and a recommended fix approach. Do NOT run draht, draht-tools, or pi commands."
19
19
 
20
20
  2. **Write a reproducing test**: Based on the diagnosis, write a test that demonstrates the bug (it must fail)
21
- - Commit: `draht-tools commit-docs "red: reproduce bug"`
21
+ - Commit: `draht-tools commit-docs "test: reproduce bug"`
22
22
 
23
23
  3. **Minimal fix**: Write the smallest change that makes the test pass
24
24
  - Do not refactor or add features — just fix the bug
25
25
  - Run the full test suite to check for regressions
26
- - Commit: `draht-tools commit-docs "green: fix description"`
26
+ - Commit: `draht-tools commit-docs "fix: fix description"`
27
27
 
28
28
  4. **Refactor** (if needed): Clean up without changing behavior
29
29
  - Tests must stay green after every change
@@ -34,7 +34,11 @@ Phase: $1
34
34
  - Instruction to output the plan as XML (you will save it via `draht-tools create-plan`)
35
35
 
36
36
  6. Collect all plan outputs from subagents
37
- 7. Save plans yourself: `draht-tools create-plan $1 P` for each plan
37
+ 7. Save each plan by piping the subagent's output into `draht-tools create-plan`:
38
+ ```
39
+ echo 'plan content from subagent' | draht-tools create-plan $1 P [title]
40
+ ```
41
+ The content must contain real task details (files, actions, tests) — NOT placeholder brackets. If `create-plan` is called without stdin, it writes a useless template.
38
42
  8. Validate: `draht-tools validate-plans $1`
39
43
  9. Commit: `draht-tools commit-docs "create phase $1 plans"`
40
44
 
@@ -15,7 +15,11 @@ Task: $ARGUMENTS
15
15
 
16
16
  ## Steps
17
17
  1. Run `draht-tools next-quick-number` to get task number
18
- 2. Create quick plan: `draht-tools create-quick-plan NNN "$ARGUMENTS"`
18
+ 2. Analyze the task and write a concrete plan with actual task details (files, actions, verification). Pipe it into `draht-tools create-quick-plan`:
19
+ ```
20
+ echo 'plan content here' | draht-tools create-quick-plan NNN "$ARGUMENTS"
21
+ ```
22
+ The plan content must include: a `# Quick Task NNN: title` heading, a `## Tasks` section with one or more `<task>` XML blocks containing real file paths, real actions, and real verification steps — NOT placeholders like `[files]`.
19
23
  3. **Delegate execution to subagent**: Use the `subagent` tool in **single mode** with the `implementer` agent:
20
24
  "Execute this task: $ARGUMENTS
21
25