@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
@@ -2,6 +2,12 @@
2
2
 
3
3
  All keyboard shortcuts can be customized via `~/.pi/agent/keybindings.json`. Each action can be bound to one or more keys.
4
4
 
5
+ The config file uses the same namespaced keybinding ids that pi uses internally and that extension authors use in `keyHint()` and injected `keybindings` managers.
6
+
7
+ Older configs using pre-namespaced ids such as `cursorUp` or `expandTools` are migrated automatically to the namespaced ids on startup.
8
+
9
+ After editing `keybindings.json`, run `/reload` in pi to apply the changes without restarting the session.
10
+
5
11
  ## Key Format
6
12
 
7
13
  `modifier+key` where modifiers are `ctrl`, `shift`, `alt` (combinable) and keys are:
@@ -16,127 +22,112 @@ Modifier combinations: `ctrl+shift+x`, `alt+ctrl+x`, `ctrl+shift+alt+x`, `ctrl+1
16
22
 
17
23
  ## All Actions
18
24
 
19
- ### Cursor Movement
25
+ ### TUI Editor Cursor Movement
20
26
 
21
- | Action | Default | Description |
27
+ | Keybinding id | Default | Description |
22
28
  |--------|---------|-------------|
23
- | `cursorUp` | `up` | Move cursor up |
24
- | `cursorDown` | `down` | Move cursor down |
25
- | `cursorLeft` | `left`, `ctrl+b` | Move cursor left |
26
- | `cursorRight` | `right`, `ctrl+f` | Move cursor right |
27
- | `cursorWordLeft` | `alt+left`, `ctrl+left`, `alt+b` | Move cursor word left |
28
- | `cursorWordRight` | `alt+right`, `ctrl+right`, `alt+f` | Move cursor word right |
29
- | `cursorLineStart` | `home`, `ctrl+a` | Move to line start |
30
- | `cursorLineEnd` | `end`, `ctrl+e` | Move to line end |
31
- | `jumpForward` | `ctrl+]` | Jump forward to character |
32
- | `jumpBackward` | `ctrl+alt+]` | Jump backward to character |
33
- | `pageUp` | `pageUp` | Scroll up by page |
34
- | `pageDown` | `pageDown` | Scroll down by page |
35
-
36
- ### Deletion
37
-
38
- | Action | Default | Description |
29
+ | `tui.editor.cursorUp` | `up` | Move cursor up |
30
+ | `tui.editor.cursorDown` | `down` | Move cursor down |
31
+ | `tui.editor.cursorLeft` | `left`, `ctrl+b` | Move cursor left |
32
+ | `tui.editor.cursorRight` | `right`, `ctrl+f` | Move cursor right |
33
+ | `tui.editor.cursorWordLeft` | `alt+left`, `ctrl+left`, `alt+b` | Move cursor word left |
34
+ | `tui.editor.cursorWordRight` | `alt+right`, `ctrl+right`, `alt+f` | Move cursor word right |
35
+ | `tui.editor.cursorLineStart` | `home`, `ctrl+a` | Move to line start |
36
+ | `tui.editor.cursorLineEnd` | `end`, `ctrl+e` | Move to line end |
37
+ | `tui.editor.jumpForward` | `ctrl+]` | Jump forward to character |
38
+ | `tui.editor.jumpBackward` | `ctrl+alt+]` | Jump backward to character |
39
+ | `tui.editor.pageUp` | `pageUp` | Scroll up by page |
40
+ | `tui.editor.pageDown` | `pageDown` | Scroll down by page |
41
+
42
+ ### TUI Editor Deletion
43
+
44
+ | Keybinding id | Default | Description |
39
45
  |--------|---------|-------------|
40
- | `deleteCharBackward` | `backspace` | Delete character backward |
41
- | `deleteCharForward` | `delete`, `ctrl+d` | Delete character forward |
42
- | `deleteWordBackward` | `ctrl+w`, `alt+backspace` | Delete word backward |
43
- | `deleteWordForward` | `alt+d`, `alt+delete` | Delete word forward |
44
- | `deleteToLineStart` | `ctrl+u` | Delete to line start |
45
- | `deleteToLineEnd` | `ctrl+k` | Delete to line end |
46
+ | `tui.editor.deleteCharBackward` | `backspace` | Delete character backward |
47
+ | `tui.editor.deleteCharForward` | `delete`, `ctrl+d` | Delete character forward |
48
+ | `tui.editor.deleteWordBackward` | `ctrl+w`, `alt+backspace` | Delete word backward |
49
+ | `tui.editor.deleteWordForward` | `alt+d`, `alt+delete` | Delete word forward |
50
+ | `tui.editor.deleteToLineStart` | `ctrl+u` | Delete to line start |
51
+ | `tui.editor.deleteToLineEnd` | `ctrl+k` | Delete to line end |
46
52
 
47
- ### Text Input
53
+ ### TUI Input
48
54
 
49
- | Action | Default | Description |
55
+ | Keybinding id | Default | Description |
50
56
  |--------|---------|-------------|
51
- | `newLine` | `shift+enter` | Insert new line |
52
- | `submit` | `enter` | Submit input |
53
- | `tab` | `tab` | Tab / autocomplete |
57
+ | `tui.input.newLine` | `shift+enter` | Insert new line |
58
+ | `tui.input.submit` | `enter` | Submit input |
59
+ | `tui.input.tab` | `tab` | Tab / autocomplete |
54
60
 
55
- ### Kill Ring
61
+ ### TUI Kill Ring
56
62
 
57
- | Action | Default | Description |
63
+ | Keybinding id | Default | Description |
58
64
  |--------|---------|-------------|
59
- | `yank` | `ctrl+y` | Paste most recently deleted text |
60
- | `yankPop` | `alt+y` | Cycle through deleted text after yank |
61
- | `undo` | `ctrl+-` | Undo last edit |
65
+ | `tui.editor.yank` | `ctrl+y` | Paste most recently deleted text |
66
+ | `tui.editor.yankPop` | `alt+y` | Cycle through deleted text after yank |
67
+ | `tui.editor.undo` | `ctrl+-` | Undo last edit |
62
68
 
63
- ### Clipboard
69
+ ### TUI Clipboard and Selection
64
70
 
65
- | Action | Default | Description |
71
+ | Keybinding id | Default | Description |
66
72
  |--------|---------|-------------|
67
- | `copy` | `ctrl+c` | Copy selection |
68
- | `pasteImage` | `ctrl+v` | Paste image from clipboard |
73
+ | `tui.input.copy` | `ctrl+c` | Copy selection |
74
+ | `tui.select.up` | `up` | Move selection up |
75
+ | `tui.select.down` | `down` | Move selection down |
76
+ | `tui.select.pageUp` | `pageUp` | Page up in list |
77
+ | `tui.select.pageDown` | `pageDown` | Page down in list |
78
+ | `tui.select.confirm` | `enter` | Confirm selection |
79
+ | `tui.select.cancel` | `escape`, `ctrl+c` | Cancel selection |
69
80
 
70
81
  ### Application
71
82
 
72
- | Action | Default | Description |
73
- |--------|---------|-------------|
74
- | `interrupt` | `escape` | Cancel / abort |
75
- | `clear` | `ctrl+c` | Clear editor |
76
- | `exit` | `ctrl+d` | Exit (when editor empty) |
77
- | `suspend` | `ctrl+z` | Suspend to background |
78
- | `externalEditor` | `ctrl+g` | Open in external editor (`$VISUAL` or `$EDITOR`) |
79
-
80
- ### Session
81
-
82
- | Action | Default | Description |
83
- |--------|---------|-------------|
84
- | `newSession` | *(none)* | Start a new session (`/new`) |
85
- | `tree` | *(none)* | Open session tree navigator (`/tree`) |
86
- | `fork` | *(none)* | Fork current session (`/fork`) |
87
- | `resume` | *(none)* | Open session resume picker (`/resume`) |
88
-
89
- ### Models & Thinking
90
-
91
- | Action | Default | Description |
83
+ | Keybinding id | Default | Description |
92
84
  |--------|---------|-------------|
93
- | `selectModel` | `ctrl+l` | Open model selector |
94
- | `cycleModelForward` | `ctrl+p` | Cycle to next model |
95
- | `cycleModelBackward` | `shift+ctrl+p` | Cycle to previous model |
96
- | `cycleThinkingLevel` | `shift+tab` | Cycle thinking level |
85
+ | `app.interrupt` | `escape` | Cancel / abort |
86
+ | `app.clear` | `ctrl+c` | Clear editor |
87
+ | `app.exit` | `ctrl+d` | Exit (when editor empty) |
88
+ | `app.suspend` | `ctrl+z` | Suspend to background |
89
+ | `app.editor.external` | `ctrl+g` | Open in external editor (`$VISUAL` or `$EDITOR`) |
90
+ | `app.clipboard.pasteImage` | `ctrl+v` (`alt+v` on Windows) | Paste image from clipboard |
97
91
 
98
- ### Display
92
+ ### Sessions
99
93
 
100
- | Action | Default | Description |
94
+ | Keybinding id | Default | Description |
101
95
  |--------|---------|-------------|
102
- | `expandTools` | `ctrl+o` | Collapse/expand tool output |
103
- | `toggleThinking` | `ctrl+t` | Collapse/expand thinking blocks |
104
-
105
- ### Message Queue
106
-
107
- | Action | Default | Description |
96
+ | `app.session.new` | *(none)* | Start a new session (`/new`) |
97
+ | `app.session.tree` | *(none)* | Open session tree navigator (`/tree`) |
98
+ | `app.session.fork` | *(none)* | Fork current session (`/fork`) |
99
+ | `app.session.resume` | *(none)* | Open session resume picker (`/resume`) |
100
+ | `app.session.togglePath` | `ctrl+p` | Toggle path display |
101
+ | `app.session.toggleSort` | `ctrl+s` | Toggle sort mode |
102
+ | `app.session.toggleNamedFilter` | `ctrl+n` | Toggle named-only filter |
103
+ | `app.session.rename` | `ctrl+r` | Rename session |
104
+ | `app.session.delete` | `ctrl+d` | Delete session |
105
+ | `app.session.deleteNoninvasive` | `ctrl+backspace` | Delete session when query is empty |
106
+
107
+ ### Models and Thinking
108
+
109
+ | Keybinding id | Default | Description |
108
110
  |--------|---------|-------------|
109
- | `followUp` | `alt+enter` | Queue follow-up message |
110
- | `dequeue` | `alt+up` | Restore queued messages to editor |
111
+ | `app.model.select` | `ctrl+l` | Open model selector |
112
+ | `app.model.cycleForward` | `ctrl+p` | Cycle to next model |
113
+ | `app.model.cycleBackward` | `shift+ctrl+p` | Cycle to previous model |
114
+ | `app.thinking.cycle` | `shift+tab` | Cycle thinking level |
115
+ | `app.thinking.toggle` | `ctrl+t` | Collapse or expand thinking blocks |
111
116
 
112
- ### Selection (Lists, Pickers)
117
+ ### Display and Message Queue
113
118
 
114
- | Action | Default | Description |
119
+ | Keybinding id | Default | Description |
115
120
  |--------|---------|-------------|
116
- | `selectUp` | `up` | Move selection up |
117
- | `selectDown` | `down` | Move selection down |
118
- | `selectPageUp` | `pageUp` | Page up in list |
119
- | `selectPageDown` | `pageDown` | Page down in list |
120
- | `selectConfirm` | `enter` | Confirm selection |
121
- | `selectCancel` | `escape`, `ctrl+c` | Cancel selection |
121
+ | `app.tools.expand` | `ctrl+o` | Collapse or expand tool output |
122
+ | `app.message.followUp` | `alt+enter` | Queue follow-up message |
123
+ | `app.message.dequeue` | `alt+up` | Restore queued messages to editor |
122
124
 
123
125
  ### Tree Navigation
124
126
 
125
- | Action | Default | Description |
126
- |--------|---------|-------------|
127
- | `treeFoldOrUp` | `ctrl+left`, `alt+left` | Fold current branch segment, or jump to the previous segment start |
128
- | `treeUnfoldOrDown` | `ctrl+right`, `alt+right` | Unfold current branch segment, or jump to the next segment start or branch end |
129
-
130
- ### Session Picker
131
-
132
- | Action | Default | Description |
127
+ | Keybinding id | Default | Description |
133
128
  |--------|---------|-------------|
134
- | `toggleSessionPath` | `ctrl+p` | Toggle path display |
135
- | `toggleSessionSort` | `ctrl+s` | Toggle sort mode |
136
- | `toggleSessionNamedFilter` | `ctrl+n` | Toggle named-only filter |
137
- | `renameSession` | `ctrl+r` | Rename session |
138
- | `deleteSession` | `ctrl+d` | Delete session |
139
- | `deleteSessionNoninvasive` | `ctrl+backspace` | Delete session (when query empty) |
129
+ | `app.tree.foldOrUp` | `ctrl+left`, `alt+left` | Fold current branch segment, or jump to the previous segment start |
130
+ | `app.tree.unfoldOrDown` | `ctrl+right`, `alt+right` | Unfold current branch segment, or jump to the next segment start or branch end |
140
131
 
141
132
  ## Custom Configuration
142
133
 
@@ -144,9 +135,9 @@ Create `~/.pi/agent/keybindings.json`:
144
135
 
145
136
  ```json
