apex-code 0.0.1-alpha.9 → 0.0.5

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 (513) hide show
  1. package/CHANGELOG.md +150 -2
  2. package/README.md +9 -8
  3. package/dist/cli/args.d.ts +25 -1
  4. package/dist/cli/args.d.ts.map +1 -1
  5. package/dist/cli/args.js +43 -1
  6. package/dist/cli/args.js.map +1 -1
  7. package/dist/cli/mcp-command.d.ts +9 -0
  8. package/dist/cli/mcp-command.d.ts.map +1 -0
  9. package/dist/cli/mcp-command.js +53 -0
  10. package/dist/cli/mcp-command.js.map +1 -0
  11. package/dist/cli/project-trust.d.ts.map +1 -1
  12. package/dist/cli/project-trust.js +3 -1
  13. package/dist/cli/project-trust.js.map +1 -1
  14. package/dist/cli/startup-ui.d.ts.map +1 -1
  15. package/dist/cli/startup-ui.js +2 -1
  16. package/dist/cli/startup-ui.js.map +1 -1
  17. package/dist/cli.d.ts.map +1 -1
  18. package/dist/cli.js +94 -5
  19. package/dist/cli.js.map +1 -1
  20. package/dist/config.d.ts.map +1 -1
  21. package/dist/config.js +24 -5
  22. package/dist/config.js.map +1 -1
  23. package/dist/core/agent-session-services.d.ts +3 -0
  24. package/dist/core/agent-session-services.d.ts.map +1 -1
  25. package/dist/core/agent-session-services.js +1 -0
  26. package/dist/core/agent-session-services.js.map +1 -1
  27. package/dist/core/agent-session.d.ts +157 -8
  28. package/dist/core/agent-session.d.ts.map +1 -1
  29. package/dist/core/agent-session.js +565 -22
  30. package/dist/core/agent-session.js.map +1 -1
  31. package/dist/core/bash-executor.d.ts.map +1 -1
  32. package/dist/core/bash-executor.js +7 -0
  33. package/dist/core/bash-executor.js.map +1 -1
  34. package/dist/core/checkpoints/git-checkpoints.d.ts +39 -0
  35. package/dist/core/checkpoints/git-checkpoints.d.ts.map +1 -0
  36. package/dist/core/checkpoints/git-checkpoints.js +251 -0
  37. package/dist/core/checkpoints/git-checkpoints.js.map +1 -0
  38. package/dist/core/checkpoints/session-checkpoints.d.ts +23 -0
  39. package/dist/core/checkpoints/session-checkpoints.d.ts.map +1 -0
  40. package/dist/core/checkpoints/session-checkpoints.js +36 -0
  41. package/dist/core/checkpoints/session-checkpoints.js.map +1 -0
  42. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  43. package/dist/core/compaction/branch-summarization.js +4 -3
  44. package/dist/core/compaction/branch-summarization.js.map +1 -1
  45. package/dist/core/compaction/compaction.d.ts +5 -0
  46. package/dist/core/compaction/compaction.d.ts.map +1 -1
  47. package/dist/core/compaction/compaction.js +19 -5
  48. package/dist/core/compaction/compaction.js.map +1 -1
  49. package/dist/core/delegation/runtime.d.ts +6 -5
  50. package/dist/core/delegation/runtime.d.ts.map +1 -1
  51. package/dist/core/delegation/runtime.js +4 -3
  52. package/dist/core/delegation/runtime.js.map +1 -1
  53. package/dist/core/exec.d.ts.map +1 -1
  54. package/dist/core/exec.js +5 -2
  55. package/dist/core/exec.js.map +1 -1
  56. package/dist/core/extensions/index.d.ts +1 -1
  57. package/dist/core/extensions/index.d.ts.map +1 -1
  58. package/dist/core/extensions/index.js.map +1 -1
  59. package/dist/core/extensions/loader.d.ts.map +1 -1
  60. package/dist/core/extensions/loader.js +8 -2
  61. package/dist/core/extensions/loader.js.map +1 -1
  62. package/dist/core/extensions/runner.d.ts +5 -0
  63. package/dist/core/extensions/runner.d.ts.map +1 -1
  64. package/dist/core/extensions/runner.js +45 -1
  65. package/dist/core/extensions/runner.js.map +1 -1
  66. package/dist/core/extensions/source-runtime.d.ts +14 -0
  67. package/dist/core/extensions/source-runtime.d.ts.map +1 -0
  68. package/dist/core/extensions/source-runtime.js +56 -0
  69. package/dist/core/extensions/source-runtime.js.map +1 -0
  70. package/dist/core/extensions/types.d.ts +22 -2
  71. package/dist/core/extensions/types.d.ts.map +1 -1
  72. package/dist/core/extensions/types.js.map +1 -1
  73. package/dist/core/formatter-lifecycle.d.ts +69 -0
  74. package/dist/core/formatter-lifecycle.d.ts.map +1 -0
  75. package/dist/core/formatter-lifecycle.js +360 -0
  76. package/dist/core/formatter-lifecycle.js.map +1 -0
  77. package/dist/core/hooks/command-handler.d.ts +19 -0
  78. package/dist/core/hooks/command-handler.d.ts.map +1 -0
  79. package/dist/core/hooks/command-handler.js +112 -0
  80. package/dist/core/hooks/command-handler.js.map +1 -0
  81. package/dist/core/hooks/http-handler.d.ts +10 -0
  82. package/dist/core/hooks/http-handler.d.ts.map +1 -0
  83. package/dist/core/hooks/http-handler.js +36 -0
  84. package/dist/core/hooks/http-handler.js.map +1 -0
  85. package/dist/core/hooks/loader.d.ts +29 -0
  86. package/dist/core/hooks/loader.d.ts.map +1 -0
  87. package/dist/core/hooks/loader.js +139 -0
  88. package/dist/core/hooks/loader.js.map +1 -0
  89. package/dist/core/hooks/runtime.d.ts +13 -0
  90. package/dist/core/hooks/runtime.d.ts.map +1 -0
  91. package/dist/core/hooks/runtime.js +63 -0
  92. package/dist/core/hooks/runtime.js.map +1 -0
  93. package/dist/core/hooks/types.d.ts +83 -0
  94. package/dist/core/hooks/types.d.ts.map +1 -0
  95. package/dist/core/hooks/types.js +24 -0
  96. package/dist/core/hooks/types.js.map +1 -0
  97. package/dist/core/mcp/config.d.ts +16 -0
  98. package/dist/core/mcp/config.d.ts.map +1 -0
  99. package/dist/core/mcp/config.js +166 -0
  100. package/dist/core/mcp/config.js.map +1 -0
  101. package/dist/core/mcp/connector.d.ts +35 -0
  102. package/dist/core/mcp/connector.d.ts.map +1 -0
  103. package/dist/core/mcp/connector.js +105 -0
  104. package/dist/core/mcp/connector.js.map +1 -0
  105. package/dist/core/mcp/contract.d.ts +19 -0
  106. package/dist/core/mcp/contract.d.ts.map +1 -0
  107. package/dist/core/mcp/contract.js +89 -0
  108. package/dist/core/mcp/contract.js.map +1 -0
  109. package/dist/core/mcp/mcp-tool.d.ts +32 -0
  110. package/dist/core/mcp/mcp-tool.d.ts.map +1 -0
  111. package/dist/core/mcp/mcp-tool.js +171 -0
  112. package/dist/core/mcp/mcp-tool.js.map +1 -0
  113. package/dist/core/mcp/metadata-cache.d.ts +29 -0
  114. package/dist/core/mcp/metadata-cache.d.ts.map +1 -0
  115. package/dist/core/mcp/metadata-cache.js +99 -0
  116. package/dist/core/mcp/metadata-cache.js.map +1 -0
  117. package/dist/core/mcp/oauth/authorize.d.ts +21 -0
  118. package/dist/core/mcp/oauth/authorize.d.ts.map +1 -0
  119. package/dist/core/mcp/oauth/authorize.js +32 -0
  120. package/dist/core/mcp/oauth/authorize.js.map +1 -0
  121. package/dist/core/mcp/oauth/discover.d.ts +27 -0
  122. package/dist/core/mcp/oauth/discover.d.ts.map +1 -0
  123. package/dist/core/mcp/oauth/discover.js +116 -0
  124. package/dist/core/mcp/oauth/discover.js.map +1 -0
  125. package/dist/core/mcp/oauth/flow.d.ts +31 -0
  126. package/dist/core/mcp/oauth/flow.d.ts.map +1 -0
  127. package/dist/core/mcp/oauth/flow.js +175 -0
  128. package/dist/core/mcp/oauth/flow.js.map +1 -0
  129. package/dist/core/mcp/oauth/mcp-token.d.ts +51 -0
  130. package/dist/core/mcp/oauth/mcp-token.d.ts.map +1 -0
  131. package/dist/core/mcp/oauth/mcp-token.js +129 -0
  132. package/dist/core/mcp/oauth/mcp-token.js.map +1 -0
  133. package/dist/core/mcp/oauth/pkce.d.ts +12 -0
  134. package/dist/core/mcp/oauth/pkce.d.ts.map +1 -0
  135. package/dist/core/mcp/oauth/pkce.js +11 -0
  136. package/dist/core/mcp/oauth/pkce.js.map +1 -0
  137. package/dist/core/mcp/oauth/register.d.ts +16 -0
  138. package/dist/core/mcp/oauth/register.d.ts.map +1 -0
  139. package/dist/core/mcp/oauth/register.js +42 -0
  140. package/dist/core/mcp/oauth/register.js.map +1 -0
  141. package/dist/core/mcp/oauth/token-client.d.ts +33 -0
  142. package/dist/core/mcp/oauth/token-client.d.ts.map +1 -0
  143. package/dist/core/mcp/oauth/token-client.js +65 -0
  144. package/dist/core/mcp/oauth/token-client.js.map +1 -0
  145. package/dist/core/mcp/runtime.d.ts +20 -0
  146. package/dist/core/mcp/runtime.d.ts.map +1 -0
  147. package/dist/core/mcp/runtime.js +37 -0
  148. package/dist/core/mcp/runtime.js.map +1 -0
  149. package/dist/core/mcp/schema.d.ts +22 -0
  150. package/dist/core/mcp/schema.d.ts.map +1 -0
  151. package/dist/core/mcp/schema.js +20 -0
  152. package/dist/core/mcp/schema.js.map +1 -0
  153. package/dist/core/mcp/server-manager.d.ts +43 -0
  154. package/dist/core/mcp/server-manager.d.ts.map +1 -0
  155. package/dist/core/mcp/server-manager.js +142 -0
  156. package/dist/core/mcp/server-manager.js.map +1 -0
  157. package/dist/core/mcp/types.d.ts +100 -0
  158. package/dist/core/mcp/types.d.ts.map +1 -0
  159. package/dist/core/mcp/types.js +8 -0
  160. package/dist/core/mcp/types.js.map +1 -0
  161. package/dist/core/permissions/gate.d.ts.map +1 -1
  162. package/dist/core/permissions/gate.js +45 -4
  163. package/dist/core/permissions/gate.js.map +1 -1
  164. package/dist/core/permissions/operations.d.ts +20 -0
  165. package/dist/core/permissions/operations.d.ts.map +1 -0
  166. package/dist/core/permissions/operations.js +9 -0
  167. package/dist/core/permissions/operations.js.map +1 -0
  168. package/dist/core/permissions/policy-command.d.ts +42 -0
  169. package/dist/core/permissions/policy-command.d.ts.map +1 -0
  170. package/dist/core/permissions/policy-command.js +44 -0
  171. package/dist/core/permissions/policy-command.js.map +1 -0
  172. package/dist/core/permissions/responder.d.ts +49 -2
  173. package/dist/core/permissions/responder.d.ts.map +1 -1
  174. package/dist/core/permissions/responder.js +20 -8
  175. package/dist/core/permissions/responder.js.map +1 -1
  176. package/dist/core/permissions/rules.d.ts.map +1 -1
  177. package/dist/core/permissions/rules.js +11 -1
  178. package/dist/core/permissions/rules.js.map +1 -1
  179. package/dist/core/permissions/store.d.ts +18 -0
  180. package/dist/core/permissions/store.d.ts.map +1 -1
  181. package/dist/core/permissions/store.js +89 -8
  182. package/dist/core/permissions/store.js.map +1 -1
  183. package/dist/core/policy-executor.d.ts +47 -0
  184. package/dist/core/policy-executor.d.ts.map +1 -0
  185. package/dist/core/policy-executor.js +228 -0
  186. package/dist/core/policy-executor.js.map +1 -0
  187. package/dist/core/policy-loader.d.ts +72 -0
  188. package/dist/core/policy-loader.d.ts.map +1 -0
  189. package/dist/core/policy-loader.js +195 -0
  190. package/dist/core/policy-loader.js.map +1 -0
  191. package/dist/core/project-trust.d.ts +1 -1
  192. package/dist/core/project-trust.d.ts.map +1 -1
  193. package/dist/core/project-trust.js.map +1 -1
  194. package/dist/core/sandbox/bwrap-arguments.d.ts +41 -0
  195. package/dist/core/sandbox/bwrap-arguments.d.ts.map +1 -0
  196. package/dist/core/sandbox/bwrap-arguments.js +136 -0
  197. package/dist/core/sandbox/bwrap-arguments.js.map +1 -0
  198. package/dist/core/sandbox/child-entry.d.ts.map +1 -1
  199. package/dist/core/sandbox/child-entry.js +3 -1
  200. package/dist/core/sandbox/child-entry.js.map +1 -1
  201. package/dist/core/sandbox/cli-launch.d.ts +84 -4
  202. package/dist/core/sandbox/cli-launch.d.ts.map +1 -1
  203. package/dist/core/sandbox/cli-launch.js +115 -16
  204. package/dist/core/sandbox/cli-launch.js.map +1 -1
  205. package/dist/core/sandbox/cli-supervisor.d.ts +2 -0
  206. package/dist/core/sandbox/cli-supervisor.d.ts.map +1 -1
  207. package/dist/core/sandbox/cli-supervisor.js +50 -2
  208. package/dist/core/sandbox/cli-supervisor.js.map +1 -1
  209. package/dist/core/sandbox/full-access.d.ts +28 -0
  210. package/dist/core/sandbox/full-access.d.ts.map +1 -0
  211. package/dist/core/sandbox/full-access.js +63 -0
  212. package/dist/core/sandbox/full-access.js.map +1 -0
  213. package/dist/core/sandbox/git-identity.d.ts +57 -0
  214. package/dist/core/sandbox/git-identity.d.ts.map +1 -0
  215. package/dist/core/sandbox/git-identity.js +78 -0
  216. package/dist/core/sandbox/git-identity.js.map +1 -0
  217. package/dist/core/sandbox/host-approval.d.ts +42 -0
  218. package/dist/core/sandbox/host-approval.d.ts.map +1 -0
  219. package/dist/core/sandbox/host-approval.js +99 -0
  220. package/dist/core/sandbox/host-approval.js.map +1 -0
  221. package/dist/core/sandbox/linux-backend.d.ts +14 -0
  222. package/dist/core/sandbox/linux-backend.d.ts.map +1 -1
  223. package/dist/core/sandbox/linux-backend.js +158 -80
  224. package/dist/core/sandbox/linux-backend.js.map +1 -1
  225. package/dist/core/sandbox/macos-backend.d.ts +5 -0
  226. package/dist/core/sandbox/macos-backend.d.ts.map +1 -1
  227. package/dist/core/sandbox/macos-backend.js +164 -5
  228. package/dist/core/sandbox/macos-backend.js.map +1 -1
  229. package/dist/core/sandbox/network-proxy.d.ts +19 -0
  230. package/dist/core/sandbox/network-proxy.d.ts.map +1 -1
  231. package/dist/core/sandbox/network-proxy.js +93 -19
  232. package/dist/core/sandbox/network-proxy.js.map +1 -1
  233. package/dist/core/sandbox/policy.d.ts +8 -0
  234. package/dist/core/sandbox/policy.d.ts.map +1 -1
  235. package/dist/core/sandbox/policy.js +29 -12
  236. package/dist/core/sandbox/policy.js.map +1 -1
  237. package/dist/core/sandbox/profiles.d.ts +25 -0
  238. package/dist/core/sandbox/profiles.d.ts.map +1 -0
  239. package/dist/core/sandbox/profiles.js +23 -0
  240. package/dist/core/sandbox/profiles.js.map +1 -0
  241. package/dist/core/sandbox/rpc/command-client.d.ts +28 -0
  242. package/dist/core/sandbox/rpc/command-client.d.ts.map +1 -0
  243. package/dist/core/sandbox/rpc/command-client.js +86 -0
  244. package/dist/core/sandbox/rpc/command-client.js.map +1 -0
  245. package/dist/core/sandbox/rpc/command-proxy.d.ts +48 -0
  246. package/dist/core/sandbox/rpc/command-proxy.d.ts.map +1 -0
  247. package/dist/core/sandbox/rpc/command-proxy.js +120 -0
  248. package/dist/core/sandbox/rpc/command-proxy.js.map +1 -0
  249. package/dist/core/sandbox/rpc/credential-proxy.d.ts.map +1 -1
  250. package/dist/core/sandbox/rpc/credential-proxy.js +2 -96
  251. package/dist/core/sandbox/rpc/credential-proxy.js.map +1 -1
  252. package/dist/core/sandbox/rpc/framing.d.ts +35 -0
  253. package/dist/core/sandbox/rpc/framing.d.ts.map +1 -0
  254. package/dist/core/sandbox/rpc/framing.js +114 -0
  255. package/dist/core/sandbox/rpc/framing.js.map +1 -0
  256. package/dist/core/sandbox/rpc/git-credential-helper.d.ts +47 -0
  257. package/dist/core/sandbox/rpc/git-credential-helper.d.ts.map +1 -0
  258. package/dist/core/sandbox/rpc/git-credential-helper.js +222 -0
  259. package/dist/core/sandbox/rpc/git-credential-helper.js.map +1 -0
  260. package/dist/core/sandbox/rpc/git-credential-proxy.d.ts +66 -0
  261. package/dist/core/sandbox/rpc/git-credential-proxy.d.ts.map +1 -0
  262. package/dist/core/sandbox/rpc/git-credential-proxy.js +209 -0
  263. package/dist/core/sandbox/rpc/git-credential-proxy.js.map +1 -0
  264. package/dist/core/sandbox/supervisor-temp.d.ts +18 -0
  265. package/dist/core/sandbox/supervisor-temp.d.ts.map +1 -0
  266. package/dist/core/sandbox/supervisor-temp.js +21 -0
  267. package/dist/core/sandbox/supervisor-temp.js.map +1 -0
  268. package/dist/core/sandbox/supervisor.d.ts +12 -1
  269. package/dist/core/sandbox/supervisor.d.ts.map +1 -1
  270. package/dist/core/sandbox/supervisor.js +15 -1
  271. package/dist/core/sandbox/supervisor.js.map +1 -1
  272. package/dist/core/sandbox/terminal-handoff.d.ts +68 -0
  273. package/dist/core/sandbox/terminal-handoff.d.ts.map +1 -0
  274. package/dist/core/sandbox/terminal-handoff.js +221 -0
  275. package/dist/core/sandbox/terminal-handoff.js.map +1 -0
  276. package/dist/core/sandbox/terminal-size.d.ts +13 -0
  277. package/dist/core/sandbox/terminal-size.d.ts.map +1 -1
  278. package/dist/core/sandbox/terminal-size.js +23 -2
  279. package/dist/core/sandbox/terminal-size.js.map +1 -1
  280. package/dist/core/sdk.d.ts +22 -0
  281. package/dist/core/sdk.d.ts.map +1 -1
  282. package/dist/core/sdk.js +53 -1
  283. package/dist/core/sdk.js.map +1 -1
  284. package/dist/core/session-manager.d.ts +13 -1
  285. package/dist/core/session-manager.d.ts.map +1 -1
  286. package/dist/core/session-manager.js +32 -5
  287. package/dist/core/session-manager.js.map +1 -1
  288. package/dist/core/settings-manager.d.ts +163 -1
  289. package/dist/core/settings-manager.d.ts.map +1 -1
  290. package/dist/core/settings-manager.js +107 -0
  291. package/dist/core/settings-manager.js.map +1 -1
  292. package/dist/core/slash-commands.d.ts.map +1 -1
  293. package/dist/core/slash-commands.js +2 -0
  294. package/dist/core/slash-commands.js.map +1 -1
  295. package/dist/core/tools/background-shell.d.ts +39 -0
  296. package/dist/core/tools/background-shell.d.ts.map +1 -0
  297. package/dist/core/tools/background-shell.js +81 -0
  298. package/dist/core/tools/background-shell.js.map +1 -0
  299. package/dist/core/tools/bash-command-segments.d.ts.map +1 -1
  300. package/dist/core/tools/bash-command-segments.js +2 -0
  301. package/dist/core/tools/bash-command-segments.js.map +1 -1
  302. package/dist/core/tools/bash.d.ts +30 -15
  303. package/dist/core/tools/bash.d.ts.map +1 -1
  304. package/dist/core/tools/bash.js +228 -12
  305. package/dist/core/tools/bash.js.map +1 -1
  306. package/dist/core/tools/contract-snapshot.d.ts +58 -0
  307. package/dist/core/tools/contract-snapshot.d.ts.map +1 -0
  308. package/dist/core/tools/contract-snapshot.js +51 -0
  309. package/dist/core/tools/contract-snapshot.js.map +1 -0
  310. package/dist/core/tools/contract.d.ts +53 -5
  311. package/dist/core/tools/contract.d.ts.map +1 -1
  312. package/dist/core/tools/contract.js +22 -2
  313. package/dist/core/tools/contract.js.map +1 -1
  314. package/dist/core/tools/delegate.d.ts +6 -4
  315. package/dist/core/tools/delegate.d.ts.map +1 -1
  316. package/dist/core/tools/delegate.js +21 -11
  317. package/dist/core/tools/delegate.js.map +1 -1
  318. package/dist/core/tools/edit-diff.d.ts +48 -0
  319. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  320. package/dist/core/tools/edit-diff.js +215 -3
  321. package/dist/core/tools/edit-diff.js.map +1 -1
  322. package/dist/core/tools/edit.d.ts +8 -0
  323. package/dist/core/tools/edit.d.ts.map +1 -1
  324. package/dist/core/tools/edit.js +53 -7
  325. package/dist/core/tools/edit.js.map +1 -1
  326. package/dist/core/tools/find.d.ts.map +1 -1
  327. package/dist/core/tools/find.js +5 -2
  328. package/dist/core/tools/find.js.map +1 -1
  329. package/dist/core/tools/grep.d.ts.map +1 -1
  330. package/dist/core/tools/grep.js +5 -2
  331. package/dist/core/tools/grep.js.map +1 -1
  332. package/dist/core/tools/index.d.ts +10 -1
  333. package/dist/core/tools/index.d.ts.map +1 -1
  334. package/dist/core/tools/index.js +3 -0
  335. package/dist/core/tools/index.js.map +1 -1
  336. package/dist/core/tools/ls.d.ts.map +1 -1
  337. package/dist/core/tools/ls.js +5 -2
  338. package/dist/core/tools/ls.js.map +1 -1
  339. package/dist/core/tools/lsp.d.ts +19 -1
  340. package/dist/core/tools/lsp.d.ts.map +1 -1
  341. package/dist/core/tools/lsp.js +163 -10
  342. package/dist/core/tools/lsp.js.map +1 -1
  343. package/dist/core/tools/path-permission.d.ts +3 -0
  344. package/dist/core/tools/path-permission.d.ts.map +1 -1
  345. package/dist/core/tools/path-permission.js +16 -4
  346. package/dist/core/tools/path-permission.js.map +1 -1
  347. package/dist/core/tools/path-utils.d.ts +27 -2
  348. package/dist/core/tools/path-utils.d.ts.map +1 -1
  349. package/dist/core/tools/path-utils.js +221 -4
  350. package/dist/core/tools/path-utils.js.map +1 -1
  351. package/dist/core/tools/read.d.ts.map +1 -1
  352. package/dist/core/tools/read.js +20 -11
  353. package/dist/core/tools/read.js.map +1 -1
  354. package/dist/core/tools/test.d.ts +54 -9
  355. package/dist/core/tools/test.d.ts.map +1 -1
  356. package/dist/core/tools/test.js +239 -19
  357. package/dist/core/tools/test.js.map +1 -1
  358. package/dist/core/tools/write.d.ts +7 -0
  359. package/dist/core/tools/write.d.ts.map +1 -1
  360. package/dist/core/tools/write.js +64 -9
  361. package/dist/core/tools/write.js.map +1 -1
  362. package/dist/core/verification-lifecycle.d.ts +77 -0
  363. package/dist/core/verification-lifecycle.d.ts.map +1 -0
  364. package/dist/core/verification-lifecycle.js +146 -0
  365. package/dist/core/verification-lifecycle.js.map +1 -0
  366. package/dist/core/workspace/artifacts.d.ts +45 -0
  367. package/dist/core/workspace/artifacts.d.ts.map +1 -0
  368. package/dist/core/workspace/artifacts.js +165 -0
  369. package/dist/core/workspace/artifacts.js.map +1 -0
  370. package/dist/core/workspace/comparison.d.ts +27 -0
  371. package/dist/core/workspace/comparison.d.ts.map +1 -0
  372. package/dist/core/workspace/comparison.js +94 -0
  373. package/dist/core/workspace/comparison.js.map +1 -0
  374. package/dist/core/workspace/git-observer.d.ts +48 -0
  375. package/dist/core/workspace/git-observer.d.ts.map +1 -0
  376. package/dist/core/workspace/git-observer.js +346 -0
  377. package/dist/core/workspace/git-observer.js.map +1 -0
  378. package/dist/core/workspace/projection.d.ts +3 -0
  379. package/dist/core/workspace/projection.d.ts.map +1 -0
  380. package/dist/core/workspace/projection.js +56 -0
  381. package/dist/core/workspace/projection.js.map +1 -0
  382. package/dist/core/workspace/state.d.ts +133 -0
  383. package/dist/core/workspace/state.d.ts.map +1 -0
  384. package/dist/core/workspace/state.js +96 -0
  385. package/dist/core/workspace/state.js.map +1 -0
  386. package/dist/extensions/llama/client.d.ts +6 -0
  387. package/dist/extensions/llama/client.d.ts.map +1 -1
  388. package/dist/extensions/llama/client.js +7 -0
  389. package/dist/extensions/llama/client.js.map +1 -1
  390. package/dist/extensions/llama/provider.d.ts +3 -1
  391. package/dist/extensions/llama/provider.d.ts.map +1 -1
  392. package/dist/extensions/llama/provider.js +27 -6
  393. package/dist/extensions/llama/provider.js.map +1 -1
  394. package/dist/index.d.ts +4 -1
  395. package/dist/index.d.ts.map +1 -1
  396. package/dist/index.js +3 -0
  397. package/dist/index.js.map +1 -1
  398. package/dist/main.d.ts +3 -1
  399. package/dist/main.d.ts.map +1 -1
  400. package/dist/main.js +41 -9
  401. package/dist/main.js.map +1 -1
  402. package/dist/modes/acp/server.d.ts +55 -0
  403. package/dist/modes/acp/server.d.ts.map +1 -0
  404. package/dist/modes/acp/server.js +244 -0
  405. package/dist/modes/acp/server.js.map +1 -0
  406. package/dist/modes/acp/translate.d.ts +37 -0
  407. package/dist/modes/acp/translate.d.ts.map +1 -0
  408. package/dist/modes/acp/translate.js +50 -0
  409. package/dist/modes/acp/translate.js.map +1 -0
  410. package/dist/modes/index.d.ts +1 -0
  411. package/dist/modes/index.d.ts.map +1 -1
  412. package/dist/modes/index.js +1 -0
  413. package/dist/modes/index.js.map +1 -1
  414. package/dist/modes/interactive/components/assistant-message.d.ts +29 -0
  415. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  416. package/dist/modes/interactive/components/assistant-message.js +182 -23
  417. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  418. package/dist/modes/interactive/components/bash-execution.d.ts +7 -0
  419. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  420. package/dist/modes/interactive/components/bash-execution.js +20 -0
  421. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  422. package/dist/modes/interactive/components/custom-editor.d.ts +9 -4
  423. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  424. package/dist/modes/interactive/components/custom-editor.js +20 -9
  425. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  426. package/dist/modes/interactive/components/extension-selector.d.ts +7 -1
  427. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  428. package/dist/modes/interactive/components/extension-selector.js +7 -3
  429. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  430. package/dist/modes/interactive/components/footer.d.ts +19 -0
  431. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  432. package/dist/modes/interactive/components/footer.js +70 -10
  433. package/dist/modes/interactive/components/footer.js.map +1 -1
  434. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  435. package/dist/modes/interactive/components/model-selector.js +6 -6
  436. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  437. package/dist/modes/interactive/components/permission-preview.d.ts +15 -0
  438. package/dist/modes/interactive/components/permission-preview.d.ts.map +1 -0
  439. package/dist/modes/interactive/components/permission-preview.js +33 -0
  440. package/dist/modes/interactive/components/permission-preview.js.map +1 -0
  441. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  442. package/dist/modes/interactive/components/session-selector.js +2 -2
  443. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  444. package/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  445. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  446. package/dist/modes/interactive/components/settings-selector.js +10 -0
  447. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  448. package/dist/modes/interactive/components/tool-execution.d.ts +23 -1
  449. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  450. package/dist/modes/interactive/components/tool-execution.js +64 -10
  451. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  452. package/dist/modes/interactive/interactive-mode.d.ts +34 -0
  453. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  454. package/dist/modes/interactive/interactive-mode.js +231 -26
  455. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  456. package/dist/modes/interactive/theme/theme.d.ts +12 -0
  457. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  458. package/dist/modes/interactive/theme/theme.js +15 -5
  459. package/dist/modes/interactive/theme/theme.js.map +1 -1
  460. package/dist/modes/print-mode.d.ts.map +1 -1
  461. package/dist/modes/print-mode.js +27 -12
  462. package/dist/modes/print-mode.js.map +1 -1
  463. package/dist/modes/rpc/rpc-client.d.ts +7 -0
  464. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  465. package/dist/modes/rpc/rpc-client.js +7 -0
  466. package/dist/modes/rpc/rpc-client.js.map +1 -1
  467. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  468. package/dist/modes/rpc/rpc-mode.js +3 -0
  469. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  470. package/dist/modes/rpc/rpc-types.d.ts +12 -0
  471. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  472. package/dist/modes/rpc/rpc-types.js.map +1 -1
  473. package/dist/package-manager-cli.d.ts.map +1 -1
  474. package/dist/package-manager-cli.js +0 -6
  475. package/dist/package-manager-cli.js.map +1 -1
  476. package/dist/utils/shell.d.ts.map +1 -1
  477. package/dist/utils/shell.js +6 -4
  478. package/dist/utils/shell.js.map +1 -1
  479. package/dist/utils/version-check.d.ts.map +1 -1
  480. package/dist/utils/version-check.js +6 -4
  481. package/dist/utils/version-check.js.map +1 -1
  482. package/docs/compaction.md +4 -0
  483. package/docs/custom-provider.md +7 -7
  484. package/docs/environment-variables.md +1 -1
  485. package/docs/extensions.md +18 -0
  486. package/docs/keybindings.md +1 -1
  487. package/docs/quickstart.md +1 -1
  488. package/docs/rpc.md +23 -0
  489. package/docs/sdk.md +25 -0
  490. package/docs/settings.md +12 -4
  491. package/docs/terminal-setup.md +12 -0
  492. package/docs/usage.md +4 -3
  493. package/examples/extensions/built-in-tool-renderer.ts +8 -4
  494. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  495. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  496. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  497. package/examples/extensions/git-checkpoint.ts +24 -36
  498. package/examples/extensions/gondolin/package-lock.json +2 -2
  499. package/examples/extensions/gondolin/package.json +1 -1
  500. package/examples/extensions/minimal-mode.ts +2 -2
  501. package/examples/extensions/permission-gate.ts +1 -1
  502. package/examples/extensions/plan-mode/index.ts +1 -1
  503. package/examples/extensions/rpc-demo.ts +1 -1
  504. package/examples/extensions/sandbox/package-lock.json +2 -2
  505. package/examples/extensions/sandbox/package.json +1 -1
  506. package/examples/extensions/with-deps/package-lock.json +2 -2
  507. package/examples/extensions/with-deps/package.json +1 -1
  508. package/npm-shrinkwrap.json +194 -46
  509. package/package.json +14 -12
  510. package/dist/server/create-harness.d.ts +0 -26
  511. package/dist/server/create-harness.d.ts.map +0 -1
  512. package/dist/server/create-harness.js +0 -107
  513. 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, 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";
