@earendil-works/pi-coding-agent 0.84.4 → 0.85.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 (323) hide show
  1. package/CHANGELOG.md +75 -5
  2. package/README.md +1 -1
  3. package/dist/bun/cli.d.ts +3 -1
  4. package/dist/bun/cli.d.ts.map +1 -1
  5. package/dist/bun/cli.js +3 -9
  6. package/dist/bun/cli.js.map +1 -1
  7. package/dist/bun/runtime-setup.d.ts +2 -0
  8. package/dist/bun/runtime-setup.d.ts.map +1 -0
  9. package/dist/bun/runtime-setup.js +9 -0
  10. package/dist/bun/runtime-setup.js.map +1 -0
  11. package/dist/bun/sandbox-env-setup.d.ts +2 -0
  12. package/dist/bun/sandbox-env-setup.d.ts.map +1 -0
  13. package/dist/bun/sandbox-env-setup.js +4 -0
  14. package/dist/bun/sandbox-env-setup.js.map +1 -0
  15. package/dist/bundle/chunks/anthropic-messages-VWZZOSJQ.js +6 -0
  16. package/dist/bundle/chunks/{azure-openai-responses-5ENVCQ7U.js → azure-openai-responses-BJLAM6CD.js} +1 -1
  17. package/dist/bundle/chunks/bedrock-converse-stream.js +1 -1
  18. package/dist/bundle/chunks/chunk-7ZC4UXSL.js +2 -0
  19. package/dist/bundle/chunks/chunk-CLNPYIDP.js +42 -0
  20. package/dist/bundle/chunks/{chunk-MNAIPA3J.js → chunk-IDDQWTHI.js} +1 -1
  21. package/dist/bundle/chunks/chunk-JVUZSMYM.js +1547 -0
  22. package/dist/bundle/chunks/{chunk-NBBFIJUL.js → chunk-OUXLLA64.js} +2 -2
  23. package/dist/bundle/chunks/{chunk-2KVJKXS2.js → chunk-U6ZMQKGD.js} +1 -1
  24. package/dist/bundle/chunks/chunk-USJZMAIR.js +2 -0
  25. package/dist/bundle/chunks/github-copilot.js +1 -1
  26. package/dist/bundle/chunks/{google-generative-ai-YMUPJBKR.js → google-generative-ai-Q2K7FBDI.js} +1 -1
  27. package/dist/bundle/chunks/{google-vertex-MPWMV4OF.js → google-vertex-7UJBF4S7.js} +1 -1
  28. package/dist/bundle/chunks/image-resize-worker.js +1 -1
  29. package/dist/bundle/chunks/{mistral-conversations-Q3AWZJAZ.js → mistral-conversations-4M6BZBX6.js} +1 -1
  30. package/dist/bundle/chunks/node-KG362ECQ.js +16 -0
  31. package/dist/bundle/chunks/node-TWVVAGPO.js +2 -0
  32. package/dist/bundle/chunks/openai-codex-responses-R6VYZTVY.js +10 -0
  33. package/dist/bundle/chunks/{openai-completions-ERMU2SS7.js → openai-completions-EKZT2IH2.js} +3 -3
  34. package/dist/bundle/chunks/openai-responses-TFDINO6W.js +2 -0
  35. package/dist/bundle/chunks/{pi-messages-TPFH44NP.js → pi-messages-PML4SPVJ.js} +1 -1
  36. package/dist/bundle/cli.js +1 -1
  37. package/dist/bundle/index.js +1 -1
  38. package/dist/bundle/rpc-entry.js +1 -1
  39. package/dist/cli/config-selector.d.ts.map +1 -1
  40. package/dist/cli/config-selector.js +2 -1
  41. package/dist/cli/config-selector.js.map +1 -1
  42. package/dist/cli/setup.d.ts +2 -0
  43. package/dist/cli/setup.d.ts.map +1 -0
  44. package/dist/cli/setup.js +12 -0
  45. package/dist/cli/setup.js.map +1 -0
  46. package/dist/cli.d.ts.map +1 -1
  47. package/dist/cli.js +2 -15
  48. package/dist/cli.js.map +1 -1
  49. package/dist/config.d.ts +1 -0
  50. package/dist/config.d.ts.map +1 -1
  51. package/dist/config.js +1 -0
  52. package/dist/config.js.map +1 -1
  53. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  54. package/dist/core/agent-session-runtime.js +15 -7
  55. package/dist/core/agent-session-runtime.js.map +1 -1
  56. package/dist/core/agent-session.d.ts +2 -6
  57. package/dist/core/agent-session.d.ts.map +1 -1
  58. package/dist/core/agent-session.js +14 -6
  59. package/dist/core/agent-session.js.map +1 -1
  60. package/dist/core/compaction/branch-summarization.d.ts +1 -1
  61. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  62. package/dist/core/compaction/branch-summarization.js +2 -1
  63. package/dist/core/compaction/branch-summarization.js.map +1 -1
  64. package/dist/core/extensions/loader.d.ts.map +1 -1
  65. package/dist/core/extensions/loader.js +1 -2
  66. package/dist/core/extensions/loader.js.map +1 -1
  67. package/dist/core/extensions/types.d.ts +8 -2
  68. package/dist/core/extensions/types.d.ts.map +1 -1
  69. package/dist/core/extensions/types.js.map +1 -1
  70. package/dist/core/http-dispatcher.d.ts.map +1 -1
  71. package/dist/core/http-dispatcher.js +2 -0
  72. package/dist/core/http-dispatcher.js.map +1 -1
  73. package/dist/core/keybindings.d.ts +5 -0
  74. package/dist/core/keybindings.d.ts.map +1 -1
  75. package/dist/core/keybindings.js +4 -0
  76. package/dist/core/keybindings.js.map +1 -1
  77. package/dist/core/messages.d.ts +1 -1
  78. package/dist/core/messages.d.ts.map +1 -1
  79. package/dist/core/messages.js.map +1 -1
  80. package/dist/core/model-config.d.ts +15 -0
  81. package/dist/core/model-config.d.ts.map +1 -1
  82. package/dist/core/model-config.js +3 -0
  83. package/dist/core/model-config.js.map +1 -1
  84. package/dist/core/model-runtime.d.ts +1 -0
  85. package/dist/core/model-runtime.d.ts.map +1 -1
  86. package/dist/core/model-runtime.js +5 -2
  87. package/dist/core/model-runtime.js.map +1 -1
  88. package/dist/core/provider-composer.d.ts.map +1 -1
  89. package/dist/core/provider-composer.js +8 -2
  90. package/dist/core/provider-composer.js.map +1 -1
  91. package/dist/core/session-manager.d.ts +3 -2
  92. package/dist/core/session-manager.d.ts.map +1 -1
  93. package/dist/core/session-manager.js +40 -13
  94. package/dist/core/session-manager.js.map +1 -1
  95. package/dist/core/settings-manager.d.ts.map +1 -1
  96. package/dist/core/settings-manager.js.map +1 -1
  97. package/dist/core/skills.d.ts +1 -1
  98. package/dist/core/skills.d.ts.map +1 -1
  99. package/dist/core/skills.js +4 -2
  100. package/dist/core/skills.js.map +1 -1
  101. package/dist/core/system-prompt.d.ts.map +1 -1
  102. package/dist/core/system-prompt.js +8 -9
  103. package/dist/core/system-prompt.js.map +1 -1
  104. package/dist/core/tools/bash.d.ts.map +1 -1
  105. package/dist/core/tools/bash.js +3 -117
  106. package/dist/core/tools/bash.js.map +1 -1
  107. package/dist/core/tools/edit.d.ts +1 -12
  108. package/dist/core/tools/edit.d.ts.map +1 -1
  109. package/dist/core/tools/edit.js +5 -163
  110. package/dist/core/tools/edit.js.map +1 -1
  111. package/dist/core/tools/find.d.ts.map +1 -1
  112. package/dist/core/tools/find.js +4 -55
  113. package/dist/core/tools/find.js.map +1 -1
  114. package/dist/core/tools/grep.d.ts.map +1 -1
  115. package/dist/core/tools/grep.js +4 -60
  116. package/dist/core/tools/grep.js.map +1 -1
  117. package/dist/core/tools/ls.d.ts.map +1 -1
  118. package/dist/core/tools/ls.js +4 -49
  119. package/dist/core/tools/ls.js.map +1 -1
  120. package/dist/core/tools/read.d.ts.map +1 -1
  121. package/dist/core/tools/read.js +4 -120
  122. package/dist/core/tools/read.js.map +1 -1
  123. package/dist/core/tools/renderers/bash.d.ts +12 -0
  124. package/dist/core/tools/renderers/bash.d.ts.map +1 -0
  125. package/dist/core/tools/renderers/bash.js +130 -0
  126. package/dist/core/tools/renderers/bash.js.map +1 -0
  127. package/dist/core/tools/renderers/edit.d.ts +23 -0
  128. package/dist/core/tools/renderers/edit.d.ts.map +1 -0
  129. package/dist/core/tools/renderers/edit.js +167 -0
  130. package/dist/core/tools/renderers/edit.js.map +1 -0
  131. package/dist/core/tools/renderers/find.d.ts +10 -0
  132. package/dist/core/tools/renderers/find.d.ts.map +1 -0
  133. package/dist/core/tools/renderers/find.js +64 -0
  134. package/dist/core/tools/renderers/find.js.map +1 -0
  135. package/dist/core/tools/renderers/grep.d.ts +10 -0
  136. package/dist/core/tools/renderers/grep.d.ts.map +1 -0
  137. package/dist/core/tools/renderers/grep.js +69 -0
  138. package/dist/core/tools/renderers/grep.js.map +1 -0
  139. package/dist/core/tools/renderers/index.d.ts +28 -0
  140. package/dist/core/tools/renderers/index.d.ts.map +1 -0
  141. package/dist/core/tools/renderers/index.js +47 -0
  142. package/dist/core/tools/renderers/index.js.map +1 -0
  143. package/dist/core/tools/renderers/ls.d.ts +10 -0
  144. package/dist/core/tools/renderers/ls.d.ts.map +1 -0
  145. package/dist/core/tools/renderers/ls.js +58 -0
  146. package/dist/core/tools/renderers/ls.js.map +1 -0
  147. package/dist/core/tools/renderers/read.d.ts +11 -0
  148. package/dist/core/tools/renderers/read.d.ts.map +1 -0
  149. package/dist/core/tools/renderers/read.js +129 -0
  150. package/dist/core/tools/renderers/read.js.map +1 -0
  151. package/dist/core/tools/renderers/write.d.ts +10 -0
  152. package/dist/core/tools/renderers/write.d.ts.map +1 -0
  153. package/dist/core/tools/renderers/write.js +153 -0
  154. package/dist/core/tools/renderers/write.js.map +1 -0
  155. package/dist/core/tools/write.d.ts.map +1 -1
  156. package/dist/core/tools/write.js +5 -146
  157. package/dist/core/tools/write.js.map +1 -1
  158. package/dist/index.d.ts +1 -1
  159. package/dist/index.d.ts.map +1 -1
  160. package/dist/index.js.map +1 -1
  161. package/dist/main.d.ts.map +1 -1
  162. package/dist/main.js +4 -1
  163. package/dist/main.js.map +1 -1
  164. package/dist/modes/interactive/chat-viewport.d.ts +20 -0
  165. package/dist/modes/interactive/chat-viewport.d.ts.map +1 -0
  166. package/dist/modes/interactive/chat-viewport.js +28 -0
  167. package/dist/modes/interactive/chat-viewport.js.map +1 -0
  168. package/dist/modes/interactive/components/assistant-message.d.ts +1 -0
  169. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  170. package/dist/modes/interactive/components/assistant-message.js +18 -10
  171. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  172. package/dist/modes/interactive/components/custom-editor.d.ts +10 -1
  173. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  174. package/dist/modes/interactive/components/custom-editor.js +39 -1
  175. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  176. package/dist/modes/interactive/components/index.d.ts +1 -1
  177. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  178. package/dist/modes/interactive/components/index.js.map +1 -1
  179. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  180. package/dist/modes/interactive/components/model-selector.js +10 -19
  181. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  182. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  183. package/dist/modes/interactive/components/scoped-models-selector.js +21 -23
  184. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  185. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  186. package/dist/modes/interactive/components/settings-selector.js +14 -10
  187. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  188. package/dist/modes/interactive/components/status-indicator.d.ts +3 -1
  189. package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -1
  190. package/dist/modes/interactive/components/status-indicator.js +10 -3
  191. package/dist/modes/interactive/components/status-indicator.js.map +1 -1
  192. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  193. package/dist/modes/interactive/components/thinking-selector.js +6 -6
  194. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  195. package/dist/modes/interactive/components/tool-execution.d.ts +21 -4
  196. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  197. package/dist/modes/interactive/components/tool-execution.js +35 -33
  198. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  199. package/dist/modes/interactive/components/trust-selector.d.ts.map +1 -1
  200. package/dist/modes/interactive/components/trust-selector.js +2 -2
  201. package/dist/modes/interactive/components/trust-selector.js.map +1 -1
  202. package/dist/modes/interactive/interactive-mode.d.ts +8 -15
  203. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  204. package/dist/modes/interactive/interactive-mode.js +95 -80
  205. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  206. package/dist/modes/interactive/session-share.d.ts.map +1 -1
  207. package/dist/modes/interactive/session-share.js +8 -12
  208. package/dist/modes/interactive/session-share.js.map +1 -1
  209. package/dist/modes/interactive/theme/dark.json +2 -1
  210. package/dist/modes/interactive/theme/light.json +2 -1
  211. package/dist/modes/interactive/theme/theme-controller.d.ts +1 -0
  212. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
  213. package/dist/modes/interactive/theme/theme-controller.js +5 -0
  214. package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
  215. package/dist/modes/interactive/theme/theme-json.d.ts +84 -0
  216. package/dist/modes/interactive/theme/theme-json.d.ts.map +1 -0
  217. package/dist/modes/interactive/theme/theme-json.js +130 -0
  218. package/dist/modes/interactive/theme/theme-json.js.map +1 -0
  219. package/dist/modes/interactive/theme/theme-schema.json +6 -2
  220. package/dist/modes/interactive/theme/theme.d.ts +14 -5
  221. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  222. package/dist/modes/interactive/theme/theme.js +18 -119
  223. package/dist/modes/interactive/theme/theme.js.map +1 -1
  224. package/dist/modes/interactive/tui-renderer.d.ts +21 -0
  225. package/dist/modes/interactive/tui-renderer.d.ts.map +1 -0
  226. package/dist/modes/interactive/tui-renderer.js +66 -0
  227. package/dist/modes/interactive/tui-renderer.js.map +1 -0
  228. package/dist/utils/exif-orientation.d.ts.map +1 -1
  229. package/dist/utils/exif-orientation.js +2 -3
  230. package/dist/utils/exif-orientation.js.map +1 -1
  231. package/dist/utils/tools-manager.d.ts +1 -0
  232. package/dist/utils/tools-manager.d.ts.map +1 -1
  233. package/dist/utils/tools-manager.js +41 -19
  234. package/dist/utils/tools-manager.js.map +1 -1
  235. package/docs/containerization.md +45 -0
  236. package/docs/development.md +19 -0
  237. package/docs/environment-variables.md +2 -0
  238. package/docs/extensions.md +5 -2
  239. package/docs/keybindings.md +5 -2
  240. package/docs/models.md +4 -1
  241. package/docs/rpc.md +1 -1
  242. package/docs/sdk.md +5 -0
  243. package/docs/settings.md +5 -5
  244. package/docs/skills.md +1 -1
  245. package/docs/terminal-setup.md +15 -0
  246. package/docs/themes.md +8 -6
  247. package/docs/tui.md +20 -1
  248. package/examples/README.md +3 -0
  249. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  250. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  251. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  252. package/examples/extensions/dynamic-resources/dynamic.json +2 -0
  253. package/examples/extensions/gondolin/package-lock.json +2 -2
  254. package/examples/extensions/gondolin/package.json +1 -1
  255. package/examples/extensions/sandbox/package-lock.json +2 -2
  256. package/examples/extensions/sandbox/package.json +1 -1
  257. package/examples/extensions/with-deps/package-lock.json +2 -2
  258. package/examples/extensions/with-deps/package.json +1 -1
  259. package/examples/plugins/pi-example-plugin/README.md +38 -0
  260. package/examples/plugins/pi-example-plugin/package.json +10 -0
  261. package/examples/plugins/pi-example-plugin/src/contract.ts +13 -0
  262. package/examples/plugins/pi-example-plugin/src/session.ts +23 -0
  263. package/examples/plugins/pi-example-plugin/src/tui.ts +31 -0
  264. package/npm-shrinkwrap.json +511 -42
  265. package/package.json +15 -8
  266. package/dist/bun/register-bedrock.d.ts +0 -2
  267. package/dist/bun/register-bedrock.d.ts.map +0 -1
  268. package/dist/bun/register-bedrock.js +0 -4
  269. package/dist/bun/register-bedrock.js.map +0 -1
  270. package/dist/bundle/chunks/anthropic-messages-JWX2WP65.js +0 -45
  271. package/dist/bundle/chunks/chunk-JUUC5AZY.js +0 -2
  272. package/dist/bundle/chunks/chunk-OMWWHBTG.js +0 -1548
  273. package/dist/bundle/chunks/openai-codex-responses-GJVBJXLB.js +0 -8
  274. package/dist/bundle/chunks/openai-responses-BSOJMSEV.js +0 -2
  275. package/dist/bundle/client.js +0 -2
  276. package/dist/cli/experimental/auth.d.ts +0 -16
  277. package/dist/cli/experimental/auth.d.ts.map +0 -1
  278. package/dist/cli/experimental/auth.js +0 -13
  279. package/dist/cli/experimental/auth.js.map +0 -1
  280. package/dist/cli/experimental/cli.d.ts +0 -6
  281. package/dist/cli/experimental/cli.d.ts.map +0 -1
  282. package/dist/cli/experimental/cli.js +0 -5
  283. package/dist/cli/experimental/cli.js.map +0 -1
  284. package/dist/cli/experimental/command-options.d.ts +0 -17
  285. package/dist/cli/experimental/command-options.d.ts.map +0 -1
  286. package/dist/cli/experimental/command-options.js +0 -35
  287. package/dist/cli/experimental/command-options.js.map +0 -1
  288. package/dist/cli/experimental/command.d.ts +0 -63
  289. package/dist/cli/experimental/command.d.ts.map +0 -1
  290. package/dist/cli/experimental/command.js +0 -130
  291. package/dist/cli/experimental/command.js.map +0 -1
  292. package/dist/cli/experimental/commands/client.d.ts +0 -13
  293. package/dist/cli/experimental/commands/client.d.ts.map +0 -1
  294. package/dist/cli/experimental/commands/client.js +0 -25
  295. package/dist/cli/experimental/commands/client.js.map +0 -1
  296. package/dist/cli/experimental/commands/pi.d.ts +0 -15
  297. package/dist/cli/experimental/commands/pi.d.ts.map +0 -1
  298. package/dist/cli/experimental/commands/pi.js +0 -28
  299. package/dist/cli/experimental/commands/pi.js.map +0 -1
  300. package/dist/cli/experimental/commands/server.d.ts +0 -13
  301. package/dist/cli/experimental/commands/server.d.ts.map +0 -1
  302. package/dist/cli/experimental/commands/server.js +0 -25
  303. package/dist/cli/experimental/commands/server.js.map +0 -1
  304. package/dist/cli/experimental/transport-address.d.ts +0 -10
  305. package/dist/cli/experimental/transport-address.d.ts.map +0 -1
  306. package/dist/cli/experimental/transport-address.js +0 -38
  307. package/dist/cli/experimental/transport-address.js.map +0 -1
  308. package/dist/client/index.d.ts +0 -3
  309. package/dist/client/index.d.ts.map +0 -1
  310. package/dist/client/index.js +0 -3
  311. package/dist/client/index.js.map +0 -1
  312. package/dist/client/remote-session.d.ts +0 -53
  313. package/dist/client/remote-session.d.ts.map +0 -1
  314. package/dist/client/remote-session.js +0 -340
  315. package/dist/client/remote-session.js.map +0 -1
  316. package/dist/client/transcript.d.ts +0 -12
  317. package/dist/client/transcript.d.ts.map +0 -1
  318. package/dist/client/transcript.js +0 -98
  319. package/dist/client/transcript.js.map +0 -1
  320. package/dist/server/create-harness.d.ts +0 -26
  321. package/dist/server/create-harness.d.ts.map +0 -1
  322. package/dist/server/create-harness.js +0 -106
  323. package/dist/server/create-harness.js.map +0 -1
