mixdog 0.9.147 → 0.9.149
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.
- package/package.json +23 -3
- package/scripts/build-voice-runtime-unix.sh +101 -0
- package/scripts/embedding-quality-probe.mjs +96 -0
- package/scripts/generate-voice-runtime-manifest.mjs +300 -0
- package/scripts/generate-voice-runtime-manifest.test.mjs +135 -0
- package/scripts/native-binary-arch.mjs +30 -13
- package/scripts/native-binary-arch.test.mjs +40 -4
- package/scripts/plan-voice-runtime-release.mjs +73 -0
- package/scripts/prepare-native-assets.mjs +50 -9
- package/scripts/prune-embedding-runtime.mjs +3 -3
- package/scripts/sync-voice-runtime-manifest.mjs +46 -0
- package/scripts/verify-release-assets.mjs +106 -6
- package/scripts/verify-voice-runtime-release.mjs +89 -0
- package/scripts/voice-runtime-config.json +52 -0
- package/src/app.mjs +42 -5
- package/src/headless-exec.mjs +58 -32
- package/src/headless-exec.test.mjs +74 -13
- package/src/rules/lead/01-general.md +2 -0
- package/src/rules/shared/10-tool-workflow.md +7 -4
- package/src/rules/shared/30-exploration.md +5 -1
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +28 -9
- package/src/runtime/agent/orchestrator/agent-trace-format.mjs +6 -1
- package/src/runtime/agent/orchestrator/config.mjs +53 -18
- package/src/runtime/agent/orchestrator/mcp/cancellation.test.mjs +139 -0
- package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +34 -5
- package/src/runtime/agent/orchestrator/mcp/client.mjs +94 -10
- package/src/runtime/agent/orchestrator/providers/anthropic-betas.mjs +5 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-fast-mode.mjs +98 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-fast-mode.test.mjs +90 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-leaked-toolcall.mjs +67 -16
- package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +4 -82
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +0 -5
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +62 -121
- package/src/runtime/agent/orchestrator/providers/anthropic-server-fallback.mjs +48 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-server-fallback.test.mjs +215 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +44 -48
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +54 -31
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +56 -2
- package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +34 -2
- package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +61 -1
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +6 -1
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +61 -15
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +120 -1
- package/src/runtime/agent/orchestrator/providers/lib/env-utils.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/lib/stream-outcome.mjs +0 -3
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +187 -84
- package/src/runtime/agent/orchestrator/providers/openai-codex-identity.test.mjs +32 -9
- package/src/runtime/agent/orchestrator/providers/openai-codex-metadata.mjs +78 -33
- package/src/runtime/agent/orchestrator/providers/openai-codex-model.mjs +21 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +36 -36
- package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +16 -6
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +50 -213
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +135 -126
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +20 -11
- package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +112 -36
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +220 -50
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +112 -9
- package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +11 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-pool.mjs +130 -60
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +28 -10
- package/src/runtime/agent/orchestrator/providers/registry.mjs +122 -95
- package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +69 -3
- package/src/runtime/agent/orchestrator/providers/tool-stream-state.mjs +4 -22
- package/src/runtime/agent/orchestrator/session/agent-loop.mjs +7 -14
- package/src/runtime/agent/orchestrator/session/compact-policy.test.mjs +128 -0
- package/src/runtime/agent/orchestrator/session/context-compaction-policy.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +27 -48
- package/src/runtime/agent/orchestrator/session/loop/steering.mjs +19 -14
- package/src/runtime/agent/orchestrator/session/loop/stored-tool-args.mjs +9 -43
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +5 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +43 -5
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +15 -2
- package/src/runtime/agent/orchestrator/session/manager/pending-messages-persistence.test.mjs +325 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +599 -195
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +22 -0
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +9 -2
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +26 -16
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +23 -11
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +118 -3
- package/src/runtime/agent/orchestrator/session/store-summary-reader.test.mjs +332 -0
- package/src/runtime/agent/orchestrator/session/store.mjs +38 -1
- package/src/runtime/agent/orchestrator/tools/builtin/advisory-lock.mjs +27 -6
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +12 -20
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +291 -128
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +46 -9
- package/src/runtime/agent/orchestrator/tools/builtin/edit-encoding-eol.test.mjs +224 -0
- package/src/runtime/agent/orchestrator/tools/builtin/edit-sequential-occupation.test.mjs +53 -3
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +255 -25
- package/src/runtime/agent/orchestrator/tools/builtin/find-search-budget.test.mjs +87 -0
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-policy.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +132 -9
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.test.mjs +10 -0
- package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-pattern-fanout.mjs +29 -3
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/list-tool-integrity.test.mjs +14 -0
- package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +180 -31
- package/src/runtime/agent/orchestrator/tools/builtin/local-search-telemetry.mjs +4 -1
- package/src/runtime/agent/orchestrator/tools/builtin/native-search-client.mjs +32 -5
- package/src/runtime/agent/orchestrator/tools/builtin/native-search-health.test.mjs +5 -2
- package/src/runtime/agent/orchestrator/tools/builtin/native-search-runner.mjs +10 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-batch.mjs +38 -10
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +12 -0
- package/src/runtime/agent/orchestrator/tools/builtin/read-snapshot-runtime.mjs +31 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +11 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-windows.mjs +22 -4
- package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +6 -8
- package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +25 -24
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +152 -133
- package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +114 -42
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +129 -15
- package/src/runtime/agent/orchestrator/tools/code-graph/loose-file-target.test.mjs +72 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/project-root.mjs +7 -8
- package/src/runtime/agent/orchestrator/tools/code-graph/search-references.mjs +4 -4
- package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +201 -19
- package/src/runtime/agent/orchestrator/tools/code-graph/span.mjs +26 -3
- package/src/runtime/agent/orchestrator/tools/code-graph/symbol-index.mjs +10 -1
- package/src/runtime/agent/orchestrator/tools/code-graph/symbol-search-scope.test.mjs +55 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/text-mask.mjs +115 -25
- package/src/runtime/agent/orchestrator/tools/code-graph/text-span-mask.test.mjs +268 -0
- package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +3 -3
- package/src/runtime/agent/orchestrator/tools/lib/native-spawn-client.mjs +296 -46
- package/src/runtime/agent/orchestrator/tools/lib/native-spawn-client.test.mjs +104 -0
- package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +136 -0
- package/src/runtime/agent/orchestrator/tools/patch/dispatch.mjs +127 -38
- package/src/runtime/agent/orchestrator/tools/patch/engine-contract-gate.test.mjs +661 -0
- package/src/runtime/agent/orchestrator/tools/patch/matcher.mjs +350 -9
- package/src/runtime/agent/orchestrator/tools/patch/native-server.mjs +418 -44
- package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +27 -3
- package/src/runtime/agent/orchestrator/tools/patch/patch-codec-eol.test.mjs +552 -0
- package/src/runtime/agent/orchestrator/tools/patch/v4a-convert.mjs +65 -15
- package/src/runtime/agent/orchestrator/tools/patch-manifest.json +11 -11
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +284 -109
- package/src/runtime/agent/orchestrator/tools/shell-exec-output.mjs +51 -21
- package/src/runtime/agent/orchestrator/tools/shell-exec-policy.mjs +44 -27
- package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +6 -1
- package/src/runtime/agent/orchestrator/tools/spawn-manifest.json +11 -11
- package/src/runtime/attachments/store.mjs +11 -3
- package/src/runtime/channels/data/voice-runtime-manifest.json +46 -70
- package/src/runtime/channels/lib/event-queue.mjs +51 -41
- package/src/runtime/channels/lib/scheduler.mjs +23 -28
- package/src/runtime/channels/lib/voice-runtime-fetcher.mjs +6 -17
- package/src/runtime/channels/lib/voice-runtime-fetcher.test.mjs +17 -0
- package/src/runtime/channels/lib/webhook.mjs +39 -20
- package/src/runtime/channels/lib/whisper-server.mjs +46 -1
- package/src/runtime/channels/lib/worker-main.mjs +3 -1
- package/src/runtime/media/adapters/gemini-video.mjs +20 -4
- package/src/runtime/media/jobs.mjs +13 -0
- package/src/runtime/media/renditions.mjs +7 -1
- package/src/runtime/media/store.mjs +42 -22
- package/src/runtime/memory/index.mjs +4 -9
- package/src/runtime/memory/lib/agent-ipc.mjs +1 -6
- package/src/runtime/memory/lib/archive-security.test.mjs +21 -1
- package/src/runtime/memory/lib/core-memory-store.mjs +28 -50
- package/src/runtime/memory/lib/embedding-model-config.mjs +37 -1
- package/src/runtime/memory/lib/embedding-model-config.test.mjs +33 -0
- package/src/runtime/memory/lib/embedding-provider.mjs +34 -12
- package/src/runtime/memory/lib/embedding-worker.mjs +37 -5
- package/src/runtime/memory/lib/ko-morph.mjs +46 -15
- package/src/runtime/memory/lib/memory-action-handlers.mjs +18 -1
- package/src/runtime/memory/lib/memory-cycle1.mjs +1 -18
- package/src/runtime/memory/lib/memory-cycle2-gate.mjs +1 -18
- package/src/runtime/memory/lib/memory-cycle2-mutations.mjs +98 -45
- package/src/runtime/memory/lib/memory-cycle2-shared.mjs +71 -0
- package/src/runtime/memory/lib/memory-cycle2-shared.test.mjs +78 -0
- package/src/runtime/memory/lib/memory-cycle2.mjs +37 -3
- package/src/runtime/memory/lib/memory-cycle3.mjs +1 -1
- package/src/runtime/memory/lib/memory-embedding-migration.test.mjs +50 -0
- package/src/runtime/memory/lib/memory-recall-store.mjs +9 -24
- package/src/runtime/memory/lib/memory.mjs +50 -12
- package/src/runtime/memory/lib/pg/process.mjs +1 -10
- package/src/runtime/memory/lib/pg/supervisor.mjs +1 -9
- package/src/runtime/memory/lib/query-handlers.mjs +2 -4
- package/src/runtime/memory/lib/session-ingest-runtime.mjs +2 -2
- package/src/runtime/shared/background-tasks.mjs +15 -0
- package/src/runtime/shared/background-tasks.test.mjs +78 -0
- package/src/runtime/shared/child-guardian.mjs +2 -10
- package/src/runtime/shared/pid-liveness.mjs +27 -0
- package/src/runtime/shared/pristine-execution-contract.json +0 -1
- package/src/runtime/shared/runtime-root.mjs +1 -11
- package/src/runtime/shared/service-discovery.mjs +1 -17
- package/src/runtime/shared/singleton-owner.mjs +1 -11
- package/src/runtime/shared/staged-update.mjs +2 -12
- package/src/runtime/shared/tool-status.mjs +5 -1
- package/src/runtime/shared/tool-surface.mjs +15 -7
- package/src/runtime/shared/turn-snapshot-store.mjs +168 -0
- package/src/runtime/shared/turn-snapshot.mjs +137 -13
- package/src/runtime/shared/turn-worktree-snapshot.mjs +110 -18
- package/src/runtime/shared/webhook-session-run.mjs +16 -2
- package/src/runtime/web-search/lib/http-fetch.mjs +34 -4
- package/src/runtime/web-search/lib/state.mjs +15 -15
- package/src/runtime/web-search/lib/web-tools.mjs +46 -5
- package/src/session-runtime/context-status.mjs +4 -12
- package/src/session-runtime/runtime-core.mjs +20 -1
- package/src/session-runtime/session-lifecycle.mjs +9 -0
- package/src/standalone/agent-dispatch-broker.mjs +33 -2
- package/src/standalone/agent-tool/job-task-reconcile.mjs +78 -0
- package/src/standalone/agent-tool/notify.mjs +3 -1
- package/src/standalone/agent-tool/spawn-flow.mjs +52 -70
- package/src/standalone/agent-tool/tag-registry.mjs +116 -33
- package/src/standalone/agent-tool/tool-def.mjs +2 -2
- package/src/standalone/agent-tool/worker-index.mjs +8 -11
- package/src/standalone/agent-tool/worker-rows.mjs +4 -1
- package/src/standalone/agent-tool.mjs +20 -55
- package/src/standalone/agent-watchdog-registry.mjs +28 -4
- package/src/standalone/channel-client.mjs +47 -15
- package/src/standalone/channel-transport.mjs +44 -25
- package/src/standalone/daemon.mjs +31 -2
- package/src/standalone/hook-bus/config.mjs +25 -9
- package/src/standalone/hook-bus/handlers.mjs +16 -52
- package/src/standalone/hook-bus.mjs +29 -23
- package/src/standalone/memory-runtime-proxy.mjs +1 -16
- package/src/standalone/session-client.mjs +86 -23
- package/src/standalone/session-protocol.mjs +0 -2
- package/src/standalone/session-runtime-host-health.test.mjs +5 -4
- package/src/standalone/session-runtime-host.mjs +101 -6
- package/src/standalone/session-runtime-record.mjs +1 -5
- package/src/standalone/session-runtime-worker.mjs +52 -57
- package/src/standalone/session-service.mjs +4 -1
- package/src/standalone/session-transport.mjs +56 -25
- package/src/tui/App.jsx +40 -49
- package/src/tui/app/app-view.jsx +14 -21
- package/src/tui/app/core-memory-picker.mjs +29 -16
- package/src/tui/app/create-app-pickers.mjs +15 -36
- package/src/tui/app/extension-pickers.mjs +60 -49
- package/src/tui/app/maintenance-pickers.mjs +100 -57
- package/src/tui/app/message-selector.mjs +6 -5
- package/src/tui/app/model-picker.mjs +30 -13
- package/src/tui/app/onboarding-steps.mjs +21 -12
- package/src/tui/app/panel-epoch.mjs +56 -0
- package/src/tui/app/panel-epoch.test.mjs +1009 -0
- package/src/tui/app/panel-surface.mjs +98 -0
- package/src/tui/app/project-picker.mjs +30 -29
- package/src/tui/app/prompt-submit.mjs +192 -97
- package/src/tui/app/prompt-submit.test.mjs +206 -0
- package/src/tui/app/provider-setup-picker.mjs +74 -43
- package/src/tui/app/resume-picker.mjs +11 -8
- package/src/tui/app/route-pickers.mjs +45 -28
- package/src/tui/app/settings-picker.mjs +69 -18
- package/src/tui/app/shell-layout.mjs +1 -3
- package/src/tui/app/slash-commands.mjs +0 -2
- package/src/tui/app/slash-dispatch.mjs +4 -2
- package/src/tui/app/text-entry-policy.mjs +25 -0
- package/src/tui/app/theme-effort-pickers.mjs +11 -16
- package/src/tui/app/usage-context-panels.mjs +21 -25
- package/src/tui/app/use-global-key-input.mjs +3 -2
- package/src/tui/app/use-prompt-draft-flow.mjs +6 -18
- package/src/tui/app/use-prompt-handlers.mjs +3 -2
- package/src/tui/app/use-welcome-prompt-hint.mjs +17 -3
- package/src/tui/components/Picker.jsx +1 -1
- package/src/tui/components/TextEntryPanel.jsx +7 -2
- package/src/tui/dist/index.mjs +652 -561
- package/src/tui/lib/voice-setup.mjs +1 -2
- package/src/tui/session/agent-job-feed.mjs +73 -11
- package/src/tui/session/session-api-ext.mjs +5 -6
- package/src/tui/session/session-api.mjs +1 -0
- package/src/tui/session/tool-approval.mjs +15 -5
- package/src/tui/session/tui-steering-persist.mjs +33 -19
- package/src/tui/session/tui-steering-persist.test.mjs +104 -0
- package/src/tui/session-local.mjs +0 -22
- package/scripts/.tmp-coverage-report.mjs +0 -96
- package/src/runtime/agent/orchestrator/tools/builtin/shell-monitor.mjs +0 -57
- package/src/runtime/agent/orchestrator/tools/builtin/shell-monitor.test.mjs +0 -57
|
@@ -19,12 +19,9 @@ import { providerDisplayRank } from './model-options.mjs';
|
|
|
19
19
|
|
|
20
20
|
export function createProviderSetupPicker({
|
|
21
21
|
store,
|
|
22
|
-
|
|
22
|
+
surface,
|
|
23
23
|
setProviderPrompt,
|
|
24
|
-
setChannelPrompt,
|
|
25
|
-
setHookPrompt,
|
|
26
24
|
setSettingsPrompt,
|
|
27
|
-
setContextPanel,
|
|
28
25
|
closeUsagePanel,
|
|
29
26
|
oauthSubmitRef,
|
|
30
27
|
clearModelCaches,
|
|
@@ -33,25 +30,34 @@ export function createProviderSetupPicker({
|
|
|
33
30
|
const returnTo = typeof options.returnTo === 'function' ? options.returnTo : null;
|
|
34
31
|
const onContinue = typeof options.onContinue === 'function' ? options.onContinue : returnTo;
|
|
35
32
|
const onCancel = typeof options.onCancel === 'function' ? options.onCancel : null;
|
|
33
|
+
// ONE claim (panel-surface.mjs) per open, shared by the nested action /
|
|
34
|
+
// progress / result panels: every paint re-validates and re-arms it, so a
|
|
35
|
+
// daemon ack (key removal, OAuth callback, usage login) landing after Esc
|
|
36
|
+
// can neither paint nor navigate.
|
|
37
|
+
const own = surface.claim();
|
|
36
38
|
setProviderPrompt(null);
|
|
37
|
-
setChannelPrompt(null);
|
|
38
|
-
setHookPrompt(null);
|
|
39
39
|
setSettingsPrompt(null);
|
|
40
40
|
// Close full-panel overlays too: they render ahead of providerPrompt in
|
|
41
41
|
// the floating-panel chain, so a lingering usage/context panel would mask
|
|
42
42
|
// any text-entry prompt opened from the provider actions (e.g. the
|
|
43
43
|
// OpenCode Go cookie prompt appeared to do nothing).
|
|
44
|
-
|
|
44
|
+
own.context(null);
|
|
45
45
|
closeUsagePanel();
|
|
46
46
|
// Onboarding (and any caller) can pass a preloaded provider setup so we skip
|
|
47
47
|
// the "Checking Providers" placeholder frame that otherwise flashes before
|
|
48
48
|
// the real list — that swap is what looked like a jump on Step 1 entry.
|
|
49
|
+
const ownsSurface = () => own.owns();
|
|
50
|
+
const paintProviders = (panel) => own.paint(panel);
|
|
51
|
+
// The flow itself handing the picker surface to a prompt (Enter on a row):
|
|
52
|
+
// still ours, so clear-and-continue instead of going stale. Esc paths use
|
|
53
|
+
// own.close() — leaving IS the handover.
|
|
54
|
+
const releaseSurface = () => own.paint(null);
|
|
49
55
|
let setup = options.preloadedSetup && typeof options.preloadedSetup === 'object'
|
|
50
56
|
? options.preloadedSetup
|
|
51
57
|
: null;
|
|
52
58
|
options.preloadedSetup = null;
|
|
53
59
|
if (!setup) {
|
|
54
|
-
|
|
60
|
+
paintProviders({
|
|
55
61
|
title: options.title || 'Providers',
|
|
56
62
|
description: options.description || 'Choose a provider to configure.',
|
|
57
63
|
labelWidth: 18,
|
|
@@ -67,7 +73,7 @@ export function createProviderSetupPicker({
|
|
|
67
73
|
}],
|
|
68
74
|
onSelect: () => {},
|
|
69
75
|
onCancel: () => {
|
|
70
|
-
|
|
76
|
+
own.close();
|
|
71
77
|
if (onCancel) onCancel();
|
|
72
78
|
},
|
|
73
79
|
});
|
|
@@ -170,7 +176,11 @@ export function createProviderSetupPicker({
|
|
|
170
176
|
};
|
|
171
177
|
|
|
172
178
|
const reopenProviders = () => {
|
|
173
|
-
|
|
179
|
+
// Reached from acks as well as key presses: a stale ack must not restart
|
|
180
|
+
// the whole cluster over the user's surface.
|
|
181
|
+
if (!ownsSurface()) return;
|
|
182
|
+
void Promise.resolve(openProviderSetupPicker(options))
|
|
183
|
+
.catch((e) => store.pushNotice(`providers failed: ${e?.message || e}`, 'error'));
|
|
174
184
|
};
|
|
175
185
|
const providerActionFooter = (provider) => provider ? [{
|
|
176
186
|
glyph: providerIsActive(provider) ? '●' : '○',
|
|
@@ -178,6 +188,7 @@ export function createProviderSetupPicker({
|
|
|
178
188
|
text: [providerKindLabel(provider), providerStatusLabel(provider), providerDetailText(provider)].filter(Boolean).join(' · '),
|
|
179
189
|
}] : '';
|
|
180
190
|
const setApiKeyPrompt = (providerItem) => {
|
|
191
|
+
if (!ownsSurface()) return;
|
|
181
192
|
setProviderPrompt({
|
|
182
193
|
kind: 'api-key',
|
|
183
194
|
providerId: providerItem._providerId,
|
|
@@ -189,6 +200,9 @@ export function createProviderSetupPicker({
|
|
|
189
200
|
});
|
|
190
201
|
};
|
|
191
202
|
const openApiProviderActions = (providerItem) => {
|
|
203
|
+
// Reached from acks (forget-key failure, usage-login back-out) as well as
|
|
204
|
+
// key presses: prove ownership at the sink so every caller is covered.
|
|
205
|
+
if (!ownsSurface()) return;
|
|
192
206
|
rememberProviderSelection(providerItem);
|
|
193
207
|
const provider = providerItem._provider || {};
|
|
194
208
|
const hasAuth = providerItem._authenticated || provider.authenticated;
|
|
@@ -216,7 +230,7 @@ export function createProviderSetupPicker({
|
|
|
216
230
|
_action: 'usage-login-browser',
|
|
217
231
|
});
|
|
218
232
|
}
|
|
219
|
-
|
|
233
|
+
paintProviders({
|
|
220
234
|
title: `Provider · ${providerItem._providerName}`,
|
|
221
235
|
description: 'Choose an API-key action.',
|
|
222
236
|
footer: () => providerActionFooter(provider),
|
|
@@ -227,19 +241,23 @@ export function createProviderSetupPicker({
|
|
|
227
241
|
initialIndex: 0,
|
|
228
242
|
items: apiActions,
|
|
229
243
|
onSelect: (_detailValue, detail) => {
|
|
230
|
-
|
|
244
|
+
releaseSurface();
|
|
231
245
|
if (detail._action === 'set-key') {
|
|
232
246
|
setApiKeyPrompt(providerItem);
|
|
233
247
|
return;
|
|
234
248
|
}
|
|
235
249
|
if (detail._action === 'forget-key') {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
250
|
+
// Daemon RPC: only navigate once the removal is acknowledged, and
|
|
251
|
+
// return to these actions (not an empty panel) when it fails.
|
|
252
|
+
void Promise.resolve(store.forgetProviderAuth?.(providerItem._providerId))
|
|
253
|
+
.then(() => {
|
|
254
|
+
clearModelCaches('all');
|
|
255
|
+
reopenProviders();
|
|
256
|
+
})
|
|
257
|
+
.catch((e) => {
|
|
258
|
+
store.pushNotice(`auth-forget failed: ${e?.message || e}`, 'error');
|
|
259
|
+
openApiProviderActions(providerItem);
|
|
260
|
+
});
|
|
243
261
|
}
|
|
244
262
|
if (detail._action === 'usage-login-browser') {
|
|
245
263
|
let backedOut = false;
|
|
@@ -259,7 +277,7 @@ export function createProviderSetupPicker({
|
|
|
259
277
|
_action: 'back',
|
|
260
278
|
},
|
|
261
279
|
];
|
|
262
|
-
|
|
280
|
+
paintProviders({
|
|
263
281
|
title: `Provider · ${providerItem._providerName}`,
|
|
264
282
|
description: 'Opening browser. Sign in at opencode.ai/auth; the auth cookie is captured automatically.',
|
|
265
283
|
footer: () => providerActionFooter(provider),
|
|
@@ -317,7 +335,7 @@ export function createProviderSetupPicker({
|
|
|
317
335
|
_action: 'back',
|
|
318
336
|
},
|
|
319
337
|
];
|
|
320
|
-
|
|
338
|
+
paintProviders({
|
|
321
339
|
title: `Provider · ${providerItem._providerName}`,
|
|
322
340
|
description: message,
|
|
323
341
|
footer: () => providerActionFooter(provider),
|
|
@@ -336,7 +354,7 @@ export function createProviderSetupPicker({
|
|
|
336
354
|
};
|
|
337
355
|
const showOAuthResult = (ok, message = '') => {
|
|
338
356
|
setProviderPrompt(null);
|
|
339
|
-
|
|
357
|
+
paintProviders({
|
|
340
358
|
title: `Provider · ${providerItem._providerName}`,
|
|
341
359
|
description: message || (ok ? 'Login complete.' : 'Login did not complete.'),
|
|
342
360
|
footer: () => providerActionFooter(provider),
|
|
@@ -386,7 +404,10 @@ export function createProviderSetupPicker({
|
|
|
386
404
|
void store.beginOAuthProviderLogin(providerItem._providerId)
|
|
387
405
|
.then((login) => {
|
|
388
406
|
if (typeof login?.completeCode === 'function') {
|
|
389
|
-
|
|
407
|
+
// Post-await handover to the OAuth code prompt: only if this flow
|
|
408
|
+
// still owns the surface (Esc during beginOAuthProviderLogin).
|
|
409
|
+
if (!ownsSurface()) return;
|
|
410
|
+
releaseSurface();
|
|
390
411
|
const manualUrl = login?.manualUrl || '';
|
|
391
412
|
setProviderPrompt({
|
|
392
413
|
kind: 'oauth-code',
|
|
@@ -445,6 +466,7 @@ export function createProviderSetupPicker({
|
|
|
445
466
|
});
|
|
446
467
|
};
|
|
447
468
|
const openOAuthProviderActions = (providerItem) => {
|
|
469
|
+
if (!ownsSurface()) return;
|
|
448
470
|
rememberProviderSelection(providerItem);
|
|
449
471
|
const provider = providerItem._provider || {};
|
|
450
472
|
const hasAuth = providerItem._authenticated || provider.authenticated || provider.reauthRequired === true;
|
|
@@ -463,7 +485,7 @@ export function createProviderSetupPicker({
|
|
|
463
485
|
_action: 'forget-oauth',
|
|
464
486
|
});
|
|
465
487
|
}
|
|
466
|
-
|
|
488
|
+
paintProviders({
|
|
467
489
|
title: `Provider · ${providerItem._providerName}`,
|
|
468
490
|
description: 'Choose an OAuth login action.',
|
|
469
491
|
footer: () => providerActionFooter(provider),
|
|
@@ -479,13 +501,15 @@ export function createProviderSetupPicker({
|
|
|
479
501
|
return;
|
|
480
502
|
}
|
|
481
503
|
if (detail._action === 'forget-oauth') {
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
504
|
+
void Promise.resolve(store.forgetProviderAuth?.(providerItem._providerId))
|
|
505
|
+
.then(() => {
|
|
506
|
+
clearModelCaches('all');
|
|
507
|
+
reopenProviders();
|
|
508
|
+
})
|
|
509
|
+
.catch((e) => {
|
|
510
|
+
store.pushNotice(`auth-forget failed: ${e?.message || e}`, 'error');
|
|
511
|
+
openOAuthProviderActions(providerItem);
|
|
512
|
+
});
|
|
489
513
|
}
|
|
490
514
|
},
|
|
491
515
|
onCancel: reopenProviders,
|
|
@@ -493,6 +517,7 @@ export function createProviderSetupPicker({
|
|
|
493
517
|
};
|
|
494
518
|
|
|
495
519
|
const openLocalProviderActions = (providerItem) => {
|
|
520
|
+
if (!ownsSurface()) return;
|
|
496
521
|
rememberProviderSelection(providerItem);
|
|
497
522
|
const provider = providerItem._provider || {};
|
|
498
523
|
const localActions = [
|
|
@@ -511,7 +536,7 @@ export function createProviderSetupPicker({
|
|
|
511
536
|
_action: 'disable-local',
|
|
512
537
|
});
|
|
513
538
|
}
|
|
514
|
-
|
|
539
|
+
paintProviders({
|
|
515
540
|
title: `Provider · ${providerItem._providerName}`,
|
|
516
541
|
description: 'Choose a local endpoint action.',
|
|
517
542
|
footer: () => providerActionFooter(provider),
|
|
@@ -522,7 +547,7 @@ export function createProviderSetupPicker({
|
|
|
522
547
|
initialIndex: 0,
|
|
523
548
|
items: localActions,
|
|
524
549
|
onSelect: (_detailValue, detail) => {
|
|
525
|
-
|
|
550
|
+
releaseSurface();
|
|
526
551
|
if (detail._action === 'set-local-url') {
|
|
527
552
|
setProviderPrompt({
|
|
528
553
|
kind: 'local-url',
|
|
@@ -534,20 +559,22 @@ export function createProviderSetupPicker({
|
|
|
534
559
|
return;
|
|
535
560
|
}
|
|
536
561
|
if (detail._action === 'disable-local') {
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
562
|
+
void Promise.resolve(store.setLocalProvider?.(providerItem._providerId, { enabled: false, baseURL: providerItem._baseURL }))
|
|
563
|
+
.then(() => {
|
|
564
|
+
clearModelCaches('all');
|
|
565
|
+
reopenProviders();
|
|
566
|
+
})
|
|
567
|
+
.catch((e) => {
|
|
568
|
+
store.pushNotice(`local provider update failed: ${e?.message || e}`, 'error');
|
|
569
|
+
openLocalProviderActions(providerItem);
|
|
570
|
+
});
|
|
544
571
|
}
|
|
545
572
|
},
|
|
546
573
|
onCancel: reopenProviders,
|
|
547
574
|
});
|
|
548
575
|
};
|
|
549
576
|
|
|
550
|
-
|
|
577
|
+
paintProviders({
|
|
551
578
|
title: options.title || 'Providers',
|
|
552
579
|
description: options.description || 'Choose a provider. Enter opens provider actions.',
|
|
553
580
|
footer: providerFooter,
|
|
@@ -564,7 +591,11 @@ export function createProviderSetupPicker({
|
|
|
564
591
|
if (item?._providerId) rememberProviderSelection(item);
|
|
565
592
|
},
|
|
566
593
|
onSelect: (_value, item) => {
|
|
567
|
-
|
|
594
|
+
// In-flow navigation (Enter on a provider row): the flow keeps the
|
|
595
|
+
// surface, so clear-and-continue — own.close() would supersede this
|
|
596
|
+
// very flow and paintProviders would then reject the action panel the
|
|
597
|
+
// user just asked for. Esc (onCancel below) does close.
|
|
598
|
+
releaseSurface();
|
|
568
599
|
if (item._type === 'continue') {
|
|
569
600
|
onContinue?.();
|
|
570
601
|
return;
|
|
@@ -582,7 +613,7 @@ export function createProviderSetupPicker({
|
|
|
582
613
|
}
|
|
583
614
|
},
|
|
584
615
|
onCancel: () => {
|
|
585
|
-
|
|
616
|
+
own.close();
|
|
586
617
|
if (onCancel) onCancel();
|
|
587
618
|
else if (returnTo) returnTo();
|
|
588
619
|
},
|
|
@@ -2,18 +2,21 @@
|
|
|
2
2
|
* resume-picker.mjs — the /resume saved-chat session picker.
|
|
3
3
|
*
|
|
4
4
|
* Extracted from App.jsx behavior-preservingly as a dependency-injection
|
|
5
|
-
* factory: openResumePicker drives
|
|
6
|
-
* can't be pure. The function body is the original App logic
|
|
7
|
-
* closure identifiers (store,
|
|
8
|
-
* projects.mjs) threaded in through the factory argument.
|
|
5
|
+
* factory: openResumePicker drives the panel surface and reads live store
|
|
6
|
+
* state, so it can't be pure. The function body is the original App logic
|
|
7
|
+
* verbatim, with closure identifiers (store, surface, and the two session
|
|
8
|
+
* formatters from projects.mjs) threaded in through the factory argument.
|
|
9
9
|
*/
|
|
10
10
|
export function createResumePicker({
|
|
11
11
|
store,
|
|
12
|
-
|
|
12
|
+
surface,
|
|
13
13
|
formatSessionUpdatedAt,
|
|
14
14
|
formatSessionMessageCount,
|
|
15
15
|
}) {
|
|
16
16
|
const openResumePicker = async () => {
|
|
17
|
+
// Surface claim (panel-surface.mjs): the storage rescan below is slow, so
|
|
18
|
+
// Esc can easily land before this panel ever paints.
|
|
19
|
+
const own = surface.claim();
|
|
17
20
|
let sessions;
|
|
18
21
|
try {
|
|
19
22
|
// Terminal ↔ desktop interop: the summary cache is per-process, so a
|
|
@@ -39,13 +42,13 @@ export function createResumePicker({
|
|
|
39
42
|
description: title || preview || '(no message)',
|
|
40
43
|
};
|
|
41
44
|
});
|
|
42
|
-
|
|
45
|
+
own.paint({
|
|
43
46
|
title: 'Resume',
|
|
44
47
|
description: 'Restore a saved chat session.',
|
|
45
48
|
items,
|
|
46
49
|
labelWidth: 21,
|
|
47
50
|
onSelect: (value) => {
|
|
48
|
-
|
|
51
|
+
own.close();
|
|
49
52
|
const selected = sessions.find((session) => session.id === value);
|
|
50
53
|
const resumedName = String(selected?.title || selected?.preview || value)
|
|
51
54
|
.replace(/\s+/g, ' ')
|
|
@@ -55,7 +58,7 @@ export function createResumePicker({
|
|
|
55
58
|
.catch((e) => store.pushNotice(`Couldn’t resume chat: ${e?.message || e}`, 'error'));
|
|
56
59
|
},
|
|
57
60
|
onCancel: () => {
|
|
58
|
-
|
|
61
|
+
own.close();
|
|
59
62
|
},
|
|
60
63
|
});
|
|
61
64
|
};
|
|
@@ -19,12 +19,9 @@ export const outputStyleNotice = (result) => {
|
|
|
19
19
|
export function createRoutePickers({
|
|
20
20
|
store,
|
|
21
21
|
state,
|
|
22
|
-
|
|
22
|
+
surface,
|
|
23
23
|
setProviderPrompt,
|
|
24
|
-
setChannelPrompt,
|
|
25
|
-
setHookPrompt,
|
|
26
24
|
setSettingsPrompt,
|
|
27
|
-
setContextPanel,
|
|
28
25
|
closeUsagePanel,
|
|
29
26
|
clean,
|
|
30
27
|
routeLabel,
|
|
@@ -38,7 +35,11 @@ export function createRoutePickers({
|
|
|
38
35
|
const openWebSearchPicker = async (options = {}) => {
|
|
39
36
|
const routeOverride = options.routeOverride || null;
|
|
40
37
|
const returnTo = typeof options.returnTo === 'function' ? options.returnTo : null;
|
|
38
|
+
// Surface claim (panel-surface.mjs) taken on this keypress: the route read
|
|
39
|
+
// below is a daemon round-trip, so Esc can land before anything paints.
|
|
40
|
+
const own = surface.claim();
|
|
41
41
|
const currentWebSearchRoute = routeOverride || (await store.getWebSearchRoute?.()) || null;
|
|
42
|
+
if (!own.owns()) return;
|
|
42
43
|
void openModelPicker({
|
|
43
44
|
title: 'Web Search Model',
|
|
44
45
|
loadingDescription: 'Loading web-search-capable models...',
|
|
@@ -53,7 +54,8 @@ export function createRoutePickers({
|
|
|
53
54
|
returnOnNestedCancel: options.returnOnNestedCancel === true,
|
|
54
55
|
onImmediateSelect: () => {
|
|
55
56
|
if (returnTo) returnTo();
|
|
56
|
-
|
|
57
|
+
// Enter inside the nested picker: that keypress owns what it clears.
|
|
58
|
+
else surface.claim().close();
|
|
57
59
|
},
|
|
58
60
|
onSelectRoute: async (routeInput) => {
|
|
59
61
|
const result = await store.setWebSearchRoute?.(routeInput);
|
|
@@ -69,6 +71,7 @@ export function createRoutePickers({
|
|
|
69
71
|
};
|
|
70
72
|
|
|
71
73
|
const openAgentsPicker = async (options = {}) => {
|
|
74
|
+
const own = surface.claim();
|
|
72
75
|
let agents = [];
|
|
73
76
|
try {
|
|
74
77
|
// Await: on a daemon-backed store this is a remote call, and the old sync
|
|
@@ -92,13 +95,12 @@ export function createRoutePickers({
|
|
|
92
95
|
description: agent.description || agent.definition?.description || '',
|
|
93
96
|
_agent: agent,
|
|
94
97
|
}));
|
|
98
|
+
if (!own.owns()) return;
|
|
95
99
|
setProviderPrompt(null);
|
|
96
|
-
setChannelPrompt(null);
|
|
97
|
-
setHookPrompt(null);
|
|
98
100
|
setSettingsPrompt(null);
|
|
99
|
-
|
|
101
|
+
own.context(null);
|
|
100
102
|
closeUsagePanel();
|
|
101
|
-
|
|
103
|
+
own.paint({
|
|
102
104
|
title: 'Agents',
|
|
103
105
|
description: 'Workflow agents available for agent tasks.',
|
|
104
106
|
help: '↑/↓ Select · Enter Set Model · Esc Back',
|
|
@@ -130,7 +132,9 @@ export function createRoutePickers({
|
|
|
130
132
|
store.pushNotice(`${agent.label} model set to ${agentModelProfile(result)}`, 'info');
|
|
131
133
|
},
|
|
132
134
|
});
|
|
133
|
-
|
|
135
|
+
// Nested panel for an Enter on an agent row: the same claim that
|
|
136
|
+
// painted the Agents list, re-armed by that paint.
|
|
137
|
+
own.paint({
|
|
134
138
|
title: agent.label,
|
|
135
139
|
description: 'Pick a model for this agent, or turn it off.',
|
|
136
140
|
help: '↑/↓ Select · Enter Choose · Esc Back',
|
|
@@ -156,6 +160,9 @@ export function createRoutePickers({
|
|
|
156
160
|
openAgentModelPicker();
|
|
157
161
|
return;
|
|
158
162
|
}
|
|
163
|
+
// Post-ack handover back to Agents, bound to THIS keypress: a late
|
|
164
|
+
// ack must not overwrite whatever replaced this panel meanwhile.
|
|
165
|
+
const reopenAgents = own.defer(() => { void openAgentsPicker(); });
|
|
159
166
|
try {
|
|
160
167
|
const result = await store.setAgentRoute?.(agent.id, { disabled: true });
|
|
161
168
|
if (!result) {
|
|
@@ -166,7 +173,7 @@ export function createRoutePickers({
|
|
|
166
173
|
} catch (e) {
|
|
167
174
|
store.pushNotice(`could not turn off ${agent.label}: ${e?.message || e}`, 'error');
|
|
168
175
|
}
|
|
169
|
-
|
|
176
|
+
reopenAgents();
|
|
170
177
|
},
|
|
171
178
|
onCancel: () => {
|
|
172
179
|
void openAgentsPicker();
|
|
@@ -174,13 +181,14 @@ export function createRoutePickers({
|
|
|
174
181
|
});
|
|
175
182
|
},
|
|
176
183
|
onCancel: () => {
|
|
177
|
-
|
|
184
|
+
own.close();
|
|
178
185
|
},
|
|
179
186
|
});
|
|
180
187
|
};
|
|
181
188
|
|
|
182
189
|
const openWorkflowPicker = async (options = {}) => {
|
|
183
190
|
const returnTo = typeof options.returnTo === 'function' ? options.returnTo : null;
|
|
191
|
+
const own = surface.claim();
|
|
184
192
|
let workflows = [];
|
|
185
193
|
try {
|
|
186
194
|
workflows = (await store.listWorkflows?.()) || [];
|
|
@@ -200,13 +208,12 @@ export function createRoutePickers({
|
|
|
200
208
|
description: workflow.description || `${workflow.source || 'workflow'} workflow`,
|
|
201
209
|
_workflow: workflow,
|
|
202
210
|
}));
|
|
211
|
+
if (!own.owns()) return;
|
|
203
212
|
setProviderPrompt(null);
|
|
204
|
-
setChannelPrompt(null);
|
|
205
|
-
setHookPrompt(null);
|
|
206
213
|
setSettingsPrompt(null);
|
|
207
|
-
|
|
214
|
+
own.context(null);
|
|
208
215
|
closeUsagePanel();
|
|
209
|
-
|
|
216
|
+
own.paint({
|
|
210
217
|
title: 'Workflow',
|
|
211
218
|
description: 'Select active workflow.',
|
|
212
219
|
help: returnTo ? '↑/↓ Select · Enter Choose · Esc Settings' : '↑/↓ Select · Enter Choose · Esc Back',
|
|
@@ -215,7 +222,11 @@ export function createRoutePickers({
|
|
|
215
222
|
onSelect: (_value, item) => {
|
|
216
223
|
const workflow = item?._workflow;
|
|
217
224
|
if (!workflow) return;
|
|
218
|
-
|
|
225
|
+
// Clear-and-continue: the flow keeps the surface it just emptied, so
|
|
226
|
+
// the post-ack hop below is bound to THIS keypress. An Esc before the
|
|
227
|
+
// switch acks cancels the hop instead of re-opening Settings.
|
|
228
|
+
own.paint(null);
|
|
229
|
+
const returnAfterSwitch = own.defer(() => { if (returnTo) returnTo(); });
|
|
219
230
|
void store.setWorkflow?.(workflow.id)
|
|
220
231
|
.then((result) => {
|
|
221
232
|
if (!result) {
|
|
@@ -223,12 +234,12 @@ export function createRoutePickers({
|
|
|
223
234
|
return;
|
|
224
235
|
}
|
|
225
236
|
store.pushNotice(workflowSwitchNotice(result), 'info');
|
|
226
|
-
|
|
237
|
+
returnAfterSwitch();
|
|
227
238
|
})
|
|
228
239
|
.catch((e) => store.pushNotice(`Couldn’t switch workflow: ${e?.message || e}`, 'error'));
|
|
229
240
|
},
|
|
230
241
|
onCancel: () => {
|
|
231
|
-
|
|
242
|
+
own.close();
|
|
232
243
|
if (returnTo) returnTo();
|
|
233
244
|
},
|
|
234
245
|
});
|
|
@@ -240,6 +251,7 @@ export function createRoutePickers({
|
|
|
240
251
|
// the chosen style, then advance. `onboarding.onAdvance/onBack` drive the
|
|
241
252
|
// wizard; the confirm bar is built here so both paths share `saveStyle`.
|
|
242
253
|
const onboarding = options.onboarding || null;
|
|
254
|
+
const own = surface.claim();
|
|
243
255
|
let status = null;
|
|
244
256
|
try {
|
|
245
257
|
status = (await store.listOutputStyles?.()) || null;
|
|
@@ -262,18 +274,24 @@ export function createRoutePickers({
|
|
|
262
274
|
description: style.description || style.source || 'output style',
|
|
263
275
|
_style: style,
|
|
264
276
|
}));
|
|
277
|
+
if (!own.owns()) return;
|
|
265
278
|
setProviderPrompt(null);
|
|
266
|
-
setChannelPrompt(null);
|
|
267
|
-
setHookPrompt(null);
|
|
268
279
|
setSettingsPrompt(null);
|
|
269
|
-
|
|
280
|
+
own.context(null);
|
|
270
281
|
closeUsagePanel();
|
|
271
282
|
const saveStyle = (styleId, { advance = false } = {}) => {
|
|
272
283
|
if (!styleId) return;
|
|
273
284
|
// Onboarding advance: keep the current picker visible during the async
|
|
274
285
|
// style switch so the screen never flashes empty between steps; the next
|
|
275
286
|
// step (or finishOnboarding) replaces/clears the picker itself.
|
|
276
|
-
if (!(advance && onboarding))
|
|
287
|
+
if (!(advance && onboarding)) own.paint(null);
|
|
288
|
+
// Post-ack delegation (next onboarding step, or back to the caller):
|
|
289
|
+
// bound after this keypress's own navigation so an Esc while the switch
|
|
290
|
+
// is in flight cannot paint a panel over the new surface.
|
|
291
|
+
const advanceAfterSave = own.defer(() => {
|
|
292
|
+
if (advance && onboarding) onboarding.onAdvance?.();
|
|
293
|
+
else if (returnTo) returnTo();
|
|
294
|
+
});
|
|
277
295
|
void store.setOutputStyle?.(styleId)
|
|
278
296
|
.then((result) => {
|
|
279
297
|
if (!result) {
|
|
@@ -281,12 +299,11 @@ export function createRoutePickers({
|
|
|
281
299
|
} else {
|
|
282
300
|
store.pushNotice(outputStyleNotice(result), 'info');
|
|
283
301
|
}
|
|
284
|
-
|
|
285
|
-
else if (returnTo) returnTo();
|
|
302
|
+
advanceAfterSave();
|
|
286
303
|
})
|
|
287
304
|
.catch((e) => store.pushNotice(`Couldn’t switch output style: ${e?.message || e}`, 'error'));
|
|
288
305
|
};
|
|
289
|
-
|
|
306
|
+
own.paint({
|
|
290
307
|
title: 'Output Style',
|
|
291
308
|
description: 'Select response style.',
|
|
292
309
|
// Onboarding uses a ConfirmBar (←/→ = Back/Next); let the Picker supply
|
|
@@ -301,7 +318,7 @@ export function createRoutePickers({
|
|
|
301
318
|
],
|
|
302
319
|
onConfirm: (button) => {
|
|
303
320
|
if (button.value === 'back') {
|
|
304
|
-
|
|
321
|
+
own.close();
|
|
305
322
|
onboarding.onBack?.();
|
|
306
323
|
return;
|
|
307
324
|
}
|
|
@@ -317,7 +334,7 @@ export function createRoutePickers({
|
|
|
317
334
|
saveStyle(style.id, { advance: Boolean(onboarding) });
|
|
318
335
|
},
|
|
319
336
|
onCancel: () => {
|
|
320
|
-
|
|
337
|
+
own.close();
|
|
321
338
|
if (onboarding) onboarding.onCancel?.();
|
|
322
339
|
else if (returnTo) returnTo();
|
|
323
340
|
},
|