@earendil-works/pi-coding-agent 0.87.0 → 0.99.0

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 (743) hide show
  1. package/CHANGELOG.md +103 -0
  2. package/README.md +25 -711
  3. package/dist/bun/cli.d.ts.map +1 -1
  4. package/dist/bun/restore-sandbox-env.d.ts.map +1 -1
  5. package/dist/bun/restore-sandbox-env.js.map +1 -1
  6. package/dist/bun/runtime-setup.d.ts.map +1 -1
  7. package/dist/bun/runtime-setup.js +4 -1
  8. package/dist/bun/runtime-setup.js.map +1 -1
  9. package/dist/bun/sandbox-env-setup.d.ts.map +1 -1
  10. package/dist/bundle/chunks/anthropic-messages-A6EXUBG6.js +6 -0
  11. package/dist/bundle/chunks/anthropic.js +2 -2
  12. package/dist/bundle/chunks/azure-openai-responses-EN5WOBET.js +2 -0
  13. package/dist/bundle/chunks/bedrock-converse-stream.js +2 -2
  14. package/dist/bundle/chunks/chunk-4CSSZFEW.js +1435 -0
  15. package/dist/bundle/chunks/chunk-7JGR3GZN.js +11 -0
  16. package/dist/bundle/chunks/chunk-AXPY26X7.js +146 -0
  17. package/dist/bundle/chunks/chunk-EPDRUIU6.js +2 -0
  18. package/dist/bundle/chunks/chunk-GOPCREV2.js +4 -0
  19. package/dist/bundle/chunks/chunk-H3QXYIF7.js +31 -0
  20. package/dist/bundle/chunks/{chunk-S7SZN6Z3.js → chunk-HSPCVFST.js} +1 -1
  21. package/dist/bundle/chunks/chunk-IMTXZUO7.js +82 -0
  22. package/dist/bundle/chunks/chunk-J4CWPC4N.js +2 -0
  23. package/dist/bundle/chunks/chunk-LLMKQWZS.js +21 -0
  24. package/dist/bundle/chunks/{chunk-WIUZI2CJ.js → chunk-LRS5S6EK.js} +3 -3
  25. package/dist/bundle/chunks/chunk-PEHWOV5U.js +187 -0
  26. package/dist/bundle/chunks/{chunk-XDUWOHPL.js → chunk-S3GGRYIO.js} +2 -2
  27. package/dist/bundle/chunks/chunk-UTB4DTYQ.js +2 -0
  28. package/dist/bundle/chunks/{chunk-FUXEF6JQ.js → chunk-W2DOMZSC.js} +1 -1
  29. package/dist/bundle/chunks/cli-AZXNGIZH.js +49 -0
  30. package/dist/bundle/chunks/cloudflare-workers-ai-system-one-XJQQYGGU.js +2 -0
  31. package/dist/bundle/chunks/codemode-worker.js +295 -0
  32. package/dist/bundle/chunks/execute-7XXPZAWW.js +308 -0
  33. package/dist/bundle/chunks/github-copilot.js +1 -1
  34. package/dist/bundle/chunks/google-generative-ai-CQAKKJTA.js +2 -0
  35. package/dist/bundle/chunks/google-vertex-AE36YXJU.js +2 -0
  36. package/dist/bundle/chunks/{lib-HGQMNYVT.js → lib-TEDK3E5I.js} +2 -2
  37. package/dist/bundle/chunks/llama-cpp-classify-PJJYKPLD.js +22 -0
  38. package/dist/bundle/chunks/mistral-conversations-KEYTXJM7.js +5 -0
  39. package/dist/bundle/chunks/{openai-codex-responses-QDSOTBBO.js → openai-codex-responses-JQTCOVEG.js} +2 -2
  40. package/dist/bundle/chunks/openai-codex.js +2 -2
  41. package/dist/bundle/chunks/{openai-completions-XHML6MTL.js → openai-completions-XW2Q5HVC.js} +2 -2
  42. package/dist/bundle/chunks/openai-responses-6AXWFL75.js +3 -0
  43. package/dist/bundle/chunks/{openrouter-images-N4XVVFSD.js → openrouter-images-TPQ4V6OR.js} +1 -1
  44. package/dist/bundle/chunks/openrouter.js +2 -2
  45. package/dist/bundle/chunks/{pi-messages-GFKBWJHZ.js → pi-messages-TM5SOOIW.js} +2 -2
  46. package/dist/bundle/chunks/radius.js +2 -2
  47. package/dist/bundle/chunks/runtime-G5WJPRBM.js +2 -0
  48. package/dist/bundle/chunks/typesafe-system-one-E7A4HNJI.js +2 -0
  49. package/dist/bundle/chunks/virtual-modules-AQ3FLU6H.js +2 -0
  50. package/dist/bundle/cli-runtime.js +1 -1
  51. package/dist/bundle/index.js +1 -1
  52. package/dist/bundle/rpc-entry.js +1 -1
  53. package/dist/cli/args.d.ts.map +1 -1
  54. package/dist/cli/args.js +18 -7
  55. package/dist/cli/args.js.map +1 -1
  56. package/dist/cli/auth-check.d.ts.map +1 -1
  57. package/dist/cli/auth-check.js.map +1 -1
  58. package/dist/cli/auth-command.d.ts.map +1 -1
  59. package/dist/cli/auth-command.js.map +1 -1
  60. package/dist/cli/config-selector.d.ts.map +1 -1
  61. package/dist/cli/config-selector.js.map +1 -1
  62. package/dist/cli/credential-print.d.ts.map +1 -1
  63. package/dist/cli/credential-print.js.map +1 -1
  64. package/dist/cli/file-processor.d.ts.map +1 -1
  65. package/dist/cli/file-processor.js.map +1 -1
  66. package/dist/cli/initial-message.d.ts +1 -1
  67. package/dist/cli/initial-message.d.ts.map +1 -1
  68. package/dist/cli/initial-message.js.map +1 -1
  69. package/dist/cli/list-models.d.ts.map +1 -1
  70. package/dist/cli/list-models.js.map +1 -1
  71. package/dist/cli/project-trust.d.ts.map +1 -1
  72. package/dist/cli/project-trust.js.map +1 -1
  73. package/dist/cli/session-picker.d.ts.map +1 -1
  74. package/dist/cli/session-picker.js.map +1 -1
  75. package/dist/cli/setup.d.ts.map +1 -1
  76. package/dist/cli/setup.js.map +1 -1
  77. package/dist/cli/startup-ui.d.ts.map +1 -1
  78. package/dist/cli/startup-ui.js +38 -30
  79. package/dist/cli/startup-ui.js.map +1 -1
  80. package/dist/cli.d.ts.map +1 -1
  81. package/dist/config.d.ts +18 -4
  82. package/dist/config.d.ts.map +1 -1
  83. package/dist/config.js +30 -4
  84. package/dist/config.js.map +1 -1
  85. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  86. package/dist/core/agent-session-runtime.js +1 -1
  87. package/dist/core/agent-session-runtime.js.map +1 -1
  88. package/dist/core/agent-session-services.d.ts.map +1 -1
  89. package/dist/core/agent-session-services.js +13 -0
  90. package/dist/core/agent-session-services.js.map +1 -1
  91. package/dist/core/agent-session.d.ts +135 -11
  92. package/dist/core/agent-session.d.ts.map +1 -1
  93. package/dist/core/agent-session.js +509 -253
  94. package/dist/core/agent-session.js.map +1 -1
  95. package/dist/core/auth-guidance.d.ts.map +1 -1
  96. package/dist/core/auth-guidance.js.map +1 -1
  97. package/dist/core/auth-storage.d.ts.map +1 -1
  98. package/dist/core/auth-storage.js.map +1 -1
  99. package/dist/core/bash-executor.d.ts.map +1 -1
  100. package/dist/core/bash-executor.js.map +1 -1
  101. package/dist/core/bug-report-upload.d.ts.map +1 -1
  102. package/dist/core/bug-report-upload.js.map +1 -1
  103. package/dist/core/bug-report.d.ts +1 -1
  104. package/dist/core/bug-report.d.ts.map +1 -1
  105. package/dist/core/bug-report.js +1 -1
  106. package/dist/core/bug-report.js.map +1 -1
  107. package/dist/core/cache-stats.d.ts.map +1 -1
  108. package/dist/core/cache-stats.js.map +1 -1
  109. package/dist/core/cache-warmer.d.ts.map +1 -1
  110. package/dist/core/cache-warmer.js.map +1 -1
  111. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  112. package/dist/core/compaction/branch-summarization.js.map +1 -1
  113. package/dist/core/compaction/compaction.d.ts.map +1 -1
  114. package/dist/core/compaction/compaction.js +10 -31
  115. package/dist/core/compaction/compaction.js.map +1 -1
  116. package/dist/core/compaction/index.d.ts.map +1 -1
  117. package/dist/core/compaction/utils.d.ts +2 -1
  118. package/dist/core/compaction/utils.d.ts.map +1 -1
  119. package/dist/core/compaction/utils.js +25 -18
  120. package/dist/core/compaction/utils.js.map +1 -1
  121. package/dist/core/crash-log.d.ts.map +1 -1
  122. package/dist/core/crash-log.js +2 -1
  123. package/dist/core/crash-log.js.map +1 -1
  124. package/dist/core/defaults.d.ts.map +1 -1
  125. package/dist/core/diagnostics.d.ts.map +1 -1
  126. package/dist/core/event-bus.d.ts.map +1 -1
  127. package/dist/core/event-bus.js.map +1 -1
  128. package/dist/core/exec.d.ts.map +1 -1
  129. package/dist/core/exec.js.map +1 -1
  130. package/dist/core/experimental.d.ts.map +1 -1
  131. package/dist/core/experimental.js.map +1 -1
  132. package/dist/core/export-html/ansi-to-html.d.ts.map +1 -1
  133. package/dist/core/export-html/ansi-to-html.js.map +1 -1
  134. package/dist/core/export-html/index.d.ts.map +1 -1
  135. package/dist/core/export-html/index.js.map +1 -1
  136. package/dist/core/export-html/template.css +10 -0
  137. package/dist/core/export-html/template.js +66 -17
  138. package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
  139. package/dist/core/export-html/tool-renderer.js.map +1 -1
  140. package/dist/core/extensions/index.d.ts +1 -1
  141. package/dist/core/extensions/index.d.ts.map +1 -1
  142. package/dist/core/extensions/index.js.map +1 -1
  143. package/dist/core/extensions/jiti-loader.d.ts.map +1 -1
  144. package/dist/core/extensions/jiti-static-loader.d.ts.map +1 -1
  145. package/dist/core/extensions/loader.d.ts.map +1 -1
  146. package/dist/core/extensions/loader.js +55 -5
  147. package/dist/core/extensions/loader.js.map +1 -1
  148. package/dist/core/extensions/runner.d.ts +18 -1
  149. package/dist/core/extensions/runner.d.ts.map +1 -1
  150. package/dist/core/extensions/runner.js +99 -0
  151. package/dist/core/extensions/runner.js.map +1 -1
  152. package/dist/core/extensions/types.d.ts +296 -22
  153. package/dist/core/extensions/types.d.ts.map +1 -1
  154. package/dist/core/extensions/types.js.map +1 -1
  155. package/dist/core/extensions/virtual-modules.d.ts.map +1 -1
  156. package/dist/core/extensions/wrapper.d.ts +2 -2
  157. package/dist/core/extensions/wrapper.d.ts.map +1 -1
  158. package/dist/core/extensions/wrapper.js +3 -3
  159. package/dist/core/extensions/wrapper.js.map +1 -1
  160. package/dist/core/footer-data-provider.d.ts.map +1 -1
  161. package/dist/core/footer-data-provider.js.map +1 -1
  162. package/dist/core/http-dispatcher.d.ts.map +1 -1
  163. package/dist/core/http-dispatcher.js.map +1 -1
  164. package/dist/core/index.d.ts.map +1 -1
  165. package/dist/core/keybindings.d.ts +1 -1
  166. package/dist/core/keybindings.d.ts.map +1 -1
  167. package/dist/core/keybindings.js +1 -1
  168. package/dist/core/keybindings.js.map +1 -1
  169. package/dist/core/mcp-servers.d.ts +98 -0
  170. package/dist/core/mcp-servers.d.ts.map +1 -0
  171. package/dist/core/mcp-servers.js +157 -0
  172. package/dist/core/mcp-servers.js.map +1 -0
  173. package/dist/core/messages.d.ts.map +1 -1
  174. package/dist/core/messages.js.map +1 -1
  175. package/dist/core/model-config.d.ts.map +1 -1
  176. package/dist/core/model-config.js.map +1 -1
  177. package/dist/core/model-registry.d.ts +13 -1
  178. package/dist/core/model-registry.d.ts.map +1 -1
  179. package/dist/core/model-registry.js +25 -0
  180. package/dist/core/model-registry.js.map +1 -1
  181. package/dist/core/model-resolver.d.ts +2 -2
  182. package/dist/core/model-resolver.d.ts.map +1 -1
  183. package/dist/core/model-resolver.js +5 -5
  184. package/dist/core/model-resolver.js.map +1 -1
  185. package/dist/core/model-runtime.d.ts +41 -3
  186. package/dist/core/model-runtime.d.ts.map +1 -1
  187. package/dist/core/model-runtime.js +167 -17
  188. package/dist/core/model-runtime.js.map +1 -1
  189. package/dist/core/models-store.d.ts.map +1 -1
  190. package/dist/core/models-store.js.map +1 -1
  191. package/dist/core/nested-tool-calls.d.ts +102 -0
  192. package/dist/core/nested-tool-calls.d.ts.map +1 -0
  193. package/dist/core/nested-tool-calls.js +178 -0
  194. package/dist/core/nested-tool-calls.js.map +1 -0
  195. package/dist/core/output-guard.d.ts.map +1 -1
  196. package/dist/core/output-guard.js.map +1 -1
  197. package/dist/core/package-manager.d.ts +4 -0
  198. package/dist/core/package-manager.d.ts.map +1 -1
  199. package/dist/core/package-manager.js +59 -12
  200. package/dist/core/package-manager.js.map +1 -1
  201. package/dist/core/pi-manifest.d.ts.map +1 -1
  202. package/dist/core/pi-manifest.js.map +1 -1
  203. package/dist/core/project-trust.d.ts.map +1 -1
  204. package/dist/core/project-trust.js.map +1 -1
  205. package/dist/core/prompt-templates.d.ts.map +1 -1
  206. package/dist/core/prompt-templates.js.map +1 -1
  207. package/dist/core/provider-attribution.d.ts.map +1 -1
  208. package/dist/core/provider-attribution.js.map +1 -1
  209. package/dist/core/provider-composer.d.ts +40 -21
  210. package/dist/core/provider-composer.d.ts.map +1 -1
  211. package/dist/core/provider-composer.js +92 -40
  212. package/dist/core/provider-composer.js.map +1 -1
  213. package/dist/core/radius.d.ts.map +1 -1
  214. package/dist/core/radius.js.map +1 -1
  215. package/dist/core/remote-catalog-provider.d.ts +8 -1
  216. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  217. package/dist/core/remote-catalog-provider.js +18 -3
  218. package/dist/core/remote-catalog-provider.js.map +1 -1
  219. package/dist/core/resolve-config-value.d.ts.map +1 -1
  220. package/dist/core/resolve-config-value.js.map +1 -1
  221. package/dist/core/resource-loader.d.ts +7 -1
  222. package/dist/core/resource-loader.d.ts.map +1 -1
  223. package/dist/core/resource-loader.js +161 -35
  224. package/dist/core/resource-loader.js.map +1 -1
  225. package/dist/core/runtime-credentials.d.ts.map +1 -1
  226. package/dist/core/runtime-credentials.js.map +1 -1
  227. package/dist/core/sdk.d.ts +1 -1
  228. package/dist/core/sdk.d.ts.map +1 -1
  229. package/dist/core/sdk.js +24 -6
  230. package/dist/core/sdk.js.map +1 -1
  231. package/dist/core/session-cwd.d.ts.map +1 -1
  232. package/dist/core/session-cwd.js.map +1 -1
  233. package/dist/core/session-export.d.ts.map +1 -1
  234. package/dist/core/session-export.js.map +1 -1
  235. package/dist/core/session-manager.d.ts +9 -0
  236. package/dist/core/session-manager.d.ts.map +1 -1
  237. package/dist/core/session-manager.js +22 -22
  238. package/dist/core/session-manager.js.map +1 -1
  239. package/dist/core/settings-diagnostics.d.ts.map +1 -1
  240. package/dist/core/settings-diagnostics.js.map +1 -1
  241. package/dist/core/settings-manager.d.ts +31 -1
  242. package/dist/core/settings-manager.d.ts.map +1 -1
  243. package/dist/core/settings-manager.js +72 -2
  244. package/dist/core/settings-manager.js.map +1 -1
  245. package/dist/core/skills.d.ts.map +1 -1
  246. package/dist/core/skills.js.map +1 -1
  247. package/dist/core/slash-commands.d.ts.map +1 -1
  248. package/dist/core/source-info.d.ts +8 -0
  249. package/dist/core/source-info.d.ts.map +1 -1
  250. package/dist/core/source-info.js +16 -0
  251. package/dist/core/source-info.js.map +1 -1
  252. package/dist/core/system-prompt.d.ts.map +1 -1
  253. package/dist/core/system-prompt.js +1 -1
  254. package/dist/core/system-prompt.js.map +1 -1
  255. package/dist/core/telemetry.d.ts.map +1 -1
  256. package/dist/core/telemetry.js.map +1 -1
  257. package/dist/core/timings.d.ts.map +1 -1
  258. package/dist/core/timings.js.map +1 -1
  259. package/dist/core/tools/bash.d.ts +12 -0
  260. package/dist/core/tools/bash.d.ts.map +1 -1
  261. package/dist/core/tools/bash.js +35 -2
  262. package/dist/core/tools/bash.js.map +1 -1
  263. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  264. package/dist/core/tools/edit-diff.js.map +1 -1
  265. package/dist/core/tools/edit.d.ts.map +1 -1
  266. package/dist/core/tools/edit.js.map +1 -1
  267. package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
  268. package/dist/core/tools/file-mutation-queue.js.map +1 -1
  269. package/dist/core/tools/find.d.ts.map +1 -1
  270. package/dist/core/tools/find.js.map +1 -1
  271. package/dist/core/tools/grep.d.ts.map +1 -1
  272. package/dist/core/tools/grep.js.map +1 -1
  273. package/dist/core/tools/index.d.ts.map +1 -1
  274. package/dist/core/tools/index.js.map +1 -1
  275. package/dist/core/tools/ls.d.ts.map +1 -1
  276. package/dist/core/tools/ls.js.map +1 -1
  277. package/dist/core/tools/output-accumulator.d.ts +11 -0
  278. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  279. package/dist/core/tools/output-accumulator.js +36 -0
  280. package/dist/core/tools/output-accumulator.js.map +1 -1
  281. package/dist/core/tools/path-utils.d.ts.map +1 -1
  282. package/dist/core/tools/path-utils.js.map +1 -1
  283. package/dist/core/tools/powershell.d.ts.map +1 -1
  284. package/dist/core/tools/powershell.js.map +1 -1
  285. package/dist/core/tools/read.d.ts.map +1 -1
  286. package/dist/core/tools/read.js.map +1 -1
  287. package/dist/core/tools/render-utils.d.ts +6 -0
  288. package/dist/core/tools/render-utils.d.ts.map +1 -1
  289. package/dist/core/tools/render-utils.js +26 -0
  290. package/dist/core/tools/render-utils.js.map +1 -1
  291. package/dist/core/tools/renderers/bash.d.ts.map +1 -1
  292. package/dist/core/tools/renderers/bash.js +9 -10
  293. package/dist/core/tools/renderers/bash.js.map +1 -1
  294. package/dist/core/tools/renderers/edit.d.ts.map +1 -1
  295. package/dist/core/tools/renderers/edit.js.map +1 -1
  296. package/dist/core/tools/renderers/find.d.ts.map +1 -1
  297. package/dist/core/tools/renderers/find.js.map +1 -1
  298. package/dist/core/tools/renderers/grep.d.ts.map +1 -1
  299. package/dist/core/tools/renderers/grep.js.map +1 -1
  300. package/dist/core/tools/renderers/index.d.ts.map +1 -1
  301. package/dist/core/tools/renderers/index.js.map +1 -1
  302. package/dist/core/tools/renderers/ls.d.ts.map +1 -1
  303. package/dist/core/tools/renderers/ls.js.map +1 -1
  304. package/dist/core/tools/renderers/read.d.ts.map +1 -1
  305. package/dist/core/tools/renderers/read.js +3 -2
  306. package/dist/core/tools/renderers/read.js.map +1 -1
  307. package/dist/core/tools/renderers/write.d.ts.map +1 -1
  308. package/dist/core/tools/renderers/write.js.map +1 -1
  309. package/dist/core/tools/tool-definition-wrapper.d.ts +5 -3
  310. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  311. package/dist/core/tools/tool-definition-wrapper.js +3 -1
  312. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  313. package/dist/core/tools/truncate.d.ts +14 -0
  314. package/dist/core/tools/truncate.d.ts.map +1 -1
  315. package/dist/core/tools/truncate.js +29 -0
  316. package/dist/core/tools/truncate.js.map +1 -1
  317. package/dist/core/tools/write.d.ts.map +1 -1
  318. package/dist/core/tools/write.js.map +1 -1
  319. package/dist/core/trust-manager.d.ts.map +1 -1
  320. package/dist/core/trust-manager.js +1 -0
  321. package/dist/core/trust-manager.js.map +1 -1
  322. package/dist/core/usage-totals.d.ts +2 -0
  323. package/dist/core/usage-totals.d.ts.map +1 -1
  324. package/dist/core/usage-totals.js +23 -0
  325. package/dist/core/usage-totals.js.map +1 -1
  326. package/dist/core/virtual-models.d.ts +115 -0
  327. package/dist/core/virtual-models.d.ts.map +1 -0
  328. package/dist/core/virtual-models.js +117 -0
  329. package/dist/core/virtual-models.js.map +1 -0
  330. package/dist/extensions/codemode/execute.d.ts +16 -0
  331. package/dist/extensions/codemode/execute.d.ts.map +1 -0
  332. package/dist/extensions/codemode/execute.js +390 -0
  333. package/dist/extensions/codemode/execute.js.map +1 -0
  334. package/dist/extensions/codemode/execute.lazy.d.ts +3 -0
  335. package/dist/extensions/codemode/execute.lazy.d.ts.map +1 -0
  336. package/dist/extensions/codemode/execute.lazy.js +3 -0
  337. package/dist/extensions/codemode/execute.lazy.js.map +1 -0
  338. package/dist/extensions/codemode/index.d.ts +21 -0
  339. package/dist/extensions/codemode/index.d.ts.map +1 -0
  340. package/dist/extensions/codemode/index.js +31 -0
  341. package/dist/extensions/codemode/index.js.map +1 -0
  342. package/dist/extensions/codemode/renderer.d.ts +12 -0
  343. package/dist/extensions/codemode/renderer.d.ts.map +1 -0
  344. package/dist/extensions/codemode/renderer.js +119 -0
  345. package/dist/extensions/codemode/renderer.js.map +1 -0
  346. package/dist/extensions/codemode/tool.d.ts +122 -0
  347. package/dist/extensions/codemode/tool.d.ts.map +1 -0
  348. package/dist/extensions/codemode/tool.js +324 -0
  349. package/dist/extensions/codemode/tool.js.map +1 -0
  350. package/dist/extensions/codemode/worker.d.ts +7 -0
  351. package/dist/extensions/codemode/worker.d.ts.map +1 -0
  352. package/dist/extensions/codemode/worker.js +7 -0
  353. package/dist/extensions/codemode/worker.js.map +1 -0
  354. package/dist/extensions/index.d.ts.map +1 -1
  355. package/dist/extensions/index.js +11 -1
  356. package/dist/extensions/index.js.map +1 -1
  357. package/dist/extensions/llama/client.d.ts.map +1 -1
  358. package/dist/extensions/llama/client.js.map +1 -1
  359. package/dist/extensions/llama/huggingface.d.ts.map +1 -1
  360. package/dist/extensions/llama/huggingface.js.map +1 -1
  361. package/dist/extensions/llama/index.d.ts.map +1 -1
  362. package/dist/extensions/llama/index.js.map +1 -1
  363. package/dist/extensions/llama/provider.d.ts +1 -1
  364. package/dist/extensions/llama/provider.d.ts.map +1 -1
  365. package/dist/extensions/llama/provider.js +65 -13
  366. package/dist/extensions/llama/provider.js.map +1 -1
  367. package/dist/extensions/llama/ui.d.ts.map +1 -1
  368. package/dist/extensions/llama/ui.js.map +1 -1
  369. package/dist/extensions/mcp/cli.d.ts +21 -0
  370. package/dist/extensions/mcp/cli.d.ts.map +1 -0
  371. package/dist/extensions/mcp/cli.js +485 -0
  372. package/dist/extensions/mcp/cli.js.map +1 -0
  373. package/dist/extensions/mcp/cli.lazy.d.ts +3 -0
  374. package/dist/extensions/mcp/cli.lazy.d.ts.map +1 -0
  375. package/dist/extensions/mcp/cli.lazy.js +3 -0
  376. package/dist/extensions/mcp/cli.lazy.js.map +1 -0
  377. package/dist/extensions/mcp/config.d.ts +70 -0
  378. package/dist/extensions/mcp/config.d.ts.map +1 -0
  379. package/dist/extensions/mcp/config.js +146 -0
  380. package/dist/extensions/mcp/config.js.map +1 -0
  381. package/dist/extensions/mcp/index.d.ts +52 -0
  382. package/dist/extensions/mcp/index.d.ts.map +1 -0
  383. package/dist/extensions/mcp/index.js +902 -0
  384. package/dist/extensions/mcp/index.js.map +1 -0
  385. package/dist/extensions/mcp/log.d.ts +16 -0
  386. package/dist/extensions/mcp/log.d.ts.map +1 -0
  387. package/dist/extensions/mcp/log.js +66 -0
  388. package/dist/extensions/mcp/log.js.map +1 -0
  389. package/dist/extensions/mcp/oauth.d.ts +94 -0
  390. package/dist/extensions/mcp/oauth.d.ts.map +1 -0
  391. package/dist/extensions/mcp/oauth.js +333 -0
  392. package/dist/extensions/mcp/oauth.js.map +1 -0
  393. package/dist/extensions/mcp/resources.d.ts +43 -0
  394. package/dist/extensions/mcp/resources.d.ts.map +1 -0
  395. package/dist/extensions/mcp/resources.js +262 -0
  396. package/dist/extensions/mcp/resources.js.map +1 -0
  397. package/dist/extensions/mcp/runtime.d.ts +96 -0
  398. package/dist/extensions/mcp/runtime.d.ts.map +1 -0
  399. package/dist/extensions/mcp/runtime.js +388 -0
  400. package/dist/extensions/mcp/runtime.js.map +1 -0
  401. package/dist/extensions/mcp/runtime.lazy.d.ts +3 -0
  402. package/dist/extensions/mcp/runtime.lazy.d.ts.map +1 -0
  403. package/dist/extensions/mcp/runtime.lazy.js +3 -0
  404. package/dist/extensions/mcp/runtime.lazy.js.map +1 -0
  405. package/dist/extensions/mcp/tools.d.ts +83 -0
  406. package/dist/extensions/mcp/tools.d.ts.map +1 -0
  407. package/dist/extensions/mcp/tools.js +233 -0
  408. package/dist/extensions/mcp/tools.js.map +1 -0
  409. package/dist/extensions/mcp/ui.d.ts +60 -0
  410. package/dist/extensions/mcp/ui.d.ts.map +1 -0
  411. package/dist/extensions/mcp/ui.js +172 -0
  412. package/dist/extensions/mcp/ui.js.map +1 -0
  413. package/dist/extensions/tool-search/index.d.ts +12 -0
  414. package/dist/extensions/tool-search/index.d.ts.map +1 -0
  415. package/dist/extensions/tool-search/index.js +15 -0
  416. package/dist/extensions/tool-search/index.js.map +1 -0
  417. package/dist/extensions/tool-search/tool.d.ts +72 -0
  418. package/dist/extensions/tool-search/tool.d.ts.map +1 -0
  419. package/dist/extensions/tool-search/tool.js +210 -0
  420. package/dist/extensions/tool-search/tool.js.map +1 -0
  421. package/dist/index.d.ts +9 -2
  422. package/dist/index.d.ts.map +1 -1
  423. package/dist/index.js +5 -0
  424. package/dist/index.js.map +1 -1
  425. package/dist/main.d.ts.map +1 -1
  426. package/dist/main.js +10 -0
  427. package/dist/main.js.map +1 -1
  428. package/dist/migrations.d.ts.map +1 -1
  429. package/dist/migrations.js.map +1 -1
  430. package/dist/modes/index.d.ts.map +1 -1
  431. package/dist/modes/interactive/bug-report.d.ts.map +1 -1
  432. package/dist/modes/interactive/bug-report.js.map +1 -1
  433. package/dist/modes/interactive/chat-viewport.d.ts.map +1 -1
  434. package/dist/modes/interactive/chat-viewport.js.map +1 -1
  435. package/dist/modes/interactive/components/armin.d.ts.map +1 -1
  436. package/dist/modes/interactive/components/armin.js.map +1 -1
  437. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  438. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  439. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  440. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  441. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
  442. package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
  443. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  444. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  445. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  446. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  447. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  448. package/dist/modes/interactive/components/config-selector.js +13 -3
  449. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  450. package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -1
  451. package/dist/modes/interactive/components/countdown-timer.js.map +1 -1
  452. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  453. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  454. package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -1
  455. package/dist/modes/interactive/components/custom-entry.js.map +1 -1
  456. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  457. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  458. package/dist/modes/interactive/components/daxnuts.d.ts.map +1 -1
  459. package/dist/modes/interactive/components/daxnuts.js.map +1 -1
  460. package/dist/modes/interactive/components/diff.d.ts.map +1 -1
  461. package/dist/modes/interactive/components/diff.js.map +1 -1
  462. package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
  463. package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  464. package/dist/modes/interactive/components/earendil-announcement.d.ts.map +1 -1
  465. package/dist/modes/interactive/components/earendil-announcement.js.map +1 -1
  466. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  467. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  468. package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  469. package/dist/modes/interactive/components/extension-input.js.map +1 -1
  470. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  471. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  472. package/dist/modes/interactive/components/first-time-setup.d.ts +4 -4
  473. package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -1
  474. package/dist/modes/interactive/components/first-time-setup.js +8 -2
  475. package/dist/modes/interactive/components/first-time-setup.js.map +1 -1
  476. package/dist/modes/interactive/components/footer.d.ts +7 -0
  477. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  478. package/dist/modes/interactive/components/footer.js +43 -3
  479. package/dist/modes/interactive/components/footer.js.map +1 -1
  480. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  481. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  482. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  483. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  484. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  485. package/dist/modes/interactive/components/markdown-transform.d.ts.map +1 -1
  486. package/dist/modes/interactive/components/markdown-transform.js.map +1 -1
  487. package/dist/modes/interactive/components/mermaid.d.ts.map +1 -1
  488. package/dist/modes/interactive/components/mermaid.js.map +1 -1
  489. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  490. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  491. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  492. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  493. package/dist/modes/interactive/components/pi-logo.d.ts +12 -0
  494. package/dist/modes/interactive/components/pi-logo.d.ts.map +1 -0
  495. package/dist/modes/interactive/components/pi-logo.js +25 -0
  496. package/dist/modes/interactive/components/pi-logo.js.map +1 -0
  497. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  498. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  499. package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
  500. package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
  501. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  502. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  503. package/dist/modes/interactive/components/settings-selector.d.ts +3 -1
  504. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  505. package/dist/modes/interactive/components/settings-selector.js +28 -6
  506. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  507. package/dist/modes/interactive/components/settings-submenu.d.ts.map +1 -1
  508. package/dist/modes/interactive/components/settings-submenu.js.map +1 -1
  509. package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
  510. package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
  511. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  512. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  513. package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -1
  514. package/dist/modes/interactive/components/status-indicator.js.map +1 -1
  515. package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
  516. package/dist/modes/interactive/components/theme-selector.js.map +1 -1
  517. package/dist/modes/interactive/components/themed-text.d.ts +17 -0
  518. package/dist/modes/interactive/components/themed-text.d.ts.map +1 -0
  519. package/dist/modes/interactive/components/themed-text.js +29 -0
  520. package/dist/modes/interactive/components/themed-text.js.map +1 -0
  521. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  522. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  523. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  524. package/dist/modes/interactive/components/tool-execution.js +2 -2
  525. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  526. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  527. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  528. package/dist/modes/interactive/components/trust-selector.d.ts.map +1 -1
  529. package/dist/modes/interactive/components/trust-selector.js.map +1 -1
  530. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
  531. package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
  532. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  533. package/dist/modes/interactive/components/user-message.js.map +1 -1
  534. package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -1
  535. package/dist/modes/interactive/components/visual-truncate.js.map +1 -1
  536. package/dist/modes/interactive/external-editor.d.ts.map +1 -1
  537. package/dist/modes/interactive/external-editor.js.map +1 -1
  538. package/dist/modes/interactive/interactive-mode.d.ts +11 -0
  539. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  540. package/dist/modes/interactive/interactive-mode.js +199 -161
  541. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  542. package/dist/modes/interactive/model-catalog-refresh.d.ts.map +1 -1
  543. package/dist/modes/interactive/model-catalog-refresh.js.map +1 -1
  544. package/dist/modes/interactive/model-search.d.ts.map +1 -1
  545. package/dist/modes/interactive/model-search.js.map +1 -1
  546. package/dist/modes/interactive/session-share.d.ts.map +1 -1
  547. package/dist/modes/interactive/session-share.js.map +1 -1
  548. package/dist/modes/interactive/theme/dark.json +59 -72
  549. package/dist/modes/interactive/theme/light.json +57 -69
  550. package/dist/modes/interactive/theme/system-theme.d.ts +54 -0
  551. package/dist/modes/interactive/theme/system-theme.d.ts.map +1 -0
  552. package/dist/modes/interactive/theme/system-theme.js +535 -0
  553. package/dist/modes/interactive/theme/system-theme.js.map +1 -0
  554. package/dist/modes/interactive/theme/theme-controller.d.ts +46 -6
  555. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
  556. package/dist/modes/interactive/theme/theme-controller.js +127 -47
  557. package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
  558. package/dist/modes/interactive/theme/theme-json.d.ts +1 -0
  559. package/dist/modes/interactive/theme/theme-json.d.ts.map +1 -1
  560. package/dist/modes/interactive/theme/theme-json.js +3 -1
  561. package/dist/modes/interactive/theme/theme-json.js.map +1 -1
  562. package/dist/modes/interactive/theme/theme-schema.json +7 -2
  563. package/dist/modes/interactive/theme/theme.d.ts +66 -39
  564. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  565. package/dist/modes/interactive/theme/theme.js +238 -317
  566. package/dist/modes/interactive/theme/theme.js.map +1 -1
  567. package/dist/modes/interactive/tui-renderer.d.ts +2 -1
  568. package/dist/modes/interactive/tui-renderer.d.ts.map +1 -1
  569. package/dist/modes/interactive/tui-renderer.js +1 -0
  570. package/dist/modes/interactive/tui-renderer.js.map +1 -1
  571. package/dist/modes/json-event.d.ts.map +1 -1
  572. package/dist/modes/json-event.js.map +1 -1
  573. package/dist/modes/print-mode.d.ts.map +1 -1
  574. package/dist/modes/print-mode.js.map +1 -1
  575. package/dist/modes/rpc/jsonl.d.ts.map +1 -1
  576. package/dist/modes/rpc/jsonl.js.map +1 -1
  577. package/dist/modes/rpc/rpc-client.d.ts +6 -6
  578. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  579. package/dist/modes/rpc/rpc-client.js +12 -8
  580. package/dist/modes/rpc/rpc-client.js.map +1 -1
  581. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  582. package/dist/modes/rpc/rpc-mode.js +7 -9
  583. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  584. package/dist/modes/rpc/rpc-types.d.ts +10 -1
  585. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  586. package/dist/modes/rpc/rpc-types.js.map +1 -1
  587. package/dist/package-manager-cli.d.ts.map +1 -1
  588. package/dist/package-manager-cli.js +6 -2
  589. package/dist/package-manager-cli.js.map +1 -1
  590. package/dist/rpc-entry.d.ts.map +1 -1
  591. package/dist/rpc-entry.js.map +1 -1
  592. package/dist/utils/abort.d.ts.map +1 -1
  593. package/dist/utils/abort.js.map +1 -1
  594. package/dist/utils/ansi.d.ts.map +1 -1
  595. package/dist/utils/ansi.js.map +1 -1
  596. package/dist/utils/changelog.d.ts.map +1 -1
  597. package/dist/utils/changelog.js.map +1 -1
  598. package/dist/utils/child-process.d.ts.map +1 -1
  599. package/dist/utils/child-process.js.map +1 -1
  600. package/dist/utils/clipboard-command.d.ts.map +1 -1
  601. package/dist/utils/clipboard-command.js.map +1 -1
  602. package/dist/utils/clipboard-image.d.ts.map +1 -1
  603. package/dist/utils/clipboard-image.js +14 -17
  604. package/dist/utils/clipboard-image.js.map +1 -1
  605. package/dist/utils/clipboard.d.ts +2 -0
  606. package/dist/utils/clipboard.d.ts.map +1 -1
  607. package/dist/utils/clipboard.js +5 -0
  608. package/dist/utils/clipboard.js.map +1 -1
  609. package/dist/utils/deprecation.d.ts.map +1 -1
  610. package/dist/utils/deprecation.js.map +1 -1
  611. package/dist/utils/exif-orientation.d.ts.map +1 -1
  612. package/dist/utils/exif-orientation.js.map +1 -1
  613. package/dist/utils/frontmatter.d.ts.map +1 -1
  614. package/dist/utils/frontmatter.js.map +1 -1
  615. package/dist/utils/fs-watch.d.ts.map +1 -1
  616. package/dist/utils/fs-watch.js.map +1 -1
  617. package/dist/utils/git.d.ts.map +1 -1
  618. package/dist/utils/git.js.map +1 -1
  619. package/dist/utils/html.d.ts.map +1 -1
  620. package/dist/utils/html.js.map +1 -1
  621. package/dist/utils/image-convert.d.ts.map +1 -1
  622. package/dist/utils/image-convert.js.map +1 -1
  623. package/dist/utils/image-process.d.ts.map +1 -1
  624. package/dist/utils/image-process.js.map +1 -1
  625. package/dist/utils/image-resize-core.d.ts.map +1 -1
  626. package/dist/utils/image-resize-core.js.map +1 -1
  627. package/dist/utils/image-resize-worker.d.ts.map +1 -1
  628. package/dist/utils/image-resize-worker.js.map +1 -1
  629. package/dist/utils/image-resize.d.ts.map +1 -1
  630. package/dist/utils/image-resize.js.map +1 -1
  631. package/dist/utils/json.d.ts.map +1 -1
  632. package/dist/utils/json.js.map +1 -1
  633. package/dist/utils/management-http.d.ts.map +1 -1
  634. package/dist/utils/management-http.js.map +1 -1
  635. package/dist/utils/mime.d.ts.map +1 -1
  636. package/dist/utils/mime.js.map +1 -1
  637. package/dist/utils/open-browser.d.ts.map +1 -1
  638. package/dist/utils/open-browser.js.map +1 -1
  639. package/dist/utils/paths.d.ts +3 -3
  640. package/dist/utils/paths.d.ts.map +1 -1
  641. package/dist/utils/paths.js +5 -4
  642. package/dist/utils/paths.js.map +1 -1
  643. package/dist/utils/photon.d.ts.map +1 -1
  644. package/dist/utils/photon.js.map +1 -1
  645. package/dist/utils/pi-user-agent.d.ts.map +1 -1
  646. package/dist/utils/pi-user-agent.js.map +1 -1
  647. package/dist/utils/shell.d.ts +1 -3
  648. package/dist/utils/shell.d.ts.map +1 -1
  649. package/dist/utils/shell.js +3 -30
  650. package/dist/utils/shell.js.map +1 -1
  651. package/dist/utils/sleep.d.ts.map +1 -1
  652. package/dist/utils/sleep.js.map +1 -1
  653. package/dist/utils/syntax-highlight.d.ts.map +1 -1
  654. package/dist/utils/syntax-highlight.js +2 -0
  655. package/dist/utils/syntax-highlight.js.map +1 -1
  656. package/dist/utils/text.d.ts.map +1 -1
  657. package/dist/utils/text.js.map +1 -1
  658. package/dist/utils/tool-result-images.d.ts.map +1 -1
  659. package/dist/utils/tool-result-images.js.map +1 -1
  660. package/dist/utils/tools-manager.d.ts.map +1 -1
  661. package/dist/utils/tools-manager.js.map +1 -1
  662. package/dist/utils/version-check.d.ts.map +1 -1
  663. package/dist/utils/version-check.js.map +1 -1
  664. package/dist/utils/windows-self-update.d.ts.map +1 -1
  665. package/dist/utils/windows-self-update.js.map +1 -1
  666. package/dist/utils/wsl.d.ts.map +1 -1
  667. package/dist/utils/wsl.js.map +1 -1
  668. package/dist/utils/zip.d.ts.map +1 -1
  669. package/dist/utils/zip.js.map +1 -1
  670. package/docs/cli-integration.md +106 -0
  671. package/docs/cli.md +329 -0
  672. package/docs/compaction.md +22 -22
  673. package/docs/configuration.md +47 -0
  674. package/docs/containerization.md +109 -82
  675. package/docs/custom-provider.md +109 -722
  676. package/docs/docs.json +147 -99
  677. package/docs/environment-variables.md +3 -5
  678. package/docs/extensions.md +165 -2996
  679. package/docs/how-pi-works.md +49 -0
  680. package/docs/images/interactive-mode.png +0 -0
  681. package/docs/index.md +24 -69
  682. package/docs/json.md +193 -65
  683. package/docs/keybindings.md +58 -103
  684. package/docs/llama-cpp.md +16 -3
  685. package/docs/mcp.md +188 -0
  686. package/docs/message-types.md +261 -0
  687. package/docs/models.md +81 -556
  688. package/docs/packages.md +67 -166
  689. package/docs/prompt-templates.md +31 -68
  690. package/docs/providers.md +103 -240
  691. package/docs/quickstart.md +61 -106
  692. package/docs/rpc-commands.md +860 -0
  693. package/docs/rpc-extension-ui.md +200 -0
  694. package/docs/rpc.md +130 -1555
  695. package/docs/sdk.md +79 -1169
  696. package/docs/security.md +72 -32
  697. package/docs/session-format.md +15 -215
  698. package/docs/sessions.md +35 -141
  699. package/docs/settings.md +116 -377
  700. package/docs/shell-aliases.md +85 -5
  701. package/docs/skills.md +51 -190
  702. package/docs/slash-commands.md +60 -0
  703. package/docs/terminal-setup.md +105 -78
  704. package/docs/termux.md +74 -83
  705. package/docs/themes.md +88 -274
  706. package/docs/tmux.md +31 -39
  707. package/docs/tui.md +74 -910
  708. package/docs/usage.md +54 -272
  709. package/docs/virtual-models.md +114 -0
  710. package/docs/windows.md +45 -17
  711. package/examples/README.md +13 -2
  712. package/examples/extensions/README.md +2 -0
  713. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  714. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  715. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  716. package/examples/extensions/custom-provider-gitlab-duo/test.ts +5 -5
  717. package/examples/extensions/debug-provider.ts +90 -0
  718. package/examples/extensions/gondolin/package-lock.json +2 -2
  719. package/examples/extensions/gondolin/package.json +1 -1
  720. package/examples/extensions/jev-router.ts +113 -0
  721. package/examples/extensions/sandbox/package-lock.json +2 -2
  722. package/examples/extensions/sandbox/package.json +1 -1
  723. package/examples/extensions/with-deps/package-lock.json +2 -2
  724. package/examples/extensions/with-deps/package.json +1 -1
  725. package/examples/rpc-client.ts +35 -0
  726. package/examples/rpc-extension-ui.ts +26 -6
  727. package/examples/sdk/14-codemode-mcp.ts +61 -0
  728. package/examples/sdk/README.md +3 -2
  729. package/npm-shrinkwrap.json +89 -39
  730. package/package.json +14 -12
  731. package/dist/bundle/chunks/anthropic-messages-MYU5ZMRF.js +0 -6
  732. package/dist/bundle/chunks/azure-openai-responses-HUSQ3GP2.js +0 -2
  733. package/dist/bundle/chunks/chunk-4DKZACXI.js +0 -1568
  734. package/dist/bundle/chunks/chunk-6R7UI4IY.js +0 -2
  735. package/dist/bundle/chunks/chunk-GV2E3GBU.js +0 -2
  736. package/dist/bundle/chunks/chunk-NUHFSC37.js +0 -25
  737. package/dist/bundle/chunks/chunk-RCZIEVGO.js +0 -11
  738. package/dist/bundle/chunks/google-generative-ai-IMS5EK2Y.js +0 -2
  739. package/dist/bundle/chunks/google-vertex-O4YJEQUW.js +0 -2
  740. package/dist/bundle/chunks/mistral-conversations-NOSQHBEY.js +0 -5
  741. package/dist/bundle/chunks/openai-responses-HWEUZ6WZ.js +0 -2
  742. package/dist/bundle/chunks/virtual-modules-BNWPZYDH.js +0 -2
  743. package/docs/development.md +0 -90