@@ -7,7 +7,7 @@ import * as fs from "node:fs";
7
7
  import * as os from "node:os";
8
8
  import * as path from "node:path";
9
9
  import * as TuiLayouts from "@earendil-works/pi-tui";
10
- import { CombinedAutocompleteProvider, Container, fuzzyFilter, getCapabilities, hyperlink, Markdown, matchesKey, ProcessTerminal, Spacer, setCapabilityOverrides, setKeybindings, Text, TruncatedText, TuiAltScreen, TuiMainScreen, visibleWidth, } from "@earendil-works/pi-tui";
10
+ import { CombinedAutocompleteProvider, Container, fuzzyFilter, getCapabilities, hyperlink, Markdown, matchesKey, Spacer, setCapabilityOverrides, setKeybindings, Text, TruncatedText, TuiAltScreen, TuiMainScreen, visibleWidth, } from "@earendil-works/pi-tui";
11
11
  import chalk from "chalk";
12
12
  import { spawn } from "child_process";
13
13
  import { APP_NAME, APP_TITLE, CONFIG_DIR_NAME, getAgentDir, getAuthPath, getDebugLogPath, getDocsPath, VERSION, } from "../../config.js";
@@ -26,19 +26,20 @@ import { formatMissingSessionCwdPrompt, MissingSessionCwdError } from "../../cor
26
26
  import { SessionManager, sessionEntryToContextMessages } from "../../core/session-manager.js";