146
137
  {
147
- "cursorUp": ["up", "ctrl+p"],
148
- "cursorDown": ["down", "ctrl+n"],
149
- "deleteWordBackward": ["ctrl+w", "alt+backspace"]
138
+ "tui.editor.cursorUp": ["up", "ctrl+p"],
139
+ "tui.editor.cursorDown": ["down", "ctrl+n"],
140
+ "tui.editor.deleteWordBackward": ["ctrl+w", "alt+backspace"]
150
141
  }
151
142
  ```
152
143
 
@@ -156,15 +147,15 @@ Each action can have a single key or an array of keys. User config overrides def
156
147
 
157
148
  ```json
158
149
  {
159
- "cursorUp": ["up", "ctrl+p"],
160
- "cursorDown": ["down", "ctrl+n"],
161
- "cursorLeft": ["left", "ctrl+b"],
162
- "cursorRight": ["right", "ctrl+f"],
163
- "cursorWordLeft": ["alt+left", "alt+b"],
164
- "cursorWordRight": ["alt+right", "alt+f"],
165
- "deleteCharForward": ["delete", "ctrl+d"],
166
- "deleteCharBackward": ["backspace", "ctrl+h"],
167
- "newLine": ["shift+enter", "ctrl+j"]
150
+ "tui.editor.cursorUp": ["up", "ctrl+p"],
151
+ "tui.editor.cursorDown": ["down", "ctrl+n"],
152
+ "tui.editor.cursorLeft": ["left", "ctrl+b"],
153
+ "tui.editor.cursorRight": ["right", "ctrl+f"],
154
+ "tui.editor.cursorWordLeft": ["alt+left", "alt+b"],
155
+ "tui.editor.cursorWordRight": ["alt+right", "alt+f"],
156
+ "tui.editor.deleteCharForward": ["delete", "ctrl+d"],
157
+ "tui.editor.deleteCharBackward": ["backspace", "ctrl+h"],
158
+ "tui.input.newLine": ["shift+enter", "ctrl+j"]
168
159
  }
