apex-code 0.0.1-alpha.8 → 0.0.4

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 (634) hide show
  1. package/CHANGELOG.md +231 -0
  2. package/README.md +9 -8
  3. package/dist/cli/args.d.ts +26 -1
  4. package/dist/cli/args.d.ts.map +1 -1
  5. package/dist/cli/args.js +72 -10
  6. package/dist/cli/args.js.map +1 -1
  7. package/dist/cli/file-processor.d.ts.map +1 -1
  8. package/dist/cli/file-processor.js +2 -1
  9. package/dist/cli/file-processor.js.map +1 -1
  10. package/dist/cli/mcp-command.d.ts +9 -0
  11. package/dist/cli/mcp-command.d.ts.map +1 -0
  12. package/dist/cli/mcp-command.js +53 -0
  13. package/dist/cli/mcp-command.js.map +1 -0
  14. package/dist/cli/project-trust.d.ts.map +1 -1
  15. package/dist/cli/project-trust.js +3 -1
  16. package/dist/cli/project-trust.js.map +1 -1
  17. package/dist/cli/startup-ui.d.ts.map +1 -1
  18. package/dist/cli/startup-ui.js +2 -1
  19. package/dist/cli/startup-ui.js.map +1 -1
  20. package/dist/cli.d.ts.map +1 -1
  21. package/dist/cli.js +94 -5
  22. package/dist/cli.js.map +1 -1
  23. package/dist/config.d.ts +3 -2
  24. package/dist/config.d.ts.map +1 -1
  25. package/dist/config.js +45 -18
  26. package/dist/config.js.map +1 -1
  27. package/dist/core/agent-session-services.d.ts +3 -0
  28. package/dist/core/agent-session-services.d.ts.map +1 -1
  29. package/dist/core/agent-session-services.js +1 -0
  30. package/dist/core/agent-session-services.js.map +1 -1
  31. package/dist/core/agent-session.d.ts +183 -15
  32. package/dist/core/agent-session.d.ts.map +1 -1
  33. package/dist/core/agent-session.js +728 -117
  34. package/dist/core/agent-session.js.map +1 -1
  35. package/dist/core/auth-storage.d.ts.map +1 -1
  36. package/dist/core/auth-storage.js +6 -7
  37. package/dist/core/auth-storage.js.map +1 -1
  38. package/dist/core/bash-executor.d.ts.map +1 -1
  39. package/dist/core/bash-executor.js +7 -0
  40. package/dist/core/bash-executor.js.map +1 -1
  41. package/dist/core/checkpoints/git-checkpoints.d.ts +39 -0
  42. package/dist/core/checkpoints/git-checkpoints.d.ts.map +1 -0
  43. package/dist/core/checkpoints/git-checkpoints.js +251 -0
  44. package/dist/core/checkpoints/git-checkpoints.js.map +1 -0
  45. package/dist/core/checkpoints/session-checkpoints.d.ts +23 -0
  46. package/dist/core/checkpoints/session-checkpoints.d.ts.map +1 -0
  47. package/dist/core/checkpoints/session-checkpoints.js +36 -0
  48. package/dist/core/checkpoints/session-checkpoints.js.map +1 -0
  49. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  50. package/dist/core/compaction/branch-summarization.js +7 -3
  51. package/dist/core/compaction/branch-summarization.js.map +1 -1
  52. package/dist/core/compaction/compaction.d.ts +9 -3
  53. package/dist/core/compaction/compaction.d.ts.map +1 -1
  54. package/dist/core/compaction/compaction.js +59 -36
  55. package/dist/core/compaction/compaction.js.map +1 -1
  56. package/dist/core/defaults.d.ts +1 -0
  57. package/dist/core/defaults.d.ts.map +1 -1
  58. package/dist/core/defaults.js +9 -0
  59. package/dist/core/defaults.js.map +1 -1
  60. package/dist/core/delegation/runtime.d.ts +6 -5
  61. package/dist/core/delegation/runtime.d.ts.map +1 -1
  62. package/dist/core/delegation/runtime.js +4 -3
  63. package/dist/core/delegation/runtime.js.map +1 -1
  64. package/dist/core/durable-state/sqlite.d.ts.map +1 -1
  65. package/dist/core/durable-state/sqlite.js +26 -2
  66. package/dist/core/durable-state/sqlite.js.map +1 -1
  67. package/dist/core/exec.d.ts.map +1 -1
  68. package/dist/core/exec.js +5 -2
  69. package/dist/core/exec.js.map +1 -1
  70. package/dist/core/extensions/index.d.ts +2 -2
  71. package/dist/core/extensions/index.d.ts.map +1 -1
  72. package/dist/core/extensions/index.js +1 -1
  73. package/dist/core/extensions/index.js.map +1 -1
  74. package/dist/core/extensions/loader.d.ts.map +1 -1
  75. package/dist/core/extensions/loader.js +123 -50
  76. package/dist/core/extensions/loader.js.map +1 -1
  77. package/dist/core/extensions/runner.d.ts +5 -0
  78. package/dist/core/extensions/runner.d.ts.map +1 -1
  79. package/dist/core/extensions/runner.js +45 -1
  80. package/dist/core/extensions/runner.js.map +1 -1
  81. package/dist/core/extensions/source-runtime.d.ts +14 -0
  82. package/dist/core/extensions/source-runtime.d.ts.map +1 -0
  83. package/dist/core/extensions/source-runtime.js +56 -0
  84. package/dist/core/extensions/source-runtime.js.map +1 -0
  85. package/dist/core/extensions/types.d.ts +60 -11
  86. package/dist/core/extensions/types.d.ts.map +1 -1
  87. package/dist/core/extensions/types.js +3 -0
  88. package/dist/core/extensions/types.js.map +1 -1
  89. package/dist/core/footer-data-provider.d.ts +1 -1
  90. package/dist/core/footer-data-provider.d.ts.map +1 -1
  91. package/dist/core/footer-data-provider.js +1 -1
  92. package/dist/core/footer-data-provider.js.map +1 -1
  93. package/dist/core/formatter-lifecycle.d.ts +69 -0
  94. package/dist/core/formatter-lifecycle.d.ts.map +1 -0
  95. package/dist/core/formatter-lifecycle.js +360 -0
  96. package/dist/core/formatter-lifecycle.js.map +1 -0
  97. package/dist/core/hooks/command-handler.d.ts +19 -0
  98. package/dist/core/hooks/command-handler.d.ts.map +1 -0
  99. package/dist/core/hooks/command-handler.js +112 -0
  100. package/dist/core/hooks/command-handler.js.map +1 -0
  101. package/dist/core/hooks/http-handler.d.ts +10 -0
  102. package/dist/core/hooks/http-handler.d.ts.map +1 -0
  103. package/dist/core/hooks/http-handler.js +36 -0
  104. package/dist/core/hooks/http-handler.js.map +1 -0
  105. package/dist/core/hooks/loader.d.ts +29 -0
  106. package/dist/core/hooks/loader.d.ts.map +1 -0
  107. package/dist/core/hooks/loader.js +139 -0
  108. package/dist/core/hooks/loader.js.map +1 -0
  109. package/dist/core/hooks/runtime.d.ts +13 -0
  110. package/dist/core/hooks/runtime.d.ts.map +1 -0
  111. package/dist/core/hooks/runtime.js +63 -0
  112. package/dist/core/hooks/runtime.js.map +1 -0
  113. package/dist/core/hooks/types.d.ts +83 -0
  114. package/dist/core/hooks/types.d.ts.map +1 -0
  115. package/dist/core/hooks/types.js +24 -0
  116. package/dist/core/hooks/types.js.map +1 -0
  117. package/dist/core/keybindings.d.ts +20 -19
  118. package/dist/core/keybindings.d.ts.map +1 -1
  119. package/dist/core/keybindings.js +26 -5
  120. package/dist/core/keybindings.js.map +1 -1
  121. package/dist/core/mcp/config.d.ts +16 -0
  122. package/dist/core/mcp/config.d.ts.map +1 -0
  123. package/dist/core/mcp/config.js +166 -0
  124. package/dist/core/mcp/config.js.map +1 -0
  125. package/dist/core/mcp/connector.d.ts +35 -0
  126. package/dist/core/mcp/connector.d.ts.map +1 -0
  127. package/dist/core/mcp/connector.js +105 -0
  128. package/dist/core/mcp/connector.js.map +1 -0
  129. package/dist/core/mcp/contract.d.ts +19 -0
  130. package/dist/core/mcp/contract.d.ts.map +1 -0
  131. package/dist/core/mcp/contract.js +89 -0
  132. package/dist/core/mcp/contract.js.map +1 -0
  133. package/dist/core/mcp/mcp-tool.d.ts +32 -0
  134. package/dist/core/mcp/mcp-tool.d.ts.map +1 -0
  135. package/dist/core/mcp/mcp-tool.js +171 -0
  136. package/dist/core/mcp/mcp-tool.js.map +1 -0
  137. package/dist/core/mcp/metadata-cache.d.ts +29 -0
  138. package/dist/core/mcp/metadata-cache.d.ts.map +1 -0
  139. package/dist/core/mcp/metadata-cache.js +99 -0
  140. package/dist/core/mcp/metadata-cache.js.map +1 -0
  141. package/dist/core/mcp/oauth/authorize.d.ts +21 -0
  142. package/dist/core/mcp/oauth/authorize.d.ts.map +1 -0
  143. package/dist/core/mcp/oauth/authorize.js +32 -0
  144. package/dist/core/mcp/oauth/authorize.js.map +1 -0
  145. package/dist/core/mcp/oauth/discover.d.ts +27 -0
  146. package/dist/core/mcp/oauth/discover.d.ts.map +1 -0
  147. package/dist/core/mcp/oauth/discover.js +116 -0
  148. package/dist/core/mcp/oauth/discover.js.map +1 -0
  149. package/dist/core/mcp/oauth/flow.d.ts +31 -0
  150. package/dist/core/mcp/oauth/flow.d.ts.map +1 -0
  151. package/dist/core/mcp/oauth/flow.js +175 -0
  152. package/dist/core/mcp/oauth/flow.js.map +1 -0
  153. package/dist/core/mcp/oauth/mcp-token.d.ts +51 -0
  154. package/dist/core/mcp/oauth/mcp-token.d.ts.map +1 -0
  155. package/dist/core/mcp/oauth/mcp-token.js +129 -0
  156. package/dist/core/mcp/oauth/mcp-token.js.map +1 -0
  157. package/dist/core/mcp/oauth/pkce.d.ts +12 -0
  158. package/dist/core/mcp/oauth/pkce.d.ts.map +1 -0
  159. package/dist/core/mcp/oauth/pkce.js +11 -0
  160. package/dist/core/mcp/oauth/pkce.js.map +1 -0
  161. package/dist/core/mcp/oauth/register.d.ts +16 -0
  162. package/dist/core/mcp/oauth/register.d.ts.map +1 -0
  163. package/dist/core/mcp/oauth/register.js +42 -0
  164. package/dist/core/mcp/oauth/register.js.map +1 -0
  165. package/dist/core/mcp/oauth/token-client.d.ts +33 -0
  166. package/dist/core/mcp/oauth/token-client.d.ts.map +1 -0
  167. package/dist/core/mcp/oauth/token-client.js +65 -0
  168. package/dist/core/mcp/oauth/token-client.js.map +1 -0
  169. package/dist/core/mcp/runtime.d.ts +20 -0
  170. package/dist/core/mcp/runtime.d.ts.map +1 -0
  171. package/dist/core/mcp/runtime.js +37 -0
  172. package/dist/core/mcp/runtime.js.map +1 -0
  173. package/dist/core/mcp/schema.d.ts +22 -0
  174. package/dist/core/mcp/schema.d.ts.map +1 -0
  175. package/dist/core/mcp/schema.js +20 -0
  176. package/dist/core/mcp/schema.js.map +1 -0
  177. package/dist/core/mcp/server-manager.d.ts +43 -0
  178. package/dist/core/mcp/server-manager.d.ts.map +1 -0
  179. package/dist/core/mcp/server-manager.js +142 -0
  180. package/dist/core/mcp/server-manager.js.map +1 -0
  181. package/dist/core/mcp/types.d.ts +100 -0
  182. package/dist/core/mcp/types.d.ts.map +1 -0
  183. package/dist/core/mcp/types.js +8 -0
  184. package/dist/core/mcp/types.js.map +1 -0
  185. package/dist/core/model-config.d.ts +5 -0
  186. package/dist/core/model-config.d.ts.map +1 -1
  187. package/dist/core/model-config.js +3 -1
  188. package/dist/core/model-config.js.map +1 -1
  189. package/dist/core/model-resolver.d.ts +1 -0
  190. package/dist/core/model-resolver.d.ts.map +1 -1
  191. package/dist/core/model-resolver.js +14 -8
  192. package/dist/core/model-resolver.js.map +1 -1
  193. package/dist/core/models-store.d.ts.map +1 -1
  194. package/dist/core/models-store.js +2 -1
  195. package/dist/core/models-store.js.map +1 -1
  196. package/dist/core/package-manager.d.ts.map +1 -1
  197. package/dist/core/package-manager.js +22 -14
  198. package/dist/core/package-manager.js.map +1 -1
  199. package/dist/core/permissions/gate.d.ts.map +1 -1
  200. package/dist/core/permissions/gate.js +45 -4
  201. package/dist/core/permissions/gate.js.map +1 -1
  202. package/dist/core/permissions/operations.d.ts +20 -0
  203. package/dist/core/permissions/operations.d.ts.map +1 -0
  204. package/dist/core/permissions/operations.js +9 -0
  205. package/dist/core/permissions/operations.js.map +1 -0
  206. package/dist/core/permissions/policy-command.d.ts +42 -0
  207. package/dist/core/permissions/policy-command.d.ts.map +1 -0
  208. package/dist/core/permissions/policy-command.js +44 -0
  209. package/dist/core/permissions/policy-command.js.map +1 -0
  210. package/dist/core/permissions/responder.d.ts +49 -2
  211. package/dist/core/permissions/responder.d.ts.map +1 -1
  212. package/dist/core/permissions/responder.js +20 -8
  213. package/dist/core/permissions/responder.js.map +1 -1
  214. package/dist/core/permissions/rules.d.ts.map +1 -1
  215. package/dist/core/permissions/rules.js +11 -1
  216. package/dist/core/permissions/rules.js.map +1 -1
  217. package/dist/core/permissions/store.d.ts +18 -0
  218. package/dist/core/permissions/store.d.ts.map +1 -1
  219. package/dist/core/permissions/store.js +89 -8
  220. package/dist/core/permissions/store.js.map +1 -1
  221. package/dist/core/pi-manifest.d.ts.map +1 -1
  222. package/dist/core/pi-manifest.js +2 -1
  223. package/dist/core/pi-manifest.js.map +1 -1
  224. package/dist/core/policy-executor.d.ts +47 -0
  225. package/dist/core/policy-executor.d.ts.map +1 -0
  226. package/dist/core/policy-executor.js +228 -0
  227. package/dist/core/policy-executor.js.map +1 -0
  228. package/dist/core/policy-loader.d.ts +72 -0
  229. package/dist/core/policy-loader.d.ts.map +1 -0
  230. package/dist/core/policy-loader.js +195 -0
  231. package/dist/core/policy-loader.js.map +1 -0
  232. package/dist/core/project-trust.d.ts +1 -1
  233. package/dist/core/project-trust.d.ts.map +1 -1
  234. package/dist/core/project-trust.js.map +1 -1
  235. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  236. package/dist/core/remote-catalog-provider.js +2 -1
  237. package/dist/core/remote-catalog-provider.js.map +1 -1
  238. package/dist/core/resource-loader.d.ts.map +1 -1
  239. package/dist/core/resource-loader.js +3 -2
  240. package/dist/core/resource-loader.js.map +1 -1
  241. package/dist/core/sandbox/bwrap-arguments.d.ts +41 -0
  242. package/dist/core/sandbox/bwrap-arguments.d.ts.map +1 -0
  243. package/dist/core/sandbox/bwrap-arguments.js +136 -0
  244. package/dist/core/sandbox/bwrap-arguments.js.map +1 -0
  245. package/dist/core/sandbox/child-entry.d.ts.map +1 -1
  246. package/dist/core/sandbox/child-entry.js +3 -1
  247. package/dist/core/sandbox/child-entry.js.map +1 -1
  248. package/dist/core/sandbox/cli-launch.d.ts +84 -4
  249. package/dist/core/sandbox/cli-launch.d.ts.map +1 -1
  250. package/dist/core/sandbox/cli-launch.js +115 -16
  251. package/dist/core/sandbox/cli-launch.js.map +1 -1
  252. package/dist/core/sandbox/cli-supervisor.d.ts +2 -0
  253. package/dist/core/sandbox/cli-supervisor.d.ts.map +1 -1
  254. package/dist/core/sandbox/cli-supervisor.js +50 -2
  255. package/dist/core/sandbox/cli-supervisor.js.map +1 -1
  256. package/dist/core/sandbox/full-access.d.ts +28 -0
  257. package/dist/core/sandbox/full-access.d.ts.map +1 -0
  258. package/dist/core/sandbox/full-access.js +63 -0
  259. package/dist/core/sandbox/full-access.js.map +1 -0
  260. package/dist/core/sandbox/git-identity.d.ts +57 -0
  261. package/dist/core/sandbox/git-identity.d.ts.map +1 -0
  262. package/dist/core/sandbox/git-identity.js +78 -0
  263. package/dist/core/sandbox/git-identity.js.map +1 -0
  264. package/dist/core/sandbox/host-approval.d.ts +42 -0
  265. package/dist/core/sandbox/host-approval.d.ts.map +1 -0
  266. package/dist/core/sandbox/host-approval.js +99 -0
  267. package/dist/core/sandbox/host-approval.js.map +1 -0
  268. package/dist/core/sandbox/linux-backend.d.ts +14 -0
  269. package/dist/core/sandbox/linux-backend.d.ts.map +1 -1
  270. package/dist/core/sandbox/linux-backend.js +158 -80
  271. package/dist/core/sandbox/linux-backend.js.map +1 -1
  272. package/dist/core/sandbox/macos-backend.d.ts +5 -0
  273. package/dist/core/sandbox/macos-backend.d.ts.map +1 -1
  274. package/dist/core/sandbox/macos-backend.js +164 -5
  275. package/dist/core/sandbox/macos-backend.js.map +1 -1
  276. package/dist/core/sandbox/network-proxy.d.ts +19 -0
  277. package/dist/core/sandbox/network-proxy.d.ts.map +1 -1
  278. package/dist/core/sandbox/network-proxy.js +93 -19
  279. package/dist/core/sandbox/network-proxy.js.map +1 -1
  280. package/dist/core/sandbox/policy.d.ts +8 -0
  281. package/dist/core/sandbox/policy.d.ts.map +1 -1
  282. package/dist/core/sandbox/policy.js +29 -12
  283. package/dist/core/sandbox/policy.js.map +1 -1
  284. package/dist/core/sandbox/profiles.d.ts +25 -0
  285. package/dist/core/sandbox/profiles.d.ts.map +1 -0
  286. package/dist/core/sandbox/profiles.js +23 -0
  287. package/dist/core/sandbox/profiles.js.map +1 -0
  288. package/dist/core/sandbox/rpc/command-client.d.ts +28 -0
  289. package/dist/core/sandbox/rpc/command-client.d.ts.map +1 -0
  290. package/dist/core/sandbox/rpc/command-client.js +86 -0
  291. package/dist/core/sandbox/rpc/command-client.js.map +1 -0
  292. package/dist/core/sandbox/rpc/command-proxy.d.ts +48 -0
  293. package/dist/core/sandbox/rpc/command-proxy.d.ts.map +1 -0
  294. package/dist/core/sandbox/rpc/command-proxy.js +120 -0
  295. package/dist/core/sandbox/rpc/command-proxy.js.map +1 -0
  296. package/dist/core/sandbox/rpc/credential-proxy.d.ts.map +1 -1
  297. package/dist/core/sandbox/rpc/credential-proxy.js +2 -96
  298. package/dist/core/sandbox/rpc/credential-proxy.js.map +1 -1
  299. package/dist/core/sandbox/rpc/framing.d.ts +35 -0
  300. package/dist/core/sandbox/rpc/framing.d.ts.map +1 -0
  301. package/dist/core/sandbox/rpc/framing.js +114 -0
  302. package/dist/core/sandbox/rpc/framing.js.map +1 -0
  303. package/dist/core/sandbox/rpc/git-credential-helper.d.ts +47 -0
  304. package/dist/core/sandbox/rpc/git-credential-helper.d.ts.map +1 -0
  305. package/dist/core/sandbox/rpc/git-credential-helper.js +222 -0
  306. package/dist/core/sandbox/rpc/git-credential-helper.js.map +1 -0
  307. package/dist/core/sandbox/rpc/git-credential-proxy.d.ts +66 -0
  308. package/dist/core/sandbox/rpc/git-credential-proxy.d.ts.map +1 -0
  309. package/dist/core/sandbox/rpc/git-credential-proxy.js +209 -0
  310. package/dist/core/sandbox/rpc/git-credential-proxy.js.map +1 -0
  311. package/dist/core/sandbox/supervisor-temp.d.ts +18 -0
  312. package/dist/core/sandbox/supervisor-temp.d.ts.map +1 -0
  313. package/dist/core/sandbox/supervisor-temp.js +21 -0
  314. package/dist/core/sandbox/supervisor-temp.js.map +1 -0
  315. package/dist/core/sandbox/supervisor.d.ts +12 -1
  316. package/dist/core/sandbox/supervisor.d.ts.map +1 -1
  317. package/dist/core/sandbox/supervisor.js +15 -1
  318. package/dist/core/sandbox/supervisor.js.map +1 -1
  319. package/dist/core/sandbox/terminal-handoff.d.ts +68 -0
  320. package/dist/core/sandbox/terminal-handoff.d.ts.map +1 -0
  321. package/dist/core/sandbox/terminal-handoff.js +221 -0
  322. package/dist/core/sandbox/terminal-handoff.js.map +1 -0
  323. package/dist/core/sandbox/terminal-size.d.ts +13 -0
  324. package/dist/core/sandbox/terminal-size.d.ts.map +1 -1
  325. package/dist/core/sandbox/terminal-size.js +23 -2
  326. package/dist/core/sandbox/terminal-size.js.map +1 -1
  327. package/dist/core/sdk.d.ts +24 -2
  328. package/dist/core/sdk.d.ts.map +1 -1
  329. package/dist/core/sdk.js +63 -4
  330. package/dist/core/sdk.js.map +1 -1
  331. package/dist/core/session-export.d.ts +4 -0
  332. package/dist/core/session-export.d.ts.map +1 -0
  333. package/dist/core/session-export.js +32 -0
  334. package/dist/core/session-export.js.map +1 -0
  335. package/dist/core/session-manager.d.ts +13 -1
  336. package/dist/core/session-manager.d.ts.map +1 -1
  337. package/dist/core/session-manager.js +34 -6
  338. package/dist/core/session-manager.js.map +1 -1
  339. package/dist/core/settings-diagnostics.d.ts +9 -0
  340. package/dist/core/settings-diagnostics.d.ts.map +1 -0
  341. package/dist/core/settings-diagnostics.js +21 -0
  342. package/dist/core/settings-diagnostics.js.map +1 -0
  343. package/dist/core/settings-manager.d.ts +172 -1
  344. package/dist/core/settings-manager.d.ts.map +1 -1
  345. package/dist/core/settings-manager.js +160 -11
  346. package/dist/core/settings-manager.js.map +1 -1
  347. package/dist/core/skills.d.ts.map +1 -1
  348. package/dist/core/skills.js +51 -33
  349. package/dist/core/skills.js.map +1 -1
  350. package/dist/core/slash-commands.d.ts.map +1 -1
  351. package/dist/core/slash-commands.js +4 -1
  352. package/dist/core/slash-commands.js.map +1 -1
  353. package/dist/core/system-prompt.d.ts.map +1 -1
  354. package/dist/core/system-prompt.js +8 -2
  355. package/dist/core/system-prompt.js.map +1 -1
  356. package/dist/core/tools/background-shell.d.ts +39 -0
  357. package/dist/core/tools/background-shell.d.ts.map +1 -0
  358. package/dist/core/tools/background-shell.js +81 -0
  359. package/dist/core/tools/background-shell.js.map +1 -0
  360. package/dist/core/tools/bash-command-segments.d.ts.map +1 -1
  361. package/dist/core/tools/bash-command-segments.js +2 -0
  362. package/dist/core/tools/bash-command-segments.js.map +1 -1
  363. package/dist/core/tools/bash.d.ts +44 -16
  364. package/dist/core/tools/bash.d.ts.map +1 -1
  365. package/dist/core/tools/bash.js +264 -32
  366. package/dist/core/tools/bash.js.map +1 -1
  367. package/dist/core/tools/contract-snapshot.d.ts +58 -0
  368. package/dist/core/tools/contract-snapshot.d.ts.map +1 -0
  369. package/dist/core/tools/contract-snapshot.js +51 -0
  370. package/dist/core/tools/contract-snapshot.js.map +1 -0
  371. package/dist/core/tools/contract.d.ts +53 -5
  372. package/dist/core/tools/contract.d.ts.map +1 -1
  373. package/dist/core/tools/contract.js +22 -2
  374. package/dist/core/tools/contract.js.map +1 -1
  375. package/dist/core/tools/delegate.d.ts +6 -4
  376. package/dist/core/tools/delegate.d.ts.map +1 -1
  377. package/dist/core/tools/delegate.js +21 -11
  378. package/dist/core/tools/delegate.js.map +1 -1
  379. package/dist/core/tools/edit-diff.d.ts +48 -5
  380. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  381. package/dist/core/tools/edit-diff.js +217 -8
  382. package/dist/core/tools/edit-diff.js.map +1 -1
  383. package/dist/core/tools/edit.d.ts +8 -0
  384. package/dist/core/tools/edit.d.ts.map +1 -1
  385. package/dist/core/tools/edit.js +72 -10
  386. package/dist/core/tools/edit.js.map +1 -1
  387. package/dist/core/tools/find.d.ts.map +1 -1
  388. package/dist/core/tools/find.js +5 -2
  389. package/dist/core/tools/find.js.map +1 -1
  390. package/dist/core/tools/grep.d.ts.map +1 -1
  391. package/dist/core/tools/grep.js +5 -2
  392. package/dist/core/tools/grep.js.map +1 -1
  393. package/dist/core/tools/index.d.ts +14 -2
  394. package/dist/core/tools/index.d.ts.map +1 -1
  395. package/dist/core/tools/index.js +12 -0
  396. package/dist/core/tools/index.js.map +1 -1
  397. package/dist/core/tools/ls.d.ts.map +1 -1
  398. package/dist/core/tools/ls.js +5 -2
  399. package/dist/core/tools/ls.js.map +1 -1
  400. package/dist/core/tools/lsp.d.ts +19 -1
  401. package/dist/core/tools/lsp.d.ts.map +1 -1
  402. package/dist/core/tools/lsp.js +163 -10
  403. package/dist/core/tools/lsp.js.map +1 -1
  404. package/dist/core/tools/path-permission.d.ts +3 -0
  405. package/dist/core/tools/path-permission.d.ts.map +1 -1
  406. package/dist/core/tools/path-permission.js +16 -4
  407. package/dist/core/tools/path-permission.js.map +1 -1
  408. package/dist/core/tools/path-utils.d.ts +27 -2
  409. package/dist/core/tools/path-utils.d.ts.map +1 -1
  410. package/dist/core/tools/path-utils.js +221 -4
  411. package/dist/core/tools/path-utils.js.map +1 -1
  412. package/dist/core/tools/powershell.d.ts +16 -0
  413. package/dist/core/tools/powershell.d.ts.map +1 -0
  414. package/dist/core/tools/powershell.js +39 -0
  415. package/dist/core/tools/powershell.js.map +1 -0
  416. package/dist/core/tools/read.d.ts.map +1 -1
  417. package/dist/core/tools/read.js +20 -11
  418. package/dist/core/tools/read.js.map +1 -1
  419. package/dist/core/tools/test.d.ts +54 -9
  420. package/dist/core/tools/test.d.ts.map +1 -1
  421. package/dist/core/tools/test.js +239 -19
  422. package/dist/core/tools/test.js.map +1 -1
  423. package/dist/core/tools/write.d.ts +7 -0
  424. package/dist/core/tools/write.d.ts.map +1 -1
  425. package/dist/core/tools/write.js +64 -9
  426. package/dist/core/tools/write.js.map +1 -1
  427. package/dist/core/trust-manager.d.ts.map +1 -1
  428. package/dist/core/trust-manager.js +2 -1
  429. package/dist/core/trust-manager.js.map +1 -1
  430. package/dist/core/verification-lifecycle.d.ts +77 -0
  431. package/dist/core/verification-lifecycle.d.ts.map +1 -0
  432. package/dist/core/verification-lifecycle.js +146 -0
  433. package/dist/core/verification-lifecycle.js.map +1 -0
  434. package/dist/core/workspace/artifacts.d.ts +45 -0
  435. package/dist/core/workspace/artifacts.d.ts.map +1 -0
  436. package/dist/core/workspace/artifacts.js +165 -0
  437. package/dist/core/workspace/artifacts.js.map +1 -0
  438. package/dist/core/workspace/comparison.d.ts +27 -0
  439. package/dist/core/workspace/comparison.d.ts.map +1 -0
  440. package/dist/core/workspace/comparison.js +94 -0
  441. package/dist/core/workspace/comparison.js.map +1 -0
  442. package/dist/core/workspace/git-observer.d.ts +48 -0
  443. package/dist/core/workspace/git-observer.d.ts.map +1 -0
  444. package/dist/core/workspace/git-observer.js +346 -0
  445. package/dist/core/workspace/git-observer.js.map +1 -0
  446. package/dist/core/workspace/projection.d.ts +3 -0
  447. package/dist/core/workspace/projection.d.ts.map +1 -0
  448. package/dist/core/workspace/projection.js +56 -0
  449. package/dist/core/workspace/projection.js.map +1 -0
  450. package/dist/core/workspace/state.d.ts +133 -0
  451. package/dist/core/workspace/state.d.ts.map +1 -0
  452. package/dist/core/workspace/state.js +96 -0
  453. package/dist/core/workspace/state.js.map +1 -0
  454. package/dist/extensions/llama/client.d.ts +6 -0
  455. package/dist/extensions/llama/client.d.ts.map +1 -1
  456. package/dist/extensions/llama/client.js +7 -0
  457. package/dist/extensions/llama/client.js.map +1 -1
  458. package/dist/extensions/llama/index.d.ts.map +1 -1
  459. package/dist/extensions/llama/index.js +2 -0
  460. package/dist/extensions/llama/index.js.map +1 -1
  461. package/dist/extensions/llama/provider.d.ts +3 -1
  462. package/dist/extensions/llama/provider.d.ts.map +1 -1
  463. package/dist/extensions/llama/provider.js +29 -4
  464. package/dist/extensions/llama/provider.js.map +1 -1
  465. package/dist/index.d.ts +8 -5
  466. package/dist/index.d.ts.map +1 -1
  467. package/dist/index.js +7 -4
  468. package/dist/index.js.map +1 -1
  469. package/dist/main.d.ts +6 -0
  470. package/dist/main.d.ts.map +1 -1
  471. package/dist/main.js +58 -23
  472. package/dist/main.js.map +1 -1
  473. package/dist/migrations.d.ts.map +1 -1
  474. package/dist/migrations.js +4 -3
  475. package/dist/migrations.js.map +1 -1
  476. package/dist/modes/acp/server.d.ts +55 -0
  477. package/dist/modes/acp/server.d.ts.map +1 -0
  478. package/dist/modes/acp/server.js +244 -0
  479. package/dist/modes/acp/server.js.map +1 -0
  480. package/dist/modes/acp/translate.d.ts +37 -0
  481. package/dist/modes/acp/translate.d.ts.map +1 -0
  482. package/dist/modes/acp/translate.js +50 -0
  483. package/dist/modes/acp/translate.js.map +1 -0
  484. package/dist/modes/index.d.ts +1 -0
  485. package/dist/modes/index.d.ts.map +1 -1
  486. package/dist/modes/index.js +1 -0
  487. package/dist/modes/index.js.map +1 -1
  488. package/dist/modes/interactive/components/assistant-message.d.ts +29 -0
  489. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  490. package/dist/modes/interactive/components/assistant-message.js +182 -23
  491. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  492. package/dist/modes/interactive/components/bash-execution.d.ts +7 -0
  493. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  494. package/dist/modes/interactive/components/bash-execution.js +20 -0
  495. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  496. package/dist/modes/interactive/components/custom-editor.d.ts +9 -4
  497. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  498. package/dist/modes/interactive/components/custom-editor.js +20 -9
  499. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  500. package/dist/modes/interactive/components/extension-selector.d.ts +7 -1
  501. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  502. package/dist/modes/interactive/components/extension-selector.js +7 -3
  503. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  504. package/dist/modes/interactive/components/footer.d.ts +19 -0
  505. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  506. package/dist/modes/interactive/components/footer.js +70 -10
  507. package/dist/modes/interactive/components/footer.js.map +1 -1
  508. package/dist/modes/interactive/components/model-selector.d.ts +10 -3
  509. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  510. package/dist/modes/interactive/components/model-selector.js +56 -14
  511. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  512. package/dist/modes/interactive/components/permission-preview.d.ts +15 -0
  513. package/dist/modes/interactive/components/permission-preview.d.ts.map +1 -0
  514. package/dist/modes/interactive/components/permission-preview.js +33 -0
  515. package/dist/modes/interactive/components/permission-preview.js.map +1 -0
  516. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  517. package/dist/modes/interactive/components/session-selector.js +2 -2
  518. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  519. package/dist/modes/interactive/components/settings-selector.d.ts +9 -2
  520. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  521. package/dist/modes/interactive/components/settings-selector.js +128 -56
  522. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  523. package/dist/modes/interactive/components/settings-submenu.d.ts +72 -0
  524. package/dist/modes/interactive/components/settings-submenu.d.ts.map +1 -0
  525. package/dist/modes/interactive/components/settings-submenu.js +165 -0
  526. package/dist/modes/interactive/components/settings-submenu.js.map +1 -0
  527. package/dist/modes/interactive/components/thinking-selector.d.ts +15 -3
  528. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  529. package/dist/modes/interactive/components/thinking-selector.js +74 -17
  530. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  531. package/dist/modes/interactive/components/tool-execution.d.ts +23 -1
  532. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  533. package/dist/modes/interactive/components/tool-execution.js +64 -10
  534. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  535. package/dist/modes/interactive/external-editor.d.ts.map +1 -1
  536. package/dist/modes/interactive/external-editor.js +2 -1
  537. package/dist/modes/interactive/external-editor.js.map +1 -1
  538. package/dist/modes/interactive/interactive-mode.d.ts +45 -0
  539. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  540. package/dist/modes/interactive/interactive-mode.js +395 -43
  541. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  542. package/dist/modes/interactive/theme/theme.d.ts +12 -0
  543. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  544. package/dist/modes/interactive/theme/theme.js +20 -9
  545. package/dist/modes/interactive/theme/theme.js.map +1 -1
  546. package/dist/modes/json-event.d.ts +16 -13
  547. package/dist/modes/json-event.d.ts.map +1 -1
  548. package/dist/modes/json-event.js +20 -6
  549. package/dist/modes/json-event.js.map +1 -1
  550. package/dist/modes/print-mode.d.ts.map +1 -1
  551. package/dist/modes/print-mode.js +27 -12
  552. package/dist/modes/print-mode.js.map +1 -1
  553. package/dist/modes/rpc/rpc-client.d.ts +7 -0
  554. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  555. package/dist/modes/rpc/rpc-client.js +7 -0
  556. package/dist/modes/rpc/rpc-client.js.map +1 -1
  557. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  558. package/dist/modes/rpc/rpc-mode.js +3 -0
  559. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  560. package/dist/modes/rpc/rpc-types.d.ts +12 -0
  561. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  562. package/dist/modes/rpc/rpc-types.js.map +1 -1
  563. package/dist/package-manager-cli.d.ts +1 -0
  564. package/dist/package-manager-cli.d.ts.map +1 -1
  565. package/dist/package-manager-cli.js +196 -10
  566. package/dist/package-manager-cli.js.map +1 -1
  567. package/dist/utils/frontmatter.d.ts.map +1 -1
  568. package/dist/utils/frontmatter.js +2 -1
  569. package/dist/utils/frontmatter.js.map +1 -1
  570. package/dist/utils/management-http.d.ts +5 -3
  571. package/dist/utils/management-http.d.ts.map +1 -1
  572. package/dist/utils/management-http.js +14 -10
  573. package/dist/utils/management-http.js.map +1 -1
  574. package/dist/utils/shell.d.ts +3 -0
  575. package/dist/utils/shell.d.ts.map +1 -1
  576. package/dist/utils/shell.js +23 -9
  577. package/dist/utils/shell.js.map +1 -1
  578. package/dist/utils/syntax-highlight.d.ts +1 -0
  579. package/dist/utils/syntax-highlight.d.ts.map +1 -1
  580. package/dist/utils/syntax-highlight.js +60 -1
  581. package/dist/utils/syntax-highlight.js.map +1 -1
  582. package/dist/utils/text.d.ts +8 -0
  583. package/dist/utils/text.d.ts.map +1 -0
  584. package/dist/utils/text.js +9 -0
  585. package/dist/utils/text.js.map +1 -0
  586. package/dist/utils/version-check.d.ts.map +1 -1
  587. package/dist/utils/version-check.js +6 -4
  588. package/dist/utils/version-check.js.map +1 -1
  589. package/docs/compaction.md +19 -0
  590. package/docs/custom-provider.md +12 -9
  591. package/docs/environment-variables.md +1 -1
  592. package/docs/extensions.md +35 -7
  593. package/docs/json.md +7 -2
  594. package/docs/keybindings.md +9 -9
  595. package/docs/llama-cpp.md +2 -0
  596. package/docs/models.md +8 -2
  597. package/docs/packages.md +2 -2
  598. package/docs/quickstart.md +1 -1
  599. package/docs/rpc.md +32 -3
  600. package/docs/sdk.md +32 -2
  601. package/docs/settings.md +23 -7
  602. package/docs/skills.md +4 -3
  603. package/docs/terminal-setup.md +23 -7
  604. package/docs/usage.md +10 -5
  605. package/docs/windows.md +24 -2
  606. package/examples/extensions/border-status-editor.ts +1 -1
  607. package/examples/extensions/built-in-tool-renderer.ts +8 -4
  608. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  609. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  610. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  611. package/examples/extensions/git-checkpoint.ts +24 -36
  612. package/examples/extensions/gondolin/package-lock.json +2 -2
  613. package/examples/extensions/gondolin/package.json +1 -1
  614. package/examples/extensions/minimal-mode.ts +2 -2
  615. package/examples/extensions/notify.ts +3 -1
  616. package/examples/extensions/permission-gate.ts +1 -1
  617. package/examples/extensions/plan-mode/index.ts +1 -1
  618. package/examples/extensions/rpc-demo.ts +1 -1
  619. package/examples/extensions/sandbox/package-lock.json +2 -2
  620. package/examples/extensions/sandbox/package.json +1 -1
  621. package/examples/extensions/subagent/README.md +1 -1
  622. package/examples/extensions/subagent/index.ts +6 -1
  623. package/examples/extensions/titlebar-spinner.ts +1 -1
  624. package/examples/extensions/with-deps/package-lock.json +2 -2
  625. package/examples/extensions/with-deps/package.json +1 -1
  626. package/examples/rpc-extension-ui.ts +1 -1
  627. package/examples/sdk/06-extensions.ts +1 -1
  628. package/examples/sdk/README.md +1 -1
  629. package/npm-shrinkwrap.json +439 -405
  630. package/package.json +17 -17
  631. package/dist/server/create-harness.d.ts +0 -26
  632. package/dist/server/create-harness.d.ts.map +0 -1
  633. package/dist/server/create-harness.js +0 -107
  634. package/dist/server/create-harness.js.map +0 -1
