@bastani/atomic 0.8.21-0 → 0.8.22-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 (235) hide show
  1. package/CHANGELOG.md +46 -9
  2. package/dist/builtin/intercom/broker/broker.ts +3 -3
  3. package/dist/builtin/intercom/config.ts +3 -3
  4. package/dist/builtin/intercom/index.ts +1 -1
  5. package/dist/builtin/intercom/package.json +1 -1
  6. package/dist/builtin/intercom/ui/compose.ts +2 -2
  7. package/dist/builtin/mcp/host-html-template.ts +0 -3
  8. package/dist/builtin/mcp/package.json +1 -1
  9. package/dist/builtin/subagents/CHANGELOG.md +13 -4
  10. package/dist/builtin/subagents/agents/codebase-online-researcher.md +9 -9
  11. package/dist/builtin/subagents/agents/debugger.md +6 -6
  12. package/dist/builtin/subagents/package.json +1 -1
  13. package/dist/builtin/subagents/prompts/parallel-handoff-plan.md +1 -1
  14. package/dist/builtin/subagents/skills/browser-use/SKILL.md +234 -0
  15. package/dist/builtin/subagents/skills/browser-use/references/cdp-python.md +76 -0
  16. package/dist/builtin/subagents/skills/browser-use/references/multi-session.md +92 -0
  17. package/dist/builtin/subagents/skills/subagent/SKILL.md +4 -4
  18. package/dist/builtin/subagents/src/agents/skills.ts +19 -1
  19. package/dist/builtin/subagents/src/extension/index.ts +24 -22
  20. package/dist/builtin/subagents/src/intercom/intercom-bridge.ts +7 -1
  21. package/dist/builtin/subagents/src/runs/background/async-execution.ts +23 -7
  22. package/dist/builtin/subagents/src/runs/background/async-job-tracker.ts +98 -3
  23. package/dist/builtin/subagents/src/runs/background/async-status.ts +3 -1
  24. package/dist/builtin/subagents/src/runs/background/run-status.ts +1 -1
  25. package/dist/builtin/subagents/src/runs/background/stale-run-reconciler.ts +3 -0
  26. package/dist/builtin/subagents/src/runs/background/subagent-runner.ts +37 -12
  27. package/dist/builtin/subagents/src/runs/foreground/chain-clarify.ts +15 -15
  28. package/dist/builtin/subagents/src/runs/foreground/execution.ts +26 -2
  29. package/dist/builtin/subagents/src/runs/shared/nested-render.ts +1 -1
  30. package/dist/builtin/subagents/src/runs/shared/parallel-utils.ts +7 -0
  31. package/dist/builtin/subagents/src/runs/shared/pi-args.ts +28 -1
  32. package/dist/builtin/subagents/src/shared/fast-mode.ts +80 -0
  33. package/dist/builtin/subagents/src/shared/formatters.ts +4 -2
  34. package/dist/builtin/subagents/src/shared/types.ts +4 -2
  35. package/dist/builtin/subagents/src/shared/utils.ts +3 -61
  36. package/dist/builtin/subagents/src/tui/render.ts +303 -157
  37. package/dist/builtin/web-access/package.json +1 -1
  38. package/dist/builtin/workflows/CHANGELOG.md +101 -35
  39. package/dist/builtin/workflows/README.md +228 -41
  40. package/dist/builtin/workflows/builtin/deep-research-codebase.ts +535 -541
  41. package/dist/builtin/workflows/builtin/goal.ts +39 -25
  42. package/dist/builtin/workflows/builtin/open-claude-design.ts +66 -69
  43. package/dist/builtin/workflows/builtin/ralph.ts +21 -21
  44. package/dist/builtin/workflows/package.json +6 -5
  45. package/dist/builtin/workflows/skills/research-codebase/SKILL.md +1 -1
  46. package/dist/builtin/workflows/src/extension/background-ui-adapter.ts +2 -2
  47. package/dist/builtin/workflows/src/extension/discovery.ts +25 -146
  48. package/dist/builtin/workflows/src/extension/dispatcher.ts +72 -24
  49. package/dist/builtin/workflows/src/extension/hil-answer-notifications.ts +363 -0
  50. package/dist/builtin/workflows/src/extension/index.ts +690 -352
  51. package/dist/builtin/workflows/src/extension/lifecycle-notifications.ts +99 -62
  52. package/dist/builtin/workflows/src/extension/render-call.ts +2 -1
  53. package/dist/builtin/workflows/src/extension/render-result.ts +9 -3
  54. package/dist/builtin/workflows/src/extension/renderers.ts +5 -3
  55. package/dist/builtin/workflows/src/extension/runtime.ts +68 -33
  56. package/dist/builtin/workflows/src/extension/status-writer.ts +1 -1
  57. package/dist/builtin/workflows/src/extension/wiring.ts +34 -13
  58. package/dist/builtin/workflows/src/extension/workflow-module-loader.ts +142 -0
  59. package/dist/builtin/workflows/src/extension/workflow-schema.ts +4 -4
  60. package/dist/builtin/workflows/src/index.ts +2 -0
  61. package/dist/builtin/workflows/src/intercom/result-intercom.ts +1 -1
  62. package/dist/builtin/workflows/src/runs/background/runner.ts +6 -4
  63. package/dist/builtin/workflows/src/runs/background/status.ts +45 -21
  64. package/dist/builtin/workflows/src/runs/foreground/executor.ts +624 -52
  65. package/dist/builtin/workflows/src/runs/foreground/stage-control-registry.ts +1 -1
  66. package/dist/builtin/workflows/src/runs/foreground/stage-runner.ts +80 -24
  67. package/dist/builtin/workflows/src/runs/shared/validate-inputs.ts +61 -24
  68. package/dist/builtin/workflows/src/runs/shared/workflow-runner.ts +32 -10
  69. package/dist/builtin/workflows/src/sdk-surface.ts +6 -0
  70. package/dist/builtin/workflows/src/shared/expanded-workflow-graph.ts +178 -0
  71. package/dist/builtin/workflows/src/shared/persistence-restore.ts +92 -12
  72. package/dist/builtin/workflows/src/shared/persistence-session-entries.ts +21 -3
  73. package/dist/builtin/workflows/src/shared/render-inputs-schema.ts +1 -2
  74. package/dist/builtin/workflows/src/shared/run-visibility.ts +9 -0
  75. package/dist/builtin/workflows/src/shared/schema-introspection.ts +121 -0
  76. package/dist/builtin/workflows/src/shared/serializable.ts +132 -0
  77. package/dist/builtin/workflows/src/shared/stage-ui-broker.ts +91 -9
  78. package/dist/builtin/workflows/src/shared/store-types.ts +31 -3
  79. package/dist/builtin/workflows/src/shared/store.ts +58 -14
  80. package/dist/builtin/workflows/src/shared/types.ts +105 -40
  81. package/dist/builtin/workflows/src/tui/chat-surface-message.ts +129 -13
  82. package/dist/builtin/workflows/src/tui/chat-surface.ts +6 -1
  83. package/dist/builtin/workflows/src/tui/dispatch-confirm.ts +3 -2
  84. package/dist/builtin/workflows/src/tui/graph-canvas.ts +1 -1
  85. package/dist/builtin/workflows/src/tui/graph-view.ts +91 -65
  86. package/dist/builtin/workflows/src/tui/inline-form-card.ts +1 -1
  87. package/dist/builtin/workflows/src/tui/inline-form-overlay.ts +3 -2
  88. package/dist/builtin/workflows/src/tui/inputs-overlay.ts +3 -2
  89. package/dist/builtin/workflows/src/tui/inputs-picker.ts +8 -7
  90. package/dist/builtin/workflows/src/tui/keybindings-adapter.ts +2 -0
  91. package/dist/builtin/workflows/src/tui/node-card.ts +34 -8
  92. package/dist/builtin/workflows/src/tui/overlay-adapter.ts +4 -11
  93. package/dist/builtin/workflows/src/tui/prompt-card.ts +98 -50
  94. package/dist/builtin/workflows/src/tui/session-list.ts +7 -2
  95. package/dist/builtin/workflows/src/tui/session-picker.ts +2 -0
  96. package/dist/builtin/workflows/src/tui/stage-chat-view.ts +226 -55
  97. package/dist/builtin/workflows/src/tui/status-helpers.ts +2 -0
  98. package/dist/builtin/workflows/src/tui/store-widget-installer.ts +37 -158
  99. package/dist/builtin/workflows/src/tui/toast.ts +2 -2
  100. package/dist/builtin/workflows/src/tui/widget.ts +53 -12
  101. package/dist/builtin/workflows/src/tui/workflow-attach-pane.ts +270 -19
  102. package/dist/builtin/workflows/src/tui/workflow-notice-card.ts +184 -0
  103. package/dist/builtin/workflows/src/workflows/define-workflow.ts +138 -43
  104. package/dist/config.d.ts +9 -0
  105. package/dist/config.d.ts.map +1 -1
  106. package/dist/config.js +45 -0
  107. package/dist/config.js.map +1 -1
  108. package/dist/core/agent-session.d.ts +27 -9
  109. package/dist/core/agent-session.d.ts.map +1 -1
  110. package/dist/core/agent-session.js +196 -17
  111. package/dist/core/agent-session.js.map +1 -1
  112. package/dist/core/atomic-guide-command.d.ts.map +1 -1
  113. package/dist/core/atomic-guide-command.js +2 -2
  114. package/dist/core/atomic-guide-command.js.map +1 -1
  115. package/dist/core/codex-fast-mode.d.ts +36 -0
  116. package/dist/core/codex-fast-mode.d.ts.map +1 -0
  117. package/dist/core/codex-fast-mode.js +117 -0
  118. package/dist/core/codex-fast-mode.js.map +1 -0
  119. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  120. package/dist/core/compaction/branch-summarization.js +1 -1
  121. package/dist/core/compaction/branch-summarization.js.map +1 -1
  122. package/dist/core/compaction/compaction.d.ts.map +1 -1
  123. package/dist/core/compaction/compaction.js +1 -1
  124. package/dist/core/compaction/compaction.js.map +1 -1
  125. package/dist/core/extensions/index.d.ts +4 -1
  126. package/dist/core/extensions/index.d.ts.map +1 -1
  127. package/dist/core/extensions/index.js +1 -0
  128. package/dist/core/extensions/index.js.map +1 -1
  129. package/dist/core/extensions/loader.d.ts +7 -2
  130. package/dist/core/extensions/loader.d.ts.map +1 -1
  131. package/dist/core/extensions/loader.js +23 -8
  132. package/dist/core/extensions/loader.js.map +1 -1
  133. package/dist/core/extensions/reactive-widget.d.ts +58 -0
  134. package/dist/core/extensions/reactive-widget.d.ts.map +1 -0
  135. package/dist/core/extensions/reactive-widget.js +182 -0
  136. package/dist/core/extensions/reactive-widget.js.map +1 -0
  137. package/dist/core/extensions/runner.d.ts.map +1 -1
  138. package/dist/core/extensions/runner.js +1 -0
  139. package/dist/core/extensions/runner.js.map +1 -1
  140. package/dist/core/extensions/types.d.ts +26 -12
  141. package/dist/core/extensions/types.d.ts.map +1 -1
  142. package/dist/core/extensions/types.js.map +1 -1
  143. package/dist/core/messages.d.ts +1 -1
  144. package/dist/core/messages.d.ts.map +1 -1
  145. package/dist/core/messages.js +8 -2
  146. package/dist/core/messages.js.map +1 -1
  147. package/dist/core/model-registry.d.ts +4 -0
  148. package/dist/core/model-registry.d.ts.map +1 -1
  149. package/dist/core/model-registry.js +11 -0
  150. package/dist/core/model-registry.js.map +1 -1
  151. package/dist/core/resource-loader.d.ts +9 -1
  152. package/dist/core/resource-loader.d.ts.map +1 -1
  153. package/dist/core/resource-loader.js +49 -21
  154. package/dist/core/resource-loader.js.map +1 -1
  155. package/dist/core/sdk.d.ts.map +1 -1
  156. package/dist/core/sdk.js +22 -13
  157. package/dist/core/sdk.js.map +1 -1
  158. package/dist/core/session-manager.d.ts +7 -5
  159. package/dist/core/session-manager.d.ts.map +1 -1
  160. package/dist/core/session-manager.js +5 -3
  161. package/dist/core/session-manager.js.map +1 -1
  162. package/dist/core/settings-manager.d.ts +16 -0
  163. package/dist/core/settings-manager.d.ts.map +1 -1
  164. package/dist/core/settings-manager.js +64 -5
  165. package/dist/core/settings-manager.js.map +1 -1
  166. package/dist/core/slash-commands.d.ts.map +1 -1
  167. package/dist/core/slash-commands.js +1 -0
  168. package/dist/core/slash-commands.js.map +1 -1
  169. package/dist/core/system-prompt.d.ts.map +1 -1
  170. package/dist/core/system-prompt.js +7 -4
  171. package/dist/core/system-prompt.js.map +1 -1
  172. package/dist/core/tools/ask-user-question/ask-user-question.d.ts.map +1 -1
  173. package/dist/core/tools/ask-user-question/ask-user-question.js +2 -2
  174. package/dist/core/tools/ask-user-question/ask-user-question.js.map +1 -1
  175. package/dist/index.d.ts +4 -3
  176. package/dist/index.d.ts.map +1 -1
  177. package/dist/index.js +3 -2
  178. package/dist/index.js.map +1 -1
  179. package/dist/main.d.ts +3 -0
  180. package/dist/main.d.ts.map +1 -1
  181. package/dist/main.js +12 -0
  182. package/dist/main.js.map +1 -1
  183. package/dist/modes/interactive/chat-input-actions.d.ts.map +1 -1
  184. package/dist/modes/interactive/chat-input-actions.js.map +1 -1
  185. package/dist/modes/interactive/components/diff.d.ts.map +1 -1
  186. package/dist/modes/interactive/components/diff.js +0 -1
  187. package/dist/modes/interactive/components/diff.js.map +1 -1
  188. package/dist/modes/interactive/components/fast-mode-selector.d.ts +27 -0
  189. package/dist/modes/interactive/components/fast-mode-selector.d.ts.map +1 -0
  190. package/dist/modes/interactive/components/fast-mode-selector.js +105 -0
  191. package/dist/modes/interactive/components/fast-mode-selector.js.map +1 -0
  192. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  193. package/dist/modes/interactive/components/footer.js +7 -12
  194. package/dist/modes/interactive/components/footer.js.map +1 -1
  195. package/dist/modes/interactive/components/index.d.ts +1 -0
  196. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  197. package/dist/modes/interactive/components/index.js +1 -0
  198. package/dist/modes/interactive/components/index.js.map +1 -1
  199. package/dist/modes/interactive/interactive-mode.d.ts +4 -0
  200. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  201. package/dist/modes/interactive/interactive-mode.js +132 -30
  202. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  203. package/dist/modes/print-mode.d.ts.map +1 -1
  204. package/dist/modes/print-mode.js +53 -6
  205. package/dist/modes/print-mode.js.map +1 -1
  206. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  207. package/dist/modes/rpc/rpc-mode.js +3 -0
  208. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  209. package/docs/compaction.md +1 -1
  210. package/docs/custom-provider.md +2 -2
  211. package/docs/development.md +2 -2
  212. package/docs/docs.json +2 -2
  213. package/docs/extensions.md +18 -13
  214. package/docs/providers.md +5 -1
  215. package/docs/quickstart.md +5 -3
  216. package/docs/rpc.md +5 -5
  217. package/docs/sdk.md +12 -12
  218. package/docs/settings.md +18 -0
  219. package/docs/themes.md +6 -6
  220. package/docs/tui.md +20 -18
  221. package/docs/usage.md +2 -0
  222. package/docs/workflows.md +403 -39
  223. package/examples/extensions/qna.ts +2 -2
  224. package/package.json +4 -4
  225. package/dist/builtin/subagents/skills/playwright-cli/SKILL.md +0 -392
  226. package/dist/builtin/subagents/skills/playwright-cli/references/element-attributes.md +0 -23
  227. package/dist/builtin/subagents/skills/playwright-cli/references/playwright-tests.md +0 -39
  228. package/dist/builtin/subagents/skills/playwright-cli/references/request-mocking.md +0 -87
  229. package/dist/builtin/subagents/skills/playwright-cli/references/running-code.md +0 -241
  230. package/dist/builtin/subagents/skills/playwright-cli/references/session-management.md +0 -225
  231. package/dist/builtin/subagents/skills/playwright-cli/references/spec-driven-testing.md +0 -305
  232. package/dist/builtin/subagents/skills/playwright-cli/references/storage-state.md +0 -275
  233. package/dist/builtin/subagents/skills/playwright-cli/references/test-generation.md +0 -134
  234. package/dist/builtin/subagents/skills/playwright-cli/references/tracing.md +0 -139
  235. package/dist/builtin/subagents/skills/playwright-cli/references/video-recording.md +0 -143
