one-code-extension 0.4.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (439) hide show
  1. package/README.md +16 -5
  2. package/agents/general-purpose.md +2 -2
  3. package/docs/guide/README.md +2 -1
  4. package/docs/guide/bring-your-claude-code-setup.md +60 -9
  5. package/docs/guide/configuration.md +48 -14
  6. package/docs/guide/differences-from-claude-code.md +40 -28
  7. package/docs/guide/doctor.md +20 -13
  8. package/docs/guide/hooks.md +18 -3
  9. package/docs/guide/installation.md +26 -4
  10. package/docs/guide/permissions-modes-and-auto-mode.md +225 -49
  11. package/docs/guide/providers-and-models.md +137 -54
  12. package/docs/guide/reference.md +27 -15
  13. package/docs/guide/sessions-and-context.md +69 -16
  14. package/docs/guide/skills-plugins-and-mcp.md +57 -20
  15. package/docs/guide/subagents-and-workflows.md +95 -29
  16. package/docs/guide/tasks-and-background-work.md +101 -26
  17. package/docs/guide/terminal-interface.md +24 -12
  18. package/docs/guide/tools.md +46 -5
  19. package/docs/guide/troubleshooting.md +13 -9
  20. package/docs/guide/windows.md +58 -31
  21. package/extensions/artifacts/gallery.ts +227 -0
  22. package/extensions/artifacts/index.ts +288 -0
  23. package/extensions/artifacts/store.ts +570 -0
  24. package/extensions/artifacts/viewer.ts +199 -0
  25. package/extensions/ask-user/description.ts +67 -0
  26. package/extensions/ask-user/dialogs.ts +80 -0
  27. package/extensions/ask-user/index.ts +37 -33
  28. package/extensions/ask-user/questions.ts +32 -7
  29. package/extensions/ask-user/widget.ts +45 -25
  30. package/extensions/auto-mode/actions.ts +6 -0
  31. package/extensions/auto-mode/cache.ts +88 -0
  32. package/extensions/auto-mode/classifier-prompt.ts +5 -4
  33. package/extensions/auto-mode/classifier.ts +290 -65
  34. package/extensions/auto-mode/config.ts +72 -20
  35. package/extensions/auto-mode/decision-log.ts +2 -0
  36. package/extensions/auto-mode/defaults.ts +1 -1
  37. package/extensions/auto-mode/denials.ts +124 -0
  38. package/extensions/auto-mode/git-checkout-programs.ts +187 -0
  39. package/extensions/auto-mode/git-status-meta.ts +159 -0
  40. package/extensions/auto-mode/history.ts +189 -0
  41. package/extensions/auto-mode/instructions.ts +58 -52
  42. package/extensions/auto-mode/model-select.ts +159 -134
  43. package/extensions/auto-mode/paths.ts +57 -5
  44. package/extensions/auto-mode/pause.ts +57 -2
  45. package/extensions/auto-mode/prompt.ts +37 -21
  46. package/extensions/auto-mode/read-only-options.ts +724 -0
  47. package/extensions/auto-mode/resolved-paths-meta.ts +133 -0
  48. package/extensions/auto-mode/rules.ts +18 -1
  49. package/extensions/auto-mode/safety-floor.ts +361 -18
  50. package/extensions/auto-mode/setup-run.ts +20 -14
  51. package/extensions/auto-mode/shell-analysis.ts +764 -490
  52. package/extensions/auto-mode/shell-parse.ts +885 -0
  53. package/extensions/auto-mode/system-note.ts +33 -0
  54. package/extensions/auto-mode/transcript.ts +80 -51
  55. package/extensions/background/cron.ts +642 -0
  56. package/extensions/background/index.ts +614 -248
  57. package/extensions/background/loop-fire.ts +173 -0
  58. package/extensions/background/loop-preamble.ts +59 -0
  59. package/extensions/background/loop-skill.ts +163 -0
  60. package/extensions/background/monitor-batch.ts +53 -0
  61. package/extensions/background/noop-fold.ts +128 -0
  62. package/extensions/background/switch-guard.ts +56 -0
  63. package/extensions/background/wakeup.ts +178 -55
  64. package/extensions/bash/background.ts +53 -17
  65. package/extensions/bash/child.ts +7 -0
  66. package/extensions/bash/description.ts +188 -0
  67. package/extensions/bash/guards.ts +15 -67
  68. package/extensions/bash/index.ts +66 -35
  69. package/extensions/branding/compaction-keep.ts +63 -0
  70. package/extensions/branding/declined.ts +22 -0
  71. package/extensions/branding/index.ts +133 -9
  72. package/extensions/branding/prompt-editor.ts +53 -6
  73. package/extensions/branding/queued-edit.ts +31 -0
  74. package/extensions/branding/replaced-builtins.ts +68 -0
  75. package/extensions/branding/startup.ts +33 -71
  76. package/extensions/btw/index.ts +250 -78
  77. package/extensions/btw/panel.ts +228 -100
  78. package/extensions/btw/prompt.ts +41 -4
  79. package/extensions/cache-marks/index.ts +42 -0
  80. package/extensions/claude-compat/index.ts +7 -11
  81. package/extensions/claude-context/index.ts +436 -63
  82. package/extensions/compaction/cut.ts +157 -0
  83. package/extensions/compaction/index.ts +219 -75
  84. package/extensions/compaction/kept-thinking.ts +62 -0
  85. package/extensions/compaction/prompt.ts +15 -12
  86. package/extensions/context-budget/budget.ts +16 -2
  87. package/extensions/context-budget/index.ts +35 -15
  88. package/extensions/context-management/index.ts +36 -28
  89. package/extensions/doctor/build.ts +59 -8
  90. package/extensions/doctor/builtins.ts +84 -0
  91. package/extensions/doctor/cli.ts +7 -1
  92. package/extensions/doctor/compat.ts +88 -23
  93. package/extensions/doctor/dependencies.ts +41 -5
  94. package/extensions/doctor/fix-prompt.ts +9 -2
  95. package/extensions/doctor/index.ts +102 -58
  96. package/extensions/doctor/models.ts +102 -63
  97. package/extensions/doctor/presets.ts +42 -27
  98. package/extensions/doctor/report.ts +19 -2
  99. package/extensions/doctor/viewer.ts +49 -27
  100. package/extensions/effort/index.ts +141 -25
  101. package/extensions/effort/settings.ts +21 -0
  102. package/extensions/effort/slider.ts +24 -20
  103. package/extensions/exit/index.ts +32 -1
  104. package/extensions/file-tracker/index.ts +420 -42
  105. package/extensions/file-tracker/replay.ts +137 -24
  106. package/extensions/file-tracker/restore.ts +66 -0
  107. package/extensions/file-tracker/results.ts +66 -0
  108. package/extensions/file-tracker/shell-reads.ts +211 -0
  109. package/extensions/file-tracker/tracker.ts +45 -15
  110. package/extensions/footer/footer-line.ts +45 -24
  111. package/extensions/footer/index.ts +47 -2
  112. package/extensions/footer/pr.ts +34 -5
  113. package/extensions/hooks/compaction.ts +7 -0
  114. package/extensions/hooks/executor.ts +32 -30
  115. package/extensions/hooks/index.ts +209 -58
  116. package/extensions/hooks/matcher.ts +3 -0
  117. package/extensions/hooks/prompt-context.ts +59 -0
  118. package/extensions/hooks/protocol.ts +41 -3
  119. package/extensions/hooks/settings.ts +50 -19
  120. package/extensions/hooks/subagent-bridge.ts +2 -0
  121. package/extensions/hooks/trust.ts +26 -12
  122. package/extensions/idle-compact/index.ts +119 -0
  123. package/extensions/idle-compact/policy.ts +143 -0
  124. package/extensions/init/index.ts +11 -10
  125. package/extensions/init/prompt.ts +25 -32
  126. package/extensions/interrupted/index.ts +13 -1
  127. package/extensions/kept-thinking/index.ts +27 -0
  128. package/extensions/ledger/index.ts +46 -0
  129. package/extensions/ledger/wire.ts +154 -0
  130. package/extensions/lib/agent-cron.ts +146 -0
  131. package/extensions/lib/agent-loader.ts +18 -3
  132. package/extensions/lib/agent-view.ts +85 -0
  133. package/extensions/lib/anthropic-auth.ts +98 -0
  134. package/extensions/lib/anthropic-payload.ts +82 -1
  135. package/extensions/lib/anthropic-server-call.ts +230 -0
  136. package/extensions/lib/anthropic-server-tools.ts +485 -0
  137. package/extensions/lib/app-launch.mjs +94 -0
  138. package/extensions/lib/argument-hints.ts +190 -0
  139. package/extensions/lib/atomic-write.ts +6 -2
  140. package/extensions/lib/auto-memory.ts +75 -0
  141. package/extensions/lib/bash-parser.ts +84 -0
  142. package/extensions/lib/btw-fork.ts +93 -0
  143. package/extensions/lib/child-extensions.ts +52 -0
  144. package/extensions/lib/child-writes.ts +45 -0
  145. package/extensions/lib/claude-context.ts +515 -100
  146. package/extensions/lib/claude-external-includes.ts +68 -0
  147. package/extensions/lib/claude-id.ts +22 -0
  148. package/extensions/lib/claude-rules.ts +323 -0
  149. package/extensions/lib/claude-settings.ts +76 -4
  150. package/extensions/lib/compaction-boundary.ts +36 -0
  151. package/extensions/lib/compaction-keep.mjs +83 -0
  152. package/extensions/lib/config-mode.ts +112 -0
  153. package/extensions/lib/consent-dialogs.ts +63 -0
  154. package/extensions/lib/consent-preview.ts +5 -1
  155. package/extensions/lib/consent-stores.ts +48 -0
  156. package/extensions/lib/context-facts.ts +97 -0
  157. package/extensions/lib/covered-messages.ts +23 -0
  158. package/extensions/lib/deferred.ts +359 -25
  159. package/extensions/lib/dock-rows.ts +60 -0
  160. package/extensions/lib/empty-tool-result.ts +27 -0
  161. package/extensions/lib/environment-block.ts +76 -0
  162. package/extensions/lib/fetch-timeout.ts +24 -6
  163. package/extensions/{system-prompt → lib}/git-status.ts +51 -13
  164. package/extensions/lib/git.ts +75 -13
  165. package/extensions/lib/grammars/LICENSE-tree-sitter-bash +21 -0
  166. package/extensions/lib/grammars/README.md +2 -0
  167. package/extensions/lib/grammars/tree-sitter-bash.wasm +0 -0
  168. package/extensions/lib/guide-docs.ts +45 -0
  169. package/extensions/lib/headless-output.ts +46 -0
  170. package/extensions/lib/hook-gate.ts +7 -7
  171. package/extensions/lib/interrupt.ts +20 -4
  172. package/extensions/lib/key-input.ts +455 -0
  173. package/extensions/lib/keys.ts +14 -1
  174. package/extensions/lib/ledger/fold-memo.ts +49 -0
  175. package/extensions/lib/ledger/fold.ts +265 -0
  176. package/extensions/lib/ledger/layout.ts +72 -0
  177. package/extensions/lib/ledger/plan.ts +102 -0
  178. package/extensions/lib/ledger/records.ts +276 -0
  179. package/extensions/lib/ledger/state.ts +47 -0
  180. package/extensions/lib/ledger/validate.ts +141 -0
  181. package/extensions/lib/ledger/wire.ts +632 -0
  182. package/extensions/lib/local-command.ts +71 -19
  183. package/extensions/lib/mcp-overrides.ts +1 -1
  184. package/extensions/lib/mcp-share.ts +46 -0
  185. package/extensions/lib/memory-content.ts +146 -0
  186. package/extensions/lib/memory-index.ts +18 -0
  187. package/extensions/lib/memory.ts +134 -123
  188. package/extensions/lib/model-catalog/huggingface.json +178 -0
  189. package/extensions/lib/model-catalog/models-dev.json +18533 -0
  190. package/extensions/lib/model-catalog/openrouter.json +5050 -0
  191. package/extensions/lib/model-catalog-data.ts +513 -0
  192. package/extensions/lib/model-catalog.ts +462 -0
  193. package/extensions/lib/model-choice-warnings.ts +137 -0
  194. package/extensions/lib/model-pairings.ts +152 -0
  195. package/extensions/{auto-mode → lib}/model-picker.ts +26 -43
  196. package/extensions/lib/model-policy.ts +112 -15
  197. package/extensions/lib/model-tier.ts +283 -355
  198. package/extensions/lib/model-unusable.ts +1 -1
  199. package/extensions/lib/newer-model.ts +100 -0
  200. package/extensions/lib/notices.ts +87 -0
  201. package/extensions/lib/notifications.ts +357 -73
  202. package/extensions/lib/one-code-settings.ts +74 -8
  203. package/extensions/lib/open-browser.ts +63 -0
  204. package/extensions/lib/openrouter-generation.ts +94 -0
  205. package/extensions/lib/operation-deadline.ts +30 -0
  206. package/extensions/lib/original-command.ts +4 -4
  207. package/extensions/lib/package-version.ts +1 -1
  208. package/extensions/lib/panel-focus.ts +134 -0
  209. package/extensions/lib/paths.ts +17 -2
  210. package/extensions/lib/permission-gate.ts +72 -6
  211. package/extensions/lib/persisted-output.ts +60 -8
  212. package/extensions/lib/pi-ai-estimate.ts +19 -3
  213. package/extensions/lib/pi-version.ts +38 -2
  214. package/extensions/lib/plan-mode-channels.ts +42 -5
  215. package/extensions/lib/plugins.ts +26 -17
  216. package/extensions/lib/powershell-parse-script.ts +208 -0
  217. package/extensions/lib/powershell-parser.ts +344 -0
  218. package/extensions/lib/previous-mark.ts +101 -0
  219. package/extensions/lib/process-state.ts +48 -0
  220. package/extensions/lib/process-tree.ts +132 -8
  221. package/extensions/lib/prompt-options.ts +82 -0
  222. package/extensions/lib/queued-delivery.ts +44 -0
  223. package/extensions/lib/reminders.ts +370 -358
  224. package/extensions/lib/replaced-builtins.mjs +199 -0
  225. package/extensions/lib/replay-call.ts +70 -0
  226. package/extensions/lib/request-replay.ts +547 -0
  227. package/extensions/lib/scratchpad.ts +81 -14
  228. package/extensions/lib/send-now-channel.ts +7 -0
  229. package/extensions/lib/session-model-tier.ts +51 -0
  230. package/extensions/lib/session-work.ts +64 -0
  231. package/extensions/lib/settings-channels.ts +4 -4
  232. package/extensions/lib/shell-exit-semantics.ts +170 -0
  233. package/extensions/lib/shell-quote.ts +11 -0
  234. package/extensions/lib/shell-result.ts +70 -0
  235. package/extensions/lib/shell-spawn.ts +70 -6
  236. package/extensions/lib/shell-tool.ts +75 -25
  237. package/extensions/lib/side-call-cache.ts +124 -0
  238. package/extensions/lib/side-call-run.ts +96 -0
  239. package/extensions/lib/side-call-usage.ts +38 -0
  240. package/extensions/lib/side-call.ts +24 -1
  241. package/extensions/lib/single-flight.ts +18 -0
  242. package/extensions/lib/skill-body.ts +42 -0
  243. package/extensions/lib/skill-scan.ts +63 -24
  244. package/extensions/lib/spill-file.ts +140 -0
  245. package/extensions/lib/subagent-handback.ts +112 -0
  246. package/extensions/lib/system-role.ts +156 -0
  247. package/extensions/lib/terminal-text.ts +114 -0
  248. package/extensions/lib/text-width.ts +47 -16
  249. package/extensions/lib/timer-ops.ts +20 -0
  250. package/extensions/lib/tool-additions.ts +129 -0
  251. package/extensions/lib/tool-call-corruption.ts +134 -0
  252. package/extensions/lib/tool-path.ts +66 -0
  253. package/extensions/lib/tool-variants.ts +69 -0
  254. package/extensions/lib/tui-render.ts +255 -27
  255. package/extensions/lib/turn-budget-layout.ts +159 -0
  256. package/extensions/lib/update-check.mjs +15 -2
  257. package/extensions/lib/usage-bus.ts +1 -1
  258. package/extensions/lib/user-denial.ts +38 -0
  259. package/extensions/lib/workspace-channel.ts +16 -0
  260. package/extensions/lib/worktree-channel.ts +31 -3
  261. package/extensions/lib/worktree-isolation.ts +40 -10
  262. package/extensions/lsp/client.ts +8 -9
  263. package/extensions/lsp/index.ts +76 -12
  264. package/extensions/lsp/keep-alive.ts +1 -1
  265. package/extensions/lsp/trust.ts +119 -0
  266. package/extensions/lsp/watcher.ts +1 -1
  267. package/extensions/mcp/announce.ts +90 -43
  268. package/extensions/mcp/client.ts +161 -48
  269. package/extensions/mcp/config.ts +132 -8
  270. package/extensions/mcp/discovery.ts +19 -0
  271. package/extensions/mcp/index.ts +220 -121
  272. package/extensions/mcp/oauth/browser.ts +38 -17
  273. package/extensions/mcp/oauth/flow.ts +25 -17
  274. package/extensions/mcp/oauth/provider.ts +14 -8
  275. package/extensions/mcp/oauth/store.ts +34 -16
  276. package/extensions/mcp/panel/keys.ts +12 -11
  277. package/extensions/mcp/panel/render.ts +9 -6
  278. package/extensions/mcp/schema.ts +104 -5
  279. package/extensions/mcp/trust.ts +164 -73
  280. package/extensions/memory/entries.ts +23 -14
  281. package/extensions/memory/index.ts +134 -28
  282. package/extensions/memory/open-external.ts +33 -18
  283. package/extensions/memory/panel.ts +135 -26
  284. package/extensions/model-default/index.ts +86 -19
  285. package/extensions/newer-model/index.ts +31 -0
  286. package/extensions/notebook/description.ts +18 -0
  287. package/extensions/notebook/index.ts +6 -5
  288. package/extensions/notebook/notebook.ts +1 -1
  289. package/extensions/permissions/index.ts +1426 -398
  290. package/extensions/permissions/matcher.ts +425 -74
  291. package/extensions/permissions/modes.ts +11 -4
  292. package/extensions/permissions/panel/host.ts +130 -0
  293. package/extensions/permissions/panel/keys.ts +48 -0
  294. package/extensions/permissions/panel/render.ts +450 -0
  295. package/extensions/permissions/panel/state.ts +550 -0
  296. package/extensions/permissions/powershell-cmdlets.ts +198 -0
  297. package/extensions/permissions/powershell-paths.ts +197 -0
  298. package/extensions/permissions/powershell-rules.ts +207 -280
  299. package/extensions/permissions/powershell-tree.ts +557 -0
  300. package/extensions/permissions/project-trust.ts +27 -11
  301. package/extensions/permissions/protected-paths.ts +14 -2
  302. package/extensions/permissions/session-grant.ts +6 -0
  303. package/extensions/permissions/settings.ts +166 -31
  304. package/extensions/permissions/subagent-gate.ts +25 -0
  305. package/extensions/permissions/workspace.ts +78 -0
  306. package/extensions/plan-mode/index.ts +276 -92
  307. package/extensions/plan-mode/reminder.ts +89 -21
  308. package/extensions/plan-mode/run-state.ts +26 -0
  309. package/extensions/plan-mode/texts.ts +177 -0
  310. package/extensions/plan-mode/viewer.ts +92 -27
  311. package/extensions/plugins/counts.ts +3 -3
  312. package/extensions/plugins/index.ts +64 -46
  313. package/extensions/plugins/install/install.ts +16 -0
  314. package/extensions/plugins/marketplace/sync.ts +9 -3
  315. package/extensions/plugins/marketplace/types.ts +3 -1
  316. package/extensions/plugins/panel/keys.ts +21 -24
  317. package/extensions/plugins/panel/render.ts +12 -6
  318. package/extensions/plugins/shell-expand.ts +107 -0
  319. package/extensions/plugins/template.ts +32 -15
  320. package/extensions/powershell/child.ts +7 -0
  321. package/extensions/powershell/description.ts +38 -6
  322. package/extensions/powershell/guards.ts +1 -1
  323. package/extensions/powershell/index.ts +14 -7
  324. package/extensions/recap/index.ts +73 -71
  325. package/extensions/recap/prompt.ts +2 -2
  326. package/extensions/recap/scheduler.ts +3 -5
  327. package/extensions/search-tools/grep-merge.ts +39 -0
  328. package/extensions/search-tools/index.ts +0 -0
  329. package/extensions/send-now/chord.ts +62 -0
  330. package/extensions/send-now/index.ts +133 -0
  331. package/extensions/session-title/index.ts +3 -0
  332. package/extensions/session-title/title.ts +4 -1
  333. package/extensions/skill/announce.ts +30 -0
  334. package/extensions/skill/code-review.ts +97 -0
  335. package/extensions/skill/index.ts +469 -132
  336. package/extensions/skill/invoke.ts +118 -75
  337. package/extensions/skill/listing.ts +133 -9
  338. package/extensions/skill/panel/keys.ts +15 -16
  339. package/extensions/skill/panel/render.ts +5 -2
  340. package/extensions/skill/panel/state.ts +12 -1
  341. package/extensions/subagents/agent-args.ts +39 -0
  342. package/extensions/subagents/agent-description.ts +132 -0
  343. package/extensions/subagents/agents.ts +146 -31
  344. package/extensions/subagents/default-model.ts +2 -3
  345. package/extensions/subagents/delegation-steer.ts +4 -4
  346. package/extensions/subagents/fork-cache.ts +82 -0
  347. package/extensions/subagents/guide-agent.ts +189 -0
  348. package/extensions/subagents/hand-back-review.ts +3 -0
  349. package/extensions/subagents/index.ts +1594 -852
  350. package/extensions/subagents/live-runs.ts +26 -6
  351. package/extensions/subagents/model-select.ts +38 -25
  352. package/extensions/subagents/outcome.ts +5 -2
  353. package/extensions/subagents/panel-keys.ts +73 -31
  354. package/extensions/subagents/panel-render.ts +120 -96
  355. package/extensions/subagents/panel-widget.ts +60 -89
  356. package/extensions/subagents/parent-mode.ts +50 -0
  357. package/extensions/subagents/pending-claim.ts +18 -1
  358. package/extensions/subagents/runner.ts +135 -80
  359. package/extensions/subagents/runs.ts +44 -5
  360. package/extensions/subagents/send-to-main-tool.ts +1 -1
  361. package/extensions/subagents/session-turns.ts +32 -8
  362. package/extensions/subagents/shell-panel.ts +36 -178
  363. package/extensions/subagents/tasks-dialog.ts +170 -0
  364. package/extensions/subagents/viewport-mirror.ts +95 -0
  365. package/extensions/subagents/worktree.ts +57 -13
  366. package/extensions/system-prompt/environment.ts +19 -19
  367. package/extensions/system-prompt/idle-turn.ts +65 -0
  368. package/extensions/system-prompt/index.ts +165 -47
  369. package/extensions/system-prompt/template.ts +34 -51
  370. package/extensions/system-prompt/tiers/common.ts +23 -64
  371. package/extensions/system-prompt/tiers/frontier.ts +32 -11
  372. package/extensions/system-prompt/tiers/low.ts +67 -45
  373. package/extensions/system-prompt/tiers/mid.ts +96 -38
  374. package/extensions/system-reminder/index.ts +204 -70
  375. package/extensions/tasks/descriptions.ts +190 -0
  376. package/extensions/tasks/index.ts +120 -41
  377. package/extensions/tasks/store.ts +83 -16
  378. package/extensions/tool-call-corruption/child.ts +7 -0
  379. package/extensions/tool-call-corruption/index.ts +237 -0
  380. package/extensions/tool-search/index.ts +366 -144
  381. package/extensions/tool-style/index.ts +68 -10
  382. package/extensions/tool-style/write-description.ts +40 -0
  383. package/extensions/tool-style/write-render.ts +237 -0
  384. package/extensions/turn-duration/index.ts +7 -3
  385. package/extensions/turn-duration/line.ts +47 -4
  386. package/extensions/web/backends.ts +6 -9
  387. package/extensions/web/description.ts +50 -0
  388. package/extensions/web/index.ts +118 -53
  389. package/extensions/web/native-call.ts +15 -0
  390. package/extensions/web/native-results.ts +41 -0
  391. package/extensions/web-fetch/description.ts +42 -0
  392. package/extensions/web-fetch/extract.ts +53 -6
  393. package/extensions/web-fetch/index.ts +125 -76
  394. package/extensions/web-fetch/page-content.ts +19 -0
  395. package/extensions/web-fetch/response.ts +49 -0
  396. package/extensions/web-fetch/summarize.ts +9 -10
  397. package/extensions/workflow/agent-session.ts +108 -18
  398. package/extensions/workflow/args.ts +24 -0
  399. package/extensions/workflow/description.ts +67 -0
  400. package/extensions/workflow/globals.ts +17 -3
  401. package/extensions/workflow/index.ts +157 -162
  402. package/extensions/workflow/records.ts +1 -0
  403. package/extensions/workflow/run-manager.ts +33 -6
  404. package/extensions/workflow/saved-workflows.ts +3 -2
  405. package/extensions/workflow/types.ts +22 -1
  406. package/extensions/workflow/viewer.ts +54 -24
  407. package/extensions/workflow/widget.ts +20 -0
  408. package/extensions/worktree/descriptions.ts +91 -0
  409. package/extensions/worktree/guards.ts +316 -54
  410. package/extensions/worktree/index.ts +162 -44
  411. package/extensions/worktree/powershell-guards.ts +167 -0
  412. package/extensions/worktree/rewrite.ts +14 -16
  413. package/package.json +21 -7
  414. package/skills/artifact-design/SKILL.md +85 -0
  415. package/skills/code-review/SKILL.md +20 -20
  416. package/skills/code-review/cells/arguments-and-flags.md +19 -0
  417. package/skills/code-review/cells/high-3x5-recall-verify.md +137 -0
  418. package/skills/code-review/cells/high-8-inline.md +122 -0
  419. package/skills/code-review/cells/low-1-pass-max4.md +27 -0
  420. package/skills/code-review/cells/low-1-pass-min-files-4.md +28 -0
  421. package/skills/code-review/cells/max-5x5-verify-sweep.md +162 -0
  422. package/skills/code-review/cells/medium-3x5-verify.md +132 -0
  423. package/skills/code-review/cells/minimal-prompt.md +32 -0
  424. package/skills/code-review/cells/xhigh-10-inline-sweep.md +149 -0
  425. package/skills/code-review/cells/xhigh-5x5-verify-sweep.md +162 -0
  426. package/skills/fewer-permission-prompts/SKILL.md +1 -1
  427. package/skills/loop/SKILL.md +11 -0
  428. package/skills/security-review/SKILL.md +2 -5
  429. package/skills/simplify/SKILL.md +7 -5
  430. package/skills/workflow-authoring/SKILL.md +143 -0
  431. package/themes/onecode-light.json +1 -1
  432. package/themes/onecode.json +1 -1
  433. package/types/app.d.ts +58 -0
  434. package/types/community-packages.d.ts +26 -1
  435. package/extensions/auto-mode/recoverability.ts +0 -229
  436. package/extensions/lib/capability-index.ts +0 -466
  437. package/extensions/lib/model-facts.generated.json +0 -2675
  438. package/extensions/lib/model-facts.ts +0 -162
  439. package/extensions/tool-search/announce.ts +0 -42