@@ -7,22 +7,25 @@ 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, setKeybindings, Text, TruncatedText, TuiAltScreen, TuiMainScreen, visibleWidth, } 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";
11
11
  import chalk from "chalk";
12
12
  import { spawn, spawnSync } from "child_process";
13
13
  import { APP_NAME, APP_TITLE, CONFIG_DIR_NAME, getAgentDir, getAuthPath, getDebugLogPath, getDocsPath, getShareViewerUrl, VERSION, } from "../../config.js";
14
14
  import { parseSkillBlock } from "../../core/agent-session.js";
15
15
  import { SessionImportFileNotFoundError } from "../../core/agent-session-runtime.js";
16
16
  import { CACHE_TTL_MS, collectCacheMisses, computeCacheWaste, detectCacheMiss, } from "../../core/cache-stats.js";
17
+ import { DEFAULT_THINKING_LEVEL, THINKING_LEVEL_OPTIONS } from "../../core/defaults.js";
17
18
  import { getApexEnvironment } from "../../core/environment.js";
18
19
  import { FooterDataProvider } from "../../core/footer-data-provider.js";
19
20
  import { configureHttpDispatcher, formatHttpIdleTimeoutMs } from "../../core/http-dispatcher.js";
20
21
  import { KeybindingsManager } from "../../core/keybindings.js";