27
27
  import { BUILTIN_SLASH_COMMANDS } from "../../core/slash-commands.js";
28
28
  import { isInstallTelemetryEnabled } from "../../core/telemetry.js";
29
+ import { withBuiltInRenderers } from "../../core/tools/renderers/index.js";
29
30
  import { hasTrustRequiringProjectResources, ProjectTrustStore } from "../../core/trust-manager.js";
30
31
  import { getUsageCostBreakdown } from "../../core/usage-totals.js";
31
32
  import { getChangelogPath, getNewEntries, normalizeChangelogLinks, parseChangelog } from "../../utils/changelog.js";
32
33
  import { copyToClipboard, readClipboardText } from "../../utils/clipboard.js";
33
34
  import { extensionForImageMimeType, readClipboardImage } from "../../utils/clipboard-image.js";
34
35
  import { parseGitUrl } from "../../utils/git.js";
35
- import { openBrowser } from "../../utils/open-browser.js";
36
36
  import { getCwdRelativePath } from "../../utils/paths.js";
37
37
  import { getPiUserAgent } from "../../utils/pi-user-agent.js";
38
38
  import { killTrackedDetachedChildren } from "../../utils/shell.js";
39
39
  import { loadAllHighlightLanguages } from "../../utils/syntax-highlight.js";