@@ -19,11 +19,13 @@ import { getApexEnvironment } from "../../core/environment.js";
19
19
  import { FooterDataProvider } from "../../core/footer-data-provider.js";
20
20
  import { configureHttpDispatcher, formatHttpIdleTimeoutMs } from "../../core/http-dispatcher.js";
21
21
  import { KeybindingsManager } from "../../core/keybindings.js";
22
+ import { authorizeConfiguredServer } from "../../core/mcp/oauth/authorize.js";
22
23
  import { createCompactionSummaryMessage } from "../../core/messages.js";
23
24
  import { defaultModelPerProvider, findExactModelReferenceMatch, resolveModelScopeFromModels, } from "../../core/model-resolver.js";
24
25
  import { CredentialSynchronizationError } from "../../core/model-runtime.js";
25
26
  import { aggregateUsagePerformance } from "../../core/observability/aggregate.js";
26
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";
27
29
  import { formatMissingSessionCwdPrompt, MissingSessionCwdError } from "../../core/session-cwd.js";
28
30
  import { SessionManager, sessionEntryToContextMessages } from "../../core/session-manager.js";
29
31
  import { formatShareUnavailableMessage, publishSessionShare } from "../../core/session-share.js";
@@ -63,6 +65,7 @@ import { LoginDialogComponent } from "./components/login-dialog.js";
63
65
  import { createMermaidMarkdownTransformer } from "./components/mermaid.js";