22
+ import { authorizeConfiguredServer } from "../../core/mcp/oauth/authorize.js";
21
23
  import { createCompactionSummaryMessage } from "../../core/messages.js";
22
24
  import { defaultModelPerProvider, findExactModelReferenceMatch, resolveModelScopeFromModels, } from "../../core/model-resolver.js";
23
25
  import { CredentialSynchronizationError } from "../../core/model-runtime.js";
24
26
  import { aggregateUsagePerformance } from "../../core/observability/aggregate.js";
25
27
  import { DefaultPackageManager } from "../../core/package-manager.js";
28
+ import { observeTerminalHandoff, TERMINAL_HANDOFF_ACK_PATH_VARIABLE, TERMINAL_HANDOFF_PATH_VARIABLE, } from "../../core/sandbox/terminal-handoff.js";
26
29
  import { formatMissingSessionCwdPrompt, MissingSessionCwdError } from "../../core/session-cwd.js";
27
30
  import { SessionManager, sessionEntryToContextMessages } from "../../core/session-manager.js";
28
31
  import { formatShareUnavailableMessage, publishSessionShare } from "../../core/session-share.js";
@@ -37,6 +40,7 @@ import { parseGitUrl } from "../../utils/git.js";
37
40
  import { openBrowser } from "../../utils/open-browser.js";
