@xelauvas/xela-cli 0.1.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.
- package/README.md +200 -0
- package/bin/xela +100 -0
- package/package.json +88 -0
- package/src/QueryEngine.ts +1295 -0
- package/src/Task.ts +125 -0
- package/src/Tool.ts +792 -0
- package/src/_shims/_generated_stubs/_universal_stub.mjs +168 -0
- package/src/_shims/_generated_stubs/text_stub.mjs +1 -0
- package/src/_shims/bun_bundle.js +9 -0
- package/src/_shims/cjs_stub.cjs +23 -0
- package/src/_shims/empty_stub.js +33 -0
- package/src/_shims/loader.js +352 -0
- package/src/_shims/openai_adapter.ts +486 -0
- package/src/_shims/react_compiler_runtime.js +17 -0
- package/src/_shims/register.js +148 -0
- package/src/assistant/sessionHistory.ts +87 -0
- package/src/bootstrap/state.ts +1759 -0
- package/src/bridge/bridgeApi.ts +539 -0
- package/src/bridge/bridgeConfig.ts +48 -0
- package/src/bridge/bridgeDebug.ts +135 -0
- package/src/bridge/bridgeEnabled.ts +202 -0
- package/src/bridge/bridgeMain.ts +2999 -0
- package/src/bridge/bridgeMessaging.ts +461 -0
- package/src/bridge/bridgePermissionCallbacks.ts +43 -0
- package/src/bridge/bridgePointer.ts +210 -0
- package/src/bridge/bridgeStatusUtil.ts +163 -0
- package/src/bridge/bridgeUI.ts +530 -0
- package/src/bridge/capacityWake.ts +56 -0
- package/src/bridge/codeSessionApi.ts +168 -0
- package/src/bridge/createSession.ts +384 -0
- package/src/bridge/debugUtils.ts +141 -0
- package/src/bridge/envLessBridgeConfig.ts +165 -0
- package/src/bridge/flushGate.ts +71 -0
- package/src/bridge/inboundAttachments.ts +175 -0
- package/src/bridge/inboundMessages.ts +80 -0
- package/src/bridge/initReplBridge.ts +569 -0
- package/src/bridge/jwtUtils.ts +256 -0
- package/src/bridge/pollConfig.ts +110 -0
- package/src/bridge/pollConfigDefaults.ts +82 -0
- package/src/bridge/remoteBridgeCore.ts +1008 -0
- package/src/bridge/replBridge.ts +2406 -0
- package/src/bridge/replBridgeHandle.ts +36 -0
- package/src/bridge/replBridgeTransport.ts +370 -0
- package/src/bridge/sessionIdCompat.ts +57 -0
- package/src/bridge/sessionRunner.ts +550 -0
- package/src/bridge/trustedDevice.ts +210 -0
- package/src/bridge/types.ts +262 -0
- package/src/bridge/workSecret.ts +127 -0
- package/src/buddy/CompanionSprite.tsx +371 -0
- package/src/buddy/companion.ts +133 -0
- package/src/buddy/prompt.ts +36 -0
- package/src/buddy/sprites.ts +514 -0
- package/src/buddy/types.ts +148 -0
- package/src/buddy/useBuddyNotification.tsx +98 -0
- package/src/cli/exit.ts +31 -0
- package/src/cli/handlers/agents.ts +70 -0
- package/src/cli/handlers/auth.ts +330 -0
- package/src/cli/handlers/autoMode.ts +170 -0
- package/src/cli/handlers/mcp.tsx +362 -0
- package/src/cli/handlers/plugins.ts +878 -0
- package/src/cli/handlers/util.tsx +110 -0
- package/src/cli/ndjsonSafeStringify.ts +32 -0
- package/src/cli/print.ts +5594 -0
- package/src/cli/remoteIO.ts +255 -0
- package/src/cli/structuredIO.ts +859 -0
- package/src/cli/transports/HybridTransport.ts +282 -0
- package/src/cli/transports/SSETransport.ts +711 -0
- package/src/cli/transports/SerialBatchEventUploader.ts +275 -0
- package/src/cli/transports/WebSocketTransport.ts +800 -0
- package/src/cli/transports/WorkerStateUploader.ts +131 -0
- package/src/cli/transports/ccrClient.ts +998 -0
- package/src/cli/transports/transportUtils.ts +45 -0
- package/src/cli/update.ts +422 -0
- package/src/commands/add-dir/add-dir.tsx +126 -0
- package/src/commands/add-dir/index.ts +11 -0
- package/src/commands/add-dir/validation.ts +110 -0
- package/src/commands/advisor.ts +109 -0
- package/src/commands/agents/agents.tsx +12 -0
- package/src/commands/agents/index.ts +10 -0
- package/src/commands/ant-trace/index.js +1 -0
- package/src/commands/autofix-pr/index.js +1 -0
- package/src/commands/backfill-sessions/index.js +1 -0
- package/src/commands/branch/branch.ts +296 -0
- package/src/commands/branch/index.ts +14 -0
- package/src/commands/break-cache/index.js +1 -0
- package/src/commands/bridge/bridge.tsx +509 -0
- package/src/commands/bridge/index.ts +26 -0
- package/src/commands/bridge-kick.ts +200 -0
- package/src/commands/brief.ts +130 -0
- package/src/commands/btw/btw.tsx +243 -0
- package/src/commands/btw/index.ts +13 -0
- package/src/commands/bughunter/index.js +1 -0
- package/src/commands/chrome/chrome.tsx +285 -0
- package/src/commands/chrome/index.ts +13 -0
- package/src/commands/clear/caches.ts +144 -0
- package/src/commands/clear/clear.ts +7 -0
- package/src/commands/clear/conversation.ts +251 -0
- package/src/commands/clear/index.ts +19 -0
- package/src/commands/color/color.ts +93 -0
- package/src/commands/color/index.ts +16 -0
- package/src/commands/commit-push-pr.ts +158 -0
- package/src/commands/commit.ts +92 -0
- package/src/commands/compact/compact.ts +287 -0
- package/src/commands/compact/index.ts +15 -0
- package/src/commands/config/config.tsx +7 -0
- package/src/commands/config/index.ts +11 -0
- package/src/commands/context/context-noninteractive.ts +325 -0
- package/src/commands/context/context.tsx +64 -0
- package/src/commands/context/index.ts +24 -0
- package/src/commands/copy/copy.tsx +371 -0
- package/src/commands/copy/index.ts +15 -0
- package/src/commands/cost/cost.ts +24 -0
- package/src/commands/cost/index.ts +23 -0
- package/src/commands/createMovedToPluginCommand.ts +65 -0
- package/src/commands/ctx_viz/index.js +1 -0
- package/src/commands/debug-tool-call/index.js +1 -0
- package/src/commands/desktop/desktop.tsx +9 -0
- package/src/commands/desktop/index.ts +26 -0
- package/src/commands/diff/diff.tsx +9 -0
- package/src/commands/diff/index.ts +8 -0
- package/src/commands/doctor/doctor.tsx +7 -0
- package/src/commands/doctor/index.ts +12 -0
- package/src/commands/effort/effort.tsx +183 -0
- package/src/commands/effort/index.ts +13 -0
- package/src/commands/env/index.js +1 -0
- package/src/commands/exit/exit.tsx +33 -0
- package/src/commands/exit/index.ts +12 -0
- package/src/commands/export/export.tsx +91 -0
- package/src/commands/export/index.ts +11 -0
- package/src/commands/extra-usage/extra-usage-core.ts +118 -0
- package/src/commands/extra-usage/extra-usage-noninteractive.ts +16 -0
- package/src/commands/extra-usage/extra-usage.tsx +17 -0
- package/src/commands/extra-usage/index.ts +31 -0
- package/src/commands/fast/fast.tsx +269 -0
- package/src/commands/fast/index.ts +26 -0
- package/src/commands/feedback/feedback.tsx +25 -0
- package/src/commands/feedback/index.ts +26 -0
- package/src/commands/files/files.ts +19 -0
- package/src/commands/files/index.ts +12 -0
- package/src/commands/good-claude/index.js +1 -0
- package/src/commands/heapdump/heapdump.ts +17 -0
- package/src/commands/heapdump/index.ts +12 -0
- package/src/commands/help/help.tsx +11 -0
- package/src/commands/help/index.ts +10 -0
- package/src/commands/hooks/hooks.tsx +13 -0
- package/src/commands/hooks/index.ts +11 -0
- package/src/commands/ide/ide.tsx +646 -0
- package/src/commands/ide/index.ts +11 -0
- package/src/commands/init-verifiers.ts +262 -0
- package/src/commands/init.ts +256 -0
- package/src/commands/insights.ts +3200 -0
- package/src/commands/install-github-app/ApiKeyStep.tsx +231 -0
- package/src/commands/install-github-app/CheckExistingSecretStep.tsx +190 -0
- package/src/commands/install-github-app/CheckGitHubStep.tsx +15 -0
- package/src/commands/install-github-app/ChooseRepoStep.tsx +211 -0
- package/src/commands/install-github-app/CreatingStep.tsx +65 -0
- package/src/commands/install-github-app/ErrorStep.tsx +85 -0
- package/src/commands/install-github-app/ExistingWorkflowStep.tsx +103 -0
- package/src/commands/install-github-app/InstallAppStep.tsx +94 -0
- package/src/commands/install-github-app/OAuthFlowStep.tsx +276 -0
- package/src/commands/install-github-app/SuccessStep.tsx +96 -0
- package/src/commands/install-github-app/WarningsStep.tsx +73 -0
- package/src/commands/install-github-app/index.ts +13 -0
- package/src/commands/install-github-app/install-github-app.tsx +587 -0
- package/src/commands/install-github-app/setupGitHubActions.ts +325 -0
- package/src/commands/install-slack-app/index.ts +12 -0
- package/src/commands/install-slack-app/install-slack-app.ts +30 -0
- package/src/commands/install.tsx +300 -0
- package/src/commands/issue/index.js +1 -0
- package/src/commands/keybindings/index.ts +13 -0
- package/src/commands/keybindings/keybindings.ts +53 -0
- package/src/commands/login/index.ts +14 -0
- package/src/commands/login/login.tsx +104 -0
- package/src/commands/logout/index.ts +10 -0
- package/src/commands/logout/logout.tsx +82 -0
- package/src/commands/mcp/addCommand.ts +280 -0
- package/src/commands/mcp/index.ts +12 -0
- package/src/commands/mcp/mcp.tsx +85 -0
- package/src/commands/mcp/xaaIdpCommand.ts +266 -0
- package/src/commands/memory/index.ts +10 -0
- package/src/commands/memory/memory.tsx +90 -0
- package/src/commands/mobile/index.ts +11 -0
- package/src/commands/mobile/mobile.tsx +274 -0
- package/src/commands/mock-limits/index.js +1 -0
- package/src/commands/model/index.ts +16 -0
- package/src/commands/model/model.tsx +297 -0
- package/src/commands/oauth-refresh/index.js +1 -0
- package/src/commands/onboarding/index.js +1 -0
- package/src/commands/output-style/index.ts +11 -0
- package/src/commands/output-style/output-style.tsx +7 -0
- package/src/commands/passes/index.ts +22 -0
- package/src/commands/passes/passes.tsx +24 -0
- package/src/commands/perf-issue/index.js +1 -0
- package/src/commands/permissions/index.ts +11 -0
- package/src/commands/permissions/permissions.tsx +10 -0
- package/src/commands/plan/index.ts +11 -0
- package/src/commands/plan/plan.tsx +122 -0
- package/src/commands/plugin/AddMarketplace.tsx +162 -0
- package/src/commands/plugin/BrowseMarketplace.tsx +802 -0
- package/src/commands/plugin/DiscoverPlugins.tsx +781 -0
- package/src/commands/plugin/ManageMarketplaces.tsx +838 -0
- package/src/commands/plugin/ManagePlugins.tsx +2215 -0
- package/src/commands/plugin/PluginErrors.tsx +124 -0
- package/src/commands/plugin/PluginOptionsDialog.tsx +357 -0
- package/src/commands/plugin/PluginOptionsFlow.tsx +135 -0
- package/src/commands/plugin/PluginSettings.tsx +1072 -0
- package/src/commands/plugin/PluginTrustWarning.tsx +32 -0
- package/src/commands/plugin/UnifiedInstalledCell.tsx +565 -0
- package/src/commands/plugin/ValidatePlugin.tsx +98 -0
- package/src/commands/plugin/index.tsx +11 -0
- package/src/commands/plugin/parseArgs.ts +103 -0
- package/src/commands/plugin/plugin.tsx +7 -0
- package/src/commands/plugin/pluginDetailsHelpers.tsx +117 -0
- package/src/commands/plugin/usePagination.ts +171 -0
- package/src/commands/pr_comments/index.ts +50 -0
- package/src/commands/privacy-settings/index.ts +14 -0
- package/src/commands/privacy-settings/privacy-settings.tsx +58 -0
- package/src/commands/rate-limit-options/index.ts +19 -0
- package/src/commands/rate-limit-options/rate-limit-options.tsx +210 -0
- package/src/commands/release-notes/index.ts +11 -0
- package/src/commands/release-notes/release-notes.ts +50 -0
- package/src/commands/reload-plugins/index.ts +18 -0
- package/src/commands/reload-plugins/reload-plugins.ts +61 -0
- package/src/commands/remote-env/index.ts +15 -0
- package/src/commands/remote-env/remote-env.tsx +7 -0
- package/src/commands/remote-setup/api.ts +182 -0
- package/src/commands/remote-setup/index.ts +20 -0
- package/src/commands/remote-setup/remote-setup.tsx +187 -0
- package/src/commands/rename/generateSessionName.ts +67 -0
- package/src/commands/rename/index.ts +12 -0
- package/src/commands/rename/rename.ts +87 -0
- package/src/commands/reset-limits/index.js +4 -0
- package/src/commands/resume/index.ts +12 -0
- package/src/commands/resume/resume.tsx +275 -0
- package/src/commands/review/UltrareviewOverageDialog.tsx +96 -0
- package/src/commands/review/reviewRemote.ts +316 -0
- package/src/commands/review/ultrareviewCommand.tsx +58 -0
- package/src/commands/review/ultrareviewEnabled.ts +14 -0
- package/src/commands/review.ts +57 -0
- package/src/commands/rewind/index.ts +13 -0
- package/src/commands/rewind/rewind.ts +13 -0
- package/src/commands/sandbox-toggle/index.ts +50 -0
- package/src/commands/sandbox-toggle/sandbox-toggle.tsx +83 -0
- package/src/commands/security-review.ts +243 -0
- package/src/commands/session/index.ts +16 -0
- package/src/commands/session/session.tsx +140 -0
- package/src/commands/share/index.js +1 -0
- package/src/commands/skills/index.ts +10 -0
- package/src/commands/skills/skills.tsx +8 -0
- package/src/commands/stats/index.ts +10 -0
- package/src/commands/stats/stats.tsx +7 -0
- package/src/commands/status/index.ts +12 -0
- package/src/commands/status/status.tsx +8 -0
- package/src/commands/statusline.tsx +24 -0
- package/src/commands/stickers/index.ts +11 -0
- package/src/commands/stickers/stickers.ts +16 -0
- package/src/commands/summary/index.js +1 -0
- package/src/commands/tag/index.ts +12 -0
- package/src/commands/tag/tag.tsx +215 -0
- package/src/commands/tasks/index.ts +11 -0
- package/src/commands/tasks/tasks.tsx +8 -0
- package/src/commands/teleport/index.js +1 -0
- package/src/commands/terminalSetup/index.ts +23 -0
- package/src/commands/terminalSetup/terminalSetup.tsx +531 -0
- package/src/commands/theme/index.ts +10 -0
- package/src/commands/theme/theme.tsx +57 -0
- package/src/commands/thinkback/index.ts +13 -0
- package/src/commands/thinkback/thinkback.tsx +554 -0
- package/src/commands/thinkback-play/index.ts +17 -0
- package/src/commands/thinkback-play/thinkback-play.ts +43 -0
- package/src/commands/ultraplan.tsx +471 -0
- package/src/commands/upgrade/index.ts +16 -0
- package/src/commands/upgrade/upgrade.tsx +38 -0
- package/src/commands/usage/index.ts +9 -0
- package/src/commands/usage/usage.tsx +7 -0
- package/src/commands/version.ts +22 -0
- package/src/commands/vim/index.ts +11 -0
- package/src/commands/vim/vim.ts +38 -0
- package/src/commands/voice/index.ts +20 -0
- package/src/commands/voice/voice.ts +150 -0
- package/src/commands.ts +754 -0
- package/src/components/AgentProgressLine.tsx +136 -0
- package/src/components/App.tsx +56 -0
- package/src/components/ApproveApiKey.tsx +123 -0
- package/src/components/AutoModeOptInDialog.tsx +142 -0
- package/src/components/AutoUpdater.tsx +198 -0
- package/src/components/AutoUpdaterWrapper.tsx +91 -0
- package/src/components/AwsAuthStatusBox.tsx +82 -0
- package/src/components/BaseTextInput.tsx +136 -0
- package/src/components/BashModeProgress.tsx +56 -0
- package/src/components/BridgeDialog.tsx +401 -0
- package/src/components/BypassPermissionsModeDialog.tsx +87 -0
- package/src/components/ChannelDowngradeDialog.tsx +102 -0
- package/src/components/ClaudeCodeHint/PluginHintMenu.tsx +78 -0
- package/src/components/ClaudeInChromeOnboarding.tsx +121 -0
- package/src/components/ClaudeMdExternalIncludesDialog.tsx +137 -0
- package/src/components/ClickableImageRef.tsx +73 -0
- package/src/components/CompactSummary.tsx +118 -0
- package/src/components/ConfigurableShortcutHint.tsx +57 -0
- package/src/components/ConsoleOAuthFlow.tsx +631 -0
- package/src/components/ContextSuggestions.tsx +47 -0
- package/src/components/ContextVisualization.tsx +489 -0
- package/src/components/CoordinatorAgentStatus.tsx +273 -0
- package/src/components/CostThresholdDialog.tsx +50 -0
- package/src/components/CtrlOToExpand.tsx +51 -0
- package/src/components/CustomSelect/SelectMulti.tsx +213 -0
- package/src/components/CustomSelect/index.ts +3 -0
- package/src/components/CustomSelect/option-map.ts +50 -0
- package/src/components/CustomSelect/select-input-option.tsx +488 -0
- package/src/components/CustomSelect/select-option.tsx +68 -0
- package/src/components/CustomSelect/select.tsx +690 -0
- package/src/components/CustomSelect/use-multi-select-state.ts +414 -0
- package/src/components/CustomSelect/use-select-input.ts +287 -0
- package/src/components/CustomSelect/use-select-navigation.ts +653 -0
- package/src/components/CustomSelect/use-select-state.ts +157 -0
- package/src/components/DesktopHandoff.tsx +193 -0
- package/src/components/DesktopUpsell/DesktopUpsellStartup.tsx +171 -0
- package/src/components/DevBar.tsx +49 -0
- package/src/components/DevChannelsDialog.tsx +105 -0
- package/src/components/DiagnosticsDisplay.tsx +95 -0
- package/src/components/EffortCallout.tsx +265 -0
- package/src/components/EffortIndicator.ts +42 -0
- package/src/components/ExitFlow.tsx +48 -0
- package/src/components/ExportDialog.tsx +128 -0
- package/src/components/FallbackToolUseErrorMessage.tsx +116 -0
- package/src/components/FallbackToolUseRejectedMessage.tsx +16 -0
- package/src/components/FastIcon.tsx +46 -0
- package/src/components/Feedback.tsx +592 -0
- package/src/components/FeedbackSurvey/FeedbackSurvey.tsx +174 -0
- package/src/components/FeedbackSurvey/FeedbackSurveyView.tsx +108 -0
- package/src/components/FeedbackSurvey/TranscriptSharePrompt.tsx +88 -0
- package/src/components/FeedbackSurvey/submitTranscriptShare.ts +112 -0
- package/src/components/FeedbackSurvey/useDebouncedDigitInput.ts +82 -0
- package/src/components/FeedbackSurvey/useFeedbackSurvey.tsx +296 -0
- package/src/components/FeedbackSurvey/useMemorySurvey.tsx +213 -0
- package/src/components/FeedbackSurvey/usePostCompactSurvey.tsx +206 -0
- package/src/components/FeedbackSurvey/useSurveyState.tsx +100 -0
- package/src/components/FileEditToolDiff.tsx +181 -0
- package/src/components/FileEditToolUpdatedMessage.tsx +124 -0
- package/src/components/FileEditToolUseRejectedMessage.tsx +170 -0
- package/src/components/FilePathLink.tsx +43 -0
- package/src/components/FullscreenLayout.tsx +637 -0
- package/src/components/GlobalSearchDialog.tsx +343 -0
- package/src/components/HelpV2/Commands.tsx +82 -0
- package/src/components/HelpV2/General.tsx +23 -0
- package/src/components/HelpV2/HelpV2.tsx +184 -0
- package/src/components/HighlightedCode/Fallback.tsx +193 -0
- package/src/components/HighlightedCode.tsx +190 -0
- package/src/components/HistorySearchDialog.tsx +118 -0
- package/src/components/IdeAutoConnectDialog.tsx +154 -0
- package/src/components/IdeOnboardingDialog.tsx +167 -0
- package/src/components/IdeStatusIndicator.tsx +58 -0
- package/src/components/IdleReturnDialog.tsx +118 -0
- package/src/components/InterruptedByUser.tsx +15 -0
- package/src/components/InvalidConfigDialog.tsx +156 -0
- package/src/components/InvalidSettingsDialog.tsx +89 -0
- package/src/components/KeybindingWarnings.tsx +55 -0
- package/src/components/LanguagePicker.tsx +86 -0
- package/src/components/LogSelector.tsx +1575 -0
- package/src/components/LogoV2/AnimatedAsterisk.tsx +50 -0
- package/src/components/LogoV2/AnimatedClawd.tsx +124 -0
- package/src/components/LogoV2/ChannelsNotice.tsx +266 -0
- package/src/components/LogoV2/Clawd.tsx +240 -0
- package/src/components/LogoV2/CondensedLogo.tsx +161 -0
- package/src/components/LogoV2/EmergencyTip.tsx +58 -0
- package/src/components/LogoV2/Feed.tsx +112 -0
- package/src/components/LogoV2/FeedColumn.tsx +59 -0
- package/src/components/LogoV2/GuestPassesUpsell.tsx +70 -0
- package/src/components/LogoV2/LogoV2.tsx +543 -0
- package/src/components/LogoV2/Opus1mMergeNotice.tsx +55 -0
- package/src/components/LogoV2/OverageCreditUpsell.tsx +166 -0
- package/src/components/LogoV2/VoiceModeNotice.tsx +68 -0
- package/src/components/LogoV2/WelcomeV2.tsx +433 -0
- package/src/components/LogoV2/feedConfigs.tsx +92 -0
- package/src/components/LspRecommendation/LspRecommendationMenu.tsx +88 -0
- package/src/components/MCPServerApprovalDialog.tsx +115 -0
- package/src/components/MCPServerDesktopImportDialog.tsx +203 -0
- package/src/components/MCPServerDialogCopy.tsx +15 -0
- package/src/components/MCPServerMultiselectDialog.tsx +133 -0
- package/src/components/ManagedSettingsSecurityDialog/ManagedSettingsSecurityDialog.tsx +149 -0
- package/src/components/ManagedSettingsSecurityDialog/utils.ts +144 -0
- package/src/components/Markdown.tsx +236 -0
- package/src/components/MarkdownTable.tsx +322 -0
- package/src/components/MemoryUsageIndicator.tsx +37 -0
- package/src/components/Message.tsx +627 -0
- package/src/components/MessageModel.tsx +43 -0
- package/src/components/MessageResponse.tsx +78 -0
- package/src/components/MessageRow.tsx +383 -0
- package/src/components/MessageSelector.tsx +831 -0
- package/src/components/MessageTimestamp.tsx +63 -0
- package/src/components/Messages.tsx +834 -0
- package/src/components/ModelPicker.tsx +448 -0
- package/src/components/NativeAutoUpdater.tsx +193 -0
- package/src/components/NotebookEditToolUseRejectedMessage.tsx +92 -0
- package/src/components/OffscreenFreeze.tsx +44 -0
- package/src/components/Onboarding.tsx +244 -0
- package/src/components/OutputStylePicker.tsx +112 -0
- package/src/components/PackageManagerAutoUpdater.tsx +104 -0
- package/src/components/Passes/Passes.tsx +184 -0
- package/src/components/PrBadge.tsx +97 -0
- package/src/components/PressEnterToContinue.tsx +15 -0
- package/src/components/PromptInput/HistorySearchInput.tsx +51 -0
- package/src/components/PromptInput/IssueFlagBanner.tsx +12 -0
- package/src/components/PromptInput/Notifications.tsx +332 -0
- package/src/components/PromptInput/PromptInput.tsx +2339 -0
- package/src/components/PromptInput/PromptInputFooter.tsx +191 -0
- package/src/components/PromptInput/PromptInputFooterLeftSide.tsx +517 -0
- package/src/components/PromptInput/PromptInputFooterSuggestions.tsx +293 -0
- package/src/components/PromptInput/PromptInputHelpMenu.tsx +358 -0
- package/src/components/PromptInput/PromptInputModeIndicator.tsx +93 -0
- package/src/components/PromptInput/PromptInputQueuedCommands.tsx +117 -0
- package/src/components/PromptInput/PromptInputStashNotice.tsx +25 -0
- package/src/components/PromptInput/SandboxPromptFooterHint.tsx +64 -0
- package/src/components/PromptInput/ShimmeredInput.tsx +143 -0
- package/src/components/PromptInput/VoiceIndicator.tsx +137 -0
- package/src/components/PromptInput/inputModes.ts +33 -0
- package/src/components/PromptInput/inputPaste.ts +90 -0
- package/src/components/PromptInput/useMaybeTruncateInput.ts +58 -0
- package/src/components/PromptInput/usePromptInputPlaceholder.ts +76 -0
- package/src/components/PromptInput/useShowFastIconHint.ts +31 -0
- package/src/components/PromptInput/useSwarmBanner.ts +155 -0
- package/src/components/PromptInput/utils.ts +60 -0
- package/src/components/QuickOpenDialog.tsx +244 -0
- package/src/components/RemoteCallout.tsx +76 -0
- package/src/components/RemoteEnvironmentDialog.tsx +340 -0
- package/src/components/ResumeTask.tsx +268 -0
- package/src/components/SandboxViolationExpandedView.tsx +99 -0
- package/src/components/ScrollKeybindingHandler.tsx +1012 -0
- package/src/components/SearchBox.tsx +72 -0
- package/src/components/SentryErrorBoundary.ts +28 -0
- package/src/components/SessionBackgroundHint.tsx +108 -0
- package/src/components/SessionPreview.tsx +194 -0
- package/src/components/Settings/Config.tsx +1822 -0
- package/src/components/Settings/Settings.tsx +137 -0
- package/src/components/Settings/Status.tsx +241 -0
- package/src/components/Settings/Usage.tsx +377 -0
- package/src/components/ShowInIDEPrompt.tsx +170 -0
- package/src/components/SkillImprovementSurvey.tsx +152 -0
- package/src/components/Spinner/FlashingChar.tsx +61 -0
- package/src/components/Spinner/GlimmerMessage.tsx +328 -0
- package/src/components/Spinner/ShimmerChar.tsx +36 -0
- package/src/components/Spinner/SpinnerAnimationRow.tsx +265 -0
- package/src/components/Spinner/SpinnerGlyph.tsx +80 -0
- package/src/components/Spinner/TeammateSpinnerLine.tsx +233 -0
- package/src/components/Spinner/TeammateSpinnerTree.tsx +272 -0
- package/src/components/Spinner/index.ts +10 -0
- package/src/components/Spinner/teammateSelectHint.ts +1 -0
- package/src/components/Spinner/useShimmerAnimation.ts +31 -0
- package/src/components/Spinner/useStalledAnimation.ts +75 -0
- package/src/components/Spinner/utils.ts +84 -0
- package/src/components/Spinner.tsx +562 -0
- package/src/components/Stats.tsx +1228 -0
- package/src/components/StatusLine.tsx +324 -0
- package/src/components/StatusNotices.tsx +55 -0
- package/src/components/StructuredDiff/Fallback.tsx +487 -0
- package/src/components/StructuredDiff/colorDiff.ts +37 -0
- package/src/components/StructuredDiff.tsx +190 -0
- package/src/components/StructuredDiffList.tsx +30 -0
- package/src/components/TagTabs.tsx +139 -0
- package/src/components/TaskListV2.tsx +378 -0
- package/src/components/TeammateViewHeader.tsx +82 -0
- package/src/components/TeleportError.tsx +189 -0
- package/src/components/TeleportProgress.tsx +140 -0
- package/src/components/TeleportRepoMismatchDialog.tsx +104 -0
- package/src/components/TeleportResumeWrapper.tsx +167 -0
- package/src/components/TeleportStash.tsx +116 -0
- package/src/components/TextInput.tsx +124 -0
- package/src/components/ThemePicker.tsx +333 -0
- package/src/components/ThinkingToggle.tsx +153 -0
- package/src/components/TokenWarning.tsx +179 -0
- package/src/components/ToolUseLoader.tsx +42 -0
- package/src/components/TrustDialog/TrustDialog.tsx +290 -0
- package/src/components/TrustDialog/utils.ts +245 -0
- package/src/components/ValidationErrorsList.tsx +148 -0
- package/src/components/VimTextInput.tsx +140 -0
- package/src/components/VirtualMessageList.tsx +1082 -0
- package/src/components/WorkflowMultiselectDialog.tsx +128 -0
- package/src/components/WorktreeExitDialog.tsx +231 -0
- package/src/components/agents/AgentDetail.tsx +220 -0
- package/src/components/agents/AgentEditor.tsx +178 -0
- package/src/components/agents/AgentNavigationFooter.tsx +26 -0
- package/src/components/agents/AgentsList.tsx +440 -0
- package/src/components/agents/AgentsMenu.tsx +800 -0
- package/src/components/agents/ColorPicker.tsx +112 -0
- package/src/components/agents/ModelSelector.tsx +68 -0
- package/src/components/agents/ToolSelector.tsx +562 -0
- package/src/components/agents/agentFileUtils.ts +272 -0
- package/src/components/agents/generateAgent.ts +197 -0
- package/src/components/agents/new-agent-creation/CreateAgentWizard.tsx +97 -0
- package/src/components/agents/new-agent-creation/wizard-steps/ColorStep.tsx +84 -0
- package/src/components/agents/new-agent-creation/wizard-steps/ConfirmStep.tsx +378 -0
- package/src/components/agents/new-agent-creation/wizard-steps/ConfirmStepWrapper.tsx +74 -0
- package/src/components/agents/new-agent-creation/wizard-steps/DescriptionStep.tsx +123 -0
- package/src/components/agents/new-agent-creation/wizard-steps/GenerateStep.tsx +143 -0
- package/src/components/agents/new-agent-creation/wizard-steps/LocationStep.tsx +80 -0
- package/src/components/agents/new-agent-creation/wizard-steps/MemoryStep.tsx +113 -0
- package/src/components/agents/new-agent-creation/wizard-steps/MethodStep.tsx +80 -0
- package/src/components/agents/new-agent-creation/wizard-steps/ModelStep.tsx +52 -0
- package/src/components/agents/new-agent-creation/wizard-steps/PromptStep.tsx +128 -0
- package/src/components/agents/new-agent-creation/wizard-steps/ToolsStep.tsx +61 -0
- package/src/components/agents/new-agent-creation/wizard-steps/TypeStep.tsx +103 -0
- package/src/components/agents/types.ts +27 -0
- package/src/components/agents/utils.ts +18 -0
- package/src/components/agents/validateAgent.ts +109 -0
- package/src/components/design-system/Byline.tsx +77 -0
- package/src/components/design-system/Dialog.tsx +138 -0
- package/src/components/design-system/Divider.tsx +149 -0
- package/src/components/design-system/FuzzyPicker.tsx +312 -0
- package/src/components/design-system/KeyboardShortcutHint.tsx +81 -0
- package/src/components/design-system/ListItem.tsx +244 -0
- package/src/components/design-system/LoadingState.tsx +94 -0
- package/src/components/design-system/Pane.tsx +77 -0
- package/src/components/design-system/ProgressBar.tsx +86 -0
- package/src/components/design-system/Ratchet.tsx +80 -0
- package/src/components/design-system/StatusIcon.tsx +95 -0
- package/src/components/design-system/Tabs.tsx +340 -0
- package/src/components/design-system/ThemeProvider.tsx +174 -0
- package/src/components/design-system/ThemedBox.tsx +156 -0
- package/src/components/design-system/ThemedText.tsx +124 -0
- package/src/components/design-system/color.ts +30 -0
- package/src/components/diff/DiffDetailView.tsx +281 -0
- package/src/components/diff/DiffDialog.tsx +383 -0
- package/src/components/diff/DiffFileList.tsx +292 -0
- package/src/components/grove/Grove.tsx +463 -0
- package/src/components/hooks/HooksConfigMenu.tsx +578 -0
- package/src/components/hooks/PromptDialog.tsx +90 -0
- package/src/components/hooks/SelectEventMode.tsx +127 -0
- package/src/components/hooks/SelectHookMode.tsx +112 -0
- package/src/components/hooks/SelectMatcherMode.tsx +144 -0
- package/src/components/hooks/ViewHookMode.tsx +199 -0
- package/src/components/mcp/CapabilitiesSection.tsx +61 -0
- package/src/components/mcp/ElicitationDialog.tsx +1169 -0
- package/src/components/mcp/MCPAgentServerMenu.tsx +183 -0
- package/src/components/mcp/MCPListPanel.tsx +504 -0
- package/src/components/mcp/MCPReconnect.tsx +167 -0
- package/src/components/mcp/MCPRemoteServerMenu.tsx +649 -0
- package/src/components/mcp/MCPSettings.tsx +398 -0
- package/src/components/mcp/MCPStdioServerMenu.tsx +177 -0
- package/src/components/mcp/MCPToolDetailView.tsx +212 -0
- package/src/components/mcp/MCPToolListView.tsx +141 -0
- package/src/components/mcp/McpParsingWarnings.tsx +213 -0
- package/src/components/mcp/index.ts +9 -0
- package/src/components/mcp/utils/reconnectHelpers.tsx +49 -0
- package/src/components/memory/MemoryFileSelector.tsx +438 -0
- package/src/components/memory/MemoryUpdateNotification.tsx +45 -0
- package/src/components/messageActions.tsx +450 -0
- package/src/components/messages/AdvisorMessage.tsx +158 -0
- package/src/components/messages/AssistantRedactedThinkingMessage.tsx +31 -0
- package/src/components/messages/AssistantTextMessage.tsx +270 -0
- package/src/components/messages/AssistantThinkingMessage.tsx +86 -0
- package/src/components/messages/AssistantToolUseMessage.tsx +368 -0
- package/src/components/messages/AttachmentMessage.tsx +536 -0
- package/src/components/messages/CollapsedReadSearchContent.tsx +484 -0
- package/src/components/messages/CompactBoundaryMessage.tsx +18 -0
- package/src/components/messages/GroupedToolUseContent.tsx +58 -0
- package/src/components/messages/HighlightedThinkingText.tsx +162 -0
- package/src/components/messages/HookProgressMessage.tsx +116 -0
- package/src/components/messages/PlanApprovalMessage.tsx +222 -0
- package/src/components/messages/RateLimitMessage.tsx +161 -0
- package/src/components/messages/ShutdownMessage.tsx +132 -0
- package/src/components/messages/SystemAPIErrorMessage.tsx +141 -0
- package/src/components/messages/SystemTextMessage.tsx +827 -0
- package/src/components/messages/TaskAssignmentMessage.tsx +76 -0
- package/src/components/messages/UserAgentNotificationMessage.tsx +83 -0
- package/src/components/messages/UserBashInputMessage.tsx +58 -0
- package/src/components/messages/UserBashOutputMessage.tsx +54 -0
- package/src/components/messages/UserChannelMessage.tsx +137 -0
- package/src/components/messages/UserCommandMessage.tsx +108 -0
- package/src/components/messages/UserImageMessage.tsx +59 -0
- package/src/components/messages/UserLocalCommandOutputMessage.tsx +167 -0
- package/src/components/messages/UserMemoryInputMessage.tsx +75 -0
- package/src/components/messages/UserPlanMessage.tsx +42 -0
- package/src/components/messages/UserPromptMessage.tsx +80 -0
- package/src/components/messages/UserResourceUpdateMessage.tsx +121 -0
- package/src/components/messages/UserTeammateMessage.tsx +206 -0
- package/src/components/messages/UserTextMessage.tsx +275 -0
- package/src/components/messages/UserToolResultMessage/RejectedPlanMessage.tsx +31 -0
- package/src/components/messages/UserToolResultMessage/RejectedToolUseMessage.tsx +16 -0
- package/src/components/messages/UserToolResultMessage/UserToolCanceledMessage.tsx +16 -0
- package/src/components/messages/UserToolResultMessage/UserToolErrorMessage.tsx +103 -0
- package/src/components/messages/UserToolResultMessage/UserToolRejectMessage.tsx +95 -0
- package/src/components/messages/UserToolResultMessage/UserToolResultMessage.tsx +106 -0
- package/src/components/messages/UserToolResultMessage/UserToolSuccessMessage.tsx +104 -0
- package/src/components/messages/UserToolResultMessage/utils.tsx +44 -0
- package/src/components/messages/nullRenderingAttachments.ts +70 -0
- package/src/components/messages/teamMemCollapsed.tsx +140 -0
- package/src/components/messages/teamMemSaved.ts +19 -0
- package/src/components/permissions/AskUserQuestionPermissionRequest/AskUserQuestionPermissionRequest.tsx +645 -0
- package/src/components/permissions/AskUserQuestionPermissionRequest/PreviewBox.tsx +229 -0
- package/src/components/permissions/AskUserQuestionPermissionRequest/PreviewQuestionView.tsx +328 -0
- package/src/components/permissions/AskUserQuestionPermissionRequest/QuestionNavigationBar.tsx +178 -0
- package/src/components/permissions/AskUserQuestionPermissionRequest/QuestionView.tsx +465 -0
- package/src/components/permissions/AskUserQuestionPermissionRequest/SubmitQuestionsView.tsx +144 -0
- package/src/components/permissions/AskUserQuestionPermissionRequest/use-multiple-choice-state.ts +179 -0
- package/src/components/permissions/BashPermissionRequest/BashPermissionRequest.tsx +482 -0
- package/src/components/permissions/BashPermissionRequest/bashToolUseOptions.tsx +147 -0
- package/src/components/permissions/ComputerUseApproval/ComputerUseApproval.tsx +441 -0
- package/src/components/permissions/EnterPlanModePermissionRequest/EnterPlanModePermissionRequest.tsx +122 -0
- package/src/components/permissions/ExitPlanModePermissionRequest/ExitPlanModePermissionRequest.tsx +768 -0
- package/src/components/permissions/FallbackPermissionRequest.tsx +333 -0
- package/src/components/permissions/FileEditPermissionRequest/FileEditPermissionRequest.tsx +182 -0
- package/src/components/permissions/FilePermissionDialog/FilePermissionDialog.tsx +204 -0
- package/src/components/permissions/FilePermissionDialog/ideDiffConfig.ts +42 -0
- package/src/components/permissions/FilePermissionDialog/permissionOptions.tsx +177 -0
- package/src/components/permissions/FilePermissionDialog/useFilePermissionDialog.ts +212 -0
- package/src/components/permissions/FilePermissionDialog/usePermissionHandler.ts +185 -0
- package/src/components/permissions/FileWritePermissionRequest/FileWritePermissionRequest.tsx +161 -0
- package/src/components/permissions/FileWritePermissionRequest/FileWriteToolDiff.tsx +89 -0
- package/src/components/permissions/FilesystemPermissionRequest/FilesystemPermissionRequest.tsx +115 -0
- package/src/components/permissions/NotebookEditPermissionRequest/NotebookEditPermissionRequest.tsx +166 -0
- package/src/components/permissions/NotebookEditPermissionRequest/NotebookEditToolDiff.tsx +235 -0
- package/src/components/permissions/PermissionDecisionDebugInfo.tsx +460 -0
- package/src/components/permissions/PermissionDialog.tsx +72 -0
- package/src/components/permissions/PermissionExplanation.tsx +272 -0
- package/src/components/permissions/PermissionPrompt.tsx +336 -0
- package/src/components/permissions/PermissionRequest.tsx +217 -0
- package/src/components/permissions/PermissionRequestTitle.tsx +66 -0
- package/src/components/permissions/PermissionRuleExplanation.tsx +121 -0
- package/src/components/permissions/PowerShellPermissionRequest/PowerShellPermissionRequest.tsx +235 -0
- package/src/components/permissions/PowerShellPermissionRequest/powershellToolUseOptions.tsx +91 -0
- package/src/components/permissions/SandboxPermissionRequest.tsx +163 -0
- package/src/components/permissions/SedEditPermissionRequest/SedEditPermissionRequest.tsx +230 -0
- package/src/components/permissions/SkillPermissionRequest/SkillPermissionRequest.tsx +369 -0
- package/src/components/permissions/WebFetchPermissionRequest/WebFetchPermissionRequest.tsx +258 -0
- package/src/components/permissions/WorkerBadge.tsx +49 -0
- package/src/components/permissions/WorkerPendingPermission.tsx +105 -0
- package/src/components/permissions/hooks.ts +209 -0
- package/src/components/permissions/rules/AddPermissionRules.tsx +180 -0
- package/src/components/permissions/rules/AddWorkspaceDirectory.tsx +340 -0
- package/src/components/permissions/rules/PermissionRuleDescription.tsx +76 -0
- package/src/components/permissions/rules/PermissionRuleInput.tsx +138 -0
- package/src/components/permissions/rules/PermissionRuleList.tsx +1179 -0
- package/src/components/permissions/rules/RecentDenialsTab.tsx +207 -0
- package/src/components/permissions/rules/RemoveWorkspaceDirectory.tsx +110 -0
- package/src/components/permissions/rules/WorkspaceTab.tsx +150 -0
- package/src/components/permissions/shellPermissionHelpers.tsx +164 -0
- package/src/components/permissions/useShellPermissionFeedback.ts +148 -0
- package/src/components/permissions/utils.ts +25 -0
- package/src/components/sandbox/SandboxConfigTab.tsx +45 -0
- package/src/components/sandbox/SandboxDependenciesTab.tsx +120 -0
- package/src/components/sandbox/SandboxDoctorSection.tsx +46 -0
- package/src/components/sandbox/SandboxOverridesTab.tsx +193 -0
- package/src/components/sandbox/SandboxSettings.tsx +296 -0
- package/src/components/shell/ExpandShellOutputContext.tsx +36 -0
- package/src/components/shell/OutputLine.tsx +118 -0
- package/src/components/shell/ShellProgressMessage.tsx +150 -0
- package/src/components/shell/ShellTimeDisplay.tsx +74 -0
- package/src/components/skills/SkillsMenu.tsx +237 -0
- package/src/components/tasks/AsyncAgentDetailDialog.tsx +229 -0
- package/src/components/tasks/BackgroundTask.tsx +345 -0
- package/src/components/tasks/BackgroundTaskStatus.tsx +429 -0
- package/src/components/tasks/BackgroundTasksDialog.tsx +652 -0
- package/src/components/tasks/DreamDetailDialog.tsx +251 -0
- package/src/components/tasks/InProcessTeammateDetailDialog.tsx +266 -0
- package/src/components/tasks/RemoteSessionDetailDialog.tsx +904 -0
- package/src/components/tasks/RemoteSessionProgress.tsx +243 -0
- package/src/components/tasks/ShellDetailDialog.tsx +404 -0
- package/src/components/tasks/ShellProgress.tsx +87 -0
- package/src/components/tasks/renderToolActivity.tsx +33 -0
- package/src/components/tasks/taskStatusUtils.tsx +107 -0
- package/src/components/teams/TeamStatus.tsx +80 -0
- package/src/components/teams/TeamsDialog.tsx +715 -0
- package/src/components/ui/OrderedList.tsx +71 -0
- package/src/components/ui/OrderedListItem.tsx +45 -0
- package/src/components/ui/TreeSelect.tsx +397 -0
- package/src/components/wizard/WizardDialogLayout.tsx +65 -0
- package/src/components/wizard/WizardNavigationFooter.tsx +24 -0
- package/src/components/wizard/WizardProvider.tsx +213 -0
- package/src/components/wizard/index.ts +9 -0
- package/src/components/wizard/useWizard.ts +13 -0
- package/src/constants/apiLimits.ts +94 -0
- package/src/constants/betas.ts +52 -0
- package/src/constants/common.ts +33 -0
- package/src/constants/cyberRiskInstruction.ts +24 -0
- package/src/constants/errorIds.ts +15 -0
- package/src/constants/figures.ts +45 -0
- package/src/constants/files.ts +156 -0
- package/src/constants/github-app.ts +144 -0
- package/src/constants/keys.ts +11 -0
- package/src/constants/messages.ts +1 -0
- package/src/constants/oauth.ts +234 -0
- package/src/constants/outputStyles.ts +216 -0
- package/src/constants/product.ts +76 -0
- package/src/constants/prompts.ts +914 -0
- package/src/constants/spinnerVerbs.ts +204 -0
- package/src/constants/system.ts +95 -0
- package/src/constants/systemPromptSections.ts +68 -0
- package/src/constants/toolLimits.ts +56 -0
- package/src/constants/tools.ts +112 -0
- package/src/constants/turnCompletionVerbs.ts +12 -0
- package/src/constants/xml.ts +86 -0
- package/src/context/QueuedMessageContext.tsx +63 -0
- package/src/context/fpsMetrics.tsx +30 -0
- package/src/context/mailbox.tsx +38 -0
- package/src/context/modalContext.tsx +58 -0
- package/src/context/notifications.tsx +240 -0
- package/src/context/overlayContext.tsx +151 -0
- package/src/context/promptOverlayContext.tsx +125 -0
- package/src/context/stats.tsx +220 -0
- package/src/context/voice.tsx +88 -0
- package/src/context.ts +189 -0
- package/src/coordinator/coordinatorMode.ts +369 -0
- package/src/cost-tracker.ts +323 -0
- package/src/costHook.ts +22 -0
- package/src/dialogLaunchers.tsx +133 -0
- package/src/entrypoints/agentSdkTypes.ts +443 -0
- package/src/entrypoints/cli.tsx +303 -0
- package/src/entrypoints/init.ts +340 -0
- package/src/entrypoints/mcp.ts +196 -0
- package/src/entrypoints/sandboxTypes.ts +156 -0
- package/src/entrypoints/sdk/controlSchemas.ts +663 -0
- package/src/entrypoints/sdk/coreSchemas.ts +1889 -0
- package/src/entrypoints/sdk/coreTypes.ts +62 -0
- package/src/history.ts +464 -0
- package/src/hooks/fileSuggestions.ts +811 -0
- package/src/hooks/notifs/useAutoModeUnavailableNotification.ts +56 -0
- package/src/hooks/notifs/useCanSwitchToExistingSubscription.tsx +60 -0
- package/src/hooks/notifs/useDeprecationWarningNotification.tsx +44 -0
- package/src/hooks/notifs/useFastModeNotification.tsx +162 -0
- package/src/hooks/notifs/useIDEStatusIndicator.tsx +186 -0
- package/src/hooks/notifs/useInstallMessages.tsx +26 -0
- package/src/hooks/notifs/useLspInitializationNotification.tsx +143 -0
- package/src/hooks/notifs/useMcpConnectivityStatus.tsx +88 -0
- package/src/hooks/notifs/useModelMigrationNotifications.tsx +52 -0
- package/src/hooks/notifs/useNpmDeprecationNotification.tsx +25 -0
- package/src/hooks/notifs/usePluginAutoupdateNotification.tsx +83 -0
- package/src/hooks/notifs/usePluginInstallationStatus.tsx +128 -0
- package/src/hooks/notifs/useRateLimitWarningNotification.tsx +114 -0
- package/src/hooks/notifs/useSettingsErrors.tsx +69 -0
- package/src/hooks/notifs/useStartupNotification.ts +41 -0
- package/src/hooks/notifs/useTeammateShutdownNotification.ts +78 -0
- package/src/hooks/renderPlaceholder.ts +51 -0
- package/src/hooks/toolPermission/PermissionContext.ts +388 -0
- package/src/hooks/toolPermission/handlers/coordinatorHandler.ts +65 -0
- package/src/hooks/toolPermission/handlers/interactiveHandler.ts +536 -0
- package/src/hooks/toolPermission/handlers/swarmWorkerHandler.ts +159 -0
- package/src/hooks/toolPermission/permissionLogging.ts +238 -0
- package/src/hooks/unifiedSuggestions.ts +202 -0
- package/src/hooks/useAfterFirstRender.ts +17 -0
- package/src/hooks/useApiKeyVerification.ts +84 -0
- package/src/hooks/useArrowKeyHistory.tsx +229 -0
- package/src/hooks/useAssistantHistory.ts +250 -0
- package/src/hooks/useAwaySummary.ts +125 -0
- package/src/hooks/useBackgroundTaskNavigation.ts +251 -0
- package/src/hooks/useBlink.ts +34 -0
- package/src/hooks/useCanUseTool.tsx +204 -0
- package/src/hooks/useCancelRequest.ts +276 -0
- package/src/hooks/useChromeExtensionNotification.tsx +50 -0
- package/src/hooks/useClaudeCodeHintRecommendation.tsx +129 -0
- package/src/hooks/useClipboardImageHint.ts +77 -0
- package/src/hooks/useCommandKeybindings.tsx +108 -0
- package/src/hooks/useCommandQueue.ts +15 -0
- package/src/hooks/useCopyOnSelect.ts +98 -0
- package/src/hooks/useDeferredHookMessages.ts +46 -0
- package/src/hooks/useDiffData.ts +110 -0
- package/src/hooks/useDiffInIDE.ts +379 -0
- package/src/hooks/useDirectConnect.ts +229 -0
- package/src/hooks/useDoublePress.ts +62 -0
- package/src/hooks/useDynamicConfig.ts +22 -0
- package/src/hooks/useElapsedTime.ts +37 -0
- package/src/hooks/useExitOnCtrlCD.ts +95 -0
- package/src/hooks/useExitOnCtrlCDWithKeybindings.ts +24 -0
- package/src/hooks/useFileHistorySnapshotInit.ts +25 -0
- package/src/hooks/useGlobalKeybindings.tsx +249 -0
- package/src/hooks/useHistorySearch.ts +303 -0
- package/src/hooks/useIDEIntegration.tsx +70 -0
- package/src/hooks/useIdeAtMentioned.ts +76 -0
- package/src/hooks/useIdeConnectionStatus.ts +33 -0
- package/src/hooks/useIdeLogging.ts +41 -0
- package/src/hooks/useIdeSelection.ts +150 -0
- package/src/hooks/useInboxPoller.ts +969 -0
- package/src/hooks/useInputBuffer.ts +132 -0
- package/src/hooks/useIssueFlagBanner.ts +133 -0
- package/src/hooks/useLogMessages.ts +119 -0
- package/src/hooks/useLspPluginRecommendation.tsx +194 -0
- package/src/hooks/useMailboxBridge.ts +21 -0
- package/src/hooks/useMainLoopModel.ts +34 -0
- package/src/hooks/useManagePlugins.ts +304 -0
- package/src/hooks/useMemoryUsage.ts +39 -0
- package/src/hooks/useMergedClients.ts +23 -0
- package/src/hooks/useMergedCommands.ts +15 -0
- package/src/hooks/useMergedTools.ts +44 -0
- package/src/hooks/useMinDisplayTime.ts +35 -0
- package/src/hooks/useNotifyAfterTimeout.ts +65 -0
- package/src/hooks/useOfficialMarketplaceNotification.tsx +48 -0
- package/src/hooks/usePasteHandler.ts +285 -0
- package/src/hooks/usePluginRecommendationBase.tsx +105 -0
- package/src/hooks/usePrStatus.ts +106 -0
- package/src/hooks/usePromptSuggestion.ts +177 -0
- package/src/hooks/usePromptsFromClaudeInChrome.tsx +71 -0
- package/src/hooks/useQueueProcessor.ts +68 -0
- package/src/hooks/useRemoteSession.ts +605 -0
- package/src/hooks/useReplBridge.tsx +723 -0
- package/src/hooks/useSSHSession.ts +241 -0
- package/src/hooks/useScheduledTasks.ts +139 -0
- package/src/hooks/useSearchInput.ts +364 -0
- package/src/hooks/useSessionBackgrounding.ts +158 -0
- package/src/hooks/useSettings.ts +17 -0
- package/src/hooks/useSettingsChange.ts +25 -0
- package/src/hooks/useSkillImprovementSurvey.ts +105 -0
- package/src/hooks/useSkillsChange.ts +62 -0
- package/src/hooks/useSwarmInitialization.ts +81 -0
- package/src/hooks/useSwarmPermissionPoller.ts +330 -0
- package/src/hooks/useTaskListWatcher.ts +221 -0
- package/src/hooks/useTasksV2.ts +250 -0
- package/src/hooks/useTeammateViewAutoExit.ts +63 -0
- package/src/hooks/useTeleportResume.tsx +85 -0
- package/src/hooks/useTerminalSize.ts +15 -0
- package/src/hooks/useTextInput.ts +529 -0
- package/src/hooks/useTimeout.ts +14 -0
- package/src/hooks/useTurnDiffs.ts +213 -0
- package/src/hooks/useTypeahead.tsx +1385 -0
- package/src/hooks/useUpdateNotification.ts +34 -0
- package/src/hooks/useVimInput.ts +316 -0
- package/src/hooks/useVirtualScroll.ts +721 -0
- package/src/hooks/useVoice.ts +1144 -0
- package/src/hooks/useVoiceEnabled.ts +25 -0
- package/src/hooks/useVoiceIntegration.tsx +677 -0
- package/src/ink/Ansi.tsx +292 -0
- package/src/ink/bidi.ts +139 -0
- package/src/ink/clearTerminal.ts +74 -0
- package/src/ink/colorize.ts +231 -0
- package/src/ink/components/AlternateScreen.tsx +80 -0
- package/src/ink/components/App.tsx +659 -0
- package/src/ink/components/AppContext.ts +21 -0
- package/src/ink/components/Box.tsx +214 -0
- package/src/ink/components/Button.tsx +192 -0
- package/src/ink/components/ClockContext.tsx +112 -0
- package/src/ink/components/CursorDeclarationContext.ts +32 -0
- package/src/ink/components/ErrorOverview.tsx +109 -0
- package/src/ink/components/Link.tsx +42 -0
- package/src/ink/components/Newline.tsx +39 -0
- package/src/ink/components/NoSelect.tsx +68 -0
- package/src/ink/components/RawAnsi.tsx +57 -0
- package/src/ink/components/ScrollBox.tsx +237 -0
- package/src/ink/components/Spacer.tsx +20 -0
- package/src/ink/components/StdinContext.ts +49 -0
- package/src/ink/components/TerminalFocusContext.tsx +52 -0
- package/src/ink/components/TerminalSizeContext.tsx +7 -0
- package/src/ink/components/Text.tsx +254 -0
- package/src/ink/constants.ts +2 -0
- package/src/ink/dom.ts +484 -0
- package/src/ink/events/click-event.ts +38 -0
- package/src/ink/events/dispatcher.ts +233 -0
- package/src/ink/events/emitter.ts +39 -0
- package/src/ink/events/event-handlers.ts +73 -0
- package/src/ink/events/event.ts +11 -0
- package/src/ink/events/focus-event.ts +21 -0
- package/src/ink/events/input-event.ts +205 -0
- package/src/ink/events/keyboard-event.ts +51 -0
- package/src/ink/events/terminal-event.ts +107 -0
- package/src/ink/events/terminal-focus-event.ts +19 -0
- package/src/ink/focus.ts +181 -0
- package/src/ink/frame.ts +124 -0
- package/src/ink/get-max-width.ts +27 -0
- package/src/ink/hit-test.ts +130 -0
- package/src/ink/hooks/use-animation-frame.ts +57 -0
- package/src/ink/hooks/use-app.ts +8 -0
- package/src/ink/hooks/use-declared-cursor.ts +73 -0
- package/src/ink/hooks/use-input.ts +92 -0
- package/src/ink/hooks/use-interval.ts +67 -0
- package/src/ink/hooks/use-search-highlight.ts +53 -0
- package/src/ink/hooks/use-selection.ts +104 -0
- package/src/ink/hooks/use-stdin.ts +8 -0
- package/src/ink/hooks/use-tab-status.ts +72 -0
- package/src/ink/hooks/use-terminal-focus.ts +16 -0
- package/src/ink/hooks/use-terminal-title.ts +31 -0
- package/src/ink/hooks/use-terminal-viewport.ts +96 -0
- package/src/ink/ink.tsx +1728 -0
- package/src/ink/instances.ts +10 -0
- package/src/ink/layout/engine.ts +6 -0
- package/src/ink/layout/geometry.ts +97 -0
- package/src/ink/layout/node.ts +152 -0
- package/src/ink/layout/yoga.ts +308 -0
- package/src/ink/line-width-cache.ts +24 -0
- package/src/ink/log-update.ts +773 -0
- package/src/ink/measure-element.ts +23 -0
- package/src/ink/measure-text.ts +47 -0
- package/src/ink/node-cache.ts +54 -0
- package/src/ink/optimizer.ts +93 -0
- package/src/ink/output.ts +797 -0
- package/src/ink/parse-keypress.ts +801 -0
- package/src/ink/reconciler.ts +512 -0
- package/src/ink/render-border.ts +231 -0
- package/src/ink/render-node-to-output.ts +1462 -0
- package/src/ink/render-to-screen.ts +231 -0
- package/src/ink/renderer.ts +178 -0
- package/src/ink/root.ts +184 -0
- package/src/ink/screen.ts +1486 -0
- package/src/ink/searchHighlight.ts +93 -0
- package/src/ink/selection.ts +917 -0
- package/src/ink/squash-text-nodes.ts +92 -0
- package/src/ink/stringWidth.ts +222 -0
- package/src/ink/styles.ts +771 -0
- package/src/ink/supports-hyperlinks.ts +57 -0
- package/src/ink/tabstops.ts +46 -0
- package/src/ink/terminal-focus-state.ts +47 -0
- package/src/ink/terminal-querier.ts +212 -0
- package/src/ink/terminal.ts +248 -0
- package/src/ink/termio/ansi.ts +75 -0
- package/src/ink/termio/csi.ts +319 -0
- package/src/ink/termio/dec.ts +60 -0
- package/src/ink/termio/esc.ts +67 -0
- package/src/ink/termio/osc.ts +493 -0
- package/src/ink/termio/parser.ts +394 -0
- package/src/ink/termio/sgr.ts +308 -0
- package/src/ink/termio/tokenize.ts +319 -0
- package/src/ink/termio/types.ts +236 -0
- package/src/ink/termio.ts +42 -0
- package/src/ink/useTerminalNotification.ts +126 -0
- package/src/ink/warn.ts +9 -0
- package/src/ink/widest-line.ts +19 -0
- package/src/ink/wrap-text.ts +74 -0
- package/src/ink/wrapAnsi.ts +20 -0
- package/src/ink.ts +85 -0
- package/src/interactiveHelpers.tsx +367 -0
- package/src/keybindings/KeybindingContext.tsx +243 -0
- package/src/keybindings/KeybindingProviderSetup.tsx +308 -0
- package/src/keybindings/defaultBindings.ts +340 -0
- package/src/keybindings/loadUserBindings.ts +472 -0
- package/src/keybindings/match.ts +120 -0
- package/src/keybindings/parser.ts +203 -0
- package/src/keybindings/reservedShortcuts.ts +127 -0
- package/src/keybindings/resolver.ts +244 -0
- package/src/keybindings/schema.ts +236 -0
- package/src/keybindings/shortcutFormat.ts +63 -0
- package/src/keybindings/template.ts +52 -0
- package/src/keybindings/useKeybinding.ts +196 -0
- package/src/keybindings/useShortcutDisplay.ts +59 -0
- package/src/keybindings/validate.ts +498 -0
- package/src/main.tsx +4684 -0
- package/src/memdir/findRelevantMemories.ts +141 -0
- package/src/memdir/memdir.ts +507 -0
- package/src/memdir/memoryAge.ts +53 -0
- package/src/memdir/memoryScan.ts +94 -0
- package/src/memdir/memoryTypes.ts +271 -0
- package/src/memdir/paths.ts +278 -0
- package/src/memdir/teamMemPaths.ts +292 -0
- package/src/memdir/teamMemPrompts.ts +100 -0
- package/src/migrations/migrateAutoUpdatesToSettings.ts +61 -0
- package/src/migrations/migrateBypassPermissionsAcceptedToSettings.ts +40 -0
- package/src/migrations/migrateEnableAllProjectMcpServersToSettings.ts +118 -0
- package/src/migrations/migrateFennecToOpus.ts +45 -0
- package/src/migrations/migrateLegacyOpusToCurrent.ts +57 -0
- package/src/migrations/migrateOpusToOpus1m.ts +43 -0
- package/src/migrations/migrateReplBridgeEnabledToRemoteControlAtStartup.ts +22 -0
- package/src/migrations/migrateSonnet1mToSonnet45.ts +48 -0
- package/src/migrations/migrateSonnet45ToSonnet46.ts +67 -0
- package/src/migrations/resetAutoModeOptInForDefaultOffer.ts +51 -0
- package/src/migrations/resetProToOpusDefault.ts +51 -0
- package/src/moreright/useMoreRight.tsx +26 -0
- package/src/native-ts/color-diff/index.ts +999 -0
- package/src/native-ts/file-index/index.ts +370 -0
- package/src/native-ts/yoga-layout/enums.ts +134 -0
- package/src/native-ts/yoga-layout/index.ts +2578 -0
- package/src/outputStyles/loadOutputStylesDir.ts +98 -0
- package/src/plugins/builtinPlugins.ts +159 -0
- package/src/plugins/bundled/index.ts +23 -0
- package/src/projectOnboardingState.ts +83 -0
- package/src/query/config.ts +46 -0
- package/src/query/deps.ts +40 -0
- package/src/query/stopHooks.ts +473 -0
- package/src/query/tokenBudget.ts +93 -0
- package/src/query.ts +1729 -0
- package/src/remote/RemoteSessionManager.ts +343 -0
- package/src/remote/SessionsWebSocket.ts +404 -0
- package/src/remote/remotePermissionBridge.ts +78 -0
- package/src/remote/sdkMessageAdapter.ts +302 -0
- package/src/replLauncher.tsx +23 -0
- package/src/schemas/hooks.ts +222 -0
- package/src/screens/Doctor.tsx +575 -0
- package/src/screens/REPL.tsx +5006 -0
- package/src/screens/ResumeConversation.tsx +399 -0
- package/src/server/createDirectConnectSession.ts +88 -0
- package/src/server/directConnectManager.ts +213 -0
- package/src/server/types.ts +57 -0
- package/src/services/AgentSummary/agentSummary.ts +179 -0
- package/src/services/MagicDocs/magicDocs.ts +254 -0
- package/src/services/MagicDocs/prompts.ts +127 -0
- package/src/services/PromptSuggestion/promptSuggestion.ts +523 -0
- package/src/services/PromptSuggestion/speculation.ts +991 -0
- package/src/services/SessionMemory/prompts.ts +324 -0
- package/src/services/SessionMemory/sessionMemory.ts +495 -0
- package/src/services/SessionMemory/sessionMemoryUtils.ts +207 -0
- package/src/services/analytics/config.ts +38 -0
- package/src/services/analytics/datadog.ts +307 -0
- package/src/services/analytics/firstPartyEventLogger.ts +449 -0
- package/src/services/analytics/firstPartyEventLoggingExporter.ts +806 -0
- package/src/services/analytics/growthbook.ts +1157 -0
- package/src/services/analytics/index.ts +173 -0
- package/src/services/analytics/metadata.ts +973 -0
- package/src/services/analytics/sink.ts +114 -0
- package/src/services/analytics/sinkKillswitch.ts +25 -0
- package/src/services/api/adminRequests.ts +119 -0
- package/src/services/api/bootstrap.ts +142 -0
- package/src/services/api/claude.ts +3433 -0
- package/src/services/api/client.ts +395 -0
- package/src/services/api/dumpPrompts.ts +226 -0
- package/src/services/api/emptyUsage.ts +22 -0
- package/src/services/api/errorUtils.ts +260 -0
- package/src/services/api/errors.ts +1207 -0
- package/src/services/api/filesApi.ts +748 -0
- package/src/services/api/firstTokenDate.ts +60 -0
- package/src/services/api/grove.ts +357 -0
- package/src/services/api/logging.ts +788 -0
- package/src/services/api/metricsOptOut.ts +159 -0
- package/src/services/api/overageCreditGrant.ts +137 -0
- package/src/services/api/promptCacheBreakDetection.ts +727 -0
- package/src/services/api/referral.ts +281 -0
- package/src/services/api/sessionIngress.ts +514 -0
- package/src/services/api/ultrareviewQuota.ts +38 -0
- package/src/services/api/usage.ts +63 -0
- package/src/services/api/withRetry.ts +826 -0
- package/src/services/autoDream/autoDream.ts +324 -0
- package/src/services/autoDream/config.ts +21 -0
- package/src/services/autoDream/consolidationLock.ts +140 -0
- package/src/services/autoDream/consolidationPrompt.ts +65 -0
- package/src/services/awaySummary.ts +74 -0
- package/src/services/claudeAiLimits.ts +515 -0
- package/src/services/claudeAiLimitsHook.ts +23 -0
- package/src/services/compact/apiMicrocompact.ts +153 -0
- package/src/services/compact/autoCompact.ts +351 -0
- package/src/services/compact/compact.ts +1705 -0
- package/src/services/compact/compactWarningHook.ts +16 -0
- package/src/services/compact/compactWarningState.ts +18 -0
- package/src/services/compact/grouping.ts +63 -0
- package/src/services/compact/microCompact.ts +530 -0
- package/src/services/compact/postCompactCleanup.ts +77 -0
- package/src/services/compact/prompt.ts +374 -0
- package/src/services/compact/sessionMemoryCompact.ts +630 -0
- package/src/services/compact/timeBasedMCConfig.ts +43 -0
- package/src/services/diagnosticTracking.ts +397 -0
- package/src/services/extractMemories/extractMemories.ts +615 -0
- package/src/services/extractMemories/prompts.ts +154 -0
- package/src/services/internalLogging.ts +90 -0
- package/src/services/lsp/LSPClient.ts +447 -0
- package/src/services/lsp/LSPDiagnosticRegistry.ts +386 -0
- package/src/services/lsp/LSPServerInstance.ts +511 -0
- package/src/services/lsp/LSPServerManager.ts +420 -0
- package/src/services/lsp/config.ts +79 -0
- package/src/services/lsp/manager.ts +289 -0
- package/src/services/lsp/passiveFeedback.ts +328 -0
- package/src/services/mcp/InProcessTransport.ts +63 -0
- package/src/services/mcp/MCPConnectionManager.tsx +73 -0
- package/src/services/mcp/SdkControlTransport.ts +136 -0
- package/src/services/mcp/auth.ts +2465 -0
- package/src/services/mcp/channelAllowlist.ts +76 -0
- package/src/services/mcp/channelNotification.ts +316 -0
- package/src/services/mcp/channelPermissions.ts +240 -0
- package/src/services/mcp/claudeai.ts +164 -0
- package/src/services/mcp/client.ts +3348 -0
- package/src/services/mcp/config.ts +1578 -0
- package/src/services/mcp/elicitationHandler.ts +313 -0
- package/src/services/mcp/envExpansion.ts +38 -0
- package/src/services/mcp/headersHelper.ts +138 -0
- package/src/services/mcp/mcpStringUtils.ts +106 -0
- package/src/services/mcp/normalization.ts +23 -0
- package/src/services/mcp/oauthPort.ts +78 -0
- package/src/services/mcp/officialRegistry.ts +72 -0
- package/src/services/mcp/types.ts +258 -0
- package/src/services/mcp/useManageMCPConnections.ts +1141 -0
- package/src/services/mcp/utils.ts +575 -0
- package/src/services/mcp/vscodeSdkMcp.ts +112 -0
- package/src/services/mcp/xaa.ts +511 -0
- package/src/services/mcp/xaaIdpLogin.ts +487 -0
- package/src/services/mcpServerApproval.tsx +41 -0
- package/src/services/mockRateLimits.ts +882 -0
- package/src/services/notifier.ts +156 -0
- package/src/services/oauth/auth-code-listener.ts +211 -0
- package/src/services/oauth/client.ts +566 -0
- package/src/services/oauth/crypto.ts +23 -0
- package/src/services/oauth/getOauthProfile.ts +53 -0
- package/src/services/oauth/index.ts +198 -0
- package/src/services/plugins/PluginInstallationManager.ts +184 -0
- package/src/services/plugins/pluginCliCommands.ts +344 -0
- package/src/services/plugins/pluginOperations.ts +1088 -0
- package/src/services/policyLimits/index.ts +664 -0
- package/src/services/policyLimits/types.ts +27 -0
- package/src/services/preventSleep.ts +165 -0
- package/src/services/rateLimitMessages.ts +344 -0
- package/src/services/rateLimitMocking.ts +144 -0
- package/src/services/remoteManagedSettings/index.ts +639 -0
- package/src/services/remoteManagedSettings/securityCheck.tsx +74 -0
- package/src/services/remoteManagedSettings/syncCache.ts +112 -0
- package/src/services/remoteManagedSettings/syncCacheState.ts +96 -0
- package/src/services/remoteManagedSettings/types.ts +31 -0
- package/src/services/settingsSync/index.ts +581 -0
- package/src/services/settingsSync/types.ts +67 -0
- package/src/services/teamMemorySync/index.ts +1256 -0
- package/src/services/teamMemorySync/secretScanner.ts +324 -0
- package/src/services/teamMemorySync/teamMemSecretGuard.ts +44 -0
- package/src/services/teamMemorySync/types.ts +156 -0
- package/src/services/teamMemorySync/watcher.ts +387 -0
- package/src/services/tips/tipHistory.ts +17 -0
- package/src/services/tips/tipRegistry.ts +686 -0
- package/src/services/tips/tipScheduler.ts +58 -0
- package/src/services/tokenEstimation.ts +495 -0
- package/src/services/toolUseSummary/toolUseSummaryGenerator.ts +112 -0
- package/src/services/tools/StreamingToolExecutor.ts +530 -0
- package/src/services/tools/toolExecution.ts +1745 -0
- package/src/services/tools/toolHooks.ts +650 -0
- package/src/services/tools/toolOrchestration.ts +188 -0
- package/src/services/vcr.ts +406 -0
- package/src/services/voice.ts +525 -0
- package/src/services/voiceKeyterms.ts +106 -0
- package/src/services/voiceStreamSTT.ts +544 -0
- package/src/setup.ts +477 -0
- package/src/skills/bundled/batch.ts +124 -0
- package/src/skills/bundled/claudeApi.ts +196 -0
- package/src/skills/bundled/claudeApiContent.ts +75 -0
- package/src/skills/bundled/claudeInChrome.ts +34 -0
- package/src/skills/bundled/debug.ts +103 -0
- package/src/skills/bundled/index.ts +79 -0
- package/src/skills/bundled/keybindings.ts +339 -0
- package/src/skills/bundled/loop.ts +92 -0
- package/src/skills/bundled/loremIpsum.ts +282 -0
- package/src/skills/bundled/remember.ts +82 -0
- package/src/skills/bundled/scheduleRemoteAgents.ts +447 -0
- package/src/skills/bundled/simplify.ts +69 -0
- package/src/skills/bundled/skillify.ts +197 -0
- package/src/skills/bundled/stuck.ts +79 -0
- package/src/skills/bundled/updateConfig.ts +475 -0
- package/src/skills/bundled/verify.ts +30 -0
- package/src/skills/bundled/verifyContent.ts +13 -0
- package/src/skills/bundledSkills.ts +220 -0
- package/src/skills/loadSkillsDir.ts +1086 -0
- package/src/skills/mcpSkillBuilders.ts +44 -0
- package/src/state/AppState.tsx +200 -0
- package/src/state/AppStateStore.ts +569 -0
- package/src/state/onChangeAppState.ts +171 -0
- package/src/state/selectors.ts +76 -0
- package/src/state/store.ts +34 -0
- package/src/state/teammateViewHelpers.ts +141 -0
- package/src/tasks/DreamTask/DreamTask.ts +157 -0
- package/src/tasks/InProcessTeammateTask/InProcessTeammateTask.tsx +126 -0
- package/src/tasks/InProcessTeammateTask/types.ts +121 -0
- package/src/tasks/LocalAgentTask/LocalAgentTask.tsx +683 -0
- package/src/tasks/LocalMainSessionTask.ts +479 -0
- package/src/tasks/LocalShellTask/LocalShellTask.tsx +523 -0
- package/src/tasks/LocalShellTask/guards.ts +41 -0
- package/src/tasks/LocalShellTask/killShellTasks.ts +76 -0
- package/src/tasks/RemoteAgentTask/RemoteAgentTask.tsx +856 -0
- package/src/tasks/pillLabel.ts +82 -0
- package/src/tasks/stopTask.ts +100 -0
- package/src/tasks/types.ts +46 -0
- package/src/tasks.ts +39 -0
- package/src/tools/AgentTool/AgentTool.tsx +1398 -0
- package/src/tools/AgentTool/UI.tsx +872 -0
- package/src/tools/AgentTool/agentColorManager.ts +66 -0
- package/src/tools/AgentTool/agentDisplay.ts +104 -0
- package/src/tools/AgentTool/agentMemory.ts +177 -0
- package/src/tools/AgentTool/agentMemorySnapshot.ts +197 -0
- package/src/tools/AgentTool/agentToolUtils.ts +686 -0
- package/src/tools/AgentTool/built-in/claudeCodeGuideAgent.ts +205 -0
- package/src/tools/AgentTool/built-in/exploreAgent.ts +83 -0
- package/src/tools/AgentTool/built-in/generalPurposeAgent.ts +34 -0
- package/src/tools/AgentTool/built-in/planAgent.ts +92 -0
- package/src/tools/AgentTool/built-in/statuslineSetup.ts +144 -0
- package/src/tools/AgentTool/built-in/verificationAgent.ts +152 -0
- package/src/tools/AgentTool/builtInAgents.ts +72 -0
- package/src/tools/AgentTool/constants.ts +12 -0
- package/src/tools/AgentTool/forkSubagent.ts +210 -0
- package/src/tools/AgentTool/loadAgentsDir.ts +755 -0
- package/src/tools/AgentTool/prompt.ts +287 -0
- package/src/tools/AgentTool/resumeAgent.ts +265 -0
- package/src/tools/AgentTool/runAgent.ts +973 -0
- package/src/tools/AskUserQuestionTool/AskUserQuestionTool.tsx +266 -0
- package/src/tools/AskUserQuestionTool/prompt.ts +44 -0
- package/src/tools/BashTool/BashTool.tsx +1144 -0
- package/src/tools/BashTool/BashToolResultMessage.tsx +191 -0
- package/src/tools/BashTool/UI.tsx +185 -0
- package/src/tools/BashTool/bashCommandHelpers.ts +265 -0
- package/src/tools/BashTool/bashPermissions.ts +2621 -0
- package/src/tools/BashTool/bashSecurity.ts +2592 -0
- package/src/tools/BashTool/commandSemantics.ts +140 -0
- package/src/tools/BashTool/commentLabel.ts +13 -0
- package/src/tools/BashTool/destructiveCommandWarning.ts +102 -0
- package/src/tools/BashTool/modeValidation.ts +115 -0
- package/src/tools/BashTool/pathValidation.ts +1303 -0
- package/src/tools/BashTool/prompt.ts +369 -0
- package/src/tools/BashTool/readOnlyValidation.ts +1990 -0
- package/src/tools/BashTool/sedEditParser.ts +322 -0
- package/src/tools/BashTool/sedValidation.ts +684 -0
- package/src/tools/BashTool/shouldUseSandbox.ts +153 -0
- package/src/tools/BashTool/toolName.ts +2 -0
- package/src/tools/BashTool/utils.ts +223 -0
- package/src/tools/BriefTool/BriefTool.ts +204 -0
- package/src/tools/BriefTool/UI.tsx +101 -0
- package/src/tools/BriefTool/attachments.ts +110 -0
- package/src/tools/BriefTool/prompt.ts +22 -0
- package/src/tools/BriefTool/upload.ts +174 -0
- package/src/tools/ConfigTool/ConfigTool.ts +467 -0
- package/src/tools/ConfigTool/UI.tsx +38 -0
- package/src/tools/ConfigTool/constants.ts +1 -0
- package/src/tools/ConfigTool/prompt.ts +93 -0
- package/src/tools/ConfigTool/supportedSettings.ts +211 -0
- package/src/tools/EnterPlanModeTool/EnterPlanModeTool.ts +126 -0
- package/src/tools/EnterPlanModeTool/UI.tsx +33 -0
- package/src/tools/EnterPlanModeTool/constants.ts +1 -0
- package/src/tools/EnterPlanModeTool/prompt.ts +170 -0
- package/src/tools/EnterWorktreeTool/EnterWorktreeTool.ts +127 -0
- package/src/tools/EnterWorktreeTool/UI.tsx +20 -0
- package/src/tools/EnterWorktreeTool/constants.ts +1 -0
- package/src/tools/EnterWorktreeTool/prompt.ts +30 -0
- package/src/tools/ExitPlanModeTool/ExitPlanModeV2Tool.ts +493 -0
- package/src/tools/ExitPlanModeTool/UI.tsx +82 -0
- package/src/tools/ExitPlanModeTool/constants.ts +2 -0
- package/src/tools/ExitPlanModeTool/prompt.ts +29 -0
- package/src/tools/ExitWorktreeTool/ExitWorktreeTool.ts +329 -0
- package/src/tools/ExitWorktreeTool/UI.tsx +25 -0
- package/src/tools/ExitWorktreeTool/constants.ts +1 -0
- package/src/tools/ExitWorktreeTool/prompt.ts +32 -0
- package/src/tools/FileEditTool/FileEditTool.ts +625 -0
- package/src/tools/FileEditTool/UI.tsx +289 -0
- package/src/tools/FileEditTool/constants.ts +11 -0
- package/src/tools/FileEditTool/prompt.ts +28 -0
- package/src/tools/FileEditTool/types.ts +85 -0
- package/src/tools/FileEditTool/utils.ts +775 -0
- package/src/tools/FileReadTool/FileReadTool.ts +1183 -0
- package/src/tools/FileReadTool/UI.tsx +185 -0
- package/src/tools/FileReadTool/imageProcessor.ts +94 -0
- package/src/tools/FileReadTool/limits.ts +92 -0
- package/src/tools/FileReadTool/prompt.ts +49 -0
- package/src/tools/FileWriteTool/FileWriteTool.ts +434 -0
- package/src/tools/FileWriteTool/UI.tsx +405 -0
- package/src/tools/FileWriteTool/prompt.ts +18 -0
- package/src/tools/GlobTool/GlobTool.ts +198 -0
- package/src/tools/GlobTool/UI.tsx +63 -0
- package/src/tools/GlobTool/prompt.ts +7 -0
- package/src/tools/GrepTool/GrepTool.ts +577 -0
- package/src/tools/GrepTool/UI.tsx +201 -0
- package/src/tools/GrepTool/prompt.ts +18 -0
- package/src/tools/LSPTool/LSPTool.ts +860 -0
- package/src/tools/LSPTool/UI.tsx +228 -0
- package/src/tools/LSPTool/formatters.ts +592 -0
- package/src/tools/LSPTool/prompt.ts +21 -0
- package/src/tools/LSPTool/schemas.ts +215 -0
- package/src/tools/LSPTool/symbolContext.ts +90 -0
- package/src/tools/ListMcpResourcesTool/ListMcpResourcesTool.ts +123 -0
- package/src/tools/ListMcpResourcesTool/UI.tsx +29 -0
- package/src/tools/ListMcpResourcesTool/prompt.ts +20 -0
- package/src/tools/MCPTool/MCPTool.ts +77 -0
- package/src/tools/MCPTool/UI.tsx +403 -0
- package/src/tools/MCPTool/classifyForCollapse.ts +604 -0
- package/src/tools/MCPTool/prompt.ts +3 -0
- package/src/tools/McpAuthTool/McpAuthTool.ts +215 -0
- package/src/tools/NotebookEditTool/NotebookEditTool.ts +490 -0
- package/src/tools/NotebookEditTool/UI.tsx +93 -0
- package/src/tools/NotebookEditTool/constants.ts +2 -0
- package/src/tools/NotebookEditTool/prompt.ts +3 -0
- package/src/tools/PowerShellTool/PowerShellTool.tsx +1001 -0
- package/src/tools/PowerShellTool/UI.tsx +131 -0
- package/src/tools/PowerShellTool/clmTypes.ts +211 -0
- package/src/tools/PowerShellTool/commandSemantics.ts +142 -0
- package/src/tools/PowerShellTool/commonParameters.ts +30 -0
- package/src/tools/PowerShellTool/destructiveCommandWarning.ts +109 -0
- package/src/tools/PowerShellTool/gitSafety.ts +176 -0
- package/src/tools/PowerShellTool/modeValidation.ts +404 -0
- package/src/tools/PowerShellTool/pathValidation.ts +2049 -0
- package/src/tools/PowerShellTool/powershellPermissions.ts +1648 -0
- package/src/tools/PowerShellTool/powershellSecurity.ts +1090 -0
- package/src/tools/PowerShellTool/prompt.ts +145 -0
- package/src/tools/PowerShellTool/readOnlyValidation.ts +1823 -0
- package/src/tools/PowerShellTool/toolName.ts +2 -0
- package/src/tools/REPLTool/constants.ts +46 -0
- package/src/tools/REPLTool/primitiveTools.ts +39 -0
- package/src/tools/ReadMcpResourceTool/ReadMcpResourceTool.ts +158 -0
- package/src/tools/ReadMcpResourceTool/UI.tsx +37 -0
- package/src/tools/ReadMcpResourceTool/prompt.ts +16 -0
- package/src/tools/RemoteTriggerTool/RemoteTriggerTool.ts +161 -0
- package/src/tools/RemoteTriggerTool/UI.tsx +17 -0
- package/src/tools/RemoteTriggerTool/prompt.ts +15 -0
- package/src/tools/ScheduleCronTool/CronCreateTool.ts +157 -0
- package/src/tools/ScheduleCronTool/CronDeleteTool.ts +95 -0
- package/src/tools/ScheduleCronTool/CronListTool.ts +97 -0
- package/src/tools/ScheduleCronTool/UI.tsx +60 -0
- package/src/tools/ScheduleCronTool/prompt.ts +135 -0
- package/src/tools/SendMessageTool/SendMessageTool.ts +917 -0
- package/src/tools/SendMessageTool/UI.tsx +31 -0
- package/src/tools/SendMessageTool/constants.ts +1 -0
- package/src/tools/SendMessageTool/prompt.ts +49 -0
- package/src/tools/SkillTool/SkillTool.ts +1108 -0
- package/src/tools/SkillTool/UI.tsx +128 -0
- package/src/tools/SkillTool/constants.ts +1 -0
- package/src/tools/SkillTool/prompt.ts +241 -0
- package/src/tools/SleepTool/prompt.ts +17 -0
- package/src/tools/SyntheticOutputTool/SyntheticOutputTool.ts +163 -0
- package/src/tools/TaskCreateTool/TaskCreateTool.ts +138 -0
- package/src/tools/TaskCreateTool/constants.ts +1 -0
- package/src/tools/TaskCreateTool/prompt.ts +56 -0
- package/src/tools/TaskGetTool/TaskGetTool.ts +128 -0
- package/src/tools/TaskGetTool/constants.ts +1 -0
- package/src/tools/TaskGetTool/prompt.ts +24 -0
- package/src/tools/TaskListTool/TaskListTool.ts +116 -0
- package/src/tools/TaskListTool/constants.ts +1 -0
- package/src/tools/TaskListTool/prompt.ts +49 -0
- package/src/tools/TaskOutputTool/TaskOutputTool.tsx +584 -0
- package/src/tools/TaskOutputTool/constants.ts +1 -0
- package/src/tools/TaskStopTool/TaskStopTool.ts +131 -0
- package/src/tools/TaskStopTool/UI.tsx +41 -0
- package/src/tools/TaskStopTool/prompt.ts +8 -0
- package/src/tools/TaskUpdateTool/TaskUpdateTool.ts +406 -0
- package/src/tools/TaskUpdateTool/constants.ts +1 -0
- package/src/tools/TaskUpdateTool/prompt.ts +77 -0
- package/src/tools/TeamCreateTool/TeamCreateTool.ts +240 -0
- package/src/tools/TeamCreateTool/UI.tsx +6 -0
- package/src/tools/TeamCreateTool/constants.ts +1 -0
- package/src/tools/TeamCreateTool/prompt.ts +113 -0
- package/src/tools/TeamDeleteTool/TeamDeleteTool.ts +139 -0
- package/src/tools/TeamDeleteTool/UI.tsx +20 -0
- package/src/tools/TeamDeleteTool/constants.ts +1 -0
- package/src/tools/TeamDeleteTool/prompt.ts +16 -0
- package/src/tools/TodoWriteTool/TodoWriteTool.ts +115 -0
- package/src/tools/TodoWriteTool/constants.ts +1 -0
- package/src/tools/TodoWriteTool/prompt.ts +184 -0
- package/src/tools/ToolSearchTool/ToolSearchTool.ts +471 -0
- package/src/tools/ToolSearchTool/constants.ts +1 -0
- package/src/tools/ToolSearchTool/prompt.ts +121 -0
- package/src/tools/TungstenTool/TungstenTool.js +2 -0
- package/src/tools/TungstenTool/TungstenTool.ts +1 -0
- package/src/tools/WebFetchTool/UI.tsx +72 -0
- package/src/tools/WebFetchTool/WebFetchTool.ts +318 -0
- package/src/tools/WebFetchTool/preapproved.ts +166 -0
- package/src/tools/WebFetchTool/prompt.ts +46 -0
- package/src/tools/WebFetchTool/utils.ts +530 -0
- package/src/tools/WebSearchTool/UI.tsx +101 -0
- package/src/tools/WebSearchTool/WebSearchTool.ts +435 -0
- package/src/tools/WebSearchTool/prompt.ts +34 -0
- package/src/tools/shared/gitOperationTracking.ts +277 -0
- package/src/tools/shared/spawnMultiAgent.ts +1093 -0
- package/src/tools/testing/TestingPermissionTool.tsx +74 -0
- package/src/tools/utils.ts +40 -0
- package/src/tools.ts +389 -0
- package/src/types/command.ts +216 -0
- package/src/types/connectorText.js +5 -0
- package/src/types/connectorText.ts +1 -0
- package/src/types/generated/events_mono/claude_code/v1/claude_code_internal_event.ts +865 -0
- package/src/types/generated/events_mono/common/v1/auth.ts +100 -0
- package/src/types/generated/events_mono/growthbook/v1/growthbook_experiment_event.ts +223 -0
- package/src/types/generated/google/protobuf/timestamp.ts +187 -0
- package/src/types/hooks.ts +290 -0
- package/src/types/ids.ts +44 -0
- package/src/types/logs.ts +330 -0
- package/src/types/permissions.ts +441 -0
- package/src/types/plugin.ts +363 -0
- package/src/types/textInputTypes.ts +387 -0
- package/src/upstreamproxy/relay.ts +455 -0
- package/src/upstreamproxy/upstreamproxy.ts +285 -0
- package/src/utils/CircularBuffer.ts +84 -0
- package/src/utils/Cursor.ts +1530 -0
- package/src/utils/QueryGuard.ts +121 -0
- package/src/utils/Shell.ts +474 -0
- package/src/utils/ShellCommand.ts +465 -0
- package/src/utils/abortController.ts +99 -0
- package/src/utils/activityManager.ts +164 -0
- package/src/utils/advisor.ts +145 -0
- package/src/utils/agentContext.ts +178 -0
- package/src/utils/agentId.ts +99 -0
- package/src/utils/agentSwarmsEnabled.ts +44 -0
- package/src/utils/agenticSessionSearch.ts +307 -0
- package/src/utils/analyzeContext.ts +1382 -0
- package/src/utils/ansiToPng.ts +334 -0
- package/src/utils/ansiToSvg.ts +272 -0
- package/src/utils/api.ts +718 -0
- package/src/utils/apiPreconnect.ts +72 -0
- package/src/utils/appleTerminalBackup.ts +124 -0
- package/src/utils/argumentSubstitution.ts +145 -0
- package/src/utils/array.ts +13 -0
- package/src/utils/asciicast.ts +239 -0
- package/src/utils/attachments.ts +3997 -0
- package/src/utils/attribution.ts +393 -0
- package/src/utils/auth.ts +2007 -0
- package/src/utils/authFileDescriptor.ts +196 -0
- package/src/utils/authPortable.ts +19 -0
- package/src/utils/autoModeDenials.ts +26 -0
- package/src/utils/autoRunIssue.tsx +122 -0
- package/src/utils/autoUpdater.ts +562 -0
- package/src/utils/aws.ts +74 -0
- package/src/utils/awsAuthStatusManager.ts +81 -0
- package/src/utils/background/remote/preconditions.ts +235 -0
- package/src/utils/background/remote/remoteSession.ts +98 -0
- package/src/utils/backgroundHousekeeping.ts +94 -0
- package/src/utils/bash/ParsedCommand.ts +318 -0
- package/src/utils/bash/ShellSnapshot.ts +582 -0
- package/src/utils/bash/ast.ts +2679 -0
- package/src/utils/bash/bashParser.ts +4436 -0
- package/src/utils/bash/bashPipeCommand.ts +294 -0
- package/src/utils/bash/commands.ts +1339 -0
- package/src/utils/bash/heredoc.ts +733 -0
- package/src/utils/bash/parser.ts +230 -0
- package/src/utils/bash/prefix.ts +204 -0
- package/src/utils/bash/registry.ts +53 -0
- package/src/utils/bash/shellCompletion.ts +259 -0
- package/src/utils/bash/shellPrefix.ts +28 -0
- package/src/utils/bash/shellQuote.ts +304 -0
- package/src/utils/bash/shellQuoting.ts +128 -0
- package/src/utils/bash/specs/alias.ts +14 -0
- package/src/utils/bash/specs/index.ts +18 -0
- package/src/utils/bash/specs/nohup.ts +13 -0
- package/src/utils/bash/specs/pyright.ts +91 -0
- package/src/utils/bash/specs/sleep.ts +13 -0
- package/src/utils/bash/specs/srun.ts +31 -0
- package/src/utils/bash/specs/time.ts +13 -0
- package/src/utils/bash/specs/timeout.ts +20 -0
- package/src/utils/bash/treeSitterAnalysis.ts +506 -0
- package/src/utils/betas.ts +438 -0
- package/src/utils/billing.ts +78 -0
- package/src/utils/binaryCheck.ts +53 -0
- package/src/utils/browser.ts +68 -0
- package/src/utils/bufferedWriter.ts +100 -0
- package/src/utils/bundledMode.ts +22 -0
- package/src/utils/caCerts.ts +115 -0
- package/src/utils/caCertsConfig.ts +88 -0
- package/src/utils/cachePaths.ts +38 -0
- package/src/utils/classifierApprovals.ts +88 -0
- package/src/utils/classifierApprovalsHook.ts +17 -0
- package/src/utils/claudeCodeHints.ts +193 -0
- package/src/utils/claudeDesktop.ts +152 -0
- package/src/utils/claudeInChrome/chromeNativeHost.ts +527 -0
- package/src/utils/claudeInChrome/common.ts +540 -0
- package/src/utils/claudeInChrome/mcpServer.ts +293 -0
- package/src/utils/claudeInChrome/prompt.ts +83 -0
- package/src/utils/claudeInChrome/setup.ts +400 -0
- package/src/utils/claudeInChrome/setupPortable.ts +233 -0
- package/src/utils/claudeInChrome/toolRendering.tsx +262 -0
- package/src/utils/claudemd.ts +1479 -0
- package/src/utils/cleanup.ts +602 -0
- package/src/utils/cleanupRegistry.ts +25 -0
- package/src/utils/cliArgs.ts +60 -0
- package/src/utils/cliHighlight.ts +54 -0
- package/src/utils/codeIndexing.ts +206 -0
- package/src/utils/collapseBackgroundBashNotifications.ts +84 -0
- package/src/utils/collapseHookSummaries.ts +59 -0
- package/src/utils/collapseReadSearch.ts +1109 -0
- package/src/utils/collapseTeammateShutdowns.ts +55 -0
- package/src/utils/combinedAbortSignal.ts +47 -0
- package/src/utils/commandLifecycle.ts +21 -0
- package/src/utils/commitAttribution.ts +961 -0
- package/src/utils/completionCache.ts +166 -0
- package/src/utils/computerUse/appNames.ts +196 -0
- package/src/utils/computerUse/cleanup.ts +86 -0
- package/src/utils/computerUse/common.ts +61 -0
- package/src/utils/computerUse/computerUseLock.ts +215 -0
- package/src/utils/computerUse/drainRunLoop.ts +79 -0
- package/src/utils/computerUse/escHotkey.ts +54 -0
- package/src/utils/computerUse/executor.ts +658 -0
- package/src/utils/computerUse/gates.ts +72 -0
- package/src/utils/computerUse/hostAdapter.ts +69 -0
- package/src/utils/computerUse/inputLoader.ts +30 -0
- package/src/utils/computerUse/mcpServer.ts +106 -0
- package/src/utils/computerUse/setup.ts +53 -0
- package/src/utils/computerUse/swiftLoader.ts +23 -0
- package/src/utils/computerUse/toolRendering.tsx +125 -0
- package/src/utils/computerUse/wrapper.tsx +336 -0
- package/src/utils/concurrentSessions.ts +204 -0
- package/src/utils/config.ts +1817 -0
- package/src/utils/configConstants.ts +21 -0
- package/src/utils/contentArray.ts +51 -0
- package/src/utils/context.ts +221 -0
- package/src/utils/contextAnalysis.ts +272 -0
- package/src/utils/contextSuggestions.ts +235 -0
- package/src/utils/controlMessageCompat.ts +32 -0
- package/src/utils/conversationRecovery.ts +597 -0
- package/src/utils/cron.ts +308 -0
- package/src/utils/cronJitterConfig.ts +75 -0
- package/src/utils/cronScheduler.ts +565 -0
- package/src/utils/cronTasks.ts +458 -0
- package/src/utils/cronTasksLock.ts +195 -0
- package/src/utils/crossProjectResume.ts +75 -0
- package/src/utils/crypto.ts +13 -0
- package/src/utils/cwd.ts +32 -0
- package/src/utils/debug.ts +268 -0
- package/src/utils/debugFilter.ts +157 -0
- package/src/utils/deepLink/banner.ts +123 -0
- package/src/utils/deepLink/parseDeepLink.ts +170 -0
- package/src/utils/deepLink/protocolHandler.ts +136 -0
- package/src/utils/deepLink/registerProtocol.ts +348 -0
- package/src/utils/deepLink/terminalLauncher.ts +557 -0
- package/src/utils/deepLink/terminalPreference.ts +54 -0
- package/src/utils/desktopDeepLink.ts +236 -0
- package/src/utils/detectRepository.ts +178 -0
- package/src/utils/diagLogs.ts +94 -0
- package/src/utils/diff.ts +177 -0
- package/src/utils/directMemberMessage.ts +69 -0
- package/src/utils/displayTags.ts +51 -0
- package/src/utils/doctorContextWarnings.ts +265 -0
- package/src/utils/doctorDiagnostic.ts +625 -0
- package/src/utils/dxt/helpers.ts +88 -0
- package/src/utils/dxt/zip.ts +226 -0
- package/src/utils/earlyInput.ts +191 -0
- package/src/utils/editor.ts +183 -0
- package/src/utils/effort.ts +329 -0
- package/src/utils/embeddedTools.ts +29 -0
- package/src/utils/env.ts +347 -0
- package/src/utils/envDynamic.ts +151 -0
- package/src/utils/envUtils.ts +183 -0
- package/src/utils/envValidation.ts +38 -0
- package/src/utils/errorLogSink.ts +235 -0
- package/src/utils/errors.ts +238 -0
- package/src/utils/exampleCommands.ts +184 -0
- package/src/utils/execFileNoThrow.ts +150 -0
- package/src/utils/execFileNoThrowPortable.ts +89 -0
- package/src/utils/execSyncWrapper.ts +38 -0
- package/src/utils/exportRenderer.tsx +98 -0
- package/src/utils/extraUsage.ts +23 -0
- package/src/utils/fastMode.ts +532 -0
- package/src/utils/file.ts +584 -0
- package/src/utils/fileHistory.ts +1115 -0
- package/src/utils/fileOperationAnalytics.ts +71 -0
- package/src/utils/filePersistence/filePersistence.ts +287 -0
- package/src/utils/filePersistence/outputsScanner.ts +126 -0
- package/src/utils/fileRead.ts +102 -0
- package/src/utils/fileReadCache.ts +96 -0
- package/src/utils/fileStateCache.ts +142 -0
- package/src/utils/findExecutable.ts +17 -0
- package/src/utils/fingerprint.ts +76 -0
- package/src/utils/forkedAgent.ts +689 -0
- package/src/utils/format.ts +308 -0
- package/src/utils/formatBriefTimestamp.ts +81 -0
- package/src/utils/fpsTracker.ts +47 -0
- package/src/utils/frontmatterParser.ts +370 -0
- package/src/utils/fsOperations.ts +770 -0
- package/src/utils/fullscreen.ts +202 -0
- package/src/utils/generatedFiles.ts +136 -0
- package/src/utils/generators.ts +88 -0
- package/src/utils/genericProcessUtils.ts +184 -0
- package/src/utils/getWorktreePaths.ts +70 -0
- package/src/utils/getWorktreePathsPortable.ts +27 -0
- package/src/utils/ghPrStatus.ts +106 -0
- package/src/utils/git/gitConfigParser.ts +277 -0
- package/src/utils/git/gitFilesystem.ts +699 -0
- package/src/utils/git/gitignore.ts +99 -0
- package/src/utils/git.ts +926 -0
- package/src/utils/gitDiff.ts +532 -0
- package/src/utils/gitSettings.ts +18 -0
- package/src/utils/github/ghAuthStatus.ts +29 -0
- package/src/utils/githubRepoPathMapping.ts +162 -0
- package/src/utils/glob.ts +130 -0
- package/src/utils/gracefulShutdown.ts +529 -0
- package/src/utils/groupToolUses.ts +182 -0
- package/src/utils/handlePromptSubmit.ts +610 -0
- package/src/utils/hash.ts +46 -0
- package/src/utils/headlessProfiler.ts +178 -0
- package/src/utils/heapDumpService.ts +303 -0
- package/src/utils/heatmap.ts +198 -0
- package/src/utils/highlightMatch.tsx +28 -0
- package/src/utils/hooks/AsyncHookRegistry.ts +309 -0
- package/src/utils/hooks/apiQueryHookHelper.ts +141 -0
- package/src/utils/hooks/execAgentHook.ts +339 -0
- package/src/utils/hooks/execHttpHook.ts +242 -0
- package/src/utils/hooks/execPromptHook.ts +211 -0
- package/src/utils/hooks/fileChangedWatcher.ts +191 -0
- package/src/utils/hooks/hookEvents.ts +192 -0
- package/src/utils/hooks/hookHelpers.ts +83 -0
- package/src/utils/hooks/hooksConfigManager.ts +400 -0
- package/src/utils/hooks/hooksConfigSnapshot.ts +133 -0
- package/src/utils/hooks/hooksSettings.ts +271 -0
- package/src/utils/hooks/postSamplingHooks.ts +70 -0
- package/src/utils/hooks/registerFrontmatterHooks.ts +67 -0
- package/src/utils/hooks/registerSkillHooks.ts +64 -0
- package/src/utils/hooks/sessionHooks.ts +447 -0
- package/src/utils/hooks/skillImprovement.ts +267 -0
- package/src/utils/hooks/ssrfGuard.ts +294 -0
- package/src/utils/hooks.ts +5022 -0
- package/src/utils/horizontalScroll.ts +137 -0
- package/src/utils/http.ts +136 -0
- package/src/utils/hyperlink.ts +39 -0
- package/src/utils/iTermBackup.ts +73 -0
- package/src/utils/ide.ts +1494 -0
- package/src/utils/idePathConversion.ts +90 -0
- package/src/utils/idleTimeout.ts +53 -0
- package/src/utils/imagePaste.ts +416 -0
- package/src/utils/imageResizer.ts +880 -0
- package/src/utils/imageStore.ts +167 -0
- package/src/utils/imageValidation.ts +104 -0
- package/src/utils/immediateCommand.ts +15 -0
- package/src/utils/inProcessTeammateHelpers.ts +102 -0
- package/src/utils/ink.ts +26 -0
- package/src/utils/intl.ts +94 -0
- package/src/utils/jetbrains.ts +191 -0
- package/src/utils/json.ts +277 -0
- package/src/utils/jsonRead.ts +16 -0
- package/src/utils/keyboardShortcuts.ts +14 -0
- package/src/utils/lazySchema.ts +8 -0
- package/src/utils/listSessionsImpl.ts +454 -0
- package/src/utils/localInstaller.ts +162 -0
- package/src/utils/lockfile.ts +43 -0
- package/src/utils/log.ts +362 -0
- package/src/utils/logoV2Utils.ts +350 -0
- package/src/utils/mailbox.ts +73 -0
- package/src/utils/managedEnv.ts +199 -0
- package/src/utils/managedEnvConstants.ts +191 -0
- package/src/utils/markdown.ts +381 -0
- package/src/utils/markdownConfigLoader.ts +600 -0
- package/src/utils/mcp/dateTimeParser.ts +121 -0
- package/src/utils/mcp/elicitationValidation.ts +336 -0
- package/src/utils/mcpInstructionsDelta.ts +130 -0
- package/src/utils/mcpOutputStorage.ts +189 -0
- package/src/utils/mcpValidation.ts +208 -0
- package/src/utils/mcpWebSocketTransport.ts +200 -0
- package/src/utils/memoize.ts +269 -0
- package/src/utils/memory/types.ts +12 -0
- package/src/utils/memory/versions.ts +8 -0
- package/src/utils/memoryFileDetection.ts +289 -0
- package/src/utils/messagePredicates.ts +8 -0
- package/src/utils/messageQueueManager.ts +547 -0
- package/src/utils/messages/mappers.ts +290 -0
- package/src/utils/messages/systemInit.ts +96 -0
- package/src/utils/messages.ts +5512 -0
- package/src/utils/model/agent.ts +157 -0
- package/src/utils/model/aliases.ts +25 -0
- package/src/utils/model/antModels.ts +64 -0
- package/src/utils/model/bedrock.ts +265 -0
- package/src/utils/model/check1mAccess.ts +72 -0
- package/src/utils/model/configs.ts +118 -0
- package/src/utils/model/contextWindowUpgradeCheck.ts +47 -0
- package/src/utils/model/deprecation.ts +101 -0
- package/src/utils/model/model.ts +634 -0
- package/src/utils/model/modelAllowlist.ts +170 -0
- package/src/utils/model/modelCapabilities.ts +118 -0
- package/src/utils/model/modelOptions.ts +540 -0
- package/src/utils/model/modelStrings.ts +166 -0
- package/src/utils/model/modelSupportOverrides.ts +50 -0
- package/src/utils/model/providers.ts +46 -0
- package/src/utils/model/validateModel.ts +159 -0
- package/src/utils/modelCost.ts +235 -0
- package/src/utils/modifiers.ts +36 -0
- package/src/utils/mtls.ts +179 -0
- package/src/utils/nativeInstaller/download.ts +523 -0
- package/src/utils/nativeInstaller/index.ts +18 -0
- package/src/utils/nativeInstaller/installer.ts +1708 -0
- package/src/utils/nativeInstaller/packageManagers.ts +336 -0
- package/src/utils/nativeInstaller/pidLock.ts +433 -0
- package/src/utils/notebook.ts +224 -0
- package/src/utils/objectGroupBy.ts +18 -0
- package/src/utils/pasteStore.ts +104 -0
- package/src/utils/path.ts +155 -0
- package/src/utils/pdf.ts +300 -0
- package/src/utils/pdfUtils.ts +70 -0
- package/src/utils/peerAddress.ts +21 -0
- package/src/utils/permissions/PermissionMode.ts +141 -0
- package/src/utils/permissions/PermissionPromptToolResultSchema.ts +127 -0
- package/src/utils/permissions/PermissionResult.ts +35 -0
- package/src/utils/permissions/PermissionRule.ts +40 -0
- package/src/utils/permissions/PermissionUpdate.ts +389 -0
- package/src/utils/permissions/PermissionUpdateSchema.ts +78 -0
- package/src/utils/permissions/autoModeState.ts +39 -0
- package/src/utils/permissions/bashClassifier.ts +61 -0
- package/src/utils/permissions/bypassPermissionsKillswitch.ts +155 -0
- package/src/utils/permissions/classifierDecision.ts +98 -0
- package/src/utils/permissions/classifierShared.ts +39 -0
- package/src/utils/permissions/dangerousPatterns.ts +80 -0
- package/src/utils/permissions/denialTracking.ts +45 -0
- package/src/utils/permissions/filesystem.ts +1777 -0
- package/src/utils/permissions/getNextPermissionMode.ts +101 -0
- package/src/utils/permissions/pathValidation.ts +485 -0
- package/src/utils/permissions/permissionExplainer.ts +250 -0
- package/src/utils/permissions/permissionRuleParser.ts +198 -0
- package/src/utils/permissions/permissionSetup.ts +1532 -0
- package/src/utils/permissions/permissions.ts +1486 -0
- package/src/utils/permissions/permissionsLoader.ts +296 -0
- package/src/utils/permissions/shadowedRuleDetection.ts +234 -0
- package/src/utils/permissions/shellRuleMatching.ts +228 -0
- package/src/utils/permissions/yoloClassifier.ts +1495 -0
- package/src/utils/planModeV2.ts +95 -0
- package/src/utils/plans.ts +397 -0
- package/src/utils/platform.ts +150 -0
- package/src/utils/plugins/addDirPluginSettings.ts +71 -0
- package/src/utils/plugins/cacheUtils.ts +196 -0
- package/src/utils/plugins/dependencyResolver.ts +305 -0
- package/src/utils/plugins/fetchTelemetry.ts +135 -0
- package/src/utils/plugins/gitAvailability.ts +69 -0
- package/src/utils/plugins/headlessPluginInstall.ts +174 -0
- package/src/utils/plugins/hintRecommendation.ts +164 -0
- package/src/utils/plugins/installCounts.ts +292 -0
- package/src/utils/plugins/installedPluginsManager.ts +1268 -0
- package/src/utils/plugins/loadPluginAgents.ts +348 -0
- package/src/utils/plugins/loadPluginCommands.ts +946 -0
- package/src/utils/plugins/loadPluginHooks.ts +287 -0
- package/src/utils/plugins/loadPluginOutputStyles.ts +178 -0
- package/src/utils/plugins/lspPluginIntegration.ts +387 -0
- package/src/utils/plugins/lspRecommendation.ts +374 -0
- package/src/utils/plugins/managedPlugins.ts +27 -0
- package/src/utils/plugins/marketplaceHelpers.ts +592 -0
- package/src/utils/plugins/marketplaceManager.ts +2643 -0
- package/src/utils/plugins/mcpPluginIntegration.ts +634 -0
- package/src/utils/plugins/mcpbHandler.ts +968 -0
- package/src/utils/plugins/officialMarketplace.ts +25 -0
- package/src/utils/plugins/officialMarketplaceGcs.ts +216 -0
- package/src/utils/plugins/officialMarketplaceStartupCheck.ts +439 -0
- package/src/utils/plugins/orphanedPluginFilter.ts +114 -0
- package/src/utils/plugins/parseMarketplaceInput.ts +162 -0
- package/src/utils/plugins/performStartupChecks.tsx +70 -0
- package/src/utils/plugins/pluginAutoupdate.ts +284 -0
- package/src/utils/plugins/pluginBlocklist.ts +127 -0
- package/src/utils/plugins/pluginDirectories.ts +178 -0
- package/src/utils/plugins/pluginFlagging.ts +208 -0
- package/src/utils/plugins/pluginIdentifier.ts +123 -0
- package/src/utils/plugins/pluginInstallationHelpers.ts +595 -0
- package/src/utils/plugins/pluginLoader.ts +3302 -0
- package/src/utils/plugins/pluginOptionsStorage.ts +400 -0
- package/src/utils/plugins/pluginPolicy.ts +20 -0
- package/src/utils/plugins/pluginStartupCheck.ts +341 -0
- package/src/utils/plugins/pluginVersioning.ts +157 -0
- package/src/utils/plugins/reconciler.ts +265 -0
- package/src/utils/plugins/refresh.ts +215 -0
- package/src/utils/plugins/schemas.ts +1681 -0
- package/src/utils/plugins/validatePlugin.ts +903 -0
- package/src/utils/plugins/walkPluginMarkdown.ts +69 -0
- package/src/utils/plugins/zipCache.ts +406 -0
- package/src/utils/plugins/zipCacheAdapters.ts +164 -0
- package/src/utils/powershell/dangerousCmdlets.ts +185 -0
- package/src/utils/powershell/parser.ts +1804 -0
- package/src/utils/powershell/staticPrefix.ts +316 -0
- package/src/utils/preflightChecks.tsx +151 -0
- package/src/utils/privacyLevel.ts +55 -0
- package/src/utils/process.ts +68 -0
- package/src/utils/processUserInput/processBashCommand.tsx +140 -0
- package/src/utils/processUserInput/processSlashCommand.tsx +922 -0
- package/src/utils/processUserInput/processTextPrompt.ts +100 -0
- package/src/utils/processUserInput/processUserInput.ts +605 -0
- package/src/utils/profilerBase.ts +46 -0
- package/src/utils/promptCategory.ts +49 -0
- package/src/utils/promptEditor.ts +188 -0
- package/src/utils/promptShellExecution.ts +183 -0
- package/src/utils/proxy.ts +426 -0
- package/src/utils/queryContext.ts +179 -0
- package/src/utils/queryHelpers.ts +552 -0
- package/src/utils/queryProfiler.ts +301 -0
- package/src/utils/queueProcessor.ts +95 -0
- package/src/utils/readEditContext.ts +227 -0
- package/src/utils/readFileInRange.ts +383 -0
- package/src/utils/releaseNotes.ts +360 -0
- package/src/utils/renderOptions.ts +77 -0
- package/src/utils/ripgrep.ts +679 -0
- package/src/utils/sandbox/sandbox-adapter.ts +985 -0
- package/src/utils/sandbox/sandbox-ui-utils.ts +12 -0
- package/src/utils/sanitization.ts +91 -0
- package/src/utils/screenshotClipboard.ts +121 -0
- package/src/utils/sdkEventQueue.ts +134 -0
- package/src/utils/secureStorage/fallbackStorage.ts +70 -0
- package/src/utils/secureStorage/index.ts +17 -0
- package/src/utils/secureStorage/keychainPrefetch.ts +116 -0
- package/src/utils/secureStorage/macOsKeychainHelpers.ts +111 -0
- package/src/utils/secureStorage/macOsKeychainStorage.ts +231 -0
- package/src/utils/secureStorage/plainTextStorage.ts +84 -0
- package/src/utils/semanticBoolean.ts +29 -0
- package/src/utils/semanticNumber.ts +36 -0
- package/src/utils/semver.ts +59 -0
- package/src/utils/sequential.ts +56 -0
- package/src/utils/sessionActivity.ts +133 -0
- package/src/utils/sessionEnvVars.ts +22 -0
- package/src/utils/sessionEnvironment.ts +166 -0
- package/src/utils/sessionFileAccessHooks.ts +250 -0
- package/src/utils/sessionIngressAuth.ts +140 -0
- package/src/utils/sessionRestore.ts +551 -0
- package/src/utils/sessionStart.ts +232 -0
- package/src/utils/sessionState.ts +150 -0
- package/src/utils/sessionStorage.ts +5105 -0
- package/src/utils/sessionStoragePortable.ts +793 -0
- package/src/utils/sessionTitle.ts +129 -0
- package/src/utils/sessionUrl.ts +64 -0
- package/src/utils/set.ts +53 -0
- package/src/utils/settings/allErrors.ts +32 -0
- package/src/utils/settings/applySettingsChange.ts +92 -0
- package/src/utils/settings/changeDetector.ts +488 -0
- package/src/utils/settings/constants.ts +202 -0
- package/src/utils/settings/internalWrites.ts +37 -0
- package/src/utils/settings/managedPath.ts +34 -0
- package/src/utils/settings/mdm/constants.ts +81 -0
- package/src/utils/settings/mdm/rawRead.ts +130 -0
- package/src/utils/settings/mdm/settings.ts +316 -0
- package/src/utils/settings/permissionValidation.ts +262 -0
- package/src/utils/settings/pluginOnlyPolicy.ts +60 -0
- package/src/utils/settings/schemaOutput.ts +8 -0
- package/src/utils/settings/settings.ts +1015 -0
- package/src/utils/settings/settingsCache.ts +80 -0
- package/src/utils/settings/toolValidationConfig.ts +103 -0
- package/src/utils/settings/types.ts +1148 -0
- package/src/utils/settings/validateEditTool.ts +45 -0
- package/src/utils/settings/validation.ts +265 -0
- package/src/utils/settings/validationTips.ts +164 -0
- package/src/utils/shell/bashProvider.ts +255 -0
- package/src/utils/shell/outputLimits.ts +14 -0
- package/src/utils/shell/powershellDetection.ts +107 -0
- package/src/utils/shell/powershellProvider.ts +123 -0
- package/src/utils/shell/prefix.ts +367 -0
- package/src/utils/shell/readOnlyCommandValidation.ts +1893 -0
- package/src/utils/shell/resolveDefaultShell.ts +14 -0
- package/src/utils/shell/shellProvider.ts +33 -0
- package/src/utils/shell/shellToolUtils.ts +22 -0
- package/src/utils/shell/specPrefix.ts +241 -0
- package/src/utils/shellConfig.ts +167 -0
- package/src/utils/sideQuery.ts +222 -0
- package/src/utils/sideQuestion.ts +155 -0
- package/src/utils/signal.ts +43 -0
- package/src/utils/sinks.ts +16 -0
- package/src/utils/skills/skillChangeDetector.ts +311 -0
- package/src/utils/slashCommandParsing.ts +60 -0
- package/src/utils/sleep.ts +84 -0
- package/src/utils/sliceAnsi.ts +91 -0
- package/src/utils/slowOperations.ts +286 -0
- package/src/utils/standaloneAgent.ts +23 -0
- package/src/utils/startupProfiler.ts +194 -0
- package/src/utils/staticRender.tsx +116 -0
- package/src/utils/stats.ts +1061 -0
- package/src/utils/statsCache.ts +434 -0
- package/src/utils/status.tsx +362 -0
- package/src/utils/statusNoticeDefinitions.tsx +198 -0
- package/src/utils/statusNoticeHelpers.ts +20 -0
- package/src/utils/stream.ts +76 -0
- package/src/utils/streamJsonStdoutGuard.ts +123 -0
- package/src/utils/streamlinedTransform.ts +201 -0
- package/src/utils/stringUtils.ts +235 -0
- package/src/utils/subprocessEnv.ts +99 -0
- package/src/utils/suggestions/commandSuggestions.ts +567 -0
- package/src/utils/suggestions/directoryCompletion.ts +263 -0
- package/src/utils/suggestions/shellHistoryCompletion.ts +119 -0
- package/src/utils/suggestions/skillUsageTracking.ts +55 -0
- package/src/utils/suggestions/slackChannelSuggestions.ts +209 -0
- package/src/utils/swarm/It2SetupPrompt.tsx +380 -0
- package/src/utils/swarm/backends/ITermBackend.ts +370 -0
- package/src/utils/swarm/backends/InProcessBackend.ts +339 -0
- package/src/utils/swarm/backends/PaneBackendExecutor.ts +354 -0
- package/src/utils/swarm/backends/TmuxBackend.ts +764 -0
- package/src/utils/swarm/backends/detection.ts +128 -0
- package/src/utils/swarm/backends/it2Setup.ts +245 -0
- package/src/utils/swarm/backends/registry.ts +464 -0
- package/src/utils/swarm/backends/teammateModeSnapshot.ts +87 -0
- package/src/utils/swarm/backends/types.ts +311 -0
- package/src/utils/swarm/constants.ts +33 -0
- package/src/utils/swarm/inProcessRunner.ts +1552 -0
- package/src/utils/swarm/leaderPermissionBridge.ts +54 -0
- package/src/utils/swarm/permissionSync.ts +928 -0
- package/src/utils/swarm/reconnection.ts +119 -0
- package/src/utils/swarm/spawnInProcess.ts +328 -0
- package/src/utils/swarm/spawnUtils.ts +146 -0
- package/src/utils/swarm/teamHelpers.ts +683 -0
- package/src/utils/swarm/teammateInit.ts +129 -0
- package/src/utils/swarm/teammateLayoutManager.ts +107 -0
- package/src/utils/swarm/teammateModel.ts +10 -0
- package/src/utils/swarm/teammatePromptAddendum.ts +18 -0
- package/src/utils/systemDirectories.ts +74 -0
- package/src/utils/systemPrompt.ts +123 -0
- package/src/utils/systemPromptType.ts +14 -0
- package/src/utils/systemTheme.ts +119 -0
- package/src/utils/taggedId.ts +54 -0
- package/src/utils/task/TaskOutput.ts +390 -0
- package/src/utils/task/diskOutput.ts +451 -0
- package/src/utils/task/framework.ts +308 -0
- package/src/utils/task/outputFormatting.ts +38 -0
- package/src/utils/task/sdkProgress.ts +36 -0
- package/src/utils/tasks.ts +862 -0
- package/src/utils/teamDiscovery.ts +81 -0
- package/src/utils/teamMemoryOps.ts +88 -0
- package/src/utils/teammate.ts +292 -0
- package/src/utils/teammateContext.ts +96 -0
- package/src/utils/teammateMailbox.ts +1183 -0
- package/src/utils/telemetry/betaSessionTracing.ts +491 -0
- package/src/utils/telemetry/bigqueryExporter.ts +252 -0
- package/src/utils/telemetry/events.ts +75 -0
- package/src/utils/telemetry/instrumentation.ts +825 -0
- package/src/utils/telemetry/logger.ts +26 -0
- package/src/utils/telemetry/perfettoTracing.ts +1120 -0
- package/src/utils/telemetry/pluginTelemetry.ts +289 -0
- package/src/utils/telemetry/sessionTracing.ts +927 -0
- package/src/utils/telemetry/skillLoadedEvent.ts +39 -0
- package/src/utils/telemetryAttributes.ts +71 -0
- package/src/utils/teleport/api.ts +466 -0
- package/src/utils/teleport/environmentSelection.ts +77 -0
- package/src/utils/teleport/environments.ts +120 -0
- package/src/utils/teleport/gitBundle.ts +292 -0
- package/src/utils/teleport.tsx +1226 -0
- package/src/utils/tempfile.ts +31 -0
- package/src/utils/terminal.ts +131 -0
- package/src/utils/terminalPanel.ts +191 -0
- package/src/utils/textHighlighting.ts +166 -0
- package/src/utils/theme.ts +639 -0
- package/src/utils/thinking.ts +162 -0
- package/src/utils/timeouts.ts +39 -0
- package/src/utils/tmuxSocket.ts +427 -0
- package/src/utils/todo/types.ts +18 -0
- package/src/utils/tokenBudget.ts +73 -0
- package/src/utils/tokens.ts +261 -0
- package/src/utils/toolErrors.ts +132 -0
- package/src/utils/toolPool.ts +79 -0
- package/src/utils/toolResultStorage.ts +1040 -0
- package/src/utils/toolSchemaCache.ts +26 -0
- package/src/utils/toolSearch.ts +756 -0
- package/src/utils/transcriptSearch.ts +202 -0
- package/src/utils/treeify.ts +170 -0
- package/src/utils/truncate.ts +179 -0
- package/src/utils/ultraplan/ccrSession.ts +349 -0
- package/src/utils/ultraplan/keyword.ts +127 -0
- package/src/utils/ultraplan/prompt.txt +1 -0
- package/src/utils/unaryLogging.ts +39 -0
- package/src/utils/undercover.ts +89 -0
- package/src/utils/user.ts +194 -0
- package/src/utils/userAgent.ts +10 -0
- package/src/utils/userPromptKeywords.ts +27 -0
- package/src/utils/uuid.ts +27 -0
- package/src/utils/warningHandler.ts +121 -0
- package/src/utils/which.ts +82 -0
- package/src/utils/windowsPaths.ts +173 -0
- package/src/utils/withResolvers.ts +13 -0
- package/src/utils/words.ts +800 -0
- package/src/utils/workloadContext.ts +57 -0
- package/src/utils/worktree.ts +1519 -0
- package/src/utils/worktreeModeEnabled.ts +11 -0
- package/src/utils/xdg.ts +65 -0
- package/src/utils/xml.ts +16 -0
- package/src/utils/yaml.ts +15 -0
- package/src/utils/zodToJsonSchema.ts +23 -0
- package/src/vim/motions.ts +82 -0
- package/src/vim/operators.ts +556 -0
- package/src/vim/textObjects.ts +186 -0
- package/src/vim/transitions.ts +490 -0
- package/src/vim/types.ts +199 -0
- package/src/voice/voiceModeEnabled.ts +54 -0
- package/start.js +1 -0
|
@@ -0,0 +1,1708 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native Installer Implementation
|
|
3
|
+
*
|
|
4
|
+
* This module implements the file-based native installer system described in
|
|
5
|
+
* docs/native-installer.md. It provides:
|
|
6
|
+
* - Directory structure management with symlinks
|
|
7
|
+
* - Version installation and activation
|
|
8
|
+
* - Multi-process safety with locking
|
|
9
|
+
* - Simple fallback mechanism using modification time
|
|
10
|
+
* - Support for both JS and native builds
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { constants as fsConstants, type Stats } from 'fs'
|
|
14
|
+
import {
|
|
15
|
+
access,
|
|
16
|
+
chmod,
|
|
17
|
+
copyFile,
|
|
18
|
+
lstat,
|
|
19
|
+
mkdir,
|
|
20
|
+
readdir,
|
|
21
|
+
readlink,
|
|
22
|
+
realpath,
|
|
23
|
+
rename,
|
|
24
|
+
rm,
|
|
25
|
+
rmdir,
|
|
26
|
+
stat,
|
|
27
|
+
symlink,
|
|
28
|
+
unlink,
|
|
29
|
+
writeFile,
|
|
30
|
+
} from 'fs/promises'
|
|
31
|
+
import { homedir } from 'os'
|
|
32
|
+
import { basename, delimiter, dirname, join, resolve } from 'path'
|
|
33
|
+
import {
|
|
34
|
+
type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
|
35
|
+
logEvent,
|
|
36
|
+
} from 'src/services/analytics/index.js'
|
|
37
|
+
import { getMaxVersion, shouldSkipVersion } from '../autoUpdater.js'
|
|
38
|
+
import { registerCleanup } from '../cleanupRegistry.js'
|
|
39
|
+
import { getGlobalConfig, saveGlobalConfig } from '../config.js'
|
|
40
|
+
import { logForDebugging } from '../debug.js'
|
|
41
|
+
import { getCurrentInstallationType } from '../doctorDiagnostic.js'
|
|
42
|
+
import { env } from '../env.js'
|
|
43
|
+
import { envDynamic } from '../envDynamic.js'
|
|
44
|
+
import { isEnvTruthy } from '../envUtils.js'
|
|
45
|
+
import { errorMessage, getErrnoCode, isENOENT, toError } from '../errors.js'
|
|
46
|
+
import { execFileNoThrowWithCwd } from '../execFileNoThrow.js'
|
|
47
|
+
import { getShellType } from '../localInstaller.js'
|
|
48
|
+
import * as lockfile from '../lockfile.js'
|
|
49
|
+
import { logError } from '../log.js'
|
|
50
|
+
import { gt, gte } from '../semver.js'
|
|
51
|
+
import {
|
|
52
|
+
filterClaudeAliases,
|
|
53
|
+
getShellConfigPaths,
|
|
54
|
+
readFileLines,
|
|
55
|
+
writeFileLines,
|
|
56
|
+
} from '../shellConfig.js'
|
|
57
|
+
import { sleep } from '../sleep.js'
|
|
58
|
+
import {
|
|
59
|
+
getUserBinDir,
|
|
60
|
+
getXDGCacheHome,
|
|
61
|
+
getXDGDataHome,
|
|
62
|
+
getXDGStateHome,
|
|
63
|
+
} from '../xdg.js'
|
|
64
|
+
import { downloadVersion, getLatestVersion } from './download.js'
|
|
65
|
+
import {
|
|
66
|
+
acquireProcessLifetimeLock,
|
|
67
|
+
cleanupStaleLocks,
|
|
68
|
+
isLockActive,
|
|
69
|
+
isPidBasedLockingEnabled,
|
|
70
|
+
readLockContent,
|
|
71
|
+
withLock,
|
|
72
|
+
} from './pidLock.js'
|
|
73
|
+
|
|
74
|
+
export const VERSION_RETENTION_COUNT = 2
|
|
75
|
+
|
|
76
|
+
// 7 days in milliseconds - used for mtime-based lock stale timeout.
|
|
77
|
+
// This is long enough to survive laptop sleep durations while still
|
|
78
|
+
// allowing cleanup of abandoned locks from crashed processes within a reasonable time.
|
|
79
|
+
const LOCK_STALE_MS = 7 * 24 * 60 * 60 * 1000
|
|
80
|
+
|
|
81
|
+
export type SetupMessage = {
|
|
82
|
+
message: string
|
|
83
|
+
userActionRequired: boolean
|
|
84
|
+
type: 'path' | 'alias' | 'info' | 'error'
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function getPlatform(): string {
|
|
88
|
+
// Use env.platform which already handles platform detection and defaults to 'linux'
|
|
89
|
+
const os = env.platform
|
|
90
|
+
|
|
91
|
+
const arch =
|
|
92
|
+
process.arch === 'x64' ? 'x64' : process.arch === 'arm64' ? 'arm64' : null
|
|
93
|
+
|
|
94
|
+
if (!arch) {
|
|
95
|
+
const error = new Error(`Unsupported architecture: ${process.arch}`)
|
|
96
|
+
logForDebugging(
|
|
97
|
+
`Native installer does not support architecture: ${process.arch}`,
|
|
98
|
+
{ level: 'error' },
|
|
99
|
+
)
|
|
100
|
+
throw error
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Check for musl on Linux and adjust platform accordingly
|
|
104
|
+
if (os === 'linux' && envDynamic.isMuslEnvironment()) {
|
|
105
|
+
return `linux-${arch}-musl`
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return `${os}-${arch}`
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function getBinaryName(platform: string): string {
|
|
112
|
+
return platform.startsWith('win32') ? 'claude.exe' : 'claude'
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function getBaseDirectories() {
|
|
116
|
+
const platform = getPlatform()
|
|
117
|
+
const executableName = getBinaryName(platform)
|
|
118
|
+
|
|
119
|
+
return {
|
|
120
|
+
// Data directories (permanent storage)
|
|
121
|
+
versions: join(getXDGDataHome(), 'claude', 'versions'),
|
|
122
|
+
|
|
123
|
+
// Cache directories (can be deleted)
|
|
124
|
+
staging: join(getXDGCacheHome(), 'claude', 'staging'),
|
|
125
|
+
|
|
126
|
+
// State directories
|
|
127
|
+
locks: join(getXDGStateHome(), 'claude', 'locks'),
|
|
128
|
+
|
|
129
|
+
// User bin
|
|
130
|
+
executable: join(getUserBinDir(), executableName),
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
async function isPossibleClaudeBinary(filePath: string): Promise<boolean> {
|
|
135
|
+
try {
|
|
136
|
+
const stats = await stat(filePath)
|
|
137
|
+
// before download, the version lock file (located at the same filePath) will be size 0
|
|
138
|
+
// also, we allow small sizes because we want to treat small wrapper scripts as valid
|
|
139
|
+
if (!stats.isFile() || stats.size === 0) {
|
|
140
|
+
return false
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Check if file is executable. Note: On Windows, this relies on file extensions
|
|
144
|
+
// (.exe, .bat, .cmd) and ACL permissions rather than Unix permission bits,
|
|
145
|
+
// so it may not work perfectly for all executable files on Windows.
|
|
146
|
+
await access(filePath, fsConstants.X_OK)
|
|
147
|
+
return true
|
|
148
|
+
} catch {
|
|
149
|
+
return false
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
async function getVersionPaths(version: string) {
|
|
154
|
+
const dirs = getBaseDirectories()
|
|
155
|
+
|
|
156
|
+
// Create directories, but not the executable path (which is a file)
|
|
157
|
+
const dirsToCreate = [dirs.versions, dirs.staging, dirs.locks]
|
|
158
|
+
await Promise.all(dirsToCreate.map(dir => mkdir(dir, { recursive: true })))
|
|
159
|
+
|
|
160
|
+
// Ensure parent directory of executable exists
|
|
161
|
+
const executableParentDir = dirname(dirs.executable)
|
|
162
|
+
await mkdir(executableParentDir, { recursive: true })
|
|
163
|
+
|
|
164
|
+
const installPath = join(dirs.versions, version)
|
|
165
|
+
|
|
166
|
+
// Create an empty file if it doesn't exist
|
|
167
|
+
try {
|
|
168
|
+
await stat(installPath)
|
|
169
|
+
} catch {
|
|
170
|
+
await writeFile(installPath, '', { encoding: 'utf8' })
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return {
|
|
174
|
+
stagingPath: join(dirs.staging, version),
|
|
175
|
+
installPath,
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Execute a callback while holding a lock on a version file
|
|
180
|
+
// Returns false if the file is already locked, true if callback executed
|
|
181
|
+
async function tryWithVersionLock(
|
|
182
|
+
versionFilePath: string,
|
|
183
|
+
callback: () => void | Promise<void>,
|
|
184
|
+
retries = 0,
|
|
185
|
+
): Promise<boolean> {
|
|
186
|
+
const dirs = getBaseDirectories()
|
|
187
|
+
|
|
188
|
+
const lockfilePath = getLockFilePathFromVersionPath(dirs, versionFilePath)
|
|
189
|
+
|
|
190
|
+
// Ensure the locks directory exists
|
|
191
|
+
await mkdir(dirs.locks, { recursive: true })
|
|
192
|
+
|
|
193
|
+
if (isPidBasedLockingEnabled()) {
|
|
194
|
+
// Use PID-based locking with optional retries
|
|
195
|
+
let attempts = 0
|
|
196
|
+
const maxAttempts = retries + 1
|
|
197
|
+
const minTimeout = retries > 0 ? 1000 : 100
|
|
198
|
+
const maxTimeout = retries > 0 ? 5000 : 500
|
|
199
|
+
|
|
200
|
+
while (attempts < maxAttempts) {
|
|
201
|
+
const success = await withLock(
|
|
202
|
+
versionFilePath,
|
|
203
|
+
lockfilePath,
|
|
204
|
+
async () => {
|
|
205
|
+
try {
|
|
206
|
+
await callback()
|
|
207
|
+
} catch (error) {
|
|
208
|
+
logError(error)
|
|
209
|
+
throw error
|
|
210
|
+
}
|
|
211
|
+
},
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
if (success) {
|
|
215
|
+
logEvent('tengu_version_lock_acquired', {
|
|
216
|
+
is_pid_based: true,
|
|
217
|
+
is_lifetime_lock: false,
|
|
218
|
+
attempts: attempts + 1,
|
|
219
|
+
})
|
|
220
|
+
return true
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
attempts++
|
|
224
|
+
if (attempts < maxAttempts) {
|
|
225
|
+
// Wait before retrying with exponential backoff
|
|
226
|
+
const timeout = Math.min(
|
|
227
|
+
minTimeout * Math.pow(2, attempts - 1),
|
|
228
|
+
maxTimeout,
|
|
229
|
+
)
|
|
230
|
+
await sleep(timeout)
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
logEvent('tengu_version_lock_failed', {
|
|
235
|
+
is_pid_based: true,
|
|
236
|
+
is_lifetime_lock: false,
|
|
237
|
+
attempts: maxAttempts,
|
|
238
|
+
})
|
|
239
|
+
logLockAcquisitionError(
|
|
240
|
+
versionFilePath,
|
|
241
|
+
new Error('Lock held by another process'),
|
|
242
|
+
)
|
|
243
|
+
return false
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Use mtime-based locking (proper-lockfile) with 30-day stale timeout
|
|
247
|
+
let release: (() => Promise<void>) | null = null
|
|
248
|
+
try {
|
|
249
|
+
// Lock acquisition phase - catch lock errors and return false
|
|
250
|
+
// Use 30 days for stale to match lockCurrentVersion() - this ensures we never
|
|
251
|
+
// consider a running process's lock as stale during normal usage (including
|
|
252
|
+
// laptop sleep). 30 days allows eventual cleanup of abandoned locks from
|
|
253
|
+
// crashed processes while being long enough for any realistic session.
|
|
254
|
+
try {
|
|
255
|
+
release = await lockfile.lock(versionFilePath, {
|
|
256
|
+
stale: LOCK_STALE_MS,
|
|
257
|
+
retries: {
|
|
258
|
+
retries,
|
|
259
|
+
minTimeout: retries > 0 ? 1000 : 100,
|
|
260
|
+
maxTimeout: retries > 0 ? 5000 : 500,
|
|
261
|
+
},
|
|
262
|
+
lockfilePath,
|
|
263
|
+
// Handle lock compromise gracefully to prevent unhandled rejections
|
|
264
|
+
// This can happen if another process deletes the lock directory while we hold it
|
|
265
|
+
onCompromised: (err: Error) => {
|
|
266
|
+
logForDebugging(
|
|
267
|
+
`NON-FATAL: Version lock was compromised during operation: ${err.message}`,
|
|
268
|
+
{ level: 'info' },
|
|
269
|
+
)
|
|
270
|
+
},
|
|
271
|
+
})
|
|
272
|
+
} catch (lockError) {
|
|
273
|
+
logEvent('tengu_version_lock_failed', {
|
|
274
|
+
is_pid_based: false,
|
|
275
|
+
is_lifetime_lock: false,
|
|
276
|
+
})
|
|
277
|
+
logLockAcquisitionError(versionFilePath, lockError)
|
|
278
|
+
return false
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// Operation phase - log errors but let them propagate
|
|
282
|
+
try {
|
|
283
|
+
await callback()
|
|
284
|
+
logEvent('tengu_version_lock_acquired', {
|
|
285
|
+
is_pid_based: false,
|
|
286
|
+
is_lifetime_lock: false,
|
|
287
|
+
})
|
|
288
|
+
return true
|
|
289
|
+
} catch (error) {
|
|
290
|
+
logError(error)
|
|
291
|
+
throw error
|
|
292
|
+
}
|
|
293
|
+
} finally {
|
|
294
|
+
if (release) {
|
|
295
|
+
await release()
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
async function atomicMoveToInstallPath(
|
|
301
|
+
stagedBinaryPath: string,
|
|
302
|
+
installPath: string,
|
|
303
|
+
) {
|
|
304
|
+
// Create installation directory if it doesn't exist
|
|
305
|
+
await mkdir(dirname(installPath), { recursive: true })
|
|
306
|
+
|
|
307
|
+
// Move from staging to final location atomically
|
|
308
|
+
const tempInstallPath = `${installPath}.tmp.${process.pid}.${Date.now()}`
|
|
309
|
+
|
|
310
|
+
try {
|
|
311
|
+
// Copy to temp next to install path, then rename. A direct rename from staging
|
|
312
|
+
// would fail with EXDEV if staging and install are on different filesystems.
|
|
313
|
+
await copyFile(stagedBinaryPath, tempInstallPath)
|
|
314
|
+
await chmod(tempInstallPath, 0o755)
|
|
315
|
+
await rename(tempInstallPath, installPath)
|
|
316
|
+
logForDebugging(`Atomically installed binary to ${installPath}`)
|
|
317
|
+
} catch (error) {
|
|
318
|
+
// Clean up temp file if it exists
|
|
319
|
+
try {
|
|
320
|
+
await unlink(tempInstallPath)
|
|
321
|
+
} catch {
|
|
322
|
+
// Ignore cleanup errors
|
|
323
|
+
}
|
|
324
|
+
throw error
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
async function installVersionFromPackage(
|
|
329
|
+
stagingPath: string,
|
|
330
|
+
installPath: string,
|
|
331
|
+
) {
|
|
332
|
+
try {
|
|
333
|
+
// Extract binary from npm package structure in staging
|
|
334
|
+
const nodeModulesDir = join(stagingPath, 'node_modules', '@anthropic-ai')
|
|
335
|
+
const entries = await readdir(nodeModulesDir)
|
|
336
|
+
const nativePackage = entries.find((entry: string) =>
|
|
337
|
+
entry.startsWith('claude-cli-native-'),
|
|
338
|
+
)
|
|
339
|
+
|
|
340
|
+
if (!nativePackage) {
|
|
341
|
+
logEvent('tengu_native_install_package_failure', {
|
|
342
|
+
stage_find_package: true,
|
|
343
|
+
error_package_not_found: true,
|
|
344
|
+
})
|
|
345
|
+
const error = new Error('Could not find platform-specific native package')
|
|
346
|
+
throw error
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
const stagedBinaryPath = join(nodeModulesDir, nativePackage, 'cli')
|
|
350
|
+
|
|
351
|
+
try {
|
|
352
|
+
await stat(stagedBinaryPath)
|
|
353
|
+
} catch {
|
|
354
|
+
logEvent('tengu_native_install_package_failure', {
|
|
355
|
+
stage_binary_exists: true,
|
|
356
|
+
error_binary_not_found: true,
|
|
357
|
+
})
|
|
358
|
+
const error = new Error('Native binary not found in staged package')
|
|
359
|
+
throw error
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
await atomicMoveToInstallPath(stagedBinaryPath, installPath)
|
|
363
|
+
|
|
364
|
+
// Clean up staging directory
|
|
365
|
+
await rm(stagingPath, { recursive: true, force: true })
|
|
366
|
+
|
|
367
|
+
logEvent('tengu_native_install_package_success', {})
|
|
368
|
+
} catch (error) {
|
|
369
|
+
// Log if not already logged above
|
|
370
|
+
const msg = errorMessage(error)
|
|
371
|
+
if (
|
|
372
|
+
!msg.includes('Could not find platform-specific') &&
|
|
373
|
+
!msg.includes('Native binary not found')
|
|
374
|
+
) {
|
|
375
|
+
logEvent('tengu_native_install_package_failure', {
|
|
376
|
+
stage_atomic_move: true,
|
|
377
|
+
error_move_failed: true,
|
|
378
|
+
})
|
|
379
|
+
}
|
|
380
|
+
logError(toError(error))
|
|
381
|
+
throw error
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
async function installVersionFromBinary(
|
|
386
|
+
stagingPath: string,
|
|
387
|
+
installPath: string,
|
|
388
|
+
) {
|
|
389
|
+
try {
|
|
390
|
+
// For direct binary downloads (GCS, generic bucket), the binary is directly in staging
|
|
391
|
+
const platform = getPlatform()
|
|
392
|
+
const binaryName = getBinaryName(platform)
|
|
393
|
+
const stagedBinaryPath = join(stagingPath, binaryName)
|
|
394
|
+
|
|
395
|
+
try {
|
|
396
|
+
await stat(stagedBinaryPath)
|
|
397
|
+
} catch {
|
|
398
|
+
logEvent('tengu_native_install_binary_failure', {
|
|
399
|
+
stage_binary_exists: true,
|
|
400
|
+
error_binary_not_found: true,
|
|
401
|
+
})
|
|
402
|
+
const error = new Error('Staged binary not found')
|
|
403
|
+
throw error
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
await atomicMoveToInstallPath(stagedBinaryPath, installPath)
|
|
407
|
+
|
|
408
|
+
// Clean up staging directory
|
|
409
|
+
await rm(stagingPath, { recursive: true, force: true })
|
|
410
|
+
|
|
411
|
+
logEvent('tengu_native_install_binary_success', {})
|
|
412
|
+
} catch (error) {
|
|
413
|
+
if (!errorMessage(error).includes('Staged binary not found')) {
|
|
414
|
+
logEvent('tengu_native_install_binary_failure', {
|
|
415
|
+
stage_atomic_move: true,
|
|
416
|
+
error_move_failed: true,
|
|
417
|
+
})
|
|
418
|
+
}
|
|
419
|
+
logError(toError(error))
|
|
420
|
+
throw error
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
async function installVersion(
|
|
425
|
+
stagingPath: string,
|
|
426
|
+
installPath: string,
|
|
427
|
+
downloadType: 'npm' | 'binary',
|
|
428
|
+
) {
|
|
429
|
+
// Use the explicit download type instead of guessing
|
|
430
|
+
if (downloadType === 'npm') {
|
|
431
|
+
await installVersionFromPackage(stagingPath, installPath)
|
|
432
|
+
} else {
|
|
433
|
+
await installVersionFromBinary(stagingPath, installPath)
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* Performs the core update operation: download (if needed), install, and update symlink.
|
|
439
|
+
* Returns whether a new install was performed (vs just updating symlink).
|
|
440
|
+
*/
|
|
441
|
+
async function performVersionUpdate(
|
|
442
|
+
version: string,
|
|
443
|
+
forceReinstall: boolean,
|
|
444
|
+
): Promise<boolean> {
|
|
445
|
+
const { stagingPath: baseStagingPath, installPath } =
|
|
446
|
+
await getVersionPaths(version)
|
|
447
|
+
const { executable: executablePath } = getBaseDirectories()
|
|
448
|
+
|
|
449
|
+
// For lockless updates, use a unique staging path to avoid conflicts between concurrent downloads
|
|
450
|
+
const stagingPath = isEnvTruthy(process.env.ENABLE_LOCKLESS_UPDATES)
|
|
451
|
+
? `${baseStagingPath}.${process.pid}.${Date.now()}`
|
|
452
|
+
: baseStagingPath
|
|
453
|
+
|
|
454
|
+
// Only download if not already installed (or if force reinstall)
|
|
455
|
+
const needsInstall = !(await versionIsAvailable(version)) || forceReinstall
|
|
456
|
+
if (needsInstall) {
|
|
457
|
+
logForDebugging(
|
|
458
|
+
forceReinstall
|
|
459
|
+
? `Force reinstalling native installer version ${version}`
|
|
460
|
+
: `Downloading native installer version ${version}`,
|
|
461
|
+
)
|
|
462
|
+
const downloadType = await downloadVersion(version, stagingPath)
|
|
463
|
+
await installVersion(stagingPath, installPath, downloadType)
|
|
464
|
+
} else {
|
|
465
|
+
logForDebugging(`Version ${version} already installed, updating symlink`)
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
// Create direct symlink from ~/.local/bin/claude to the version binary
|
|
469
|
+
await removeDirectoryIfEmpty(executablePath)
|
|
470
|
+
await updateSymlink(executablePath, installPath)
|
|
471
|
+
|
|
472
|
+
// Verify the executable was actually created/updated
|
|
473
|
+
if (!(await isPossibleClaudeBinary(executablePath))) {
|
|
474
|
+
let installPathExists = false
|
|
475
|
+
try {
|
|
476
|
+
await stat(installPath)
|
|
477
|
+
installPathExists = true
|
|
478
|
+
} catch {
|
|
479
|
+
// installPath doesn't exist
|
|
480
|
+
}
|
|
481
|
+
throw new Error(
|
|
482
|
+
`Failed to create executable at ${executablePath}. ` +
|
|
483
|
+
`Source file exists: ${installPathExists}. ` +
|
|
484
|
+
`Check write permissions to ${executablePath}.`,
|
|
485
|
+
)
|
|
486
|
+
}
|
|
487
|
+
return needsInstall
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
async function versionIsAvailable(version: string): Promise<boolean> {
|
|
491
|
+
const { installPath } = await getVersionPaths(version)
|
|
492
|
+
return isPossibleClaudeBinary(installPath)
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
async function updateLatest(
|
|
496
|
+
channelOrVersion: string,
|
|
497
|
+
forceReinstall: boolean = false,
|
|
498
|
+
): Promise<{
|
|
499
|
+
success: boolean
|
|
500
|
+
latestVersion: string
|
|
501
|
+
lockFailed?: boolean
|
|
502
|
+
lockHolderPid?: number
|
|
503
|
+
}> {
|
|
504
|
+
const startTime = Date.now()
|
|
505
|
+
let version = await getLatestVersion(channelOrVersion)
|
|
506
|
+
const { executable: executablePath } = getBaseDirectories()
|
|
507
|
+
|
|
508
|
+
logForDebugging(`Checking for native installer update to version ${version}`)
|
|
509
|
+
|
|
510
|
+
// Check if max version is set (server-side kill switch for auto-updates)
|
|
511
|
+
if (!forceReinstall) {
|
|
512
|
+
const maxVersion = await getMaxVersion()
|
|
513
|
+
if (maxVersion && gt(version, maxVersion)) {
|
|
514
|
+
logForDebugging(
|
|
515
|
+
`Native installer: maxVersion ${maxVersion} is set, capping update from ${version} to ${maxVersion}`,
|
|
516
|
+
)
|
|
517
|
+
// If we're already at or above maxVersion, skip the update entirely
|
|
518
|
+
if (gte(MACRO.VERSION, maxVersion)) {
|
|
519
|
+
logForDebugging(
|
|
520
|
+
`Native installer: current version ${MACRO.VERSION} is already at or above maxVersion ${maxVersion}, skipping update`,
|
|
521
|
+
)
|
|
522
|
+
logEvent('tengu_native_update_skipped_max_version', {
|
|
523
|
+
latency_ms: Date.now() - startTime,
|
|
524
|
+
max_version:
|
|
525
|
+
maxVersion as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
|
526
|
+
available_version:
|
|
527
|
+
version as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
|
528
|
+
})
|
|
529
|
+
return { success: true, latestVersion: version }
|
|
530
|
+
}
|
|
531
|
+
version = maxVersion
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
// Early exit: if we're already running this exact version AND both the version binary
|
|
536
|
+
// and executable exist and are valid. We need to proceed if the executable doesn't exist,
|
|
537
|
+
// is invalid (e.g., empty/corrupted from a failed install), or we're running via npx.
|
|
538
|
+
if (
|
|
539
|
+
!forceReinstall &&
|
|
540
|
+
version === MACRO.VERSION &&
|
|
541
|
+
(await versionIsAvailable(version)) &&
|
|
542
|
+
(await isPossibleClaudeBinary(executablePath))
|
|
543
|
+
) {
|
|
544
|
+
logForDebugging(`Found ${version} at ${executablePath}, skipping install`)
|
|
545
|
+
logEvent('tengu_native_update_complete', {
|
|
546
|
+
latency_ms: Date.now() - startTime,
|
|
547
|
+
was_new_install: false,
|
|
548
|
+
was_force_reinstall: false,
|
|
549
|
+
was_already_running: true,
|
|
550
|
+
})
|
|
551
|
+
return { success: true, latestVersion: version }
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
// Check if this version should be skipped due to minimumVersion setting
|
|
555
|
+
if (!forceReinstall && shouldSkipVersion(version)) {
|
|
556
|
+
logEvent('tengu_native_update_skipped_minimum_version', {
|
|
557
|
+
latency_ms: Date.now() - startTime,
|
|
558
|
+
target_version:
|
|
559
|
+
version as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
|
560
|
+
})
|
|
561
|
+
return { success: true, latestVersion: version }
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
// Track if we're actually installing or just symlinking
|
|
565
|
+
let wasNewInstall = false
|
|
566
|
+
let latencyMs: number
|
|
567
|
+
|
|
568
|
+
if (isEnvTruthy(process.env.ENABLE_LOCKLESS_UPDATES)) {
|
|
569
|
+
// Lockless: rely on atomic operations, errors propagate
|
|
570
|
+
wasNewInstall = await performVersionUpdate(version, forceReinstall)
|
|
571
|
+
latencyMs = Date.now() - startTime
|
|
572
|
+
} else {
|
|
573
|
+
// Lock-based updates
|
|
574
|
+
const { installPath } = await getVersionPaths(version)
|
|
575
|
+
// If force reinstall, remove any existing lock to bypass stale locks
|
|
576
|
+
if (forceReinstall) {
|
|
577
|
+
await forceRemoveLock(installPath)
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
const lockAcquired = await tryWithVersionLock(
|
|
581
|
+
installPath,
|
|
582
|
+
async () => {
|
|
583
|
+
wasNewInstall = await performVersionUpdate(version, forceReinstall)
|
|
584
|
+
},
|
|
585
|
+
3, // retries
|
|
586
|
+
)
|
|
587
|
+
|
|
588
|
+
latencyMs = Date.now() - startTime
|
|
589
|
+
|
|
590
|
+
// Lock acquisition failed - get lock holder PID for error message
|
|
591
|
+
if (!lockAcquired) {
|
|
592
|
+
const dirs = getBaseDirectories()
|
|
593
|
+
let lockHolderPid: number | undefined
|
|
594
|
+
if (isPidBasedLockingEnabled()) {
|
|
595
|
+
const lockfilePath = getLockFilePathFromVersionPath(dirs, installPath)
|
|
596
|
+
if (isLockActive(lockfilePath)) {
|
|
597
|
+
lockHolderPid = readLockContent(lockfilePath)?.pid
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
logEvent('tengu_native_update_lock_failed', {
|
|
601
|
+
latency_ms: latencyMs,
|
|
602
|
+
lock_holder_pid: lockHolderPid,
|
|
603
|
+
})
|
|
604
|
+
return {
|
|
605
|
+
success: false,
|
|
606
|
+
latestVersion: version,
|
|
607
|
+
lockFailed: true,
|
|
608
|
+
lockHolderPid,
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
logEvent('tengu_native_update_complete', {
|
|
614
|
+
latency_ms: latencyMs,
|
|
615
|
+
was_new_install: wasNewInstall,
|
|
616
|
+
was_force_reinstall: forceReinstall,
|
|
617
|
+
})
|
|
618
|
+
logForDebugging(`Successfully updated to version ${version}`)
|
|
619
|
+
return { success: true, latestVersion: version }
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
// Exported for testing
|
|
623
|
+
export async function removeDirectoryIfEmpty(path: string): Promise<void> {
|
|
624
|
+
// rmdir alone handles all cases: ENOTDIR if path is a file, ENOTEMPTY if
|
|
625
|
+
// directory is non-empty, ENOENT if missing. No need to stat+readdir first.
|
|
626
|
+
try {
|
|
627
|
+
await rmdir(path)
|
|
628
|
+
logForDebugging(`Removed empty directory at ${path}`)
|
|
629
|
+
} catch (error) {
|
|
630
|
+
const code = getErrnoCode(error)
|
|
631
|
+
// Expected cases (not-a-dir, missing, not-empty) — silently skip.
|
|
632
|
+
// ENOTDIR is the normal path: executablePath is typically a symlink.
|
|
633
|
+
if (code !== 'ENOTDIR' && code !== 'ENOENT' && code !== 'ENOTEMPTY') {
|
|
634
|
+
logForDebugging(`Could not remove directory at ${path}: ${error}`)
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
async function updateSymlink(
|
|
640
|
+
symlinkPath: string,
|
|
641
|
+
targetPath: string,
|
|
642
|
+
): Promise<boolean> {
|
|
643
|
+
const platform = getPlatform()
|
|
644
|
+
const isWindows = platform.startsWith('win32')
|
|
645
|
+
|
|
646
|
+
// On Windows, directly copy the executable instead of creating a symlink
|
|
647
|
+
if (isWindows) {
|
|
648
|
+
try {
|
|
649
|
+
// Ensure parent directory exists
|
|
650
|
+
const parentDir = dirname(symlinkPath)
|
|
651
|
+
await mkdir(parentDir, { recursive: true })
|
|
652
|
+
|
|
653
|
+
// Check if file already exists and has same content
|
|
654
|
+
let existingStats: Stats | undefined
|
|
655
|
+
try {
|
|
656
|
+
existingStats = await stat(symlinkPath)
|
|
657
|
+
} catch {
|
|
658
|
+
// symlinkPath doesn't exist
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
if (existingStats) {
|
|
662
|
+
try {
|
|
663
|
+
const targetStats = await stat(targetPath)
|
|
664
|
+
// If sizes match, assume files are the same (avoid reading large files)
|
|
665
|
+
if (existingStats.size === targetStats.size) {
|
|
666
|
+
return false
|
|
667
|
+
}
|
|
668
|
+
} catch {
|
|
669
|
+
// Continue with copy if we can't compare
|
|
670
|
+
}
|
|
671
|
+
// Use rename strategy to handle file locking on Windows
|
|
672
|
+
// Rename always works even for running executables, unlike delete
|
|
673
|
+
const oldFileName = `${symlinkPath}.old.${Date.now()}`
|
|
674
|
+
await rename(symlinkPath, oldFileName)
|
|
675
|
+
|
|
676
|
+
// Try to copy new executable, with rollback on failure
|
|
677
|
+
try {
|
|
678
|
+
await copyFile(targetPath, symlinkPath)
|
|
679
|
+
// Success - try immediate cleanup of old file (non-blocking)
|
|
680
|
+
try {
|
|
681
|
+
await unlink(oldFileName)
|
|
682
|
+
} catch {
|
|
683
|
+
// File still running - ignore, Windows will clean up eventually
|
|
684
|
+
}
|
|
685
|
+
} catch (copyError) {
|
|
686
|
+
// Copy failed - restore the old executable
|
|
687
|
+
try {
|
|
688
|
+
await rename(oldFileName, symlinkPath)
|
|
689
|
+
} catch (restoreError) {
|
|
690
|
+
// Critical: User left without working executable - prioritize restore error
|
|
691
|
+
const errorWithCause = new Error(
|
|
692
|
+
`Failed to restore old executable: ${restoreError}`,
|
|
693
|
+
{ cause: copyError },
|
|
694
|
+
)
|
|
695
|
+
logError(errorWithCause)
|
|
696
|
+
throw errorWithCause
|
|
697
|
+
}
|
|
698
|
+
throw copyError
|
|
699
|
+
}
|
|
700
|
+
} else {
|
|
701
|
+
// First-time installation (no existing file to rename)
|
|
702
|
+
// Copy the executable directly; handle ENOENT from copyFile itself
|
|
703
|
+
// rather than a stat() pre-check (avoids TOCTOU + extra syscall)
|
|
704
|
+
try {
|
|
705
|
+
await copyFile(targetPath, symlinkPath)
|
|
706
|
+
} catch (e) {
|
|
707
|
+
if (isENOENT(e)) {
|
|
708
|
+
throw new Error(`Source file does not exist: ${targetPath}`)
|
|
709
|
+
}
|
|
710
|
+
throw e
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
// chmod is not needed on Windows - executability is determined by .exe extension
|
|
714
|
+
return true
|
|
715
|
+
} catch (error) {
|
|
716
|
+
logError(
|
|
717
|
+
new Error(
|
|
718
|
+
`Failed to copy executable from ${targetPath} to ${symlinkPath}: ${error}`,
|
|
719
|
+
),
|
|
720
|
+
)
|
|
721
|
+
return false
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
// For non-Windows platforms, use symlinks as before
|
|
726
|
+
// Ensure parent directory exists (same as Windows path above)
|
|
727
|
+
const parentDir = dirname(symlinkPath)
|
|
728
|
+
try {
|
|
729
|
+
await mkdir(parentDir, { recursive: true })
|
|
730
|
+
logForDebugging(`Created directory ${parentDir} for symlink`)
|
|
731
|
+
} catch (mkdirError) {
|
|
732
|
+
logError(
|
|
733
|
+
new Error(`Failed to create directory ${parentDir}: ${mkdirError}`),
|
|
734
|
+
)
|
|
735
|
+
return false
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
// Check if symlink already exists and points to the correct target
|
|
739
|
+
try {
|
|
740
|
+
let symlinkExists = false
|
|
741
|
+
try {
|
|
742
|
+
await stat(symlinkPath)
|
|
743
|
+
symlinkExists = true
|
|
744
|
+
} catch {
|
|
745
|
+
// symlinkPath doesn't exist
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
if (symlinkExists) {
|
|
749
|
+
try {
|
|
750
|
+
const currentTarget = await readlink(symlinkPath)
|
|
751
|
+
const resolvedCurrentTarget = resolve(
|
|
752
|
+
dirname(symlinkPath),
|
|
753
|
+
currentTarget,
|
|
754
|
+
)
|
|
755
|
+
const resolvedTargetPath = resolve(targetPath)
|
|
756
|
+
|
|
757
|
+
if (resolvedCurrentTarget === resolvedTargetPath) {
|
|
758
|
+
return false
|
|
759
|
+
}
|
|
760
|
+
} catch {
|
|
761
|
+
// Path exists but is not a symlink - will remove it below
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
// Remove existing file/symlink before creating new one
|
|
765
|
+
await unlink(symlinkPath)
|
|
766
|
+
}
|
|
767
|
+
} catch (error) {
|
|
768
|
+
logError(new Error(`Failed to check/remove existing symlink: ${error}`))
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
// Use atomic rename to avoid race conditions. Create symlink with temporary name
|
|
772
|
+
// then atomically rename to final name. This ensures the symlink always exists
|
|
773
|
+
// and is always valid, even with concurrent updates.
|
|
774
|
+
const tempSymlink = `${symlinkPath}.tmp.${process.pid}.${Date.now()}`
|
|
775
|
+
try {
|
|
776
|
+
await symlink(targetPath, tempSymlink)
|
|
777
|
+
|
|
778
|
+
// Atomically rename to final name (replaces existing)
|
|
779
|
+
await rename(tempSymlink, symlinkPath)
|
|
780
|
+
logForDebugging(
|
|
781
|
+
`Atomically updated symlink ${symlinkPath} -> ${targetPath}`,
|
|
782
|
+
)
|
|
783
|
+
return true
|
|
784
|
+
} catch (error) {
|
|
785
|
+
// Clean up temp symlink if it exists
|
|
786
|
+
try {
|
|
787
|
+
await unlink(tempSymlink)
|
|
788
|
+
} catch {
|
|
789
|
+
// Ignore cleanup errors
|
|
790
|
+
}
|
|
791
|
+
logError(
|
|
792
|
+
new Error(
|
|
793
|
+
`Failed to create symlink from ${symlinkPath} to ${targetPath}: ${error}`,
|
|
794
|
+
),
|
|
795
|
+
)
|
|
796
|
+
return false
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
export async function checkInstall(
|
|
801
|
+
force: boolean = false,
|
|
802
|
+
): Promise<SetupMessage[]> {
|
|
803
|
+
// Skip all installation checks if disabled via environment variable
|
|
804
|
+
if (isEnvTruthy(process.env.DISABLE_INSTALLATION_CHECKS)) {
|
|
805
|
+
return []
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
// Get the actual installation type and config
|
|
809
|
+
const installationType = await getCurrentInstallationType()
|
|
810
|
+
|
|
811
|
+
// Skip checks for development builds - config.installMethod from a previous
|
|
812
|
+
// native installation shouldn't trigger warnings when running dev builds
|
|
813
|
+
if (installationType === 'development') {
|
|
814
|
+
return []
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
const config = getGlobalConfig()
|
|
818
|
+
|
|
819
|
+
// Only show warnings if:
|
|
820
|
+
// 1. User is actually running from native installation, OR
|
|
821
|
+
// 2. User has explicitly set installMethod to 'native' in config (they're trying to use native)
|
|
822
|
+
// 3. force is true (used during installation process)
|
|
823
|
+
const shouldCheckNative =
|
|
824
|
+
force || installationType === 'native' || config.installMethod === 'native'
|
|
825
|
+
|
|
826
|
+
if (!shouldCheckNative) {
|
|
827
|
+
return []
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
const dirs = getBaseDirectories()
|
|
831
|
+
const messages: SetupMessage[] = []
|
|
832
|
+
const localBinDir = dirname(dirs.executable)
|
|
833
|
+
const resolvedLocalBinPath = resolve(localBinDir)
|
|
834
|
+
const platform = getPlatform()
|
|
835
|
+
const isWindows = platform.startsWith('win32')
|
|
836
|
+
|
|
837
|
+
// Check if bin directory exists
|
|
838
|
+
try {
|
|
839
|
+
await access(localBinDir)
|
|
840
|
+
} catch {
|
|
841
|
+
messages.push({
|
|
842
|
+
message: `installMethod is native, but directory ${localBinDir} does not exist`,
|
|
843
|
+
userActionRequired: true,
|
|
844
|
+
type: 'error',
|
|
845
|
+
})
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
// Check if claude executable exists and is valid.
|
|
849
|
+
// On non-Windows, call readlink directly and route errno — ENOENT means
|
|
850
|
+
// the executable is missing, EINVAL means it exists but isn't a symlink.
|
|
851
|
+
// This avoids an access()→readlink() TOCTOU where deletion between the
|
|
852
|
+
// two calls produces a misleading "Not a symlink" diagnostic.
|
|
853
|
+
// isPossibleClaudeBinary stats the path internally, so we don't pre-check
|
|
854
|
+
// with access() — that would be a TOCTOU between access and the stat.
|
|
855
|
+
if (isWindows) {
|
|
856
|
+
// On Windows it's a copied executable, not a symlink
|
|
857
|
+
if (!(await isPossibleClaudeBinary(dirs.executable))) {
|
|
858
|
+
messages.push({
|
|
859
|
+
message: `installMethod is native, but claude command is missing or invalid at ${dirs.executable}`,
|
|
860
|
+
userActionRequired: true,
|
|
861
|
+
type: 'error',
|
|
862
|
+
})
|
|
863
|
+
}
|
|
864
|
+
} else {
|
|
865
|
+
try {
|
|
866
|
+
const target = await readlink(dirs.executable)
|
|
867
|
+
const absoluteTarget = resolve(dirname(dirs.executable), target)
|
|
868
|
+
if (!(await isPossibleClaudeBinary(absoluteTarget))) {
|
|
869
|
+
messages.push({
|
|
870
|
+
message: `Claude symlink points to missing or invalid binary: ${target}`,
|
|
871
|
+
userActionRequired: true,
|
|
872
|
+
type: 'error',
|
|
873
|
+
})
|
|
874
|
+
}
|
|
875
|
+
} catch (e) {
|
|
876
|
+
if (isENOENT(e)) {
|
|
877
|
+
messages.push({
|
|
878
|
+
message: `installMethod is native, but claude command not found at ${dirs.executable}`,
|
|
879
|
+
userActionRequired: true,
|
|
880
|
+
type: 'error',
|
|
881
|
+
})
|
|
882
|
+
} else {
|
|
883
|
+
// EINVAL (not a symlink) or other — check as regular binary
|
|
884
|
+
if (!(await isPossibleClaudeBinary(dirs.executable))) {
|
|
885
|
+
messages.push({
|
|
886
|
+
message: `${dirs.executable} exists but is not a valid Claude binary`,
|
|
887
|
+
userActionRequired: true,
|
|
888
|
+
type: 'error',
|
|
889
|
+
})
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
// Check if bin directory is in PATH
|
|
896
|
+
const isInCurrentPath = (process.env.PATH || '')
|
|
897
|
+
.split(delimiter)
|
|
898
|
+
.some(entry => {
|
|
899
|
+
try {
|
|
900
|
+
const resolvedEntry = resolve(entry)
|
|
901
|
+
// On Windows, perform case-insensitive comparison for paths
|
|
902
|
+
if (isWindows) {
|
|
903
|
+
return (
|
|
904
|
+
resolvedEntry.toLowerCase() === resolvedLocalBinPath.toLowerCase()
|
|
905
|
+
)
|
|
906
|
+
}
|
|
907
|
+
return resolvedEntry === resolvedLocalBinPath
|
|
908
|
+
} catch {
|
|
909
|
+
return false
|
|
910
|
+
}
|
|
911
|
+
})
|
|
912
|
+
|
|
913
|
+
if (!isInCurrentPath) {
|
|
914
|
+
if (isWindows) {
|
|
915
|
+
// Windows-specific PATH instructions
|
|
916
|
+
const windowsBinPath = localBinDir.replace(/\//g, '\\')
|
|
917
|
+
messages.push({
|
|
918
|
+
message: `Native installation exists but ${windowsBinPath} is not in your PATH. Add it by opening: System Properties → Environment Variables → Edit User PATH → New → Add the path above. Then restart your terminal.`,
|
|
919
|
+
userActionRequired: true,
|
|
920
|
+
type: 'path',
|
|
921
|
+
})
|
|
922
|
+
} else {
|
|
923
|
+
// Unix-style PATH instructions
|
|
924
|
+
const shellType = getShellType()
|
|
925
|
+
const configPaths = getShellConfigPaths()
|
|
926
|
+
const configFile = configPaths[shellType as keyof typeof configPaths]
|
|
927
|
+
const displayPath = configFile
|
|
928
|
+
? configFile.replace(homedir(), '~')
|
|
929
|
+
: 'your shell config file'
|
|
930
|
+
|
|
931
|
+
messages.push({
|
|
932
|
+
message: `Native installation exists but ~/.local/bin is not in your PATH. Run:\n\necho 'export PATH="$HOME/.local/bin:$PATH"' >> ${displayPath} && source ${displayPath}`,
|
|
933
|
+
userActionRequired: true,
|
|
934
|
+
type: 'path',
|
|
935
|
+
})
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
return messages
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
type InstallLatestResult = {
|
|
943
|
+
latestVersion: string | null
|
|
944
|
+
wasUpdated: boolean
|
|
945
|
+
lockFailed?: boolean
|
|
946
|
+
lockHolderPid?: number
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
// In-process singleflight guard. NativeAutoUpdater remounts whenever the
|
|
950
|
+
// prompt suggestions overlay toggles (PromptInput.tsx:2916), and the
|
|
951
|
+
// isUpdating guard does not survive the remount. Each remount kicked off a
|
|
952
|
+
// fresh 271MB binary download while previous ones were still in flight.
|
|
953
|
+
// Telemetry: session 42fed33f saw arrayBuffers climb to 91GB at ~650MB/s.
|
|
954
|
+
let inFlightInstall: Promise<InstallLatestResult> | null = null
|
|
955
|
+
|
|
956
|
+
export function installLatest(
|
|
957
|
+
channelOrVersion: string,
|
|
958
|
+
forceReinstall: boolean = false,
|
|
959
|
+
): Promise<InstallLatestResult> {
|
|
960
|
+
if (forceReinstall) {
|
|
961
|
+
return installLatestImpl(channelOrVersion, forceReinstall)
|
|
962
|
+
}
|
|
963
|
+
if (inFlightInstall) {
|
|
964
|
+
logForDebugging('installLatest: joining in-flight call')
|
|
965
|
+
return inFlightInstall
|
|
966
|
+
}
|
|
967
|
+
const promise = installLatestImpl(channelOrVersion, forceReinstall)
|
|
968
|
+
inFlightInstall = promise
|
|
969
|
+
const clear = (): void => {
|
|
970
|
+
inFlightInstall = null
|
|
971
|
+
}
|
|
972
|
+
void promise.then(clear, clear)
|
|
973
|
+
return promise
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
async function installLatestImpl(
|
|
977
|
+
channelOrVersion: string,
|
|
978
|
+
forceReinstall: boolean = false,
|
|
979
|
+
): Promise<InstallLatestResult> {
|
|
980
|
+
const updateResult = await updateLatest(channelOrVersion, forceReinstall)
|
|
981
|
+
|
|
982
|
+
if (!updateResult.success) {
|
|
983
|
+
return {
|
|
984
|
+
latestVersion: null,
|
|
985
|
+
wasUpdated: false,
|
|
986
|
+
lockFailed: updateResult.lockFailed,
|
|
987
|
+
lockHolderPid: updateResult.lockHolderPid,
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
// Installation succeeded (early return above covers failure). Mark as native
|
|
992
|
+
// and disable legacy auto-updater to protect symlinks.
|
|
993
|
+
const config = getGlobalConfig()
|
|
994
|
+
if (config.installMethod !== 'native') {
|
|
995
|
+
saveGlobalConfig(current => ({
|
|
996
|
+
...current,
|
|
997
|
+
installMethod: 'native',
|
|
998
|
+
// Disable legacy auto-updater to prevent npm sessions from deleting native symlinks.
|
|
999
|
+
// Native installations use NativeAutoUpdater instead, which respects native installation.
|
|
1000
|
+
autoUpdates: false,
|
|
1001
|
+
// Mark this as protection-based, not user preference
|
|
1002
|
+
autoUpdatesProtectedForNative: true,
|
|
1003
|
+
}))
|
|
1004
|
+
logForDebugging(
|
|
1005
|
+
'Native installer: Set installMethod to "native" and disabled legacy auto-updater for protection',
|
|
1006
|
+
)
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
void cleanupOldVersions()
|
|
1010
|
+
|
|
1011
|
+
return {
|
|
1012
|
+
latestVersion: updateResult.latestVersion,
|
|
1013
|
+
wasUpdated: updateResult.success,
|
|
1014
|
+
lockFailed: false,
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
async function getVersionFromSymlink(
|
|
1019
|
+
symlinkPath: string,
|
|
1020
|
+
): Promise<string | null> {
|
|
1021
|
+
try {
|
|
1022
|
+
const target = await readlink(symlinkPath)
|
|
1023
|
+
const absoluteTarget = resolve(dirname(symlinkPath), target)
|
|
1024
|
+
if (await isPossibleClaudeBinary(absoluteTarget)) {
|
|
1025
|
+
return absoluteTarget
|
|
1026
|
+
}
|
|
1027
|
+
} catch {
|
|
1028
|
+
// Not a symlink / doesn't exist / target doesn't exist
|
|
1029
|
+
}
|
|
1030
|
+
return null
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
function getLockFilePathFromVersionPath(
|
|
1034
|
+
dirs: ReturnType<typeof getBaseDirectories>,
|
|
1035
|
+
versionPath: string,
|
|
1036
|
+
) {
|
|
1037
|
+
const versionName = basename(versionPath)
|
|
1038
|
+
return join(dirs.locks, `${versionName}.lock`)
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
/**
|
|
1042
|
+
* Acquire a lock on the current running version to prevent it from being deleted
|
|
1043
|
+
* This lock is held for the entire lifetime of the process
|
|
1044
|
+
*
|
|
1045
|
+
* Uses PID-based locking (when enabled) which can immediately detect crashed processes
|
|
1046
|
+
* (unlike mtime-based locking which requires a 30-day timeout)
|
|
1047
|
+
*/
|
|
1048
|
+
export async function lockCurrentVersion(): Promise<void> {
|
|
1049
|
+
const dirs = getBaseDirectories()
|
|
1050
|
+
|
|
1051
|
+
// Only lock if we're running from the versions directory
|
|
1052
|
+
if (!process.execPath.includes(dirs.versions)) {
|
|
1053
|
+
return
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
const versionPath = resolve(process.execPath)
|
|
1057
|
+
try {
|
|
1058
|
+
const lockfilePath = getLockFilePathFromVersionPath(dirs, versionPath)
|
|
1059
|
+
|
|
1060
|
+
// Ensure locks directory exists
|
|
1061
|
+
await mkdir(dirs.locks, { recursive: true })
|
|
1062
|
+
|
|
1063
|
+
if (isPidBasedLockingEnabled()) {
|
|
1064
|
+
// Acquire PID-based lock and hold it for the process lifetime
|
|
1065
|
+
// PID-based locking allows immediate detection of crashed processes
|
|
1066
|
+
// while still surviving laptop sleep (process is suspended but PID exists)
|
|
1067
|
+
const acquired = await acquireProcessLifetimeLock(
|
|
1068
|
+
versionPath,
|
|
1069
|
+
lockfilePath,
|
|
1070
|
+
)
|
|
1071
|
+
|
|
1072
|
+
if (!acquired) {
|
|
1073
|
+
logEvent('tengu_version_lock_failed', {
|
|
1074
|
+
is_pid_based: true,
|
|
1075
|
+
is_lifetime_lock: true,
|
|
1076
|
+
})
|
|
1077
|
+
logLockAcquisitionError(
|
|
1078
|
+
versionPath,
|
|
1079
|
+
new Error('Lock already held by another process'),
|
|
1080
|
+
)
|
|
1081
|
+
return
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
logEvent('tengu_version_lock_acquired', {
|
|
1085
|
+
is_pid_based: true,
|
|
1086
|
+
is_lifetime_lock: true,
|
|
1087
|
+
})
|
|
1088
|
+
logForDebugging(`Acquired PID lock on running version: ${versionPath}`)
|
|
1089
|
+
} else {
|
|
1090
|
+
// Acquire mtime-based lock and never release it (until process exits)
|
|
1091
|
+
// Use 30 days for stale to prevent the lock from being considered stale during
|
|
1092
|
+
// normal usage. This is critical because laptop sleep suspends the process,
|
|
1093
|
+
// stopping the mtime heartbeat. 30 days is long enough for any realistic session
|
|
1094
|
+
// while still allowing eventual cleanup of abandoned locks.
|
|
1095
|
+
let release: (() => Promise<void>) | undefined
|
|
1096
|
+
try {
|
|
1097
|
+
release = await lockfile.lock(versionPath, {
|
|
1098
|
+
stale: LOCK_STALE_MS,
|
|
1099
|
+
retries: 0, // Don't retry - if we can't lock, that's fine
|
|
1100
|
+
lockfilePath,
|
|
1101
|
+
// Handle lock compromise gracefully (e.g., if another process deletes the lock directory)
|
|
1102
|
+
onCompromised: (err: Error) => {
|
|
1103
|
+
logForDebugging(
|
|
1104
|
+
`NON-FATAL: Lock on running version was compromised: ${err.message}`,
|
|
1105
|
+
{ level: 'info' },
|
|
1106
|
+
)
|
|
1107
|
+
},
|
|
1108
|
+
})
|
|
1109
|
+
logEvent('tengu_version_lock_acquired', {
|
|
1110
|
+
is_pid_based: false,
|
|
1111
|
+
is_lifetime_lock: true,
|
|
1112
|
+
})
|
|
1113
|
+
logForDebugging(
|
|
1114
|
+
`Acquired mtime-based lock on running version: ${versionPath}`,
|
|
1115
|
+
)
|
|
1116
|
+
|
|
1117
|
+
// Release lock explicitly; proper-lockfile's cleanup is unreliable with signal-exit v3+v4
|
|
1118
|
+
registerCleanup(async () => {
|
|
1119
|
+
try {
|
|
1120
|
+
await release?.()
|
|
1121
|
+
} catch {
|
|
1122
|
+
// Lock may already be released
|
|
1123
|
+
}
|
|
1124
|
+
})
|
|
1125
|
+
} catch (lockError) {
|
|
1126
|
+
if (isENOENT(lockError)) {
|
|
1127
|
+
logForDebugging(
|
|
1128
|
+
`Cannot lock current version - file does not exist: ${versionPath}`,
|
|
1129
|
+
{ level: 'info' },
|
|
1130
|
+
)
|
|
1131
|
+
return
|
|
1132
|
+
}
|
|
1133
|
+
logEvent('tengu_version_lock_failed', {
|
|
1134
|
+
is_pid_based: false,
|
|
1135
|
+
is_lifetime_lock: true,
|
|
1136
|
+
})
|
|
1137
|
+
logLockAcquisitionError(versionPath, lockError)
|
|
1138
|
+
return
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
} catch (error) {
|
|
1142
|
+
if (isENOENT(error)) {
|
|
1143
|
+
logForDebugging(
|
|
1144
|
+
`Cannot lock current version - file does not exist: ${versionPath}`,
|
|
1145
|
+
{ level: 'info' },
|
|
1146
|
+
)
|
|
1147
|
+
return
|
|
1148
|
+
}
|
|
1149
|
+
// We fallback to previous behavior where we don't acquire a lock on a running version
|
|
1150
|
+
// This ~mostly works but using native binaries like ripgrep will fail
|
|
1151
|
+
logForDebugging(
|
|
1152
|
+
`NON-FATAL: Failed to lock current version during execution ${errorMessage(error)}`,
|
|
1153
|
+
{ level: 'info' },
|
|
1154
|
+
)
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
function logLockAcquisitionError(versionPath: string, lockError: unknown) {
|
|
1159
|
+
logError(
|
|
1160
|
+
new Error(
|
|
1161
|
+
`NON-FATAL: Lock acquisition failed for ${versionPath} (expected in multi-process scenarios)`,
|
|
1162
|
+
{ cause: lockError },
|
|
1163
|
+
),
|
|
1164
|
+
)
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
/**
|
|
1168
|
+
* Force-remove a lock file for a given version path.
|
|
1169
|
+
* Used when --force is specified to bypass stale locks.
|
|
1170
|
+
*/
|
|
1171
|
+
async function forceRemoveLock(versionFilePath: string): Promise<void> {
|
|
1172
|
+
const dirs = getBaseDirectories()
|
|
1173
|
+
const lockfilePath = getLockFilePathFromVersionPath(dirs, versionFilePath)
|
|
1174
|
+
|
|
1175
|
+
try {
|
|
1176
|
+
await unlink(lockfilePath)
|
|
1177
|
+
logForDebugging(`Force-removed lock file at ${lockfilePath}`)
|
|
1178
|
+
} catch (error) {
|
|
1179
|
+
// Log but don't throw - we'll try to acquire the lock anyway
|
|
1180
|
+
logForDebugging(`Failed to force-remove lock file: ${errorMessage(error)}`)
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1184
|
+
export async function cleanupOldVersions(): Promise<void> {
|
|
1185
|
+
// Yield to ensure we don't block startup
|
|
1186
|
+
await Promise.resolve()
|
|
1187
|
+
|
|
1188
|
+
const dirs = getBaseDirectories()
|
|
1189
|
+
const oneHourAgo = Date.now() - 3600000
|
|
1190
|
+
|
|
1191
|
+
// Clean up old renamed executables on Windows (no longer running at startup)
|
|
1192
|
+
if (getPlatform().startsWith('win32')) {
|
|
1193
|
+
const executableDir = dirname(dirs.executable)
|
|
1194
|
+
try {
|
|
1195
|
+
const files = await readdir(executableDir)
|
|
1196
|
+
let cleanedCount = 0
|
|
1197
|
+
for (const file of files) {
|
|
1198
|
+
if (!/^claude\.exe\.old\.\d+$/.test(file)) continue
|
|
1199
|
+
try {
|
|
1200
|
+
await unlink(join(executableDir, file))
|
|
1201
|
+
cleanedCount++
|
|
1202
|
+
} catch {
|
|
1203
|
+
// File might still be in use by another process
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
if (cleanedCount > 0) {
|
|
1207
|
+
logForDebugging(
|
|
1208
|
+
`Cleaned up ${cleanedCount} old Windows executables on startup`,
|
|
1209
|
+
)
|
|
1210
|
+
}
|
|
1211
|
+
} catch (error) {
|
|
1212
|
+
if (!isENOENT(error)) {
|
|
1213
|
+
logForDebugging(`Failed to clean up old Windows executables: ${error}`)
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
// Clean up orphaned staging directories older than 1 hour
|
|
1219
|
+
try {
|
|
1220
|
+
const stagingEntries = await readdir(dirs.staging)
|
|
1221
|
+
let stagingCleanedCount = 0
|
|
1222
|
+
for (const entry of stagingEntries) {
|
|
1223
|
+
const stagingPath = join(dirs.staging, entry)
|
|
1224
|
+
try {
|
|
1225
|
+
// stat() is load-bearing here (we need mtime). There is a theoretical
|
|
1226
|
+
// TOCTOU where a concurrent installer could freshen a stale staging
|
|
1227
|
+
// dir between stat and rm — but the 1-hour threshold makes this
|
|
1228
|
+
// vanishingly unlikely, and rm({force:true}) tolerates concurrent
|
|
1229
|
+
// deletion.
|
|
1230
|
+
const stats = await stat(stagingPath)
|
|
1231
|
+
if (stats.mtime.getTime() < oneHourAgo) {
|
|
1232
|
+
await rm(stagingPath, { recursive: true, force: true })
|
|
1233
|
+
stagingCleanedCount++
|
|
1234
|
+
logForDebugging(`Cleaned up old staging directory: ${entry}`)
|
|
1235
|
+
}
|
|
1236
|
+
} catch {
|
|
1237
|
+
// Ignore individual errors
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
if (stagingCleanedCount > 0) {
|
|
1241
|
+
logForDebugging(
|
|
1242
|
+
`Cleaned up ${stagingCleanedCount} orphaned staging directories`,
|
|
1243
|
+
)
|
|
1244
|
+
logEvent('tengu_native_staging_cleanup', {
|
|
1245
|
+
cleaned_count: stagingCleanedCount,
|
|
1246
|
+
})
|
|
1247
|
+
}
|
|
1248
|
+
} catch (error) {
|
|
1249
|
+
if (!isENOENT(error)) {
|
|
1250
|
+
logForDebugging(`Failed to clean up staging directories: ${error}`)
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
// Clean up stale PID locks (crashed processes) — cleanupStaleLocks handles ENOENT
|
|
1255
|
+
if (isPidBasedLockingEnabled()) {
|
|
1256
|
+
const staleLocksCleaned = cleanupStaleLocks(dirs.locks)
|
|
1257
|
+
if (staleLocksCleaned > 0) {
|
|
1258
|
+
logForDebugging(`Cleaned up ${staleLocksCleaned} stale version locks`)
|
|
1259
|
+
logEvent('tengu_native_stale_locks_cleanup', {
|
|
1260
|
+
cleaned_count: staleLocksCleaned,
|
|
1261
|
+
})
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1265
|
+
// Single readdir of versions dir. Partition into temp files vs candidate binaries,
|
|
1266
|
+
// stat'ing each entry at most once.
|
|
1267
|
+
let versionEntries: string[]
|
|
1268
|
+
try {
|
|
1269
|
+
versionEntries = await readdir(dirs.versions)
|
|
1270
|
+
} catch (error) {
|
|
1271
|
+
if (!isENOENT(error)) {
|
|
1272
|
+
logForDebugging(`Failed to readdir versions directory: ${error}`)
|
|
1273
|
+
}
|
|
1274
|
+
return
|
|
1275
|
+
}
|
|
1276
|
+
|
|
1277
|
+
type VersionInfo = {
|
|
1278
|
+
name: string
|
|
1279
|
+
path: string
|
|
1280
|
+
resolvedPath: string
|
|
1281
|
+
mtime: Date
|
|
1282
|
+
}
|
|
1283
|
+
const versionFiles: VersionInfo[] = []
|
|
1284
|
+
let tempFilesCleanedCount = 0
|
|
1285
|
+
|
|
1286
|
+
for (const entry of versionEntries) {
|
|
1287
|
+
const entryPath = join(dirs.versions, entry)
|
|
1288
|
+
if (/\.tmp\.\d+\.\d+$/.test(entry)) {
|
|
1289
|
+
// Orphaned temp install file — pattern: {version}.tmp.{pid}.{timestamp}
|
|
1290
|
+
try {
|
|
1291
|
+
const stats = await stat(entryPath)
|
|
1292
|
+
if (stats.mtime.getTime() < oneHourAgo) {
|
|
1293
|
+
await unlink(entryPath)
|
|
1294
|
+
tempFilesCleanedCount++
|
|
1295
|
+
logForDebugging(`Cleaned up orphaned temp install file: ${entry}`)
|
|
1296
|
+
}
|
|
1297
|
+
} catch {
|
|
1298
|
+
// Ignore individual errors
|
|
1299
|
+
}
|
|
1300
|
+
continue
|
|
1301
|
+
}
|
|
1302
|
+
// Candidate version binary — stat once, reuse for isFile/size/mtime/mode
|
|
1303
|
+
try {
|
|
1304
|
+
const stats = await stat(entryPath)
|
|
1305
|
+
if (!stats.isFile()) continue
|
|
1306
|
+
if (
|
|
1307
|
+
process.platform !== 'win32' &&
|
|
1308
|
+
stats.size > 0 &&
|
|
1309
|
+
(stats.mode & 0o111) === 0
|
|
1310
|
+
) {
|
|
1311
|
+
// Check executability via mode bits from the existing stat result —
|
|
1312
|
+
// avoids a second syscall (access(X_OK)) and the TOCTOU window between
|
|
1313
|
+
// stat and access. Skip on Windows: libuv only sets execute bits for
|
|
1314
|
+
// .exe/.com/.bat/.cmd, but version files are extensionless semver
|
|
1315
|
+
// strings (e.g. "1.2.3"), so this check would reject all of them.
|
|
1316
|
+
// The previous access(X_OK) passed any readable file on Windows anyway.
|
|
1317
|
+
continue
|
|
1318
|
+
}
|
|
1319
|
+
versionFiles.push({
|
|
1320
|
+
name: entry,
|
|
1321
|
+
path: entryPath,
|
|
1322
|
+
resolvedPath: resolve(entryPath),
|
|
1323
|
+
mtime: stats.mtime,
|
|
1324
|
+
})
|
|
1325
|
+
} catch {
|
|
1326
|
+
// Skip files we can't stat
|
|
1327
|
+
}
|
|
1328
|
+
}
|
|
1329
|
+
|
|
1330
|
+
if (tempFilesCleanedCount > 0) {
|
|
1331
|
+
logForDebugging(
|
|
1332
|
+
`Cleaned up ${tempFilesCleanedCount} orphaned temp install files`,
|
|
1333
|
+
)
|
|
1334
|
+
logEvent('tengu_native_temp_files_cleanup', {
|
|
1335
|
+
cleaned_count: tempFilesCleanedCount,
|
|
1336
|
+
})
|
|
1337
|
+
}
|
|
1338
|
+
|
|
1339
|
+
if (versionFiles.length === 0) {
|
|
1340
|
+
return
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1343
|
+
try {
|
|
1344
|
+
// Identify protected versions
|
|
1345
|
+
const currentBinaryPath = process.execPath
|
|
1346
|
+
const protectedVersions = new Set<string>()
|
|
1347
|
+
if (currentBinaryPath && currentBinaryPath.includes(dirs.versions)) {
|
|
1348
|
+
protectedVersions.add(resolve(currentBinaryPath))
|
|
1349
|
+
}
|
|
1350
|
+
|
|
1351
|
+
const currentSymlinkVersion = await getVersionFromSymlink(dirs.executable)
|
|
1352
|
+
if (currentSymlinkVersion) {
|
|
1353
|
+
protectedVersions.add(currentSymlinkVersion)
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
// Protect versions with active locks (running in other processes)
|
|
1357
|
+
for (const v of versionFiles) {
|
|
1358
|
+
if (protectedVersions.has(v.resolvedPath)) continue
|
|
1359
|
+
|
|
1360
|
+
const lockFilePath = getLockFilePathFromVersionPath(dirs, v.resolvedPath)
|
|
1361
|
+
let hasActiveLock = false
|
|
1362
|
+
if (isPidBasedLockingEnabled()) {
|
|
1363
|
+
hasActiveLock = isLockActive(lockFilePath)
|
|
1364
|
+
} else {
|
|
1365
|
+
try {
|
|
1366
|
+
hasActiveLock = await lockfile.check(v.resolvedPath, {
|
|
1367
|
+
stale: LOCK_STALE_MS,
|
|
1368
|
+
lockfilePath: lockFilePath,
|
|
1369
|
+
})
|
|
1370
|
+
} catch {
|
|
1371
|
+
hasActiveLock = false
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1374
|
+
if (hasActiveLock) {
|
|
1375
|
+
protectedVersions.add(v.resolvedPath)
|
|
1376
|
+
logForDebugging(`Protecting locked version from cleanup: ${v.name}`)
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1380
|
+
// Eligible versions: not protected, sorted newest first (reuse cached mtime)
|
|
1381
|
+
const eligibleVersions = versionFiles
|
|
1382
|
+
.filter(v => !protectedVersions.has(v.resolvedPath))
|
|
1383
|
+
.sort((a, b) => b.mtime.getTime() - a.mtime.getTime())
|
|
1384
|
+
|
|
1385
|
+
const versionsToDelete = eligibleVersions.slice(VERSION_RETENTION_COUNT)
|
|
1386
|
+
|
|
1387
|
+
if (versionsToDelete.length === 0) {
|
|
1388
|
+
logEvent('tengu_native_version_cleanup', {
|
|
1389
|
+
total_count: versionFiles.length,
|
|
1390
|
+
deleted_count: 0,
|
|
1391
|
+
protected_count: protectedVersions.size,
|
|
1392
|
+
retained_count: VERSION_RETENTION_COUNT,
|
|
1393
|
+
lock_failed_count: 0,
|
|
1394
|
+
error_count: 0,
|
|
1395
|
+
})
|
|
1396
|
+
return
|
|
1397
|
+
}
|
|
1398
|
+
|
|
1399
|
+
let deletedCount = 0
|
|
1400
|
+
let lockFailedCount = 0
|
|
1401
|
+
let errorCount = 0
|
|
1402
|
+
|
|
1403
|
+
await Promise.all(
|
|
1404
|
+
versionsToDelete.map(async version => {
|
|
1405
|
+
try {
|
|
1406
|
+
const deleted = await tryWithVersionLock(version.path, async () => {
|
|
1407
|
+
await unlink(version.path)
|
|
1408
|
+
})
|
|
1409
|
+
if (deleted) {
|
|
1410
|
+
deletedCount++
|
|
1411
|
+
} else {
|
|
1412
|
+
lockFailedCount++
|
|
1413
|
+
logForDebugging(
|
|
1414
|
+
`Skipping deletion of ${version.name} - locked by another process`,
|
|
1415
|
+
)
|
|
1416
|
+
}
|
|
1417
|
+
} catch (error) {
|
|
1418
|
+
errorCount++
|
|
1419
|
+
logError(
|
|
1420
|
+
new Error(`Failed to delete version ${version.name}: ${error}`),
|
|
1421
|
+
)
|
|
1422
|
+
}
|
|
1423
|
+
}),
|
|
1424
|
+
)
|
|
1425
|
+
|
|
1426
|
+
logEvent('tengu_native_version_cleanup', {
|
|
1427
|
+
total_count: versionFiles.length,
|
|
1428
|
+
deleted_count: deletedCount,
|
|
1429
|
+
protected_count: protectedVersions.size,
|
|
1430
|
+
retained_count: VERSION_RETENTION_COUNT,
|
|
1431
|
+
lock_failed_count: lockFailedCount,
|
|
1432
|
+
error_count: errorCount,
|
|
1433
|
+
})
|
|
1434
|
+
} catch (error) {
|
|
1435
|
+
if (!isENOENT(error)) {
|
|
1436
|
+
logError(new Error(`Version cleanup failed: ${error}`))
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1441
|
+
/**
|
|
1442
|
+
* Check if a given path is managed by npm
|
|
1443
|
+
* @param executablePath - The path to check (can be a symlink)
|
|
1444
|
+
* @returns true if the path is npm-managed, false otherwise
|
|
1445
|
+
*/
|
|
1446
|
+
async function isNpmSymlink(executablePath: string): Promise<boolean> {
|
|
1447
|
+
// Resolve symlink to its target if applicable
|
|
1448
|
+
let targetPath = executablePath
|
|
1449
|
+
const stats = await lstat(executablePath)
|
|
1450
|
+
if (stats.isSymbolicLink()) {
|
|
1451
|
+
targetPath = await realpath(executablePath)
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1454
|
+
// checking npm prefix isn't guaranteed to work, as prefix can change
|
|
1455
|
+
// and users may set --prefix manually when installing
|
|
1456
|
+
// thus we use this heuristic:
|
|
1457
|
+
return targetPath.endsWith('.js') || targetPath.includes('node_modules')
|
|
1458
|
+
}
|
|
1459
|
+
|
|
1460
|
+
/**
|
|
1461
|
+
* Remove the claude symlink from the executable directory
|
|
1462
|
+
* This is used when switching away from native installation
|
|
1463
|
+
* Will only remove if it's a native binary symlink, not npm-managed JS files
|
|
1464
|
+
*/
|
|
1465
|
+
export async function removeInstalledSymlink(): Promise<void> {
|
|
1466
|
+
const dirs = getBaseDirectories()
|
|
1467
|
+
|
|
1468
|
+
try {
|
|
1469
|
+
// Check if this is an npm-managed installation
|
|
1470
|
+
if (await isNpmSymlink(dirs.executable)) {
|
|
1471
|
+
logForDebugging(
|
|
1472
|
+
`Skipping removal of ${dirs.executable} - appears to be npm-managed`,
|
|
1473
|
+
)
|
|
1474
|
+
return
|
|
1475
|
+
}
|
|
1476
|
+
|
|
1477
|
+
// It's a native binary symlink, safe to remove
|
|
1478
|
+
await unlink(dirs.executable)
|
|
1479
|
+
logForDebugging(`Removed claude symlink at ${dirs.executable}`)
|
|
1480
|
+
} catch (error) {
|
|
1481
|
+
if (isENOENT(error)) {
|
|
1482
|
+
return
|
|
1483
|
+
}
|
|
1484
|
+
logError(new Error(`Failed to remove claude symlink: ${error}`))
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1488
|
+
/**
|
|
1489
|
+
* Clean up old claude aliases from shell configuration files
|
|
1490
|
+
* Only handles alias removal, not PATH setup
|
|
1491
|
+
*/
|
|
1492
|
+
export async function cleanupShellAliases(): Promise<SetupMessage[]> {
|
|
1493
|
+
const messages: SetupMessage[] = []
|
|
1494
|
+
const configMap = getShellConfigPaths()
|
|
1495
|
+
|
|
1496
|
+
for (const [shellType, configFile] of Object.entries(configMap)) {
|
|
1497
|
+
try {
|
|
1498
|
+
const lines = await readFileLines(configFile)
|
|
1499
|
+
if (!lines) continue
|
|
1500
|
+
|
|
1501
|
+
const { filtered, hadAlias } = filterClaudeAliases(lines)
|
|
1502
|
+
|
|
1503
|
+
if (hadAlias) {
|
|
1504
|
+
await writeFileLines(configFile, filtered)
|
|
1505
|
+
messages.push({
|
|
1506
|
+
message: `Removed claude alias from ${configFile}. Run: unalias claude`,
|
|
1507
|
+
userActionRequired: true,
|
|
1508
|
+
type: 'alias',
|
|
1509
|
+
})
|
|
1510
|
+
logForDebugging(`Cleaned up claude alias from ${shellType} config`)
|
|
1511
|
+
}
|
|
1512
|
+
} catch (error) {
|
|
1513
|
+
logError(error)
|
|
1514
|
+
messages.push({
|
|
1515
|
+
message: `Failed to clean up ${configFile}: ${error}`,
|
|
1516
|
+
userActionRequired: false,
|
|
1517
|
+
type: 'error',
|
|
1518
|
+
})
|
|
1519
|
+
}
|
|
1520
|
+
}
|
|
1521
|
+
|
|
1522
|
+
return messages
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1525
|
+
async function manualRemoveNpmPackage(
|
|
1526
|
+
packageName: string,
|
|
1527
|
+
): Promise<{ success: boolean; error?: string; warning?: string }> {
|
|
1528
|
+
try {
|
|
1529
|
+
// Get npm global prefix
|
|
1530
|
+
const prefixResult = await execFileNoThrowWithCwd('npm', [
|
|
1531
|
+
'config',
|
|
1532
|
+
'get',
|
|
1533
|
+
'prefix',
|
|
1534
|
+
])
|
|
1535
|
+
if (prefixResult.code !== 0 || !prefixResult.stdout) {
|
|
1536
|
+
return {
|
|
1537
|
+
success: false,
|
|
1538
|
+
error: 'Failed to get npm global prefix',
|
|
1539
|
+
}
|
|
1540
|
+
}
|
|
1541
|
+
|
|
1542
|
+
const globalPrefix = prefixResult.stdout.trim()
|
|
1543
|
+
let manuallyRemoved = false
|
|
1544
|
+
|
|
1545
|
+
// Helper to try removing a file. unlink alone is sufficient — it throws
|
|
1546
|
+
// ENOENT if the file is missing, which the catch handles identically.
|
|
1547
|
+
// A stat() pre-check would add a syscall and a TOCTOU window where
|
|
1548
|
+
// concurrent cleanup causes a false-negative return.
|
|
1549
|
+
async function tryRemove(filePath: string, description: string) {
|
|
1550
|
+
try {
|
|
1551
|
+
await unlink(filePath)
|
|
1552
|
+
logForDebugging(`Manually removed ${description}: ${filePath}`)
|
|
1553
|
+
return true
|
|
1554
|
+
} catch {
|
|
1555
|
+
return false
|
|
1556
|
+
}
|
|
1557
|
+
}
|
|
1558
|
+
|
|
1559
|
+
if (getPlatform().startsWith('win32')) {
|
|
1560
|
+
// Windows - only remove executables, not the package directory
|
|
1561
|
+
const binCmd = join(globalPrefix, 'claude.cmd')
|
|
1562
|
+
const binPs1 = join(globalPrefix, 'claude.ps1')
|
|
1563
|
+
const binExe = join(globalPrefix, 'claude')
|
|
1564
|
+
|
|
1565
|
+
if (await tryRemove(binCmd, 'bin script')) {
|
|
1566
|
+
manuallyRemoved = true
|
|
1567
|
+
}
|
|
1568
|
+
|
|
1569
|
+
if (await tryRemove(binPs1, 'PowerShell script')) {
|
|
1570
|
+
manuallyRemoved = true
|
|
1571
|
+
}
|
|
1572
|
+
|
|
1573
|
+
if (await tryRemove(binExe, 'bin executable')) {
|
|
1574
|
+
manuallyRemoved = true
|
|
1575
|
+
}
|
|
1576
|
+
} else {
|
|
1577
|
+
// Unix/Mac - only remove symlink, not the package directory
|
|
1578
|
+
const binSymlink = join(globalPrefix, 'bin', 'claude')
|
|
1579
|
+
|
|
1580
|
+
if (await tryRemove(binSymlink, 'bin symlink')) {
|
|
1581
|
+
manuallyRemoved = true
|
|
1582
|
+
}
|
|
1583
|
+
}
|
|
1584
|
+
|
|
1585
|
+
if (manuallyRemoved) {
|
|
1586
|
+
logForDebugging(`Successfully removed ${packageName} manually`)
|
|
1587
|
+
const nodeModulesPath = getPlatform().startsWith('win32')
|
|
1588
|
+
? join(globalPrefix, 'node_modules', packageName)
|
|
1589
|
+
: join(globalPrefix, 'lib', 'node_modules', packageName)
|
|
1590
|
+
|
|
1591
|
+
return {
|
|
1592
|
+
success: true,
|
|
1593
|
+
warning: `${packageName} executables removed, but node_modules directory was left intact for safety. You may manually delete it later at: ${nodeModulesPath}`,
|
|
1594
|
+
}
|
|
1595
|
+
} else {
|
|
1596
|
+
return { success: false }
|
|
1597
|
+
}
|
|
1598
|
+
} catch (manualError) {
|
|
1599
|
+
logForDebugging(`Manual removal failed: ${manualError}`, {
|
|
1600
|
+
level: 'error',
|
|
1601
|
+
})
|
|
1602
|
+
return {
|
|
1603
|
+
success: false,
|
|
1604
|
+
error: `Manual removal failed: ${manualError}`,
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1608
|
+
|
|
1609
|
+
async function attemptNpmUninstall(
|
|
1610
|
+
packageName: string,
|
|
1611
|
+
): Promise<{ success: boolean; error?: string; warning?: string }> {
|
|
1612
|
+
const { code, stderr } = await execFileNoThrowWithCwd(
|
|
1613
|
+
'npm',
|
|
1614
|
+
['uninstall', '-g', packageName],
|
|
1615
|
+
// eslint-disable-next-line custom-rules/no-process-cwd -- matches original behavior
|
|
1616
|
+
{ cwd: process.cwd() },
|
|
1617
|
+
)
|
|
1618
|
+
|
|
1619
|
+
if (code === 0) {
|
|
1620
|
+
logForDebugging(`Removed global npm installation of ${packageName}`)
|
|
1621
|
+
return { success: true }
|
|
1622
|
+
} else if (stderr && !stderr.includes('npm ERR! code E404')) {
|
|
1623
|
+
// Check for ENOTEMPTY error and try manual removal
|
|
1624
|
+
if (stderr.includes('npm error code ENOTEMPTY')) {
|
|
1625
|
+
logForDebugging(
|
|
1626
|
+
`Failed to uninstall global npm package ${packageName}: ${stderr}`,
|
|
1627
|
+
{ level: 'error' },
|
|
1628
|
+
)
|
|
1629
|
+
logForDebugging(`Attempting manual removal due to ENOTEMPTY error`)
|
|
1630
|
+
|
|
1631
|
+
const manualResult = await manualRemoveNpmPackage(packageName)
|
|
1632
|
+
if (manualResult.success) {
|
|
1633
|
+
return { success: true, warning: manualResult.warning }
|
|
1634
|
+
} else if (manualResult.error) {
|
|
1635
|
+
return {
|
|
1636
|
+
success: false,
|
|
1637
|
+
error: `Failed to remove global npm installation of ${packageName}: ${stderr}. Manual removal also failed: ${manualResult.error}`,
|
|
1638
|
+
}
|
|
1639
|
+
}
|
|
1640
|
+
}
|
|
1641
|
+
|
|
1642
|
+
// Only report as error if it's not a "package not found" error
|
|
1643
|
+
logForDebugging(
|
|
1644
|
+
`Failed to uninstall global npm package ${packageName}: ${stderr}`,
|
|
1645
|
+
{ level: 'error' },
|
|
1646
|
+
)
|
|
1647
|
+
return {
|
|
1648
|
+
success: false,
|
|
1649
|
+
error: `Failed to remove global npm installation of ${packageName}: ${stderr}`,
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1652
|
+
|
|
1653
|
+
return { success: false } // Package not found, not an error
|
|
1654
|
+
}
|
|
1655
|
+
|
|
1656
|
+
export async function cleanupNpmInstallations(): Promise<{
|
|
1657
|
+
removed: number
|
|
1658
|
+
errors: string[]
|
|
1659
|
+
warnings: string[]
|
|
1660
|
+
}> {
|
|
1661
|
+
const errors: string[] = []
|
|
1662
|
+
const warnings: string[] = []
|
|
1663
|
+
let removed = 0
|
|
1664
|
+
|
|
1665
|
+
// Always attempt to remove @anthropic-ai/claude-code
|
|
1666
|
+
const codePackageResult = await attemptNpmUninstall(
|
|
1667
|
+
'@anthropic-ai/claude-code',
|
|
1668
|
+
)
|
|
1669
|
+
if (codePackageResult.success) {
|
|
1670
|
+
removed++
|
|
1671
|
+
if (codePackageResult.warning) {
|
|
1672
|
+
warnings.push(codePackageResult.warning)
|
|
1673
|
+
}
|
|
1674
|
+
} else if (codePackageResult.error) {
|
|
1675
|
+
errors.push(codePackageResult.error)
|
|
1676
|
+
}
|
|
1677
|
+
|
|
1678
|
+
// Also attempt to remove MACRO.PACKAGE_URL if it's defined and different
|
|
1679
|
+
if (MACRO.PACKAGE_URL && MACRO.PACKAGE_URL !== '@anthropic-ai/claude-code') {
|
|
1680
|
+
const macroPackageResult = await attemptNpmUninstall(MACRO.PACKAGE_URL)
|
|
1681
|
+
if (macroPackageResult.success) {
|
|
1682
|
+
removed++
|
|
1683
|
+
if (macroPackageResult.warning) {
|
|
1684
|
+
warnings.push(macroPackageResult.warning)
|
|
1685
|
+
}
|
|
1686
|
+
} else if (macroPackageResult.error) {
|
|
1687
|
+
errors.push(macroPackageResult.error)
|
|
1688
|
+
}
|
|
1689
|
+
}
|
|
1690
|
+
|
|
1691
|
+
// Check for local installation at ~/.claude/local
|
|
1692
|
+
const localInstallDir = join(homedir(), '.claude', 'local')
|
|
1693
|
+
|
|
1694
|
+
try {
|
|
1695
|
+
await rm(localInstallDir, { recursive: true })
|
|
1696
|
+
removed++
|
|
1697
|
+
logForDebugging(`Removed local installation at ${localInstallDir}`)
|
|
1698
|
+
} catch (error) {
|
|
1699
|
+
if (!isENOENT(error)) {
|
|
1700
|
+
errors.push(`Failed to remove ${localInstallDir}: ${error}`)
|
|
1701
|
+
logForDebugging(`Failed to remove local installation: ${error}`, {
|
|
1702
|
+
level: 'error',
|
|
1703
|
+
})
|
|
1704
|
+
}
|
|
1705
|
+
}
|
|
1706
|
+
|
|
1707
|
+
return { removed, errors, warnings }
|
|
1708
|
+
}
|