@aria-cli/cli 1.0.54 → 1.0.56
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/bin/aria.mjs +671 -802
- package/dist/.tsbuildinfo +1 -0
- package/dist/attached-local-control-client.js +826 -0
- package/dist/attached-local-control-client.js.map +1 -0
- package/dist/bootstrap-local-control-client.js +2 -0
- package/dist/bootstrap-local-control-client.js.map +1 -0
- package/dist/capability-aware-method-proxy.js +42 -0
- package/dist/capability-aware-method-proxy.js.map +1 -0
- package/dist/cli-context.js +160 -0
- package/dist/cli-context.js.map +1 -0
- package/dist/commands/arions.js +174 -0
- package/dist/commands/arions.js.map +1 -0
- package/dist/commands/auth.js +123 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/daemon.js +367 -0
- package/dist/commands/daemon.js.map +1 -0
- package/dist/commands/definitions.js +176 -0
- package/dist/commands/definitions.js.map +1 -0
- package/dist/commands/index.js +80 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/login-handler.js +1108 -0
- package/dist/commands/login-handler.js.map +1 -0
- package/dist/commands/logout-handler.js +92 -0
- package/dist/commands/logout-handler.js.map +1 -0
- package/dist/commands/memory-handlers.js +89 -0
- package/dist/commands/memory-handlers.js.map +1 -0
- package/dist/commands/pairing.js +60 -0
- package/dist/commands/pairing.js.map +1 -0
- package/dist/commands/runtime-cutover-reset-command.js +12 -0
- package/dist/commands/runtime-cutover-reset-command.js.map +1 -0
- package/dist/commands/runtime-cutover-reset.js +265 -0
- package/dist/commands/runtime-cutover-reset.js.map +1 -0
- package/dist/commands/terminal-setup.js +84 -0
- package/dist/commands/terminal-setup.js.map +1 -0
- package/dist/config/aria-config.js +238 -0
- package/dist/config/aria-config.js.map +1 -0
- package/dist/config/index.js +3 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/loader.js +97 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config.js +142 -0
- package/dist/config.js.map +1 -0
- package/dist/daemon-info.js +10 -0
- package/dist/daemon-info.js.map +1 -0
- package/dist/ensure-daemon.js +128 -0
- package/dist/ensure-daemon.js.map +1 -0
- package/dist/entrypoints/command-mode.js +5 -0
- package/dist/entrypoints/command-mode.js.map +1 -0
- package/dist/entrypoints/daemon.js +50 -0
- package/dist/entrypoints/daemon.js.map +1 -0
- package/dist/entrypoints/headless-stdio.js +25 -0
- package/dist/entrypoints/headless-stdio.js.map +1 -0
- package/dist/entrypoints/interactive.d.ts.map +1 -0
- package/dist/entrypoints/interactive.js +80 -0
- package/dist/entrypoints/interactive.js.map +1 -0
- package/dist/event-loop-watchdog.js +73 -0
- package/dist/event-loop-watchdog.js.map +1 -0
- package/dist/headless/auth-orchestrator.js +508 -0
- package/dist/headless/auth-orchestrator.js.map +1 -0
- package/dist/headless/auth-service.js +43 -0
- package/dist/headless/auth-service.js.map +1 -0
- package/dist/headless/bootstrap-fast-path.js +112 -0
- package/dist/headless/bootstrap-fast-path.js.map +1 -0
- package/dist/headless/call-command.js +143 -0
- package/dist/headless/call-command.js.map +1 -0
- package/dist/headless/daemon-service.js +318 -0
- package/dist/headless/daemon-service.js.map +1 -0
- package/dist/headless/hook-actions.js +235 -0
- package/dist/headless/hook-actions.js.map +1 -0
- package/dist/headless/hook-service.js +42 -0
- package/dist/headless/hook-service.js.map +1 -0
- package/dist/headless/kernel-services.js +216 -0
- package/dist/headless/kernel-services.js.map +1 -0
- package/dist/headless/kernel.js +785 -0
- package/dist/headless/kernel.js.map +1 -0
- package/dist/headless/operations/arion.js +119 -0
- package/dist/headless/operations/arion.js.map +1 -0
- package/dist/headless/operations/auth.js +45 -0
- package/dist/headless/operations/auth.js.map +1 -0
- package/dist/headless/operations/client.js +31 -0
- package/dist/headless/operations/client.js.map +1 -0
- package/dist/headless/operations/config.js +69 -0
- package/dist/headless/operations/config.js.map +1 -0
- package/dist/headless/operations/daemon.js +47 -0
- package/dist/headless/operations/daemon.js.map +1 -0
- package/dist/headless/operations/hook.js +56 -0
- package/dist/headless/operations/hook.js.map +1 -0
- package/dist/headless/operations/index.js +11 -0
- package/dist/headless/operations/index.js.map +1 -0
- package/dist/headless/operations/memory.js +102 -0
- package/dist/headless/operations/memory.js.map +1 -0
- package/dist/headless/operations/message.js +279 -0
- package/dist/headless/operations/message.js.map +1 -0
- package/dist/headless/operations/model.js +100 -0
- package/dist/headless/operations/model.js.map +1 -0
- package/dist/headless/operations/peer.js +56 -0
- package/dist/headless/operations/peer.js.map +1 -0
- package/dist/headless/operations/run.js +24 -0
- package/dist/headless/operations/run.js.map +1 -0
- package/dist/headless/operations/session.js +90 -0
- package/dist/headless/operations/session.js.map +1 -0
- package/dist/headless/operations/system.js +19 -0
- package/dist/headless/operations/system.js.map +1 -0
- package/dist/headless/operations/utils.js +35 -0
- package/dist/headless/operations/utils.js.map +1 -0
- package/dist/headless/run-orchestrator.js +703 -0
- package/dist/headless/run-orchestrator.js.map +1 -0
- package/dist/headless/stdio-server.js +439 -0
- package/dist/headless/stdio-server.js.map +1 -0
- package/dist/history/SessionHistory.js +8 -0
- package/dist/history/SessionHistory.js.map +1 -0
- package/dist/history/SessionHistoryClient.js +186 -0
- package/dist/history/SessionHistoryClient.js.map +1 -0
- package/dist/history/conversation-message.js +112 -0
- package/dist/history/conversation-message.js.map +1 -0
- package/dist/history/index.js +8 -0
- package/dist/history/index.js.map +1 -0
- package/dist/history/jsonl-replay.js +154 -0
- package/dist/history/jsonl-replay.js.map +1 -0
- package/dist/history/repair-tool-pairing.js +84 -0
- package/dist/history/repair-tool-pairing.js.map +1 -0
- package/dist/history/stall-phase-bridge.js +11 -0
- package/dist/history/stall-phase-bridge.js.map +1 -0
- package/dist/history/turn-accumulator.js +427 -0
- package/dist/history/turn-accumulator.js.map +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/ink-repl.d.ts.map +1 -0
- package/dist/ink-repl.js +4183 -0
- package/dist/ink-repl.js.map +1 -0
- package/dist/local-control-bootstrap.js +26 -0
- package/dist/local-control-bootstrap.js.map +1 -0
- package/dist/local-control-client.js +2 -0
- package/dist/local-control-client.js.map +1 -0
- package/dist/local-control-error-reporting.js +34 -0
- package/dist/local-control-error-reporting.js.map +1 -0
- package/dist/local-control-http-client.js +362 -0
- package/dist/local-control-http-client.js.map +1 -0
- package/dist/local-control-lazy-wrapper.js +363 -0
- package/dist/local-control-lazy-wrapper.js.map +1 -0
- package/dist/local-control-manager.js +146 -0
- package/dist/local-control-manager.js.map +1 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +62 -0
- package/dist/main.js.map +1 -0
- package/dist/network-security.js +62 -0
- package/dist/network-security.js.map +1 -0
- package/dist/networking-server.js +38 -0
- package/dist/networking-server.js.map +1 -0
- package/dist/peer-identity.js +23 -0
- package/dist/peer-identity.js.map +1 -0
- package/dist/polling-subscription.js +34 -0
- package/dist/polling-subscription.js.map +1 -0
- package/dist/relaunch.d.ts +63 -0
- package/dist/relaunch.d.ts.map +1 -0
- package/dist/relaunch.js +617 -0
- package/dist/relaunch.js.map +1 -0
- package/dist/release-notes.js +35 -0
- package/dist/release-notes.js.map +1 -0
- package/dist/repl-cleanup.js +47 -0
- package/dist/repl-cleanup.js.map +1 -0
- package/dist/runtime/configure-bun-sqlite.js +3 -0
- package/dist/runtime/configure-bun-sqlite.js.map +1 -0
- package/dist/runtime/crash-handlers.js +111 -0
- package/dist/runtime/crash-handlers.js.map +1 -0
- package/dist/runtime/interactive-invocation.js +39 -0
- package/dist/runtime/interactive-invocation.js.map +1 -0
- package/dist/runtime/internal-mode.js +14 -0
- package/dist/runtime/internal-mode.js.map +1 -0
- package/dist/runtime/launch-spec.js +64 -0
- package/dist/runtime/launch-spec.js.map +1 -0
- package/dist/runtime/owner-lease.js +44 -0
- package/dist/runtime/owner-lease.js.map +1 -0
- package/dist/runtime/public-mode.js +20 -0
- package/dist/runtime/public-mode.js.map +1 -0
- package/dist/runtime/run-internal-mode.d.ts.map +1 -0
- package/dist/runtime/run-internal-mode.js +18 -0
- package/dist/runtime/run-internal-mode.js.map +1 -0
- package/dist/runtime/runtime-kind.js +32 -0
- package/dist/runtime/runtime-kind.js.map +1 -0
- package/dist/runtime/spawn-aria.js +38 -0
- package/dist/runtime/spawn-aria.js.map +1 -0
- package/dist/selectable-client.js +2 -0
- package/dist/selectable-client.js.map +1 -0
- package/dist/selectable-peer.js +2 -0
- package/dist/selectable-peer.js.map +1 -0
- package/dist/session.js +203 -0
- package/dist/session.js.map +1 -0
- package/dist/slash-commands.js +80 -0
- package/dist/slash-commands.js.map +1 -0
- package/dist/sounds.js +210 -0
- package/dist/sounds.js.map +1 -0
- package/dist/ui/App.js +526 -0
- package/dist/ui/App.js.map +1 -0
- package/dist/ui/components/AnthropicMethodPicker.js +6 -0
- package/dist/ui/components/AnthropicMethodPicker.js.map +1 -0
- package/dist/ui/components/ArionPrompt.js +15 -0
- package/dist/ui/components/ArionPrompt.js.map +1 -0
- package/dist/ui/components/AutocompleteDropdown.js +23 -0
- package/dist/ui/components/AutocompleteDropdown.js.map +1 -0
- package/dist/ui/components/AutonomySelector.js +55 -0
- package/dist/ui/components/AutonomySelector.js.map +1 -0
- package/dist/ui/components/Banner.js +98 -0
- package/dist/ui/components/Banner.js.map +1 -0
- package/dist/ui/components/ConversationHistory.js +175 -0
- package/dist/ui/components/ConversationHistory.js.map +1 -0
- package/dist/ui/components/CopilotDeviceLoginFlow.js +88 -0
- package/dist/ui/components/CopilotDeviceLoginFlow.js.map +1 -0
- package/dist/ui/components/CopilotSourcePicker.js +50 -0
- package/dist/ui/components/CopilotSourcePicker.js.map +1 -0
- package/dist/ui/components/Cost.js +10 -0
- package/dist/ui/components/Cost.js.map +1 -0
- package/dist/ui/components/CustomSelect/option-map.js +30 -0
- package/dist/ui/components/CustomSelect/option-map.js.map +1 -0
- package/dist/ui/components/CustomSelect/select-option.js +13 -0
- package/dist/ui/components/CustomSelect/select-option.js.map +1 -0
- package/dist/ui/components/CustomSelect/select.js +42 -0
- package/dist/ui/components/CustomSelect/select.js.map +1 -0
- package/dist/ui/components/CustomSelect/use-select-state.js +179 -0
- package/dist/ui/components/CustomSelect/use-select-state.js.map +1 -0
- package/dist/ui/components/CustomSelect/use-select.js +15 -0
- package/dist/ui/components/CustomSelect/use-select.js.map +1 -0
- package/dist/ui/components/ErrorDisplay.js +35 -0
- package/dist/ui/components/ErrorDisplay.js.map +1 -0
- package/dist/ui/components/FallbackToolUseRejectedMessage.js +7 -0
- package/dist/ui/components/FallbackToolUseRejectedMessage.js.map +1 -0
- package/dist/ui/components/FileEditToolUpdatedMessage.js +57 -0
- package/dist/ui/components/FileEditToolUpdatedMessage.js.map +1 -0
- package/dist/ui/components/HandoffMarker.js +18 -0
- package/dist/ui/components/HandoffMarker.js.map +1 -0
- package/dist/ui/components/HighlightedCode.js +21 -0
- package/dist/ui/components/HighlightedCode.js.map +1 -0
- package/dist/ui/components/InputArea.js +187 -0
- package/dist/ui/components/InputArea.js.map +1 -0
- package/dist/ui/components/Message.js +25 -0
- package/dist/ui/components/Message.js.map +1 -0
- package/dist/ui/components/OAuthLoginFlow.js +113 -0
- package/dist/ui/components/OAuthLoginFlow.js.map +1 -0
- package/dist/ui/components/OutputTruncation.js +35 -0
- package/dist/ui/components/OutputTruncation.js.map +1 -0
- package/dist/ui/components/PermissionPrompt.js +79 -0
- package/dist/ui/components/PermissionPrompt.js.map +1 -0
- package/dist/ui/components/PipelineTimingPanel.js +15 -0
- package/dist/ui/components/PipelineTimingPanel.js.map +1 -0
- package/dist/ui/components/ProviderMethodPicker.js +61 -0
- package/dist/ui/components/ProviderMethodPicker.js.map +1 -0
- package/dist/ui/components/ProviderPicker.js +63 -0
- package/dist/ui/components/ProviderPicker.js.map +1 -0
- package/dist/ui/components/RenderItemView.js +71 -0
- package/dist/ui/components/RenderItemView.js.map +1 -0
- package/dist/ui/components/Spinner.js +46 -0
- package/dist/ui/components/Spinner.js.map +1 -0
- package/dist/ui/components/StatusBar.js +95 -0
- package/dist/ui/components/StatusBar.js.map +1 -0
- package/dist/ui/components/StreamingIndicator.js +55 -0
- package/dist/ui/components/StreamingIndicator.js.map +1 -0
- package/dist/ui/components/StructuredDiff.js +168 -0
- package/dist/ui/components/StructuredDiff.js.map +1 -0
- package/dist/ui/components/TextInputOverlay.js +43 -0
- package/dist/ui/components/TextInputOverlay.js.map +1 -0
- package/dist/ui/components/ThinkingBlock.js +82 -0
- package/dist/ui/components/ThinkingBlock.js.map +1 -0
- package/dist/ui/components/ToolCost.js +17 -0
- package/dist/ui/components/ToolCost.js.map +1 -0
- package/dist/ui/components/ToolExecution.js +61 -0
- package/dist/ui/components/ToolExecution.js.map +1 -0
- package/dist/ui/components/ToolHeader.js +51 -0
- package/dist/ui/components/ToolHeader.js.map +1 -0
- package/dist/ui/components/ToolRenderLayoutContext.js +14 -0
- package/dist/ui/components/ToolRenderLayoutContext.js.map +1 -0
- package/dist/ui/components/ToolResultWrapper.js +6 -0
- package/dist/ui/components/ToolResultWrapper.js.map +1 -0
- package/dist/ui/components/ToolUseLoader.js +35 -0
- package/dist/ui/components/ToolUseLoader.js.map +1 -0
- package/dist/ui/components/TraceWaterfall.js +91 -0
- package/dist/ui/components/TraceWaterfall.js.map +1 -0
- package/dist/ui/components/index.js +33 -0
- package/dist/ui/components/index.js.map +1 -0
- package/dist/ui/components/messages/AssistantTextMessage.js +25 -0
- package/dist/ui/components/messages/AssistantTextMessage.js.map +1 -0
- package/dist/ui/components/messages/UserImageMessage.js +12 -0
- package/dist/ui/components/messages/UserImageMessage.js.map +1 -0
- package/dist/ui/components/messages/UserTextMessage.js +12 -0
- package/dist/ui/components/messages/UserTextMessage.js.map +1 -0
- package/dist/ui/components/overlays/ArionSelector.js +68 -0
- package/dist/ui/components/overlays/ArionSelector.js.map +1 -0
- package/dist/ui/components/overlays/ClientSelector.js +62 -0
- package/dist/ui/components/overlays/ClientSelector.js.map +1 -0
- package/dist/ui/components/overlays/CommandPalette.js +67 -0
- package/dist/ui/components/overlays/CommandPalette.js.map +1 -0
- package/dist/ui/components/overlays/DaemonControl.js +87 -0
- package/dist/ui/components/overlays/DaemonControl.js.map +1 -0
- package/dist/ui/components/overlays/InviteShareOverlay.js +15 -0
- package/dist/ui/components/overlays/InviteShareOverlay.js.map +1 -0
- package/dist/ui/components/overlays/JoinInviteOverlay.js +32 -0
- package/dist/ui/components/overlays/JoinInviteOverlay.js.map +1 -0
- package/dist/ui/components/overlays/MemoryBrowser.js +100 -0
- package/dist/ui/components/overlays/MemoryBrowser.js.map +1 -0
- package/dist/ui/components/overlays/MessageSelector.js +123 -0
- package/dist/ui/components/overlays/MessageSelector.js.map +1 -0
- package/dist/ui/components/overlays/ModelSelector.js +211 -0
- package/dist/ui/components/overlays/ModelSelector.js.map +1 -0
- package/dist/ui/components/overlays/PairRequestOverlay.js +42 -0
- package/dist/ui/components/overlays/PairRequestOverlay.js.map +1 -0
- package/dist/ui/components/overlays/PeerSelector.js +84 -0
- package/dist/ui/components/overlays/PeerSelector.js.map +1 -0
- package/dist/ui/components/overlays/SessionSelector.js +102 -0
- package/dist/ui/components/overlays/SessionSelector.js.map +1 -0
- package/dist/ui/components/overlays/SoundSelector.js +86 -0
- package/dist/ui/components/overlays/SoundSelector.js.map +1 -0
- package/dist/ui/components/overlays/ThemeSelector.js +139 -0
- package/dist/ui/components/overlays/ThemeSelector.js.map +1 -0
- package/dist/ui/components/overlays/index.js +15 -0
- package/dist/ui/components/overlays/index.js.map +1 -0
- package/dist/ui/components/permissions/BashPermissionRequest/BashPermissionRequest.js +53 -0
- package/dist/ui/components/permissions/BashPermissionRequest/BashPermissionRequest.js.map +1 -0
- package/dist/ui/components/permissions/FallbackPermissionRequest.js +56 -0
- package/dist/ui/components/permissions/FallbackPermissionRequest.js.map +1 -0
- package/dist/ui/components/permissions/FileEditPermissionRequest/FileEditPermissionRequest.js +76 -0
- package/dist/ui/components/permissions/FileEditPermissionRequest/FileEditPermissionRequest.js.map +1 -0
- package/dist/ui/components/permissions/FileEditPermissionRequest/FileEditToolDiff.js +18 -0
- package/dist/ui/components/permissions/FileEditPermissionRequest/FileEditToolDiff.js.map +1 -0
- package/dist/ui/components/permissions/FileWritePermissionRequest/FileWritePermissionRequest.js +64 -0
- package/dist/ui/components/permissions/FileWritePermissionRequest/FileWritePermissionRequest.js.map +1 -0
- package/dist/ui/components/permissions/FileWritePermissionRequest/FileWriteToolDiff.js +26 -0
- package/dist/ui/components/permissions/FileWritePermissionRequest/FileWriteToolDiff.js.map +1 -0
- package/dist/ui/components/permissions/FilesystemPermissionRequest/FilesystemPermissionRequest.js +141 -0
- package/dist/ui/components/permissions/FilesystemPermissionRequest/FilesystemPermissionRequest.js.map +1 -0
- package/dist/ui/components/permissions/PermissionRequest.js +70 -0
- package/dist/ui/components/permissions/PermissionRequest.js.map +1 -0
- package/dist/ui/components/permissions/PermissionRequestTitle.js +41 -0
- package/dist/ui/components/permissions/PermissionRequestTitle.js.map +1 -0
- package/dist/ui/components/permissions/hooks.js +10 -0
- package/dist/ui/components/permissions/hooks.js.map +1 -0
- package/dist/ui/components/permissions/toolUseOptions.js +68 -0
- package/dist/ui/components/permissions/toolUseOptions.js.map +1 -0
- package/dist/ui/components/permissions/utils.js +10 -0
- package/dist/ui/components/permissions/utils.js.map +1 -0
- package/dist/ui/components/text-input/Cursor.js +326 -0
- package/dist/ui/components/text-input/Cursor.js.map +1 -0
- package/dist/ui/components/text-input/TextInput.js +231 -0
- package/dist/ui/components/text-input/TextInput.js.map +1 -0
- package/dist/ui/components/text-input/imagePaste.js +28 -0
- package/dist/ui/components/text-input/imagePaste.js.map +1 -0
- package/dist/ui/components/text-input/index.js +6 -0
- package/dist/ui/components/text-input/index.js.map +1 -0
- package/dist/ui/components/text-input/useDoublePress.js +30 -0
- package/dist/ui/components/text-input/useDoublePress.js.map +1 -0
- package/dist/ui/components/text-input/useTextInput.js +245 -0
- package/dist/ui/components/text-input/useTextInput.js.map +1 -0
- package/dist/ui/components/tool-types.js +9 -0
- package/dist/ui/components/tool-types.js.map +1 -0
- package/dist/ui/constants/figures.js +4 -0
- package/dist/ui/constants/figures.js.map +1 -0
- package/dist/ui/constants/index.js +3 -0
- package/dist/ui/constants/index.js.map +1 -0
- package/dist/ui/display-mode.js +93 -0
- package/dist/ui/display-mode.js.map +1 -0
- package/dist/ui/display-policy.js +19 -0
- package/dist/ui/display-policy.js.map +1 -0
- package/dist/ui/hooks/index.js +6 -0
- package/dist/ui/hooks/index.js.map +1 -0
- package/dist/ui/hooks/useCommandAutocomplete.js +93 -0
- package/dist/ui/hooks/useCommandAutocomplete.js.map +1 -0
- package/dist/ui/hooks/useDoublePress.js +37 -0
- package/dist/ui/hooks/useDoublePress.js.map +1 -0
- package/dist/ui/hooks/useIndicatorState.js +55 -0
- package/dist/ui/hooks/useIndicatorState.js.map +1 -0
- package/dist/ui/hooks/useInterval.js +23 -0
- package/dist/ui/hooks/useInterval.js.map +1 -0
- package/dist/ui/hooks/useKeyboardShortcuts.js +127 -0
- package/dist/ui/hooks/useKeyboardShortcuts.js.map +1 -0
- package/dist/ui/hooks/useTerminalSize.js +55 -0
- package/dist/ui/hooks/useTerminalSize.js.map +1 -0
- package/dist/ui/hooks/useUnifiedMessages.js +117 -0
- package/dist/ui/hooks/useUnifiedMessages.js.map +1 -0
- package/dist/ui/indicator-state.js +44 -0
- package/dist/ui/indicator-state.js.map +1 -0
- package/dist/ui/markdown/highlight.js +44 -0
- package/dist/ui/markdown/highlight.js.map +1 -0
- package/dist/ui/markdown/index.js +1460 -0
- package/dist/ui/markdown/index.js.map +1 -0
- package/dist/ui/markdown/tokenizer.js +24 -0
- package/dist/ui/markdown/tokenizer.js.map +1 -0
- package/dist/ui/render-item.js +5 -0
- package/dist/ui/render-item.js.map +1 -0
- package/dist/ui/screens/REPL.js +119 -0
- package/dist/ui/screens/REPL.js.map +1 -0
- package/dist/ui/screens/approval-lifecycle.js +38 -0
- package/dist/ui/screens/approval-lifecycle.js.map +1 -0
- package/dist/ui/status-line.js +72 -0
- package/dist/ui/status-line.js.map +1 -0
- package/dist/ui/theme/index.js +51 -0
- package/dist/ui/theme/index.js.map +1 -0
- package/dist/ui/theme/themes/claude-dark-daltonized.js +51 -0
- package/dist/ui/theme/themes/claude-dark-daltonized.js.map +1 -0
- package/dist/ui/theme/themes/claude-dark.js +50 -0
- package/dist/ui/theme/themes/claude-dark.js.map +1 -0
- package/dist/ui/theme/themes/claude-light-daltonized.js +51 -0
- package/dist/ui/theme/themes/claude-light-daltonized.js.map +1 -0
- package/dist/ui/theme/themes/claude-light.js +50 -0
- package/dist/ui/theme/themes/claude-light.js.map +1 -0
- package/dist/ui/theme/themes/dark-accessible.js +18 -0
- package/dist/ui/theme/themes/dark-accessible.js.map +1 -0
- package/dist/ui/theme/themes/dark.js +49 -0
- package/dist/ui/theme/themes/dark.js.map +1 -0
- package/dist/ui/theme/themes/light-accessible.js +18 -0
- package/dist/ui/theme/themes/light-accessible.js.map +1 -0
- package/dist/ui/theme/themes/light.js +49 -0
- package/dist/ui/theme/themes/light.js.map +1 -0
- package/dist/ui/theme/types.js +3 -0
- package/dist/ui/theme/types.js.map +1 -0
- package/dist/ui/theme.js +142 -0
- package/dist/ui/theme.js.map +1 -0
- package/dist/ui/to-render-items.js +145 -0
- package/dist/ui/to-render-items.js.map +1 -0
- package/dist/ui/tools/AgentTool/index.js +30 -0
- package/dist/ui/tools/AgentTool/index.js.map +1 -0
- package/dist/ui/tools/ArchitectTool/index.js +31 -0
- package/dist/ui/tools/ArchitectTool/index.js.map +1 -0
- package/dist/ui/tools/AskUserTool/index.js +46 -0
- package/dist/ui/tools/AskUserTool/index.js.map +1 -0
- package/dist/ui/tools/BashTool/BashToolResultMessage.js +11 -0
- package/dist/ui/tools/BashTool/BashToolResultMessage.js.map +1 -0
- package/dist/ui/tools/BashTool/OutputLine.js +21 -0
- package/dist/ui/tools/BashTool/OutputLine.js.map +1 -0
- package/dist/ui/tools/BashTool/index.js +91 -0
- package/dist/ui/tools/BashTool/index.js.map +1 -0
- package/dist/ui/tools/BrowseTool/index.js +43 -0
- package/dist/ui/tools/BrowseTool/index.js.map +1 -0
- package/dist/ui/tools/BrowserTool/index.js +47 -0
- package/dist/ui/tools/BrowserTool/index.js.map +1 -0
- package/dist/ui/tools/CbmTool/index.js +188 -0
- package/dist/ui/tools/CbmTool/index.js.map +1 -0
- package/dist/ui/tools/CheckDelegationTool/index.js +46 -0
- package/dist/ui/tools/CheckDelegationTool/index.js.map +1 -0
- package/dist/ui/tools/CheckMessagesTool/index.js +85 -0
- package/dist/ui/tools/CheckMessagesTool/index.js.map +1 -0
- package/dist/ui/tools/CreateQuipTool/index.js +30 -0
- package/dist/ui/tools/CreateQuipTool/index.js.map +1 -0
- package/dist/ui/tools/CreateSkillTool/index.js +22 -0
- package/dist/ui/tools/CreateSkillTool/index.js.map +1 -0
- package/dist/ui/tools/CreateToolTool/index.js +31 -0
- package/dist/ui/tools/CreateToolTool/index.js.map +1 -0
- package/dist/ui/tools/DelegateRemoteTool/index.js +42 -0
- package/dist/ui/tools/DelegateRemoteTool/index.js.map +1 -0
- package/dist/ui/tools/DeployTool/index.js +47 -0
- package/dist/ui/tools/DeployTool/index.js.map +1 -0
- package/dist/ui/tools/FffTool/index.js +103 -0
- package/dist/ui/tools/FffTool/index.js.map +1 -0
- package/dist/ui/tools/FileEditTool/index.js +67 -0
- package/dist/ui/tools/FileEditTool/index.js.map +1 -0
- package/dist/ui/tools/FileReadTool/index.js +68 -0
- package/dist/ui/tools/FileReadTool/index.js.map +1 -0
- package/dist/ui/tools/FileWriteTool/index.js +61 -0
- package/dist/ui/tools/FileWriteTool/index.js.map +1 -0
- package/dist/ui/tools/ForkTool/index.js +47 -0
- package/dist/ui/tools/ForkTool/index.js.map +1 -0
- package/dist/ui/tools/FrgTool/index.js +96 -0
- package/dist/ui/tools/FrgTool/index.js.map +1 -0
- package/dist/ui/tools/GetThreadTool/index.js +39 -0
- package/dist/ui/tools/GetThreadTool/index.js.map +1 -0
- package/dist/ui/tools/GlobTool/index.js +50 -0
- package/dist/ui/tools/GlobTool/index.js.map +1 -0
- package/dist/ui/tools/GrepTool/index.js +84 -0
- package/dist/ui/tools/GrepTool/index.js.map +1 -0
- package/dist/ui/tools/HatchArionTool/index.js +36 -0
- package/dist/ui/tools/HatchArionTool/index.js.map +1 -0
- package/dist/ui/tools/LearnSkillTool/index.js +22 -0
- package/dist/ui/tools/LearnSkillTool/index.js.map +1 -0
- package/dist/ui/tools/LearnTool/index.js +43 -0
- package/dist/ui/tools/LearnTool/index.js.map +1 -0
- package/dist/ui/tools/LearnToolTool/index.js +22 -0
- package/dist/ui/tools/LearnToolTool/index.js.map +1 -0
- package/dist/ui/tools/ListClientsTool/index.js +39 -0
- package/dist/ui/tools/ListClientsTool/index.js.map +1 -0
- package/dist/ui/tools/LspTool/index.js +261 -0
- package/dist/ui/tools/LspTool/index.js.map +1 -0
- package/dist/ui/tools/MCPTool/index.js +33 -0
- package/dist/ui/tools/MCPTool/index.js.map +1 -0
- package/dist/ui/tools/ManageNetworkTool/index.js +53 -0
- package/dist/ui/tools/ManageNetworkTool/index.js.map +1 -0
- package/dist/ui/tools/MemoryReadTool/index.js +64 -0
- package/dist/ui/tools/MemoryReadTool/index.js.map +1 -0
- package/dist/ui/tools/MemoryWriteTool/index.js +20 -0
- package/dist/ui/tools/MemoryWriteTool/index.js.map +1 -0
- package/dist/ui/tools/NotebookEditTool/index.js +33 -0
- package/dist/ui/tools/NotebookEditTool/index.js.map +1 -0
- package/dist/ui/tools/NotebookReadTool/index.js +25 -0
- package/dist/ui/tools/NotebookReadTool/index.js.map +1 -0
- package/dist/ui/tools/OutlookReadTool/index.js +66 -0
- package/dist/ui/tools/OutlookReadTool/index.js.map +1 -0
- package/dist/ui/tools/OutlookReplyTool/index.js +49 -0
- package/dist/ui/tools/OutlookReplyTool/index.js.map +1 -0
- package/dist/ui/tools/OutlookSendTool/index.js +49 -0
- package/dist/ui/tools/OutlookSendTool/index.js.map +1 -0
- package/dist/ui/tools/PauseDelegationTool/index.js +35 -0
- package/dist/ui/tools/PauseDelegationTool/index.js.map +1 -0
- package/dist/ui/tools/ProbeTool/index.js +121 -0
- package/dist/ui/tools/ProbeTool/index.js.map +1 -0
- package/dist/ui/tools/ProcessTool/index.js +66 -0
- package/dist/ui/tools/ProcessTool/index.js.map +1 -0
- package/dist/ui/tools/QuestListTool/index.js +46 -0
- package/dist/ui/tools/QuestListTool/index.js.map +1 -0
- package/dist/ui/tools/QuestReportTool/index.js +49 -0
- package/dist/ui/tools/QuestReportTool/index.js.map +1 -0
- package/dist/ui/tools/QuestUpdateTool/index.js +87 -0
- package/dist/ui/tools/QuestUpdateTool/index.js.map +1 -0
- package/dist/ui/tools/QuipCommentTool/index.js +69 -0
- package/dist/ui/tools/QuipCommentTool/index.js.map +1 -0
- package/dist/ui/tools/QuipReadTool/index.js +71 -0
- package/dist/ui/tools/QuipReadTool/index.js.map +1 -0
- package/dist/ui/tools/RestArionTool/index.js +32 -0
- package/dist/ui/tools/RestArionTool/index.js.map +1 -0
- package/dist/ui/tools/RestartTool/index.js +35 -0
- package/dist/ui/tools/RestartTool/index.js.map +1 -0
- package/dist/ui/tools/ResumeDelegationTool/index.js +35 -0
- package/dist/ui/tools/ResumeDelegationTool/index.js.map +1 -0
- package/dist/ui/tools/RetireArionTool/index.js +32 -0
- package/dist/ui/tools/RetireArionTool/index.js.map +1 -0
- package/dist/ui/tools/RgTool/index.js +73 -0
- package/dist/ui/tools/RgTool/index.js.map +1 -0
- package/dist/ui/tools/SearchKnowledgeTool/index.js +43 -0
- package/dist/ui/tools/SearchKnowledgeTool/index.js.map +1 -0
- package/dist/ui/tools/SearchMessagesTool/index.js +43 -0
- package/dist/ui/tools/SearchMessagesTool/index.js.map +1 -0
- package/dist/ui/tools/SelfDiagnoseTool/index.js +61 -0
- package/dist/ui/tools/SelfDiagnoseTool/index.js.map +1 -0
- package/dist/ui/tools/SendMessageTool/index.js +45 -0
- package/dist/ui/tools/SendMessageTool/index.js.map +1 -0
- package/dist/ui/tools/SerenaTool/index.js +124 -0
- package/dist/ui/tools/SerenaTool/index.js.map +1 -0
- package/dist/ui/tools/SessionHistoryTool/index.js +52 -0
- package/dist/ui/tools/SessionHistoryTool/index.js.map +1 -0
- package/dist/ui/tools/SgTool/index.js +80 -0
- package/dist/ui/tools/SgTool/index.js.map +1 -0
- package/dist/ui/tools/SlackReactTool/index.js +41 -0
- package/dist/ui/tools/SlackReactTool/index.js.map +1 -0
- package/dist/ui/tools/SlackReadTool/index.js +48 -0
- package/dist/ui/tools/SlackReadTool/index.js.map +1 -0
- package/dist/ui/tools/SlackSendTool/index.js +45 -0
- package/dist/ui/tools/SlackSendTool/index.js.map +1 -0
- package/dist/ui/tools/SpawnWorkerTool/index.js +33 -0
- package/dist/ui/tools/SpawnWorkerTool/index.js.map +1 -0
- package/dist/ui/tools/StickerRequestTool/index.js +19 -0
- package/dist/ui/tools/StickerRequestTool/index.js.map +1 -0
- package/dist/ui/tools/ThinkTool/index.js +17 -0
- package/dist/ui/tools/ThinkTool/index.js.map +1 -0
- package/dist/ui/tools/UgTool/index.js +108 -0
- package/dist/ui/tools/UgTool/index.js.map +1 -0
- package/dist/ui/tools/UseSkillTool/index.js +22 -0
- package/dist/ui/tools/UseSkillTool/index.js.map +1 -0
- package/dist/ui/tools/WakeArionTool/index.js +32 -0
- package/dist/ui/tools/WakeArionTool/index.js.map +1 -0
- package/dist/ui/tools/WebFetchTool/index.js +56 -0
- package/dist/ui/tools/WebFetchTool/index.js.map +1 -0
- package/dist/ui/tools/WebSearchTool/index.js +44 -0
- package/dist/ui/tools/WebSearchTool/index.js.map +1 -0
- package/dist/ui/tools/lsTool/index.js +58 -0
- package/dist/ui/tools/lsTool/index.js.map +1 -0
- package/dist/ui/tools/registry.js +197 -0
- package/dist/ui/tools/registry.js.map +1 -0
- package/dist/ui/tools/tool-renderer.js +11 -0
- package/dist/ui/tools/tool-renderer.js.map +1 -0
- package/dist/ui/tools/truncation.js +35 -0
- package/dist/ui/tools/truncation.js.map +1 -0
- package/dist/ui/types/anthropic.js +4 -0
- package/dist/ui/types/anthropic.js.map +1 -0
- package/dist/ui/types/index.js +2 -0
- package/dist/ui/types/index.js.map +1 -0
- package/dist/ui/types/message.js +3 -0
- package/dist/ui/types/message.js.map +1 -0
- package/dist/ui/types/tool.js +4 -0
- package/dist/ui/types/tool.js.map +1 -0
- package/dist/ui/utils/array.js +4 -0
- package/dist/ui/utils/array.js.map +1 -0
- package/dist/ui/utils/cursor.js +131 -0
- package/dist/ui/utils/cursor.js.map +1 -0
- package/dist/ui/utils/diff.js +120 -0
- package/dist/ui/utils/diff.js.map +1 -0
- package/dist/ui/utils/format.js +42 -0
- package/dist/ui/utils/format.js.map +1 -0
- package/dist/ui/utils/fuzzy.js +59 -0
- package/dist/ui/utils/fuzzy.js.map +1 -0
- package/dist/ui/utils/index.js +11 -0
- package/dist/ui/utils/index.js.map +1 -0
- package/dist/ui/utils/keys.js +8 -0
- package/dist/ui/utils/keys.js.map +1 -0
- package/dist/ui/utils/patch.js +17 -0
- package/dist/ui/utils/patch.js.map +1 -0
- package/dist/ui/utils/risk.js +114 -0
- package/dist/ui/utils/risk.js.map +1 -0
- package/dist/ui/utils/terminal-image.js +70 -0
- package/dist/ui/utils/terminal-image.js.map +1 -0
- package/dist/ui/utils/validation.js +48 -0
- package/dist/ui/utils/validation.js.map +1 -0
- package/dist/ui/verb-pairs.js +248 -0
- package/dist/ui/verb-pairs.js.map +1 -0
- package/dist/ui.js +131 -0
- package/dist/ui.js.map +1 -0
- package/package.json +77 -15
- package/src/entrypoints/command-mode.ts +5 -0
- package/src/entrypoints/daemon.ts +54 -0
- package/src/entrypoints/headless-stdio.ts +27 -0
- package/src/entrypoints/interactive.ts +112 -0
- package/src/main.ts +72 -0
- package/src/runtime/configure-bun-sqlite.ts +3 -0
- package/src/runtime/crash-handlers.ts +128 -0
- package/src/runtime/interactive-invocation.test.ts +42 -0
- package/src/runtime/interactive-invocation.ts +51 -0
- package/src/runtime/internal-mode.test.ts +19 -0
- package/src/runtime/internal-mode.ts +24 -0
- package/src/runtime/launch-spec.test.ts +26 -0
- package/src/runtime/launch-spec.ts +84 -0
- package/src/runtime/owner-lease.ts +52 -0
- package/src/runtime/public-mode.test.ts +18 -0
- package/src/runtime/public-mode.ts +19 -0
- package/src/runtime/run-internal-mode.ts +19 -0
- package/src/runtime/runtime-kind.test.ts +23 -0
- package/src/runtime/runtime-kind.ts +41 -0
- package/src/runtime/spawn-aria.ts +62 -0
|
@@ -0,0 +1,1108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Slash command handler for /login — authenticate with providers.
|
|
3
|
+
*
|
|
4
|
+
* Supports three result modes:
|
|
5
|
+
* - PickerResult: `/login` with no args → return provider list for interactive picker
|
|
6
|
+
* - DirectResult: `/login bedrock`, `/login anthropic <key>` → immediate result
|
|
7
|
+
* - OAuthFlowResult: `/login anthropic` (no key) → trigger OAuth flow component
|
|
8
|
+
*/
|
|
9
|
+
import { ensureAuthProfileStore, syncExternalCliCredentials, isProfileInCooldown, upsertAuthProfile, updateAuthProfileStoreWithLockSync, refreshBedrockSsoToken, loginBedrockSso, listProfilesForProvider, loginWithGitHubCopilotToken, readClaudeCodeCredentialsCached, readCodexCredentialsCached, readGeminiCredentialsCached, normalizeProviderId, OPENAI_CODEX_OAUTH_PROFILE_ID, } from "@aria-cli/auth";
|
|
10
|
+
import { spawnSync } from "node:child_process";
|
|
11
|
+
import { loadConfig, saveConfig, persistAwsSelectorHintsFromEnv } from "../config.js";
|
|
12
|
+
function readGhAuthToken() {
|
|
13
|
+
try {
|
|
14
|
+
const result = spawnSync("gh", ["auth", "token", "-h", "github.com"], {
|
|
15
|
+
encoding: "utf8",
|
|
16
|
+
timeout: 5000,
|
|
17
|
+
});
|
|
18
|
+
if (result.error) {
|
|
19
|
+
return { error: result.error.message };
|
|
20
|
+
}
|
|
21
|
+
if (result.status !== 0) {
|
|
22
|
+
const stderr = (result.stderr || "").trim();
|
|
23
|
+
const stdout = (result.stdout || "").trim();
|
|
24
|
+
return { error: stderr || stdout || `gh auth token exited with status ${result.status}` };
|
|
25
|
+
}
|
|
26
|
+
const token = (result.stdout || "").trim();
|
|
27
|
+
if (token.length < 8) {
|
|
28
|
+
return { error: "gh auth token returned an empty/short token" };
|
|
29
|
+
}
|
|
30
|
+
return { token };
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
return { error: error instanceof Error ? error.message : String(error) };
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function readGhUsernames(host = "github.com") {
|
|
37
|
+
try {
|
|
38
|
+
const result = spawnSync("gh", ["auth", "status", "-h", host], {
|
|
39
|
+
encoding: "utf8",
|
|
40
|
+
timeout: 5000,
|
|
41
|
+
});
|
|
42
|
+
const text = `${result.stdout || ""}\n${result.stderr || ""}`;
|
|
43
|
+
const names = new Set();
|
|
44
|
+
for (const line of text.split(/\r?\n/)) {
|
|
45
|
+
const m = line.match(/Logged in to .* account\s+([^\s]+)/i);
|
|
46
|
+
if (m?.[1]) {
|
|
47
|
+
names.add(m[1]);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return [...names];
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return [];
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function readGhTokenForUser(user, host = "github.com") {
|
|
57
|
+
try {
|
|
58
|
+
const result = spawnSync("gh", ["auth", "token", "-h", host, "-u", user], {
|
|
59
|
+
encoding: "utf8",
|
|
60
|
+
timeout: 5000,
|
|
61
|
+
});
|
|
62
|
+
if (result.error) {
|
|
63
|
+
return { error: result.error.message };
|
|
64
|
+
}
|
|
65
|
+
if (result.status !== 0) {
|
|
66
|
+
return { error: (result.stderr || result.stdout || "").trim() || "gh token failed" };
|
|
67
|
+
}
|
|
68
|
+
const token = (result.stdout || "").trim();
|
|
69
|
+
if (token.length < 8) {
|
|
70
|
+
return { error: "empty/short token" };
|
|
71
|
+
}
|
|
72
|
+
return { token };
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
return { error: error instanceof Error ? error.message : String(error) };
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function readCopilotLastLoggedInUser() {
|
|
79
|
+
try {
|
|
80
|
+
const configPath = `${process.env.HOME || ""}/.copilot/config.json`;
|
|
81
|
+
const result = spawnSync("node", [
|
|
82
|
+
"-e",
|
|
83
|
+
`const fs=require('fs');const p=${JSON.stringify(configPath)};if(!fs.existsSync(p)){process.exit(0);}const j=JSON.parse(fs.readFileSync(p,'utf8'));const login=j?.last_logged_in_user?.login||j?.logged_in_users?.[0]?.login||'';if(login)process.stdout.write(login);`,
|
|
84
|
+
], {
|
|
85
|
+
encoding: "utf8",
|
|
86
|
+
timeout: 5000,
|
|
87
|
+
});
|
|
88
|
+
const login = (result.stdout || "").trim();
|
|
89
|
+
return login ? { login } : {};
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
return { error: error instanceof Error ? error.message : String(error) };
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function parseCopilotLoginArgs(raw) {
|
|
96
|
+
const text = raw?.trim() ?? "";
|
|
97
|
+
if (!text) {
|
|
98
|
+
return { useGhToken: true, autoSelectSource: true };
|
|
99
|
+
}
|
|
100
|
+
const parts = text.split(/\s+/).filter(Boolean);
|
|
101
|
+
let token;
|
|
102
|
+
let profileLabel;
|
|
103
|
+
let useGhToken = true;
|
|
104
|
+
let autoSelectSource = false;
|
|
105
|
+
const takeValue = (index) => {
|
|
106
|
+
const value = parts[index + 1];
|
|
107
|
+
return value && !value.startsWith("--") ? value : undefined;
|
|
108
|
+
};
|
|
109
|
+
for (let i = 0; i < parts.length; i += 1) {
|
|
110
|
+
const part = parts[i];
|
|
111
|
+
if (part === "--profile" || part === "--label") {
|
|
112
|
+
const value = takeValue(i);
|
|
113
|
+
if (value) {
|
|
114
|
+
profileLabel = value;
|
|
115
|
+
i += 1;
|
|
116
|
+
}
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
if (part.startsWith("--profile=") || part.startsWith("--label=")) {
|
|
120
|
+
profileLabel = part.split("=", 2)[1]?.trim() || profileLabel;
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
if (part === "--source") {
|
|
124
|
+
const value = takeValue(i)?.toLowerCase();
|
|
125
|
+
if (value === "device") {
|
|
126
|
+
useGhToken = false;
|
|
127
|
+
}
|
|
128
|
+
else if (value === "auto") {
|
|
129
|
+
autoSelectSource = true;
|
|
130
|
+
}
|
|
131
|
+
i += value ? 1 : 0;
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
if (part.startsWith("--source=")) {
|
|
135
|
+
const value = part.split("=", 2)[1]?.toLowerCase();
|
|
136
|
+
if (value === "device") {
|
|
137
|
+
useGhToken = false;
|
|
138
|
+
}
|
|
139
|
+
else if (value === "auto") {
|
|
140
|
+
autoSelectSource = true;
|
|
141
|
+
}
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
if (!part.startsWith("--") && !token) {
|
|
145
|
+
token = part;
|
|
146
|
+
useGhToken = false;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (token && token.length > 0) {
|
|
150
|
+
useGhToken = false;
|
|
151
|
+
}
|
|
152
|
+
return { token, profileLabel, useGhToken, autoSelectSource };
|
|
153
|
+
}
|
|
154
|
+
function sanitizeProfileLabel(input) {
|
|
155
|
+
const raw = (input || "").trim();
|
|
156
|
+
if (!raw)
|
|
157
|
+
return undefined;
|
|
158
|
+
return (raw
|
|
159
|
+
.toLowerCase()
|
|
160
|
+
.replace(/[^a-z0-9._-]+/g, "-")
|
|
161
|
+
.replace(/^-+|-+$/g, "") || undefined);
|
|
162
|
+
}
|
|
163
|
+
function buildCopilotSourceOptions() {
|
|
164
|
+
const options = [];
|
|
165
|
+
const seen = new Set();
|
|
166
|
+
// Check GitHub token env vars (GH_TOKEN, GITHUB_TOKEN, COPILOT_GITHUB_TOKEN)
|
|
167
|
+
const envTokenVars = ["GH_TOKEN", "GITHUB_TOKEN", "COPILOT_GITHUB_TOKEN"];
|
|
168
|
+
for (const varName of envTokenVars) {
|
|
169
|
+
const token = process.env[varName]?.trim();
|
|
170
|
+
if (token && token.length >= 8) {
|
|
171
|
+
const key = `env:${varName}`;
|
|
172
|
+
if (!seen.has(key)) {
|
|
173
|
+
options.push({
|
|
174
|
+
id: key,
|
|
175
|
+
label: `Using ${varName} from environment`,
|
|
176
|
+
source: "env",
|
|
177
|
+
token,
|
|
178
|
+
status: "connected",
|
|
179
|
+
});
|
|
180
|
+
seen.add(key);
|
|
181
|
+
}
|
|
182
|
+
// Only show the first env var that has a token — they're likely the same value
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
const ghUsers = readGhUsernames("github.com");
|
|
187
|
+
for (const user of ghUsers) {
|
|
188
|
+
const token = readGhTokenForUser(user, "github.com").token;
|
|
189
|
+
const label = `GitHub CLI account: ${user}`;
|
|
190
|
+
const key = `gh:${user}`;
|
|
191
|
+
if (!seen.has(key)) {
|
|
192
|
+
options.push({
|
|
193
|
+
id: key,
|
|
194
|
+
label,
|
|
195
|
+
source: "gh",
|
|
196
|
+
login: user,
|
|
197
|
+
token,
|
|
198
|
+
profileLabel: sanitizeProfileLabel(user),
|
|
199
|
+
status: token ? "connected" : "none",
|
|
200
|
+
});
|
|
201
|
+
seen.add(key);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
// Check existing Copilot auth profiles in the store — these already have
|
|
205
|
+
// working tokens and don't need device flow re-authentication.
|
|
206
|
+
const store = ensureAuthProfileStore();
|
|
207
|
+
syncExternalCliCredentials(store);
|
|
208
|
+
const copilotProfiles = listProfilesForProvider(store, "github-copilot");
|
|
209
|
+
for (const profileId of copilotProfiles) {
|
|
210
|
+
const profile = store.profiles[profileId];
|
|
211
|
+
if (!profile)
|
|
212
|
+
continue;
|
|
213
|
+
// Extract the login name from the profile ID (e.g. "github-copilot:hole_axoncorp" → "hole_axoncorp")
|
|
214
|
+
const login = profileId.split(":").slice(1).join(":") || profileId;
|
|
215
|
+
const key = `profile:${login}`;
|
|
216
|
+
if (seen.has(key))
|
|
217
|
+
continue;
|
|
218
|
+
// For OAuth profiles, the refresh token is the original GitHub token
|
|
219
|
+
// that can be used for Copilot token exchange via loginWithGitHubCopilotToken.
|
|
220
|
+
const token = profile.type === "oauth" && profile.refresh ? profile.refresh : undefined;
|
|
221
|
+
const isFresh = profile.type === "oauth" && Date.now() < profile.expires;
|
|
222
|
+
options.push({
|
|
223
|
+
id: key,
|
|
224
|
+
label: `Copilot profile: ${login}`,
|
|
225
|
+
source: "copilot",
|
|
226
|
+
login,
|
|
227
|
+
token,
|
|
228
|
+
profileLabel: sanitizeProfileLabel(login),
|
|
229
|
+
status: isFresh || token ? "connected" : "none",
|
|
230
|
+
});
|
|
231
|
+
seen.add(key);
|
|
232
|
+
}
|
|
233
|
+
const copilot = readCopilotLastLoggedInUser();
|
|
234
|
+
if (copilot.login) {
|
|
235
|
+
const key = `copilot:${copilot.login}`;
|
|
236
|
+
// Only add if not already covered by an auth profile above
|
|
237
|
+
if (!seen.has(key) && !seen.has(`profile:${copilot.login}`)) {
|
|
238
|
+
options.push({
|
|
239
|
+
id: key,
|
|
240
|
+
label: `Copilot CLI last login: ${copilot.login}`,
|
|
241
|
+
source: "copilot",
|
|
242
|
+
login: copilot.login,
|
|
243
|
+
profileLabel: sanitizeProfileLabel(copilot.login),
|
|
244
|
+
status: "connected",
|
|
245
|
+
});
|
|
246
|
+
seen.add(key);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
options.push({
|
|
250
|
+
id: "device:new",
|
|
251
|
+
label: "Sign in with a new GitHub account (device flow)",
|
|
252
|
+
source: "device",
|
|
253
|
+
status: "none",
|
|
254
|
+
});
|
|
255
|
+
return options;
|
|
256
|
+
}
|
|
257
|
+
// ---------------------------------------------------------------------------
|
|
258
|
+
// Anthropic method picker — 3-method login flow + import + setup-token
|
|
259
|
+
// ---------------------------------------------------------------------------
|
|
260
|
+
function buildAnthropicMethodOptions() {
|
|
261
|
+
const options = [];
|
|
262
|
+
const config = loadConfig();
|
|
263
|
+
if (persistAwsSelectorHintsFromEnv(config)) {
|
|
264
|
+
saveConfig(config);
|
|
265
|
+
}
|
|
266
|
+
const configuredAwsProfile = config.awsProfile?.trim();
|
|
267
|
+
// 0. Check for ANTHROPIC_API_KEY in environment
|
|
268
|
+
const envKey = process.env.ANTHROPIC_API_KEY?.trim();
|
|
269
|
+
if (envKey && envKey.length > 8) {
|
|
270
|
+
const looksValid = envKey.startsWith("sk-ant-api");
|
|
271
|
+
options.push({
|
|
272
|
+
id: "env-key",
|
|
273
|
+
label: "Using ANTHROPIC_API_KEY from environment",
|
|
274
|
+
description: looksValid ? "API key detected" : "Key format unrecognized",
|
|
275
|
+
method: "env-key",
|
|
276
|
+
status: looksValid ? "connected" : "none",
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
// 1. Check existing Anthropic profiles in the auth store
|
|
280
|
+
const store = ensureAuthProfileStore();
|
|
281
|
+
syncExternalCliCredentials(store);
|
|
282
|
+
const anthropicProfiles = listProfilesForProvider(store, "anthropic");
|
|
283
|
+
for (const profileId of anthropicProfiles) {
|
|
284
|
+
const profile = store.profiles[profileId];
|
|
285
|
+
if (!profile)
|
|
286
|
+
continue;
|
|
287
|
+
const isFresh = (profile.type === "oauth" || profile.type === "token") &&
|
|
288
|
+
"expires" in profile &&
|
|
289
|
+
typeof profile.expires === "number" &&
|
|
290
|
+
profile.expires > Date.now();
|
|
291
|
+
options.push({
|
|
292
|
+
id: `profile:${profileId}`,
|
|
293
|
+
label: `Saved profile: ${profileId}`,
|
|
294
|
+
description: isFresh ? "Credentials active" : "Credentials expired — will refresh on use",
|
|
295
|
+
method: "api-key", // existing profiles don't need a new login method
|
|
296
|
+
status: isFresh ? "connected" : "available",
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
// 2. Check if Claude Code CLI credentials exist
|
|
300
|
+
const claudeCred = readClaudeCodeCredentialsCached();
|
|
301
|
+
if (claudeCred) {
|
|
302
|
+
const isFresh = claudeCred.expires > Date.now();
|
|
303
|
+
options.push({
|
|
304
|
+
id: "claude-cli",
|
|
305
|
+
label: "Import from Claude Code CLI",
|
|
306
|
+
description: isFresh
|
|
307
|
+
? "Use existing Claude Code credentials from keychain"
|
|
308
|
+
: "Credentials expired, will refresh",
|
|
309
|
+
method: "claude-cli",
|
|
310
|
+
status: isFresh ? "connected" : "available",
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
// 3. Claude subscription (OAuth via claude.ai)
|
|
314
|
+
options.push({
|
|
315
|
+
id: "subscription",
|
|
316
|
+
label: "Claude account with subscription",
|
|
317
|
+
description: "Pro, Max, Team, or Enterprise",
|
|
318
|
+
method: "subscription",
|
|
319
|
+
status: resolveProviderStatus("anthropic") === "connected" ? "connected" : "none",
|
|
320
|
+
});
|
|
321
|
+
// 4. Console account (API key)
|
|
322
|
+
options.push({
|
|
323
|
+
id: "console",
|
|
324
|
+
label: "Anthropic Console account",
|
|
325
|
+
description: "API usage billing",
|
|
326
|
+
method: "console",
|
|
327
|
+
status: "none",
|
|
328
|
+
});
|
|
329
|
+
// 5. Setup token (from `claude setup-token`)
|
|
330
|
+
options.push({
|
|
331
|
+
id: "setup-token",
|
|
332
|
+
label: "Paste setup-token",
|
|
333
|
+
description: "From `claude setup-token` or admin provisioning",
|
|
334
|
+
method: "setup-token",
|
|
335
|
+
status: "none",
|
|
336
|
+
});
|
|
337
|
+
// 6. Bedrock (3rd-party platform) — always shown with appropriate status
|
|
338
|
+
{
|
|
339
|
+
const bedrockStatus = resolveProviderStatus("bedrock");
|
|
340
|
+
const hasAwsProfile = !!configuredAwsProfile;
|
|
341
|
+
options.push({
|
|
342
|
+
id: "bedrock",
|
|
343
|
+
label: "3rd-party platform",
|
|
344
|
+
description: hasAwsProfile
|
|
345
|
+
? `Amazon Bedrock (profile=${configuredAwsProfile})`
|
|
346
|
+
: "Amazon Bedrock — configure daemon-owned awsProfile/region selectors",
|
|
347
|
+
method: "bedrock",
|
|
348
|
+
status: bedrockStatus === "connected" ? "connected" : hasAwsProfile ? "available" : "none",
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
return options;
|
|
352
|
+
}
|
|
353
|
+
export async function handleAnthropicMethodSelection(methodId) {
|
|
354
|
+
switch (methodId) {
|
|
355
|
+
case "subscription":
|
|
356
|
+
return { mode: "oauth", provider: "anthropic" };
|
|
357
|
+
case "console":
|
|
358
|
+
case "api-key":
|
|
359
|
+
return { mode: "anthropic_key_input", provider: "anthropic" };
|
|
360
|
+
case "setup-token":
|
|
361
|
+
return { mode: "anthropic_setup_token", provider: "anthropic" };
|
|
362
|
+
case "env-key": {
|
|
363
|
+
const key = process.env.ANTHROPIC_API_KEY?.trim();
|
|
364
|
+
if (!key) {
|
|
365
|
+
return {
|
|
366
|
+
mode: "direct",
|
|
367
|
+
result: { success: false, message: "ANTHROPIC_API_KEY not set in environment" },
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
upsertAuthProfile({
|
|
371
|
+
profileId: "anthropic:env",
|
|
372
|
+
credential: { type: "api_key", provider: "anthropic", key },
|
|
373
|
+
});
|
|
374
|
+
return {
|
|
375
|
+
mode: "direct",
|
|
376
|
+
result: { success: true, message: "Saved ANTHROPIC_API_KEY from environment" },
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
case "claude-cli": {
|
|
380
|
+
const cred = readClaudeCodeCredentialsCached();
|
|
381
|
+
if (!cred) {
|
|
382
|
+
return {
|
|
383
|
+
mode: "direct",
|
|
384
|
+
result: {
|
|
385
|
+
success: false,
|
|
386
|
+
message: "No Claude Code credentials found. Run `claude login` first.",
|
|
387
|
+
},
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
if (cred.type === "oauth") {
|
|
391
|
+
upsertAuthProfile({
|
|
392
|
+
profileId: "anthropic:claude-cli",
|
|
393
|
+
credential: {
|
|
394
|
+
type: "oauth",
|
|
395
|
+
provider: "anthropic",
|
|
396
|
+
access: cred.access,
|
|
397
|
+
refresh: cred.refresh,
|
|
398
|
+
expires: cred.expires,
|
|
399
|
+
},
|
|
400
|
+
});
|
|
401
|
+
return {
|
|
402
|
+
mode: "direct",
|
|
403
|
+
result: { success: true, message: "Imported Claude Code OAuth credentials" },
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
if (cred.type === "token") {
|
|
407
|
+
upsertAuthProfile({
|
|
408
|
+
profileId: "anthropic:claude-cli",
|
|
409
|
+
credential: {
|
|
410
|
+
type: "token",
|
|
411
|
+
provider: "anthropic",
|
|
412
|
+
token: cred.token,
|
|
413
|
+
expires: cred.expires,
|
|
414
|
+
},
|
|
415
|
+
});
|
|
416
|
+
return {
|
|
417
|
+
mode: "direct",
|
|
418
|
+
result: { success: true, message: "Imported Claude Code token" },
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
return {
|
|
422
|
+
mode: "direct",
|
|
423
|
+
result: { success: false, message: "Unknown Claude Code credential type" },
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
case "bedrock":
|
|
427
|
+
return handleBedrockLogin();
|
|
428
|
+
default: {
|
|
429
|
+
if (methodId.startsWith("profile:")) {
|
|
430
|
+
return {
|
|
431
|
+
mode: "direct",
|
|
432
|
+
result: {
|
|
433
|
+
success: true,
|
|
434
|
+
message: `Selected profile: ${methodId.replace("profile:", "")}`,
|
|
435
|
+
},
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
return {
|
|
439
|
+
mode: "direct",
|
|
440
|
+
result: { success: false, message: `Unknown method: ${methodId}` },
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
// ---------------------------------------------------------------------------
|
|
446
|
+
// OpenAI method picker — env key + profiles + Codex import + paste key
|
|
447
|
+
// ---------------------------------------------------------------------------
|
|
448
|
+
function buildOpenAIMethodOptions() {
|
|
449
|
+
const options = [];
|
|
450
|
+
// 0. Check for OPENAI_API_KEY in environment
|
|
451
|
+
const envKey = process.env.OPENAI_API_KEY?.trim();
|
|
452
|
+
if (envKey && envKey.length > 8) {
|
|
453
|
+
const looksValid = envKey.startsWith("sk-");
|
|
454
|
+
options.push({
|
|
455
|
+
id: "env-key",
|
|
456
|
+
label: "Using OPENAI_API_KEY from environment",
|
|
457
|
+
description: looksValid ? "API key detected" : "Key format unrecognized",
|
|
458
|
+
method: "env-key",
|
|
459
|
+
status: looksValid ? "connected" : "none",
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
// 1. Check existing OpenAI profiles in the auth store
|
|
463
|
+
const store = ensureAuthProfileStore();
|
|
464
|
+
syncExternalCliCredentials(store);
|
|
465
|
+
const seenProfiles = new Set();
|
|
466
|
+
for (const providerKey of ["openai", "openai-codex"]) {
|
|
467
|
+
const profiles = listProfilesForProvider(store, providerKey);
|
|
468
|
+
for (const profileId of profiles) {
|
|
469
|
+
if (seenProfiles.has(profileId))
|
|
470
|
+
continue;
|
|
471
|
+
seenProfiles.add(profileId);
|
|
472
|
+
const profile = store.profiles[profileId];
|
|
473
|
+
if (!profile)
|
|
474
|
+
continue;
|
|
475
|
+
const isFresh = (profile.type === "oauth" || profile.type === "token") &&
|
|
476
|
+
"expires" in profile &&
|
|
477
|
+
typeof profile.expires === "number" &&
|
|
478
|
+
profile.expires > Date.now();
|
|
479
|
+
options.push({
|
|
480
|
+
id: `profile:${profileId}`,
|
|
481
|
+
label: `Saved profile: ${profileId}`,
|
|
482
|
+
description: isFresh ? "Credentials active" : "Credentials expired — will refresh on use",
|
|
483
|
+
method: "profile",
|
|
484
|
+
status: isFresh ? "connected" : "available",
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
// 2. Check if Codex CLI credentials exist
|
|
489
|
+
const codexCred = readCodexCredentialsCached();
|
|
490
|
+
if (codexCred) {
|
|
491
|
+
const isFresh = codexCred.expires > Date.now();
|
|
492
|
+
options.push({
|
|
493
|
+
id: "codex-import",
|
|
494
|
+
label: "Import from Codex CLI",
|
|
495
|
+
description: isFresh ? "Use existing Codex credentials" : "Credentials expired, will refresh",
|
|
496
|
+
method: "codex-import",
|
|
497
|
+
status: isFresh ? "connected" : "available",
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
// 3. Paste API key option
|
|
501
|
+
options.push({
|
|
502
|
+
id: "api-key",
|
|
503
|
+
label: "Paste API key",
|
|
504
|
+
description: "Enter your OpenAI sk-* API key",
|
|
505
|
+
method: "api-key",
|
|
506
|
+
status: "none",
|
|
507
|
+
});
|
|
508
|
+
return options;
|
|
509
|
+
}
|
|
510
|
+
export async function handleOpenAIMethodSelection(methodId) {
|
|
511
|
+
switch (methodId) {
|
|
512
|
+
case "api-key":
|
|
513
|
+
return { mode: "openai_key_input", provider: "openai" };
|
|
514
|
+
case "env-key": {
|
|
515
|
+
const key = process.env.OPENAI_API_KEY?.trim();
|
|
516
|
+
if (!key) {
|
|
517
|
+
return {
|
|
518
|
+
mode: "direct",
|
|
519
|
+
result: { success: false, message: "OPENAI_API_KEY not set in environment" },
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
upsertAuthProfile({
|
|
523
|
+
profileId: "openai:env",
|
|
524
|
+
credential: { type: "api_key", provider: "openai", key },
|
|
525
|
+
});
|
|
526
|
+
return {
|
|
527
|
+
mode: "direct",
|
|
528
|
+
result: { success: true, message: "Saved OPENAI_API_KEY from environment" },
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
case "codex-import": {
|
|
532
|
+
const cred = readCodexCredentialsCached();
|
|
533
|
+
if (!cred) {
|
|
534
|
+
return {
|
|
535
|
+
mode: "direct",
|
|
536
|
+
result: {
|
|
537
|
+
success: false,
|
|
538
|
+
message: "No Codex CLI credentials found. Run `codex auth` first.",
|
|
539
|
+
},
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
upsertAuthProfile({
|
|
543
|
+
profileId: OPENAI_CODEX_OAUTH_PROFILE_ID,
|
|
544
|
+
credential: {
|
|
545
|
+
type: "oauth",
|
|
546
|
+
provider: "openai",
|
|
547
|
+
access: cred.access,
|
|
548
|
+
refresh: cred.refresh,
|
|
549
|
+
expires: cred.expires,
|
|
550
|
+
},
|
|
551
|
+
});
|
|
552
|
+
return {
|
|
553
|
+
mode: "direct",
|
|
554
|
+
result: { success: true, message: "Imported Codex CLI OAuth credentials" },
|
|
555
|
+
};
|
|
556
|
+
}
|
|
557
|
+
default: {
|
|
558
|
+
if (methodId.startsWith("profile:")) {
|
|
559
|
+
return {
|
|
560
|
+
mode: "direct",
|
|
561
|
+
result: {
|
|
562
|
+
success: true,
|
|
563
|
+
message: `Selected profile: ${methodId.replace("profile:", "")}`,
|
|
564
|
+
},
|
|
565
|
+
};
|
|
566
|
+
}
|
|
567
|
+
return {
|
|
568
|
+
mode: "direct",
|
|
569
|
+
result: { success: false, message: `Unknown method: ${methodId}` },
|
|
570
|
+
};
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
// ---------------------------------------------------------------------------
|
|
575
|
+
// Google method picker — env key + profiles + Gemini import + paste key + OAuth
|
|
576
|
+
// ---------------------------------------------------------------------------
|
|
577
|
+
function buildGoogleMethodOptions() {
|
|
578
|
+
const options = [];
|
|
579
|
+
// 0. Check for GOOGLE_API_KEY or GEMINI_API_KEY in environment
|
|
580
|
+
const envKey = (process.env.GOOGLE_API_KEY ?? process.env.GEMINI_API_KEY)?.trim();
|
|
581
|
+
if (envKey && envKey.length > 8) {
|
|
582
|
+
const looksValid = envKey.startsWith("AIza");
|
|
583
|
+
options.push({
|
|
584
|
+
id: "env-key",
|
|
585
|
+
label: `Using ${process.env.GOOGLE_API_KEY ? "GOOGLE_API_KEY" : "GEMINI_API_KEY"} from environment`,
|
|
586
|
+
description: looksValid ? "API key detected" : "Key format unrecognized",
|
|
587
|
+
method: "env-key",
|
|
588
|
+
status: looksValid ? "connected" : "none",
|
|
589
|
+
});
|
|
590
|
+
}
|
|
591
|
+
// 1. Check existing Google profiles in the auth store
|
|
592
|
+
const store = ensureAuthProfileStore();
|
|
593
|
+
syncExternalCliCredentials(store);
|
|
594
|
+
const googleProfiles = listProfilesForProvider(store, "google");
|
|
595
|
+
for (const profileId of googleProfiles) {
|
|
596
|
+
const profile = store.profiles[profileId];
|
|
597
|
+
if (!profile)
|
|
598
|
+
continue;
|
|
599
|
+
const isFresh = (profile.type === "oauth" || profile.type === "token") &&
|
|
600
|
+
"expires" in profile &&
|
|
601
|
+
typeof profile.expires === "number" &&
|
|
602
|
+
profile.expires > Date.now();
|
|
603
|
+
options.push({
|
|
604
|
+
id: `profile:${profileId}`,
|
|
605
|
+
label: `Saved profile: ${profileId}`,
|
|
606
|
+
description: isFresh ? "Credentials active" : "Credentials expired — will refresh on use",
|
|
607
|
+
method: "profile",
|
|
608
|
+
status: isFresh ? "connected" : "available",
|
|
609
|
+
});
|
|
610
|
+
}
|
|
611
|
+
// 2. Check if Gemini CLI credentials exist
|
|
612
|
+
const geminiCred = readGeminiCredentialsCached();
|
|
613
|
+
if (geminiCred) {
|
|
614
|
+
const isFresh = geminiCred.expires > Date.now();
|
|
615
|
+
options.push({
|
|
616
|
+
id: "gemini-import",
|
|
617
|
+
label: "Import from Gemini CLI",
|
|
618
|
+
description: isFresh
|
|
619
|
+
? "Use existing Gemini CLI credentials"
|
|
620
|
+
: "Credentials expired, will refresh",
|
|
621
|
+
method: "gemini-import",
|
|
622
|
+
status: isFresh ? "connected" : "available",
|
|
623
|
+
});
|
|
624
|
+
}
|
|
625
|
+
// 3. Paste API key option
|
|
626
|
+
options.push({
|
|
627
|
+
id: "api-key",
|
|
628
|
+
label: "Paste API key",
|
|
629
|
+
description: "Enter your Google AIza* API key",
|
|
630
|
+
method: "api-key",
|
|
631
|
+
status: "none",
|
|
632
|
+
});
|
|
633
|
+
// 4. Gemini CLI OAuth option
|
|
634
|
+
options.push({
|
|
635
|
+
id: "oauth",
|
|
636
|
+
label: "Gemini CLI OAuth",
|
|
637
|
+
description: "Sign in via browser-based OAuth flow",
|
|
638
|
+
method: "oauth",
|
|
639
|
+
status: "none",
|
|
640
|
+
});
|
|
641
|
+
return options;
|
|
642
|
+
}
|
|
643
|
+
export async function handleGoogleMethodSelection(methodId) {
|
|
644
|
+
switch (methodId) {
|
|
645
|
+
case "api-key":
|
|
646
|
+
return { mode: "google_key_input", provider: "google" };
|
|
647
|
+
case "oauth":
|
|
648
|
+
return { mode: "oauth", provider: "google" };
|
|
649
|
+
case "env-key": {
|
|
650
|
+
const key = (process.env.GOOGLE_API_KEY ?? process.env.GEMINI_API_KEY)?.trim();
|
|
651
|
+
if (!key) {
|
|
652
|
+
return {
|
|
653
|
+
mode: "direct",
|
|
654
|
+
result: {
|
|
655
|
+
success: false,
|
|
656
|
+
message: "GOOGLE_API_KEY / GEMINI_API_KEY not set in environment",
|
|
657
|
+
},
|
|
658
|
+
};
|
|
659
|
+
}
|
|
660
|
+
upsertAuthProfile({
|
|
661
|
+
profileId: "google:env",
|
|
662
|
+
credential: { type: "api_key", provider: "google", key },
|
|
663
|
+
});
|
|
664
|
+
return {
|
|
665
|
+
mode: "direct",
|
|
666
|
+
result: { success: true, message: "Saved Google API key from environment" },
|
|
667
|
+
};
|
|
668
|
+
}
|
|
669
|
+
case "gemini-import": {
|
|
670
|
+
const cred = readGeminiCredentialsCached();
|
|
671
|
+
if (!cred) {
|
|
672
|
+
return {
|
|
673
|
+
mode: "direct",
|
|
674
|
+
result: {
|
|
675
|
+
success: false,
|
|
676
|
+
message: "No Gemini CLI credentials found. Run `gemini auth` first.",
|
|
677
|
+
},
|
|
678
|
+
};
|
|
679
|
+
}
|
|
680
|
+
upsertAuthProfile({
|
|
681
|
+
profileId: "google:gemini-cli",
|
|
682
|
+
credential: {
|
|
683
|
+
type: "oauth",
|
|
684
|
+
provider: "google",
|
|
685
|
+
access: cred.access,
|
|
686
|
+
refresh: cred.refresh,
|
|
687
|
+
expires: cred.expires,
|
|
688
|
+
},
|
|
689
|
+
});
|
|
690
|
+
return {
|
|
691
|
+
mode: "direct",
|
|
692
|
+
result: { success: true, message: "Imported Gemini CLI OAuth credentials" },
|
|
693
|
+
};
|
|
694
|
+
}
|
|
695
|
+
default: {
|
|
696
|
+
if (methodId.startsWith("profile:")) {
|
|
697
|
+
return {
|
|
698
|
+
mode: "direct",
|
|
699
|
+
result: {
|
|
700
|
+
success: true,
|
|
701
|
+
message: `Selected profile: ${methodId.replace("profile:", "")}`,
|
|
702
|
+
},
|
|
703
|
+
};
|
|
704
|
+
}
|
|
705
|
+
return {
|
|
706
|
+
mode: "direct",
|
|
707
|
+
result: { success: false, message: `Unknown method: ${methodId}` },
|
|
708
|
+
};
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
// ---------------------------------------------------------------------------
|
|
713
|
+
// Provider metadata
|
|
714
|
+
// ---------------------------------------------------------------------------
|
|
715
|
+
const SUPPORTED_PROVIDERS = ["bedrock", "anthropic", "google", "openai", "github-copilot"];
|
|
716
|
+
const PROVIDER_LABELS = {
|
|
717
|
+
bedrock: "Bedrock (AWS SSO)",
|
|
718
|
+
anthropic: "Anthropic",
|
|
719
|
+
google: "Google (Gemini)",
|
|
720
|
+
openai: "OpenAI",
|
|
721
|
+
"github-copilot": "GitHub Copilot",
|
|
722
|
+
};
|
|
723
|
+
function isSupportedProvider(name) {
|
|
724
|
+
return SUPPORTED_PROVIDERS.includes(name);
|
|
725
|
+
}
|
|
726
|
+
// ---------------------------------------------------------------------------
|
|
727
|
+
// Provider status resolution
|
|
728
|
+
// ---------------------------------------------------------------------------
|
|
729
|
+
/** Env vars that indicate a provider is available without stored profiles. */
|
|
730
|
+
const PROVIDER_ENV_VARS = {
|
|
731
|
+
anthropic: ["ANTHROPIC_API_KEY"],
|
|
732
|
+
openai: ["OPENAI_API_KEY"],
|
|
733
|
+
google: ["GOOGLE_API_KEY", "GEMINI_API_KEY"],
|
|
734
|
+
"github-copilot": ["GH_TOKEN", "GITHUB_TOKEN", "COPILOT_GITHUB_TOKEN"],
|
|
735
|
+
bedrock: [],
|
|
736
|
+
};
|
|
737
|
+
function resolveProviderStatus(provider) {
|
|
738
|
+
const store = updateAuthProfileStoreWithLockSync({
|
|
739
|
+
updater: (freshStore) => syncExternalCliCredentials(freshStore),
|
|
740
|
+
}) ?? ensureAuthProfileStore();
|
|
741
|
+
const normalized = normalizeProviderId(provider);
|
|
742
|
+
const profileIds = listProfilesForProvider(store, normalized);
|
|
743
|
+
// Check if any profile is active (not expired, not in cooldown)
|
|
744
|
+
for (const id of profileIds) {
|
|
745
|
+
const cred = store.profiles[id];
|
|
746
|
+
if (!cred)
|
|
747
|
+
continue;
|
|
748
|
+
if (isProfileInCooldown(store, id))
|
|
749
|
+
continue;
|
|
750
|
+
// API key profiles are always active if they have a key
|
|
751
|
+
if (cred.type === "api_key" && cred.key?.trim())
|
|
752
|
+
return "connected";
|
|
753
|
+
if (cred.type === "oauth" && "expires" in cred) {
|
|
754
|
+
const expires = cred.expires;
|
|
755
|
+
if (expires && expires < Date.now())
|
|
756
|
+
continue; // expired
|
|
757
|
+
return "connected";
|
|
758
|
+
}
|
|
759
|
+
if (cred.type === "token") {
|
|
760
|
+
const expires = cred.expires;
|
|
761
|
+
if (!expires || Date.now() < expires)
|
|
762
|
+
return "connected";
|
|
763
|
+
continue; // expired
|
|
764
|
+
}
|
|
765
|
+
// Unknown type with no expiry — treat as active
|
|
766
|
+
return "connected";
|
|
767
|
+
}
|
|
768
|
+
// Check environment variables
|
|
769
|
+
const vars = PROVIDER_ENV_VARS[normalized] ?? [];
|
|
770
|
+
for (const v of vars) {
|
|
771
|
+
if (process.env[v]?.trim())
|
|
772
|
+
return "connected";
|
|
773
|
+
}
|
|
774
|
+
// Profiles exist but none are active → expired; otherwise → none
|
|
775
|
+
return profileIds.length > 0 ? "expired" : "none";
|
|
776
|
+
}
|
|
777
|
+
// ---------------------------------------------------------------------------
|
|
778
|
+
// getProviderOptions — build the picker list
|
|
779
|
+
// ---------------------------------------------------------------------------
|
|
780
|
+
export function getProviderOptions() {
|
|
781
|
+
return SUPPORTED_PROVIDERS.map((id) => {
|
|
782
|
+
const status = resolveProviderStatus(id);
|
|
783
|
+
const store = ensureAuthProfileStore();
|
|
784
|
+
const profileIds = listProfilesForProvider(store, id);
|
|
785
|
+
// Try to find an email from any profile
|
|
786
|
+
let email;
|
|
787
|
+
for (const pid of profileIds) {
|
|
788
|
+
const cred = store.profiles[pid];
|
|
789
|
+
if (cred?.email) {
|
|
790
|
+
email = cred.email;
|
|
791
|
+
break;
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
return {
|
|
795
|
+
id,
|
|
796
|
+
label: PROVIDER_LABELS[id],
|
|
797
|
+
status,
|
|
798
|
+
...(email ? { email } : {}),
|
|
799
|
+
};
|
|
800
|
+
});
|
|
801
|
+
}
|
|
802
|
+
// ---------------------------------------------------------------------------
|
|
803
|
+
// Bedrock SSO login — tries silent refresh first, then interactive
|
|
804
|
+
// ---------------------------------------------------------------------------
|
|
805
|
+
async function handleBedrockLogin(profile) {
|
|
806
|
+
const config = loadConfig();
|
|
807
|
+
const selectedProfile = profile?.trim() || config.awsProfile?.trim();
|
|
808
|
+
const selectedRegion = config.awsRegion?.trim();
|
|
809
|
+
const selector = {
|
|
810
|
+
awsProfile: selectedProfile,
|
|
811
|
+
awsRegion: selectedRegion,
|
|
812
|
+
awsConfigFile: config.awsConfigFile?.trim(),
|
|
813
|
+
awsSharedCredentialsFile: config.awsSharedCredentialsFile?.trim(),
|
|
814
|
+
};
|
|
815
|
+
if (!selectedProfile) {
|
|
816
|
+
return {
|
|
817
|
+
mode: "direct",
|
|
818
|
+
result: {
|
|
819
|
+
success: false,
|
|
820
|
+
message: "Bedrock is not configured. Set daemon-owned awsProfile (and ideally awsRegion) selectors before logging in.",
|
|
821
|
+
},
|
|
822
|
+
};
|
|
823
|
+
}
|
|
824
|
+
// Step 1: silent refresh
|
|
825
|
+
const silentOk = await refreshBedrockSsoToken(selector);
|
|
826
|
+
if (silentOk) {
|
|
827
|
+
return {
|
|
828
|
+
mode: "direct",
|
|
829
|
+
result: { success: true, message: "Bedrock SSO token refreshed (silent)" },
|
|
830
|
+
};
|
|
831
|
+
}
|
|
832
|
+
// Step 2: interactive aws sso login
|
|
833
|
+
const loginOk = await loginBedrockSso(selector);
|
|
834
|
+
if (loginOk) {
|
|
835
|
+
return {
|
|
836
|
+
mode: "direct",
|
|
837
|
+
result: {
|
|
838
|
+
success: true,
|
|
839
|
+
message: `Bedrock SSO login succeeded — credentials refreshed${selectedRegion ? ` (${selectedProfile} @ ${selectedRegion})` : ` (${selectedProfile})`}`,
|
|
840
|
+
},
|
|
841
|
+
};
|
|
842
|
+
}
|
|
843
|
+
return {
|
|
844
|
+
mode: "direct",
|
|
845
|
+
result: {
|
|
846
|
+
success: false,
|
|
847
|
+
message: [
|
|
848
|
+
"Bedrock SSO login failed.",
|
|
849
|
+
"The daemon resolves Bedrock auth from its configured AWS profile/region selectors and AWS shared config/SSO cache.",
|
|
850
|
+
"Try running manually: aws sso login --profile " + selectedProfile,
|
|
851
|
+
].join("\n"),
|
|
852
|
+
},
|
|
853
|
+
};
|
|
854
|
+
}
|
|
855
|
+
// ---------------------------------------------------------------------------
|
|
856
|
+
// API key login — save directly
|
|
857
|
+
// ---------------------------------------------------------------------------
|
|
858
|
+
function handleApiKeyLogin(provider, apiKey) {
|
|
859
|
+
if (apiKey.length < 8) {
|
|
860
|
+
return {
|
|
861
|
+
mode: "direct",
|
|
862
|
+
result: { success: false, message: "API key too short (minimum 8 characters)" },
|
|
863
|
+
};
|
|
864
|
+
}
|
|
865
|
+
const profileId = `${provider}:manual`;
|
|
866
|
+
upsertAuthProfile({
|
|
867
|
+
profileId,
|
|
868
|
+
credential: { type: "api_key", provider, key: apiKey },
|
|
869
|
+
});
|
|
870
|
+
return {
|
|
871
|
+
mode: "direct",
|
|
872
|
+
result: { success: true, message: `Saved ${provider} API key (profile: ${profileId})` },
|
|
873
|
+
};
|
|
874
|
+
}
|
|
875
|
+
function handleAnthropicSetupTokenLogin(token) {
|
|
876
|
+
if (token.length < 8) {
|
|
877
|
+
return {
|
|
878
|
+
mode: "direct",
|
|
879
|
+
result: { success: false, message: "Setup token too short (minimum 8 characters)" },
|
|
880
|
+
};
|
|
881
|
+
}
|
|
882
|
+
const profileId = "anthropic:setup-token";
|
|
883
|
+
upsertAuthProfile({
|
|
884
|
+
profileId,
|
|
885
|
+
credential: { type: "api_key", provider: "anthropic", key: token },
|
|
886
|
+
});
|
|
887
|
+
return {
|
|
888
|
+
mode: "direct",
|
|
889
|
+
result: { success: true, message: `Saved Anthropic setup token (profile: ${profileId})` },
|
|
890
|
+
};
|
|
891
|
+
}
|
|
892
|
+
// ---------------------------------------------------------------------------
|
|
893
|
+
// loginProvider — handle login for a specific provider
|
|
894
|
+
// ---------------------------------------------------------------------------
|
|
895
|
+
export async function loginProvider(provider, args) {
|
|
896
|
+
if (!isSupportedProvider(provider)) {
|
|
897
|
+
return {
|
|
898
|
+
mode: "direct",
|
|
899
|
+
result: {
|
|
900
|
+
success: false,
|
|
901
|
+
message: `Unknown provider "${provider}". Supported: ${SUPPORTED_PROVIDERS.join(", ")}`,
|
|
902
|
+
},
|
|
903
|
+
};
|
|
904
|
+
}
|
|
905
|
+
// Bedrock: always SSO flow
|
|
906
|
+
if (provider === "bedrock") {
|
|
907
|
+
const trimmedArgs = args?.trim();
|
|
908
|
+
if (trimmedArgs) {
|
|
909
|
+
const parts = trimmedArgs.split(/\s+/);
|
|
910
|
+
const nextConfig = loadConfig();
|
|
911
|
+
let mutated = false;
|
|
912
|
+
const candidateProfile = parts[0]?.trim();
|
|
913
|
+
if (candidateProfile) {
|
|
914
|
+
nextConfig.awsProfile = candidateProfile;
|
|
915
|
+
mutated = true;
|
|
916
|
+
}
|
|
917
|
+
const candidateRegion = parts[1]?.trim();
|
|
918
|
+
if (candidateRegion) {
|
|
919
|
+
nextConfig.awsRegion = candidateRegion;
|
|
920
|
+
mutated = true;
|
|
921
|
+
}
|
|
922
|
+
if (persistAwsSelectorHintsFromEnv(nextConfig)) {
|
|
923
|
+
mutated = true;
|
|
924
|
+
}
|
|
925
|
+
if (mutated) {
|
|
926
|
+
saveConfig(nextConfig);
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
return handleBedrockLogin();
|
|
930
|
+
}
|
|
931
|
+
// GitHub Copilot: token shortcut or interactive device-code flow
|
|
932
|
+
if (provider === "github-copilot") {
|
|
933
|
+
const parsed = parseCopilotLoginArgs(args);
|
|
934
|
+
if (!parsed.token && !parsed.profileLabel && parsed.autoSelectSource) {
|
|
935
|
+
const options = buildCopilotSourceOptions();
|
|
936
|
+
return {
|
|
937
|
+
mode: "copilot_source_picker",
|
|
938
|
+
provider: "github-copilot",
|
|
939
|
+
options,
|
|
940
|
+
};
|
|
941
|
+
}
|
|
942
|
+
if (parsed.token) {
|
|
943
|
+
const result = await loginWithGitHubCopilotToken({
|
|
944
|
+
githubToken: parsed.token,
|
|
945
|
+
profileLabel: parsed.profileLabel,
|
|
946
|
+
});
|
|
947
|
+
return {
|
|
948
|
+
mode: "direct",
|
|
949
|
+
result: {
|
|
950
|
+
success: result.success,
|
|
951
|
+
message: result.message,
|
|
952
|
+
},
|
|
953
|
+
};
|
|
954
|
+
}
|
|
955
|
+
// No explicit token provided: best-effort import from GitHub CLI auth.
|
|
956
|
+
if (parsed.useGhToken) {
|
|
957
|
+
const gh = readGhAuthToken();
|
|
958
|
+
if (gh.token) {
|
|
959
|
+
const result = await loginWithGitHubCopilotToken({
|
|
960
|
+
githubToken: gh.token,
|
|
961
|
+
profileLabel: parsed.profileLabel,
|
|
962
|
+
});
|
|
963
|
+
if (result.success) {
|
|
964
|
+
return {
|
|
965
|
+
mode: "direct",
|
|
966
|
+
result: {
|
|
967
|
+
success: true,
|
|
968
|
+
message: `${result.message} (imported from gh auth token)`,
|
|
969
|
+
},
|
|
970
|
+
};
|
|
971
|
+
}
|
|
972
|
+
return {
|
|
973
|
+
mode: "copilot_device",
|
|
974
|
+
provider: "github-copilot",
|
|
975
|
+
profileLabel: parsed.profileLabel,
|
|
976
|
+
message: `gh auth token import failed: ${result.message}\nFalling back to interactive device login...`,
|
|
977
|
+
};
|
|
978
|
+
}
|
|
979
|
+
return {
|
|
980
|
+
mode: "copilot_device",
|
|
981
|
+
provider: "github-copilot",
|
|
982
|
+
profileLabel: parsed.profileLabel,
|
|
983
|
+
...(gh.error ? { message: `Could not read gh auth token: ${gh.error}` } : {}),
|
|
984
|
+
};
|
|
985
|
+
}
|
|
986
|
+
return {
|
|
987
|
+
mode: "copilot_device",
|
|
988
|
+
provider: "github-copilot",
|
|
989
|
+
profileLabel: parsed.profileLabel,
|
|
990
|
+
};
|
|
991
|
+
}
|
|
992
|
+
// Anthropic: 3-method picker or --method dispatch
|
|
993
|
+
if (provider === "anthropic") {
|
|
994
|
+
const keyArg = args?.trim();
|
|
995
|
+
if (keyArg?.startsWith("--setup-token")) {
|
|
996
|
+
const token = keyArg.replace(/^--setup-token\s*/, "").trim();
|
|
997
|
+
return handleAnthropicSetupTokenLogin(token);
|
|
998
|
+
}
|
|
999
|
+
// `/login anthropic --method <method>` — handle specific method
|
|
1000
|
+
if (keyArg?.startsWith("--method")) {
|
|
1001
|
+
const methodId = keyArg.replace(/^--method\s*/, "").trim();
|
|
1002
|
+
return handleAnthropicMethodSelection(methodId);
|
|
1003
|
+
}
|
|
1004
|
+
// `/login anthropic <api-key>` — direct API key (preserve existing behavior)
|
|
1005
|
+
if (keyArg) {
|
|
1006
|
+
return handleApiKeyLogin(provider, keyArg);
|
|
1007
|
+
}
|
|
1008
|
+
// `/login anthropic` with no args → show method picker
|
|
1009
|
+
const options = buildAnthropicMethodOptions();
|
|
1010
|
+
return {
|
|
1011
|
+
mode: "anthropic_method_picker",
|
|
1012
|
+
provider: "anthropic",
|
|
1013
|
+
options,
|
|
1014
|
+
};
|
|
1015
|
+
}
|
|
1016
|
+
// OpenAI: method picker or direct key
|
|
1017
|
+
if (provider === "openai") {
|
|
1018
|
+
const keyArg = args?.trim();
|
|
1019
|
+
if (keyArg?.startsWith("--method")) {
|
|
1020
|
+
const methodId = keyArg.replace(/^--method\s*/, "").trim();
|
|
1021
|
+
return handleOpenAIMethodSelection(methodId);
|
|
1022
|
+
}
|
|
1023
|
+
if (keyArg) {
|
|
1024
|
+
return handleApiKeyLogin(provider, keyArg);
|
|
1025
|
+
}
|
|
1026
|
+
const options = buildOpenAIMethodOptions();
|
|
1027
|
+
return {
|
|
1028
|
+
mode: "openai_method_picker",
|
|
1029
|
+
provider: "openai",
|
|
1030
|
+
options,
|
|
1031
|
+
};
|
|
1032
|
+
}
|
|
1033
|
+
// Google: method picker or direct key
|
|
1034
|
+
if (provider === "google") {
|
|
1035
|
+
const keyArg = args?.trim();
|
|
1036
|
+
if (keyArg?.startsWith("--method")) {
|
|
1037
|
+
const methodId = keyArg.replace(/^--method\s*/, "").trim();
|
|
1038
|
+
return handleGoogleMethodSelection(methodId);
|
|
1039
|
+
}
|
|
1040
|
+
if (keyArg) {
|
|
1041
|
+
return handleApiKeyLogin(provider, keyArg);
|
|
1042
|
+
}
|
|
1043
|
+
const options = buildGoogleMethodOptions();
|
|
1044
|
+
return {
|
|
1045
|
+
mode: "google_method_picker",
|
|
1046
|
+
provider: "google",
|
|
1047
|
+
options,
|
|
1048
|
+
};
|
|
1049
|
+
}
|
|
1050
|
+
// Fallback: direct key or OAuth
|
|
1051
|
+
const keyArg = args?.trim();
|
|
1052
|
+
if (keyArg) {
|
|
1053
|
+
return handleApiKeyLogin(provider, keyArg);
|
|
1054
|
+
}
|
|
1055
|
+
return { mode: "oauth", provider };
|
|
1056
|
+
}
|
|
1057
|
+
// ---------------------------------------------------------------------------
|
|
1058
|
+
// handleLoginCommand — entry point from REPL command dispatch
|
|
1059
|
+
// ---------------------------------------------------------------------------
|
|
1060
|
+
export async function handleLoginCommand(args) {
|
|
1061
|
+
const parts = args.trim().split(/\s+/);
|
|
1062
|
+
const providerArg = parts[0]?.toLowerCase() || "";
|
|
1063
|
+
const keyArg = parts.slice(1).join(" ").trim();
|
|
1064
|
+
// /login with no args → show interactive picker
|
|
1065
|
+
if (!providerArg) {
|
|
1066
|
+
return { mode: "picker", providers: getProviderOptions() };
|
|
1067
|
+
}
|
|
1068
|
+
if (providerArg === "github-copilot" && keyArg.startsWith("--from ")) {
|
|
1069
|
+
const sourceId = keyArg.slice("--from ".length).trim();
|
|
1070
|
+
const options = buildCopilotSourceOptions();
|
|
1071
|
+
const selected = options.find((o) => o.id === sourceId);
|
|
1072
|
+
if (!selected) {
|
|
1073
|
+
return {
|
|
1074
|
+
mode: "direct",
|
|
1075
|
+
result: { success: false, message: `Unknown Copilot source: ${sourceId}` },
|
|
1076
|
+
};
|
|
1077
|
+
}
|
|
1078
|
+
if (selected.source === "device") {
|
|
1079
|
+
return {
|
|
1080
|
+
mode: "copilot_device",
|
|
1081
|
+
provider: "github-copilot",
|
|
1082
|
+
profileLabel: selected.profileLabel,
|
|
1083
|
+
};
|
|
1084
|
+
}
|
|
1085
|
+
if (selected.token) {
|
|
1086
|
+
const result = await loginWithGitHubCopilotToken({
|
|
1087
|
+
githubToken: selected.token,
|
|
1088
|
+
profileLabel: selected.profileLabel,
|
|
1089
|
+
});
|
|
1090
|
+
return {
|
|
1091
|
+
mode: "direct",
|
|
1092
|
+
result: {
|
|
1093
|
+
success: result.success,
|
|
1094
|
+
message: result.message,
|
|
1095
|
+
},
|
|
1096
|
+
};
|
|
1097
|
+
}
|
|
1098
|
+
if (selected.login) {
|
|
1099
|
+
return {
|
|
1100
|
+
mode: "copilot_device",
|
|
1101
|
+
provider: "github-copilot",
|
|
1102
|
+
profileLabel: sanitizeProfileLabel(selected.login),
|
|
1103
|
+
};
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
return loginProvider(providerArg, keyArg || undefined);
|
|
1107
|
+
}
|
|
1108
|
+
//# sourceMappingURL=login-handler.js.map
|