@xortex/xcode 3.0.0 → 3.0.2
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/QueryEngine.ts +1331 -0
- package/Task.ts +125 -0
- package/Tool.ts +792 -0
- package/assistant/sessionHistory.ts +87 -0
- package/bin/xcode +57 -25
- package/bridge/bridgeApi.ts +539 -0
- package/bridge/bridgeConfig.ts +48 -0
- package/bridge/bridgeDebug.ts +135 -0
- package/bridge/bridgeEnabled.ts +202 -0
- package/bridge/bridgeMain.ts +2999 -0
- package/bridge/bridgeMessaging.ts +461 -0
- package/bridge/bridgePermissionCallbacks.ts +43 -0
- package/bridge/bridgePointer.ts +210 -0
- package/bridge/bridgeStatusUtil.ts +163 -0
- package/bridge/bridgeUI.ts +530 -0
- package/bridge/capacityWake.ts +56 -0
- package/bridge/codeSessionApi.ts +168 -0
- package/bridge/createSession.ts +384 -0
- package/bridge/debugUtils.ts +141 -0
- package/bridge/envLessBridgeConfig.ts +165 -0
- package/bridge/flushGate.ts +71 -0
- package/bridge/inboundAttachments.ts +175 -0
- package/bridge/inboundMessages.ts +80 -0
- package/bridge/initReplBridge.ts +569 -0
- package/bridge/jwtUtils.ts +256 -0
- package/bridge/pollConfig.ts +110 -0
- package/bridge/pollConfigDefaults.ts +82 -0
- package/bridge/remoteBridgeCore.ts +1008 -0
- package/bridge/replBridge.ts +2406 -0
- package/bridge/replBridgeHandle.ts +36 -0
- package/bridge/replBridgeTransport.ts +370 -0
- package/bridge/sessionIdCompat.ts +57 -0
- package/bridge/sessionRunner.ts +550 -0
- package/bridge/trustedDevice.ts +210 -0
- package/bridge/types.ts +262 -0
- package/bridge/workSecret.ts +127 -0
- package/buddy/CompanionSprite.tsx +371 -0
- package/buddy/companion.ts +133 -0
- package/buddy/prompt.ts +36 -0
- package/buddy/sprites.ts +514 -0
- package/buddy/types.ts +148 -0
- package/buddy/useBuddyNotification.tsx +98 -0
- package/cli/exit.ts +31 -0
- package/cli/handlers/agents.ts +70 -0
- package/cli/handlers/auth.ts +330 -0
- package/cli/handlers/autoMode.ts +170 -0
- package/cli/handlers/mcp.tsx +362 -0
- package/cli/handlers/plugins.ts +878 -0
- package/cli/handlers/util.tsx +110 -0
- package/cli/ndjsonSafeStringify.ts +32 -0
- package/cli/print.ts +5594 -0
- package/cli/remoteIO.ts +255 -0
- package/cli/structuredIO.ts +859 -0
- package/cli/transports/HybridTransport.ts +282 -0
- package/cli/transports/SSETransport.ts +711 -0
- package/cli/transports/SerialBatchEventUploader.ts +275 -0
- package/cli/transports/WebSocketTransport.ts +800 -0
- package/cli/transports/WorkerStateUploader.ts +131 -0
- package/cli/transports/ccrClient.ts +998 -0
- package/cli/transports/transportUtils.ts +45 -0
- package/cli/update.ts +422 -0
- package/commands/add-dir/add-dir.tsx +126 -0
- package/commands/add-dir/index.ts +11 -0
- package/commands/add-dir/validation.ts +110 -0
- package/commands/advisor.ts +109 -0
- package/commands/agents/agents.tsx +12 -0
- package/commands/agents/index.ts +10 -0
- package/commands/ant-trace/index.js +1 -0
- package/commands/autofix-pr/index.js +1 -0
- package/commands/backfill-sessions/index.js +1 -0
- package/commands/branch/branch.ts +296 -0
- package/commands/branch/index.ts +14 -0
- package/commands/break-cache/index.js +1 -0
- package/commands/bridge/bridge.tsx +509 -0
- package/commands/bridge/index.ts +26 -0
- package/commands/bridge-kick.ts +200 -0
- package/commands/brief.ts +130 -0
- package/commands/btw/btw.tsx +243 -0
- package/commands/btw/index.ts +13 -0
- package/commands/bughunter/index.js +1 -0
- package/commands/chrome/chrome.tsx +285 -0
- package/commands/chrome/index.ts +13 -0
- package/commands/clear/caches.ts +144 -0
- package/commands/clear/clear.ts +7 -0
- package/commands/clear/conversation.ts +251 -0
- package/commands/clear/index.ts +19 -0
- package/commands/color/color.ts +93 -0
- package/commands/color/index.ts +16 -0
- package/commands/commit-push-pr.ts +158 -0
- package/commands/commit.ts +92 -0
- package/commands/compact/compact.ts +287 -0
- package/commands/compact/index.ts +15 -0
- package/commands/config/config.tsx +7 -0
- package/commands/config/index.ts +11 -0
- package/commands/context/context-noninteractive.ts +325 -0
- package/commands/context/context.tsx +64 -0
- package/commands/context/index.ts +24 -0
- package/commands/copy/copy.tsx +371 -0
- package/commands/copy/index.ts +15 -0
- package/commands/cost/cost.ts +24 -0
- package/commands/cost/index.ts +23 -0
- package/commands/createMovedToPluginCommand.ts +65 -0
- package/commands/ctx_viz/index.js +1 -0
- package/commands/debug-tool-call/index.js +1 -0
- package/commands/desktop/desktop.tsx +9 -0
- package/commands/desktop/index.ts +26 -0
- package/commands/diff/diff.tsx +9 -0
- package/commands/diff/index.ts +8 -0
- package/commands/doctor/doctor.tsx +7 -0
- package/commands/doctor/index.ts +12 -0
- package/commands/effort/effort.tsx +183 -0
- package/commands/effort/index.ts +13 -0
- package/commands/env/index.js +1 -0
- package/commands/exit/exit.tsx +33 -0
- package/commands/exit/index.ts +12 -0
- package/commands/export/export.tsx +91 -0
- package/commands/export/index.ts +11 -0
- package/commands/extra-usage/extra-usage-core.ts +118 -0
- package/commands/extra-usage/extra-usage-noninteractive.ts +16 -0
- package/commands/extra-usage/extra-usage.tsx +17 -0
- package/commands/extra-usage/index.ts +31 -0
- package/commands/fast/fast.tsx +269 -0
- package/commands/fast/index.ts +26 -0
- package/commands/feedback/feedback.tsx +25 -0
- package/commands/feedback/index.ts +26 -0
- package/commands/files/files.ts +19 -0
- package/commands/files/index.ts +12 -0
- package/commands/good-claude/index.js +1 -0
- package/commands/heapdump/heapdump.ts +17 -0
- package/commands/heapdump/index.ts +12 -0
- package/commands/help/help.tsx +11 -0
- package/commands/help/index.ts +10 -0
- package/commands/hooks/hooks.tsx +13 -0
- package/commands/hooks/index.ts +11 -0
- package/commands/ide/ide.tsx +646 -0
- package/commands/ide/index.ts +11 -0
- package/commands/init-verifiers.ts +262 -0
- package/commands/init.ts +256 -0
- package/commands/insights.ts +3200 -0
- package/commands/install-github-app/ApiKeyStep.tsx +231 -0
- package/commands/install-github-app/CheckExistingSecretStep.tsx +190 -0
- package/commands/install-github-app/CheckGitHubStep.tsx +15 -0
- package/commands/install-github-app/ChooseRepoStep.tsx +211 -0
- package/commands/install-github-app/CreatingStep.tsx +65 -0
- package/commands/install-github-app/ErrorStep.tsx +85 -0
- package/commands/install-github-app/ExistingWorkflowStep.tsx +103 -0
- package/commands/install-github-app/InstallAppStep.tsx +94 -0
- package/commands/install-github-app/OAuthFlowStep.tsx +276 -0
- package/commands/install-github-app/SuccessStep.tsx +96 -0
- package/commands/install-github-app/WarningsStep.tsx +73 -0
- package/commands/install-github-app/index.ts +13 -0
- package/commands/install-github-app/install-github-app.tsx +587 -0
- package/commands/install-github-app/setupGitHubActions.ts +325 -0
- package/commands/install-slack-app/index.ts +12 -0
- package/commands/install-slack-app/install-slack-app.ts +30 -0
- package/commands/install.tsx +300 -0
- package/commands/issue/index.js +1 -0
- package/commands/keybindings/index.ts +13 -0
- package/commands/keybindings/keybindings.ts +53 -0
- package/commands/login/index.ts +14 -0
- package/commands/login/login.tsx +104 -0
- package/commands/logout/index.ts +10 -0
- package/commands/logout/logout.tsx +82 -0
- package/commands/mcp/addCommand.ts +280 -0
- package/commands/mcp/index.ts +12 -0
- package/commands/mcp/mcp.tsx +85 -0
- package/commands/mcp/xaaIdpCommand.ts +266 -0
- package/commands/memory/index.ts +10 -0
- package/commands/memory/memory.tsx +90 -0
- package/commands/mobile/index.ts +11 -0
- package/commands/mobile/mobile.tsx +274 -0
- package/commands/mock-limits/index.js +1 -0
- package/commands/model/index.ts +16 -0
- package/commands/model/model.tsx +297 -0
- package/commands/oauth-refresh/index.js +1 -0
- package/commands/onboarding/index.js +1 -0
- package/commands/output-style/index.ts +11 -0
- package/commands/output-style/output-style.tsx +7 -0
- package/commands/passes/index.ts +22 -0
- package/commands/passes/passes.tsx +24 -0
- package/commands/perf-issue/index.js +1 -0
- package/commands/permissions/index.ts +11 -0
- package/commands/permissions/permissions.tsx +10 -0
- package/commands/plan/index.ts +11 -0
- package/commands/plan/plan.tsx +122 -0
- package/commands/plugin/AddMarketplace.tsx +162 -0
- package/commands/plugin/BrowseMarketplace.tsx +802 -0
- package/commands/plugin/DiscoverPlugins.tsx +781 -0
- package/commands/plugin/ManageMarketplaces.tsx +838 -0
- package/commands/plugin/ManagePlugins.tsx +2215 -0
- package/commands/plugin/PluginErrors.tsx +124 -0
- package/commands/plugin/PluginOptionsDialog.tsx +357 -0
- package/commands/plugin/PluginOptionsFlow.tsx +135 -0
- package/commands/plugin/PluginSettings.tsx +1072 -0
- package/commands/plugin/PluginTrustWarning.tsx +32 -0
- package/commands/plugin/UnifiedInstalledCell.tsx +565 -0
- package/commands/plugin/ValidatePlugin.tsx +98 -0
- package/commands/plugin/index.tsx +11 -0
- package/commands/plugin/parseArgs.ts +103 -0
- package/commands/plugin/plugin.tsx +7 -0
- package/commands/plugin/pluginDetailsHelpers.tsx +117 -0
- package/commands/plugin/usePagination.ts +171 -0
- package/commands/pr_comments/index.ts +50 -0
- package/commands/privacy-settings/index.ts +14 -0
- package/commands/privacy-settings/privacy-settings.tsx +58 -0
- package/commands/rate-limit-options/index.ts +19 -0
- package/commands/rate-limit-options/rate-limit-options.tsx +210 -0
- package/commands/release-notes/index.ts +11 -0
- package/commands/release-notes/release-notes.ts +50 -0
- package/commands/reload-plugins/index.ts +18 -0
- package/commands/reload-plugins/reload-plugins.ts +61 -0
- package/commands/remote-env/index.ts +15 -0
- package/commands/remote-env/remote-env.tsx +7 -0
- package/commands/remote-setup/api.ts +182 -0
- package/commands/remote-setup/index.ts +20 -0
- package/commands/remote-setup/remote-setup.tsx +187 -0
- package/commands/rename/generateSessionName.ts +67 -0
- package/commands/rename/index.ts +12 -0
- package/commands/rename/rename.ts +87 -0
- package/commands/reset-limits/index.js +4 -0
- package/commands/resume/index.ts +12 -0
- package/commands/resume/resume.tsx +275 -0
- package/commands/review/UltrareviewOverageDialog.tsx +96 -0
- package/commands/review/reviewRemote.ts +316 -0
- package/commands/review/ultrareviewCommand.tsx +58 -0
- package/commands/review/ultrareviewEnabled.ts +14 -0
- package/commands/review.ts +57 -0
- package/commands/rewind/index.ts +13 -0
- package/commands/rewind/rewind.ts +13 -0
- package/commands/sandbox-toggle/index.ts +50 -0
- package/commands/sandbox-toggle/sandbox-toggle.tsx +83 -0
- package/commands/security-review.ts +243 -0
- package/commands/session/index.ts +16 -0
- package/commands/session/session.tsx +140 -0
- package/commands/share/index.js +1 -0
- package/commands/skills/index.ts +10 -0
- package/commands/skills/skills.tsx +8 -0
- package/commands/stats/index.ts +10 -0
- package/commands/stats/stats.tsx +7 -0
- package/commands/status/index.ts +12 -0
- package/commands/status/status.tsx +8 -0
- package/commands/statusline.tsx +24 -0
- package/commands/stickers/index.ts +11 -0
- package/commands/stickers/stickers.ts +16 -0
- package/commands/summary/index.js +1 -0
- package/commands/tag/index.ts +12 -0
- package/commands/tag/tag.tsx +215 -0
- package/commands/tasks/index.ts +11 -0
- package/commands/tasks/tasks.tsx +8 -0
- package/commands/teleport/index.js +1 -0
- package/commands/terminalSetup/index.ts +23 -0
- package/commands/terminalSetup/terminalSetup.tsx +531 -0
- package/commands/theme/index.ts +10 -0
- package/commands/theme/theme.tsx +57 -0
- package/commands/thinkback/index.ts +13 -0
- package/commands/thinkback/thinkback.tsx +554 -0
- package/commands/thinkback-play/index.ts +17 -0
- package/commands/thinkback-play/thinkback-play.ts +43 -0
- package/commands/ultraplan.tsx +471 -0
- package/commands/upgrade/index.ts +16 -0
- package/commands/upgrade/upgrade.tsx +38 -0
- package/commands/usage/index.ts +9 -0
- package/commands/usage/usage.tsx +7 -0
- package/commands/version.ts +22 -0
- package/commands/vim/index.ts +11 -0
- package/commands/vim/vim.ts +38 -0
- package/commands/voice/index.ts +20 -0
- package/commands/voice/voice.ts +150 -0
- package/commands/xingest/index.ts +11 -0
- package/commands/xingest/xingest.ts +90 -0
- package/commands/xsearch/index.ts +11 -0
- package/commands/xsearch/xsearch.ts +56 -0
- package/commands.ts +758 -0
- package/components/AgentProgressLine.tsx +136 -0
- package/components/App.tsx +56 -0
- package/components/ApproveApiKey.tsx +123 -0
- package/components/AutoModeOptInDialog.tsx +142 -0
- package/components/AutoUpdater.tsx +198 -0
- package/components/AutoUpdaterWrapper.tsx +91 -0
- package/components/AwsAuthStatusBox.tsx +82 -0
- package/components/BaseTextInput.tsx +136 -0
- package/components/BashModeProgress.tsx +56 -0
- package/components/BridgeDialog.tsx +401 -0
- package/components/BypassPermissionsModeDialog.tsx +87 -0
- package/components/ChannelDowngradeDialog.tsx +102 -0
- package/components/ClaudeCodeHint/PluginHintMenu.tsx +78 -0
- package/components/ClaudeInChromeOnboarding.tsx +121 -0
- package/components/ClaudeMdExternalIncludesDialog.tsx +137 -0
- package/components/ClickableImageRef.tsx +73 -0
- package/components/CompactSummary.tsx +118 -0
- package/components/ConfigurableShortcutHint.tsx +57 -0
- package/components/ConsoleOAuthFlow.tsx +631 -0
- package/components/ContextSuggestions.tsx +47 -0
- package/components/ContextVisualization.tsx +489 -0
- package/components/CoordinatorAgentStatus.tsx +273 -0
- package/components/CostThresholdDialog.tsx +50 -0
- package/components/CtrlOToExpand.tsx +51 -0
- package/components/CustomSelect/SelectMulti.tsx +213 -0
- package/components/CustomSelect/index.ts +3 -0
- package/components/CustomSelect/option-map.ts +50 -0
- package/components/CustomSelect/select-input-option.tsx +488 -0
- package/components/CustomSelect/select-option.tsx +68 -0
- package/components/CustomSelect/select.tsx +690 -0
- package/components/CustomSelect/use-multi-select-state.ts +414 -0
- package/components/CustomSelect/use-select-input.ts +287 -0
- package/components/CustomSelect/use-select-navigation.ts +653 -0
- package/components/CustomSelect/use-select-state.ts +157 -0
- package/components/DesktopHandoff.tsx +193 -0
- package/components/DesktopUpsell/DesktopUpsellStartup.tsx +171 -0
- package/components/DevBar.tsx +49 -0
- package/components/DevChannelsDialog.tsx +105 -0
- package/components/DiagnosticsDisplay.tsx +95 -0
- package/components/EffortCallout.tsx +265 -0
- package/components/EffortIndicator.ts +42 -0
- package/components/ExitFlow.tsx +48 -0
- package/components/ExportDialog.tsx +128 -0
- package/components/FallbackToolUseErrorMessage.tsx +116 -0
- package/components/FallbackToolUseRejectedMessage.tsx +16 -0
- package/components/FastIcon.tsx +46 -0
- package/components/Feedback.tsx +592 -0
- package/components/FeedbackSurvey/FeedbackSurvey.tsx +174 -0
- package/components/FeedbackSurvey/FeedbackSurveyView.tsx +108 -0
- package/components/FeedbackSurvey/TranscriptSharePrompt.tsx +88 -0
- package/components/FeedbackSurvey/submitTranscriptShare.ts +112 -0
- package/components/FeedbackSurvey/useDebouncedDigitInput.ts +82 -0
- package/components/FeedbackSurvey/useFeedbackSurvey.tsx +296 -0
- package/components/FeedbackSurvey/useMemorySurvey.tsx +213 -0
- package/components/FeedbackSurvey/usePostCompactSurvey.tsx +206 -0
- package/components/FeedbackSurvey/useSurveyState.tsx +100 -0
- package/components/FileEditToolDiff.tsx +181 -0
- package/components/FileEditToolUpdatedMessage.tsx +124 -0
- package/components/FileEditToolUseRejectedMessage.tsx +170 -0
- package/components/FilePathLink.tsx +43 -0
- package/components/FullscreenLayout.tsx +645 -0
- package/components/GlobalSearchDialog.tsx +343 -0
- package/components/HelpV2/Commands.tsx +82 -0
- package/components/HelpV2/General.tsx +23 -0
- package/components/HelpV2/HelpV2.tsx +184 -0
- package/components/HighlightedCode/Fallback.tsx +193 -0
- package/components/HighlightedCode.tsx +190 -0
- package/components/HistorySearchDialog.tsx +118 -0
- package/components/IdeAutoConnectDialog.tsx +154 -0
- package/components/IdeOnboardingDialog.tsx +167 -0
- package/components/IdeStatusIndicator.tsx +58 -0
- package/components/IdleReturnDialog.tsx +118 -0
- package/components/InterruptedByUser.tsx +15 -0
- package/components/InvalidConfigDialog.tsx +156 -0
- package/components/InvalidSettingsDialog.tsx +89 -0
- package/components/KeybindingWarnings.tsx +55 -0
- package/components/LanguagePicker.tsx +86 -0
- package/components/LogSelector.tsx +1575 -0
- package/components/LogoV2/AnimatedAsterisk.tsx +50 -0
- package/components/LogoV2/AnimatedClawd.tsx +124 -0
- package/components/LogoV2/ChannelsNotice.tsx +266 -0
- package/components/LogoV2/Clawd.tsx +14 -0
- package/components/LogoV2/CondensedLogo.tsx +161 -0
- package/components/LogoV2/EmergencyTip.tsx +58 -0
- package/components/LogoV2/Feed.tsx +112 -0
- package/components/LogoV2/FeedColumn.tsx +59 -0
- package/components/LogoV2/GuestPassesUpsell.tsx +70 -0
- package/components/LogoV2/LogoV2.tsx +543 -0
- package/components/LogoV2/Opus1mMergeNotice.tsx +55 -0
- package/components/LogoV2/OverageCreditUpsell.tsx +166 -0
- package/components/LogoV2/VoiceModeNotice.tsx +68 -0
- package/components/LogoV2/WelcomeV2.tsx +433 -0
- package/components/LogoV2/feedConfigs.tsx +92 -0
- package/components/LspRecommendation/LspRecommendationMenu.tsx +88 -0
- package/components/MCPServerApprovalDialog.tsx +115 -0
- package/components/MCPServerDesktopImportDialog.tsx +203 -0
- package/components/MCPServerDialogCopy.tsx +15 -0
- package/components/MCPServerMultiselectDialog.tsx +133 -0
- package/components/ManagedSettingsSecurityDialog/ManagedSettingsSecurityDialog.tsx +149 -0
- package/components/ManagedSettingsSecurityDialog/utils.ts +144 -0
- package/components/Markdown.tsx +236 -0
- package/components/MarkdownTable.tsx +322 -0
- package/components/MemoryUsageIndicator.tsx +37 -0
- package/components/Message.tsx +627 -0
- package/components/MessageModel.tsx +43 -0
- package/components/MessageResponse.tsx +78 -0
- package/components/MessageRow.tsx +383 -0
- package/components/MessageSelector.tsx +831 -0
- package/components/MessageTimestamp.tsx +63 -0
- package/components/Messages.tsx +834 -0
- package/components/ModelPicker.tsx +448 -0
- package/components/NativeAutoUpdater.tsx +193 -0
- package/components/NotebookEditToolUseRejectedMessage.tsx +92 -0
- package/components/OffscreenFreeze.tsx +44 -0
- package/components/Onboarding.tsx +244 -0
- package/components/OutputStylePicker.tsx +112 -0
- package/components/PackageManagerAutoUpdater.tsx +104 -0
- package/components/Passes/Passes.tsx +184 -0
- package/components/PrBadge.tsx +97 -0
- package/components/PressEnterToContinue.tsx +15 -0
- package/components/PromptInput/HistorySearchInput.tsx +51 -0
- package/components/PromptInput/IssueFlagBanner.tsx +12 -0
- package/components/PromptInput/Notifications.tsx +332 -0
- package/components/PromptInput/PromptInput.tsx +2350 -0
- package/components/PromptInput/PromptInputFooter.tsx +191 -0
- package/components/PromptInput/PromptInputFooterLeftSide.tsx +524 -0
- package/components/PromptInput/PromptInputFooterSuggestions.tsx +293 -0
- package/components/PromptInput/PromptInputHelpMenu.tsx +358 -0
- package/components/PromptInput/PromptInputModeIndicator.tsx +93 -0
- package/components/PromptInput/PromptInputQueuedCommands.tsx +117 -0
- package/components/PromptInput/PromptInputStashNotice.tsx +25 -0
- package/components/PromptInput/SandboxPromptFooterHint.tsx +64 -0
- package/components/PromptInput/ShimmeredInput.tsx +143 -0
- package/components/PromptInput/VoiceIndicator.tsx +137 -0
- package/components/PromptInput/inputModes.ts +33 -0
- package/components/PromptInput/inputPaste.ts +90 -0
- package/components/PromptInput/useMaybeTruncateInput.ts +58 -0
- package/components/PromptInput/usePromptInputPlaceholder.ts +78 -0
- package/components/PromptInput/useShowFastIconHint.ts +31 -0
- package/components/PromptInput/useSwarmBanner.ts +155 -0
- package/components/PromptInput/utils.ts +60 -0
- package/components/QuickOpenDialog.tsx +244 -0
- package/components/RemoteCallout.tsx +76 -0
- package/components/RemoteEnvironmentDialog.tsx +340 -0
- package/components/ResumeTask.tsx +268 -0
- package/components/SandboxViolationExpandedView.tsx +99 -0
- package/components/ScrollKeybindingHandler.tsx +1012 -0
- package/components/SearchBox.tsx +72 -0
- package/components/SentryErrorBoundary.ts +28 -0
- package/components/SessionBackgroundHint.tsx +108 -0
- package/components/SessionPreview.tsx +194 -0
- package/components/Settings/Config.tsx +1822 -0
- package/components/Settings/Settings.tsx +137 -0
- package/components/Settings/Status.tsx +241 -0
- package/components/Settings/Usage.tsx +377 -0
- package/components/ShowInIDEPrompt.tsx +170 -0
- package/components/SkillImprovementSurvey.tsx +152 -0
- package/components/Spinner/FlashingChar.tsx +61 -0
- package/components/Spinner/GlimmerMessage.tsx +328 -0
- package/components/Spinner/ShimmerChar.tsx +36 -0
- package/components/Spinner/SpinnerAnimationRow.tsx +265 -0
- package/components/Spinner/SpinnerGlyph.tsx +80 -0
- package/components/Spinner/TeammateSpinnerLine.tsx +233 -0
- package/components/Spinner/TeammateSpinnerTree.tsx +272 -0
- package/components/Spinner/index.ts +10 -0
- package/components/Spinner/teammateSelectHint.ts +1 -0
- package/components/Spinner/useShimmerAnimation.ts +31 -0
- package/components/Spinner/useStalledAnimation.ts +75 -0
- package/components/Spinner/utils.ts +84 -0
- package/components/Spinner.tsx +562 -0
- package/components/Stats.tsx +1228 -0
- package/components/StatusLine.tsx +324 -0
- package/components/StatusNotices.tsx +55 -0
- package/components/StructuredDiff/Fallback.tsx +487 -0
- package/components/StructuredDiff/colorDiff.ts +37 -0
- package/components/StructuredDiff.tsx +190 -0
- package/components/StructuredDiffList.tsx +30 -0
- package/components/TagTabs.tsx +139 -0
- package/components/TaskListV2.tsx +378 -0
- package/components/TeammateViewHeader.tsx +82 -0
- package/components/TeleportError.tsx +189 -0
- package/components/TeleportProgress.tsx +140 -0
- package/components/TeleportRepoMismatchDialog.tsx +104 -0
- package/components/TeleportResumeWrapper.tsx +167 -0
- package/components/TeleportStash.tsx +116 -0
- package/components/TextInput.tsx +124 -0
- package/components/ThemePicker.tsx +333 -0
- package/components/ThinkingToggle.tsx +153 -0
- package/components/TokenWarning.tsx +179 -0
- package/components/ToolUseLoader.tsx +42 -0
- package/components/TrustDialog/TrustDialog.tsx +290 -0
- package/components/TrustDialog/utils.ts +245 -0
- package/components/ValidationErrorsList.tsx +148 -0
- package/components/VimTextInput.tsx +140 -0
- package/components/VirtualMessageList.tsx +1082 -0
- package/components/WorkflowMultiselectDialog.tsx +128 -0
- package/components/WorktreeExitDialog.tsx +231 -0
- package/components/agents/AgentDetail.tsx +220 -0
- package/components/agents/AgentEditor.tsx +178 -0
- package/components/agents/AgentNavigationFooter.tsx +26 -0
- package/components/agents/AgentsList.tsx +440 -0
- package/components/agents/AgentsMenu.tsx +800 -0
- package/components/agents/ColorPicker.tsx +112 -0
- package/components/agents/ModelSelector.tsx +68 -0
- package/components/agents/ToolSelector.tsx +562 -0
- package/components/agents/agentFileUtils.ts +272 -0
- package/components/agents/generateAgent.ts +197 -0
- package/components/agents/new-agent-creation/CreateAgentWizard.tsx +97 -0
- package/components/agents/new-agent-creation/wizard-steps/ColorStep.tsx +84 -0
- package/components/agents/new-agent-creation/wizard-steps/ConfirmStep.tsx +378 -0
- package/components/agents/new-agent-creation/wizard-steps/ConfirmStepWrapper.tsx +74 -0
- package/components/agents/new-agent-creation/wizard-steps/DescriptionStep.tsx +123 -0
- package/components/agents/new-agent-creation/wizard-steps/GenerateStep.tsx +143 -0
- package/components/agents/new-agent-creation/wizard-steps/LocationStep.tsx +80 -0
- package/components/agents/new-agent-creation/wizard-steps/MemoryStep.tsx +113 -0
- package/components/agents/new-agent-creation/wizard-steps/MethodStep.tsx +80 -0
- package/components/agents/new-agent-creation/wizard-steps/ModelStep.tsx +52 -0
- package/components/agents/new-agent-creation/wizard-steps/PromptStep.tsx +128 -0
- package/components/agents/new-agent-creation/wizard-steps/ToolsStep.tsx +61 -0
- package/components/agents/new-agent-creation/wizard-steps/TypeStep.tsx +103 -0
- package/components/agents/types.ts +27 -0
- package/components/agents/utils.ts +18 -0
- package/components/agents/validateAgent.ts +109 -0
- package/components/design-system/Byline.tsx +77 -0
- package/components/design-system/Dialog.tsx +138 -0
- package/components/design-system/Divider.tsx +149 -0
- package/components/design-system/FuzzyPicker.tsx +312 -0
- package/components/design-system/KeyboardShortcutHint.tsx +81 -0
- package/components/design-system/ListItem.tsx +244 -0
- package/components/design-system/LoadingState.tsx +94 -0
- package/components/design-system/Pane.tsx +77 -0
- package/components/design-system/ProgressBar.tsx +86 -0
- package/components/design-system/Ratchet.tsx +80 -0
- package/components/design-system/StatusIcon.tsx +95 -0
- package/components/design-system/Tabs.tsx +340 -0
- package/components/design-system/ThemeProvider.tsx +170 -0
- package/components/design-system/ThemedBox.tsx +156 -0
- package/components/design-system/ThemedText.tsx +124 -0
- package/components/design-system/color.ts +30 -0
- package/components/diff/DiffDetailView.tsx +281 -0
- package/components/diff/DiffDialog.tsx +383 -0
- package/components/diff/DiffFileList.tsx +292 -0
- package/components/grove/Grove.tsx +463 -0
- package/components/hooks/HooksConfigMenu.tsx +578 -0
- package/components/hooks/PromptDialog.tsx +90 -0
- package/components/hooks/SelectEventMode.tsx +127 -0
- package/components/hooks/SelectHookMode.tsx +112 -0
- package/components/hooks/SelectMatcherMode.tsx +144 -0
- package/components/hooks/ViewHookMode.tsx +199 -0
- package/components/mcp/CapabilitiesSection.tsx +61 -0
- package/components/mcp/ElicitationDialog.tsx +1169 -0
- package/components/mcp/MCPAgentServerMenu.tsx +183 -0
- package/components/mcp/MCPListPanel.tsx +504 -0
- package/components/mcp/MCPReconnect.tsx +167 -0
- package/components/mcp/MCPRemoteServerMenu.tsx +649 -0
- package/components/mcp/MCPSettings.tsx +398 -0
- package/components/mcp/MCPStdioServerMenu.tsx +177 -0
- package/components/mcp/MCPToolDetailView.tsx +212 -0
- package/components/mcp/MCPToolListView.tsx +141 -0
- package/components/mcp/McpParsingWarnings.tsx +213 -0
- package/components/mcp/index.ts +9 -0
- package/components/mcp/utils/reconnectHelpers.tsx +49 -0
- package/components/memory/MemoryFileSelector.tsx +438 -0
- package/components/memory/MemoryUpdateNotification.tsx +45 -0
- package/components/messageActions.tsx +450 -0
- package/components/messages/AdvisorMessage.tsx +158 -0
- package/components/messages/AssistantRedactedThinkingMessage.tsx +31 -0
- package/components/messages/AssistantTextMessage.tsx +270 -0
- package/components/messages/AssistantThinkingMessage.tsx +86 -0
- package/components/messages/AssistantToolUseMessage.tsx +368 -0
- package/components/messages/AttachmentMessage.tsx +536 -0
- package/components/messages/CollapsedReadSearchContent.tsx +484 -0
- package/components/messages/CompactBoundaryMessage.tsx +18 -0
- package/components/messages/GroupedToolUseContent.tsx +58 -0
- package/components/messages/HighlightedThinkingText.tsx +162 -0
- package/components/messages/HookProgressMessage.tsx +116 -0
- package/components/messages/PlanApprovalMessage.tsx +222 -0
- package/components/messages/RateLimitMessage.tsx +161 -0
- package/components/messages/ShutdownMessage.tsx +132 -0
- package/components/messages/SystemAPIErrorMessage.tsx +141 -0
- package/components/messages/SystemTextMessage.tsx +827 -0
- package/components/messages/TaskAssignmentMessage.tsx +76 -0
- package/components/messages/UserAgentNotificationMessage.tsx +83 -0
- package/components/messages/UserBashInputMessage.tsx +58 -0
- package/components/messages/UserBashOutputMessage.tsx +54 -0
- package/components/messages/UserChannelMessage.tsx +137 -0
- package/components/messages/UserCommandMessage.tsx +108 -0
- package/components/messages/UserImageMessage.tsx +59 -0
- package/components/messages/UserLocalCommandOutputMessage.tsx +167 -0
- package/components/messages/UserMemoryInputMessage.tsx +75 -0
- package/components/messages/UserPlanMessage.tsx +42 -0
- package/components/messages/UserPromptMessage.tsx +80 -0
- package/components/messages/UserResourceUpdateMessage.tsx +121 -0
- package/components/messages/UserTeammateMessage.tsx +206 -0
- package/components/messages/UserTextMessage.tsx +275 -0
- package/components/messages/UserToolResultMessage/RejectedPlanMessage.tsx +31 -0
- package/components/messages/UserToolResultMessage/RejectedToolUseMessage.tsx +16 -0
- package/components/messages/UserToolResultMessage/UserToolCanceledMessage.tsx +16 -0
- package/components/messages/UserToolResultMessage/UserToolErrorMessage.tsx +103 -0
- package/components/messages/UserToolResultMessage/UserToolRejectMessage.tsx +95 -0
- package/components/messages/UserToolResultMessage/UserToolResultMessage.tsx +106 -0
- package/components/messages/UserToolResultMessage/UserToolSuccessMessage.tsx +104 -0
- package/components/messages/UserToolResultMessage/utils.tsx +44 -0
- package/components/messages/nullRenderingAttachments.ts +70 -0
- package/components/messages/teamMemCollapsed.tsx +140 -0
- package/components/messages/teamMemSaved.ts +19 -0
- package/components/permissions/AskUserQuestionPermissionRequest/AskUserQuestionPermissionRequest.tsx +645 -0
- package/components/permissions/AskUserQuestionPermissionRequest/PreviewBox.tsx +229 -0
- package/components/permissions/AskUserQuestionPermissionRequest/PreviewQuestionView.tsx +328 -0
- package/components/permissions/AskUserQuestionPermissionRequest/QuestionNavigationBar.tsx +178 -0
- package/components/permissions/AskUserQuestionPermissionRequest/QuestionView.tsx +465 -0
- package/components/permissions/AskUserQuestionPermissionRequest/SubmitQuestionsView.tsx +144 -0
- package/components/permissions/AskUserQuestionPermissionRequest/use-multiple-choice-state.ts +179 -0
- package/components/permissions/BashPermissionRequest/BashPermissionRequest.tsx +482 -0
- package/components/permissions/BashPermissionRequest/bashToolUseOptions.tsx +147 -0
- package/components/permissions/ComputerUseApproval/ComputerUseApproval.tsx +441 -0
- package/components/permissions/EnterPlanModePermissionRequest/EnterPlanModePermissionRequest.tsx +122 -0
- package/components/permissions/ExitPlanModePermissionRequest/ExitPlanModePermissionRequest.tsx +768 -0
- package/components/permissions/FallbackPermissionRequest.tsx +333 -0
- package/components/permissions/FileEditPermissionRequest/FileEditPermissionRequest.tsx +182 -0
- package/components/permissions/FilePermissionDialog/FilePermissionDialog.tsx +204 -0
- package/components/permissions/FilePermissionDialog/ideDiffConfig.ts +42 -0
- package/components/permissions/FilePermissionDialog/permissionOptions.tsx +177 -0
- package/components/permissions/FilePermissionDialog/useFilePermissionDialog.ts +212 -0
- package/components/permissions/FilePermissionDialog/usePermissionHandler.ts +185 -0
- package/components/permissions/FileWritePermissionRequest/FileWritePermissionRequest.tsx +161 -0
- package/components/permissions/FileWritePermissionRequest/FileWriteToolDiff.tsx +89 -0
- package/components/permissions/FilesystemPermissionRequest/FilesystemPermissionRequest.tsx +115 -0
- package/components/permissions/NotebookEditPermissionRequest/NotebookEditPermissionRequest.tsx +166 -0
- package/components/permissions/NotebookEditPermissionRequest/NotebookEditToolDiff.tsx +235 -0
- package/components/permissions/PermissionDecisionDebugInfo.tsx +460 -0
- package/components/permissions/PermissionDialog.tsx +72 -0
- package/components/permissions/PermissionExplanation.tsx +272 -0
- package/components/permissions/PermissionPrompt.tsx +336 -0
- package/components/permissions/PermissionRequest.tsx +217 -0
- package/components/permissions/PermissionRequestTitle.tsx +66 -0
- package/components/permissions/PermissionRuleExplanation.tsx +121 -0
- package/components/permissions/PowerShellPermissionRequest/PowerShellPermissionRequest.tsx +235 -0
- package/components/permissions/PowerShellPermissionRequest/powershellToolUseOptions.tsx +91 -0
- package/components/permissions/SandboxPermissionRequest.tsx +163 -0
- package/components/permissions/SedEditPermissionRequest/SedEditPermissionRequest.tsx +230 -0
- package/components/permissions/SkillPermissionRequest/SkillPermissionRequest.tsx +369 -0
- package/components/permissions/WebFetchPermissionRequest/WebFetchPermissionRequest.tsx +258 -0
- package/components/permissions/WorkerBadge.tsx +49 -0
- package/components/permissions/WorkerPendingPermission.tsx +105 -0
- package/components/permissions/hooks.ts +209 -0
- package/components/permissions/rules/AddPermissionRules.tsx +180 -0
- package/components/permissions/rules/AddWorkspaceDirectory.tsx +340 -0
- package/components/permissions/rules/PermissionRuleDescription.tsx +76 -0
- package/components/permissions/rules/PermissionRuleInput.tsx +138 -0
- package/components/permissions/rules/PermissionRuleList.tsx +1179 -0
- package/components/permissions/rules/RecentDenialsTab.tsx +207 -0
- package/components/permissions/rules/RemoveWorkspaceDirectory.tsx +110 -0
- package/components/permissions/rules/WorkspaceTab.tsx +150 -0
- package/components/permissions/shellPermissionHelpers.tsx +164 -0
- package/components/permissions/useShellPermissionFeedback.ts +148 -0
- package/components/permissions/utils.ts +25 -0
- package/components/sandbox/SandboxConfigTab.tsx +45 -0
- package/components/sandbox/SandboxDependenciesTab.tsx +120 -0
- package/components/sandbox/SandboxDoctorSection.tsx +46 -0
- package/components/sandbox/SandboxOverridesTab.tsx +193 -0
- package/components/sandbox/SandboxSettings.tsx +296 -0
- package/components/shell/ExpandShellOutputContext.tsx +36 -0
- package/components/shell/OutputLine.tsx +118 -0
- package/components/shell/ShellProgressMessage.tsx +150 -0
- package/components/shell/ShellTimeDisplay.tsx +74 -0
- package/components/skills/SkillsMenu.tsx +237 -0
- package/components/tasks/AsyncAgentDetailDialog.tsx +229 -0
- package/components/tasks/BackgroundTask.tsx +345 -0
- package/components/tasks/BackgroundTaskStatus.tsx +429 -0
- package/components/tasks/BackgroundTasksDialog.tsx +652 -0
- package/components/tasks/DreamDetailDialog.tsx +251 -0
- package/components/tasks/InProcessTeammateDetailDialog.tsx +266 -0
- package/components/tasks/RemoteSessionDetailDialog.tsx +904 -0
- package/components/tasks/RemoteSessionProgress.tsx +243 -0
- package/components/tasks/ShellDetailDialog.tsx +404 -0
- package/components/tasks/ShellProgress.tsx +87 -0
- package/components/tasks/renderToolActivity.tsx +33 -0
- package/components/tasks/taskStatusUtils.tsx +107 -0
- package/components/teams/TeamStatus.tsx +80 -0
- package/components/teams/TeamsDialog.tsx +715 -0
- package/components/ui/OrderedList.tsx +71 -0
- package/components/ui/OrderedListItem.tsx +45 -0
- package/components/ui/TreeSelect.tsx +397 -0
- package/components/wizard/WizardDialogLayout.tsx +65 -0
- package/components/wizard/WizardNavigationFooter.tsx +24 -0
- package/components/wizard/WizardProvider.tsx +213 -0
- package/components/wizard/index.ts +9 -0
- package/components/wizard/useWizard.ts +13 -0
- package/context.ts +189 -0
- package/cost-tracker.ts +323 -0
- package/entrypoints/cli.tsx +1 -1
- package/history.ts +464 -0
- package/hooks/fileSuggestions.ts +811 -0
- package/hooks/notifs/useAutoModeUnavailableNotification.ts +56 -0
- package/hooks/notifs/useCanSwitchToExistingSubscription.tsx +60 -0
- package/hooks/notifs/useDeprecationWarningNotification.tsx +44 -0
- package/hooks/notifs/useFastModeNotification.tsx +162 -0
- package/hooks/notifs/useIDEStatusIndicator.tsx +186 -0
- package/hooks/notifs/useInstallMessages.tsx +26 -0
- package/hooks/notifs/useLspInitializationNotification.tsx +143 -0
- package/hooks/notifs/useMcpConnectivityStatus.tsx +88 -0
- package/hooks/notifs/useModelMigrationNotifications.tsx +52 -0
- package/hooks/notifs/useNpmDeprecationNotification.tsx +25 -0
- package/hooks/notifs/usePluginAutoupdateNotification.tsx +83 -0
- package/hooks/notifs/usePluginInstallationStatus.tsx +128 -0
- package/hooks/notifs/useRateLimitWarningNotification.tsx +114 -0
- package/hooks/notifs/useSettingsErrors.tsx +69 -0
- package/hooks/notifs/useStartupNotification.ts +41 -0
- package/hooks/notifs/useTeammateShutdownNotification.ts +78 -0
- package/hooks/renderPlaceholder.ts +51 -0
- package/hooks/toolPermission/PermissionContext.ts +388 -0
- package/hooks/toolPermission/handlers/coordinatorHandler.ts +65 -0
- package/hooks/toolPermission/handlers/interactiveHandler.ts +536 -0
- package/hooks/toolPermission/handlers/swarmWorkerHandler.ts +159 -0
- package/hooks/toolPermission/permissionLogging.ts +238 -0
- package/hooks/unifiedSuggestions.ts +202 -0
- package/hooks/useAfterFirstRender.ts +17 -0
- package/hooks/useApiKeyVerification.ts +84 -0
- package/hooks/useArrowKeyHistory.tsx +229 -0
- package/hooks/useAssistantHistory.ts +250 -0
- package/hooks/useAwaySummary.ts +125 -0
- package/hooks/useBackgroundTaskNavigation.ts +251 -0
- package/hooks/useBlink.ts +34 -0
- package/hooks/useCanUseTool.tsx +204 -0
- package/hooks/useCancelRequest.ts +276 -0
- package/hooks/useChromeExtensionNotification.tsx +50 -0
- package/hooks/useClaudeCodeHintRecommendation.tsx +129 -0
- package/hooks/useClipboardImageHint.ts +77 -0
- package/hooks/useCommandKeybindings.tsx +108 -0
- package/hooks/useCommandQueue.ts +15 -0
- package/hooks/useCopyOnSelect.ts +98 -0
- package/hooks/useDeferredHookMessages.ts +46 -0
- package/hooks/useDiffData.ts +110 -0
- package/hooks/useDiffInIDE.ts +379 -0
- package/hooks/useDirectConnect.ts +229 -0
- package/hooks/useDoublePress.ts +62 -0
- package/hooks/useDynamicConfig.ts +22 -0
- package/hooks/useElapsedTime.ts +37 -0
- package/hooks/useExitOnCtrlCD.ts +95 -0
- package/hooks/useExitOnCtrlCDWithKeybindings.ts +24 -0
- package/hooks/useFileHistorySnapshotInit.ts +25 -0
- package/hooks/useGlobalKeybindings.tsx +249 -0
- package/hooks/useHistorySearch.ts +303 -0
- package/hooks/useIDEIntegration.tsx +70 -0
- package/hooks/useIdeAtMentioned.ts +76 -0
- package/hooks/useIdeConnectionStatus.ts +33 -0
- package/hooks/useIdeLogging.ts +41 -0
- package/hooks/useIdeSelection.ts +150 -0
- package/hooks/useInboxPoller.ts +969 -0
- package/hooks/useInputBuffer.ts +132 -0
- package/hooks/useIssueFlagBanner.ts +133 -0
- package/hooks/useLogMessages.ts +119 -0
- package/hooks/useLspPluginRecommendation.tsx +194 -0
- package/hooks/useMailboxBridge.ts +21 -0
- package/hooks/useMainLoopModel.ts +34 -0
- package/hooks/useManagePlugins.ts +304 -0
- package/hooks/useMemoryUsage.ts +39 -0
- package/hooks/useMergedClients.ts +23 -0
- package/hooks/useMergedCommands.ts +15 -0
- package/hooks/useMergedTools.ts +44 -0
- package/hooks/useMinDisplayTime.ts +35 -0
- package/hooks/useNotifyAfterTimeout.ts +65 -0
- package/hooks/useOfficialMarketplaceNotification.tsx +48 -0
- package/hooks/usePasteHandler.ts +285 -0
- package/hooks/usePluginRecommendationBase.tsx +105 -0
- package/hooks/usePrStatus.ts +106 -0
- package/hooks/usePromptSuggestion.ts +177 -0
- package/hooks/usePromptsFromClaudeInChrome.tsx +71 -0
- package/hooks/useQueueProcessor.ts +68 -0
- package/hooks/useRemoteSession.ts +605 -0
- package/hooks/useReplBridge.tsx +723 -0
- package/hooks/useSSHSession.ts +241 -0
- package/hooks/useScheduledTasks.ts +139 -0
- package/hooks/useSearchInput.ts +364 -0
- package/hooks/useSessionBackgrounding.ts +158 -0
- package/hooks/useSettings.ts +17 -0
- package/hooks/useSettingsChange.ts +25 -0
- package/hooks/useSkillImprovementSurvey.ts +105 -0
- package/hooks/useSkillsChange.ts +62 -0
- package/hooks/useSwarmInitialization.ts +81 -0
- package/hooks/useSwarmPermissionPoller.ts +330 -0
- package/hooks/useTaskListWatcher.ts +221 -0
- package/hooks/useTasksV2.ts +250 -0
- package/hooks/useTeammateViewAutoExit.ts +63 -0
- package/hooks/useTeleportResume.tsx +85 -0
- package/hooks/useTerminalSize.ts +15 -0
- package/hooks/useTextInput.ts +529 -0
- package/hooks/useTimeout.ts +14 -0
- package/hooks/useTurnDiffs.ts +213 -0
- package/hooks/useTypeahead.tsx +1385 -0
- package/hooks/useUpdateNotification.ts +34 -0
- package/hooks/useVimInput.ts +316 -0
- package/hooks/useVirtualScroll.ts +721 -0
- package/hooks/useVoice.ts +1144 -0
- package/hooks/useVoiceEnabled.ts +25 -0
- package/hooks/useVoiceIntegration.tsx +677 -0
- package/ink/Ansi.tsx +292 -0
- package/ink/bidi.ts +139 -0
- package/ink/clearTerminal.ts +74 -0
- package/ink/colorize.ts +231 -0
- package/ink/components/AlternateScreen.tsx +80 -0
- package/ink/components/App.tsx +658 -0
- package/ink/components/AppContext.ts +21 -0
- package/ink/components/Box.tsx +214 -0
- package/ink/components/Button.tsx +192 -0
- package/ink/components/ClockContext.tsx +112 -0
- package/ink/components/CursorDeclarationContext.ts +32 -0
- package/ink/components/ErrorOverview.tsx +109 -0
- package/ink/components/Link.tsx +42 -0
- package/ink/components/Newline.tsx +39 -0
- package/ink/components/NoSelect.tsx +68 -0
- package/ink/components/RawAnsi.tsx +57 -0
- package/ink/components/ScrollBox.tsx +237 -0
- package/ink/components/Spacer.tsx +20 -0
- package/ink/components/StdinContext.ts +49 -0
- package/ink/components/TerminalFocusContext.tsx +52 -0
- package/ink/components/TerminalSizeContext.tsx +7 -0
- package/ink/components/Text.tsx +254 -0
- package/ink/constants.ts +2 -0
- package/ink/dom.ts +484 -0
- package/ink/events/click-event.ts +38 -0
- package/ink/events/dispatcher.ts +233 -0
- package/ink/events/emitter.ts +39 -0
- package/ink/events/event-handlers.ts +73 -0
- package/ink/events/event.ts +11 -0
- package/ink/events/focus-event.ts +21 -0
- package/ink/events/input-event.ts +205 -0
- package/ink/events/keyboard-event.ts +51 -0
- package/ink/events/terminal-event.ts +107 -0
- package/ink/events/terminal-focus-event.ts +19 -0
- package/ink/focus.ts +181 -0
- package/ink/frame.ts +124 -0
- package/ink/get-max-width.ts +27 -0
- package/ink/global.d.ts +26 -0
- package/ink/hit-test.ts +130 -0
- package/ink/hooks/use-animation-frame.ts +57 -0
- package/ink/hooks/use-app.ts +8 -0
- package/ink/hooks/use-declared-cursor.ts +73 -0
- package/ink/hooks/use-input.ts +92 -0
- package/ink/hooks/use-interval.ts +67 -0
- package/ink/hooks/use-search-highlight.ts +53 -0
- package/ink/hooks/use-selection.ts +104 -0
- package/ink/hooks/use-stdin.ts +8 -0
- package/ink/hooks/use-tab-status.ts +72 -0
- package/ink/hooks/use-terminal-focus.ts +16 -0
- package/ink/hooks/use-terminal-title.ts +31 -0
- package/ink/hooks/use-terminal-viewport.ts +96 -0
- package/ink/ink.tsx +1754 -0
- package/ink/instances.ts +10 -0
- package/ink/layout/engine.ts +6 -0
- package/ink/layout/geometry.ts +97 -0
- package/ink/layout/node.ts +152 -0
- package/ink/layout/yoga.ts +308 -0
- package/ink/line-width-cache.ts +24 -0
- package/ink/log-update.ts +773 -0
- package/ink/measure-element.ts +23 -0
- package/ink/measure-text.ts +47 -0
- package/ink/node-cache.ts +54 -0
- package/ink/optimizer.ts +93 -0
- package/ink/output.ts +797 -0
- package/ink/parse-keypress.ts +801 -0
- package/ink/reconciler.ts +512 -0
- package/ink/render-border.ts +231 -0
- package/ink/render-node-to-output.ts +1462 -0
- package/ink/render-to-screen.ts +231 -0
- package/ink/renderer.ts +178 -0
- package/ink/root.ts +184 -0
- package/ink/screen.ts +1486 -0
- package/ink/searchHighlight.ts +93 -0
- package/ink/selection.ts +917 -0
- package/ink/squash-text-nodes.ts +92 -0
- package/ink/stringWidth.ts +223 -0
- package/ink/styles.ts +771 -0
- package/ink/supports-hyperlinks.ts +57 -0
- package/ink/tabstops.ts +46 -0
- package/ink/terminal-focus-state.ts +47 -0
- package/ink/terminal-querier.ts +212 -0
- package/ink/terminal.ts +248 -0
- package/ink/termio/ansi.ts +75 -0
- package/ink/termio/csi.ts +319 -0
- package/ink/termio/dec.ts +60 -0
- package/ink/termio/esc.ts +67 -0
- package/ink/termio/osc.ts +493 -0
- package/ink/termio/parser.ts +394 -0
- package/ink/termio/sgr.ts +308 -0
- package/ink/termio/tokenize.ts +319 -0
- package/ink/termio/types.ts +236 -0
- package/ink/termio.ts +42 -0
- package/ink/useTerminalNotification.ts +126 -0
- package/ink/warn.ts +9 -0
- package/ink/widest-line.ts +19 -0
- package/ink/wrap-text.ts +74 -0
- package/ink/wrapAnsi.ts +20 -0
- package/inspect.js +7 -0
- package/keybindings/KeybindingContext.tsx +243 -0
- package/keybindings/KeybindingProviderSetup.tsx +308 -0
- package/keybindings/defaultBindings.ts +340 -0
- package/keybindings/loadUserBindings.ts +472 -0
- package/keybindings/match.ts +120 -0
- package/keybindings/parser.ts +203 -0
- package/keybindings/reservedShortcuts.ts +127 -0
- package/keybindings/resolver.ts +244 -0
- package/keybindings/schema.ts +236 -0
- package/keybindings/shortcutFormat.ts +63 -0
- package/keybindings/template.ts +52 -0
- package/keybindings/useKeybinding.ts +196 -0
- package/keybindings/useShortcutDisplay.ts +59 -0
- package/keybindings/validate.ts +498 -0
- package/macro.ts +24 -0
- package/migrations/migrateAutoUpdatesToSettings.ts +61 -0
- package/migrations/migrateBypassPermissionsAcceptedToSettings.ts +40 -0
- package/migrations/migrateEnableAllProjectMcpServersToSettings.ts +118 -0
- package/migrations/migrateFennecToOpus.ts +45 -0
- package/migrations/migrateLegacyOpusToCurrent.ts +57 -0
- package/migrations/migrateOpusToOpus1m.ts +43 -0
- package/migrations/migrateReplBridgeEnabledToRemoteControlAtStartup.ts +22 -0
- package/migrations/migrateSonnet1mToSonnet45.ts +48 -0
- package/migrations/migrateSonnet45ToSonnet46.ts +67 -0
- package/migrations/resetAutoModeOptInForDefaultOffer.ts +51 -0
- package/migrations/resetProToOpusDefault.ts +51 -0
- package/package.json +29 -3
- package/patch-box.js +54 -0
- package/patch-compact.js +13 -0
- package/patch-condensed-center.js +13 -0
- package/patch-condensed-row.js +13 -0
- package/patch-condensed.js +13 -0
- package/patch-final.js +58 -0
- package/patch-input-body.js +46 -0
- package/patch-input-body2.js +35 -0
- package/patch-input-style.js +13 -0
- package/patch-input-width.js +13 -0
- package/patch-layout.js +87 -0
- package/patch-logo-row.js +12 -0
- package/patch-width.js +13 -0
- package/patch-width2.js +13 -0
- package/patch2.js +74 -0
- package/patch3.js +13 -0
- package/query.ts +1750 -0
- package/remote/RemoteSessionManager.ts +343 -0
- package/remote/SessionsWebSocket.ts +404 -0
- package/remote/remotePermissionBridge.ts +78 -0
- package/remote/sdkMessageAdapter.ts +302 -0
- package/skills/bundled/batch.ts +124 -0
- package/skills/bundled/claudeApi.ts +196 -0
- package/skills/bundled/claudeApiContent.ts +75 -0
- package/skills/bundled/claudeInChrome.ts +34 -0
- package/skills/bundled/debug.ts +103 -0
- package/skills/bundled/index.ts +79 -0
- package/skills/bundled/keybindings.ts +339 -0
- package/skills/bundled/loop.ts +92 -0
- package/skills/bundled/loremIpsum.ts +282 -0
- package/skills/bundled/remember.ts +82 -0
- package/skills/bundled/scheduleRemoteAgents.ts +447 -0
- package/skills/bundled/simplify.ts +69 -0
- package/skills/bundled/skillify.ts +197 -0
- package/skills/bundled/stuck.ts +79 -0
- package/skills/bundled/updateConfig.ts +475 -0
- package/skills/bundled/verify/SKILL.md +3 -0
- package/skills/bundled/verify/examples/cli.md +3 -0
- package/skills/bundled/verify/examples/server.md +3 -0
- package/skills/bundled/verify.ts +30 -0
- package/skills/bundled/verifyContent.ts +13 -0
- package/skills/bundledSkills.ts +220 -0
- package/skills/loadSkillsDir.ts +1086 -0
- package/skills/mcpSkillBuilders.ts +44 -0
- package/state/AppState.tsx +200 -0
- package/state/AppStateStore.ts +569 -0
- package/state/onChangeAppState.ts +171 -0
- package/state/selectors.ts +76 -0
- package/state/store.ts +34 -0
- package/state/teammateViewHelpers.ts +141 -0
- package/tasks/DreamTask/DreamTask.ts +157 -0
- package/tasks/InProcessTeammateTask/InProcessTeammateTask.tsx +126 -0
- package/tasks/InProcessTeammateTask/types.ts +121 -0
- package/tasks/LocalAgentTask/LocalAgentTask.tsx +683 -0
- package/tasks/LocalMainSessionTask.ts +479 -0
- package/tasks/LocalShellTask/LocalShellTask.tsx +523 -0
- package/tasks/LocalShellTask/guards.ts +41 -0
- package/tasks/LocalShellTask/killShellTasks.ts +76 -0
- package/tasks/RemoteAgentTask/RemoteAgentTask.tsx +856 -0
- package/tasks/pillLabel.ts +82 -0
- package/tasks/stopTask.ts +100 -0
- package/tasks/types.ts +46 -0
- package/types/command.ts +216 -0
- package/types/connectorText.ts +13 -0
- package/types/generated/events_mono/claude_code/v1/claude_code_internal_event.ts +865 -0
- package/types/generated/events_mono/common/v1/auth.ts +100 -0
- package/types/generated/events_mono/growthbook/v1/growthbook_experiment_event.ts +223 -0
- package/types/generated/google/protobuf/timestamp.ts +187 -0
- package/types/hooks.ts +290 -0
- package/types/ids.ts +44 -0
- package/types/logs.ts +330 -0
- package/types/permissions.ts +441 -0
- package/types/plugin.ts +363 -0
- package/types/textInputTypes.ts +387 -0
|
@@ -0,0 +1,969 @@
|
|
|
1
|
+
import { randomUUID } from 'crypto'
|
|
2
|
+
import { useCallback, useEffect, useRef } from 'react'
|
|
3
|
+
import { useInterval } from 'usehooks-ts'
|
|
4
|
+
import type { ToolUseConfirm } from '../components/permissions/PermissionRequest.js'
|
|
5
|
+
import { TEAMMATE_MESSAGE_TAG } from '../constants/xml.js'
|
|
6
|
+
import { useTerminalNotification } from '../ink/useTerminalNotification.js'
|
|
7
|
+
import { sendNotification } from '../services/notifier.js'
|
|
8
|
+
import {
|
|
9
|
+
type AppState,
|
|
10
|
+
useAppState,
|
|
11
|
+
useAppStateStore,
|
|
12
|
+
useSetAppState,
|
|
13
|
+
} from '../state/AppState.js'
|
|
14
|
+
import { findToolByName } from '../Tool.js'
|
|
15
|
+
import { isInProcessTeammateTask } from '../tasks/InProcessTeammateTask/types.js'
|
|
16
|
+
import { getAllBaseTools } from '../tools.js'
|
|
17
|
+
import type { PermissionUpdate } from '../types/permissions.js'
|
|
18
|
+
import { logForDebugging } from '../utils/debug.js'
|
|
19
|
+
import {
|
|
20
|
+
findInProcessTeammateTaskId,
|
|
21
|
+
handlePlanApprovalResponse,
|
|
22
|
+
} from '../utils/inProcessTeammateHelpers.js'
|
|
23
|
+
import { createAssistantMessage } from '../utils/messages.js'
|
|
24
|
+
import {
|
|
25
|
+
permissionModeFromString,
|
|
26
|
+
toExternalPermissionMode,
|
|
27
|
+
} from '../utils/permissions/PermissionMode.js'
|
|
28
|
+
import { applyPermissionUpdate } from '../utils/permissions/PermissionUpdate.js'
|
|
29
|
+
import { jsonStringify } from '../utils/slowOperations.js'
|
|
30
|
+
import { isInsideTmux } from '../utils/swarm/backends/detection.js'
|
|
31
|
+
import {
|
|
32
|
+
ensureBackendsRegistered,
|
|
33
|
+
getBackendByType,
|
|
34
|
+
} from '../utils/swarm/backends/registry.js'
|
|
35
|
+
import type { PaneBackendType } from '../utils/swarm/backends/types.js'
|
|
36
|
+
import { TEAM_LEAD_NAME } from '../utils/swarm/constants.js'
|
|
37
|
+
import { getLeaderToolUseConfirmQueue } from '../utils/swarm/leaderPermissionBridge.js'
|
|
38
|
+
import { sendPermissionResponseViaMailbox } from '../utils/swarm/permissionSync.js'
|
|
39
|
+
import {
|
|
40
|
+
removeTeammateFromTeamFile,
|
|
41
|
+
setMemberMode,
|
|
42
|
+
} from '../utils/swarm/teamHelpers.js'
|
|
43
|
+
import { unassignTeammateTasks } from '../utils/tasks.js'
|
|
44
|
+
import {
|
|
45
|
+
getAgentName,
|
|
46
|
+
isPlanModeRequired,
|
|
47
|
+
isTeamLead,
|
|
48
|
+
isTeammate,
|
|
49
|
+
} from '../utils/teammate.js'
|
|
50
|
+
import { isInProcessTeammate } from '../utils/teammateContext.js'
|
|
51
|
+
import {
|
|
52
|
+
isModeSetRequest,
|
|
53
|
+
isPermissionRequest,
|
|
54
|
+
isPermissionResponse,
|
|
55
|
+
isPlanApprovalRequest,
|
|
56
|
+
isPlanApprovalResponse,
|
|
57
|
+
isSandboxPermissionRequest,
|
|
58
|
+
isSandboxPermissionResponse,
|
|
59
|
+
isShutdownApproved,
|
|
60
|
+
isShutdownRequest,
|
|
61
|
+
isTeamPermissionUpdate,
|
|
62
|
+
markMessagesAsRead,
|
|
63
|
+
readUnreadMessages,
|
|
64
|
+
type TeammateMessage,
|
|
65
|
+
writeToMailbox,
|
|
66
|
+
} from '../utils/teammateMailbox.js'
|
|
67
|
+
import {
|
|
68
|
+
hasPermissionCallback,
|
|
69
|
+
hasSandboxPermissionCallback,
|
|
70
|
+
processMailboxPermissionResponse,
|
|
71
|
+
processSandboxPermissionResponse,
|
|
72
|
+
} from './useSwarmPermissionPoller.js'
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Get the agent name to poll for messages.
|
|
76
|
+
* - In-process teammates return undefined (they use waitForNextPromptOrShutdown instead)
|
|
77
|
+
* - Process-based teammates use their CLAUDE_CODE_AGENT_NAME
|
|
78
|
+
* - Team leads use their name from teamContext.teammates
|
|
79
|
+
* - Standalone sessions return undefined
|
|
80
|
+
*/
|
|
81
|
+
function getAgentNameToPoll(appState: AppState): string | undefined {
|
|
82
|
+
// In-process teammates should NOT use useInboxPoller - they have their own
|
|
83
|
+
// polling mechanism via waitForNextPromptOrShutdown() in inProcessRunner.ts.
|
|
84
|
+
// Using useInboxPoller would cause message routing issues since in-process
|
|
85
|
+
// teammates share the same React context and AppState with the leader.
|
|
86
|
+
//
|
|
87
|
+
// Note: This can be called when the leader's REPL re-renders while an
|
|
88
|
+
// in-process teammate's AsyncLocalStorage context is active (due to shared
|
|
89
|
+
// setAppState). We return undefined to gracefully skip polling rather than
|
|
90
|
+
// throwing, since this is a normal occurrence during concurrent execution.
|
|
91
|
+
if (isInProcessTeammate()) {
|
|
92
|
+
return undefined
|
|
93
|
+
}
|
|
94
|
+
if (isTeammate()) {
|
|
95
|
+
return getAgentName()
|
|
96
|
+
}
|
|
97
|
+
// Team lead polls using their agent name (not ID)
|
|
98
|
+
if (isTeamLead(appState.teamContext)) {
|
|
99
|
+
const leadAgentId = appState.teamContext!.leadAgentId
|
|
100
|
+
// Look up the lead's name from teammates map
|
|
101
|
+
const leadName = appState.teamContext!.teammates[leadAgentId]?.name
|
|
102
|
+
return leadName || 'team-lead'
|
|
103
|
+
}
|
|
104
|
+
return undefined
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const INBOX_POLL_INTERVAL_MS = 1000
|
|
108
|
+
|
|
109
|
+
type Props = {
|
|
110
|
+
enabled: boolean
|
|
111
|
+
isLoading: boolean
|
|
112
|
+
focusedInputDialog: string | undefined
|
|
113
|
+
// Returns true if submission succeeded, false if rejected (e.g., query already running)
|
|
114
|
+
// Dead code elimination: parameter named onSubmitMessage to avoid "teammate" string in external builds
|
|
115
|
+
onSubmitMessage: (formatted: string) => boolean
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Polls the teammate inbox for new messages and submits them as turns.
|
|
120
|
+
*
|
|
121
|
+
* This hook:
|
|
122
|
+
* 1. Polls every 1s for unread messages (teammates or team leads)
|
|
123
|
+
* 2. When idle: submits messages immediately as a new turn
|
|
124
|
+
* 3. When busy: queues messages in AppState.inbox for UI display, delivers when turn ends
|
|
125
|
+
*/
|
|
126
|
+
export function useInboxPoller({
|
|
127
|
+
enabled,
|
|
128
|
+
isLoading,
|
|
129
|
+
focusedInputDialog,
|
|
130
|
+
onSubmitMessage,
|
|
131
|
+
}: Props): void {
|
|
132
|
+
// Assign to original name for clarity within the function
|
|
133
|
+
const onSubmitTeammateMessage = onSubmitMessage
|
|
134
|
+
const store = useAppStateStore()
|
|
135
|
+
const setAppState = useSetAppState()
|
|
136
|
+
const inboxMessageCount = useAppState(s => s.inbox.messages.length)
|
|
137
|
+
const terminal = useTerminalNotification()
|
|
138
|
+
|
|
139
|
+
const poll = useCallback(async () => {
|
|
140
|
+
if (!enabled) return
|
|
141
|
+
|
|
142
|
+
// Use ref to avoid dependency on appState object (prevents infinite loop)
|
|
143
|
+
const currentAppState = store.getState()
|
|
144
|
+
const agentName = getAgentNameToPoll(currentAppState)
|
|
145
|
+
if (!agentName) return
|
|
146
|
+
|
|
147
|
+
const unread = await readUnreadMessages(
|
|
148
|
+
agentName,
|
|
149
|
+
currentAppState.teamContext?.teamName,
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
if (unread.length === 0) return
|
|
153
|
+
|
|
154
|
+
logForDebugging(`[InboxPoller] Found ${unread.length} unread message(s)`)
|
|
155
|
+
|
|
156
|
+
// Check for plan approval responses and transition out of plan mode if approved
|
|
157
|
+
// Security: Only accept approval responses from the team lead
|
|
158
|
+
if (isTeammate() && isPlanModeRequired()) {
|
|
159
|
+
for (const msg of unread) {
|
|
160
|
+
const approvalResponse = isPlanApprovalResponse(msg.text)
|
|
161
|
+
// Verify the message is from the team lead to prevent teammates from forging approvals
|
|
162
|
+
if (approvalResponse && msg.from === 'team-lead') {
|
|
163
|
+
logForDebugging(
|
|
164
|
+
`[InboxPoller] Received plan approval response from team-lead: approved=${approvalResponse.approved}`,
|
|
165
|
+
)
|
|
166
|
+
if (approvalResponse.approved) {
|
|
167
|
+
// Use leader's permission mode if provided, otherwise default
|
|
168
|
+
const targetMode = approvalResponse.permissionMode ?? 'default'
|
|
169
|
+
|
|
170
|
+
// Transition out of plan mode
|
|
171
|
+
setAppState(prev => ({
|
|
172
|
+
...prev,
|
|
173
|
+
toolPermissionContext: applyPermissionUpdate(
|
|
174
|
+
prev.toolPermissionContext,
|
|
175
|
+
{
|
|
176
|
+
type: 'setMode',
|
|
177
|
+
mode: toExternalPermissionMode(targetMode),
|
|
178
|
+
destination: 'session',
|
|
179
|
+
},
|
|
180
|
+
),
|
|
181
|
+
}))
|
|
182
|
+
logForDebugging(
|
|
183
|
+
`[InboxPoller] Plan approved by team lead, exited plan mode to ${targetMode}`,
|
|
184
|
+
)
|
|
185
|
+
} else {
|
|
186
|
+
logForDebugging(
|
|
187
|
+
`[InboxPoller] Plan rejected by team lead: ${approvalResponse.feedback || 'No feedback provided'}`,
|
|
188
|
+
)
|
|
189
|
+
}
|
|
190
|
+
} else if (approvalResponse) {
|
|
191
|
+
logForDebugging(
|
|
192
|
+
`[InboxPoller] Ignoring plan approval response from non-team-lead: ${msg.from}`,
|
|
193
|
+
)
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Helper to mark messages as read in the inbox file.
|
|
199
|
+
// Called after messages are successfully delivered or reliably queued.
|
|
200
|
+
const markRead = () => {
|
|
201
|
+
void markMessagesAsRead(agentName, currentAppState.teamContext?.teamName)
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Separate permission messages from regular teammate messages
|
|
205
|
+
const permissionRequests: TeammateMessage[] = []
|
|
206
|
+
const permissionResponses: TeammateMessage[] = []
|
|
207
|
+
const sandboxPermissionRequests: TeammateMessage[] = []
|
|
208
|
+
const sandboxPermissionResponses: TeammateMessage[] = []
|
|
209
|
+
const shutdownRequests: TeammateMessage[] = []
|
|
210
|
+
const shutdownApprovals: TeammateMessage[] = []
|
|
211
|
+
const teamPermissionUpdates: TeammateMessage[] = []
|
|
212
|
+
const modeSetRequests: TeammateMessage[] = []
|
|
213
|
+
const planApprovalRequests: TeammateMessage[] = []
|
|
214
|
+
const regularMessages: TeammateMessage[] = []
|
|
215
|
+
|
|
216
|
+
for (const m of unread) {
|
|
217
|
+
const permReq = isPermissionRequest(m.text)
|
|
218
|
+
const permResp = isPermissionResponse(m.text)
|
|
219
|
+
const sandboxReq = isSandboxPermissionRequest(m.text)
|
|
220
|
+
const sandboxResp = isSandboxPermissionResponse(m.text)
|
|
221
|
+
const shutdownReq = isShutdownRequest(m.text)
|
|
222
|
+
const shutdownApproval = isShutdownApproved(m.text)
|
|
223
|
+
const teamPermUpdate = isTeamPermissionUpdate(m.text)
|
|
224
|
+
const modeSetReq = isModeSetRequest(m.text)
|
|
225
|
+
const planApprovalReq = isPlanApprovalRequest(m.text)
|
|
226
|
+
|
|
227
|
+
if (permReq) {
|
|
228
|
+
permissionRequests.push(m)
|
|
229
|
+
} else if (permResp) {
|
|
230
|
+
permissionResponses.push(m)
|
|
231
|
+
} else if (sandboxReq) {
|
|
232
|
+
sandboxPermissionRequests.push(m)
|
|
233
|
+
} else if (sandboxResp) {
|
|
234
|
+
sandboxPermissionResponses.push(m)
|
|
235
|
+
} else if (shutdownReq) {
|
|
236
|
+
shutdownRequests.push(m)
|
|
237
|
+
} else if (shutdownApproval) {
|
|
238
|
+
shutdownApprovals.push(m)
|
|
239
|
+
} else if (teamPermUpdate) {
|
|
240
|
+
teamPermissionUpdates.push(m)
|
|
241
|
+
} else if (modeSetReq) {
|
|
242
|
+
modeSetRequests.push(m)
|
|
243
|
+
} else if (planApprovalReq) {
|
|
244
|
+
planApprovalRequests.push(m)
|
|
245
|
+
} else {
|
|
246
|
+
regularMessages.push(m)
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Handle permission requests (leader side) - route to ToolUseConfirmQueue
|
|
251
|
+
if (
|
|
252
|
+
permissionRequests.length > 0 &&
|
|
253
|
+
isTeamLead(currentAppState.teamContext)
|
|
254
|
+
) {
|
|
255
|
+
logForDebugging(
|
|
256
|
+
`[InboxPoller] Found ${permissionRequests.length} permission request(s)`,
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
const setToolUseConfirmQueue = getLeaderToolUseConfirmQueue()
|
|
260
|
+
const teamName = currentAppState.teamContext?.teamName
|
|
261
|
+
|
|
262
|
+
for (const m of permissionRequests) {
|
|
263
|
+
const parsed = isPermissionRequest(m.text)
|
|
264
|
+
if (!parsed) continue
|
|
265
|
+
|
|
266
|
+
if (setToolUseConfirmQueue) {
|
|
267
|
+
// Route through the standard ToolUseConfirmQueue so tmux workers
|
|
268
|
+
// get the same tool-specific UI (BashPermissionRequest, FileEditToolDiff, etc.)
|
|
269
|
+
// as in-process teammates.
|
|
270
|
+
const tool = findToolByName(getAllBaseTools(), parsed.tool_name)
|
|
271
|
+
if (!tool) {
|
|
272
|
+
logForDebugging(
|
|
273
|
+
`[InboxPoller] Unknown tool ${parsed.tool_name}, skipping permission request`,
|
|
274
|
+
)
|
|
275
|
+
continue
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const entry: ToolUseConfirm = {
|
|
279
|
+
assistantMessage: createAssistantMessage({ content: '' }),
|
|
280
|
+
tool,
|
|
281
|
+
description: parsed.description,
|
|
282
|
+
input: parsed.input,
|
|
283
|
+
toolUseContext: {} as ToolUseConfirm['toolUseContext'],
|
|
284
|
+
toolUseID: parsed.tool_use_id,
|
|
285
|
+
permissionResult: {
|
|
286
|
+
behavior: 'ask',
|
|
287
|
+
message: parsed.description,
|
|
288
|
+
},
|
|
289
|
+
permissionPromptStartTimeMs: Date.now(),
|
|
290
|
+
workerBadge: {
|
|
291
|
+
name: parsed.agent_id,
|
|
292
|
+
color: 'cyan',
|
|
293
|
+
},
|
|
294
|
+
onUserInteraction() {
|
|
295
|
+
// No-op for tmux workers (no classifier auto-approval)
|
|
296
|
+
},
|
|
297
|
+
onAbort() {
|
|
298
|
+
void sendPermissionResponseViaMailbox(
|
|
299
|
+
parsed.agent_id,
|
|
300
|
+
{ decision: 'rejected', resolvedBy: 'leader' },
|
|
301
|
+
parsed.request_id,
|
|
302
|
+
teamName,
|
|
303
|
+
)
|
|
304
|
+
},
|
|
305
|
+
onAllow(
|
|
306
|
+
updatedInput: Record<string, unknown>,
|
|
307
|
+
permissionUpdates: PermissionUpdate[],
|
|
308
|
+
) {
|
|
309
|
+
void sendPermissionResponseViaMailbox(
|
|
310
|
+
parsed.agent_id,
|
|
311
|
+
{
|
|
312
|
+
decision: 'approved',
|
|
313
|
+
resolvedBy: 'leader',
|
|
314
|
+
updatedInput,
|
|
315
|
+
permissionUpdates,
|
|
316
|
+
},
|
|
317
|
+
parsed.request_id,
|
|
318
|
+
teamName,
|
|
319
|
+
)
|
|
320
|
+
},
|
|
321
|
+
onReject(feedback?: string) {
|
|
322
|
+
void sendPermissionResponseViaMailbox(
|
|
323
|
+
parsed.agent_id,
|
|
324
|
+
{
|
|
325
|
+
decision: 'rejected',
|
|
326
|
+
resolvedBy: 'leader',
|
|
327
|
+
feedback,
|
|
328
|
+
},
|
|
329
|
+
parsed.request_id,
|
|
330
|
+
teamName,
|
|
331
|
+
)
|
|
332
|
+
},
|
|
333
|
+
async recheckPermission() {
|
|
334
|
+
// No-op for tmux workers — permission state is on the worker side
|
|
335
|
+
},
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// Deduplicate: if markMessagesAsRead failed on a prior poll,
|
|
339
|
+
// the same message will be re-read — skip if already queued.
|
|
340
|
+
setToolUseConfirmQueue(queue => {
|
|
341
|
+
if (queue.some(q => q.toolUseID === parsed.tool_use_id)) {
|
|
342
|
+
return queue
|
|
343
|
+
}
|
|
344
|
+
return [...queue, entry]
|
|
345
|
+
})
|
|
346
|
+
} else {
|
|
347
|
+
logForDebugging(
|
|
348
|
+
`[InboxPoller] ToolUseConfirmQueue unavailable, dropping permission request from ${parsed.agent_id}`,
|
|
349
|
+
)
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// Send desktop notification for the first request
|
|
354
|
+
const firstParsed = isPermissionRequest(permissionRequests[0]?.text ?? '')
|
|
355
|
+
if (firstParsed && !isLoading && !focusedInputDialog) {
|
|
356
|
+
void sendNotification(
|
|
357
|
+
{
|
|
358
|
+
message: `${firstParsed.agent_id} needs permission for ${firstParsed.tool_name}`,
|
|
359
|
+
notificationType: 'worker_permission_prompt',
|
|
360
|
+
},
|
|
361
|
+
terminal,
|
|
362
|
+
)
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// Handle permission responses (worker side) - invoke registered callbacks
|
|
367
|
+
if (permissionResponses.length > 0 && isTeammate()) {
|
|
368
|
+
logForDebugging(
|
|
369
|
+
`[InboxPoller] Found ${permissionResponses.length} permission response(s)`,
|
|
370
|
+
)
|
|
371
|
+
|
|
372
|
+
for (const m of permissionResponses) {
|
|
373
|
+
const parsed = isPermissionResponse(m.text)
|
|
374
|
+
if (!parsed) continue
|
|
375
|
+
|
|
376
|
+
if (hasPermissionCallback(parsed.request_id)) {
|
|
377
|
+
logForDebugging(
|
|
378
|
+
`[InboxPoller] Processing permission response for ${parsed.request_id}: ${parsed.subtype}`,
|
|
379
|
+
)
|
|
380
|
+
|
|
381
|
+
if (parsed.subtype === 'success') {
|
|
382
|
+
processMailboxPermissionResponse({
|
|
383
|
+
requestId: parsed.request_id,
|
|
384
|
+
decision: 'approved',
|
|
385
|
+
updatedInput: parsed.response?.updated_input,
|
|
386
|
+
permissionUpdates: parsed.response?.permission_updates,
|
|
387
|
+
})
|
|
388
|
+
} else {
|
|
389
|
+
processMailboxPermissionResponse({
|
|
390
|
+
requestId: parsed.request_id,
|
|
391
|
+
decision: 'rejected',
|
|
392
|
+
feedback: parsed.error,
|
|
393
|
+
})
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// Handle sandbox permission requests (leader side) - add to workerSandboxPermissions queue
|
|
400
|
+
if (
|
|
401
|
+
sandboxPermissionRequests.length > 0 &&
|
|
402
|
+
isTeamLead(currentAppState.teamContext)
|
|
403
|
+
) {
|
|
404
|
+
logForDebugging(
|
|
405
|
+
`[InboxPoller] Found ${sandboxPermissionRequests.length} sandbox permission request(s)`,
|
|
406
|
+
)
|
|
407
|
+
|
|
408
|
+
const newSandboxRequests: Array<{
|
|
409
|
+
requestId: string
|
|
410
|
+
workerId: string
|
|
411
|
+
workerName: string
|
|
412
|
+
workerColor?: string
|
|
413
|
+
host: string
|
|
414
|
+
createdAt: number
|
|
415
|
+
}> = []
|
|
416
|
+
|
|
417
|
+
for (const m of sandboxPermissionRequests) {
|
|
418
|
+
const parsed = isSandboxPermissionRequest(m.text)
|
|
419
|
+
if (!parsed) continue
|
|
420
|
+
|
|
421
|
+
// Validate required nested fields to prevent crashes from malformed messages
|
|
422
|
+
if (!parsed.hostPattern?.host) {
|
|
423
|
+
logForDebugging(
|
|
424
|
+
`[InboxPoller] Invalid sandbox permission request: missing hostPattern.host`,
|
|
425
|
+
)
|
|
426
|
+
continue
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
newSandboxRequests.push({
|
|
430
|
+
requestId: parsed.requestId,
|
|
431
|
+
workerId: parsed.workerId,
|
|
432
|
+
workerName: parsed.workerName,
|
|
433
|
+
workerColor: parsed.workerColor,
|
|
434
|
+
host: parsed.hostPattern.host,
|
|
435
|
+
createdAt: parsed.createdAt,
|
|
436
|
+
})
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
if (newSandboxRequests.length > 0) {
|
|
440
|
+
setAppState(prev => ({
|
|
441
|
+
...prev,
|
|
442
|
+
workerSandboxPermissions: {
|
|
443
|
+
...prev.workerSandboxPermissions,
|
|
444
|
+
queue: [
|
|
445
|
+
...prev.workerSandboxPermissions.queue,
|
|
446
|
+
...newSandboxRequests,
|
|
447
|
+
],
|
|
448
|
+
},
|
|
449
|
+
}))
|
|
450
|
+
|
|
451
|
+
// Send desktop notification for the first new request
|
|
452
|
+
const firstRequest = newSandboxRequests[0]
|
|
453
|
+
if (firstRequest && !isLoading && !focusedInputDialog) {
|
|
454
|
+
void sendNotification(
|
|
455
|
+
{
|
|
456
|
+
message: `${firstRequest.workerName} needs network access to ${firstRequest.host}`,
|
|
457
|
+
notificationType: 'worker_permission_prompt',
|
|
458
|
+
},
|
|
459
|
+
terminal,
|
|
460
|
+
)
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
// Handle sandbox permission responses (worker side) - invoke registered callbacks
|
|
466
|
+
if (sandboxPermissionResponses.length > 0 && isTeammate()) {
|
|
467
|
+
logForDebugging(
|
|
468
|
+
`[InboxPoller] Found ${sandboxPermissionResponses.length} sandbox permission response(s)`,
|
|
469
|
+
)
|
|
470
|
+
|
|
471
|
+
for (const m of sandboxPermissionResponses) {
|
|
472
|
+
const parsed = isSandboxPermissionResponse(m.text)
|
|
473
|
+
if (!parsed) continue
|
|
474
|
+
|
|
475
|
+
// Check if we have a registered callback for this request
|
|
476
|
+
if (hasSandboxPermissionCallback(parsed.requestId)) {
|
|
477
|
+
logForDebugging(
|
|
478
|
+
`[InboxPoller] Processing sandbox permission response for ${parsed.requestId}: allow=${parsed.allow}`,
|
|
479
|
+
)
|
|
480
|
+
|
|
481
|
+
// Process the response using the exported function
|
|
482
|
+
processSandboxPermissionResponse({
|
|
483
|
+
requestId: parsed.requestId,
|
|
484
|
+
host: parsed.host,
|
|
485
|
+
allow: parsed.allow,
|
|
486
|
+
})
|
|
487
|
+
|
|
488
|
+
// Clear the pending sandbox request indicator
|
|
489
|
+
setAppState(prev => ({
|
|
490
|
+
...prev,
|
|
491
|
+
pendingSandboxRequest: null,
|
|
492
|
+
}))
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
// Handle team permission updates (teammate side) - apply permission to context
|
|
498
|
+
if (teamPermissionUpdates.length > 0 && isTeammate()) {
|
|
499
|
+
logForDebugging(
|
|
500
|
+
`[InboxPoller] Found ${teamPermissionUpdates.length} team permission update(s)`,
|
|
501
|
+
)
|
|
502
|
+
|
|
503
|
+
for (const m of teamPermissionUpdates) {
|
|
504
|
+
const parsed = isTeamPermissionUpdate(m.text)
|
|
505
|
+
if (!parsed) {
|
|
506
|
+
logForDebugging(
|
|
507
|
+
`[InboxPoller] Failed to parse team permission update: ${m.text.substring(0, 100)}`,
|
|
508
|
+
)
|
|
509
|
+
continue
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
// Validate required nested fields to prevent crashes from malformed messages
|
|
513
|
+
if (
|
|
514
|
+
!parsed.permissionUpdate?.rules ||
|
|
515
|
+
!parsed.permissionUpdate?.behavior
|
|
516
|
+
) {
|
|
517
|
+
logForDebugging(
|
|
518
|
+
`[InboxPoller] Invalid team permission update: missing permissionUpdate.rules or permissionUpdate.behavior`,
|
|
519
|
+
)
|
|
520
|
+
continue
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
// Apply the permission update to the teammate's context
|
|
524
|
+
logForDebugging(
|
|
525
|
+
`[InboxPoller] Applying team permission update: ${parsed.toolName} allowed in ${parsed.directoryPath}`,
|
|
526
|
+
)
|
|
527
|
+
logForDebugging(
|
|
528
|
+
`[InboxPoller] Permission update rules: ${jsonStringify(parsed.permissionUpdate.rules)}`,
|
|
529
|
+
)
|
|
530
|
+
|
|
531
|
+
setAppState(prev => {
|
|
532
|
+
const updated = applyPermissionUpdate(prev.toolPermissionContext, {
|
|
533
|
+
type: 'addRules',
|
|
534
|
+
rules: parsed.permissionUpdate.rules,
|
|
535
|
+
behavior: parsed.permissionUpdate.behavior,
|
|
536
|
+
destination: 'session',
|
|
537
|
+
})
|
|
538
|
+
logForDebugging(
|
|
539
|
+
`[InboxPoller] Updated session allow rules: ${jsonStringify(updated.alwaysAllowRules.session)}`,
|
|
540
|
+
)
|
|
541
|
+
return {
|
|
542
|
+
...prev,
|
|
543
|
+
toolPermissionContext: updated,
|
|
544
|
+
}
|
|
545
|
+
})
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
// Handle mode set requests (teammate side) - team lead changing teammate's mode
|
|
550
|
+
if (modeSetRequests.length > 0 && isTeammate()) {
|
|
551
|
+
logForDebugging(
|
|
552
|
+
`[InboxPoller] Found ${modeSetRequests.length} mode set request(s)`,
|
|
553
|
+
)
|
|
554
|
+
|
|
555
|
+
for (const m of modeSetRequests) {
|
|
556
|
+
// Only accept mode changes from team-lead
|
|
557
|
+
if (m.from !== 'team-lead') {
|
|
558
|
+
logForDebugging(
|
|
559
|
+
`[InboxPoller] Ignoring mode set request from non-team-lead: ${m.from}`,
|
|
560
|
+
)
|
|
561
|
+
continue
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
const parsed = isModeSetRequest(m.text)
|
|
565
|
+
if (!parsed) {
|
|
566
|
+
logForDebugging(
|
|
567
|
+
`[InboxPoller] Failed to parse mode set request: ${m.text.substring(0, 100)}`,
|
|
568
|
+
)
|
|
569
|
+
continue
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
const targetMode = permissionModeFromString(parsed.mode)
|
|
573
|
+
logForDebugging(
|
|
574
|
+
`[InboxPoller] Applying mode change from team-lead: ${targetMode}`,
|
|
575
|
+
)
|
|
576
|
+
|
|
577
|
+
// Update local permission context
|
|
578
|
+
setAppState(prev => ({
|
|
579
|
+
...prev,
|
|
580
|
+
toolPermissionContext: applyPermissionUpdate(
|
|
581
|
+
prev.toolPermissionContext,
|
|
582
|
+
{
|
|
583
|
+
type: 'setMode',
|
|
584
|
+
mode: toExternalPermissionMode(targetMode),
|
|
585
|
+
destination: 'session',
|
|
586
|
+
},
|
|
587
|
+
),
|
|
588
|
+
}))
|
|
589
|
+
|
|
590
|
+
// Update config.json so team lead can see the new mode
|
|
591
|
+
const teamName = currentAppState.teamContext?.teamName
|
|
592
|
+
const agentName = getAgentName()
|
|
593
|
+
if (teamName && agentName) {
|
|
594
|
+
setMemberMode(teamName, agentName, targetMode)
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
// Handle plan approval requests (leader side) - auto-approve and write response to teammate inbox
|
|
600
|
+
if (
|
|
601
|
+
planApprovalRequests.length > 0 &&
|
|
602
|
+
isTeamLead(currentAppState.teamContext)
|
|
603
|
+
) {
|
|
604
|
+
logForDebugging(
|
|
605
|
+
`[InboxPoller] Found ${planApprovalRequests.length} plan approval request(s), auto-approving`,
|
|
606
|
+
)
|
|
607
|
+
|
|
608
|
+
const teamName = currentAppState.teamContext?.teamName
|
|
609
|
+
const leaderExternalMode = toExternalPermissionMode(
|
|
610
|
+
currentAppState.toolPermissionContext.mode,
|
|
611
|
+
)
|
|
612
|
+
const modeToInherit =
|
|
613
|
+
leaderExternalMode === 'plan' ? 'default' : leaderExternalMode
|
|
614
|
+
|
|
615
|
+
for (const m of planApprovalRequests) {
|
|
616
|
+
const parsed = isPlanApprovalRequest(m.text)
|
|
617
|
+
if (!parsed) continue
|
|
618
|
+
|
|
619
|
+
// Write approval response to teammate's inbox
|
|
620
|
+
const approvalResponse = {
|
|
621
|
+
type: 'plan_approval_response',
|
|
622
|
+
requestId: parsed.requestId,
|
|
623
|
+
approved: true,
|
|
624
|
+
timestamp: new Date().toISOString(),
|
|
625
|
+
permissionMode: modeToInherit,
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
void writeToMailbox(
|
|
629
|
+
m.from,
|
|
630
|
+
{
|
|
631
|
+
from: TEAM_LEAD_NAME,
|
|
632
|
+
text: jsonStringify(approvalResponse),
|
|
633
|
+
timestamp: new Date().toISOString(),
|
|
634
|
+
},
|
|
635
|
+
teamName,
|
|
636
|
+
)
|
|
637
|
+
|
|
638
|
+
// Update in-process teammate task state if applicable
|
|
639
|
+
const taskId = findInProcessTeammateTaskId(m.from, currentAppState)
|
|
640
|
+
if (taskId) {
|
|
641
|
+
handlePlanApprovalResponse(
|
|
642
|
+
taskId,
|
|
643
|
+
{
|
|
644
|
+
type: 'plan_approval_response',
|
|
645
|
+
requestId: parsed.requestId,
|
|
646
|
+
approved: true,
|
|
647
|
+
timestamp: new Date().toISOString(),
|
|
648
|
+
permissionMode: modeToInherit,
|
|
649
|
+
},
|
|
650
|
+
setAppState,
|
|
651
|
+
)
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
logForDebugging(
|
|
655
|
+
`[InboxPoller] Auto-approved plan from ${m.from} (request ${parsed.requestId})`,
|
|
656
|
+
)
|
|
657
|
+
|
|
658
|
+
// Still pass through as a regular message so the model has context
|
|
659
|
+
// about what the teammate is doing, but the approval is already sent
|
|
660
|
+
regularMessages.push(m)
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
// Handle shutdown requests (teammate side) - preserve JSON for UI rendering
|
|
665
|
+
if (shutdownRequests.length > 0 && isTeammate()) {
|
|
666
|
+
logForDebugging(
|
|
667
|
+
`[InboxPoller] Found ${shutdownRequests.length} shutdown request(s)`,
|
|
668
|
+
)
|
|
669
|
+
|
|
670
|
+
// Pass through shutdown requests - the UI component will render them nicely
|
|
671
|
+
// and the model will receive instructions via the tool prompt documentation
|
|
672
|
+
for (const m of shutdownRequests) {
|
|
673
|
+
regularMessages.push(m)
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
// Handle shutdown approvals (leader side) - kill the teammate's pane
|
|
678
|
+
if (
|
|
679
|
+
shutdownApprovals.length > 0 &&
|
|
680
|
+
isTeamLead(currentAppState.teamContext)
|
|
681
|
+
) {
|
|
682
|
+
logForDebugging(
|
|
683
|
+
`[InboxPoller] Found ${shutdownApprovals.length} shutdown approval(s)`,
|
|
684
|
+
)
|
|
685
|
+
|
|
686
|
+
for (const m of shutdownApprovals) {
|
|
687
|
+
const parsed = isShutdownApproved(m.text)
|
|
688
|
+
if (!parsed) continue
|
|
689
|
+
|
|
690
|
+
// Kill the pane if we have the info (pane-based teammates)
|
|
691
|
+
if (parsed.paneId && parsed.backendType) {
|
|
692
|
+
void (async () => {
|
|
693
|
+
try {
|
|
694
|
+
// Ensure backend classes are imported (no subprocess probes)
|
|
695
|
+
await ensureBackendsRegistered()
|
|
696
|
+
const insideTmux = await isInsideTmux()
|
|
697
|
+
const backend = getBackendByType(
|
|
698
|
+
parsed.backendType as PaneBackendType,
|
|
699
|
+
)
|
|
700
|
+
const success = await backend?.killPane(
|
|
701
|
+
parsed.paneId!,
|
|
702
|
+
!insideTmux,
|
|
703
|
+
)
|
|
704
|
+
logForDebugging(
|
|
705
|
+
`[InboxPoller] Killed pane ${parsed.paneId} for ${parsed.from}: ${success}`,
|
|
706
|
+
)
|
|
707
|
+
} catch (error) {
|
|
708
|
+
logForDebugging(
|
|
709
|
+
`[InboxPoller] Failed to kill pane for ${parsed.from}: ${error}`,
|
|
710
|
+
)
|
|
711
|
+
}
|
|
712
|
+
})()
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
// Remove the teammate from teamContext.teammates so the count is accurate
|
|
716
|
+
const teammateToRemove = parsed.from
|
|
717
|
+
if (teammateToRemove && currentAppState.teamContext?.teammates) {
|
|
718
|
+
// Find the teammate ID by name
|
|
719
|
+
const teammateId = Object.entries(
|
|
720
|
+
currentAppState.teamContext.teammates,
|
|
721
|
+
).find(([, t]) => t.name === teammateToRemove)?.[0]
|
|
722
|
+
|
|
723
|
+
if (teammateId) {
|
|
724
|
+
// Remove from team file (leader owns team file mutations)
|
|
725
|
+
const teamName = currentAppState.teamContext?.teamName
|
|
726
|
+
if (teamName) {
|
|
727
|
+
removeTeammateFromTeamFile(teamName, {
|
|
728
|
+
agentId: teammateId,
|
|
729
|
+
name: teammateToRemove,
|
|
730
|
+
})
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
// Unassign tasks and build notification message
|
|
734
|
+
const { notificationMessage } = teamName
|
|
735
|
+
? await unassignTeammateTasks(
|
|
736
|
+
teamName,
|
|
737
|
+
teammateId,
|
|
738
|
+
teammateToRemove,
|
|
739
|
+
'shutdown',
|
|
740
|
+
)
|
|
741
|
+
: { notificationMessage: `${teammateToRemove} has shut down.` }
|
|
742
|
+
|
|
743
|
+
setAppState(prev => {
|
|
744
|
+
if (!prev.teamContext?.teammates) return prev
|
|
745
|
+
if (!(teammateId in prev.teamContext.teammates)) return prev
|
|
746
|
+
const { [teammateId]: _, ...remainingTeammates } =
|
|
747
|
+
prev.teamContext.teammates
|
|
748
|
+
|
|
749
|
+
// Mark the teammate's task as completed so hasRunningTeammates
|
|
750
|
+
// becomes false and the spinner stops. Without this, out-of-process
|
|
751
|
+
// (tmux) teammate tasks stay status:'running' forever because
|
|
752
|
+
// only in-process teammates have a runner that sets 'completed'.
|
|
753
|
+
const updatedTasks = { ...prev.tasks }
|
|
754
|
+
for (const [tid, task] of Object.entries(updatedTasks)) {
|
|
755
|
+
if (
|
|
756
|
+
isInProcessTeammateTask(task) &&
|
|
757
|
+
task.identity.agentId === teammateId
|
|
758
|
+
) {
|
|
759
|
+
updatedTasks[tid] = {
|
|
760
|
+
...task,
|
|
761
|
+
status: 'completed' as const,
|
|
762
|
+
endTime: Date.now(),
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
return {
|
|
768
|
+
...prev,
|
|
769
|
+
tasks: updatedTasks,
|
|
770
|
+
teamContext: {
|
|
771
|
+
...prev.teamContext,
|
|
772
|
+
teammates: remainingTeammates,
|
|
773
|
+
},
|
|
774
|
+
inbox: {
|
|
775
|
+
messages: [
|
|
776
|
+
...prev.inbox.messages,
|
|
777
|
+
{
|
|
778
|
+
id: randomUUID(),
|
|
779
|
+
from: 'system',
|
|
780
|
+
text: jsonStringify({
|
|
781
|
+
type: 'teammate_terminated',
|
|
782
|
+
message: notificationMessage,
|
|
783
|
+
}),
|
|
784
|
+
timestamp: new Date().toISOString(),
|
|
785
|
+
status: 'pending' as const,
|
|
786
|
+
},
|
|
787
|
+
],
|
|
788
|
+
},
|
|
789
|
+
}
|
|
790
|
+
})
|
|
791
|
+
logForDebugging(
|
|
792
|
+
`[InboxPoller] Removed ${teammateToRemove} (${teammateId}) from teamContext`,
|
|
793
|
+
)
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
// Pass through for UI rendering - the component will render it nicely
|
|
798
|
+
regularMessages.push(m)
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
// Process regular teammate messages (existing logic)
|
|
803
|
+
if (regularMessages.length === 0) {
|
|
804
|
+
// No regular messages, but we may have processed non-regular messages
|
|
805
|
+
// (permissions, shutdown requests, etc.) above — mark those as read.
|
|
806
|
+
markRead()
|
|
807
|
+
return
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
// Format messages with XML wrapper for Claude (include color if available)
|
|
811
|
+
// Transform plan approval requests to include instructions for Claude
|
|
812
|
+
const formatted = regularMessages
|
|
813
|
+
.map(m => {
|
|
814
|
+
const colorAttr = m.color ? ` color="${m.color}"` : ''
|
|
815
|
+
const summaryAttr = m.summary ? ` summary="${m.summary}"` : ''
|
|
816
|
+
const messageContent = m.text
|
|
817
|
+
|
|
818
|
+
return `<${TEAMMATE_MESSAGE_TAG} teammate_id="${m.from}"${colorAttr}${summaryAttr}>\n${messageContent}\n</${TEAMMATE_MESSAGE_TAG}>`
|
|
819
|
+
})
|
|
820
|
+
.join('\n\n')
|
|
821
|
+
|
|
822
|
+
// Helper to queue messages in AppState for later delivery
|
|
823
|
+
const queueMessages = () => {
|
|
824
|
+
setAppState(prev => ({
|
|
825
|
+
...prev,
|
|
826
|
+
inbox: {
|
|
827
|
+
messages: [
|
|
828
|
+
...prev.inbox.messages,
|
|
829
|
+
...regularMessages.map(m => ({
|
|
830
|
+
id: randomUUID(),
|
|
831
|
+
from: m.from,
|
|
832
|
+
text: m.text,
|
|
833
|
+
timestamp: m.timestamp,
|
|
834
|
+
status: 'pending' as const,
|
|
835
|
+
color: m.color,
|
|
836
|
+
summary: m.summary,
|
|
837
|
+
})),
|
|
838
|
+
],
|
|
839
|
+
},
|
|
840
|
+
}))
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
if (!isLoading && !focusedInputDialog) {
|
|
844
|
+
// IDLE: Submit as new turn immediately
|
|
845
|
+
logForDebugging(`[InboxPoller] Session idle, submitting immediately`)
|
|
846
|
+
const submitted = onSubmitTeammateMessage(formatted)
|
|
847
|
+
if (!submitted) {
|
|
848
|
+
// Submission rejected (query already running), queue for later
|
|
849
|
+
logForDebugging(
|
|
850
|
+
`[InboxPoller] Submission rejected, queuing for later delivery`,
|
|
851
|
+
)
|
|
852
|
+
queueMessages()
|
|
853
|
+
}
|
|
854
|
+
} else {
|
|
855
|
+
// BUSY: Add to inbox queue for UI display + later delivery
|
|
856
|
+
logForDebugging(`[InboxPoller] Session busy, queuing for later delivery`)
|
|
857
|
+
queueMessages()
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
// Mark messages as read only after they have been successfully delivered
|
|
861
|
+
// or reliably queued in AppState. This prevents permanent message loss
|
|
862
|
+
// when the session is busy — if we crash before this point, the messages
|
|
863
|
+
// will be re-read on the next poll cycle instead of being silently dropped.
|
|
864
|
+
markRead()
|
|
865
|
+
}, [
|
|
866
|
+
enabled,
|
|
867
|
+
isLoading,
|
|
868
|
+
focusedInputDialog,
|
|
869
|
+
onSubmitTeammateMessage,
|
|
870
|
+
setAppState,
|
|
871
|
+
terminal,
|
|
872
|
+
store,
|
|
873
|
+
])
|
|
874
|
+
|
|
875
|
+
// When session becomes idle, deliver any pending messages and clean up processed ones
|
|
876
|
+
useEffect(() => {
|
|
877
|
+
if (!enabled) return
|
|
878
|
+
|
|
879
|
+
// Skip if busy or in a dialog
|
|
880
|
+
if (isLoading || focusedInputDialog) {
|
|
881
|
+
return
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
// Use ref to avoid dependency on appState object (prevents infinite loop)
|
|
885
|
+
const currentAppState = store.getState()
|
|
886
|
+
const agentName = getAgentNameToPoll(currentAppState)
|
|
887
|
+
if (!agentName) return
|
|
888
|
+
|
|
889
|
+
const pendingMessages = currentAppState.inbox.messages.filter(
|
|
890
|
+
m => m.status === 'pending',
|
|
891
|
+
)
|
|
892
|
+
const processedMessages = currentAppState.inbox.messages.filter(
|
|
893
|
+
m => m.status === 'processed',
|
|
894
|
+
)
|
|
895
|
+
|
|
896
|
+
// Clean up processed messages (they were already delivered mid-turn as attachments)
|
|
897
|
+
if (processedMessages.length > 0) {
|
|
898
|
+
logForDebugging(
|
|
899
|
+
`[InboxPoller] Cleaning up ${processedMessages.length} processed message(s) that were delivered mid-turn`,
|
|
900
|
+
)
|
|
901
|
+
const processedIds = new Set(processedMessages.map(m => m.id))
|
|
902
|
+
setAppState(prev => ({
|
|
903
|
+
...prev,
|
|
904
|
+
inbox: {
|
|
905
|
+
messages: prev.inbox.messages.filter(m => !processedIds.has(m.id)),
|
|
906
|
+
},
|
|
907
|
+
}))
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
// No pending messages to deliver
|
|
911
|
+
if (pendingMessages.length === 0) return
|
|
912
|
+
|
|
913
|
+
logForDebugging(
|
|
914
|
+
`[InboxPoller] Session idle, delivering ${pendingMessages.length} pending message(s)`,
|
|
915
|
+
)
|
|
916
|
+
|
|
917
|
+
// Format messages with XML wrapper for Claude (include color if available)
|
|
918
|
+
const formatted = pendingMessages
|
|
919
|
+
.map(m => {
|
|
920
|
+
const colorAttr = m.color ? ` color="${m.color}"` : ''
|
|
921
|
+
const summaryAttr = m.summary ? ` summary="${m.summary}"` : ''
|
|
922
|
+
return `<${TEAMMATE_MESSAGE_TAG} teammate_id="${m.from}"${colorAttr}${summaryAttr}>\n${m.text}\n</${TEAMMATE_MESSAGE_TAG}>`
|
|
923
|
+
})
|
|
924
|
+
.join('\n\n')
|
|
925
|
+
|
|
926
|
+
// Try to submit - only clear messages if successful
|
|
927
|
+
const submitted = onSubmitTeammateMessage(formatted)
|
|
928
|
+
if (submitted) {
|
|
929
|
+
// Clear the specific messages we just submitted by their IDs
|
|
930
|
+
const submittedIds = new Set(pendingMessages.map(m => m.id))
|
|
931
|
+
setAppState(prev => ({
|
|
932
|
+
...prev,
|
|
933
|
+
inbox: {
|
|
934
|
+
messages: prev.inbox.messages.filter(m => !submittedIds.has(m.id)),
|
|
935
|
+
},
|
|
936
|
+
}))
|
|
937
|
+
} else {
|
|
938
|
+
logForDebugging(
|
|
939
|
+
`[InboxPoller] Submission rejected, keeping messages queued`,
|
|
940
|
+
)
|
|
941
|
+
}
|
|
942
|
+
}, [
|
|
943
|
+
enabled,
|
|
944
|
+
isLoading,
|
|
945
|
+
focusedInputDialog,
|
|
946
|
+
onSubmitTeammateMessage,
|
|
947
|
+
setAppState,
|
|
948
|
+
inboxMessageCount,
|
|
949
|
+
store,
|
|
950
|
+
])
|
|
951
|
+
|
|
952
|
+
// Poll if running as a teammate or as a team lead
|
|
953
|
+
const shouldPoll = enabled && !!getAgentNameToPoll(store.getState())
|
|
954
|
+
useInterval(() => void poll(), shouldPoll ? INBOX_POLL_INTERVAL_MS : null)
|
|
955
|
+
|
|
956
|
+
// Initial poll on mount (only once)
|
|
957
|
+
const hasDoneInitialPollRef = useRef(false)
|
|
958
|
+
useEffect(() => {
|
|
959
|
+
if (!enabled) return
|
|
960
|
+
if (hasDoneInitialPollRef.current) return
|
|
961
|
+
// Use store.getState() to avoid dependency on appState object
|
|
962
|
+
if (getAgentNameToPoll(store.getState())) {
|
|
963
|
+
hasDoneInitialPollRef.current = true
|
|
964
|
+
void poll()
|
|
965
|
+
}
|
|
966
|
+
// Note: poll uses store.getState() (not appState) so it won't re-run on appState changes
|
|
967
|
+
// The ref guard is a safety measure to ensure initial poll only happens once
|
|
968
|
+
}, [enabled, poll, store])
|
|
969
|
+
}
|