@namzu/cli 13.0.0 → 14.0.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 (64) hide show
  1. package/README.md +11 -2
  2. package/dist/commands/login.d.ts +2 -0
  3. package/dist/commands/login.d.ts.map +1 -1
  4. package/dist/commands/login.js +79 -21
  5. package/dist/commands/login.js.map +1 -1
  6. package/dist/doctor/checks/credentials.d.ts.map +1 -1
  7. package/dist/doctor/checks/credentials.js +7 -1
  8. package/dist/doctor/checks/credentials.js.map +1 -1
  9. package/dist/integrations/providers/codex-device-login.d.ts +27 -0
  10. package/dist/integrations/providers/codex-device-login.d.ts.map +1 -0
  11. package/dist/integrations/providers/codex-device-login.js +195 -0
  12. package/dist/integrations/providers/codex-device-login.js.map +1 -0
  13. package/dist/integrations/providers/codex-oauth.d.ts +10 -0
  14. package/dist/integrations/providers/codex-oauth.d.ts.map +1 -0
  15. package/dist/integrations/providers/codex-oauth.js +95 -0
  16. package/dist/integrations/providers/codex-oauth.js.map +1 -0
  17. package/dist/integrations/providers/credential-store.d.ts +23 -4
  18. package/dist/integrations/providers/credential-store.d.ts.map +1 -1
  19. package/dist/integrations/providers/credential-store.js +125 -19
  20. package/dist/integrations/providers/credential-store.js.map +1 -1
  21. package/dist/integrations/providers/discover.d.ts +25 -13
  22. package/dist/integrations/providers/discover.d.ts.map +1 -1
  23. package/dist/integrations/providers/discover.js +98 -44
  24. package/dist/integrations/providers/discover.js.map +1 -1
  25. package/dist/integrations/providers/harness-credentials.d.ts +36 -0
  26. package/dist/integrations/providers/harness-credentials.d.ts.map +1 -0
  27. package/dist/integrations/providers/harness-credentials.js +146 -0
  28. package/dist/integrations/providers/harness-credentials.js.map +1 -0
  29. package/dist/integrations/providers/identity.d.ts +8 -15
  30. package/dist/integrations/providers/identity.d.ts.map +1 -1
  31. package/dist/integrations/providers/identity.js +8 -15
  32. package/dist/integrations/providers/identity.js.map +1 -1
  33. package/dist/integrations/providers/index.d.ts +5 -2
  34. package/dist/integrations/providers/index.d.ts.map +1 -1
  35. package/dist/integrations/providers/index.js +4 -1
  36. package/dist/integrations/providers/index.js.map +1 -1
  37. package/dist/integrations/providers/oauth.d.ts +2 -2
  38. package/dist/integrations/providers/oauth.d.ts.map +1 -1
  39. package/dist/integrations/providers/oauth.js +8 -5
  40. package/dist/integrations/providers/oauth.js.map +1 -1
  41. package/dist/integrations/providers/register.d.ts.map +1 -1
  42. package/dist/integrations/providers/register.js +9 -1
  43. package/dist/integrations/providers/register.js.map +1 -1
  44. package/dist/integrations/providers/registry.d.ts +8 -1
  45. package/dist/integrations/providers/registry.d.ts.map +1 -1
  46. package/dist/integrations/providers/registry.js +29 -0
  47. package/dist/integrations/providers/registry.js.map +1 -1
  48. package/dist/tui/App.d.ts.map +1 -1
  49. package/dist/tui/App.js +77 -64
  50. package/dist/tui/App.js.map +1 -1
  51. package/dist/tui/Picker.d.ts +5 -3
  52. package/dist/tui/Picker.d.ts.map +1 -1
  53. package/dist/tui/Picker.js +70 -22
  54. package/dist/tui/Picker.js.map +1 -1
  55. package/dist/tui/agent.d.ts.map +1 -1
  56. package/dist/tui/agent.js +107 -16
  57. package/dist/tui/agent.js.map +1 -1
  58. package/dist/tui/login-prompt.d.ts +5 -0
  59. package/dist/tui/login-prompt.d.ts.map +1 -1
  60. package/dist/tui/login-prompt.js +14 -0
  61. package/dist/tui/login-prompt.js.map +1 -1
  62. package/dist/tui/slashCommands.js +1 -1
  63. package/dist/tui/slashCommands.js.map +1 -1
  64. package/package.json +5 -5