@@ -8,7 +8,7 @@ import * as path from "node:path";
8
8
  import { getProviders, } from "@earendil-works/pi-ai";
9
9
  import { CombinedAutocompleteProvider, Container, fuzzyFilter, getCapabilities, hyperlink, Loader, Markdown, matchesKey, ProcessTerminal, Spacer, setKeybindings, Text, TruncatedText, TUI, visibleWidth, } from "@earendil-works/pi-tui";
10
10
  import { spawn, spawnSync } from "child_process";
11
- import { APP_NAME, APP_TITLE, CHANGELOG_URL, ENV_OFFLINE, getEnvValue, getAgentDir, getAuthPath, getDebugLogPath, getDocsPath, getShareViewerUrl, VERSION, } from "../../config.js";
11
+ import { APP_NAME, APP_TITLE, CHANGELOG_URL, ENV_OFFLINE, getEnvValue, setCodexFastModeEnvironmentSettings, getAgentDir, getAuthPath, getDebugLogPath, getDocsPath, getShareViewerUrl, VERSION, } from "../../config.js";
12
12
  import { parseSkillBlock, } from "../../core/agent-session.js";
13
13
  import { pickWhimsicalWorkingMessage } from "./whimsical-messages.js";
14
14
  import { SessionImportFileNotFoundError, } from "../../core/agent-session-runtime.js";