package/docs/tui.md CHANGED
@@ -1,961 +1,125 @@
1
- > pi can create TUI components. Ask it to build one for your use case.
1
+ # Terminal UI
2
2
 
3
- # TUI Components
3
+ `@earendil-works/pi-tui` provides the terminal component system used by Pi. Extensions use it when built-in dialogs, notifications, status text, and widgets are not enough for the interaction they need.
4
4
 
5
- Extensions and custom tools can render custom TUI components for interactive user interfaces. This page covers the component system and available building blocks.
5
+ Start with `ctx.ui` methods from an [extension](extensions.md#interact-with-the-user). Build a custom component only when the UI needs its own rendering, keyboard or mouse input, focus, layout, or lifecycle.
6
6
 
7
- **Source:** [`@earendil-works/pi-tui`](https://github.com/earendil-works/pi/tree/main/packages/tui)
7
+ ## Choose an integration point
8
8
 
9
- ## Component Interface
9
+ | Need | Use |
10
+ |---|---|
11
+ | Select, confirm, input, or multi-line editor | `ctx.ui.select()`, `confirm()`, `input()`, or `editor()` |
12
+ | Non-blocking feedback | `ctx.ui.notify()` or `setStatus()` |
13
+ | Persistent content near the editor | `ctx.ui.setWidget()` |
14
+ | Replace the header, footer, or editor | The corresponding `ctx.ui` component factory |
15
+ | Temporary interactive screen or overlay | `ctx.ui.custom()` |
16
+ | Custom rendering for a tool or session entry | An extension renderer |
10
17
 
11
- All components implement:
18
+ These APIs receive Pi’s active theme and keybindings where needed. Do not create a second terminal renderer inside an extension.
12
19
 
13
- ```typescript
14
- interface Component {
15
- render(width: number): string[];
16
- handleInput?(data: string): void;
17
- handleMouse?(event: TuiMouseEvent): TuiMouseEventResult | undefined;
18
- wantsKeyRelease?: boolean;
19
- invalidate(): void;
20
- }
21
- ```
22
-
23
- | Method | Description |
24
- |--------|-------------|
25
- | `render(width)` | Return array of strings (one per line). Each line **must not exceed `width`**. |
26
- | `handleInput?(data)` | Receive keyboard input when component has focus. |
27
- | `handleMouse?(event)` | Receive normalized pointer input in fullscreen mode. |
28
- | `wantsKeyRelease?` | If true, component receives key release events (Kitty protocol). Default: false. |
29
- | `invalidate()` | Clear cached render state. Called on theme changes. |
30
-
31
- The TUI appends a full SGR reset and OSC 8 reset at the end of each rendered line. Styles do not carry across lines. If you emit multi-line text with styling, reapply styles per line or use `wrapTextWithAnsi()` so styles are preserved for each wrapped line.
32
-
33
- ## Focusable Interface (IME Support)
34
-
35
- Components that display a text cursor and need IME (Input Method Editor) support should implement the `Focusable` interface:
36
-
37
- ```typescript
38
- import { CURSOR_MARKER, type Component, type Focusable } from "@earendil-works/pi-tui";
39
-
40
- class MyInput implements Component, Focusable {
41
- focused: boolean = false; // Set by TUI when focus changes
42
-
43
- render(width: number): string[] {
44
- const marker = this.focused ? CURSOR_MARKER : "";
45
- // Emit marker right before the fake cursor
46
- return [`> ${beforeCursor}${marker}\x1b[7m${atCursor}\x1b[27m${afterCursor}`];
47
- }
48
- }
49
- ```
50
-
51
- When a `Focusable` component has focus, TUI:
52
- 1. Sets `focused = true` on the component
53
- 2. Scans rendered output for `CURSOR_MARKER` (a zero-width APC escape sequence)
54
- 3. Positions the hardware terminal cursor at that location
55
- 4. Shows the hardware cursor only when `showHardwareCursor` is enabled
56
-
57
- The cursor remains hidden by default. This keeps the fake cursor rendering, while still positioning the hardware cursor for terminals that track IME candidate windows with hidden cursors. Some terminals require a visible hardware cursor for IME positioning; enable it with the renderer's `showHardwareCursor` constructor argument or `setShowHardwareCursor(true)`. Pi also maps `PI_HARDWARE_CURSOR=1` to this setting before it creates its renderer. The `Editor` and `Input` built-in components already implement this interface.
58
-
59
- ### Container Components with Embedded Inputs
60
-
61
- When a container component (dialog, selector, etc.) contains an `Input` or `Editor` child, the container must implement `Focusable` and propagate the focus state to the child. Otherwise, the hardware cursor won't be positioned correctly for IME input.
62
-
63
- ```typescript
64
- import { Container, type Focusable, Input } from "@earendil-works/pi-tui";
65
-
66
- class SearchDialog extends Container implements Focusable {
67
- private searchInput: Input;
68
-
69
- // Focusable implementation - propagate to child input for IME cursor positioning
70
- private _focused = false;
71
- get focused(): boolean {
72
- return this._focused;
73
- }
74
- set focused(value: boolean) {
75
- this._focused = value;
76
- this.searchInput.focused = value;
77
- }
78
-
79
- constructor() {
80
- super();
81
- this.searchInput = new Input();
82
- this.addChild(this.searchInput);
83
- }
84
- }
85
- ```
86
-
87
- Without this propagation, typing with an IME (Chinese, Japanese, Korean, etc.) will show the candidate window in the wrong position on screen.
88
-
89
- ## Using Components
90
-
91
- **In extensions** via `ctx.ui.custom()`:
92
-
93
- ```typescript
94
- pi.on("session_start", async (_event, ctx) => {
95
- const result = await ctx.ui.custom<string | null>((tui, theme, keybindings, done) =>
96
- new MyComponent({
97
- theme,
98
- keybindings,
99
- onChange: () => tui.requestRender(),
100
- onSelect: (value) => done(value),
101
- onCancel: () => done(null),
102
- })
103
- );
104
- });
105
- ```
106
-
107
- **In custom tools** via `ctx.ui.custom()`:
20
+ ## Understand the component model
108
21
 
109
- ```typescript
110
- async execute(toolCallId, params, signal, onUpdate, ctx) {
111
- const result = await ctx.ui.custom<string | null>((tui, theme, keybindings, done) =>
112
- new MyComponent({
113
- theme,
114
- keybindings,
115
- onChange: () => tui.requestRender(),
116
- onSelect: (value) => done(value),
117
- onCancel: () => done(null),
118
- })
119
- );
120
- // Use result...
121
- }
122
- ```
22
+ A component renders an array of terminal lines for an available width. It can optionally handle keyboard and mouse input, and it must invalidate cached output when its state or theme-dependent content changes.
123
23
 
124
- ## Overlays
24
+ Every rendered line must fit within the supplied width. Measure visible terminal columns rather than string length because ANSI escapes, wide characters, emoji, and combining characters change display width.
125
25
 
126
- Overlays render components on top of existing content without clearing the screen. Pass `{ overlay: true }` to `ctx.ui.custom()`:
26
+ Use `visibleWidth()`, `truncateToWidth()`, `sliceByColumn()`, and `wrapTextWithAnsi()` instead of implementing terminal-width handling yourself. Pi resets styling and hyperlinks after every line, so reapply styles on each rendered line.
127
27
 
128
- ```typescript
129
- const result = await ctx.ui.custom<string | null>(
130
- (tui, theme, keybindings, done) => new MyDialog({ onClose: done }),
131
- { overlay: true }
132
- );
133
- ```
28
+ After changing component state, invalidate the affected component and call the injected `tui.requestRender()`. The TUI coalesces render requests and updates the terminal.
134
29
 
135
- For positioning and sizing, use `overlayOptions`:
30
+ ## Compose built-in components
136
31
 
137
- ```typescript
138
- const result = await ctx.ui.custom<string | null>(
139
- (tui, theme, keybindings, done) => new SidePanel({ onClose: done }),
140
- {
141
- overlay: true,
142
- overlayOptions: {
143
- // Size: number or percentage string
144
- width: "50%", // 50% of terminal width
145
- minWidth: 40, // minimum 40 columns
146
- maxHeight: "80%", // max 80% of terminal height
147
-
148
- // Position: anchor-based (default: "center")
149
- anchor: "right-center", // 9 positions: center, top-left, top-center, etc.
150
- offsetX: -2, // offset from anchor
151
- offsetY: 0,
152
-
153
- // Or percentage/absolute positioning
154
- row: "25%", // 25% from top
155
- col: 10, // column 10
156
-
157
- // Margins
158
- margin: 2, // all sides, or { top, right, bottom, left }
159
-
160
- // Responsive: hide on narrow terminals
161
- visible: (termWidth, termHeight) => termWidth >= 80,
162
- },
163
- // Get handle for programmatic focus and visibility control
164
- onHandle: (handle) => {
165
- // handle.focus() - focus this overlay and bring it to the visual front
166
- // handle.unfocus() - release input to normal fallback
167
- // handle.unfocus({ target }) - release input to a specific component or null
168
- // handle.setHidden(true/false) - toggle visibility
169
- // handle.hide() - permanently remove
170
- },
171
- }
172
- );
173
- ```
32
+ The package includes components for common layouts and controls:
174
33
 
175
- ### Overlay Focus
34
+ - `Text`, `Markdown`, `Image`, and `TruncatedText` render content.
35
+ - `Container`, `VStack`, `HStack`, `Box`, and `Spacer` compose layouts.
36
+ - `Input` and `Editor` accept text.
37
+ - `SelectList` and `SettingsList` implement searchable selection and settings flows.
38
+ - `ScrollView` provides a bounded scrollable viewport.
39
+ - `Loader` and `CancellableLoader` report ongoing work.
40
+ - `MouseRegion` adds pointer behavior around another component.
176
41
 
177
- A focused visible overlay keeps input ownership across temporary non-overlay UI. If an overlay opens another `ctx.ui.custom()` component without `{ overlay: true }`, that replacement UI receives input while it is active; when it closes, the focused overlay can reclaim input.
42
+ Prefer these components over rebuilding selection, scrolling, text editing, or width handling. The extension examples show how to combine them with Pi’s borders and themes.
178
43
 
179
- Use `handle.unfocus()` when a visible overlay should stop owning input and let TUI fall back to another visible capturing overlay or the previous focus target. Use `handle.unfocus({ target })` when a specific component should receive input while the overlay stays visible. Passing `{ target: null }` intentionally leaves no focused component until focus is set again.
44
+ ## Handle keyboard input and focus
180
45
 
181
- ### Overlay Lifecycle
46
+ Use `matchesKey()` and `Key` for terminal keyboard input. The parser accounts for supported terminal protocols and key modifiers. Extension components should use the injected `KeybindingsManager` for configurable application actions.
182
47
 
183
- Overlay components are disposed when closed. Don't reuse references - create fresh instances:
48
+ A component that displays a text cursor should implement `Focusable` and place `CURSOR_MARKER` immediately before its visual cursor. The TUI uses that marker to position the hardware cursor for input method editors.
184
49
 
185
- ```typescript
186
- // Wrong - stale reference
187
- let menu: MenuComponent;
188
- await ctx.ui.custom((_, __, ___, done) => {
189
- menu = new MenuComponent(done);
190
- return menu;
191
- }, { overlay: true });
192
- setActiveComponent(menu); // Disposed
193
-
194
- // Correct - re-call to re-show
195
- const showMenu = () => ctx.ui.custom((_, __, ___, done) =>
196
- new MenuComponent(done), { overlay: true });
197
-
198
- await showMenu(); // First show
199
- await showMenu(); // "Back" = just call again
200
- ```
50
+ Containers that wrap an `Input` or `Editor` must propagate their `focused` state to that child. Without propagation, Chinese, Japanese, Korean, and other IME candidate windows can appear at the wrong screen position.
201
51
 
202
- See [overlay-qa-tests.ts](../examples/extensions/overlay-qa-tests.ts) for comprehensive examples covering anchors, margins, stacking, responsive visibility, and animation.
52
+ Extend Pi’s `CustomEditor` when replacing the main editor. It preserves application shortcuts and agent controls.
203
53
 
204
- ## Built-in Components
54
+ Forward keys your editor does not own to the base implementation, and restore the default by clearing the custom editor factory.
205
55
 
206
- Import from `@earendil-works/pi-tui`:
56
+ ## Handle mouse input
207
57
 
208
- ```typescript
209
- import { Text, Box, Container, Spacer, Markdown } from "@earendil-works/pi-tui";
210
- ```
58
+ Fullscreen mode routes normalized mouse events to components. A handler can mark an event handled, capture a drag sequence, request focus, or request a render.
211
59
 
212
- ### Text
213
-
214
- Multi-line text with word wrapping.
215
-
216
- ```typescript
217
- const text = new Text(
218
- "Hello World", // content
219
- 1, // paddingX (default: 1)
220
- 1, // paddingY (default: 1)
221
- (s) => bgGray(s) // optional background function
222
- );
223
- text.setText("Updated");
224
- ```
225
-
226
- ### Box
227
-
228
- Container with padding and background color.
229
-
230
- ```typescript
231
- const box = new Box(
232
- 1, // paddingX
233
- 1, // paddingY
234
- (s) => bgGray(s) // background function
235
- );
236
- box.addChild(new Text("Content", 0, 0));
237
- box.setBgFn((s) => bgBlue(s));
238
- ```
60
+ Unhandled wheel events scroll the nearest `ScrollView`. Unhandled primary-button drags remain available for transcript selection. OSC 8 links take precedence over enclosing click regions.
239
61
 
240
- ### Container
62
+ Regular mode leaves mouse input to the terminal because the terminal owns scrollback. Design every interaction with a keyboard path even when fullscreen mouse input is available.
241
63
 
242
- Groups child components vertically.
64
+ ## Use custom screens and overlays
243
65
 
244
- ```typescript
245
- const container = new Container();
246
- container.addChild(component1);
247
- container.addChild(component2);
248
- container.removeChild(component1);
249
- ```
66
+ `ctx.ui.custom()` temporarily gives one component control of the interactive area and resolves when that component calls the supplied completion callback.
250
67
 
251
- ### Spacer
68
+ Pass `overlay: true` to draw above existing content. Overlay options control size, anchors, offsets, margins, and responsive visibility. An overlay handle can change focus or temporarily hide and show the overlay with `setHidden()` while the interaction remains active.
252
69
 
253
- Empty vertical space.
70
+ Focused overlays retain input ownership across ordinary renders. If another component should receive input while an overlay remains visible, explicitly release or redirect focus through the handle.
254
71
 
255
- ```typescript
256
- const spacer = new Spacer(2); // 2 empty lines
257
- ```
72
+ Treat each custom component instance as belonging to one interaction. Create a new instance when starting that interaction again.
258
73
 
259
- ### Markdown
74
+ Finish the interaction with the completion callback supplied to the component factory. It resolves the `ctx.ui.custom()` promise and disposes the component. Do not call `OverlayHandle.hide()` on an overlay created by `ctx.ui.custom()`.
260
75
 
261
- Renders markdown with syntax highlighting.
76
+ See [`overlay-qa-tests.ts`](../examples/extensions/overlay-qa-tests.ts) for positioning, stacking, focus, responsive visibility, and animation behavior.
262
77
 
263
- ```typescript
264
- const md = new Markdown(
265
- "# Title\n\nSome **bold** text",
266
- 1, // paddingX
267
- 1, // paddingY
268
- theme // MarkdownTheme (see below)
269
- );
270
- md.setText("Updated markdown");
271
- ```
78
+ ## Apply themes correctly
272
79
 
273
- ### Image
80
+ Use the theme passed to the extension or component callback. Theme helpers produce ANSI-styled strings for semantic colors such as accent, muted text, success, warnings, errors, tool output, and Markdown.
274
81
 
275
- Renders images in supported terminals (Kitty, iTerm2, Ghostty, WezTerm, Warp).
82
+ Use `theme.style()` to combine foreground and background colors with text attributes:
276
83
 
277
84
  ```typescript
278
- const image = new Image(
279
- base64Data, // base64-encoded image
280
- "image/png", // MIME type
281
- theme, // ImageTheme
282
- { maxWidthCells: 80, maxHeightCells: 24 }
85
+ return new Text(
86
+ theme.style("Done!", {
87
+ fg: "success",
88
+ bg: "toolSuccessBg",
89
+ bold: true,
90
+ }),
91
+ 0,
92
+ 0,
283
93
  );
284
94
  ```
285
95
 
286
- ## Keyboard Input
287
-
288
- Use `matchesKey()` for key detection:
289
-
290
- ```typescript
291
- import { matchesKey, Key } from "@earendil-works/pi-tui";
292
-
293
- handleInput(data: string) {
294
- if (matchesKey(data, Key.up)) {
295
- this.selectedIndex--;
296
- } else if (matchesKey(data, Key.enter)) {
297
- this.onSelect?.(this.selectedIndex);
298
- } else if (matchesKey(data, Key.escape)) {
299
- this.onCancel?.();
300
- } else if (matchesKey(data, Key.ctrl("c"))) {
301
- // Ctrl+C
302
- }
303
- }
304
- ```
305
-
306
- **Key identifiers** (use `Key.*` for autocomplete, or string literals):
307
- - Basic keys: `Key.enter`, `Key.escape`, `Key.tab`, `Key.space`, `Key.backspace`, `Key.delete`, `Key.home`, `Key.end`
308
- - Arrow keys: `Key.up`, `Key.down`, `Key.left`, `Key.right`
309
- - With modifiers: `Key.ctrl("c")`, `Key.shift("tab")`, `Key.alt("left")`, `Key.ctrlShift("p")`
310
- - String format also works: `"enter"`, `"ctrl+c"`, `"shift+tab"`, `"ctrl+shift+p"`
311
-
312
- ## Mouse Input
313
-
314
- Fullscreen mode routes normalized press, release, click, move, drag, and wheel events to components and overlays. Return `{ handled: true }` to suppress default behavior, `capture: true` to retain drag/release ownership, `focus: true` to request keyboard focus, and `render: true` when a hover or release visibly changes the component. Press, click, drag, and wheel render by default; no-op move/release events do not.
315
-
316
- ```typescript
317
- import { MouseRegion } from "@earendil-works/pi-tui";
318
-
319
- const clickable = new MouseRegion(content, (event) => {
320
- if (event.type !== "click" || event.button !== "left") return undefined;
321
- expanded = !expanded;
322
- return { handled: true };
323
- });
324
- ```
325
-
326
- Unhandled wheel input scrolls the nearest `ScrollView`; unhandled primary-button drags retain transcript selection. OSC 8 links take precedence over parent click regions. `Input`, `Editor`, `SelectList`, and `SettingsList` include fullscreen mouse behavior. Regular mode does not capture mouse input because the terminal owns its scrollback.
327
-
328
- ## Line Width
329
-
330
- **Critical:** Each line from `render()` must not exceed the `width` parameter.
331
-
332
- ```typescript
333
- import { visibleWidth, truncateToWidth } from "@earendil-works/pi-tui";
334
-
335
- render(width: number): string[] {
336
- // Truncate long lines
337
- return [truncateToWidth(this.text, width)];
338
- }
339
- ```
340
-
341
- Utilities:
342
- - `visibleWidth(str)` - Get display width (ignores ANSI codes)
343
- - `truncateToWidth(str, width, ellipsis?)` - Truncate with optional ellipsis
344
- - `wrapTextWithAnsi(str, width)` - Word wrap preserving ANSI codes
345
-
346
- ## Creating Custom Components
347
-
348
- Example: Interactive selector
349
-
350
- ```typescript
351
- import {
352
- matchesKey, Key,
353
- truncateToWidth, visibleWidth
354
- } from "@earendil-works/pi-tui";
355
-
356
- class MySelector {
357
- private items: string[];
358
- private selected = 0;
359
- private cachedWidth?: number;
360
- private cachedLines?: string[];
361
-
362
- public onSelect?: (item: string) => void;
363
- public onCancel?: () => void;
364
-
365
- constructor(items: string[]) {
366
- this.items = items;
367
- }
368
-
369
- handleInput(data: string): void {
370
- if (matchesKey(data, Key.up) && this.selected > 0) {
371
- this.selected--;
372
- this.invalidate();
373
- } else if (matchesKey(data, Key.down) && this.selected < this.items.length - 1) {
374
- this.selected++;
375
- this.invalidate();
376
- } else if (matchesKey(data, Key.enter)) {
377
- this.onSelect?.(this.items[this.selected]);
378
- } else if (matchesKey(data, Key.escape)) {
379
- this.onCancel?.();
380
- }
381
- }
382
-
383
- render(width: number): string[] {
384
- if (this.cachedLines && this.cachedWidth === width) {
385
- return this.cachedLines;
386
- }
387
-
388
- this.cachedLines = this.items.map((item, i) => {
389
- const prefix = i === this.selected ? "> " : " ";
390
- return truncateToWidth(prefix + item, width);
391
- });
392
- this.cachedWidth = width;
393
- return this.cachedLines;
394
- }
395
-
396
- invalidate(): void {
397
- this.cachedWidth = undefined;
398
- this.cachedLines = undefined;
399
- }
400
- }
401
- ```
402
-
403
- Usage in an extension:
404
-
405
- ```typescript
406
- pi.registerCommand("pick", {
407
- description: "Pick an item",
408
- handler: async (_args, ctx) => {
409
- const items = ["Option A", "Option B", "Option C"];
410
- const selected = await ctx.ui.custom<string | null>((tui, _theme, _keybindings, done) => {
411
- const selector = new MySelector(items);
412
- selector.onSelect = done;
413
- selector.onCancel = () => done(null);
414
-
415
- return {
416
- render: (width) => selector.render(width),
417
- handleInput: (data) => {
418
- selector.handleInput(data);
419
- tui.requestRender();
420
- },
421
- invalidate: () => selector.invalidate(),
422
- };
423
- });
424
-
425
- if (selected !== null) {
426
- ctx.ui.notify(`Selected: ${selected}`, "info");
427
- }
428
- }
429
- });
430
- ```
431
-
432
- ## Theming
433
-
434
- Components accept theme objects for styling.
435
-
436
- **In `renderCall`/`renderResult`**, use the `theme` parameter:
437
-
438
- ```typescript
439
- renderResult(result, options, theme, context) {
440
- // Use theme.fg() for foreground colors
441
- return new Text(theme.fg("success", "Done!"), 0, 0);
442
-
443
- // Use theme.bg() for background colors
444
- const styled = theme.bg("toolPendingBg", theme.fg("accent", "text"));
445
- }
446
- ```
447
-
448
- **Foreground colors** (`theme.fg(color, text)`):
449
-
450
- | Category | Colors |
451
- |----------|--------|
452
- | General | `text`, `accent`, `muted`, `dim`, `searchMatchText` |
453
- | Status | `success`, `error`, `warning` |
454
- | Borders | `border`, `borderAccent`, `borderMuted` |
455
- | Messages | `userMessageText`, `customMessageText`, `customMessageLabel` |
456
- | Tools | `toolTitle`, `toolOutput` |
457
- | Diffs | `toolDiffAdded`, `toolDiffRemoved`, `toolDiffContext` |
458
- | Markdown | `mdHeading`, `mdLink`, `mdLinkUrl`, `mdCode`, `mdCodeBlock`, `mdCodeBlockBorder`, `mdQuote`, `mdQuoteBorder`, `mdHr`, `mdListBullet` |
459
- | Syntax | `syntaxComment`, `syntaxKeyword`, `syntaxFunction`, `syntaxVariable`, `syntaxString`, `syntaxNumber`, `syntaxType`, `syntaxOperator`, `syntaxPunctuation` |
460
- | Thinking | `thinkingOff`, `thinkingMinimal`, `thinkingLow`, `thinkingMedium`, `thinkingHigh`, `thinkingXhigh`, `thinkingMax` |
461
- | Modes | `bashMode` |
462
-
463
- **Background colors** (`theme.bg(color, text)`):
464
-
465
- `selectedBg`, `searchMatchBg`, `userMessageBg`, `customMessageBg`, `toolPendingBg`, `toolSuccessBg`, `toolErrorBg`
466
-
467
- **For Markdown**, use `getMarkdownTheme()`:
468
-
469
- ```typescript
470
- import { getMarkdownTheme } from "@earendil-works/pi-coding-agent";
471
- import { Markdown } from "@earendil-works/pi-tui";
472
-
473
- renderResult(result, options, theme, context) {
474
- const mdTheme = getMarkdownTheme();
475
- return new Markdown(result.details.markdown, 0, 0, mdTheme);
476
- }
477
- ```
478
-
479
- **For custom components**, define your own theme interface:
480
-
481
- ```typescript
482
- interface MyTheme {
483
- selected: (s: string) => string;
484
- normal: (s: string) => string;
485
- }
486
- ```
487
-
488
- ## Debug logging
489
-
490
- Set `PI_TUI_WRITE_LOG` to capture the raw ANSI stream written to stdout.
491
-
492
- ```bash
493
- PI_TUI_WRITE_LOG=/tmp/tui-ansi.log npx tsx packages/tui/test/chat-simple.ts
494
- ```
495
-
496
- ## Performance
497
-
498
- Cache rendered output when possible:
499
-
500
- ```typescript
501
- class CachedComponent {
502
- private cachedWidth?: number;
503
- private cachedLines?: string[];
504
-
505
- render(width: number): string[] {
506
- if (this.cachedLines && this.cachedWidth === width) {
507
- return this.cachedLines;
508
- }
509
- // ... compute lines ...
510
- this.cachedWidth = width;
511
- this.cachedLines = lines;
512
- return lines;
513
- }
514
-
515
- invalidate(): void {
516
- this.cachedWidth = undefined;
517
- this.cachedLines = undefined;
518
- }
519
- }
520
- ```
521
-
522
- Call `invalidate()` when state changes, then use the injected `tui.requestRender()` to trigger re-render.
523
-
524
- ## Invalidation and Theme Changes
525
-
526
- When the theme changes, the TUI calls `invalidate()` on all components to clear their caches. Components must properly implement `invalidate()` to ensure theme changes take effect.
527
-
528
- ### The Problem
529
-
530
- If a component pre-bakes theme colors into strings (via `theme.fg()`, `theme.bg()`, etc.) and caches them, the cached strings contain ANSI escape codes from the old theme. Simply clearing the render cache isn't enough if the component stores the themed content separately.
531
-
532
- **Wrong approach** (theme colors won't update):
533
-
534
- ```typescript
535
- class BadComponent extends Container {
536
- private content: Text;
537
-
538
- constructor(message: string, theme: Theme) {
539
- super();
540
- // Pre-baked theme colors stored in Text component
541
- this.content = new Text(theme.fg("accent", message), 1, 0);
542
- this.addChild(this.content);
543
- }
544
- // No invalidate override - parent's invalidate only clears
545
- // child render caches, not the pre-baked content
546
- }
547
- ```
548
-
549
- ### The Solution
550
-
551
- Components that build content with theme colors must rebuild that content when `invalidate()` is called:
552
-
553
- ```typescript
554
- class GoodComponent extends Container {
555
- private message: string;
556
- private content: Text;
557
-
558
- constructor(message: string) {
559
- super();
560
- this.message = message;
561
- this.content = new Text("", 1, 0);
562
- this.addChild(this.content);
563
- this.updateDisplay();
564
- }
565
-
566
- private updateDisplay(): void {
567
- // Rebuild content with current theme
568
- this.content.setText(theme.fg("accent", this.message));
569
- }
570
-
571
- override invalidate(): void {
572
- super.invalidate(); // Clear child caches
573
- this.updateDisplay(); // Rebuild with new theme
574
- }
575
- }
576
- ```
577
-
578
- ### Pattern: Rebuild on Invalidate
579
-
580
- For components with complex content:
581
-
582
- ```typescript
583
- class ComplexComponent extends Container {
584
- private data: SomeData;
585
-
586
- constructor(data: SomeData) {
587
- super();
588
- this.data = data;
589
- this.rebuild();
590
- }
591
-
592
- private rebuild(): void {
593
- this.clear(); // Remove all children
594
-
595
- // Build UI with current theme
596
- this.addChild(new Text(theme.fg("accent", theme.bold("Title")), 1, 0));
597
- this.addChild(new Spacer(1));
598
-
599
- for (const item of this.data.items) {
600
- const color = item.active ? "success" : "muted";
601
- this.addChild(new Text(theme.fg(color, item.label), 1, 0));
602
- }
603
- }
604
-
605
- override invalidate(): void {
606
- super.invalidate();
607
- this.rebuild();
608
- }
609
- }
610
- ```
611
-
612
- ### When This Matters
613
-
614
- This pattern is needed when:
615
-
616
- 1. **Pre-baking theme colors** - Using `theme.fg()` or `theme.bg()` to create styled strings stored in child components
617
- 2. **Syntax highlighting** - Using `highlightCode()` which applies theme-based syntax colors
618
- 3. **Complex layouts** - Building child component trees that embed theme colors
619
-
620
- This pattern is NOT needed when:
621
-
622
- 1. **Using theme callbacks** - Passing functions like `(text) => theme.fg("accent", text)` that are called during render
623
- 2. **Simple containers** - Just grouping other components without adding themed content
624
- 3. **Stateless render** - Computing themed output fresh in every `render()` call (no caching)
625
-
626
- ## Common Patterns
627
-
628
- These patterns cover the most common UI needs in extensions. **Copy these patterns instead of building from scratch.**
629
-
630
- ### Pattern 1: Selection Dialog (SelectList)
631
-
632
- For letting users pick from a list of options. Use `SelectList` from `@earendil-works/pi-tui` with `DynamicBorder` for framing.
633
-
634
- ```typescript
635
- import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
636
- import { DynamicBorder } from "@earendil-works/pi-coding-agent";
637
- import { Container, type SelectItem, SelectList, Text } from "@earendil-works/pi-tui";
638
-
639
- pi.registerCommand("pick", {
640
- handler: async (_args, ctx) => {
641
- const items: SelectItem[] = [
642
- { value: "opt1", label: "Option 1", description: "First option" },
643
- { value: "opt2", label: "Option 2", description: "Second option" },
644
- { value: "opt3", label: "Option 3" }, // description is optional
645
- ];
646
-
647
- const result = await ctx.ui.custom<string | null>((tui, theme, _kb, done) => {
648
- const container = new Container();
649
-
650
- // Top border
651
- container.addChild(new DynamicBorder((s: string) => theme.fg("accent", s)));
652
-
653
- // Title
654
- container.addChild(new Text(theme.fg("accent", theme.bold("Pick an Option")), 1, 0));
655
-
656
- // SelectList with theme
657
- const selectList = new SelectList(items, Math.min(items.length, 10), {
658
- selectedPrefix: (t) => theme.fg("accent", t),
659
- selectedText: (t) => theme.fg("accent", t),
660
- description: (t) => theme.fg("muted", t),
661
- scrollInfo: (t) => theme.fg("dim", t),
662
- noMatch: (t) => theme.fg("warning", t),
663
- });
664
- selectList.onSelect = (item) => done(item.value);
665
- selectList.onCancel = () => done(null);
666
- container.addChild(selectList);
667
-
668
- // Help text
669
- container.addChild(new Text(theme.fg("dim", "↑↓ navigate • enter select • esc cancel"), 1, 0));
670
-
671
- // Bottom border
672
- container.addChild(new DynamicBorder((s: string) => theme.fg("accent", s)));
673
-
674
- return {
675
- render: (w) => container.render(w),
676
- invalidate: () => container.invalidate(),
677
- handleInput: (data) => { selectList.handleInput(data); tui.requestRender(); },
678
- };
679
- });
680
-
681
- if (result) {
682
- ctx.ui.notify(`Selected: ${result}`, "info");
683
- }
684
- },
685
- });
686
- ```
687
-
688
- **Examples:** [preset.ts](../examples/extensions/preset.ts), [tools.ts](../examples/extensions/tools.ts)
689
-
690
- ### Pattern 2: Async Operation with Cancel (BorderedLoader)
691
-
692
- For operations that take time and should be cancellable. `BorderedLoader` shows a spinner and handles escape to cancel.
693
-
694
- ```typescript
695
- import { BorderedLoader } from "@earendil-works/pi-coding-agent";
696
-
697
- pi.registerCommand("fetch", {
698
- handler: async (_args, ctx) => {
699
- const result = await ctx.ui.custom<string | null>((tui, theme, _kb, done) => {
700
- const loader = new BorderedLoader(tui, theme, "Fetching data...");
701
- loader.onAbort = () => done(null);
702
-
703
- // Do async work
704
- fetchData(loader.signal)
705
- .then((data) => done(data))
706
- .catch(() => done(null));
707
-
708
- return loader;
709
- });
710
-
711
- if (result === null) {
712
- ctx.ui.notify("Cancelled", "info");
713
- } else {
714
- ctx.ui.setEditorText(result);
715
- }
716
- },
717
- });
718
- ```
719
-
720
- **Examples:** [qna.ts](../examples/extensions/qna.ts), [handoff.ts](../examples/extensions/handoff.ts)
721
-
722
- ### Pattern 3: Settings/Toggles (SettingsList)
723
-
724
- For toggling multiple settings. Use `SettingsList` from `@earendil-works/pi-tui` with `getSettingsListTheme()`.
725
-
726
- ```typescript
727
- import { getSettingsListTheme } from "@earendil-works/pi-coding-agent";
728
- import { Container, type SettingItem, SettingsList, Text } from "@earendil-works/pi-tui";
729
-
730
- pi.registerCommand("settings", {
731
- handler: async (_args, ctx) => {
732
- const items: SettingItem[] = [
733
- { id: "verbose", label: "Verbose mode", currentValue: "off", values: ["on", "off"] },
734
- { id: "color", label: "Color output", currentValue: "on", values: ["on", "off"] },
735
- ];
736
-
737
- await ctx.ui.custom((_tui, theme, _kb, done) => {
738
- const container = new Container();
739
- container.addChild(new Text(theme.fg("accent", theme.bold("Settings")), 1, 1));
740
-
741
- const settingsList = new SettingsList(
742
- items,
743
- Math.min(items.length + 2, 15),
744
- getSettingsListTheme(),
745
- (id, newValue) => {
746
- // Handle value change
747
- ctx.ui.notify(`${id} = ${newValue}`, "info");
748
- },
749
- () => done(undefined), // On close
750
- { enableSearch: true }, // Optional: enable fuzzy search by label
751
- );
752
- container.addChild(settingsList);
753
-
754
- return {
755
- render: (w) => container.render(w),
756
- invalidate: () => container.invalidate(),
757
- handleInput: (data) => settingsList.handleInput?.(data),
758
- };
759
- });
760
- },
761
- });
762
- ```
763
-
764
- **Examples:** [tools.ts](../examples/extensions/tools.ts)
765
-
766
- ### Pattern 4: Persistent Status Indicator
767
-
768
- Show status in the footer that persists across renders. Good for mode indicators.
769
-
770
- ```typescript
771
- // Set status (shown in footer)
772
- ctx.ui.setStatus("my-ext", ctx.ui.theme.fg("accent", "● active"));
773
-
774
- // Clear status
775
- ctx.ui.setStatus("my-ext", undefined);
776
- ```
777
-
778
- **Examples:** [status-line.ts](../examples/extensions/status-line.ts), [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts), [preset.ts](../examples/extensions/preset.ts)
779
-
780
- ### Pattern 4b: Working Indicator Customization
781
-
782
- Customize the inline working indicator shown while pi is streaming a response.
783
-
784
- ```typescript
785
- // Static indicator
786
- ctx.ui.setWorkingIndicator({ frames: [ctx.ui.theme.fg("accent", "●")] });
787
-
788
- // Custom animated indicator
789
- ctx.ui.setWorkingIndicator({
790
- frames: [
791
- ctx.ui.theme.fg("dim", "·"),
792
- ctx.ui.theme.fg("muted", "•"),
793
- ctx.ui.theme.fg("accent", "●"),
794
- ctx.ui.theme.fg("muted", "•"),
795
- ],
796
- intervalMs: 120,
797
- });
798
-
799
- // Hide the indicator entirely
800
- ctx.ui.setWorkingIndicator({ frames: [] });
801
-
802
- // Restore pi's default spinner
803
- ctx.ui.setWorkingIndicator();
804
- ```
805
-
806
- This only affects the normal streaming working indicator. Compaction and retry loaders keep their built-in styling. Custom frames are rendered verbatim, so extensions must add their own colors when needed.
807
-
808
- **Examples:** [working-indicator.ts](../examples/extensions/working-indicator.ts)
809
-
810
- ### Pattern 5: Widgets Above/Below Editor
811
-
812
- Show persistent content above or below the input editor. Good for todo lists, progress.
813
-
814
- ```typescript
815
- // Simple string array (above editor by default)
816
- ctx.ui.setWidget("my-widget", ["Line 1", "Line 2"]);
817
-
818
- // Render below the editor
819
- ctx.ui.setWidget("my-widget", ["Line 1", "Line 2"], { placement: "belowEditor" });
820
-
821
- // Or with theme
822
- ctx.ui.setWidget("my-widget", (_tui, theme) => {
823
- const lines = items.map((item, i) =>
824
- item.done
825
- ? theme.fg("success", "✓ ") + theme.fg("muted", item.text)
826
- : theme.fg("dim", "○ ") + item.text
827
- );
828
- return {
829
- render: () => lines,
830
- invalidate: () => {},
831
- };
832
- });
833
-
834
- // Clear
835
- ctx.ui.setWidget("my-widget", undefined);
836
- ```
837
-
838
- **Examples:** [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts)
96
+ A style color can be a semantic theme token or a concrete `Color`. Foreground tokens are accepted as `fg` and background tokens as `bg`; to use a token's color in the other position, pass its concrete color, for example `{ fg: theme.colors.userMessageBg }`. Access concrete colors through `theme.colors` and use utilities such as `mixColors()` from `@earendil-works/pi-tui` when color math is needed. Tokens that a theme sets to the terminal default render with the terminal's own color; `theme.colors` reports the color the terminal announced for them, or a guess when it did not. Use `theme.appearance` (`"dark"` or `"light"`) to decide, for example, whether to lighten or darken a color. Pi converts the result to truecolor or 256-color output based on terminal capabilities. Theme tokens are converted once per theme; compute concrete colors outside the render path when possible.
839
97
 
840
- ### Pattern 6: Custom Footer
841
-
842
- Replace the footer. `footerData` exposes data not otherwise accessible to extensions.
843
-
844
- ```typescript
845
- ctx.ui.setFooter((tui, theme, footerData) => ({
846
- invalidate() {},
847
- render(width: number): string[] {
848
- // footerData.getGitBranch(): string | null
849
- // footerData.getExtensionStatuses(): ReadonlyMap<string, string>
850
- return [`${ctx.model?.id} (${footerData.getGitBranch() || "no git"})`];
851
- },
852
- dispose: footerData.onBranchChange(() => tui.requestRender()), // reactive
853
- }));
854
-
855
- ctx.ui.setFooter(undefined); // restore default
856
- ```
857
-
858
- Token stats available via `ctx.sessionManager.getBranch()` and `ctx.model`.
859
-
860
- **Examples:** [custom-footer.ts](../examples/extensions/custom-footer.ts)
861
-
862
- ### Pattern 7: Custom Editor (vim mode, etc.)
863
-
864
- Replace the main input editor with a custom implementation. Useful for modal editing (vim), different keybindings (emacs), or specialized input handling.
865
-
866
- ```typescript
867
- import { CustomEditor, type ExtensionAPI } from "@earendil-works/pi-coding-agent";
868
- import { matchesKey, truncateToWidth } from "@earendil-works/pi-tui";
869
-
870
- type Mode = "normal" | "insert";
871
-
872
- class VimEditor extends CustomEditor {
873
- private mode: Mode = "insert";
874
-
875
- handleInput(data: string): void {
876
- // Escape: switch to normal mode, or pass through for app handling
877
- if (matchesKey(data, "escape")) {
878
- if (this.mode === "insert") {
879
- this.mode = "normal";
880
- return;
881
- }
882
- // In normal mode, escape aborts agent (handled by CustomEditor)
883
- super.handleInput(data);
884
- return;
885
- }
886
-
887
- // Insert mode: pass everything to CustomEditor
888
- if (this.mode === "insert") {
889
- super.handleInput(data);
890
- return;
891
- }
892
-
893
- // Normal mode: vim-style navigation
894
- switch (data) {
895
- case "i": this.mode = "insert"; return;
896
- case "h": super.handleInput("\x1b[D"); return; // Left
897
- case "j": super.handleInput("\x1b[B"); return; // Down
898
- case "k": super.handleInput("\x1b[A"); return; // Up
899
- case "l": super.handleInput("\x1b[C"); return; // Right
900
- }
901
- // Pass unhandled keys to super (ctrl+c, etc.), but filter printable chars
902
- if (data.length === 1 && data.charCodeAt(0) >= 32) return;
903
- super.handleInput(data);
904
- }
905
-
906
- render(width: number): string[] {
907
- const lines = super.render(width);
908
- // Add mode indicator to bottom border (use truncateToWidth for ANSI-safe truncation)
909
- if (lines.length > 0) {
910
- const label = this.mode === "normal" ? " NORMAL " : " INSERT ";
911
- const lastLine = lines[lines.length - 1]!;
912
- // Pass "" as ellipsis to avoid adding "..." when truncating
913
- lines[lines.length - 1] = truncateToWidth(lastLine, width - label.length, "") + label;
914
- }
915
- return lines;
916
- }
917
- }
918
-
919
- export default function (pi: ExtensionAPI) {
920
- pi.on("session_start", (_event, ctx) => {
921
- // Factory receives the TUI, theme, and keybindings from the app
922
- ctx.ui.setEditorComponent((tui, theme, keybindings) =>
923
- new VimEditor(tui, theme, keybindings)
924
- );
925
- });
926
- }
927
- ```
98
+ The existing `theme.fg()` and `theme.bg()` helpers remain available for applying one semantic color.
928
99
 
929
- **Key points:**
100
+ Do not permanently store strings with theme colors unless `invalidate()` rebuilds them. A theme change clears render caches, but it cannot remove old ANSI colors embedded in application state.
930
101
 
931
- - **Extend `CustomEditor`** (not base `Editor`) to get app keybindings (escape to abort, ctrl+d to exit, model switching, etc.)
932
- - **Call `super.handleInput(data)`** for keys you don't handle
933
- - **Status spinners**: custom editors keep standalone status rows by default. Pass `{ embedWorkingStatus: true }` as the fourth `CustomEditor` constructor argument to embed working, compaction, branch summarization, and retry spinners in the editor border instead.
934
- - **Factory pattern**: `setEditorComponent` receives a factory function that gets `tui`, `theme`, and `keybindings`
935
- - **Pass `undefined`** to restore the default editor: `ctx.ui.setEditorComponent(undefined)`
102
+ Theme callbacks evaluated during rendering do not need special rebuilding. Stateless components can also calculate themed output on every render.
936
103
 
937
- **Examples:** [modal-editor.ts](../examples/extensions/modal-editor.ts)
104
+ Use [Themes](themes.md) to create terminal palettes. Use Pi’s `getMarkdownTheme()` when rendering Markdown that should match the active application theme.
938
105
 
939
- ## Key Rules
106
+ ## Keep rendering responsive
940
107
 
941
- 1. **Always use theme from callback** - Don't import theme directly. Use `theme` from the `ctx.ui.custom((tui, theme, keybindings, done) => ...)` callback.
108
+ Rendering runs on the interactive path. Cache expensive layout and highlighting work by width and content, then clear that cache from `invalidate()`.
942
109
 
943
- 2. **Always type DynamicBorder color param** - Write `(s: string) => theme.fg("accent", s)`, not `(s) => theme.fg("accent", s)`.
110
+ Keep the default view compact and reveal detail through expansion or a dedicated screen. For custom tool rendering, handle partial results and reuse the previous component when it can be updated safely.
944
111
 
945
- 3. **Call tui.requestRender() after state changes** - In `handleInput`, call `tui.requestRender()` after updating state.
112
+ Use `PI_TUI_WRITE_LOG` to capture the raw ANSI stream when diagnosing rendering problems. Test narrow widths, wide characters, resize events, theme changes, focus transitions, and both regular and fullscreen modes.
946
113
 
947
- 4. **Return the three-method object** - Custom components need `{ render, invalidate, handleInput }`.
114
+ ## Examples and source
948
115
 
949
- 5. **Use existing components** - `SelectList`, `SettingsList`, `BorderedLoader` cover 90% of cases. Don't rebuild them.
116
+ The checked extension examples cover the main patterns:
950
117
 
951
- ## Examples
118
+ - [`preset.ts`](../examples/extensions/preset.ts) and [`tools.ts`](../examples/extensions/tools.ts) use selection and settings lists.
119
+ - [`qna.ts`](../examples/extensions/qna.ts) uses cancellable asynchronous UI.
120
+ - [`modal-editor.ts`](../examples/extensions/modal-editor.ts) replaces the editor.
121
+ - [`custom-footer.ts`](../examples/extensions/custom-footer.ts) replaces the footer.
122
+ - [`widget-placement.ts`](../examples/extensions/widget-placement.ts) places persistent content around the editor.
123
+ - [`doom-overlay/`](../examples/extensions/doom-overlay/) demonstrates a continuously rendered overlay.
952
124
 
953
- - **Selection UI**: [examples/extensions/preset.ts](../examples/extensions/preset.ts) - SelectList with DynamicBorder framing
954
- - **Async with cancel**: [examples/extensions/qna.ts](../examples/extensions/qna.ts) - BorderedLoader for LLM calls
955
- - **Settings toggles**: [examples/extensions/tools.ts](../examples/extensions/tools.ts) - SettingsList for tool enable/disable
956
- - **Status indicators**: [examples/extensions/plan-mode/index.ts](../examples/extensions/plan-mode/index.ts) - setStatus and setWidget
957
- - **Working indicator**: [examples/extensions/working-indicator.ts](../examples/extensions/working-indicator.ts) - setWorkingIndicator
958
- - **Custom footer**: [examples/extensions/custom-footer.ts](../examples/extensions/custom-footer.ts) - setFooter with stats
959
- - **Custom editor**: [examples/extensions/modal-editor.ts](../examples/extensions/modal-editor.ts) - Vim-like modal editing
960
- - **Snake game**: [examples/extensions/snake.ts](../examples/extensions/snake.ts) - Full game with keyboard input, game loop
961
- - **Custom tool rendering**: [examples/extensions/todo.ts](../examples/extensions/todo.ts) - renderCall and renderResult
125
+ The public exports are defined in [`packages/tui/src/index.ts`](https://github.com/earendil-works/pi/blob/main/packages/tui/src/index.ts). See [Extensions](extensions.md) for extension lifecycle, state, tools, events, and mode behavior.