@@ -15,7 +15,25 @@ export const PROVIDER_REGISTRY = Object.freeze({
15
15
  envVars: ['ANTHROPIC_API_KEY', 'ANTHROPIC_TOKEN', 'CLAUDE_CODE_OAUTH_TOKEN'],
16
16
  defaultModel: 'claude-opus-5',
17
17
  requiresApiKey: true,
18
+ acceptsTypedCredential: true,
19
+ subscriptionLogin: 'browser',
18
20
  constructible: true,
21
+ driverPackage: '@namzu/anthropic',
22
+ },
23
+ codex: {
24
+ id: 'codex',
25
+ label: 'OpenAI (Codex subscription)',
26
+ // A Codex subscription token is never accepted through an environment
27
+ // variable here. It is a Responses credential with account routing, not
28
+ // an OpenAI API key; discovery reads its complete owned envelope instead.
29
+ envVars: [],
30
+ defaultBaseUrl: 'https://chatgpt.com/backend-api/codex',
31
+ defaultModel: 'gpt-5.6-sol',
32
+ requiresApiKey: true,
33
+ acceptsTypedCredential: false,
34
+ subscriptionLogin: 'device',
35
+ constructible: true,
36
+ driverPackage: '@namzu/openai',
19
37
  },
20
38
  openai: {
21
39
  id: 'openai',
@@ -23,7 +41,9 @@ export const PROVIDER_REGISTRY = Object.freeze({
23
41
  envVars: ['OPENAI_API_KEY'],
24
42
  defaultModel: 'gpt-4o',
25
43
  requiresApiKey: true,
44
+ acceptsTypedCredential: true,
26
45
  constructible: true,
46
+ driverPackage: '@namzu/openai',
27
47
  },
28
48
  deepseek: {
29
49
  id: 'deepseek',
@@ -35,7 +55,9 @@ export const PROVIDER_REGISTRY = Object.freeze({
35
55
  // were discontinued on 2026-07-24 and resolve to nothing.
36
56
  defaultModel: 'deepseek-v4-flash',
37
57
  requiresApiKey: true,
58
+ acceptsTypedCredential: true,
38
59
  constructible: true,
60
+ driverPackage: '@namzu/deepseek',
39
61
  },
40
62
  openrouter: {
41
63
  id: 'openrouter',
@@ -44,7 +66,9 @@ export const PROVIDER_REGISTRY = Object.freeze({
44
66
  defaultBaseUrl: 'https://openrouter.ai/api/v1',
45
67
  defaultModel: 'anthropic/claude-opus-5',
46
68
  requiresApiKey: true,
69
+ acceptsTypedCredential: true,
47
70
  constructible: true,
71
+ driverPackage: '@namzu/openrouter',
48
72
  },
49
73
  ollama: {
50
74
  id: 'ollama',
@@ -54,7 +78,9 @@ export const PROVIDER_REGISTRY = Object.freeze({
54
78
  probeUrl: 'http://localhost:11434/api/tags',
55
79
  defaultModel: 'llama3.2',
56
80
  requiresApiKey: false,
81
+ acceptsTypedCredential: false,
57
82
  constructible: true,
83
+ driverPackage: '@namzu/ollama',
58
84
  },
59
85
  lmstudio: {
60
86
  id: 'lmstudio',
@@ -64,6 +90,7 @@ export const PROVIDER_REGISTRY = Object.freeze({
64
90
  probeUrl: 'http://localhost:1234/v1/models',
65
91
  defaultModel: 'auto',
66
92
  requiresApiKey: false,
93
+ acceptsTypedCredential: false,
67
94
  constructible: false,
68
95
  },
69
96
  bedrock: {
@@ -81,6 +108,7 @@ export const PROVIDER_REGISTRY = Object.freeze({
81
108
  // means this build cannot construct the driver at all.
82
109
  defaultModel: 'anthropic.claude-opus-4-7-v1:0',
83
110
  requiresApiKey: true,
111
+ acceptsTypedCredential: true,
84
112
  constructible: false,
85
113
  },
86
114
  http: {
@@ -91,6 +119,7 @@ export const PROVIDER_REGISTRY = Object.freeze({
91
119
  envVars: [],
92
120
  defaultModel: 'gpt-4o',
93
121
  requiresApiKey: true,
122
+ acceptsTypedCredential: true,
94
123
  constructible: false,
95
124
  },
96
125
  });
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/integrations/providers/registry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/integrations/providers/registry.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/tui/App.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EASN,KAAK,OAAO,EASZ,MAAM,YAAY,CAAA;AAkGnB,OAAO,KAAK,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAQ/D,MAAM,WAAW,QAAQ;IACxB,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAA;CACxB;AA2CD,sEAAsE;AACtE,wBAAgB,mBAAmB,CAClC,QAAQ,EAAE,SAAS,OAAO,EAAE,EAC5B,MAAM,EAAE,MAAM,MAAM,EACpB,iBAAiB,GAAE,SAAS,MAAM,EAAO,GACvC,SAAS,iBAAiB,EAAE,CA4D9B;AAgED,wBAAgB,GAAG,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,EAAE,QAAQ,2CA2uGhD"}
1
+ {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/tui/App.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAMN,KAAK,OAAO,EAYZ,MAAM,YAAY,CAAA;AA+GnB,OAAO,KAAK,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAG/D,MAAM,WAAW,QAAQ;IACxB,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAA;CACxB;AA2CD,sEAAsE;AACtE,wBAAgB,mBAAmB,CAClC,QAAQ,EAAE,SAAS,OAAO,EAAE,EAC5B,MAAM,EAAE,MAAM,MAAM,EACpB,iBAAiB,GAAE,SAAS,MAAM,EAAO,GACvC,SAAS,iBAAiB,EAAE,CA4D9B;AAgED,wBAAgB,GAAG,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,EAAE,QAAQ,2CA+vGhD"}
package/dist/tui/App.js CHANGED
@@ -11,45 +11,45 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
11
11
  * 4. If discovery returned zero providers → show <Picker/> in
12
12
  * empty-state mode (explains where to put credentials).
13
13
  */
14
- import { DiskMessageFeedbackStore, GoalRoundLimitError, HostCommandRegistry, SessionGoalActivation, StaleGoalError, kernelHostCommands, createAssistantMessage, createUserMessage, generateRunId, isCompactionMessage, } from '@namzu/sdk';
15
- import { Box, Text, useApp, useInput, useStdout } from 'ink';
16
14
  import { join, relative } from 'node:path';
15
+ import { DiskMessageFeedbackStore, GoalRoundLimitError, HostCommandRegistry, SessionGoalActivation, StaleGoalError, createAssistantMessage, createUserMessage, generateRunId, isCompactionMessage, kernelHostCommands, } from '@namzu/sdk';
16
+ import { Box, Text, useApp, useInput, useStdout } from 'ink';
17
17
  import { useCallback, useEffect, useRef, useState } from 'react';
18
- import { visibleProjectInstructionPath } from '../context/project-path.js';
19
18
  import { pinTrustedProjectPath, resolveTrustedProjectContext, } from '../config/trusted-project-context.js';
20
- import { beginSubscriptionLogin, clearStoredSubscriptionCredential, credentialsPath, primaryProvider, readStoredSubscriptionCredential, writePreferences, } from '../integrations/providers/index.js';
19
+ import { visibleProjectInstructionPath } from '../context/project-path.js';
21
20
  import { writeClipboardText } from '../integrations/clipboard/text.js';
22
21
  import { terminalNotificationEnabled, writeTerminalNotification, } from '../integrations/notifications/terminal.js';
23
- import { describeLoginOutcome, describeLoginStart, describeLogout } from './login-prompt.js';
24
- import { openInBrowser } from './open-browser.js';
22
+ import { beginCodexDeviceLogin, beginSubscriptionLogin, clearAllStoredCredentials, credentialsPath, primaryProvider, readStoredCodexCredential, readStoredSubscriptionCredential, writePreferences, } from '../integrations/providers/index.js';
23
+ import { appendMessages, forkConversation, forkConversationBeforeUser, listRecent, loadConversation, openSessions, replaceConversation, requireWritableConversation, setTitle, startConversation, titleOf, } from '../integrations/sessions/store.js';
24
+ import { conversationMarkdown, writeConversationExport, } from '../integrations/sessions/transcript-export.js';
25
25
  import { isTrusted, trustDir } from '../integrations/trust/store.js';
26
+ import { checkUpdates } from '../integrations/updates.js';
26
27
  import { appendMemory, composeMemoryPrompt, readMemory } from '../memory/store.js';
27
28
  import { composeSkillsPrompt, discoverSkills, loadSkillBody } from '../skills/store.js';
28
- import { checkUpdates } from '../integrations/updates.js';
29
- import { LiveActivity, formatElapsed } from './LiveActivity.js';
30
- import { bottomSpacerRows } from './bottom-spacer.js';
31
- import { expandFileMentions } from './mentions.js';
29
+ import { discoverUserCommands } from '../user-commands/store.js';
32
30
  import { Composer } from './Composer.js';
33
31
  import { EditPromptPicker } from './EditPromptPicker.js';
34
- import { TrustPrompt } from './TrustPrompt.js';
35
- import { NAMZU_MARK, NAMZU_MARK_COLOR, NAMZU_WORDMARK, NAMZU_WORDMARK_GRADIENT, NAMZU_WORDMARK_MIN_WIDTH, } from './logo.js';
32
+ import { LiveActivity, formatElapsed } from './LiveActivity.js';
36
33
  import { PermissionOverlay } from './PermissionOverlay.js';
37
- import { approvalIsDeliberate } from './consent-timing.js';
38
34
  import { Picker } from './Picker.js';
35
+ import { ResumePicker } from './ResumePicker.js';
39
36
  import { StatusBar } from './StatusBar.js';
40
37
  import { Transcript, willCollapse } from './Transcript.js';
41
- import { liveWindow, transcriptLines } from './live-window.js';
42
- import { appendMessages, forkConversation, forkConversationBeforeUser, listRecent, loadConversation, openSessions, replaceConversation, requireWritableConversation, setTitle, startConversation, titleOf, } from '../integrations/sessions/store.js';
43
- import { conversationMarkdown, writeConversationExport, } from '../integrations/sessions/transcript-export.js';
38
+ import { TrustPrompt } from './TrustPrompt.js';
44
39
  import { createAgentSession, probeAgentSession, } from './agent.js';
45
- import { ResumePicker } from './ResumePicker.js';
46
- import { editablePrompts } from './edit-prompts.js';
40
+ import { bottomSpacerRows } from './bottom-spacer.js';
41
+ import { keepRecentRows } from './compact-transcript.js';
42
+ import { approvalIsDeliberate } from './consent-timing.js';
47
43
  import { planTurnPublication } from './conversation-history.js';
48
- import { discoverUserCommands } from '../user-commands/store.js';
44
+ import { editablePrompts } from './edit-prompts.js';
45
+ import { liveWindow, transcriptLines } from './live-window.js';
46
+ import { describeCodexDeviceLoginStart, describeLoginOutcome, describeLoginStart, describeLogout, } from './login-prompt.js';
47
+ import { NAMZU_MARK, NAMZU_MARK_COLOR, NAMZU_WORDMARK, NAMZU_WORDMARK_GRADIENT, NAMZU_WORDMARK_MIN_WIDTH, } from './logo.js';
48
+ import { expandFileMentions } from './mentions.js';
49
+ import { openInBrowser } from './open-browser.js';
49
50
  import { hostCommandNames, kernelCommandDescriptors, mergeHostCommands, renderOutcome, reviewPrompt, runSlash, } from './slashCommands.js';
50
51
  import { splitCompleteBlocks } from './stream-blocks.js';
51
52
  import { theme } from './theme.js';
52
- import { keepRecentRows } from './compact-transcript.js';
53
53
  import { renderWorkspaceDiff, workspaceDiff } from './workspace-diff.js';
54
54
  /** Last non-empty assistant text in a durable conversation, newest first. */
55
55
  function latestAssistantOutput(messages) {
@@ -213,6 +213,8 @@ export function App({ ctx: initialCtx }) {
213
213
  * chosen yet would be answering a question that was not asked.
214
214
  */
215
215
  const [keyEntryFor, setKeyEntryFor] = useState(null);
216
+ /** Which decision owns the next picker mount. */
217
+ const [pickerInitialView, setPickerInitialView] = useState('providers');
216
218
  /** The chain read from disk, held while the picker repairs its credential. */
217
219
  const savedPrefsRef = useRef(null);
218
220
  /**
@@ -328,12 +330,15 @@ export function App({ ctx: initialCtx }) {
328
330
  * which the code that comes back cannot be exchanged for anything.
329
331
  */
330
332
  const loginRef = useRef(null);
333
+ const codexLoginRef = useRef(null);
331
334
  const loginAbortCleanupRef = useRef(null);
332
335
  const cancelPendingLogin = useCallback(() => {
333
336
  loginAbortCleanupRef.current?.();
334
337
  loginAbortCleanupRef.current = null;
335
338
  loginRef.current?.cancel();
336
339
  loginRef.current = null;
340
+ codexLoginRef.current?.cancel();
341
+ codexLoginRef.current = null;
337
342
  }, []);
338
343
  const runProbeRef = useRef(null);
339
344
  useEffect(() => cancelPendingLogin, [cancelPendingLogin]);
@@ -651,9 +656,9 @@ export function App({ ctx: initialCtx }) {
651
656
  /**
652
657
  * Sign in to a subscription without leaving namzu.
653
658
  *
654
- * Two calls, one command. Bare `/login` starts an attempt and parks it in
655
- * `loginRef`; `/login <address>` finishes that one. Nothing here parses the
656
- * argument — `slashCommands` already decided which of the two this is.
659
+ * A bare `/login` no longer guesses a provider: it mounts the subscription
660
+ * picker first. The argument form remains the paste-completion half of the
661
+ * browser-callback attempt already in flight.
657
662
  *
658
663
  * ## Why it re-probes instead of installing the credential directly
659
664
  *
@@ -681,46 +686,17 @@ export function App({ ctx: initialCtx }) {
681
686
  loginAbortCleanupRef.current?.();
682
687
  loginAbortCleanupRef.current = null;
683
688
  pushMessage('system', describeLoginOutcome(outcome));
684
- if (outcome.ok)
689
+ if (outcome.ok) {
690
+ setPickerInitialView('providers');
685
691
  await runProbeRef.current?.();
692
+ }
686
693
  return;
687
694
  }
688
695
  cancelPendingLogin();
689
- let start;
690
- try {
691
- start = await beginSubscriptionLogin();
692
- }
693
- catch (err) {
694
- pushMessage('system', `Could not start a sign-in: ${err instanceof Error ? err.message : String(err)}`);
695
- return;
696
- }
697
- loginRef.current = start;
698
- pushMessage('system', describeLoginStart({
699
- url: start.url,
700
- loopback: start.loopback,
701
- browserOpened: openInBrowser(start.url),
702
- }));
703
- // The automatic half, when there is one. Not awaited by the caller:
704
- // the composer stays live throughout, so the operator can paste
705
- // instead — or type anything else — while this waits.
706
- const waiting = start.waitForCallback();
707
- if (!waiting)
708
- return;
709
- const outcome = await waiting;
710
- if (loginRef.current !== start)
711
- return; // superseded, or finished by paste
712
- loginRef.current = null;
713
- loginAbortCleanupRef.current?.();
714
- loginAbortCleanupRef.current = null;
715
- start.cancel();
716
- // A cancelled listener resolves to a refusal, and saying "sign-in
717
- // failed" when the operator finished it another way would be a lie
718
- // about their own successful login.
719
- if (!outcome.ok && outcome.reason.includes('cancelled'))
720
- return;
721
- pushMessage('system', describeLoginOutcome(outcome));
722
- if (outcome.ok)
723
- await runProbeRef.current?.();
696
+ setPickerNotice(null);
697
+ setKeyEntryFor(null);
698
+ setPickerInitialView('subscriptions');
699
+ setPhase('picker');
724
700
  }, [cancelPendingLogin, pushMessage]);
725
701
  /**
726
702
  * Sign in from the PICKER, where the transcript does not exist.
@@ -737,10 +713,43 @@ export function App({ ctx: initialCtx }) {
737
713
  * no-browser case is handed to `namzu login`, which reads the pasted
738
714
  * address from standard input and exists for exactly that machine.
739
715
  */
740
- const startLoginFromPicker = useCallback(async (signal) => {
716
+ const startLoginFromPicker = useCallback(async (provider, signal) => {
741
717
  if (signal.aborted)
742
718
  return;
743
719
  cancelPendingLogin();
720
+ if (provider === 'codex') {
721
+ let start;
722
+ try {
723
+ start = await beginCodexDeviceLogin({ signal });
724
+ }
725
+ catch (error) {
726
+ if (!signal.aborted) {
727
+ setPickerNotice(`Could not start Codex sign-in: ${error instanceof Error ? error.message : String(error)}`);
728
+ }
729
+ return;
730
+ }
731
+ if (signal.aborted) {
732
+ start.cancel();
733
+ return;
734
+ }
735
+ codexLoginRef.current = start;
736
+ setPickerNotice(describeCodexDeviceLoginStart({
737
+ url: start.url,
738
+ userCode: start.userCode,
739
+ browserOpened: openInBrowser(start.url),
740
+ }));
741
+ const outcome = await start.waitForCompletion();
742
+ if (codexLoginRef.current !== start || signal.aborted)
743
+ return;
744
+ codexLoginRef.current = null;
745
+ start.cancel();
746
+ setPickerNotice(describeLoginOutcome(outcome));
747
+ if (outcome.ok) {
748
+ setPickerInitialView('providers');
749
+ await runProbeRef.current?.(signal);
750
+ }
751
+ return;
752
+ }
744
753
  let start;
745
754
  try {
746
755
  start = await beginSubscriptionLogin({ signal });
@@ -793,8 +802,10 @@ export function App({ ctx: initialCtx }) {
793
802
  if (!outcome.ok && outcome.reason.includes('cancelled'))
794
803
  return;
795
804
  setPickerNotice(describeLoginOutcome(outcome));
796
- if (outcome.ok)
805
+ if (outcome.ok) {
806
+ setPickerInitialView('providers');
797
807
  await runProbeRef.current?.(signal);
808
+ }
798
809
  }, [cancelPendingLogin]);
799
810
  const runProbe = useCallback(async (signal) => {
800
811
  try {
@@ -1948,6 +1959,7 @@ export function App({ ctx: initialCtx }) {
1948
1959
  // been solved — the session behind this picker is running.
1949
1960
  setPickerNotice(null);
1950
1961
  setKeyEntryFor(null);
1962
+ setPickerInitialView('providers');
1951
1963
  setPhase('picker');
1952
1964
  return;
1953
1965
  case 'permission-mode': {
@@ -2007,9 +2019,9 @@ export function App({ ctx: initialCtx }) {
2007
2019
  return;
2008
2020
  case 'logout': {
2009
2021
  const path = credentialsPath();
2010
- const had = readStoredSubscriptionCredential() !== null;
2022
+ const had = readStoredSubscriptionCredential() !== null || readStoredCodexCredential() !== null;
2011
2023
  try {
2012
- clearStoredSubscriptionCredential();
2024
+ clearAllStoredCredentials();
2013
2025
  }
2014
2026
  catch (err) {
2015
2027
  pushMessage('system', `Could not remove ${path}: ${err instanceof Error ? err.message : String(err)}`);
@@ -2729,6 +2741,7 @@ export function App({ ctx: initialCtx }) {
2729
2741
  * what the empty picker's own footer has always claimed `esc` does.
2730
2742
  */
2731
2743
  const handlePickerCancel = useCallback(() => {
2744
+ setPickerInitialView('providers');
2732
2745
  if (session?.hasProvider) {
2733
2746
  setPhase('ready');
2734
2747
  return;
@@ -2930,7 +2943,7 @@ export function App({ ctx: initialCtx }) {
2930
2943
  // Background is left natural — we inherit the terminal's own background
2931
2944
  // and only theme the foreground. Forcing
2932
2945
  // a filled bg left mismatched patches around bordered areas, so we don't.
2933
- return (_jsxs(Box, { flexDirection: "column", children: [phase !== 'ready' ? (_jsx(Banner, { version: ctx.version, session: session, permissionMode: permissionMode, cwd: ctx.cwd })) : null, _jsxs(Box, { flexDirection: "column", paddingX: 1, children: [phase === 'trust' ? (_jsx(TrustPrompt, { cwd: ctx.cwd })) : phase === 'resume' ? (_jsx(ResumePicker, { conversations: resumeList, selected: selectedResume })) : phase === 'edit' ? (_jsx(EditPromptPicker, { prompts: editList, selected: selectedEdit })) : phase === 'picker' ? (_jsx(Picker, { detected: detected, currentProvider: currentProvider, currentModel: session?.modelSummary ?? null, onSubmit: handlePickerSubmit, onCancel: handlePickerCancel, onCredential: handleTypedCredential, onLogin: (signal) => void startLoginFromPicker(signal), keyEntryFor: keyEntryFor, notice: pickerNotice })) : (_jsxs(_Fragment, { children: [_jsx(TranscriptFrame, { children: _jsx(Transcript, { messages: finalized, pending: messages.find((m) => m.pending) ?? null, state: state, settled: window.settled, resetKey: resetKey, raw: rawOutput, header: phase === 'ready' ? (_jsx(Banner, { version: ctx.version, session: session, permissionMode: permissionMode, cwd: ctx.cwd })) : undefined }) }), spacerRows > 0 ? _jsx(Box, { height: spacerRows }) : null, _jsx(LiveActivity, { activeTools: activeTools, thinking: state === 'thinking' && !messages.some((m) => m.pending) }), permission ? _jsx(PermissionOverlay, { toolCalls: permission.toolCalls }) : null, _jsxs(ComposerFrame, { focus: state === 'idle' && phase === 'ready' && conversationMutation === null, hidden: permission !== null, children: [queued.length > 0 && permission === null ? (_jsx(Box, { paddingX: 1, children: _jsxs(Text, { color: theme.text.muted, children: [queuePause ? '⏸' : '⏎', " ", queued.length, " message", queued.length > 1 ? 's' : '', " queued \u2014", ' ', queuePause
2946
+ return (_jsxs(Box, { flexDirection: "column", children: [phase !== 'ready' ? (_jsx(Banner, { version: ctx.version, session: session, permissionMode: permissionMode, cwd: ctx.cwd })) : null, _jsxs(Box, { flexDirection: "column", paddingX: 1, children: [phase === 'trust' ? (_jsx(TrustPrompt, { cwd: ctx.cwd })) : phase === 'resume' ? (_jsx(ResumePicker, { conversations: resumeList, selected: selectedResume })) : phase === 'edit' ? (_jsx(EditPromptPicker, { prompts: editList, selected: selectedEdit })) : phase === 'picker' ? (_jsx(Picker, { detected: detected, currentProvider: currentProvider, currentModel: session?.modelSummary ?? null, initialView: pickerInitialView, onSubmit: handlePickerSubmit, onCancel: handlePickerCancel, onCredential: handleTypedCredential, onLogin: (provider, signal) => void startLoginFromPicker(provider, signal), keyEntryFor: keyEntryFor, notice: pickerNotice })) : (_jsxs(_Fragment, { children: [_jsx(TranscriptFrame, { children: _jsx(Transcript, { messages: finalized, pending: messages.find((m) => m.pending) ?? null, state: state, settled: window.settled, resetKey: resetKey, raw: rawOutput, header: phase === 'ready' ? (_jsx(Banner, { version: ctx.version, session: session, permissionMode: permissionMode, cwd: ctx.cwd })) : undefined }) }), spacerRows > 0 ? _jsx(Box, { height: spacerRows }) : null, _jsx(LiveActivity, { activeTools: activeTools, thinking: state === 'thinking' && !messages.some((m) => m.pending) }), permission ? _jsx(PermissionOverlay, { toolCalls: permission.toolCalls }) : null, _jsxs(ComposerFrame, { focus: state === 'idle' && phase === 'ready' && conversationMutation === null, hidden: permission !== null, children: [queued.length > 0 && permission === null ? (_jsx(Box, { paddingX: 1, children: _jsxs(Text, { color: theme.text.muted, children: [queuePause ? '⏸' : '⏎', " ", queued.length, " message", queued.length > 1 ? 's' : '', " queued \u2014", ' ', queuePause
2934
2947
  ? `paused after a ${queuePause.outcome} turn; send a message or change model to continue`
2935
2948
  : 'sending when ready'] }) })) : null, _jsx(Composer, { disabled: phase !== 'ready' ||
2936
2949
  state === 'awaiting-permission' ||