@@ -16,6 +16,7 @@ import { FooterDataProvider, } from "../../core/footer-data-provider.js";
16
16
  import { KeybindingsManager, } from "../../core/keybindings.js";
17
17
  import { createCompactionSummaryMessage } from "../../core/messages.js";
18
18
  import { defaultModelPerProvider, findExactModelReferenceMatch, resolveModelScope, } from "../../core/model-resolver.js";
19
+ import { formatCodexFastModeModelLabel, hasSupportedCodexFastModeModel, shouldApplyCodexFastMode, } from "../../core/codex-fast-mode.js";
19
20
  import { configureHttpDispatcher } from "../../core/http-dispatcher.js";
20
21
  import { DefaultPackageManager } from "../../core/package-manager.js";
21
22
  import { BUILT_IN_PROVIDER_DISPLAY_NAMES } from "../../core/provider-display-names.js";
@@ -50,6 +51,7 @@ import { EarendilAnnouncementComponent } from "./components/earendil-announcemen
50
51
  import { ExtensionEditorComponent } from "./components/extension-editor.js";
51
52
  import { ExtensionInputComponent } from "./components/extension-input.js";
52
53
  import { ExtensionSelectorComponent } from "./components/extension-selector.js";
54
+ import { FastModeSelectorComponent } from "./components/fast-mode-selector.js";
53
55
  import { FooterComponent, UsageMeterComponent } from "./components/footer.js";