169
160
  ```
170
161
 
@@ -172,11 +163,11 @@ Each action can have a single key or an array of keys. User config overrides def
172
163
 
173
164
  ```json
174
165
  {
175
- "cursorUp": ["up", "alt+k"],
176
- "cursorDown": ["down", "alt+j"],
177
- "cursorLeft": ["left", "alt+h"],
178
- "cursorRight": ["right", "alt+l"],
179
- "cursorWordLeft": ["alt+left", "alt+b"],
180
- "cursorWordRight": ["alt+right", "alt+w"]
166
+ "tui.editor.cursorUp": ["up", "alt+k"],
167
+ "tui.editor.cursorDown": ["down", "alt+j"],
168
+ "tui.editor.cursorLeft": ["left", "alt+h"],
169
+ "tui.editor.cursorRight": ["right", "alt+l"],
170
+ "tui.editor.cursorWordLeft": ["alt+left", "alt+b"],
171
+ "tui.editor.cursorWordRight": ["alt+right", "alt+w"]
181
172
  }
182
173
  ```
package/docs/models.md CHANGED
@@ -35,6 +35,32 @@ For local models (Ollama, LM Studio, vLLM), only `id` is required per model:
35
35
 
36
36
  The `apiKey` is required but Ollama ignores it, so any value works.
37
37
 
38
+ Some OpenAI-compatible servers do not understand the `developer` role used for reasoning-capable models. For those providers, set `compat.supportsDeveloperRole` to `false` so pi sends the system prompt as a `system` message instead. If the server also does not support `reasoning_effort`, set `compat.supportsReasoningEffort` to `false` too.
39
+
40
+ You can set `compat` at the provider level to apply to all models, or at the model level to override a specific model. This commonly applies to Ollama, vLLM, SGLang, and similar OpenAI-compatible servers.
41
+
42
+ ```json
43
+ {
44
+ "providers": {
45
+ "ollama": {
46
+ "baseUrl": "http://localhost:11434/v1",
47
+ "api": "openai-completions",
48
+ "apiKey": "ollama",
49
+ "compat": {
50
+ "supportsDeveloperRole": false,
51
+ "supportsReasoningEffort": false
52
+ },
53
+ "models": [
54
+ {
55
+ "id": "gpt-oss:20b",
56
+ "reasoning": true
57
+ }
58
+ ]
59
+ }
60
+ }
61
+ }
62
+ ```
63
+
38
64
  ## Full Example
39
65
 
40
66
  Override defaults when you need specific values:
@@ -136,6 +162,7 @@ The `apiKey` and `headers` fields support three formats:
136
162
  | `contextWindow` | No | `128000` | Context window size in tokens |
137
163
  | `maxTokens` | No | `16384` | Maximum output tokens |
138
164
  | `cost` | No | all zeros | `{"input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0}` (per million tokens) |
165
+ | `compat` | No | provider `compat` | OpenAI compatibility overrides. Merged with provider-level `compat` when both are set. |
139
166
 
140
167
  Current behavior:
141
168
  - `/model` and `--list-models` list entries by model `id`.
@@ -211,7 +238,10 @@ Behavior notes:
211
238
 
212
239
  ## OpenAI Compatibility
213
240
 
214
- For providers with partial OpenAI compatibility, use the `compat` field:
241
+ For providers with partial OpenAI compatibility, use the `compat` field.
242
+
243
+ - Provider-level `compat` applies defaults to all models under that provider.
244
+ - Model-level `compat` overrides provider-level values for that model.
215
245
 
216
246
  ```json
217
247
  {
@@ -234,11 +264,19 @@ For providers with partial OpenAI compatibility, use the `compat` field:
234
264
  | `supportsStore` | Provider supports `store` field |
235
265
  | `supportsDeveloperRole` | Use `developer` vs `system` role |
236
266
  | `supportsReasoningEffort` | Support for `reasoning_effort` parameter |
267
+ | `reasoningEffortMap` | Map pi thinking levels to provider-specific `reasoning_effort` values |
237
268
  | `supportsUsageInStreaming` | Supports `stream_options: { include_usage: true }` (default: `true`) |
238
269
  | `maxTokensField` | Use `max_completion_tokens` or `max_tokens` |
270
+ | `requiresToolResultName` | Include `name` on tool result messages |
271
+ | `requiresAssistantAfterToolResult` | Insert an assistant message before a user message after tool results |
272
+ | `requiresThinkingAsText` | Convert thinking blocks to plain text |
273
+ | `thinkingFormat` | Use `reasoning_effort`, `zai`, `qwen`, or `qwen-chat-template` thinking parameters |
274
+ | `supportsStrictMode` | Include the `strict` field in tool definitions |
239
275
  | `openRouterRouting` | OpenRouter routing config passed to OpenRouter for model/provider selection |
240
276
  | `vercelGatewayRouting` | Vercel AI Gateway routing config for provider selection (`only`, `order`) |
241
277
 
278
+ `qwen` uses top-level `enable_thinking`. Use `qwen-chat-template` for local Qwen-compatible servers that require `chat_template_kwargs.enable_thinking`.
279
+
242
280
  Example:
243
281
 
244
282
  ```json
package/docs/packages.md CHANGED
@@ -54,6 +54,15 @@ npm:pkg
54
54
  - Versioned specs are pinned and skipped by `pi update`.
55
55
  - Global installs use `npm install -g`.
56
56
  - Project installs go under `.pi/npm/`.
57
+ - Set `npmCommand` in `settings.json` to pin npm package lookup and install operations to a specific wrapper command such as `mise` or `asdf`.
58
+
59
+ Example:
60
+
61
+ ```json
62
+ {
63
+ "npmCommand": ["mise", "exec", "node@20", "--", "npm"]
64
+ }
65
+ ```
57
66
 
58
67
  ### git
59
68
 
package/docs/providers.md CHANGED
@@ -147,6 +147,13 @@ Also supports ECS task roles (`AWS_CONTAINER_CREDENTIALS_*`) and IRSA (`AWS_WEB_
147
147
  pi --provider amazon-bedrock --model us.anthropic.claude-sonnet-4-20250514-v1:0
148
148
  ```
149
149
 
150
+ Prompt caching is enabled automatically for Claude models whose ID contains a recognizable model name (base models and system-defined inference profiles). For application inference profiles (whose ARNs don't contain the model name), set `AWS_BEDROCK_FORCE_CACHE=1` to enable cache points:
151
+
152
+ ```bash
153
+ export AWS_BEDROCK_FORCE_CACHE=1
154
+ pi --provider amazon-bedrock --model arn:aws:bedrock:us-east-1:123456789012:application-inference-profile/abc123
155
+ ```
156
+
150
157
  If you are connecting to a Bedrock API proxy, the following environment variables can be used:
151
158
 
152
159
  ```bash
package/docs/rpc.md CHANGED
@@ -58,7 +58,7 @@ With images:
58
58
  {"type": "prompt", "message": "New instruction", "streamingBehavior": "steer"}
59
59
  ```
60
60
 
61
- - `"steer"`: Interrupt the agent mid-run. Message is delivered after current tool execution, remaining tools are skipped.
61
+ - `"steer"`: Queue the message while the agent is running. It is delivered after the current assistant turn finishes executing its tool calls, before the next LLM call.
62
62
  - `"followUp"`: Wait until the agent finishes. Message is delivered only when agent stops.
63
63
 
64
64
  If the agent is streaming and no `streamingBehavior` is specified, the command returns an error.
@@ -76,7 +76,7 @@ The `images` field is optional. Each image uses `ImageContent` format: `{"type":
76
76
 
77
77
  #### steer
78
78
 
79
- Queue a steering message to interrupt the agent mid-run. Delivered after current tool execution, remaining tools are skipped. Skill commands and prompt templates are expanded. Extension commands are not allowed (use `prompt` instead).
79
+ Queue a steering message while the agent is running. It is delivered after the current assistant turn finishes executing its tool calls, before the next LLM call. Skill commands and prompt templates are expanded. Extension commands are not allowed (use `prompt` instead).
80
80
 
81
81
  ```json
82
82
  {"type": "steer", "message": "Stop and do this instead"}
@@ -321,8 +321,8 @@ Control how steering messages (from `steer`) are delivered.
321
321
  ```
322
322
 
323
323
  Modes:
324
- - `"all"`: Deliver all steering messages at the next interruption point
325
- - `"one-at-a-time"`: Deliver one steering message per interruption (default)
324
+ - `"all"`: Deliver all steering messages after the current assistant turn finishes executing its tool calls
325
+ - `"one-at-a-time"`: Deliver one steering message per completed assistant turn (default)
326
326
 
327
327
  Response:
328
328
  ```json
@@ -494,7 +494,7 @@ Response:
494
494
 
495
495
  #### get_session_stats
496
496
 
497
- Get token usage and cost statistics.
497
+ Get token usage, cost statistics, and current context window usage.
498
498
 
499
499
  ```json
500
500
  {"type": "get_session_stats"}
@@ -521,11 +521,20 @@ Response:
521
521
  "cacheWrite": 5000,
522
522
  "total": 105000
523
523
  },
524
- "cost": 0.45
524
+ "cost": 0.45,
525
+ "contextUsage": {
526
+ "tokens": 60000,
527
+ "contextWindow": 200000,
528
+ "percent": 30
529
+ }
525
530
  }
526
531
  }
527
532
  ```
528
533
 
534
+ `tokens` contains assistant usage totals for the current session state. `contextUsage` contains the actual current context-window estimate used for compaction and footer display.
535
+
536
+ `contextUsage` is omitted when no model or context window is available. `contextUsage.tokens` and `contextUsage.percent` are `null` immediately after compaction until a fresh post-compaction assistant response provides valid usage data.
537
+
529
538
  #### export_html
530
539
 
531
540
  Export session to an HTML file.
package/docs/sdk.md CHANGED
@@ -78,7 +78,7 @@ interface AgentSession {
78
78
  prompt(text: string, options?: PromptOptions): Promise<void>;
79
79
 
80
80
  // Queue messages during streaming
81
- steer(text: string): Promise<void>; // Interrupt: delivered after current tool, skips remaining
81
+ steer(text: string): Promise<void>; // Queue for delivery after the current assistant turn finishes its tool calls
82
82
  followUp(text: string): Promise<void>; // Wait: delivered only when agent finishes
83
83
 
84
84
  // Subscribe to events (returns unsubscribe function)
@@ -150,7 +150,7 @@ await session.prompt("After you're done, also check X", { streamingBehavior: "fo
150
150
  For explicit queueing during streaming:
151
151
 
152
152
  ```typescript
153
- // Interrupt the agent (delivered after current tool, skips remaining tools)
153
+ // Queue a steering message for delivery after the current assistant turn finishes its tool calls
154
154
  await session.steer("New instruction");
155
155
 
156
156
  // Wait for agent to finish (delivered only when agent stops)
package/docs/settings.md CHANGED
@@ -117,6 +117,15 @@ When a provider requests a retry delay longer than `maxDelayMs` (e.g., Google's
117
117
  |---------|------|---------|-------------|
118
118
  | `shellPath` | string | - | Custom shell path (e.g., for Cygwin on Windows) |
119
119
  | `shellCommandPrefix` | string | - | Prefix for every bash command (e.g., `"shopt -s expand_aliases"`) |
120
+ | `npmCommand` | string[] | - | Command argv used for npm package lookup/install operations (e.g., `["mise", "exec", "node@20", "--", "npm"]`) |
121
+
122
+ ```json
123
+ {
124
+ "npmCommand": ["mise", "exec", "node@20", "--", "npm"]
125
+ }
126
+ ```
127
+
128
+ `npmCommand` is used for all npm package-manager operations, including `npm root -g`, installs, uninstalls, and `npm install` inside git packages. Use argv-style entries exactly as the process should be launched.
120
129
 
121
130
  ### Model Cycling
122
131
 
@@ -86,6 +86,17 @@ Add to `settings.json` (Ctrl+Shift+, or Settings → Open JSON file) to forward
86
86
 
87
87
  If you already have an `actions` array, add the objects to it. If the old fullscreen behavior persists, fully close and reopen Windows Terminal.
88
88
 
89
+ ## xfce4-terminal, terminator
90
+
91
+ These terminals have limited escape sequence support. Modified Enter keys like `Ctrl+Enter` and `Shift+Enter` cannot be distinguished from plain `Enter`, preventing custom keybindings such as `submit: ["ctrl+enter"]` from working.
92
+
93
+ For the best experience, use a terminal that supports the Kitty keyboard protocol:
94
+ - [Kitty](https://sw.kovidgoyal.net/kitty/)
95
+ - [Ghostty](https://ghostty.org/)
96
+ - [WezTerm](https://wezfurlong.org/wezterm/)
97
+ - [iTerm2](https://iterm2.com/)
98
+ - [Alacritty](https://github.com/alacritty/alacritty) (requires compilation with Kitty protocol support)
99
+
89
100
  ## IntelliJ IDEA (Integrated Terminal)
90
101
 
91
102
  The built-in terminal has limited escape sequence support. Shift+Enter cannot be distinguished from Enter in IntelliJ's terminal.
package/docs/tui.md CHANGED
@@ -394,7 +394,7 @@ Components accept theme objects for styling.
394
394
  **In `renderCall`/`renderResult`**, use the `theme` parameter:
395
395
 
396
396
  ```typescript
397
- renderResult(result, options, theme) {
397
+ renderResult(result, options, theme, context) {
398
398
  // Use theme.fg() for foreground colors
399
399
  return new Text(theme.fg("success", "Done!"), 0, 0);
400
400
 
@@ -428,7 +428,7 @@ renderResult(result, options, theme) {
428
428
  import { getMarkdownTheme } from "@draht/coding-agent";
429
429
  import { Markdown } from "@draht/tui";
430
430
 
431
- renderResult(result, options, theme) {
431
+ renderResult(result, options, theme, context) {
432
432
  const mdTheme = getMarkdownTheme();
433
433
  return new Markdown(result.details.markdown, 0, 0, mdTheme);
434
434
  }
@@ -1,6 +1,6 @@
1
1
  # Extension Examples
2
2
 
3
- Example extensions for pi-coding-agent.
3
+ Example extensions for @draht/coding-agent.
4
4
 
5
5
  ## Usage
6
6
 
@@ -119,7 +119,7 @@ cp permission-gate.ts ~/.draht/agent/extensions/
119
119
  | Extension | Description |
120
120
  |-----------|-------------|
121
121
  | `custom-provider-anthropic/` | Custom Anthropic provider with OAuth support and custom streaming implementation |
122
- | `custom-provider-gitlab-duo/` | GitLab Duo provider using pi-ai's built-in Anthropic/OpenAI streaming via proxy |
122
+ | `custom-provider-gitlab-duo/` | GitLab Duo provider using @draht/ai's built-in Anthropic/OpenAI streaming via proxy |
123
123
  | `custom-provider-qwen-cli/` | Qwen CLI provider with OAuth device flow and OpenAI-compatible models |
124
124
 
125
125
  ### External Dependencies
@@ -28,10 +28,9 @@
28
28
  import { randomUUID } from "node:crypto";
29
29
  import { existsSync, readFileSync } from "node:fs";
30
30
  import { mkdir, writeFile } from "node:fs/promises";
31
- import { homedir } from "node:os";
32
31
  import { join } from "node:path";
33
32
  import { StringEnum } from "@draht/ai";
34
- import type { ExtensionAPI } from "@draht/coding-agent";
33
+ import { type ExtensionAPI, getAgentDir, withFileMutationQueue } from "@draht/coding-agent";
35
34
  import { type Static, Type } from "@sinclair/typebox";
36
35
 
37
36
  const PROVIDER = "google-antigravity";
@@ -184,7 +183,8 @@ function readConfigFile(path: string): ExtensionConfig {
184
183
  }
185
184
 
186
185
  function loadConfig(cwd: string): ExtensionConfig {
187
- const globalConfig = readConfigFile(join(homedir(), ".pi", "agent", "extensions", "antigravity-image-gen.json"));
186
+ const globalPath = join(getAgentDir(), "extensions", "antigravity-image-gen.json");
187
+ const globalConfig = readConfigFile(globalPath);
188
188
  const projectConfig = readConfigFile(join(cwd, ".pi", "extensions", "antigravity-image-gen.json"));
189
189
  return { ...globalConfig, ...projectConfig };
190
190
  }
@@ -204,7 +204,8 @@ function resolveSaveConfig(params: ToolParams, cwd: string): SaveConfig {
204
204
  }
205
205
 
206
206
  if (mode === "global") {
207
- return { mode, outputDir: join(homedir(), ".pi", "agent", "generated-images") };
207
+ const outputDir = join(getAgentDir(), "generated-images");
208
+ return { mode, outputDir };
208
209
  }
209
210
 
210
211
  if (mode === "custom") {
@@ -227,12 +228,14 @@ function imageExtension(mimeType: string): string {
227
228
  }
228
229
 
229
230
  async function saveImage(base64Data: string, mimeType: string, outputDir: string): Promise<string> {
230
- await mkdir(outputDir, { recursive: true });
231
231
  const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
232
232
  const ext = imageExtension(mimeType);
233
233
  const filename = `image-${timestamp}-${randomUUID().slice(0, 8)}.${ext}`;
234
234
  const filePath = join(outputDir, filename);
235
- await writeFile(filePath, Buffer.from(base64Data, "base64"));
235
+ await withFileMutationQueue(filePath, async () => {
236
+ await mkdir(outputDir, { recursive: true });
237
+ await writeFile(filePath, Buffer.from(base64Data, "base64"));
238
+ });
236
239
  return filePath;
237
240
  }
238
241
 
@@ -42,7 +42,7 @@ export default function (pi: ExtensionAPI) {
42
42
  return originalRead.execute(toolCallId, params, signal, onUpdate);
43
43
  },
44
44
 
45
- renderCall(args, theme) {
45
+ renderCall(args, theme, _context) {
46
46
  let text = theme.fg("toolTitle", theme.bold("read "));
47
47
  text += theme.fg("accent", args.path);
48
48
  if (args.offset || args.limit) {
@@ -54,7 +54,7 @@ export default function (pi: ExtensionAPI) {
54
54
  return new Text(text, 0, 0);
55
55
  },
56
56
 
57
- renderResult(result, { expanded, isPartial }, theme) {
57
+ renderResult(result, { expanded, isPartial }, theme, _context) {
58
58
  if (isPartial) return new Text(theme.fg("warning", "Reading..."), 0, 0);
59
59
 
60
60
  const details = result.details as ReadToolDetails | undefined;
@@ -101,7 +101,7 @@ export default function (pi: ExtensionAPI) {
101
101
  return originalBash.execute(toolCallId, params, signal, onUpdate);
102
102
  },
103
103
 
104
- renderCall(args, theme) {
104
+ renderCall(args, theme, _context) {
105
105
  let text = theme.fg("toolTitle", theme.bold("$ "));
106
106
  const cmd = args.command.length > 80 ? `${args.command.slice(0, 77)}...` : args.command;
107
107
  text += theme.fg("accent", cmd);
@@ -111,7 +111,7 @@ export default function (pi: ExtensionAPI) {
111
111
  return new Text(text, 0, 0);
112
112
  },
113
113
 
114
- renderResult(result, { expanded, isPartial }, theme) {
114
+ renderResult(result, { expanded, isPartial }, theme, _context) {
115
115
  if (isPartial) return new Text(theme.fg("warning", "Running..."), 0, 0);
116
116
 
117
117
  const details = result.details as BashToolDetails | undefined;
@@ -160,13 +160,13 @@ export default function (pi: ExtensionAPI) {
160
160
  return originalEdit.execute(toolCallId, params, signal, onUpdate);
161
161
  },
162
162
 
163
- renderCall(args, theme) {
163
+ renderCall(args, theme, _context) {
164
164
  let text = theme.fg("toolTitle", theme.bold("edit "));
165
165
  text += theme.fg("accent", args.path);
166
166
  return new Text(text, 0, 0);
167
167
  },
168
168
 
169
- renderResult(result, { expanded, isPartial }, theme) {
169
+ renderResult(result, { expanded, isPartial }, theme, _context) {
170
170
  if (isPartial) return new Text(theme.fg("warning", "Editing..."), 0, 0);
171
171
 
172
172
  const details = result.details as EditToolDetails | undefined;
@@ -224,7 +224,7 @@ export default function (pi: ExtensionAPI) {
224
224
  return originalWrite.execute(toolCallId, params, signal, onUpdate);
225
225
  },
226
226
 
227
- renderCall(args, theme) {
227
+ renderCall(args, theme, _context) {
228
228
  let text = theme.fg("toolTitle", theme.bold("write "));
229
229
  text += theme.fg("accent", args.path);
230
230
  const lineCount = args.content.split("\n").length;
@@ -232,7 +232,7 @@ export default function (pi: ExtensionAPI) {
232
232
  return new Text(text, 0, 0);
233
233
  },
234
234
 
235
- renderResult(result, { isPartial }, theme) {
235
+ renderResult(result, { isPartial }, theme, _context) {
236
236
  if (isPartial) return new Text(theme.fg("warning", "Writing..."), 0, 0);
237
237
 
238
238
  const content = result.content[0];