38
41
  import { getCwdRelativePath } from "../../utils/paths.js";
39
42
  import { killTrackedDetachedChildren } from "../../utils/shell.js";
43
+ import { loadAllHighlightLanguages } from "../../utils/syntax-highlight.js";
40
44
  import { ensureTool } from "../../utils/tools-manager.js";
41
45
  import { checkForNewApexCodeVersion } from "../../utils/version-check.js";
42
46
  import { ArminComponent } from "./components/armin.js";
@@ -61,12 +65,14 @@ import { LoginDialogComponent } from "./components/login-dialog.js";
61
65
  import { createMermaidMarkdownTransformer } from "./components/mermaid.js";
62
66
  import { ModelSelectorComponent } from "./components/model-selector.js";
63
67
  import { formatAuthSelectorProviderType, OAuthSelectorComponent, } from "./components/oauth-selector.js";
68
+ import { renderPermissionPreview } from "./components/permission-preview.js";
64
69
  import { ScopedModelsSelectorComponent } from "./components/scoped-models-selector.js";
65
70
  import { SessionSelectorComponent } from "./components/session-selector.js";
66
71
  import { PERMISSION_MODE_OVERRIDE_HINTS, SettingsSelectorComponent } from "./components/settings-selector.js";
67
72
  import { SkillInvocationMessageComponent } from "./components/skill-invocation-message.js";
68
73
  import { ApexSplashHeader } from "./components/splash-header.js";