64
66
  import { ModelSelectorComponent } from "./components/model-selector.js";
65
67
  import { formatAuthSelectorProviderType, OAuthSelectorComponent, } from "./components/oauth-selector.js";
68
+ import { renderPermissionPreview } from "./components/permission-preview.js";
66
69
  import { ScopedModelsSelectorComponent } from "./components/scoped-models-selector.js";
67
70
  import { SessionSelectorComponent } from "./components/session-selector.js";
68
71
  import { PERMISSION_MODE_OVERRIDE_HINTS, SettingsSelectorComponent } from "./components/settings-selector.js";
@@ -191,6 +194,7 @@ export function createInteractiveTui(options) {
191
194
  searchCurrentMatchStyle: (text) => theme.bold(theme.inverse(styleSearchMatch(text))),
192
195
  openUrl: openBrowser,
193
196
  onRightClickPaste: options.onRightClickPaste,
197
+ copyOnSelect: options.fullscreenCopyOnSelect,
194
198
  copySelection: async (text) => {
195
199
  try {
196
200
  await copyToClipboard(text);
@@ -235,6 +239,23 @@ export function createInteractiveTuiReference(getTui) {
235
239
  getPrototypeOf: () => Reflect.getPrototypeOf(getTui()),
236
240
  });
237
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
+ }
238
259
  export class InteractiveMode {
239
260
  runtimeHost;
240
261
  /** Settled once the most recent /settings permission-mode write has hit disk. */
@@ -316,6 +337,11 @@ export class InteractiveMode {
316
337
  firstUseHints;
317
338
  // Track current bash execution component
318
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;
319
345
  // Track pending bash components (shown in pending area, moved to chat on submit)
320
346
  pendingBashComponents = [];
321
347
  // Auto-compaction state
@@ -373,6 +399,7 @@ export class InteractiveMode {
373
399
  }
374
400
  constructor(runtimeHost, options = {}) {
375
401
  this.runtimeHost = runtimeHost;
402
+ setCapabilityOverrides(this.settingsManager.getTerminalCapabilityOverrides());
376
403
  const tuiMode = options.tuiMode ?? this.settingsManager.getTuiMode();
377
404
  this.options = { ...options, tuiMode };
378
405
  this.autoTrustOnReloadCwd = options.autoTrustOnReloadCwd;
@@ -389,6 +416,7 @@ export class InteractiveMode {
389
416
  showHardwareCursor: this.settingsManager.getShowHardwareCursor(),
390
417
  logDirectory: getAgentDir(),
391
418
  onRightClickPaste: this.onRightClickPaste,
419
+ fullscreenCopyOnSelect: this.settingsManager.getFullscreenCopyOnSelect(),
392
420
  });
393
421
  this.ui = createInteractiveTuiReference(() => this.renderer);
394
422
  this.ui.setClearOnShrink(this.settingsManager.getClearOnShrink());
@@ -412,6 +440,10 @@ export class InteractiveMode {
412
440
  autocompleteMaxVisible,
413
441
  promptPrefix: "› ",
414
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),
415
447
  placeholder: "Ask anything",
416
448
  placeholderColor: (text) => theme.fg("dim", text),
417
449
  commandColor: (text) => theme.fg("accent", text),
@@ -478,8 +510,21 @@ export class InteractiveMode {
478
510
  path: command.sourceInfo.path,
479
511
  }));
480
512
  }