@@ -8,100 +8,194 @@
8
8
  * focused overlay panel, not in the transcript — so the exchange never enters
9
9
  * the main agent's context and cannot steer its work.
10
10
  *
11
- * The call reuses recap's machinery: the exact messages the session last put on
12
- * the wire (captured from the `context` event), name-only tool stubs so a
13
- * history carrying tool_use blocks stays valid on strict providers, and
14
- * withReasoningFallback for models that cannot disable thinking. Unlike recap it
15
- * uses the SESSION model (not an economical one) — a side question deserves the
16
- * same quality as the main conversation — and sends the full captured history,
17
- * not just the recent window.
11
+ * The call is Claude Code's: the session's last provider request replayed
12
+ * unchanged (system, every tool, every message), the reply that answered it,
13
+ * the session's earlier side exchanges, then the reminder and question, so it
14
+ * reads the cache the session wrote (lib/request-replay.ts; the compaction
15
+ * extension publishes the capture). Without a capture for the session model,
16
+ * or on a provider API the replay does not cover, it falls back to a
17
+ * standalone call: the current branch's messages (read from the session at
18
+ * call time), the earlier side exchanges, an empty system prompt,
19
+ * name-only tool stubs so a history carrying tool_use blocks stays valid on
20
+ * strict providers, and withReasoningFallback for models that cannot disable
21
+ * thinking. Both run on the SESSION model: a side question deserves the same
22
+ * quality as the main conversation.
18
23
  *