69
74
  import { BranchSummaryStatusIndicator, CompactionStatusIndicator, IdleStatus, RetryStatusIndicator, WorkingStatusIndicator, } from "./components/status-indicator.js";
75
+ import { ThinkingSelectorComponent } from "./components/thinking-selector.js";
70
76
  import { ToolExecutionComponent } from "./components/tool-execution.js";
71
77
  import { TreeSelectorComponent } from "./components/tree-selector.js";
72
78
  import { TrustSelectorComponent } from "./components/trust-selector.js";
@@ -95,6 +101,9 @@ class ExpandableText extends Text {
95
101
  function isCustomSessionEntry(item) {
96
102
  return "type" in item && item.type === "custom";
97
103
  }
104
+ function isCompactionCostNotice(item) {
105
+ return "type" in item && item.type === "compaction_cost";
106
+ }
98
107
  const DEAD_TERMINAL_ERROR_CODES = new Set(["EIO", "EPIPE", "ENOTCONN"]);
99
108
  function isDeadTerminalError(error) {
100
109
  if (!error || typeof error !== "object" || !("code" in error)) {
@@ -134,6 +143,11 @@ export function formatResumeCommand(sessionManager) {
134
143
  function hasDefaultModelProvider(providerId) {
135
144
  return providerId in defaultModelPerProvider;
136
145
  }
146
+ function llamaCppPostLoginGuidance(actionLabel, loadedModelCount) {
147
+ return loadedModelCount === 0
148
+ ? `${actionLabel}. No llama.cpp models are loaded. Use /llama to load a model, then /model to select it.`
149
+ : `${actionLabel}. Use /model to select a loaded llama.cpp model, or /llama to manage models.`;
150
+ }
137
151
  const AUTH_TYPE_ORDER = { oauth: 0, api_key: 1 };
138
152
  function createFuzzyAutocompleteItems(items, prefix, getSearchText, toAutocompleteItem) {
139
153
  const filtered = fuzzyFilter(items, prefix, getSearchText);
@@ -180,6 +194,7 @@ export function createInteractiveTui(options) {
180
194
  searchCurrentMatchStyle: (text) => theme.bold(theme.inverse(styleSearchMatch(text))),
181
195
  openUrl: openBrowser,
182
196
  onRightClickPaste: options.onRightClickPaste,
197
+ copyOnSelect: options.fullscreenCopyOnSelect,
183
198
  copySelection: async (text) => {
184
199
  try {
185
200
  await copyToClipboard(text);
@@ -224,6 +239,23 @@ export function createInteractiveTuiReference(getTui) {
224
239
  getPrototypeOf: () => Reflect.getPrototypeOf(getTui()),
225
240
  });
226
241
  }
242
+ /**
243
+ * Working status rides in the footer tray; everything else keeps its own rows.
244
+ *
245
+ * The tray is a line the screen already spends, so a turn no longer costs two
246
+ * rows above the editor. Retry, compaction and branch summary stay in the status
247
+ * container. They are interruptions rather than steady state and they carry
248
+ * their own countdowns.
249
+ *
250
+ * A custom footer replaces the built-in one entirely, so a session running one
251
+ * keeps its indicator where it can still be seen.
252
+ *
253
+ * Free of `this` so the white-box prototype tests can exercise the callers
254
+ * without fabricating a whole InteractiveMode.
255
+ */
256
+ function trayOwnsActivity(kind, hasCustomFooter) {
257
+ return kind === "working" && !hasCustomFooter;
258
+ }
227
259
  export class InteractiveMode {
228
260
  runtimeHost;
229
261
  /** Settled once the most recent /settings permission-mode write has hit disk. */
@@ -305,6 +337,11 @@ export class InteractiveMode {
305
337
  firstUseHints;
306
338
  // Track current bash execution component
307
339
  bashComponent = undefined;
340
+ // Reentrancy guard: session.isBashRunning only turns true inside
341
+ // executeBash, so a second `!cmd` submitted during the extension
342
+ // emitUserBash await would otherwise overwrite the in-flight component
343
+ // and orphan the first command's output callback.
344
+ isHandlingBashCommand = false;
308
345
  // Track pending bash components (shown in pending area, moved to chat on submit)
309
346
  pendingBashComponents = [];
310
347
  // Auto-compaction state
@@ -362,6 +399,7 @@ export class InteractiveMode {
362
399
  }
363
400
  constructor(runtimeHost, options = {}) {
364
401
  this.runtimeHost = runtimeHost;
402
+ setCapabilityOverrides(this.settingsManager.getTerminalCapabilityOverrides());
365
403
  const tuiMode = options.tuiMode ?? this.settingsManager.getTuiMode();
366
404
  this.options = { ...options, tuiMode };
367
405
  this.autoTrustOnReloadCwd = options.autoTrustOnReloadCwd;
@@ -378,6 +416,7 @@ export class InteractiveMode {
378
416
  showHardwareCursor: this.settingsManager.getShowHardwareCursor(),
379
417
  logDirectory: getAgentDir(),
380
418
  onRightClickPaste: this.onRightClickPaste,
419
+ fullscreenCopyOnSelect: this.settingsManager.getFullscreenCopyOnSelect(),
381
420
  });
382
421
  this.ui = createInteractiveTuiReference(() => this.renderer);
383
422
  this.ui.setClearOnShrink(this.settingsManager.getClearOnShrink());
@@ -401,6 +440,10 @@ export class InteractiveMode {
401
440
  autocompleteMaxVisible,
402
441
  promptPrefix: "› ",
403
442
  promptColor: (text) => theme.fg("accent", text),
443
+ // Bash mode changes the glyph as well as the hue, so the mode is still
444
+ // readable on a monochrome terminal. Same cell count, so nothing shifts.
445
+ bashPromptPrefix: "! ",
446
+ bashPromptColor: (text) => theme.fg("bashMode", text),
404
447
  placeholder: "Ask anything",
405
448
  placeholderColor: (text) => theme.fg("dim", text),
406
449
  commandColor: (text) => theme.fg("accent", text),
@@ -467,8 +510,21 @@ export class InteractiveMode {
467
510
  path: command.sourceInfo.path,
468
511
  }));
469
512
  }
470
- createBaseAutocompleteProvider() {
471
- // Define commands for autocomplete
513
+ /**
514
+ * Every *registered* command: builtin, prompt template, extension, and skill.
515
+ *
516
+ * One function rather than two because `/help` renders this list and autocomplete
517
+ * completes it. Built in two places they would disagree the first time either grew a
518
+ * source, and the disagreement would show up as a command a user can complete but not
519
+ * find, or find but not run.
520
+ *
521
+ * A few commands are dispatched without being registered -- `/debug`, and the
522
+ * `/arminsayshi` and `/dementedelves` easter eggs. They are absent here on purpose,
523
+ * which is also why autocomplete has never offered them. "Registered" is the boundary
524
+ * both surfaces share; listing them in `/help` would advertise what completion cannot
525
+ * complete.
526
+ */
527
+ collectSessionCommands() {
472
528
  const slashCommands = BUILTIN_SLASH_COMMANDS.map((command) => ({
473
529
  name: command.name,
474
530
  description: command.description,
@@ -496,6 +552,15 @@ export class InteractiveMode {
496
552
  }));
497
553
  };
498
554
  }
555
+ const thinkingCommand = slashCommands.find((command) => command.name === "thinking");
556
+ if (thinkingCommand) {
557
+ thinkingCommand.getArgumentCompletions = (prefix) => {
558
+ return createFuzzyAutocompleteItems(this.session.getAvailableThinkingLevels(), prefix, (level) => level, (level) => ({
559
+ value: level,
560
+ label: level,
561
+ }));
562
+ };
563
+ }
499
564
  const loginCommand = slashCommands.find((command) => command.name === "login");
500
565
  if (loginCommand) {
501
566
  loginCommand.getArgumentCompletions = (prefix) => {
@@ -536,7 +601,10 @@ export class InteractiveMode {
536
601
  });
537
602
  }
538
603
  }
539
- return new CombinedAutocompleteProvider([...slashCommands, ...templateCommands, ...extensionCommands, ...skillCommandList], this.sessionManager.getCwd(), this.fdPath);
604
+ return [...slashCommands, ...templateCommands, ...extensionCommands, ...skillCommandList];
605
+ }
606
+ createBaseAutocompleteProvider() {
607
+ return new CombinedAutocompleteProvider(this.collectSessionCommands(), this.sessionManager.getCwd(), this.fdPath);
540
608
  }
541
609
  setupAutocompleteProvider() {
542
610
  let provider = this.createBaseAutocompleteProvider();
@@ -624,6 +692,7 @@ export class InteractiveMode {
624
692
  logDirectory: getAgentDir(),
625
693
  terminal,
626
694
  onRightClickPaste: this.onRightClickPaste,
695
+ fullscreenCopyOnSelect: this.settingsManager.getFullscreenCopyOnSelect(),
627
696
  });
628
697
  nextUi.setClearOnShrink(clearOnShrink);
629
698
  nextUi.onDebug = onDebug;
@@ -792,6 +861,14 @@ export class InteractiveMode {
792
861
  });
793
862
  // Initialize available provider count for footer display
794
863
  await this.updateAvailableProviderCount();
864
+ // Flush the completed startup state before loading the remaining syntax grammars.
865
+ this.ui.renderNow();
866
+ void loadAllHighlightLanguages().then(() => {
867
+ if (!this.isInitialized)
868
+ return;
869
+ this.ui.invalidate();
870
+ this.ui.requestRender();
871
+ });
795
872
  }
796
873
  /**
797
874
  * Update terminal title with session name and cwd.
@@ -847,7 +924,18 @@ export class InteractiveMode {
847
924
  }
848
925
  });
849
926
  // Show startup warnings
850
- const { migratedProviders, modelFallbackMessage, initialMessage, initialImages, initialMessages } = this.options;
927
+ const { migratedProviders, startupDiagnostics, modelFallbackMessage, initialMessage, initialImages, initialMessages, } = this.options;
928
+ for (const diagnostic of startupDiagnostics ?? []) {
929
+ if (diagnostic.type === "error") {
930
+ this.showError(diagnostic.message);
931
+ }
932
+ else if (diagnostic.type === "warning") {
933
+ this.showWarning(diagnostic.message);
934
+ }
935
+ else {
936
+ this.showStatus(diagnostic.message);
937
+ }
938
+ }
851
939
  if (migratedProviders && migratedProviders.length > 0) {
852
940
  this.showWarning(`Migrated credentials to auth.json: ${migratedProviders.join(", ")}`);
853
941
  }
@@ -1569,8 +1657,12 @@ export class InteractiveMode {
1569
1657
  this.transcriptScrollView?.setScrollbar(this.settingsManager.getFullscreenScrollbar());
1570
1658
  }
1571
1659
  applyRuntimeSettings() {
1660
+ setCapabilityOverrides(this.settingsManager.getTerminalCapabilityOverrides());
1572
1661
  configureHttpDispatcher(this.settingsManager.getHttpIdleTimeoutMs());
1573
1662
  this.applyFullscreenScrollbarSetting();
1663
+ if (this.renderer instanceof TuiAltScreen) {
1664
+ this.renderer.setCopyOnSelect(this.settingsManager.getFullscreenCopyOnSelect());
1665
+ }
1574
1666
  this.footer.setSession(this.session);
1575
1667
  this.footer.setAutoCompactEnabled(this.session.autoCompactionEnabled);
1576
1668
  void this.refreshFooterPermissionMode();
@@ -1626,6 +1718,15 @@ export class InteractiveMode {
1626
1718
  this.compactionQueuedMessages = [];
1627
1719
  this.streamingComponent = undefined;
1628
1720
  this.streamingMessage = undefined;
1721
+ // The clears above detach children without stopping their animation
1722
+ // timers. Bash components embed an animated loader; dispose them
1723
+ // explicitly so an in-flight `!cmd` cannot keep rendering (or get
1724
+ // flushed back into a fresh session by flushPendingBashComponents).
1725
+ for (const component of this.pendingBashComponents)
1726
+ component.dispose();
1727
+ this.pendingBashComponents = [];
1728
+ this.bashComponent?.dispose();
1729
+ this.bashComponent = undefined;
1629
1730
  this.clearPendingTools();
1630
1731
  this.renderInitialMessages();
1631
1732
  }
@@ -1712,6 +1813,11 @@ export class InteractiveMode {
1712
1813
  this.activeStatusIndicator?.dispose();
1713
1814
  this.activeStatusIndicator = indicator;
1714
1815
  this.statusContainer.clear();
1816
+ if (trayOwnsActivity(indicator.kind, this.customFooter !== undefined)) {
1817
+ this.footer.setActivity(indicator);
1818
+ return;
1819
+ }
1820
+ this.footer.setActivity(undefined);
1715
1821
  this.statusContainer.addChild(indicator);
1716
1822
  }
1717
1823
  clearStatusIndicator(kind) {
@@ -1719,13 +1825,23 @@ export class InteractiveMode {
1719
1825
  return;
1720
1826
  }
1721
1827
  const hadActiveStatusIndicator = this.activeStatusIndicator !== undefined;
1828
+ const wasInTray = this.activeStatusIndicator !== undefined &&
1829
+ trayOwnsActivity(this.activeStatusIndicator.kind, this.customFooter !== undefined);
1722
1830
  this.activeStatusIndicator?.dispose();
1723
1831
  this.activeStatusIndicator = undefined;
1832
+ this.footer?.setActivity(undefined);
1724
1833
  this.statusContainer.clear();
1834
+ // The tray never occupied those rows, so it must not leave the idle filler
1835
+ // behind to reserve them.
1836
+ if (wasInTray)
1837
+ return;
1725
1838
  if (hadActiveStatusIndicator && this.options.tuiMode === "regular" && this.ui.getClearOnShrink()) {
1726
1839
  this.statusContainer.addChild(this.idleStatus);
1727
1840
  }
1728
1841
  }
1842
+ showWorkingStatusIndicator() {
1843
+ this.showStatusIndicator(new WorkingStatusIndicator(this.ui, this.workingMessage ?? this.defaultWorkingMessage, this.workingIndicatorOptions));
1844
+ }
1729
1845
  setWorkingVisible(visible) {
1730
1846
  this.workingVisible = visible;
1731
1847
  if (!visible) {
@@ -1734,7 +1850,7 @@ export class InteractiveMode {
1734
1850
  return;
1735
1851
  }
1736
1852
  if (this.session.isStreaming && this.activeStatusIndicator?.kind !== "working") {
1737
- this.showStatusIndicator(new WorkingStatusIndicator(this.ui, this.workingMessage ?? this.defaultWorkingMessage, this.workingIndicatorOptions));
1853
+ this.showWorkingStatusIndicator();
1738
1854
  }
1739
1855
  this.ui.requestRender();
1740
1856
  }
@@ -2040,6 +2156,7 @@ export class InteractiveMode {
2040
2156
  timeout: opts?.timeout,
2041
2157
  onToggleToolsExpanded: () => this.toggleToolOutputExpansion(),
2042
2158
  enableSearch,
2159
+ preamble: opts?.preview ? renderPermissionPreview(opts.preview) : undefined,
2043
2160
  });
2044
2161
  this.disposeActiveSelector();
2045
2162
  this.editorContainer.clear();
@@ -2089,10 +2206,24 @@ export class InteractiveMode {
2089
2206
  this.showTrustSelector();
2090
2207
  break;
2091
2208
  case "Resources, extensions, and MCP adapters":
2092
- this.showStatus("Run apex-code config to manage resources, extensions, and MCP adapters.");
2209
+ this.showStatus(this.describeMcpServers());
2093
2210
  break;
2094
2211
  }
2095
2212
  }
2213
+ /**
2214
+ * Report configured MCP servers and their live connection state. Replaces a string
2215
+ * that offered MCP management from `apex-code config`, which manages package
2216
+ * resources and has never been able to configure a server.
2217
+ */
2218
+ describeMcpServers() {
2219
+ const runtime = this.session.mcpRuntime;
2220
+ const servers = runtime ? [...runtime.servers.keys()] : [];
2221
+ if (servers.length === 0) {
2222
+ return "Run apex-code config to manage resources and extensions. No MCP server is configured; add one to .mcp.json.";
2223
+ }
2224
+ const states = servers.map((name) => `${name} (${runtime?.manager.state(name).kind ?? "disconnected"})`);
2225
+ return `Run apex-code config to manage resources and extensions. MCP servers: ${states.join(", ")}.`;
2226
+ }
2096
2227
  /**
2097
2228
  * Show a confirmation dialog for extensions.
2098
2229
  */
@@ -2393,7 +2524,7 @@ export class InteractiveMode {
2393
2524
  this.defaultEditor.onAction("app.tools.expand", () => this.toggleToolOutputExpansion());
2394
2525
  this.defaultEditor.onAction("app.thinking.toggle", () => this.toggleThinkingBlockVisibility());
2395
2526
  this.defaultEditor.onAction("app.editor.external", () => void this.handleOpenExternalEditor());
2396
- this.defaultEditor.onAction("app.message.copy", () => void this.handleCopyCommand({ flashConfirmation: true }));
2527
+ this.defaultEditor.onAction("app.message.copy", () => void this.handleCopyCommand({ flashConfirmation: true, preferSelection: true }));
2397
2528
  this.defaultEditor.onAction("app.message.followUp", () => this.handleFollowUp());
2398
2529
  this.defaultEditor.onAction("app.message.dequeue", () => this.handleDequeue());
2399
2530
  this.defaultEditor.onAction("app.session.new", () => this.handleClearCommand());
@@ -2492,6 +2623,12 @@ export class InteractiveMode {
2492
2623
  await this.handleModelCommand(searchTerm);
2493
2624
  return;
2494
2625
  }
2626
+ if (text === "/thinking" || text.startsWith("/thinking ")) {
2627
+ const searchTerm = text.startsWith("/thinking ") ? text.slice(10).trim() : undefined;
2628
+ this.editor.setText("");
2629
+ this.handleThinkingCommand(searchTerm);
2630
+ return;
2631
+ }
2495
2632
  if (text === "/export" || text.startsWith("/export ")) {
2496
2633
  await this.handleExportCommand(text);
2497
2634
  this.editor.setText("");
@@ -2537,6 +2674,11 @@ export class InteractiveMode {
2537
2674
  this.editor.setText("");
2538
2675
  return;
2539
2676
  }
2677
+ if (text === "/help") {
2678
+ this.handleHelpCommand();
2679
+ this.editor.setText("");
2680
+ return;
2681
+ }
2540
2682
  if (text === "/fork") {
2541
2683
  this.showUserMessageSelector();
2542
2684
  this.editor.setText("");
@@ -2568,6 +2710,12 @@ export class InteractiveMode {
2568
2710
  this.editor.setText("");
2569
2711
  return;
2570
2712
  }
2713
+ if (text === "/mcp" || text.startsWith("/mcp ")) {
2714
+ const mcpArgs = text.slice(4).trim().split(/\s+/).filter(Boolean);
2715
+ this.editor.setText("");
2716
+ await this.handleMcpAuthCommand(mcpArgs);
2717
+ return;
2718
+ }
2571
2719
  if (text === "/new") {
2572
2720
  this.editor.setText("");
2573
2721
  await this.handleClearCommand();
@@ -2682,8 +2830,15 @@ export class InteractiveMode {
2682
2830
  this.defaultEditor.onEscape = this.retryEscapeHandler;
2683
2831
  this.retryEscapeHandler = undefined;
2684
2832
  }
2833
+ break;
2834
+ case "turn_start":
2835
+ if (this.settingsManager.getShowTerminalProgress()) {
2836
+ this.ui.terminal.setProgress(true);
2837
+ }
2685
2838
  if (this.workingVisible) {
2686
- this.showStatusIndicator(new WorkingStatusIndicator(this.ui, this.workingMessage ?? this.defaultWorkingMessage, this.workingIndicatorOptions));
2839
+ if (this.activeStatusIndicator?.kind !== "working") {
2840
+ this.showWorkingStatusIndicator();
2841
+ }
2687
2842
  }
2688
2843
  else {
2689
2844
  this.clearStatusIndicator();
@@ -2878,9 +3033,21 @@ export class InteractiveMode {
2878
3033
  }
2879
3034
  }
2880
3035
  else if (event.result) {
3036
+ const entries = this.sessionManager.buildContextEntries();
3037
+ if (entries[0]?.type !== "compaction") {
3038
+ throw new Error("Completed compaction is missing from the session context");
3039
+ }
2881
3040
  this.chatContainer.clear();
2882
- this.rebuildChatFromMessages();
3041
+ // The latest compaction is prepended for model context; append it below at its chronological position.
3042
+ this.renderSessionEntries(entries.slice(1));
2883
3043
  this.addMessageToChat(createCompactionSummaryMessage(event.result.summary, event.result.tokensBefore, new Date().toISOString()));
3044
+ if (event.result.usage) {
3045
+ this.addCompactionCostNotice({
3046
+ type: "compaction_cost",
3047
+ kind: "compaction",
3048
+ usage: event.result.usage,
3049
+ });
3050
+ }
2884
3051
  this.footer.invalidate();
2885
3052
  }
2886
3053
  else if (event.errorMessage) {
@@ -3102,6 +3269,10 @@ export class InteractiveMode {
3102
3269
  this.addCustomEntryToChat(item);
3103
3270
  continue;
3104
3271
  }
3272
+ if (isCompactionCostNotice(item)) {
3273
+ this.addCompactionCostNotice(item);
3274
+ continue;
3275
+ }
3105
3276
  const message = item;
3106
3277
  // Assistant messages need special handling for tool calls
3107
3278
  if (message.role === "assistant") {
@@ -3169,10 +3340,28 @@ export class InteractiveMode {
3169
3340
  if (entry.type === "custom") {
3170
3341
  return [entry];
3171
3342
  }
3172
- return sessionEntryToContextMessages(entry);
3343
+ const messages = sessionEntryToContextMessages(entry);
3344
+ if ((entry.type === "compaction" || entry.type === "branch_summary") && entry.usage && messages.length > 0) {
3345
+ return [...messages, { type: "compaction_cost", kind: entry.type, usage: entry.usage }];
3346
+ }
3347
+ return messages;
3173
3348
  });
3174
3349
  this.renderSessionItems(items, options);
3175
3350
  }
3351
+ /**
3352
+ * Render billing usage for a compaction or branch summary. The notice is derived
3353
+ * from persisted summary usage and is not stored as a separate session entry.
3354
+ */
3355
+ addCompactionCostNotice(notice) {
3356
+ if (!this.settingsManager.getShowCacheMissNotices())
3357
+ return;
3358
+ const { usage } = notice;
3359
+ const tokens = usage.input + usage.output + usage.cacheRead + usage.cacheWrite;
3360
+ const cost = usage.cost.total >= 0.01 ? ` (~$${usage.cost.total.toFixed(2)})` : "";
3361
+ const label = notice.kind === "compaction" ? "Compaction" : "Branch summary";
3362
+ this.chatContainer.addChild(new Spacer(1));
3363
+ this.chatContainer.addChild(new Text(theme.fg("warning", `${label}: ${formatTokens(tokens)} tokens billed${cost}`), 1, 0));
3364
+ }
3176
3365
  /**
3177
3366
  * Show a transcript notice when a completed assistant message paid for a
3178
3367
  * significant cache miss. Only states observable facts: the miss itself,
@@ -3383,6 +3572,34 @@ export class InteractiveMode {
3383
3572
  const uncaughtExceptionHandler = (error) => this.uncaughtCrash(error);
3384
3573
  process.prependListener("uncaughtException", uncaughtExceptionHandler);
3385
3574
  this.signalCleanupHandlers.push(() => process.off("uncaughtException", uncaughtExceptionHandler));
3575
+ // Lend the terminal back to the supervisor when it needs to draw a sandbox
3576
+ // escalation prompt. The supervisor owns that decision (ADR 0023) and this
3577
+ // process cannot read the answer anyway -- bwrap --new-session leaves it with no
3578
+ // controlling terminal. `ui.stop()` is the same restore Ctrl+Z already performs,
3579
+ // so the terminal is in cooked mode with a visible cursor while the human answers.
3580
+ const handoffDirectory = process.env[TERMINAL_HANDOFF_PATH_VARIABLE];
3581
+ if (handoffDirectory) {
3582
+ const observer = observeTerminalHandoff(handoffDirectory, {
3583
+ suspend: () => {
3584
+ try {
3585
+ this.ui.stop();
3586
+ }
3587
+ catch {
3588
+ // A terminal we cannot restore still leaves the prompt readable.
3589
+ }
3590
+ },
3591
+ resume: () => {
3592
+ try {
3593
+ this.ui.start();
3594
+ this.ui.requestRender(true);
3595
+ }
3596
+ catch {
3597
+ // Nothing further to try; the next render request recovers.
3598
+ }
3599
+ },
3600
+ }, { acknowledgementPath: process.env[TERMINAL_HANDOFF_ACK_PATH_VARIABLE] });
3601
+ this.signalCleanupHandlers.push(() => observer.stop());
3602
+ }
3386
3603
  }
3387
3604
  unregisterSignalHandlers() {
3388
3605
  for (const cleanup of this.signalCleanupHandlers) {
@@ -3464,7 +3681,9 @@ export class InteractiveMode {
3464
3681
  }
3465
3682
  }
3466
3683
  updateEditorBorderColor() {
3467
- this.defaultEditor.setModeLabel(this.isBashMode ? "bash" : this.session.isStreaming ? "busy" : undefined);
3684
+ // Streaming no longer touches the dock. WorkingStatusIndicator already owns
3685
+ // that signal, and a `[busy]` prefix moved the caret mid-turn.
3686
+ this.defaultEditor.setPromptMode(this.isBashMode ? "bash" : "agent");
3468
3687
  if (this.isBashMode) {
3469
3688
  this.editor.borderColor = theme.getBashModeBorderColor();
3470
3689
  }
@@ -3524,19 +3743,20 @@ export class InteractiveMode {
3524
3743
  }
3525
3744
  this.showStatus(`Tool output: ${expanded ? "expanded" : "collapsed"}`);
3526
3745
  }
3746
+ /** Update rendered assistant messages without rebuilding live tool components. */
3747
+ updateThinkingBlockVisibility() {
3748
+ for (const child of this.chatContainer.children) {
3749
+ if (child instanceof AssistantMessageComponent) {
3750
+ child.setHideThinkingBlock(this.hideThinkingBlock);
3751
+ }
3752
+ }
3753
+ this.ui.requestRender();
3754
+ }
3527
3755
  toggleThinkingBlockVisibility() {
3528
3756
  this.offerFirstUseHint("thinking");
3529
3757
  this.hideThinkingBlock = !this.hideThinkingBlock;
3530
3758
  this.settingsManager.setHideThinkingBlock(this.hideThinkingBlock);
3531
- // Rebuild chat from session messages
3532
- this.chatContainer.clear();
3533
- this.rebuildChatFromMessages();
3534
- // If streaming, re-add the streaming component with updated visibility and re-render
3535
- if (this.streamingComponent && this.streamingMessage) {
3536
- this.streamingComponent.setHideThinkingBlock(this.hideThinkingBlock);
3537
- this.streamingComponent.updateContent(this.streamingMessage);
3538
- this.chatContainer.addChild(this.streamingComponent);
3539
- }
3759
+ this.updateThinkingBlockVisibility();
3540
3760
  this.showStatus(`Thinking blocks: ${this.hideThinkingBlock ? "hidden" : "visible"}`);
3541
3761
  }
3542
3762
  async handleOpenExternalEditor() {
@@ -3858,8 +4078,14 @@ export class InteractiveMode {
3858
4078
  const permissionMode = await this.session.getPermissionMode();
3859
4079
  this.showSelector((done) => {
3860
4080
  let selector;
4081
+ const defaultProvider = this.settingsManager.getDefaultProvider();
4082
+ const defaultModelId = this.settingsManager.getDefaultModel();
4083
+ const defaultModel = defaultProvider && defaultModelId ? `${defaultProvider}/${defaultModelId}` : "not set";
3861
4084
  selector = new SettingsSelectorComponent({
3862
4085
  autoCompact: this.session.autoCompactionEnabled,
4086
+ defaultModel,
4087
+ currentModel: this.session.model,
4088
+ availableDefaultModels: this.session.modelRuntime.getAvailableSnapshot(),
3863
4089
  showImages: this.settingsManager.getShowImages(),
3864
4090
  imageWidthCells: this.settingsManager.getImageWidthCells(),
3865
4091
  autoResizeImages: this.settingsManager.getImageAutoResize(),
@@ -3869,8 +4095,9 @@ export class InteractiveMode {
3869
4095
  followUpMode: this.session.followUpMode,
3870
4096
  transport: this.settingsManager.getTransport(),
3871
4097
  httpIdleTimeoutMs: this.settingsManager.getHttpIdleTimeoutMs(),
3872
- thinkingLevel: this.session.thinkingLevel,
3873
- availableThinkingLevels: this.session.getAvailableThinkingLevels(),
4098
+ thinkingLevel: this.settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL,
4099
+ availableThinkingLevels: [...THINKING_LEVEL_OPTIONS],
4100
+ modelThinkingLevels: this.settingsManager.getAllModelThinkingLevels(),
3874
4101
  currentTheme: this.themeController.getThemeSelection() || "dark",
3875
4102
  terminalTheme: this.themeController.getTerminalTheme(),
3876
4103
  availableThemes: getAvailableThemes(),
@@ -3893,6 +4120,7 @@ export class InteractiveMode {
3893
4120
  tuiMode: this.ui.mode,
3894
4121
  fullscreenExitOutput: this.settingsManager.getFullscreenExitOutput(),
3895
4122
  fullscreenScrollbar: this.settingsManager.getFullscreenScrollbar(),
4123
+ fullscreenCopyOnSelect: this.settingsManager.getFullscreenCopyOnSelect(),
3896
4124
  warnings: this.settingsManager.getWarnings(),
3897
4125
  }, {
3898
4126
  onAutoCompactChange: (enabled) => {
@@ -3940,10 +4168,26 @@ export class InteractiveMode {
3940
4168
  configureHttpDispatcher(timeoutMs);
3941
4169
  this.showStatus(`HTTP idle timeout: ${formatHttpIdleTimeoutMs(timeoutMs)}`);
3942
4170
  },
3943
- onThinkingLevelChange: (level) => {
3944
- this.session.setThinkingLevel(level);
3945
- this.footer.invalidate();
3946
- this.updateEditorBorderColor();
4171
+ onModelThinkingLevelChange: (provider, modelId, level) => {
4172
+ this.settingsManager.setModelThinkingLevel(provider, modelId, level);
4173
+ // If the override is for the current model, apply it to the session too
4174
+ const current = this.session.model;
4175
+ if (current && current.provider === provider && current.id === modelId) {
4176
+ this.session.setThinkingLevel(level);
4177
+ this.footer.invalidate();
4178
+ this.updateEditorBorderColor();
4179
+ }
4180
+ },
4181
+ onModelThinkingLevelRemove: (provider, modelId) => {
4182
+ this.settingsManager.removeModelThinkingLevel(provider, modelId);
4183
+ // If the override was for the current model, revert to global default
4184
+ const current = this.session.model;
4185
+ if (current && current.provider === provider && current.id === modelId) {
4186
+ const globalDefault = this.settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL;
4187
+ this.session.setThinkingLevel(globalDefault);
4188
+ this.footer.invalidate();
4189
+ this.updateEditorBorderColor();
4190
+ }
3947
4191
  },
3948
4192
  onThemeChange: (themeSetting) => {
3949
4193
  this.settingsManager.setTheme(themeSetting);
@@ -3953,13 +4197,7 @@ export class InteractiveMode {
3953
4197
  onHideThinkingBlockChange: (hidden) => {
3954
4198
  this.hideThinkingBlock = hidden;
3955
4199
  this.settingsManager.setHideThinkingBlock(hidden);
3956
- for (const child of this.chatContainer.children) {
3957
- if (child instanceof AssistantMessageComponent) {
3958
- child.setHideThinkingBlock(hidden);
3959
- }
3960
- }
3961
- this.chatContainer.clear();
3962
- this.rebuildChatFromMessages();
4200
+ this.updateThinkingBlockVisibility();
3963
4201
  },
3964
4202
  onMermaidRenderingModeChange: (mode) => {
3965
4203
  this.settingsManager.setMermaidRenderingMode(mode);
@@ -4056,6 +4294,11 @@ export class InteractiveMode {
4056
4294
  this.settingsManager.setFullscreenScrollbar(mode);
4057
4295
  this.applyFullscreenScrollbarSetting();
4058
4296
  },
4297
+ onFullscreenCopyOnSelectChange: (enabled) => {
4298
+ this.settingsManager.setFullscreenCopyOnSelect(enabled);
4299
+ if (this.renderer instanceof TuiAltScreen)
4300
+ this.renderer.setCopyOnSelect(enabled);
4301
+ },
4059
4302
  onWarningsChange: (warnings) => {
4060
4303
  this.settingsManager.setWarnings(warnings);
4061
4304
  },
@@ -4067,6 +4310,44 @@ export class InteractiveMode {
4067
4310
  return { component: selector, focus: selector.getSettingsList() };
4068
4311
  });
4069
4312
  }
4313
+ handleThinkingCommand(searchTerm) {
4314
+ const availableLevels = this.session.getAvailableThinkingLevels();
4315
+ if (!searchTerm) {
4316
+ this.showThinkingSelector();
4317
+ return;
4318
+ }
4319
+ const normalized = searchTerm.trim().toLowerCase();
4320
+ const level = availableLevels.find((candidate) => candidate.toLowerCase() === normalized);
4321
+ if (!level) {
4322
+ this.showError(`Unknown thinking level "${searchTerm}". Available levels: ${availableLevels.join(", ")}.`);
4323
+ return;
4324
+ }
4325
+ this.selectThinkingLevel(level, false);
4326
+ }
4327
+ selectThinkingLevel(level, persist) {
4328
+ try {
4329
+ this.session.setThinkingLevel(level, { persist });
4330
+ this.footer.invalidate();
4331
+ this.updateEditorBorderColor();
4332
+ this.showStatus(persist ? `Default thinking level: ${level}` : `Thinking level: ${level}`);
4333
+ }
4334
+ catch (error) {
4335
+ this.showError(error instanceof Error ? error.message : String(error));
4336
+ }
4337
+ }
4338
+ showThinkingSelector() {
4339
+ this.showSelector((done) => {
4340
+ const selectLevel = (level, persist) => {
4341
+ this.selectThinkingLevel(level, persist);
4342
+ done();
4343
+ };
4344
+ const selector = new ThinkingSelectorComponent(this.session.thinkingLevel ?? DEFAULT_THINKING_LEVEL, this.session.getAvailableThinkingLevels(), (level) => selectLevel(level, false), () => {
4345
+ done();
4346
+ this.ui.requestRender();
4347
+ }, (level) => selectLevel(level, true), this.settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL);
4348
+ return { component: selector, focus: selector };
4349
+ });
4350
+ }
4070
4351
  async handleModelCommand(searchTerm) {
4071
4352
  if (!searchTerm) {
4072
4353
  this.showModelSelector();
@@ -4075,7 +4356,7 @@ export class InteractiveMode {
4075
4356
  const model = await this.findExactModelMatch(searchTerm);
4076
4357
  if (model) {
4077
4358
  try {
4078
- await this.session.setModel(model);
4359
+ await this.session.setModel(model, { persist: false });
4079
4360
  this.footer.invalidate();
4080
4361
  this.updateEditorBorderColor();
4081
4362
  this.showStatus(`Model: ${model.id}`);
@@ -4204,13 +4485,14 @@ export class InteractiveMode {
4204
4485
  }
4205
4486
  showModelSelector(initialSearchInput) {
4206
4487
  this.showSelector((done) => {
4207
- const selector = new ModelSelectorComponent(this.ui, this.session.model, this.settingsManager, this.session.modelRuntime, this.session.scopedModels, async (model) => {
4488
+ const selectModel = async (model, persist) => {
4208
4489
  try {
4209
- await this.session.setModel(model);
4490
+ await this.session.setModel(model, { persist });
4491
+ this.updateAvailableProviderCount();
4210
4492
  this.footer.invalidate();
4211
4493
  this.updateEditorBorderColor();
4212
4494
  done();
4213
- this.showStatus(`Model: ${model.id}`);
4495
+ this.showStatus(persist ? `Default model: ${model.provider}/${model.id}` : `Model: ${model.id}`);
4214
4496
  void this.maybeWarnAboutAnthropicSubscriptionAuth(model);
4215
4497
  this.checkDaxnutsEasterEgg(model);
4216
4498
  }
@@ -4218,10 +4500,13 @@ export class InteractiveMode {
4218
4500
  done();
4219
4501
  this.showError(error instanceof Error ? error.message : String(error));
4220
4502
  }
4221
- }, () => {
4503
+ };
4504
+ const defaultProvider = this.settingsManager.getDefaultProvider();
4505
+ const defaultModel = this.settingsManager.getDefaultModel();
4506
+ const selector = new ModelSelectorComponent(this.ui, this.session.model, this.session.modelRuntime, this.session.scopedModels, (model) => selectModel(model, false), () => {
4222
4507
  done();
4223
4508
  this.ui.requestRender();
4224
- }, initialSearchInput);
4509
+ }, initialSearchInput, (model) => selectModel(model, true), defaultProvider && defaultModel ? { provider: defaultProvider, id: defaultModel } : undefined);
4225
4510
  return { component: selector, focus: selector, dispose: () => selector.dispose() };
4226
4511
  });
4227
4512
  }
@@ -4614,6 +4899,27 @@ export class InteractiveMode {
4614
4899
  return this.getLoginProviderOptions().filter((provider) => provider.id.toLowerCase() === normalizedProviderRef ||
4615
4900
  provider.name.toLowerCase() === normalizedProviderRef);
4616
4901
  }
4902
+ /** `/mcp auth <server>`: runs the same OAuth flow as the CLI, printing into the chat. */
4903
+ async handleMcpAuthCommand(mcpArgs) {
4904
+ const show = (line, kind = "dim") => {
4905
+ this.chatContainer.addChild(new Text(theme.fg(kind, line), 1, 0));
4906
+ this.ui.requestRender();
4907
+ };
4908
+ if (mcpArgs[0] !== "auth" || !mcpArgs[1] || mcpArgs.length > 2) {
4909
+ show("Usage: /mcp auth <server>", "error");
4910
+ return;
4911
+ }
4912
+ try {
4913
+ await authorizeConfiguredServer({
4914
+ serverName: mcpArgs[1],
4915
+ openBrowser: (url) => openBrowser(url),
4916
+ log: (line) => show(line),
4917
+ });
4918
+ }
4919
+ catch (error) {
4920
+ show(`Error: ${error instanceof Error ? error.message : String(error)}`, "error");
4921
+ }
4922
+ }
4617
4923
  async handleLoginCommand(providerRef) {
4618
4924
  if (!providerRef) {
4619
4925
  this.showLoginAuthTypeSelector();
@@ -4777,7 +5083,11 @@ export class InteractiveMode {
4777
5083
  if (isUnknownModel(previousModel)) {
4778
5084
  const availableModels = this.session.modelRuntime.getAvailableSnapshot();
4779
5085
  const providerModels = availableModels.filter((model) => model.provider === providerId);
4780
- if (!hasDefaultModelProvider(providerId)) {
5086
+ // Matches LLAMA_PROVIDER_ID from extensions/llama/provider.ts; kept inline to avoid coupling interactive mode to the built-in extension.
5087
+ if (providerId === "llama.cpp") {
5088
+ selectionError = llamaCppPostLoginGuidance(actionLabel, providerModels.length);
5089
+ }
5090
+ else if (!hasDefaultModelProvider(providerId)) {
4781
5091
  selectionError = `${actionLabel}, but no default model is configured for provider "${providerId}". Use /model to select a model.`;
4782
5092
  }
4783
5093
  else if (providerModels.length === 0) {
@@ -4791,7 +5101,7 @@ export class InteractiveMode {
4791
5101
  }
4792
5102
  else {
4793
5103
  try {
4794
- await this.session.setModel(selectedModel);
5104
+ await this.session.setModel(selectedModel, { persist: true });
4795
5105
  }
4796
5106
  catch (error) {
4797
5107
  selectedModel = undefined;
@@ -5048,8 +5358,8 @@ export class InteractiveMode {
5048
5358
  activeHeader.setExpanded(this.toolOutputExpanded);
5049
5359
  }
5050
5360
  setRegisteredThemes(this.session.resourceLoader.getThemes().themes);
5051
- await this.themeController.applyFromSettings();
5052
5361
  this.applyRuntimeSettings();
5362
+ await this.themeController.applyFromSettings();
5053
5363
  this.setupAutocompleteProvider();
5054
5364
  const runner = this.session.extensionRunner;
5055
5365
  this.setupExtensionShortcuts(runner);
@@ -5233,6 +5543,13 @@ export class InteractiveMode {
5233
5543
  }
5234
5544
  }
5235
5545
  async handleCopyCommand(options = {}) {
5546
+ if (options.preferSelection &&
5547
+ this.ui instanceof TuiAltScreen &&
5548
+ !this.ui.getCopyOnSelect() &&
5549
+ this.ui.hasActiveSelection()) {
5550
+ await this.ui.copyActiveSelectionToClipboard();
5551
+ return;
5552
+ }
5236
5553
  const text = this.session.getLastAssistantText();
5237
5554
  if (!text) {
5238
5555
  this.showError("No agent messages to copy yet.");
@@ -5491,6 +5808,28 @@ export class InteractiveMode {
5491
5808
  this.chatContainer.addChild(new DynamicBorder());
5492
5809
  this.ui.requestRender();
5493
5810
  }
5811
+ /**
5812
+ * Renders what `collectSessionCommands` returns, so the list a user reads and the list
5813
+ * autocomplete offers are the same list rather than two that agree today. Unregistered
5814
+ * dispatch-only commands are outside that boundary; see the note there.
5815
+ */
5816
+ handleHelpCommand() {
5817
+ const commands = this.collectSessionCommands();
5818
+ const rows = commands
5819
+ .map((command) => {
5820
+ const invocation = command.argumentHint ? `/${command.name} ${command.argumentHint}` : `/${command.name}`;
5821
+ return `| \`${invocation}\` | ${command.description ?? ""} |`;
5822
+ })
5823
+ .join("\n");
5824
+ const help = `| Command | Description |\n|---------|-------------|\n${rows}\n\nType \`/\` to filter these, or \`/hotkeys\` for keyboard shortcuts.`;
5825
+ this.chatContainer.addChild(new Spacer(1));
5826
+ this.chatContainer.addChild(new DynamicBorder());
5827
+ this.chatContainer.addChild(new Text(theme.bold(theme.fg("accent", "Commands")), 1, 0));
5828
+ this.chatContainer.addChild(new Spacer(1));
5829
+ this.chatContainer.addChild(new Markdown(help, 1, 1, this.getMarkdownThemeWithSettings()));
5830
+ this.chatContainer.addChild(new DynamicBorder());
5831
+ this.ui.requestRender();
5832
+ }
5494
5833
  async handleClearCommand() {
5495
5834
  this.clearStatusIndicator();
5496
5835
  try {
@@ -5554,6 +5893,19 @@ export class InteractiveMode {
5554
5893
  }
5555
5894
  }
5556
5895
  async handleBashCommand(command, excludeFromContext = false) {
5896
+ if (this.isHandlingBashCommand) {
5897
+ this.showWarning("A bash command is already running; wait for it to finish");
5898
+ return;
5899
+ }
5900
+ this.isHandlingBashCommand = true;
5901
+ try {
5902
+ await this.runBashCommand(command, excludeFromContext);
5903
+ }
5904
+ finally {
5905
+ this.isHandlingBashCommand = false;
5906
+ }
5907
+ }
5908
+ async runBashCommand(command, excludeFromContext = false) {
5557
5909
  const extensionRunner = this.session.extensionRunner;
5558
5910
  // Emit user_bash event to let extensions intercept
5559
5911
  const eventResult = await extensionRunner.emitUserBash({