481
- createBaseAutocompleteProvider() {
482
- // 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() {
483
528
  const slashCommands = BUILTIN_SLASH_COMMANDS.map((command) => ({
484
529
  name: command.name,
485
530
  description: command.description,
@@ -556,7 +601,10 @@ export class InteractiveMode {
556
601
  });
557
602
  }
558
603
  }
559
- 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);
560
608
  }
561
609
  setupAutocompleteProvider() {
562
610
  let provider = this.createBaseAutocompleteProvider();
@@ -644,6 +692,7 @@ export class InteractiveMode {
644
692
  logDirectory: getAgentDir(),
645
693
  terminal,
646
694
  onRightClickPaste: this.onRightClickPaste,
695
+ fullscreenCopyOnSelect: this.settingsManager.getFullscreenCopyOnSelect(),
647
696
  });
648
697
  nextUi.setClearOnShrink(clearOnShrink);
649
698
  nextUi.onDebug = onDebug;
@@ -1608,8 +1657,12 @@ export class InteractiveMode {
1608
1657
  this.transcriptScrollView?.setScrollbar(this.settingsManager.getFullscreenScrollbar());
1609
1658
  }
1610
1659
  applyRuntimeSettings() {
1660
+ setCapabilityOverrides(this.settingsManager.getTerminalCapabilityOverrides());
1611
1661
  configureHttpDispatcher(this.settingsManager.getHttpIdleTimeoutMs());
1612
1662
  this.applyFullscreenScrollbarSetting();
1663
+ if (this.renderer instanceof TuiAltScreen) {
1664
+ this.renderer.setCopyOnSelect(this.settingsManager.getFullscreenCopyOnSelect());
1665
+ }
1613
1666
  this.footer.setSession(this.session);
1614
1667
  this.footer.setAutoCompactEnabled(this.session.autoCompactionEnabled);
1615
1668
  void this.refreshFooterPermissionMode();
@@ -1665,6 +1718,15 @@ export class InteractiveMode {
1665
1718
  this.compactionQueuedMessages = [];
1666
1719
  this.streamingComponent = undefined;
1667
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;
1668
1730
  this.clearPendingTools();
1669
1731
  this.renderInitialMessages();
1670
1732
  }
@@ -1751,6 +1813,11 @@ export class InteractiveMode {
1751
1813
  this.activeStatusIndicator?.dispose();
1752
1814
  this.activeStatusIndicator = indicator;
1753
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);
1754
1821
  this.statusContainer.addChild(indicator);
1755
1822
  }