40
40
  import { ensureTool } from "../../utils/tools-manager.js";
41
41
  import { checkForNewPiVersion } from "../../utils/version-check.js";
42
+ import { createChatViewport } from "./chat-viewport.js";
42
43
  import { ArminComponent } from "./components/armin.js";
43
44
  import { AssistantMessageComponent } from "./components/assistant-message.js";
44
45
  import { BashExecutionComponent } from "./components/bash-execution.js";
@@ -76,6 +77,14 @@ import { getModelSearchText } from "./model-search.js";
76
77
  import { shareSession } from "./session-share.js";
77
78
  import { getAvailableThemes, getAvailableThemesWithPaths, getEditorTheme, getMarkdownTheme, getThemeByName, onThemeChange, setRegisteredThemes, stopThemeWatcher, Theme, theme, } from "./theme/theme.js";
78
79
  import { InteractiveThemeController } from "./theme/theme-controller.js";
80
+ import { createInteractiveTui, createInteractiveTuiReference } from "./tui-renderer.js";
81
+ export { createInteractiveTui, createInteractiveTuiReference } from "./tui-renderer.js";
82
+ function isWorkingStatusEditor(editor) {
83
+ return ("embedWorkingStatus" in editor &&
84
+ editor.embedWorkingStatus === true &&
85
+ "setWorkingStatusIndicator" in editor &&
86
+ typeof editor.setWorkingStatusIndicator === "function");
87
+ }
79
88
  function isExpandable(obj) {
80
89
  return typeof obj === "object" && obj !== null && "setExpanded" in obj && typeof obj.setExpanded === "function";
81
90
  }