54
56
  import { formatKeyText, keyDisplayText, keyText, } from "./components/keybinding-hints.js";
55
57
  import { LoginDialogComponent } from "./components/login-dialog.js";
@@ -94,6 +96,7 @@ function isDeadTerminalError(error) {
94
96
  return code !== undefined && DEAD_TERMINAL_ERROR_CODES.has(code);
95
97
  }
96
98
  const ANTHROPIC_SUBSCRIPTION_AUTH_WARNING = "Anthropic subscription auth is active. Third-party harness usage draws from extra usage and is billed per token, not your Claude plan limits. Manage extra usage at https://claude.ai/settings/usage.";
99
+ const BUILTIN_SLASH_COMMAND_NAMES = new Set(BUILTIN_SLASH_COMMANDS.map((command) => command.name));
97
100
  function isAnthropicSubscriptionAuthKey(apiKey) {
98
101
  return typeof apiKey === "string" && apiKey.startsWith("sk-ant-oat");
99
102
  }
@@ -265,10 +268,9 @@ export class InteractiveMode {
265
268
  return description ? `[${sourceTag}] ${description}` : `[${sourceTag}]`;
266
269
  }
267
270
  getBuiltInCommandConflictDiagnostics(extensionRunner) {
268
- const builtinNames = new Set(BUILTIN_SLASH_COMMANDS.map((command) => command.name));
269
271
  return extensionRunner
270
272
  .getRegisteredCommands()
271
- .filter((command) => builtinNames.has(command.name))
273
+ .filter((command) => BUILTIN_SLASH_COMMAND_NAMES.has(command.name))
272
274
  .map((command) => ({
273
275
  type: "warning",
274
276
  message: command.invocationName === command.name
@@ -277,9 +279,20 @@ export class InteractiveMode {
277
279
  path: command.sourceInfo.path,
278
280
  }));
279
281
  }
282
+ getCodexFastModeCandidateModels() {
283
+ if (this.session.scopedModels.length > 0) {
284
+ return this.session.scopedModels
285
+ .map((scoped) => scoped.model)
286
+ .filter((model) => this.session.modelRegistry.hasConfiguredAuth(model));
287
+ }
288
+ return this.session.modelRegistry.getAvailable();
289
+ }
290
+ hasCodexFastModeSupportedModels() {
291
+ return hasSupportedCodexFastModeModel(this.getCodexFastModeCandidateModels());
292
+ }
280
293
  createBaseAutocompleteProvider() {
281
294
  // Define commands for autocomplete
282
- const slashCommands = BUILTIN_SLASH_COMMANDS.map((command) => ({
295
+ const slashCommands = BUILTIN_SLASH_COMMANDS.filter((command) => command.name !== "fast" || this.hasCodexFastModeSupportedModels()).map((command) => ({
283
296
  name: command.name,
284
297
  description: command.description,
285
298
  getArgumentCompletions: command.getArgumentCompletions,
@@ -316,11 +329,13 @@ export class InteractiveMode {
316
329
  description: this.prefixAutocompleteDescription(cmd.description, cmd.sourceInfo),
317
330
  ...(cmd.argumentHint && { argumentHint: cmd.argumentHint }),
318
331
  }));
319
- // Convert extension commands to SlashCommand format
320
- const builtinCommandNames = new Set(slashCommands.map((c) => c.name));
332
+ // Convert extension commands to SlashCommand format. Built-in command names
333
+ // stay reserved even when a built-in is contextually hidden (for example,
334
+ // /fast without a supported OpenAI model) so extension visibility cannot
335
+ // change as auth/model state changes.
321
336
  const extensionCommands = this.session.extensionRunner
322
337
  .getRegisteredCommands()
323
- .filter((cmd) => !builtinCommandNames.has(cmd.name))
338
+ .filter((cmd) => !BUILTIN_SLASH_COMMAND_NAMES.has(cmd.name))
324
339
  .map((cmd) => ({
325
340
  name: cmd.invocationName,
326
341
  description: this.prefixAutocompleteDescription(cmd.description, cmd.sourceInfo),
@@ -667,6 +682,18 @@ export class InteractiveMode {
667
682
  }
668
683
  return this.formatDisplayPath(absolutePath);
669
684
  }
685
+ getStartupModelLabel() {
686
+ const model = this.session.state.model;
687
+ let modelLabel = model?.id ?? "no-model";
688
+ if (model?.reasoning) {
689
+ modelLabel = `${modelLabel} ${this.session.thinkingLevel || "off"}`;
690
+ }
691
+ if (!model) {
692
+ return modelLabel;
693
+ }
694
+ const fastModeEnabled = shouldApplyCodexFastMode(model, this.session.settingsManager.getCodexFastModeSettings(), this.session.orchestrationContext);
695
+ return formatCodexFastModeModelLabel(modelLabel, fastModeEnabled);
696
+ }
670
697
  getStartupIdentityText() {
671
698
  const appLabel = APP_NAME.length > 0
672
699
  ? `${APP_NAME[0].toUpperCase()}${APP_NAME.slice(1)}`
@@ -674,8 +701,7 @@ export class InteractiveMode {
674
701
  const title = `${theme.bold(theme.fg("text", appLabel))} ${theme.fg("muted", `v${this.version}`)}`;
675
702
  const model = this.session.state.model;
676
703
  const provider = model ? theme.fg("dim", `(${model.provider})`) : theme.fg("dim", "(no-provider)");
677
- const thinking = model?.reasoning ? ` ${this.session.thinkingLevel || "off"}` : "";
678
- const modelLine = `${provider} ${theme.fg("muted", `${model?.id ?? "no-model"}${thinking}`)}`;
704
+ const modelLine = `${provider} ${theme.fg("muted", this.getStartupModelLabel())}`;
679
705
  const cwd = theme.fg("muted", this.formatDisplayPath(this.sessionManager.getCwd()));
680
706
  const metaLines = [title, modelLine, cwd];
681
707
  const markLines = this.getAtomicAnsiMarkLines();
@@ -1651,6 +1677,7 @@ export class InteractiveMode {
1651
1677
  confirm: (title, message, opts) => this.showExtensionConfirm(title, message, opts),
1652
1678
  input: (title, placeholder, opts) => this.showExtensionInput(title, placeholder, opts),
1653
1679
  notify: (message, type) => this.showExtensionNotify(message, type),
1680
+ requestRender: () => this.ui.requestRender(),
1654
1681
  onTerminalInput: (handler) => this.addExtensionTerminalInputListener(handler),
1655
1682
  setStatus: (key, text) => this.setExtensionStatus(key, text),
1656
1683
  setWorkingMessage: (message) => {
@@ -1923,16 +1950,8 @@ export class InteractiveMode {
1923
1950
  return new Promise((resolve, reject) => {
1924
1951
  let component;
1925
1952
  let closed = false;
1926
- const close = (result) => {
1927
- if (closed)
1928
- return;
1929
- closed = true;
1930
- if (isOverlay)
1931
- this.ui.hideOverlay();
1932
- else
1933
- restoreEditor();
1934
- // Note: both branches above already call requestRender
1935
- resolve(result);
1953
+ let mounted = false;
1954
+ const disposeComponent = () => {
1936
1955
  try {
1937
1956
  component?.dispose?.();
1938
1957
  }
@@ -1940,10 +1959,54 @@ export class InteractiveMode {
1940
1959
  /* ignore dispose errors */
1941
1960
  }
1942
1961
  };
1962
+ const cleanupAbortListener = () => {
1963
+ options?.signal?.removeEventListener("abort", abortCustomUi);
1964
+ };
1965
+ const closeMountedUi = () => {
1966
+ if (!mounted)
1967
+ return;
1968
+ if (isOverlay)
1969
+ this.ui.hideOverlay();
1970
+ else
1971
+ restoreEditor();
1972
+ };
1973
+ const close = (result) => {
1974
+ if (closed)
1975
+ return;
1976
+ closed = true;
1977
+ cleanupAbortListener();
1978
+ closeMountedUi();
1979
+ resolve(result);
1980
+ disposeComponent();
1981
+ };
1982
+ const rejectAndClose = (reason) => {
1983
+ if (closed)
1984
+ return;
1985
+ closed = true;
1986
+ cleanupAbortListener();
1987
+ closeMountedUi();
1988
+ disposeComponent();
1989
+ reject(reason);
1990
+ };
1991
+ function abortCustomUi() {
1992
+ rejectAndClose(options?.signal?.reason ?? new Error("Extension custom UI aborted"));
1993
+ }
1994
+ if (options?.signal?.aborted) {
1995
+ abortCustomUi();
1996
+ return;
1997
+ }
1998
+ options?.signal?.addEventListener("abort", abortCustomUi, { once: true });
1943
1999
  Promise.resolve(factory(this.ui, theme, this.keybindings, close))
1944
2000
  .then((c) => {
1945
- if (closed)
2001
+ if (closed) {
2002
+ try {
2003
+ c.dispose?.();
2004
+ }
2005
+ catch {
2006
+ /* ignore dispose errors */
2007
+ }
1946
2008
  return;
2009
+ }
1947
2010
  component = c;
1948
2011
  if (isOverlay) {
1949
2012
  // Resolve overlay options - can be static or dynamic function
@@ -1955,10 +2018,11 @@ export class InteractiveMode {
1955
2018
  return opts;
1956
2019
  }
1957
2020
  // Fallback: use component's width property if available
1958
- const w = component.width;
2021
+ const w = component?.width;
1959
2022
  return w ? { width: w } : undefined;
1960
2023
  };
1961
2024
  const handle = this.ui.showOverlay(component, resolveOptions());
2025
+ mounted = true;
1962
2026
  // Expose handle to caller for visibility control
1963
2027
  options?.onHandle?.(handle);
1964
2028
  }
@@ -1966,15 +2030,12 @@ export class InteractiveMode {
1966
2030
  this.editorContainer.clear();
1967
2031
  this.editorContainer.addChild(component);
1968
2032
  this.ui.setFocus(component);
2033
+ mounted = true;
1969
2034
  this.ui.requestRender();
1970
2035
  }
1971
2036
  })
1972
2037
  .catch((err) => {
1973
- if (closed)
1974
- return;
1975
- if (!isOverlay)
1976
- restoreEditor();
1977
- reject(err);
2038
+ rejectAndClose(err);
1978
2039
  });
1979
2040
  });
1980
2041
  }
@@ -2083,6 +2144,11 @@ export class InteractiveMode {
2083
2144
  this.editor.setText("");
2084
2145
  return;
2085
2146
  }
2147
+ if (text === "/fast") {
2148
+ this.editor.setText("");
2149
+ this.showFastModeSelector();
2150
+ return;
2151
+ }
2086
2152
  if (text === "/scoped-models") {
2087
2153
  this.editor.setText("");
2088
2154
  await this.showModelsSelector();
@@ -2379,11 +2445,13 @@ export class InteractiveMode {
2379
2445
  this.streamingMessage = event.message;
2380
2446
  let errorMessage;
2381
2447
  if (this.streamingMessage.stopReason === "aborted") {
2448
+ const existingAbortMessage = this.streamingMessage.errorMessage && this.streamingMessage.errorMessage !== "Request was aborted"
2449
+ ? this.streamingMessage.errorMessage
2450
+ : undefined;
2382
2451
  const retryAttempt = this.session.retryAttempt;
2383
- errorMessage =
2384
- retryAttempt > 0
2385
- ? `Aborted after ${retryAttempt} retry attempt${retryAttempt > 1 ? "s" : ""}`
2386
- : "Operation aborted";
2452
+ errorMessage = existingAbortMessage ?? (retryAttempt > 0
2453
+ ? `Aborted after ${retryAttempt} retry attempt${retryAttempt > 1 ? "s" : ""}`
2454
+ : "Operation aborted");
2387
2455
  this.streamingMessage.errorMessage = errorMessage;
2388
2456
  }
2389
2457
  this.streamingComponent.updateContent(this.streamingMessage);
@@ -2695,6 +2763,7 @@ export class InteractiveMode {
2695
2763
  }
2696
2764
  default: {
2697
2765
  const _exhaustive = message;
2766
+ void _exhaustive;
2698
2767
  }
2699
2768
  }
2700
2769
  }
@@ -3259,6 +3328,36 @@ export class InteractiveMode {
3259
3328
  this.ui.setFocus(focus);
3260
3329
  this.ui.requestRender();
3261
3330
  }
3331
+ showFastModeSelector() {
3332
+ if (!this.hasCodexFastModeSupportedModels()) {
3333
+ this.showWarning("Codex fast mode requires an available openai/* or openai-codex/* model.");
3334
+ return;
3335
+ }
3336
+ this.showSelector((done) => {
3337
+ let pendingStatusMessage;
3338
+ const selector = new FastModeSelectorComponent(this.settingsManager.getCodexFastModeSettings(), {
3339
+ onChange: (settings, changedRow) => {
3340
+ this.settingsManager.setCodexFastModeSettings({ [changedRow]: settings[changedRow] });
3341
+ const effectiveSettings = this.settingsManager.getCodexFastModeSettings();
3342
+ setCodexFastModeEnvironmentSettings(effectiveSettings);
3343
+ this.footer.invalidate();
3344
+ this.refreshBuiltInHeader();
3345
+ const changedLabel = changedRow === "chat" ? "Chat" : "Workflow";
3346
+ const changedState = effectiveSettings[changedRow] ? "on" : "off";
3347
+ pendingStatusMessage = `${changedLabel} fast mode ${changedState}`;
3348
+ },
3349
+ onCancel: async () => {
3350
+ await this.settingsManager.flush();
3351
+ done();
3352
+ if (pendingStatusMessage) {
3353
+ this.showStatus(pendingStatusMessage);
3354
+ }
3355
+ this.ui.requestRender();
3356
+ },
3357
+ });
3358
+ return { component: selector, focus: selector };
3359
+ });
3360
+ }
3262
3361
  showSettingsSelector() {
3263
3362
  this.showSelector((done) => {
3264
3363
  const selector = new SettingsSelectorComponent({
@@ -3554,6 +3653,7 @@ export class InteractiveMode {
3554
3653
  this.session.setScopedModels([]);
3555
3654
  }
3556
3655
  await this.updateAvailableProviderCount();
3656
+ this.setupAutocompleteProvider();
3557
3657
  this.ui.requestRender();
3558
3658
  };
3559
3659
  this.showSelector((done) => {
@@ -3900,6 +4000,7 @@ export class InteractiveMode {
3900
4000
  this.session.modelRegistry.authStorage.logout(providerOption.id);
3901
4001
  this.session.modelRegistry.refresh();
3902
4002
  await this.updateAvailableProviderCount();
4003
+ this.setupAutocompleteProvider();
3903
4004
  const message = providerOption.authType === "oauth"
3904
4005
  ? `Logged out of ${providerOption.name}`
3905
4006
  : `Removed stored API key for ${providerOption.name}. Environment variables and models.json config are unchanged.`;
@@ -3950,6 +4051,7 @@ export class InteractiveMode {
3950
4051
  }
3951
4052
  }
3952
4053
  await this.updateAvailableProviderCount();
4054
+ this.setupAutocompleteProvider();
3953
4055
  this.footer.invalidate();
3954
4056
  this.updateEditorBorderColor();
3955
4057
  if (selectedModel) {