1756
1823
  clearStatusIndicator(kind) {
@@ -1758,13 +1825,23 @@ export class InteractiveMode {
1758
1825
  return;
1759
1826
  }
1760
1827
  const hadActiveStatusIndicator = this.activeStatusIndicator !== undefined;
1828
+ const wasInTray = this.activeStatusIndicator !== undefined &&
1829
+ trayOwnsActivity(this.activeStatusIndicator.kind, this.customFooter !== undefined);
1761
1830
  this.activeStatusIndicator?.dispose();
1762
1831
  this.activeStatusIndicator = undefined;
1832
+ this.footer?.setActivity(undefined);
1763
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;
1764
1838
  if (hadActiveStatusIndicator && this.options.tuiMode === "regular" && this.ui.getClearOnShrink()) {
1765
1839
  this.statusContainer.addChild(this.idleStatus);
1766
1840
  }
1767
1841
  }
1842
+ showWorkingStatusIndicator() {
1843
+ this.showStatusIndicator(new WorkingStatusIndicator(this.ui, this.workingMessage ?? this.defaultWorkingMessage, this.workingIndicatorOptions));
1844
+ }
1768
1845
  setWorkingVisible(visible) {
1769
1846
  this.workingVisible = visible;
1770
1847
  if (!visible) {
@@ -1773,7 +1850,7 @@ export class InteractiveMode {
1773
1850
  return;
1774
1851
  }
1775
1852
  if (this.session.isStreaming && this.activeStatusIndicator?.kind !== "working") {
1776
- this.showStatusIndicator(new WorkingStatusIndicator(this.ui, this.workingMessage ?? this.defaultWorkingMessage, this.workingIndicatorOptions));
1853
+ this.showWorkingStatusIndicator();
1777
1854
  }
1778
1855
  this.ui.requestRender();
1779
1856
  }
@@ -2079,6 +2156,7 @@ export class InteractiveMode {
2079
2156
  timeout: opts?.timeout,
2080
2157
  onToggleToolsExpanded: () => this.toggleToolOutputExpansion(),
2081
2158
  enableSearch,
2159
+ preamble: opts?.preview ? renderPermissionPreview(opts.preview) : undefined,
2082
2160
  });