19
- * Deviations from CC, logged in docs/decisions/btw.md: the exchange is stateless
20
- * (each `/btw` sees only the shared main context, never a prior `/btw` — CC
21
- * keeps a side-session; the "one-off, no follow-up" framing holds either way);
22
- * `f to fork` is omitted (pi's `ctx.fork` branches from a session entry, not
23
- * from an injected side exchange); and the call runs with an empty system prompt
24
- * (the `context` event carries no system prompt to reuse), relying on the shared
25
- * history plus the reminder.
24
+ * Like Claude Code, the session keeps a side history: each answered question
25
+ * is threaded into the next one and listed in the panel, where it can be
26
+ * browsed and cleared. A /tree keeps only the exchanges asked from a point
27
+ * the selected branch holds. `f` forks the current answer into a background fork
28
+ * subagent through the subagents extension (lib/btw-fork.ts).
26
29
  */
27
30
 
28
- import type { AgentMessage } from "@earendil-works/pi-agent-core";
29
31
  import type { Api, Model } from "@earendil-works/pi-ai";
30
- import { completeSimple } from "@earendil-works/pi-ai/compat";
31
- import { convertToLlm, copyToClipboard, type ExtensionAPI, type ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
32
- import { withReasoningFallback } from "../lib/model-policy.ts";
33
- import { answerText, stripImageBlocks, toolStubs, trimToTurnBoundary } from "../lib/side-call.ts";
34
- import { boundedDockHeight, truncateLine } from "../lib/tui-render.ts";
32
+ import {
33
+ convertToLlm,
34
+ copyToClipboard,
35
+ type ExtensionAPI,
36
+ type ExtensionCommandContext,
37
+ type ExtensionContext,
38
+ getAgentDir,
39
+ SettingsManager,
40
+ UserMessageComponent,
41
+ } from "@earendil-works/pi-coding-agent";
42
+ import { ARGUMENT_HINT_CHANNEL, type ArgumentHint } from "../lib/argument-hints.ts";
43
+ import { btwForkedLine, type BtwForkResult, requestBtwFork } from "../lib/btw-fork.ts";
44
+ import { canShowCustomUi, notifyOrPrint, printAnswer } from "../lib/headless-output.ts";
45
+ import { announcePromptOptions } from "../lib/prompt-options.ts";
46
+ import { followLastExchange, replaySideCall } from "../lib/replay-call.ts";
47
+ import { answerText, branchMessages, stripImageBlocks, toolStubs, trimToTurnBoundary, withoutSystemMessages } from "../lib/side-call.ts";
48
+ import { boundedDockHeight, linesComponent, safeThemePaint, truncateLine } from "../lib/tui-render.ts";
49
+ import { CONVERSATION_CACHE_PLACEMENT } from "../lib/side-call-cache.ts";
50
+ import { releaseSideCalls, runSideCall } from "../lib/side-call-run.ts";
35
51
  import { recordUsage } from "../lib/usage-bus.ts";
36
- import { applyBtwKey, type BtwBody, BTW_MAX_HEIGHT, decodeBtwKey, initialBtwState, renderBtwPanel } from "./panel.ts";
37
- import { sideQuestionMessage } from "./prompt.ts";
52
+ import type { ProseRenderer } from "../subagents/panel-render.ts";
53
+ import { createMarkdownProse } from "../subagents/prose.ts";
54
+ import { applyBtwKey, type BtwBody, BTW_MAX_HEIGHT, copyAnswer, decodeBtwKey, initialBtwState, renderBtwPanel } from "./panel.ts";
55
+ import { type BtwExchange, exchangeMessages, historyMessages, sideQuestionMessage } from "./prompt.ts";
56
+ import { panelUi } from "../lib/panel-focus.ts";
38
57
 
39
58
  const BTW_MAX_TOKENS = 8192;
40
59
  const BTW_TIMEOUT_MS = 120_000;
41
60
  /** Description on the name-only tool stubs sent with the side question. */
42
61
  const STUB_REASON = "Unavailable during this side question; answer in text.";
62
+ /**
63
+ * The transcript record of a started fork, Claude Code's `/btw <question>` row
64
+ * with `⎿ ⑂ forked <name> (<id>)` under it. A display-only session entry: it
65
+ * never reaches the model, which learns of the fork from a one-shot reminder.
66
+ */
67
+ const FORK_ENTRY_TYPE = "one-code:btw-fork";
68
+
69
+ interface BtwForkEntry {
70
+ question: string;
71
+ name: string;
72
+ taskId: string;
73
+ }
43
74
 
44
75
  export default function btwExtension(pi: ExtensionAPI) {
45
- // The exact request messages the session last sent (after every extension's
46
- // mutations), captured like recap and the compaction extension do.
47
- let capturedMessages: AgentMessage[] | undefined;
48
- pi.on("context", (event) => {
49
- capturedMessages = event.messages;
76
+ // The fork entry's `/btw` row is drawn as pi draws a user prompt, with the
77
+ // padding pi read from settings at startup.
78
+ let outputPad = 1;
79
+ try {
80
+ outputPad = SettingsManager.create(process.cwd(), getAgentDir()).getOutputPad();
81
+ } catch {
82
+ // Unreadable settings: pi's default padding.
83
+ }
84
+ pi.registerEntryRenderer<BtwForkEntry>(FORK_ENTRY_TYPE, (entry, _options, theme) => {
85
+ const data = entry.data;
86
+ if (!data) return undefined;
87
+ const row = new UserMessageComponent(`/btw ${data.question}`, undefined, outputPad);
88
+ const paint = safeThemePaint(theme);
89
+ return linesComponent((width) => [...row.render(width), truncateLine(` ⎿ ${paint("dim", btwForkedLine(data.name, data.taskId))}`, width)]);
50
90
  });
51
91
 
92
+ // The session's last request as it went on the wire, and the reply that answered it.
93
+ const exchange = followLastExchange(pi);
94
+
95
+ // The session's answered side questions, oldest first: sent before each new
96
+ // question and listed in the panel. `x` in the panel clears them. Each one
97
+ // keeps the entry the conversation stood at when it was asked, since it was
98
+ // answered from the conversation up to there.
99
+ let history: Array<BtwExchange & { askedAt: string | undefined }> = [];
100
+ /** The entry the branch ends at: where a side question is asked from (undefined in an empty session). */
101
+ const leafOf = (ctx: ExtensionContext): string | undefined => ctx.sessionManager.getBranch().at(-1)?.id;
102
+ /** Whether the selected branch holds the point a side question was asked from. */
103
+ const onBranch = (ctx: ExtensionContext, askedAt: string | undefined): boolean =>
104
+ askedAt === undefined || ctx.sessionManager.getBranch().some((entry) => entry.id === askedAt);
105
+ /** Thread an answer into the side history, unless a /tree since left the point it was asked from. */
106
+ const keep = (ctx: ExtensionContext, exchange: BtwExchange, askedAt: string | undefined) => {
107
+ if (exchange.answer && onBranch(ctx, askedAt)) history.push({ ...exchange, askedAt });
108
+ };
109
+
52
110
  // The controller for an open panel's in-flight call. Aborted when the session
53
111
  // is replaced or torn down, so a late resolve cannot repaint a disposed `tui`
54
112
  // or record usage on a stale `pi` (the crash the subagents panel once hit —
55
- // docs/decisions/tools.md lifecycle review).
113
+ // working-docs/decisions/tools.md lifecycle review).
56
114
  let inFlight: AbortController | undefined;
115
+ // Bumped when the session is replaced or torn down, so a fork request that
116
+ // settles afterwards touches neither the closed panel nor a stale ctx.
117
+ let sessionEpoch = 0;
57
118
 
58
- // A new session (including after /clear) shares no context with the old one,
59
- // and any in-flight side question is abandoned.
119
+ // A new session (including after /clear) shares no context with the old one:
120
+ // its side history starts empty and any in-flight side question is abandoned.
60
121
  pi.on("session_start", () => {
61
- capturedMessages = undefined;
122
+ sessionEpoch++;
123
+ // Claude Code's `[question]` placeholder after a bare `/btw` in the prompt.
124
+ pi.events.emit(ARGUMENT_HINT_CHANNEL, { command: "btw", hint: "[question]" } satisfies ArgumentHint);
125
+ history = [];
62
126
  inFlight?.abort();
63
127
  inFlight = undefined;
64
128
  });
65
- pi.on("session_shutdown", () => {
129
+ pi.on("session_shutdown", (_event, ctx) => {
130
+ sessionEpoch++;
66
131
  inFlight?.abort();
67
132
  inFlight = undefined;
133
+ releaseSideCalls(ctx.sessionManager.getSessionId());
134
+ });
135
+ // A /tree keeps the side exchanges asked from a point the selected branch
136
+ // holds; the others were answered from the abandoned branch's conversation.
137
+ pi.on("session_tree", (_event, ctx) => {
138
+ const ids = new Set(ctx.sessionManager.getBranch().map((entry) => entry.id));
139
+ history = history.filter((exchange) => exchange.askedAt === undefined || ids.has(exchange.askedAt));
68
140
  });
69
141
 
70
- /** Run the side question against the session model; returns the answer text. */
71
- async function ask(ctx: ExtensionCommandContext, question: string, signal: AbortSignal): Promise<string> {
72
- const model = ctx.model;
142
+ // The answer renders as Markdown, like the transcript; plain wrapped text
143
+ // until the renderer loads, or if it cannot.
144
+ let prose: ProseRenderer | undefined;
145
+ let proseLoad: Promise<void> | undefined;
146
+ const loadProse = (): Promise<void> =>
147
+ (proseLoad ??= createMarkdownProse().then(
148
+ (renderer) => {
149
+ prose = renderer;
150
+ },
151
+ () => {},
152
+ ));
153
+
154
+ /** Run the side question against the session model, after the earlier exchanges; returns the answer text. */
155
+ async function ask(ctx: ExtensionCommandContext, question: string, earlier: readonly BtwExchange[], signal: AbortSignal): Promise<string> {
156
+ const model = ctx.model as Model<Api> | undefined;
73
157
  if (!model) throw new Error("No model is configured for this session.");
158
+ const before = historyMessages(earlier, model);
159
+ const replayed = await replaySideCall(ctx, model, exchange, sideQuestionMessage(question), {
160
+ signal,
161
+ timeoutMs: BTW_TIMEOUT_MS,
162
+ onUsage: (usage) => recordUsage(pi, "btw", usage),
163
+ history: before,
164
+ });
165
+ if (replayed !== undefined) return replayed;
166
+
167
+ // No replay for this model, or it failed: the standalone call.
74
168
  const auth = await ctx.modelRegistry.getApiKeyAndHeaders(model);
75
169
  if (!auth.ok) throw new Error("No API key is available for the current model.");
76
- const baseUrl = (auth as { baseUrl?: string }).baseUrl;
77
-
78
170
  const tools = toolStubs(pi.getActiveTools(), STUB_REASON);
79
- const context = trimToTurnBoundary(capturedMessages ?? []);
171
+ // The current branch, read now: a /tree or a compaction since the last
172
+ // request changed it, and pi fires no `context` event for either.
173
+ const context = trimToTurnBoundary(withoutSystemMessages(branchMessages(ctx)));
80
174
  // btw runs on a cheap, possibly text-only reader and answers a text question,
81
175
  // so images the conversation carried are stripped before the call
82
- // (docs/decisions/model-policy.md).
83
- const messages = [...stripImageBlocks(convertToLlm(context)), { role: "user" as const, content: sideQuestionMessage(question), timestamp: Date.now() }];
84
-
85
- const result = await withReasoningFallback(
86
- model as Model<Api>,
87
- (reasoning) => {
88
- const timeout = AbortSignal.timeout(BTW_TIMEOUT_MS);
89
- return completeSimple(
90
- baseUrl ? ({ ...model, baseUrl } as Model<Api>) : (model as Model<Api>),
91
- { systemPrompt: "", messages, tools },
92
- {
93
- apiKey: auth.apiKey,
94
- headers: auth.headers,
95
- env: auth.env,
96
- signal: AbortSignal.any([signal, timeout]),
97
- maxTokens: BTW_MAX_TOKENS,
98
- ...(reasoning ? { reasoning } : {}),
99
- },
100
- );
101
- },
102
- undefined,
103
- (usage) => recordUsage(pi, "btw", usage),
104
- );
176
+ // (working-docs/decisions/model-policy.md).
177
+ const messages = [
178
+ ...stripImageBlocks(convertToLlm(context)),
179
+ ...before,
180
+ { role: "user" as const, content: sideQuestionMessage(question), timestamp: Date.now() },
181
+ ];
182
+ const result = await runSideCall({
183
+ kind: "btw",
184
+ model,
185
+ auth,
186
+ sessionId: ctx.sessionManager.getSessionId(),
187
+ context: { systemPrompt: "", messages, tools },
188
+ signal,
189
+ timeoutMs: BTW_TIMEOUT_MS,
190
+ maxTokens: BTW_MAX_TOKENS,
191
+ cache: CONVERSATION_CACHE_PLACEMENT,
192
+ onUsage: (usage) => recordUsage(pi, "btw", usage),
193
+ });
194
+ // completeSimple reports a failure (a network error, a timeout) in the
195
+ // reply instead of throwing; its empty text is not an answer.
196
+ if (signal.aborted) return "";
197
+ if (result.stopReason === "aborted") throw new Error(`No answer within ${BTW_TIMEOUT_MS / 1000} seconds.`);
198
+ if (result.stopReason === "error") throw new Error(result.errorMessage || "The model returned an error.");
105
199
  return answerText(result.content);
106
200
  }
107
201
 
@@ -113,15 +207,28 @@ export default function btwExtension(pi: ExtensionAPI) {
113
207
  ctx.ui.notify("Ask a side question: /btw <question>", "info");
114
208
  return;
115
209
  }
210
+ const askedAt = leafOf(ctx);
211
+ // The panel can fork a background agent whose completion opens the
212
+ // session's first turn; this context carries the options that turn
213
+ // is built from (lib/prompt-options.ts).
214
+ announcePromptOptions(pi.events, ctx);
116
215
 
117
- // Headless (-p / --mode json): no panel — answer and print it. The
118
- // handler blocks to completion, so the process does not exit early.
119
- if (!ctx.hasUI) {
216
+ // RPC has dialogs but no custom panel. Deliver its answer as a notice,
217
+ // never a main-conversation message; one-shot runs print it instead.
218
+ if (!canShowCustomUi(ctx)) {
219
+ inFlight?.abort();
220
+ const controller = new AbortController();
221
+ inFlight = controller;
120
222
  try {
121
- const answer = await ask(ctx, question, new AbortController().signal);
122
- ctx.ui.notify(answer || "(no answer)", "info");
223
+ const answer = await ask(ctx, question, history, controller.signal);
224
+ if (controller.signal.aborted) return;
225
+ keep(ctx, { question, answer }, askedAt);
226
+ if (ctx.mode === "rpc") ctx.ui.notify(answer || "(no answer)", "info");
227
+ else printAnswer(ctx, answer || "(no answer)");
123
228
  } catch (error) {
124
- ctx.ui.notify(`Side question failed: ${error instanceof Error ? error.message : String(error)}`, "error");
229
+ if (!controller.signal.aborted) notifyOrPrint(ctx, `Side question failed: ${error instanceof Error ? error.message : String(error)}`, "error");
230
+ } finally {
231
+ if (inFlight === controller) inFlight = undefined;
125
232
  }
126
233
  return;
127
234
  }
@@ -132,11 +239,22 @@ export default function btwExtension(pi: ExtensionAPI) {
132
239
  inFlight?.abort();
133
240
  const controller = new AbortController();
134
241
  inFlight = controller;
135
- const view: { answer?: string; error?: string } = {};
242
+ // The earlier exchanges this panel lists and browses; the current one
243
+ // joins `history` when it lands, so the next /btw lists it.
244
+ let earlier = [...history];
245
+ const view: { answer?: string; error?: string; forking?: boolean } = {};
136
246
  const bodyState = (): BtwBody =>
137
247
  view.error !== undefined ? { kind: "error", message: view.error } : view.answer !== undefined ? { kind: "answer", text: view.answer } : { kind: "loading" };
248
+ // Reported after the panel closes: a started fork joins the transcript as
249
+ // Claude Code's `⑂ forked` entry; a failure is an error notice.
250
+ let forkResult: BtwForkResult | undefined;
251
+ const reportFork = (result: BtwForkResult) => {
252
+ if ("error" in result) ctx.ui.notify(result.error, "error");
253
+ else pi.appendEntry<BtwForkEntry>(FORK_ENTRY_TYPE, { question, name: result.name, taskId: result.taskId });
254
+ };
255
+ let panelOpen = true;
138
256
 
139
- await ctx.ui.custom<null>((tui, theme, _keybindings, done) => {
257
+ await panelUi(pi.events, ctx.ui).custom<null>((tui, theme, _keybindings, done) => {
140
258
  const state = initialBtwState();
141
259
  let cache: { width: number; lines: string[] } | undefined;
142
260
  const repaint = () => {
@@ -147,13 +265,15 @@ export default function btwExtension(pi: ExtensionAPI) {
147
265
  tui.requestRender();
148
266
  } catch {}
149
267
  };
268
+ if (!prose) void loadProse().then(() => prose && repaint());
150
269
 
151
270
  // Kick off the model call once, at mount, so `repaint` is bound.
152
271
  void (async () => {
153
272
  try {
154
- const answer = await ask(ctx, question, controller.signal);
273
+ const answer = await ask(ctx, question, earlier, controller.signal);
155
274
  if (controller.signal.aborted) return;
156
275
  view.answer = answer;
276
+ keep(ctx, { question, answer }, askedAt);
157
277
  } catch (error) {
158
278
  if (controller.signal.aborted) return;
159
279
  view.error = error instanceof Error ? error.message : String(error);
@@ -161,6 +281,30 @@ export default function btwExtension(pi: ExtensionAPI) {
161
281
  repaint();
162
282
  })();
163
283
 
284
+ const fork = (answer: string) => {
285
+ const model = ctx.model as Model<Api> | undefined;
286
+ if (!model) return;
287
+ view.forking = true;
288
+ repaint();
289
+ const epoch = sessionEpoch;
290
+ // The fork sees what the answer was written from: the earlier exchanges
291
+ // still listed (none once cleared), then this one.
292
+ const messages = [...historyMessages(earlier, model), ...exchangeMessages({ question, answer }, model)];
293
+ void requestBtwFork(pi.events, { ctx, question, messages }).then((result) => {
294
+ if (epoch !== sessionEpoch) return;
295
+ if (panelOpen) {
296
+ view.forking = false;
297
+ forkResult = result;
298
+ done(null);
299
+ return;
300
+ }
301
+ // The user closed the panel while the fork was starting.
302
+ try {
303
+ reportFork(result);
304
+ } catch {}
305
+ });
306
+ };
307
+
164
308
  return {
165
309
  render: (width: number) => {
166
310
  if (cache?.width === width) return cache.lines;
@@ -169,26 +313,52 @@ export default function btwExtension(pi: ExtensionAPI) {
169
313
  // Belt-and-suspenders truncate on top of renderBtwPanel's own,
170
314
  // matching every sibling dock panel: pi-tui crashes the app on
171
315
  // a line wider than the terminal.
172
- const lines = renderBtwPanel({ state, question, body: bodyState(), width, height }, theme).map((line) => truncateLine(line, width));
316
+ const lines = renderBtwPanel(
317
+ {
318
+ state,
319
+ history: earlier,
320
+ question,
321
+ body: bodyState(),
322
+ width,
323
+ height,
324
+ canFork: true,
325
+ forking: view.forking,
326
+ renderAnswer: prose ? (text, width, ref) => prose!(ref, text, width) : undefined,
327
+ },
328
+ theme,
329
+ ).map((line) => truncateLine(line, width));
173
330
  cache = { width, lines };
174
331
  return lines;
175
332
  },
176
333
  handleInput: (data: string) => {
177
334
  const key = decodeBtwKey(data);
178
335
  if (!key) return;
179
- const effect = applyBtwKey(state, key);
336
+ // While a fork starts only closing works; its notice follows.
337
+ if (view.forking) {
338
+ if (key.kind === "close") done(null);
339
+ return;
340
+ }
341
+ const effect = applyBtwKey(state, key, earlier.length);
342
+ const shown = state.selected === null ? view.answer : earlier[state.selected]?.answer;
180
343
  switch (effect?.kind) {
181
344
  case "close":
182
345
  done(null);
183
346
  return;
184
347
  case "copy":
185
348
  // Only offer copy once there is a non-empty answer.
186
- if (view.answer) {
187
- void copyToClipboard(view.answer).then(() => {
188
- state.copied = true;
189
- repaint();
190
- });
191
- }
349
+ if (shown) void copyAnswer(copyToClipboard, shown, state, repaint);
350
+ return;
351
+ case "fork":
352
+ // The current answer only, not one browsed from the history.
353
+ if (state.selected === null && view.answer) fork(view.answer);
354
+ return;
355
+ case "clear":
356
+ if (earlier.length === 0) return;
357
+ history = history.filter((entry) => !earlier.includes(entry));
358
+ earlier = [];
359
+ state.selected = null;
360
+ state.offset = 0;
361
+ repaint();
192
362
  return;
193
363
  default:
194
364
  repaint();
@@ -200,8 +370,10 @@ export default function btwExtension(pi: ExtensionAPI) {
200
370
  };
201
371
  });
202
372
 
373
+ panelOpen = false;
203
374
  controller.abort();
204
375
  if (inFlight === controller) inFlight = undefined;
376
+ if (forkResult) reportFork(forkResult);
205
377
  },
206
378
  });
207
379
  }