@@ -177,61 +186,6 @@ function formatLoginProviderCompletionDescription(provider) {
177
186
  const authTypes = provider.authTypes.map(formatAuthSelectorProviderType).join("/");
178
187
  return provider.name === provider.id ? authTypes : `${provider.name} · ${authTypes}`;
179
188
  }
180
- /** Composition root for selecting the interactive terminal renderer. */
181
- export function createInteractiveTui(options) {
182
- const terminal = options.terminal ?? new ProcessTerminal();
183
- if (options.tuiMode === "fullscreen") {
184
- const styleSearchMatch = (text) => theme.bg("searchMatchBg", theme.fg("searchMatchText", text));
185
- return new TuiAltScreen(terminal, options.showHardwareCursor, options.logDirectory, {
186
- searchMatchStyle: (text) => theme.underline(styleSearchMatch(text)),
187
- searchCurrentMatchStyle: (text) => theme.bold(theme.inverse(styleSearchMatch(text))),
188
- openUrl: openBrowser,
189
- onRightClickPaste: options.onRightClickPaste,
190
- copyOnSelect: options.fullscreenCopyOnSelect,
191
- copySelection: async (text) => {
192
- try {
193
- await copyToClipboard(text);
194
- return true;
195
- }
196
- catch {
197
- return false;
198
- }
199
- },
200
- });
201
- }
202
- return new TuiMainScreen(terminal, options.showHardwareCursor, options.logDirectory);
203
- }
204
- /** Stable reference for components while InteractiveMode replaces the active renderer. */
205
- export function createInteractiveTuiReference(getTui) {
206
- return new Proxy({}, {
207
- get: (_target, property) => {
208
- const tui = getTui();
209
- const value = Reflect.get(tui, property, tui);
210
- if (typeof value !== "function")
211
- return value;
212
- let methodTui = tui;
213
- let method = value;
214
- return (...args) => {
215
- const currentTui = getTui();
216
- if (currentTui !== methodTui) {
217
- const currentMethod = Reflect.get(currentTui, property, currentTui);
218
- if (typeof currentMethod !== "function") {
219
- throw new TypeError(`TUI property ${String(property)} is not callable`);
220
- }
221
- methodTui = currentTui;
222
- method = currentMethod;
223
- }
224
- return Reflect.apply(method, methodTui, args);
225
- };
226
- },
227
- set: (_target, property, value) => {
228
- const tui = getTui();
229
- return Reflect.set(tui, property, value, tui);
230
- },
231
- has: (_target, property) => Reflect.has(getTui(), property),
232
- getPrototypeOf: () => Reflect.getPrototypeOf(getTui()),
233
- });
234
- }
235
189
  export class InteractiveMode {
236
190
  runtimeHost;
237
191
  renderer;
@@ -263,11 +217,12 @@ export class InteractiveMode {
263
217
  onInputCallback;
264
218
  pendingUserInputs = [];
265
219
  activeStatusIndicator = undefined;
220
+ activeWorkingIndicatorEmbedded = false;
266
221
  idleStatus = new IdleStatus();
267
222
  workingMessage = undefined;
268
223
  workingVisible = true;
269
224
  workingIndicatorOptions = undefined;
270
- defaultWorkingMessage = "Working...";
225
+ defaultWorkingMessage = "Working";
271
226
  defaultHiddenThinkingLabel = "Thinking...";
272
227
  hiddenThinkingLabel = this.defaultHiddenThinkingLabel;
273
228
  lastSigintTime = 0;
@@ -390,6 +345,7 @@ export class InteractiveMode {
390
345
  this.defaultEditor = new CustomEditor(this.ui, getEditorTheme(), this.keybindings, {
391
346
  paddingX: editorPaddingX,
392
347
  autocompleteMaxVisible,
348
+ embedWorkingStatus: true,
393
349
  });
394
350
  this.editor = this.defaultEditor;
395
351
  this.editorContainer = new Container();
@@ -661,25 +617,20 @@ export class InteractiveMode {
661
617
  }
662
618
  // Keep one component tree and remount it when changing renderers.
663
619
  this.renderWidgets(); // Initialize with default spacer
664
- this.transcriptScrollView = new TuiLayouts.ScrollView(this.documentContainer, {
665
- follow: "end",
666
- primary: true,
667
- overscroll: "chain",
620
+ const viewport = createChatViewport({
621
+ document: this.documentContainer,
622
+ pendingMessages: this.pendingMessagesContainer,
623
+ status: this.statusContainer,
624
+ widgetsAbove: this.widgetContainerAbove,
625
+ editor: this.editorContainer,
626
+ widgetsBelow: this.widgetContainerBelow,
627
+ footer: this.footerContainer,
668
628
  scrollbar: this.settingsManager.getFullscreenScrollbar(),
669
- scrollbarStyle: (text) => theme.bg("scrollbarThumb", text),
629
+ scrollbarTrackStyle: (text) => theme.fg("scrollbarTrack", text),
630
+ scrollbarThumbStyle: (text) => theme.fg("scrollbarThumb", text),
670
631
  });
671
- const dock = new TuiLayouts.VStack([
672
- { component: this.pendingMessagesContainer, shrink: 1, minSize: 0 },
673
- { component: this.statusContainer, shrink: 1, minSize: 0 },
674
- { component: this.widgetContainerAbove, shrink: 1, minSize: 0 },
675
- { component: this.editorContainer, shrink: 1, minSize: 3 },
676
- { component: this.widgetContainerBelow, shrink: 1, minSize: 0 },
677
- { component: this.footerContainer, shrink: 1, minSize: 1 },
678
- ]);
679
- this.fullscreenLayoutRoot = new TuiLayouts.VStack([
680
- { component: this.transcriptScrollView, basis: 0, grow: 1, shrink: 1, minSize: 1 },
681
- { component: dock, basis: "auto", grow: 0, shrink: 1, minSize: 1 },
682
- ]);
632
+ this.transcriptScrollView = viewport.transcript;
633
+ this.fullscreenLayoutRoot = viewport.root;
683
634
  this.mountInteractiveTui(this.renderer, [
684
635
  this.documentContainer,
685
636
  this.pendingMessagesContainer,
@@ -1591,8 +1542,12 @@ export class InteractiveMode {
1591
1542
  /**
1592
1543
  * Get a registered tool definition by name (for custom rendering).
1593
1544
  */
1545
+ /**
1546
+ * Extension-registered definition, falling back to the built-in one. The renderer components take
1547
+ * whatever this returns, so they never reach into the tool registry themselves.
1548
+ */
1594
1549
  getRegisteredToolDefinition(toolName) {
1595
- return this.session.getToolDefinition(toolName);
1550
+ return withBuiltInRenderers(toolName, this.session.getToolDefinition(toolName));
1596
1551
  }
1597
1552
  getMarkdownTransformers() {
1598
1553
  return [this.mermaidMarkdownTransformer, ...this.session.extensionRunner.getMarkdownTransformers()];
@@ -1662,26 +1617,48 @@ export class InteractiveMode {
1662
1617
  this.footerDataProvider.setExtensionStatus(key, text);
1663
1618
  this.ui.requestRender();
1664
1619
  }
1620
+ setEditorWorkingStatusIndicator(indicator) {
1621
+ this.defaultEditor.setWorkingStatusIndicator(undefined);
1622
+ if (!isWorkingStatusEditor(this.editor))
1623
+ return false;
1624
+ this.editor.setWorkingStatusIndicator(indicator);
1625
+ return true;
1626
+ }
1665
1627
  showStatusIndicator(indicator) {
1666
1628
  this.activeStatusIndicator?.dispose();
1667
1629
  this.activeStatusIndicator = indicator;
1630
+ this.activeWorkingIndicatorEmbedded = false;
1668
1631
  this.statusContainer.clear();
1632
+ this.setEditorWorkingStatusIndicator(undefined);
1633
+ if (indicator instanceof WorkingStatusIndicator && this.setEditorWorkingStatusIndicator(indicator)) {
1634
+ this.activeWorkingIndicatorEmbedded = true;
1635
+ return;
1636
+ }
1669
1637
  this.statusContainer.addChild(indicator);
1670
1638
  }
1671
1639
  clearStatusIndicator(kind) {
1672
1640
  if (kind && this.activeStatusIndicator?.kind !== kind) {
1673
1641
  return;
1674
1642
  }
1675
- const hadActiveStatusIndicator = this.activeStatusIndicator !== undefined;
1676
- this.activeStatusIndicator?.dispose();
1643
+ const clearedIndicator = this.activeStatusIndicator;
1644
+ const clearedIndicatorWasEmbedded = clearedIndicator?.kind === "working" && this.activeWorkingIndicatorEmbedded;
1645
+ clearedIndicator?.dispose();
1677
1646
  this.activeStatusIndicator = undefined;
1647
+ this.activeWorkingIndicatorEmbedded = false;
1678
1648
  this.statusContainer.clear();
1679
- if (hadActiveStatusIndicator && this.options.tuiMode === "regular" && this.ui.getClearOnShrink()) {
1649
+ this.setEditorWorkingStatusIndicator(undefined);
1650
+ if (clearedIndicator &&
1651
+ !clearedIndicatorWasEmbedded &&
1652
+ this.options.tuiMode === "regular" &&
1653
+ this.ui.getClearOnShrink()) {
1680
1654
  this.statusContainer.addChild(this.idleStatus);
1681
1655
  }
1682
1656
  }
1683
1657
  showWorkingStatusIndicator() {
1684
- this.showStatusIndicator(new WorkingStatusIndicator(this.ui, this.workingMessage ?? this.defaultWorkingMessage, this.workingIndicatorOptions));
1658
+ const colorFn = isWorkingStatusEditor(this.editor)
1659
+ ? (text) => (this.editor.borderColor ?? theme.getThinkingBorderColor(this.session.thinkingLevel || "off"))(text)
1660
+ : undefined;
1661
+ this.showStatusIndicator(new WorkingStatusIndicator(this.ui, this.workingMessage ?? this.defaultWorkingMessage, this.workingIndicatorOptions, colorFn));
1685
1662
  }
1686
1663
  setWorkingVisible(visible) {
1687
1664
  this.workingVisible = visible;
@@ -2153,6 +2130,13 @@ export class InteractiveMode {
2153
2130
  this.editor = this.defaultEditor;
2154
2131
  }
2155
2132
  this.editorContainer.addChild(this.editor);
2133
+ if (this.activeStatusIndicator instanceof WorkingStatusIndicator) {
2134
+ this.statusContainer.clear();
2135
+ this.activeWorkingIndicatorEmbedded = this.setEditorWorkingStatusIndicator(this.activeStatusIndicator);
2136
+ if (!this.activeWorkingIndicatorEmbedded) {
2137
+ this.statusContainer.addChild(this.activeStatusIndicator);
2138
+ }
2139
+ }
2156
2140
  this.ui.setFocus(this.editor);
2157
2141
  this.ui.requestRender();
2158
2142
  }
@@ -2694,6 +2678,7 @@ export class InteractiveMode {
2694
2678
  for (const [, component] of this.pendingTools.entries()) {
2695
2679
  component.setArgsComplete();
2696
2680
  }
2681
+ this.maybeShowAssistantDiagnostics(this.streamingMessage);
2697
2682
  this.maybeShowCacheMissNotice(this.streamingMessage);
2698
2683
  }
2699
2684
  this.streamingComponent = undefined;
@@ -3057,6 +3042,7 @@ export class InteractiveMode {
3057
3042
  }
3058
3043
  }
3059
3044
  if (message.stopReason !== "aborted" && message.stopReason !== "error") {
3045
+ this.maybeShowAssistantDiagnostics(message);
3060
3046
  const miss = cacheMisses.get(message);
3061
3047
  if (miss)
3062
3048
  this.addCacheMissNotice(miss);
@@ -3113,6 +3099,32 @@ export class InteractiveMode {
3113
3099
  this.chatContainer.addChild(new Spacer(1));
3114
3100
  this.chatContainer.addChild(new Text(theme.fg("warning", `${label}: ${formatTokens(tokens)} tokens billed${cost}`), 1, 0));
3115
3101
  }
3102
+ maybeShowAssistantDiagnostics(message) {
3103
+ if (!this.settingsManager.getShowCacheMissNotices())
3104
+ return;
3105
+ for (const diagnostic of message.diagnostics ?? []) {
3106
+ if (diagnostic.type !== "anthropic_input_transformations")
3107
+ continue;
3108
+ const transformations = diagnostic.details?.transformations;
3109
+ if (!Array.isArray(transformations))
3110
+ continue;
3111
+ const dropped = transformations.flatMap((transformation) => {
3112
+ if (typeof transformation !== "object" || transformation === null)
3113
+ return [];
3114
+ const details = transformation;
3115
+ if (details.type !== "thinking_dropped")
3116
+ return [];
3117
+ const reason = typeof details.reason === "string" ? details.reason : "unknown reason";
3118
+ const location = typeof details.path === "string" ? ` at ${details.path}` : "";
3119
+ return [`${reason}${location}`];
3120
+ });
3121
+ if (dropped.length === 0)
3122
+ continue;
3123
+ const noun = dropped.length === 1 ? "thinking block" : `${dropped.length} thinking blocks`;
3124
+ this.chatContainer.addChild(new Spacer(1));
3125
+ this.chatContainer.addChild(new Text(theme.fg("warning", `Anthropic dropped ${noun}: ${dropped.join("; ")}`), 1, 0));
3126
+ }
3127
+ }
3116
3128
  /**
3117
3129
  * Show a transcript notice when a completed assistant message paid for a
3118
3130
  * significant cache miss. Only states observable facts: the miss itself,
@@ -3410,6 +3422,9 @@ export class InteractiveMode {
3410
3422
  const level = this.session.thinkingLevel || "off";
3411
3423
  this.editor.borderColor = theme.getThinkingBorderColor(level);
3412
3424
  }
3425
+ if (this.activeStatusIndicator?.kind === "working") {
3426
+ this.activeStatusIndicator.invalidate();
3427
+ }
3413
3428
  this.ui.requestRender();
3414
3429
  }
3415
3430
  cycleThinkingLevel() {