2083
2161
  this.disposeActiveSelector();
2084
2162
  this.editorContainer.clear();
@@ -2128,10 +2206,24 @@ export class InteractiveMode {
2128
2206
  this.showTrustSelector();
2129
2207
  break;
2130
2208
  case "Resources, extensions, and MCP adapters":
2131
- this.showStatus("Run apex-code config to manage resources, extensions, and MCP adapters.");
2209
+ this.showStatus(this.describeMcpServers());
2132
2210
  break;
2133
2211
  }
2134
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
+ }
2135
2227
  /**
2136
2228
  * Show a confirmation dialog for extensions.
2137
2229
  */
@@ -2432,7 +2524,7 @@ export class InteractiveMode {
2432
2524
  this.defaultEditor.onAction("app.tools.expand", () => this.toggleToolOutputExpansion());
2433
2525
  this.defaultEditor.onAction("app.thinking.toggle", () => this.toggleThinkingBlockVisibility());
2434
2526
  this.defaultEditor.onAction("app.editor.external", () => void this.handleOpenExternalEditor());
2435
- 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 }));
2436
2528
  this.defaultEditor.onAction("app.message.followUp", () => this.handleFollowUp());
2437
2529
  this.defaultEditor.onAction("app.message.dequeue", () => this.handleDequeue());
2438
2530
  this.defaultEditor.onAction("app.session.new", () => this.handleClearCommand());
@@ -2582,6 +2674,11 @@ export class InteractiveMode {
2582
2674
  this.editor.setText("");
2583
2675
  return;
2584
2676
  }
2677
+ if (text === "/help") {
2678
+ this.handleHelpCommand();
2679
+ this.editor.setText("");
2680
+ return;
2681
+ }
2585
2682
  if (text === "/fork") {
2586
2683
  this.showUserMessageSelector();
2587
2684
  this.editor.setText("");
@@ -2613,6 +2710,12 @@ export class InteractiveMode {
2613
2710
  this.editor.setText("");
2614
2711
  return;
2615
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
+ }
2616
2719
  if (text === "/new") {
2617
2720
  this.editor.setText("");
2618
2721
  await this.handleClearCommand();
@@ -2727,8 +2830,15 @@ export class InteractiveMode {
2727
2830
  this.defaultEditor.onEscape = this.retryEscapeHandler;
2728
2831
  this.retryEscapeHandler = undefined;
2729
2832
  }
2833
+ break;
2834
+ case "turn_start":
2835
+ if (this.settingsManager.getShowTerminalProgress()) {
2836
+ this.ui.terminal.setProgress(true);
2837
+ }
2730
2838
  if (this.workingVisible) {
2731
- this.showStatusIndicator(new WorkingStatusIndicator(this.ui, this.workingMessage ?? this.defaultWorkingMessage, this.workingIndicatorOptions));
2839
+ if (this.activeStatusIndicator?.kind !== "working") {
2840
+ this.showWorkingStatusIndicator();
2841
+ }
2732
2842
  }
2733
2843
  else {
2734
2844
  this.clearStatusIndicator();
@@ -3462,6 +3572,34 @@ export class InteractiveMode {
3462
3572
  const uncaughtExceptionHandler = (error) => this.uncaughtCrash(error);
3463
3573
  process.prependListener("uncaughtException", uncaughtExceptionHandler);
3464
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
+ }
3465
3603
  }
3466
3604
  unregisterSignalHandlers() {
3467
3605
  for (const cleanup of this.signalCleanupHandlers) {
@@ -3543,7 +3681,9 @@ export class InteractiveMode {
3543
3681
  }
3544
3682
  }
3545
3683
  updateEditorBorderColor() {
3546
- 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");
3547
3687
  if (this.isBashMode) {
3548
3688
  this.editor.borderColor = theme.getBashModeBorderColor();
3549
3689
  }
@@ -3603,19 +3743,20 @@ export class InteractiveMode {
3603
3743
  }
3604
3744
  this.showStatus(`Tool output: ${expanded ? "expanded" : "collapsed"}`);
3605
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
+ }
3606
3755
  toggleThinkingBlockVisibility() {
3607
3756
  this.offerFirstUseHint("thinking");
3608
3757
  this.hideThinkingBlock = !this.hideThinkingBlock;
3609
3758
  this.settingsManager.setHideThinkingBlock(this.hideThinkingBlock);
3610
- // Rebuild chat from session messages
3611
- this.chatContainer.clear();
3612
- this.rebuildChatFromMessages();
3613
- // If streaming, re-add the streaming component with updated visibility and re-render
3614
- if (this.streamingComponent && this.streamingMessage) {
3615
- this.streamingComponent.setHideThinkingBlock(this.hideThinkingBlock);
3616
- this.streamingComponent.updateContent(this.streamingMessage);
3617
- this.chatContainer.addChild(this.streamingComponent);
3618
- }
3759
+ this.updateThinkingBlockVisibility();
3619
3760
  this.showStatus(`Thinking blocks: ${this.hideThinkingBlock ? "hidden" : "visible"}`);
3620
3761
  }
3621
3762
  async handleOpenExternalEditor() {
@@ -3979,6 +4120,7 @@ export class InteractiveMode {
3979
4120
  tuiMode: this.ui.mode,
3980
4121
  fullscreenExitOutput: this.settingsManager.getFullscreenExitOutput(),
3981
4122
  fullscreenScrollbar: this.settingsManager.getFullscreenScrollbar(),
4123
+ fullscreenCopyOnSelect: this.settingsManager.getFullscreenCopyOnSelect(),
3982
4124
  warnings: this.settingsManager.getWarnings(),
3983
4125
  }, {
3984
4126
  onAutoCompactChange: (enabled) => {
@@ -4055,13 +4197,7 @@ export class InteractiveMode {
4055
4197
  onHideThinkingBlockChange: (hidden) => {
4056
4198
  this.hideThinkingBlock = hidden;
4057
4199
  this.settingsManager.setHideThinkingBlock(hidden);
4058
- for (const child of this.chatContainer.children) {
4059
- if (child instanceof AssistantMessageComponent) {
4060
- child.setHideThinkingBlock(hidden);
4061
- }
4062
- }
4063
- this.chatContainer.clear();
4064
- this.rebuildChatFromMessages();
4200
+ this.updateThinkingBlockVisibility();
4065
4201
  },
4066
4202
  onMermaidRenderingModeChange: (mode) => {
4067
4203
  this.settingsManager.setMermaidRenderingMode(mode);
@@ -4158,6 +4294,11 @@ export class InteractiveMode {
4158
4294
  this.settingsManager.setFullscreenScrollbar(mode);
4159
4295
  this.applyFullscreenScrollbarSetting();
4160
4296
  },
4297
+ onFullscreenCopyOnSelectChange: (enabled) => {
4298
+ this.settingsManager.setFullscreenCopyOnSelect(enabled);
4299
+ if (this.renderer instanceof TuiAltScreen)
4300
+ this.renderer.setCopyOnSelect(enabled);
4301
+ },
4161
4302
  onWarningsChange: (warnings) => {
4162
4303
  this.settingsManager.setWarnings(warnings);
4163
4304
  },
@@ -4347,6 +4488,7 @@ export class InteractiveMode {
4347
4488
  const selectModel = async (model, persist) => {
4348
4489
  try {
4349
4490
  await this.session.setModel(model, { persist });
4491
+ this.updateAvailableProviderCount();
4350
4492
  this.footer.invalidate();
4351
4493
  this.updateEditorBorderColor();
4352
4494
  done();
@@ -4757,6 +4899,27 @@ export class InteractiveMode {
4757
4899
  return this.getLoginProviderOptions().filter((provider) => provider.id.toLowerCase() === normalizedProviderRef ||
4758
4900
  provider.name.toLowerCase() === normalizedProviderRef);
4759
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
+ }
4760
4923
  async handleLoginCommand(providerRef) {
4761
4924
  if (!providerRef) {
4762
4925
  this.showLoginAuthTypeSelector();
@@ -5195,8 +5358,8 @@ export class InteractiveMode {
5195
5358
  activeHeader.setExpanded(this.toolOutputExpanded);
5196
5359
  }
5197
5360
  setRegisteredThemes(this.session.resourceLoader.getThemes().themes);
5198
- await this.themeController.applyFromSettings();
5199
5361
  this.applyRuntimeSettings();
5362
+ await this.themeController.applyFromSettings();
5200
5363
  this.setupAutocompleteProvider();
5201
5364
  const runner = this.session.extensionRunner;
5202
5365
  this.setupExtensionShortcuts(runner);
@@ -5380,6 +5543,13 @@ export class InteractiveMode {
5380
5543
  }
5381
5544
  }
5382
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
+ }
5383
5553
  const text = this.session.getLastAssistantText();
5384
5554
  if (!text) {
5385
5555
  this.showError("No agent messages to copy yet.");
@@ -5638,6 +5808,28 @@ export class InteractiveMode {
5638
5808
  this.chatContainer.addChild(new DynamicBorder());
5639
5809
  this.ui.requestRender();
5640
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
+ }
5641
5833
  async handleClearCommand() {
5642
5834
  this.clearStatusIndicator();
5643
5835
  try {
@@ -5701,6 +5893,19 @@ export class InteractiveMode {
5701
5893
  }
5702
5894
  }
5703
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) {
5704
5909
  const extensionRunner = this.session.extensionRunner;
5705
5910
  // Emit user_bash event to let extensions intercept
5706
5911
  const eventResult = await extensionRunner.emitUserBash({