@iaforged/context-code 2.0.1 → 2.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.
Files changed (141) hide show
  1. package/dist/src/bridge/bridgeMain.js +1 -1
  2. package/dist/src/bridge/types.js +1 -1
  3. package/dist/src/cli/handlers/auth.js +1 -1
  4. package/dist/src/cli/handlers/mcp.js +1 -1
  5. package/dist/src/cli/print.js +1 -1
  6. package/dist/src/commands/copy/copy.js +1 -1
  7. package/dist/src/commands/heartbeat/heartbeat.js +1 -0
  8. package/dist/src/commands/heartbeat/index.js +1 -0
  9. package/dist/src/commands/insights.js +1 -1
  10. package/dist/src/commands/install-github-app/ExistingWorkflowStep.js +1 -1
  11. package/dist/src/commands/install-github-app/InstallAppStep.js +1 -1
  12. package/dist/src/commands/install-github-app/OAuthFlowStep.js +1 -1
  13. package/dist/src/commands/install-github-app/SuccessStep.js +1 -1
  14. package/dist/src/commands/install-github-app/setupGitHubActions.js +1 -1
  15. package/dist/src/commands/login-openai/index.js +1 -1
  16. package/dist/src/commands/mobile/mobile.js +1 -1
  17. package/dist/src/commands/remote-setup/remote-setup.js +1 -1
  18. package/dist/src/commands/swarm-auto/swarmAuto.js +1 -1
  19. package/dist/src/commands/timeline/timeline.js +1 -1
  20. package/dist/src/commands/webapp/webapp.js +1 -1
  21. package/dist/src/commands.js +1 -1
  22. package/dist/src/components/ApproveApiKey.js +1 -1
  23. package/dist/src/components/ChannelDowngradeDialog.js +1 -1
  24. package/dist/src/components/ClaudeCodeHint/PluginHintMenu.js +1 -1
  25. package/dist/src/components/ConsoleOAuthFlow.js +1 -1
  26. package/dist/src/components/CostThresholdDialog.js +1 -1
  27. package/dist/src/components/CtrlOToExpand.js +1 -1
  28. package/dist/src/components/CustomSelect/select.js +1 -1
  29. package/dist/src/components/DesktopHandoff.js +1 -1
  30. package/dist/src/components/DesktopUpsell/DesktopUpsellStartup.js +1 -1
  31. package/dist/src/components/ExportDialog.js +1 -1
  32. package/dist/src/components/Feedback.js +1 -1
  33. package/dist/src/components/FeedbackSurvey/FeedbackSurvey.js +1 -1
  34. package/dist/src/components/FeedbackSurvey/FeedbackSurveyView.js +1 -1
  35. package/dist/src/components/IdeAutoConnectDialog.js +1 -1
  36. package/dist/src/components/IdeOnboardingDialog.js +1 -1
  37. package/dist/src/components/IdleReturnDialog.js +1 -1
  38. package/dist/src/components/InterruptedByUser.js +1 -1
  39. package/dist/src/components/InvalidConfigDialog.js +1 -1
  40. package/dist/src/components/InvalidSettingsDialog.js +1 -1
  41. package/dist/src/components/LanguagePicker.js +1 -1
  42. package/dist/src/components/LogSelector.js +1 -1
  43. package/dist/src/components/LogoV2/ChannelsNotice.js +1 -1
  44. package/dist/src/components/LogoV2/LogoV2.js +1 -1
  45. package/dist/src/components/LogoV2/feedConfigs.js +1 -1
  46. package/dist/src/components/LspRecommendation/LspRecommendationMenu.js +1 -1
  47. package/dist/src/components/MCPServerApprovalDialog.js +1 -1
  48. package/dist/src/components/MCPServerDesktopImportDialog.js +1 -1
  49. package/dist/src/components/ManagedSettingsSecurityDialog/ManagedSettingsSecurityDialog.js +1 -1
  50. package/dist/src/components/MessageSelector.js +1 -1
  51. package/dist/src/components/OutputStylePicker.js +1 -1
  52. package/dist/src/components/PromptInput/PromptInput.js +1 -1
  53. package/dist/src/components/RemoteCallout.js +1 -1
  54. package/dist/src/components/ResumeTask.js +1 -1
  55. package/dist/src/components/Settings/Config.js +1 -1
  56. package/dist/src/components/ShowInIDEPrompt.js +1 -1
  57. package/dist/src/components/Stats.js +1 -1
  58. package/dist/src/components/TagTabs.js +1 -1
  59. package/dist/src/components/TeleportError.js +1 -1
  60. package/dist/src/components/TeleportResumeWrapper.js +1 -1
  61. package/dist/src/components/TextInput.js +1 -1
  62. package/dist/src/components/agents/new-agent-creation/wizard-steps/MethodStep.js +1 -1
  63. package/dist/src/components/design-system/KeyboardShortcutHint.js +1 -1
  64. package/dist/src/components/diff/DiffDetailView.js +1 -1
  65. package/dist/src/components/grove/Grove.js +1 -1
  66. package/dist/src/components/hooks/SelectEventMode.js +1 -1
  67. package/dist/src/components/hooks/SelectHookMode.js +1 -1
  68. package/dist/src/components/hooks/SelectMatcherMode.js +1 -1
  69. package/dist/src/components/hooks/ViewHookMode.js +1 -1
  70. package/dist/src/components/mcp/MCPAgentServerMenu.js +1 -1
  71. package/dist/src/components/mcp/utils/reconnectHelpers.js +1 -1
  72. package/dist/src/components/memory/MemoryFileSelector.js +1 -1
  73. package/dist/src/components/messages/AssistantTextMessage.js +1 -1
  74. package/dist/src/components/messages/PlanApprovalMessage.js +1 -1
  75. package/dist/src/components/messages/ShutdownMessage.js +1 -1
  76. package/dist/src/components/messages/SystemAPIErrorMessage.js +1 -1
  77. package/dist/src/components/messages/UserPlanMessage.js +1 -1
  78. package/dist/src/components/permissions/AskUserQuestionPermissionRequest/PreviewQuestionView.js +1 -1
  79. package/dist/src/components/permissions/ComputerUseApproval/ComputerUseApproval.js +1 -1
  80. package/dist/src/components/permissions/FileEditPermissionRequest/FileEditPermissionRequest.js +1 -1
  81. package/dist/src/components/permissions/FilePermissionDialog/FilePermissionDialog.js +1 -1
  82. package/dist/src/components/permissions/FilePermissionDialog/permissionOptions.js +1 -1
  83. package/dist/src/components/permissions/FileWritePermissionRequest/FileWritePermissionRequest.js +1 -1
  84. package/dist/src/components/permissions/FilesystemPermissionRequest/FilesystemPermissionRequest.js +1 -1
  85. package/dist/src/components/permissions/PermissionRequest.js +1 -1
  86. package/dist/src/components/permissions/SedEditPermissionRequest/SedEditPermissionRequest.js +1 -1
  87. package/dist/src/components/permissions/SkillPermissionRequest/SkillPermissionRequest.js +1 -1
  88. package/dist/src/components/permissions/WebFetchPermissionRequest/WebFetchPermissionRequest.js +1 -1
  89. package/dist/src/components/permissions/rules/AddPermissionRules.js +1 -1
  90. package/dist/src/components/permissions/rules/AddWorkspaceDirectory.js +1 -1
  91. package/dist/src/components/permissions/rules/PermissionRuleList.js +1 -1
  92. package/dist/src/components/permissions/rules/RemoveWorkspaceDirectory.js +1 -1
  93. package/dist/src/components/sandbox/SandboxConfigTab.js +1 -1
  94. package/dist/src/components/sandbox/SandboxOverridesTab.js +1 -1
  95. package/dist/src/components/tasks/RemoteSessionDetailDialog.js +1 -1
  96. package/dist/src/constants/outputStyles.js +1 -1
  97. package/dist/src/entrypoints/cli.js +1 -1
  98. package/dist/src/hooks/notifs/useCanSwitchToExistingSubscription.js +1 -1
  99. package/dist/src/main.js +1 -1
  100. package/dist/src/projectOnboardingState.js +1 -1
  101. package/dist/src/screens/REPL.js +1 -1
  102. package/dist/src/services/api/errors.js +1 -1
  103. package/dist/src/services/api/filesApi.js +1 -1
  104. package/dist/src/services/tips/tipRegistry.js +1 -1
  105. package/dist/src/tasks/RemoteAgentTask/RemoteAgentTask.js +1 -1
  106. package/dist/src/tools/AgentTool/AgentTool.js +1 -1
  107. package/dist/src/tools/ConfigTool/supportedSettings.js +1 -1
  108. package/dist/src/tools/EnterWorktreeTool/EnterWorktreeTool.js +1 -1
  109. package/dist/src/tools/ExitWorktreeTool/ExitWorktreeTool.js +1 -1
  110. package/dist/src/tools/WebFetchTool/WebFetchTool.js +1 -1
  111. package/dist/src/utils/computerUse/cleanup.js +1 -1
  112. package/dist/src/utils/computerUse/wrapper.js +1 -1
  113. package/dist/src/utils/fileHistory.js +1 -1
  114. package/dist/src/utils/heartbeat.js +1 -0
  115. package/dist/src/utils/model/providers.js +1 -1
  116. package/dist/src/utils/permissions/filesystem.js +1 -1
  117. package/dist/src/utils/permissions/permissions.js +1 -1
  118. package/dist/src/utils/processUserInput/processSlashCommand.js +1 -1
  119. package/dist/src/utils/releaseNoteTranslations.js +1 -1
  120. package/dist/src/utils/shell/shellToolUtils.js +1 -1
  121. package/dist/src/utils/sshMcp/common.js +1 -0
  122. package/dist/src/utils/sshMcp/setup.js +1 -0
  123. package/dist/src/utils/sshMcp/sshMcpServer.js +1 -0
  124. package/dist/src/utils/sshMcp/sshMcpServer.test.js +1 -0
  125. package/dist/src/utils/teleport.js +1 -1
  126. package/dist/src/webapp/server.js +1 -1
  127. package/dist/sshMcpServer.js +1 -0
  128. package/dist/sshMcpServer.test.js +1 -0
  129. package/dist/webapp/chunk-AMCDNAIG.js +1 -0
  130. package/dist/webapp/{chunk-YUEYJPXQ.js → chunk-NFYBHCXF.js} +1 -1
  131. package/dist/webapp/{chunk-DFKSSBHI.js → chunk-OJZNEHPP.js} +1 -1
  132. package/dist/webapp/chunk-VAB2VXFI.js +1 -0
  133. package/dist/webapp/index.html +2 -2
  134. package/dist/webapp/main-MTQLKGXD.js +1 -0
  135. package/dist/webapp/ngsw.json +14 -14
  136. package/dist/webapp/styles-DIKEDJBH.css +1 -0
  137. package/package.json +2 -1
  138. package/dist/webapp/chunk-4SRNXNLW.js +0 -1
  139. package/dist/webapp/chunk-SIHYW6PA.js +0 -1
  140. package/dist/webapp/main-LBNRQBXX.js +0 -1
  141. package/dist/webapp/styles-FUPULZDX.css +0 -1
@@ -1 +1 @@
1
- import e from"chalk";import{logForDebugging as n}from"../../utils/debug.js";import{fileHistoryEnabled as a}from"../../utils/fileHistory.js";import{getInitialSettings as s,getSettings_DEPRECATED as t,getSettingsForSource as o}from"../../utils/settings/settings.js";import{shouldOfferTerminalSetup as i}from"../../commands/terminalSetup/terminalSetup.js";import{getDesktopUpsellConfig as r}from"../../components/DesktopUpsell/DesktopUpsellStartup.js";import{color as l}from"../../components/design-system/color.js";import{shouldShowOverageCreditUpsell as c}from"../../components/LogoV2/OverageCreditUpsell.js";import{getShortcutDisplay as d}from"../../keybindings/shortcutFormat.js";import{isKairosCronEnabled as u}from"../../tools/ScheduleCronTool/prompt.js";import{is1PApiCustomer as p}from"../../utils/auth.js";import{countConcurrentSessions as m}from"../../utils/concurrentSessions.js";import{getGlobalConfig as f}from"../../utils/config.js";import{getEffortEnvOverride as y,modelSupportsEffort as g}from"../../utils/effort.js";import{env as v}from"../../utils/env.js";import{cacheKeys as S}from"../../utils/fileStateCache.js";import{getWorktreeCount as h}from"../../utils/git.js";import{detectRunningIDEsCached as w,getSortedIdeLockfiles as b,isCursorInstalled as R,isSupportedTerminal as j,isSupportedVSCodeTerminal as C,isVSCodeInstalled as E,isWindsurfInstalled as P}from"../../utils/ide.js";import{getMainLoopModel as _,getUserSpecifiedModelSetting as U}from"../../utils/model/model.js";import{getPlatform as k}from"../../utils/platform.js";import{isPluginInstalled as x}from"../../utils/plugins/installedPluginsManager.js";import{loadKnownMarketplacesConfigSafe as T}from"../../utils/plugins/marketplaceManager.js";import{OFFICIAL_MARKETPLACE_NAME as $}from"../../utils/plugins/officialMarketplace.js";import{getCurrentSessionAgentColor as M,isCustomTitleEnabled as O}from"../../utils/sessionStorage.js";import{getFeatureValue_CACHED_MAY_BE_STALE as A}from"../analytics/growthbook.js";import{formatGrantAmount as L,getCachedOverageCreditGrant as D}from"../api/overageCreditGrant.js";import{checkCachedPassesEligibility as I,formatCreditAmount as q,getCachedReferrerReward as z}from"../api/referral.js";import{getSessionsSinceLastShown as H}from"./tipHistory.js";let Y;async function isMarketplacePluginRelevant(e,n,a){if(!await async function(){if(void 0!==Y)return Y;const e=await T();return Y=$ in e,Y}())return!1;if(x(`${e}@${$}`))return!1;const{bashTools:s}=n??{};if(a.cli&&s?.size&&a.cli.some(e=>s.has(e)))return!0;if(a.filePath&&n?.readFileState){if(S(n.readFileState).some(e=>a.filePath.test(e)))return!0}return!1}const B=[{id:"new-user-warmup",content:async()=>"Comienza con pequeñas funciones o correcciones, pide a Context que proponga un plan y verifica sus ediciones sugeridas",cooldownSessions:3,isRelevant:async()=>f().numStartups<10},{id:"plan-mode-for-complex-tasks",content:async()=>`Usa el Modo Plan para preparar una solicitud compleja antes de realizar cambios. Presiona ${d("chat:cycleMode","Chat","shift+tab")} dos veces para activarlo.`,cooldownSessions:5,isRelevant:async()=>{if("ant"===process.env.USER_TYPE)return!1;const e=f();return(e.lastPlanModeUse?(Date.now()-e.lastPlanModeUse)/864e5:1/0)>7}},{id:"default-permission-mode-config",content:async()=>"Usa /config para cambiar tu modo de permisos predeterminado (incluyendo el Modo Plan)",cooldownSessions:10,isRelevant:async()=>{try{const e=f(),n=t(),a=Boolean(e.lastPlanModeUse),s=Boolean(n?.permissions?.defaultMode);return a&&!s}catch(e){return n(`Failed to check default-permission-mode-config tip relevance: ${e}`,{level:"warn"}),!1}}},{id:"git-worktrees",content:async()=>"Usa git worktrees para ejecutar múltiples sesiones de Context en paralelo.",cooldownSessions:10,isRelevant:async()=>{try{const e=f();return await h()<=1&&e.numStartups>50}catch(e){return!1}}},{id:"color-when-multi-clauding",content:async()=>"¿Ejecutando múltiples sesiones de Context? Usa /color y /rename para distinguirlas de un vistazo.",cooldownSessions:10,isRelevant:async()=>{if(M())return!1;return await m()>=2}},{id:"terminal-setup",content:async()=>"Apple_Terminal"===v.terminal?"Ejecuta /terminal-setup para habilitar la integración del terminal, como Option + Enter para nueva línea y más":"Ejecuta /terminal-setup para habilitar la integración del terminal, como Shift + Enter para nueva línea y más",cooldownSessions:10,async isRelevant(){const e=f();return"Apple_Terminal"===v.terminal?!e.optionAsMetaKeyInstalled:!e.shiftEnterKeyBindingInstalled}},{id:"shift-enter",content:async()=>"Apple_Terminal"===v.terminal?"Presiona Option+Enter para enviar un mensaje multilínea":"Presiona Shift+Enter para enviar un mensaje multilínea",cooldownSessions:10,async isRelevant(){const e=f();return Boolean(("Apple_Terminal"===v.terminal?e.optionAsMetaKeyInstalled:e.shiftEnterKeyBindingInstalled)&&e.numStartups>3)}},{id:"shift-enter-setup",content:async()=>"Apple_Terminal"===v.terminal?"Ejecuta /terminal-setup para habilitar Option+Enter para nuevas líneas":"Ejecuta /terminal-setup para habilitar Shift+Enter para nuevas líneas",cooldownSessions:10,async isRelevant(){if(!i())return!1;const e=f();return!("Apple_Terminal"===v.terminal?e.optionAsMetaKeyInstalled:e.shiftEnterKeyBindingInstalled)}},{id:"memory-command",content:async()=>"Usa /memory para ver y gestionar la memoria de Context",cooldownSessions:15,isRelevant:async()=>f().memoryUsageCount<=0},{id:"theme-command",content:async()=>"Usa /theme para cambiar el tema de color",cooldownSessions:20,isRelevant:async()=>!0},{id:"colorterm-truecolor",content:async()=>"Prueba a configurar la variable de entorno COLORTERM=truecolor para obtener colores más vivos",cooldownSessions:30,isRelevant:async()=>!process.env.COLORTERM&&e.level<3},{id:"powershell-tool-env",content:async()=>"Configura CLAUDE_CODE_USE_POWERSHELL_TOOL=1 para habilitar la herramienta PowerShell (vista previa)",cooldownSessions:10,isRelevant:async()=>"windows"===k()&&void 0===process.env.CLAUDE_CODE_USE_POWERSHELL_TOOL},{id:"status-line",content:async()=>"Usa /statusline para configurar una línea de estado personalizada que se mostrará debajo del cuadro de entrada",cooldownSessions:25,isRelevant:async()=>void 0===t().statusLine},{id:"prompt-queue",content:async()=>"Pulsa Enter para poner en cola mensajes adicionales mientras Context está trabajando.",cooldownSessions:5,isRelevant:async()=>f().promptQueueUseCount<=3},{id:"enter-to-steer-in-relatime",content:async()=>"Envía mensajes a Context mientras trabaja para guiarlo en tiempo real",cooldownSessions:20,isRelevant:async()=>!0},{id:"todo-list",content:async()=>"Pide a Context que cree una lista de tareas cuando trabajes en tareas complejas para seguir el progreso",cooldownSessions:20,isRelevant:async()=>!0},{id:"vscode-command-install",content:async()=>`Abre la Paleta de Comandos (Cmd+Shift+P) y ejecuta "Shell Command: Install '${"vscode"===v.terminal?"code":v.terminal}' command in PATH" para habilitar la integración con el IDE`,cooldownSessions:0,async isRelevant(){if(!C())return!1;if("macos"!==k())return!1;switch(v.terminal){case"vscode":return!await E();case"cursor":return!await R();case"windsurf":return!await P();default:return!1}}},{id:"ide-upsell-external-terminal",content:async()=>"Conecta Context a tu IDE · /ide",cooldownSessions:4,async isRelevant(){if(j())return!1;if(0!==(await b()).length)return!1;return(await w()).length>0}},{id:"install-github-app",content:async()=>"Ejecuta /install-github-app para etiquetar a @claude directamente desde tus issues y PRs de Github",cooldownSessions:10,isRelevant:async()=>!f().githubActionSetupCount},{id:"install-slack-app",content:async()=>"Ejecuta /install-slack-app para usar Context en Slack",cooldownSessions:10,isRelevant:async()=>!f().slackAppInstallCount},{id:"permissions",content:async()=>"Usa /permissions para pre-aprobar y pre-denegar herramientas de bash, edición y MCP",cooldownSessions:10,isRelevant:async()=>f().numStartups>10},{id:"drag-and-drop-images",content:async()=>"¿Sabías que puedes arrastrar y soltar archivos de imagen en tu terminal?",cooldownSessions:10,isRelevant:async()=>!v.isSSH()},{id:"paste-images-mac",content:async()=>"Pega imágenes en Context Code usando control+v (¡no cmd+v!)",cooldownSessions:10,isRelevant:async()=>"macos"===k()},{id:"double-esc",content:async()=>"Pulsa dos veces esc para rebobinar la conversación a un punto anterior en el tiempo",cooldownSessions:10,isRelevant:async()=>!a()},{id:"double-esc-code-restore",content:async()=>"Pulsa dos veces esc para rebobinar el código y/o la conversación a un punto anterior en el tiempo",cooldownSessions:10,isRelevant:async()=>a()},{id:"continue",content:async()=>"Ejecuta context --continue o context --resume para reanudar una conversación",cooldownSessions:10,isRelevant:async()=>!0},{id:"rename-conversation",content:async()=>"Nombra tus conversaciones con /rename para encontrarlas fácilmente en /resume más tarde",cooldownSessions:15,isRelevant:async()=>O()&&f().numStartups>10},{id:"custom-commands",content:async()=>"Crea habilidades añadiendo archivos .md a .context/skills/ en tu proyecto o ~/.context/skills/ para habilidades globales",cooldownSessions:15,isRelevant:async()=>f().numStartups>10},{id:"shift-tab",content:async()=>"ant"===process.env.USER_TYPE?`Pulsa ${d("chat:cycleMode","Chat","shift+tab")} para alternar entre el modo predeterminado y el modo automático`:`Pulsa ${d("chat:cycleMode","Chat","shift+tab")} para alternar entre el modo predeterminado, el modo de edición con auto-aceptación y el modo de planificación`,cooldownSessions:10,isRelevant:async()=>!0},{id:"image-paste",content:async()=>`Usa ${d("chat:imagePaste","Chat","ctrl+v")} para pegar imágenes desde tu portapapeles`,cooldownSessions:20,isRelevant:async()=>!0},{id:"custom-agents",content:async()=>"Usa /agents para optimizar tareas específicas. Ej: Arquitecto de Software, Escritor de Código, Revisor de Código",cooldownSessions:15,isRelevant:async()=>f().numStartups>5},{id:"agent-flag",content:async()=>"Usa --agent <nombre_agente> para iniciar directamente una conversación con un subagente",cooldownSessions:15,isRelevant:async()=>f().numStartups>5},{id:"desktop-app",content:async()=>"Ejecuta Context Code local o remotamente usando la aplicación de escritorio: clau.de/desktop",cooldownSessions:15,isRelevant:async()=>"linux"!==k()},{id:"desktop-shortcut",content:async e=>`Continúa tu sesión en Context Code Desktop con ${l("suggestion",e.theme)("/desktop")}`,cooldownSessions:15,isRelevant:async()=>!!r().enable_shortcut_tip&&("darwin"===process.platform||"win32"===process.platform&&"x64"===process.arch)},{id:"web-app",content:async()=>"Ejecuta tareas en la nube mientras sigues programando localmente · clau.de/web",cooldownSessions:15,isRelevant:async()=>!0},{id:"mobile-app",content:async()=>"/mobile para usar Context Code desde la aplicación de Context en tu teléfono",cooldownSessions:15,isRelevant:async()=>!0},{id:"opusplan-mode-reminder",content:async()=>`Tu modelo predeterminado es Opus Plan Mode. Presiona ${d("chat:cycleMode","Chat","shift+tab")} dos veces para activar el Modo Plan y planificar con Context Opus.`,cooldownSessions:2,async isRelevant(){if("ant"===process.env.USER_TYPE)return!1;const e=f(),n="opusplan"===U(),a=e.lastPlanModeUse?(Date.now()-e.lastPlanModeUse)/864e5:1/0;return n&&a>3}},{id:"frontend-design-plugin",content:async e=>`¿Trabajando con HTML/CSS? Instala el plugin frontend-design:\n${l("suggestion",e.theme)(`/plugin install frontend-design@${$}`)}`,cooldownSessions:3,isRelevant:async e=>isMarketplacePluginRelevant("frontend-design",e,{filePath:/\.(html|css|htm)$/i})},{id:"vercel-plugin",content:async e=>`¿Trabajando con Vercel? Instala el plugin vercel:\n${l("suggestion",e.theme)(`/plugin install vercel@${$}`)}`,cooldownSessions:3,isRelevant:async e=>isMarketplacePluginRelevant("vercel",e,{filePath:/(?:^|[/\\])vercel\.json$/i,cli:["vercel"]})},{id:"effort-high-nudge",content:async e=>{const n=l("suggestion",e.theme)("/effort high");return"copy_b"===A("tengu_tide_elm","off")?`Usa ${n} para obtener mejores respuestas directas. Context lo analiza profundamente primero.`:`¿Trabajando en algo difícil? ${n} ofrece mejores respuestas iniciales`},cooldownSessions:3,isRelevant:async()=>{if(!p())return!1;if(!g(_()))return!1;if(void 0!==o("policySettings")?.effortLevel)return!1;if(void 0!==y())return!1;const e=s().effortLevel;return"high"!==e&&"max"!==e&&"off"!==A("tengu_tide_elm","off")}},{id:"subagent-fanout-nudge",content:async e=>{const n=l("suggestion",e.theme);return"copy_b"===A("tengu_tern_alloy","off")?`Para tareas grandes, pide a Context que ${n("use subagentes")}. Trabajan en paralelo y mantienen limpia la conversación principal.`:`Di ${n('"fan out subagents"')} y Context enviará un equipo. Cada uno profundiza para que no se escape nada.`},cooldownSessions:3,isRelevant:async()=>!!p()&&"off"!==A("tengu_tern_alloy","off")},{id:"loop-command-nudge",content:async e=>{const n=l("suggestion",e.theme);return"copy_b"===A("tengu_timber_lark","off")?`Usa ${n("/loop 5m check the deploy")} para ejecutar cualquier prompt de forma programada. Configúralo y olvídate.`:`${n("/loop")} ejecuta cualquier prompt de forma recurrente. Ideal para monitorear despliegues o estados de PR.`},cooldownSessions:3,isRelevant:async()=>!!p()&&(!!u()&&"off"!==A("tengu_timber_lark","off"))},{id:"guest-passes",content:async e=>{const n=l("claude",e.theme),a=z();return a?`Comparte Context Code y gana ${n(q(a))} de uso extra · ${n("/passes")}`:`Tienes pases de invitado gratuitos para compartir · ${n("/passes")}`},cooldownSessions:3,isRelevant:async()=>{if(f().hasVisitedPasses)return!1;const{eligible:e}=I();return e}},{id:"overage-credit",content:async e=>{const n=l("claude",e.theme),a=D(),s=a?L(a):null;return s?`${n(`${s} en uso extra, por nuestra cuenta`)} · aplicaciones de terceros · ${n("/extra-usage")}`:""},cooldownSessions:3,isRelevant:async()=>c()},{id:"feedback-command",content:async()=>"¡Usa /feedback para ayudarnos a mejorar!",cooldownSessions:15,async isRelevant(){if("ant"===process.env.USER_TYPE)return!1;return f().numStartups>5}}],K="ant"===process.env.USER_TYPE?[{id:"important-claudemd",content:async()=>'[ANT-ONLY] Use "IMPORTANT:" prefix for must-follow CLAUDE.md rules',cooldownSessions:30,isRelevant:async()=>!0},{id:"skillify",content:async()=>"[ANT-ONLY] Use /skillify at the end of a workflow to turn it into a reusable skill",cooldownSessions:15,isRelevant:async()=>!0}]:[];export async function getRelevantTips(e){const n=s().spinnerTipsOverride,a=function(){const e=s().spinnerTipsOverride;return e?.tips?.length?e.tips.map((e,n)=>({id:`custom-tip-${n}`,content:async()=>e,cooldownSessions:0,isRelevant:async()=>!0})):[]}();if(n?.excludeDefault&&a.length>0)return a;const t=[...B,...K],o=await Promise.all(t.map(n=>n.isRelevant(e)));return[...t.filter((e,n)=>o[n]).filter(e=>H(e.id)>=e.cooldownSessions),...a]}
1
+ import e from"chalk";import{logForDebugging as n}from"../../utils/debug.js";import{fileHistoryEnabled as a}from"../../utils/fileHistory.js";import{getInitialSettings as s,getSettings_DEPRECATED as t,getSettingsForSource as o}from"../../utils/settings/settings.js";import{shouldOfferTerminalSetup as i}from"../../commands/terminalSetup/terminalSetup.js";import{getDesktopUpsellConfig as r}from"../../components/DesktopUpsell/DesktopUpsellStartup.js";import{color as l}from"../../components/design-system/color.js";import{shouldShowOverageCreditUpsell as c}from"../../components/LogoV2/OverageCreditUpsell.js";import{getShortcutDisplay as d}from"../../keybindings/shortcutFormat.js";import{isKairosCronEnabled as u}from"../../tools/ScheduleCronTool/prompt.js";import{is1PApiCustomer as p}from"../../utils/auth.js";import{countConcurrentSessions as m}from"../../utils/concurrentSessions.js";import{getGlobalConfig as f}from"../../utils/config.js";import{getEffortEnvOverride as y,modelSupportsEffort as g}from"../../utils/effort.js";import{env as v}from"../../utils/env.js";import{cacheKeys as S}from"../../utils/fileStateCache.js";import{getWorktreeCount as h}from"../../utils/git.js";import{detectRunningIDEsCached as w,getSortedIdeLockfiles as R,isCursorInstalled as b,isSupportedTerminal as C,isSupportedVSCodeTerminal as j,isVSCodeInstalled as E,isWindsurfInstalled as P}from"../../utils/ide.js";import{getMainLoopModel as _,getUserSpecifiedModelSetting as T}from"../../utils/model/model.js";import{getPlatform as U}from"../../utils/platform.js";import{isPluginInstalled as k}from"../../utils/plugins/installedPluginsManager.js";import{loadKnownMarketplacesConfigSafe as x}from"../../utils/plugins/marketplaceManager.js";import{OFFICIAL_MARKETPLACE_NAME as O}from"../../utils/plugins/officialMarketplace.js";import{getCurrentSessionAgentColor as $,isCustomTitleEnabled as M}from"../../utils/sessionStorage.js";import{getFeatureValue_CACHED_MAY_BE_STALE as L}from"../analytics/growthbook.js";import{formatGrantAmount as A,getCachedOverageCreditGrant as D}from"../api/overageCreditGrant.js";import{checkCachedPassesEligibility as I,formatCreditAmount as q,getCachedReferrerReward as z}from"../api/referral.js";import{getSessionsSinceLastShown as H}from"./tipHistory.js";let N;async function isMarketplacePluginRelevant(e,n,a){if(!await async function(){if(void 0!==N)return N;const e=await x();return N=O in e,N}())return!1;if(k(`${e}@${O}`))return!1;const{bashTools:s}=n??{};if(a.cli&&s?.size&&a.cli.some(e=>s.has(e)))return!0;if(a.filePath&&n?.readFileState){if(S(n.readFileState).some(e=>a.filePath.test(e)))return!0}return!1}const Y=[{id:"new-user-warmup",content:async()=>"Comienza con pequeñas funciones o correcciones, pide a Context que proponga un plan y verifica sus ediciones sugeridas",cooldownSessions:3,isRelevant:async()=>f().numStartups<10},{id:"plan-mode-for-complex-tasks",content:async()=>`Usa el Modo Plan para preparar una solicitud compleja antes de realizar cambios. Presiona ${d("chat:cycleMode","Chat","shift+tab")} dos veces para activarlo.`,cooldownSessions:5,isRelevant:async()=>{if("ant"===process.env.USER_TYPE)return!1;const e=f();return(e.lastPlanModeUse?(Date.now()-e.lastPlanModeUse)/864e5:1/0)>7}},{id:"default-permission-mode-config",content:async()=>"Usa /config para cambiar tu modo de permisos predeterminado (incluyendo el Modo Plan)",cooldownSessions:10,isRelevant:async()=>{try{const e=f(),n=t(),a=Boolean(e.lastPlanModeUse),s=Boolean(n?.permissions?.defaultMode);return a&&!s}catch(e){return n(`Failed to check default-permission-mode-config tip relevance: ${e}`,{level:"warn"}),!1}}},{id:"git-worktrees",content:async()=>"Usa git worktrees para ejecutar múltiples sesiones de Context en paralelo.",cooldownSessions:10,isRelevant:async()=>{try{const e=f();return await h()<=1&&e.numStartups>50}catch(e){return!1}}},{id:"color-when-multi-clauding",content:async()=>"¿Ejecutando múltiples sesiones de Context? Usa /color y /rename para distinguirlas de un vistazo.",cooldownSessions:10,isRelevant:async()=>{if($())return!1;return await m()>=2}},{id:"terminal-setup",content:async()=>"Apple_Terminal"===v.terminal?"Ejecuta /terminal-setup para habilitar la integración del terminal, como Option + Enter para nueva línea y más":"Ejecuta /terminal-setup para habilitar la integración del terminal, como Shift + Enter para nueva línea y más",cooldownSessions:10,async isRelevant(){const e=f();return"Apple_Terminal"===v.terminal?!e.optionAsMetaKeyInstalled:!e.shiftEnterKeyBindingInstalled}},{id:"shift-enter",content:async()=>"Apple_Terminal"===v.terminal?"Presiona Option+Enter para enviar un mensaje multilínea":"Presiona Shift+Enter para enviar un mensaje multilínea",cooldownSessions:10,async isRelevant(){const e=f();return Boolean(("Apple_Terminal"===v.terminal?e.optionAsMetaKeyInstalled:e.shiftEnterKeyBindingInstalled)&&e.numStartups>3)}},{id:"shift-enter-setup",content:async()=>"Apple_Terminal"===v.terminal?"Ejecuta /terminal-setup para habilitar Option+Enter para nuevas líneas":"Ejecuta /terminal-setup para habilitar Shift+Enter para nuevas líneas",cooldownSessions:10,async isRelevant(){if(!i())return!1;const e=f();return!("Apple_Terminal"===v.terminal?e.optionAsMetaKeyInstalled:e.shiftEnterKeyBindingInstalled)}},{id:"memory-command",content:async()=>"Usa /memory para ver y gestionar la memoria de Context",cooldownSessions:15,isRelevant:async()=>f().memoryUsageCount<=0},{id:"theme-command",content:async()=>"Usa /theme para cambiar el tema de color",cooldownSessions:20,isRelevant:async()=>!0},{id:"colorterm-truecolor",content:async()=>"Prueba a configurar la variable de entorno COLORTERM=truecolor para obtener colores más vivos",cooldownSessions:30,isRelevant:async()=>!process.env.COLORTERM&&e.level<3},{id:"powershell-tool-env",content:async()=>"Configura CONTEXT_CODE_USE_POWERSHELL_TOOL=1 para habilitar la herramienta PowerShell (vista previa)",cooldownSessions:10,isRelevant:async()=>"windows"===U()&&void 0===process.env.CONTEXT_CODE_USE_POWERSHELL_TOOL&&void 0===process.env.CLAUDE_CODE_USE_POWERSHELL_TOOL},{id:"status-line",content:async()=>"Usa /statusline para configurar una línea de estado personalizada que se mostrará debajo del cuadro de entrada",cooldownSessions:25,isRelevant:async()=>void 0===t().statusLine},{id:"prompt-queue",content:async()=>"Pulsa Enter para poner en cola mensajes adicionales mientras Context está trabajando.",cooldownSessions:5,isRelevant:async()=>f().promptQueueUseCount<=3},{id:"enter-to-steer-in-relatime",content:async()=>"Envía mensajes a Context mientras trabaja para guiarlo en tiempo real",cooldownSessions:20,isRelevant:async()=>!0},{id:"todo-list",content:async()=>"Pide a Context que cree una lista de tareas cuando trabajes en tareas complejas para seguir el progreso",cooldownSessions:20,isRelevant:async()=>!0},{id:"vscode-command-install",content:async()=>`Abre la Paleta de Comandos (Cmd+Shift+P) y ejecuta "Shell Command: Install '${"vscode"===v.terminal?"code":v.terminal}' command in PATH" para habilitar la integración con el IDE`,cooldownSessions:0,async isRelevant(){if(!j())return!1;if("macos"!==U())return!1;switch(v.terminal){case"vscode":return!await E();case"cursor":return!await b();case"windsurf":return!await P();default:return!1}}},{id:"ide-upsell-external-terminal",content:async()=>"Conecta Context a tu IDE · /ide",cooldownSessions:4,async isRelevant(){if(C())return!1;if(0!==(await R()).length)return!1;return(await w()).length>0}},{id:"install-github-app",content:async()=>"Ejecuta /install-github-app para etiquetar a @claude directamente desde tus issues y PRs de Github",cooldownSessions:10,isRelevant:async()=>!f().githubActionSetupCount},{id:"install-slack-app",content:async()=>"Ejecuta /install-slack-app para usar Context en Slack",cooldownSessions:10,isRelevant:async()=>!f().slackAppInstallCount},{id:"permissions",content:async()=>"Usa /permissions para pre-aprobar y pre-denegar herramientas de bash, edición y MCP",cooldownSessions:10,isRelevant:async()=>f().numStartups>10},{id:"drag-and-drop-images",content:async()=>"¿Sabías que puedes arrastrar y soltar archivos de imagen en tu terminal?",cooldownSessions:10,isRelevant:async()=>!v.isSSH()},{id:"paste-images-mac",content:async()=>"Pega imágenes en Context Code usando control+v (¡no cmd+v!)",cooldownSessions:10,isRelevant:async()=>"macos"===U()},{id:"double-esc",content:async()=>"Pulsa dos veces esc para rebobinar la conversación a un punto anterior en el tiempo",cooldownSessions:10,isRelevant:async()=>!a()},{id:"double-esc-code-restore",content:async()=>"Pulsa dos veces esc para rebobinar el código y/o la conversación a un punto anterior en el tiempo",cooldownSessions:10,isRelevant:async()=>a()},{id:"continue",content:async()=>"Ejecuta context --continue o context --resume para reanudar una conversación",cooldownSessions:10,isRelevant:async()=>!0},{id:"rename-conversation",content:async()=>"Nombra tus conversaciones con /rename para encontrarlas fácilmente en /resume más tarde",cooldownSessions:15,isRelevant:async()=>M()&&f().numStartups>10},{id:"custom-commands",content:async()=>"Crea habilidades añadiendo archivos .md a .context/skills/ en tu proyecto o ~/.context/skills/ para habilidades globales",cooldownSessions:15,isRelevant:async()=>f().numStartups>10},{id:"shift-tab",content:async()=>"ant"===process.env.USER_TYPE?`Pulsa ${d("chat:cycleMode","Chat","shift+tab")} para alternar entre el modo predeterminado y el modo automático`:`Pulsa ${d("chat:cycleMode","Chat","shift+tab")} para alternar entre el modo predeterminado, el modo de edición con auto-aceptación y el modo de planificación`,cooldownSessions:10,isRelevant:async()=>!0},{id:"image-paste",content:async()=>`Usa ${d("chat:imagePaste","Chat","ctrl+v")} para pegar imágenes desde tu portapapeles`,cooldownSessions:20,isRelevant:async()=>!0},{id:"custom-agents",content:async()=>"Usa /agents para optimizar tareas específicas. Ej: Arquitecto de Software, Escritor de Código, Revisor de Código",cooldownSessions:15,isRelevant:async()=>f().numStartups>5},{id:"agent-flag",content:async()=>"Usa --agent <nombre_agente> para iniciar directamente una conversación con un subagente",cooldownSessions:15,isRelevant:async()=>f().numStartups>5},{id:"desktop-app",content:async()=>"Ejecuta Context Code local o remotamente usando la aplicación de escritorio: clau.de/desktop",cooldownSessions:15,isRelevant:async()=>"linux"!==U()},{id:"desktop-shortcut",content:async e=>`Continúa tu sesión en Context Code Desktop con ${l("suggestion",e.theme)("/desktop")}`,cooldownSessions:15,isRelevant:async()=>!!r().enable_shortcut_tip&&("darwin"===process.platform||"win32"===process.platform&&"x64"===process.arch)},{id:"web-app",content:async()=>"Ejecuta tareas en la nube mientras sigues programando localmente · clau.de/web",cooldownSessions:15,isRelevant:async()=>!0},{id:"mobile-app",content:async()=>"/mobile para usar Context Code desde la aplicación de Context en tu teléfono",cooldownSessions:15,isRelevant:async()=>!0},{id:"opusplan-mode-reminder",content:async()=>`Tu modelo predeterminado es Opus Plan Mode. Presiona ${d("chat:cycleMode","Chat","shift+tab")} dos veces para activar el Modo Plan y planificar con Context Opus.`,cooldownSessions:2,async isRelevant(){if("ant"===process.env.USER_TYPE)return!1;const e=f(),n="opusplan"===T(),a=e.lastPlanModeUse?(Date.now()-e.lastPlanModeUse)/864e5:1/0;return n&&a>3}},{id:"frontend-design-plugin",content:async e=>`¿Trabajando con HTML/CSS? Instala el plugin frontend-design:\n${l("suggestion",e.theme)(`/plugin install frontend-design@${O}`)}`,cooldownSessions:3,isRelevant:async e=>isMarketplacePluginRelevant("frontend-design",e,{filePath:/\.(html|css|htm)$/i})},{id:"vercel-plugin",content:async e=>`¿Trabajando con Vercel? Instala el plugin vercel:\n${l("suggestion",e.theme)(`/plugin install vercel@${O}`)}`,cooldownSessions:3,isRelevant:async e=>isMarketplacePluginRelevant("vercel",e,{filePath:/(?:^|[/\\])vercel\.json$/i,cli:["vercel"]})},{id:"effort-high-nudge",content:async e=>{const n=l("suggestion",e.theme)("/effort high");return"copy_b"===L("tengu_tide_elm","off")?`Usa ${n} para obtener mejores respuestas directas. Context lo analiza profundamente primero.`:`¿Trabajando en algo difícil? ${n} ofrece mejores respuestas iniciales`},cooldownSessions:3,isRelevant:async()=>{if(!p())return!1;if(!g(_()))return!1;if(void 0!==o("policySettings")?.effortLevel)return!1;if(void 0!==y())return!1;const e=s().effortLevel;return"high"!==e&&"max"!==e&&"off"!==L("tengu_tide_elm","off")}},{id:"subagent-fanout-nudge",content:async e=>{const n=l("suggestion",e.theme);return"copy_b"===L("tengu_tern_alloy","off")?`Para tareas grandes, pide a Context que ${n("use subagentes")}. Trabajan en paralelo y mantienen limpia la conversación principal.`:`Di ${n('"fan out subagents"')} y Context enviará un equipo. Cada uno profundiza para que no se escape nada.`},cooldownSessions:3,isRelevant:async()=>!!p()&&"off"!==L("tengu_tern_alloy","off")},{id:"loop-command-nudge",content:async e=>{const n=l("suggestion",e.theme);return"copy_b"===L("tengu_timber_lark","off")?`Usa ${n("/loop 5m check the deploy")} para ejecutar cualquier prompt de forma programada. Configúralo y olvídate.`:`${n("/loop")} ejecuta cualquier prompt de forma recurrente. Ideal para monitorear despliegues o estados de PR.`},cooldownSessions:3,isRelevant:async()=>!!p()&&(!!u()&&"off"!==L("tengu_timber_lark","off"))},{id:"guest-passes",content:async e=>{const n=l("claude",e.theme),a=z();return a?`Comparte Context Code y gana ${n(q(a))} de uso extra · ${n("/passes")}`:`Tienes pases de invitado gratuitos para compartir · ${n("/passes")}`},cooldownSessions:3,isRelevant:async()=>{if(f().hasVisitedPasses)return!1;const{eligible:e}=I();return e}},{id:"overage-credit",content:async e=>{const n=l("claude",e.theme),a=D(),s=a?A(a):null;return s?`${n(`${s} en uso extra, por nuestra cuenta`)} · aplicaciones de terceros · ${n("/extra-usage")}`:""},cooldownSessions:3,isRelevant:async()=>c()},{id:"feedback-command",content:async()=>"¡Usa /feedback para ayudarnos a mejorar!",cooldownSessions:15,async isRelevant(){if("ant"===process.env.USER_TYPE)return!1;return f().numStartups>5}}],B="ant"===process.env.USER_TYPE?[{id:"important-claudemd",content:async()=>'[ANT-ONLY] Use "IMPORTANT:" prefix for must-follow CLAUDE.md rules',cooldownSessions:30,isRelevant:async()=>!0},{id:"skillify",content:async()=>"[ANT-ONLY] Use /skillify at the end of a workflow to turn it into a reusable skill",cooldownSessions:15,isRelevant:async()=>!0}]:[];export async function getRelevantTips(e){const n=s().spinnerTipsOverride,a=function(){const e=s().spinnerTipsOverride;return e?.tips?.length?e.tips.map((e,n)=>({id:`custom-tip-${n}`,content:async()=>e,cooldownSessions:0,isRelevant:async()=>!0})):[]}();if(n?.excludeDefault&&a.length>0)return a;const t=[...Y,...B],o=await Promise.all(t.map(n=>n.isRelevant(e)));return[...t.filter((e,n)=>o[n]).filter(e=>H(e.id)>=e.cooldownSessions),...a]}
@@ -1 +1 @@
1
- import{getRemoteSessionUrl as e}from"../../constants/product.js";import{OUTPUT_FILE_TAG as t,REMOTE_REVIEW_PROGRESS_TAG as o,REMOTE_REVIEW_TAG as s,STATUS_TAG as n,SUMMARY_TAG as i,TASK_ID_TAG as a,TASK_NOTIFICATION_TAG as r,TASK_TYPE_TAG as u,TOOL_USE_ID_TAG as m,ULTRAPLAN_TAG as l}from"../../constants/xml.js";import{createTaskStateBase as p,generateTaskId as d}from"../../Task.js";import{TodoWriteTool as c}from"../../tools/TodoWriteTool/TodoWriteTool.js";import{checkBackgroundRemoteSessionEligibility as g}from"../../utils/background/remote/remoteSession.js";import{logForDebugging as f}from"../../utils/debug.js";import{logError as k}from"../../utils/log.js";import{enqueuePendingNotification as y}from"../../utils/messageQueueManager.js";import{extractTag as R,extractTextContent as $}from"../../utils/messages.js";import{emitTaskTerminatedSdk as v}from"../../utils/sdkEventQueue.js";import{deleteRemoteAgentMetadata as w,listRemoteAgentMetadata as h,writeRemoteAgentMetadata as T}from"../../utils/sessionStorage.js";import{jsonStringify as _}from"../../utils/slowOperations.js";import{appendTaskOutput as S,evictTaskOutput as A,getTaskOutputPath as b,initTaskOutput as I}from"../../utils/task/diskOutput.js";import{registerTask as x,updateTaskState as j}from"../../utils/task/framework.js";import{fetchSession as U}from"../../utils/teleport/api.js";import{archiveRemoteSession as M,pollRemoteSessionEvents as L}from"../../utils/teleport.js";const N=["remote-agent","ultraplan","ultrareview","autofix-pr","background-pr"];function isRemoteTaskType(e){return N.includes(e??"")}const E=new Map;export function registerCompletionChecker(e,t){E.set(e,t)}async function removeRemoteAgentMetadata(e){try{await w(e)}catch(e){f(`removeRemoteAgentMetadata failed: ${String(e)}`)}}export async function checkRemoteAgentEligibility({skipBundle:e=!1}={}){const t=await g({skipBundle:e});return t.length>0?{eligible:!1,errors:t}:{eligible:!0}}export function formatPreconditionError(e){switch(e.type){case"not_logged_in":return"Please run /login and sign in with your Claude.ai account (not Console).";case"no_remote_environment":return"No cloud environment available. Set one up at https://claude.ai/code/onboarding?magic=env-setup";case"not_in_git_repo":return"Background tasks require a git repository. Initialize git or run from a git repository.";case"no_git_remote":return"Background tasks require a GitHub remote. Add one with `git remote add origin REPO_URL`.";case"github_app_not_installed":return"The Claude GitHub app must be installed on this repository first.\nhttps://github.com/apps/claude/installations/new";case"policy_blocked":return"Remote sessions are disabled by your organization's policy. Contact your organization admin to enable them."}}function enqueueRemoteNotification(e,o,s,l,p){if(!markTaskNotified(e,l))return;const d="completed"===s?"completed successfully":"failed"===s?"failed":"was stopped",c=p?`\n<${m}>${p}</${m}>`:"",g=b(e);y({value:`<${r}>\n<${a}>${e}</${a}>${c}\n<${u}>remote_agent</${u}>\n<${t}>${g}</${t}>\n<${n}>${s}</${n}>\n<${i}>Remote task "${o}" ${d}</${i}>\n</${r}>`,mode:"task-notification"})}function markTaskNotified(e,t){let o=!1;return j(e,t,e=>e.notified?e:(o=!0,{...e,notified:!0})),o}export function extractPlanFromLog(e){for(let t=e.length-1;t>=0;t--){const o=e[t];if("assistant"!==o?.type)continue;const s=$(o.message.content,"\n"),n=R(s,l);if(n?.trim())return n.trim()}return null}export function enqueueUltraplanFailureNotification(e,t,o,s){if(!markTaskNotified(e,s))return;const m=getRemoteTaskSessionUrl(t);y({value:`<${r}>\n<${a}>${e}</${a}>\n<${u}>remote_agent</${u}>\n<${n}>failed</${n}>\n<${i}>Ultraplan failed: ${o}</${i}>\n</${r}>\nThe remote Ultraplan session did not produce a plan (${o}). Inspect the session at ${m} and tell the user to retry locally with plan mode.`,mode:"task-notification"})}function enqueueRemoteReviewFailureNotification(e,t,o){if(!markTaskNotified(e,o))return;y({value:`<${r}>\n<${a}>${e}</${a}>\n<${u}>remote_agent</${u}>\n<${n}>failed</${n}>\n<${i}>Remote review failed: ${t}</${i}>\n</${r}>\nRemote review did not produce output (${t}). Tell the user to retry /ultrareview, or use /review for a local review instead.`,mode:"task-notification"})}function extractTodoListFromLog(e){const t=e.findLast(e=>"assistant"===e.type&&e.message.content.some(e=>"tool_use"===e.type&&e.name===c.name));if(!t)return[];const o=t.message.content.find(e=>"tool_use"===e.type&&e.name===c.name)?.input;if(!o)return[];const s=c.inputSchema.safeParse(o);return s.success?s.data.todos:[]}export function registerRemoteAgentTask(e){const{remoteTaskType:t,session:o,command:s,context:n,toolUseId:i,isRemoteReview:a,isUltraplan:r,isLongRunning:u,remoteTaskMetadata:m}=e,l=d("remote_agent");I(l);const c={...p(l,"remote_agent",o.title,i),type:"remote_agent",remoteTaskType:t,status:"running",sessionId:o.id,command:s,title:o.title,todoList:[],log:[],isRemoteReview:a,isUltraplan:r,isLongRunning:u,pollStartedAt:Date.now(),remoteTaskMetadata:m};x(c,n.setAppState),async function(e){try{await T(e.taskId,e)}catch(e){f(`persistRemoteAgentMetadata failed: ${String(e)}`)}}({taskId:l,remoteTaskType:t,sessionId:o.id,title:o.title,command:s,spawnedAt:Date.now(),toolUseId:i,isUltraplan:r,isRemoteReview:a,isLongRunning:u,remoteTaskMetadata:m});const g=startRemoteSessionPolling(l,n);return{taskId:l,sessionId:o.id,cleanup:g}}export async function restoreRemoteAgentTasks(e){try{await async function(e){const t=await h();if(0===t.length)return;for(const o of t){let t;try{t=(await U(o.sessionId)).session_status}catch(e){e instanceof Error&&e.message.startsWith("Session not found:")?(f(`restoreRemoteAgentTasks: dropping ${o.taskId} (404: ${String(e)})`),removeRemoteAgentMetadata(o.taskId)):f(`restoreRemoteAgentTasks: skipping ${o.taskId} (recoverable: ${String(e)})`);continue}if("archived"===t){removeRemoteAgentMetadata(o.taskId);continue}const s={...p(o.taskId,"remote_agent",o.title,o.toolUseId),type:"remote_agent",remoteTaskType:isRemoteTaskType(o.remoteTaskType)?o.remoteTaskType:"remote-agent",status:"running",sessionId:o.sessionId,command:o.command,title:o.title,todoList:[],log:[],isRemoteReview:o.isRemoteReview,isUltraplan:o.isUltraplan,isLongRunning:o.isLongRunning,startTime:o.spawnedAt,pollStartedAt:Date.now(),remoteTaskMetadata:o.remoteTaskMetadata};x(s,e.setAppState),I(o.taskId),startRemoteSessionPolling(o.taskId,e)}}(e)}catch(e){f(`restoreRemoteAgentTasks failed: ${String(e)}`)}}function startRemoteSessionPolling(e,t){let m=!0;const l=18e5;let p=0,d=null,c=[],g=null;const poll=async()=>{if(m){try{const m=t.getAppState(),f=m.tasks?.[e];if(!f||"running"!==f.status)return;const k=await L(f.sessionId,d);d=k.lastEventId;const v=k.newEvents.length>0;if(v){c=[...c,...k.newEvents];const t=k.newEvents.map(e=>"assistant"===e.type?e.message.content.filter(e=>"text"===e.type).map(e=>"text"in e?e.text:"").join("\n"):_(e)).join("\n");t&&S(e,t+"\n")}if("archived"===k.sessionStatus)return j(e,t.setAppState,e=>"running"===e.status?{...e,status:"completed",endTime:Date.now()}:e),enqueueRemoteNotification(e,f.title,"completed",t.setAppState,f.toolUseId),A(e),void removeRemoteAgentMetadata(e);const w=E.get(f.remoteTaskType);if(w){const o=await w(f.remoteTaskMetadata);if(null!==o)return j(e,t.setAppState,e=>"running"===e.status?{...e,status:"completed",endTime:Date.now()}:e),enqueueRemoteNotification(e,o,"completed",t.setAppState,f.toolUseId),A(e),void removeRemoteAgentMetadata(e)}const h=f.isUltraplan||f.isLongRunning?void 0:c.findLast(e=>"result"===e.type);let T;if(f.isRemoteReview&&v&&null===g&&(g=function(e){for(let t=e.length-1;t>=0;t--){const o=e[t];if("system"===o?.type&&("hook_progress"===o.subtype||"hook_response"===o.subtype)){const e=R(o.stdout,s);if(e?.trim())return e.trim()}}for(let t=e.length-1;t>=0;t--){const o=e[t];if("assistant"!==o?.type)continue;const n=$(o.message.content,"\n"),i=R(n,s);if(i?.trim())return i.trim()}const t=e.filter(e=>"system"===e.type&&("hook_progress"===e.subtype||"hook_response"===e.subtype)).map(e=>e.stdout).join(""),o=R(t,s);return o?.trim()?o.trim():null}(k.newEvents)),f.isRemoteReview&&v){const e=`<${o}>`,t=`</${o}>`;for(const o of k.newEvents)if("system"===o.type&&("hook_progress"===o.subtype||"hook_response"===o.subtype)){const s=o.stdout,n=s.lastIndexOf(t),i=-1===n?-1:s.lastIndexOf(e,n);if(-1!==i&&n>i)try{const t=JSON.parse(s.slice(i+e.length,n));T={stage:t.stage,bugsFound:t.bugs_found??0,bugsVerified:t.bugs_verified??0,bugsRefuted:t.bugs_refuted??0}}catch{}}}const b=c.some(e=>"assistant"===e.type||f.isRemoteReview&&"system"===e.type&&("hook_progress"===e.subtype||"hook_response"===e.subtype));"idle"===k.sessionStatus&&!v&&b?p++:p=0;const I=p>=5,x=c.some(e=>"system"===e.type&&("hook_started"===e.subtype||"hook_progress"===e.subtype||"hook_response"===e.subtype)&&"SessionStart"===e.hook_event),U=c.some(e=>"assistant"===e.type),M=f.isRemoteReview&&(null!==g||!x&&I&&U),N=f.isRemoteReview&&Date.now()-f.pollStartedAt>l,q=h?"success"===h.subtype?"completed":"failed":M||N?"completed":c.length>0?"running":"starting";let D=!1;if(j(e,t.setAppState,e=>{if("running"!==e.status)return D=!0,e;return!v&&("running"===q||"starting"===q)?e:{...e,status:"starting"===q?"running":q,log:c,todoList:v?extractTodoListFromLog(c):e.todoList,reviewProgress:T??e.reviewProgress,endTime:h||M||N?Date.now():void 0}}),D)return;if(h||M||N){const o=h&&"success"!==h.subtype?"failed":"completed";if(f.isRemoteReview){const m=g??function(e){for(let t=e.length-1;t>=0;t--){const o=e[t];if("system"===o?.type&&("hook_progress"===o.subtype||"hook_response"===o.subtype)){const e=R(o.stdout,s);if(e?.trim())return e.trim()}}for(let t=e.length-1;t>=0;t--){const o=e[t];if("assistant"!==o?.type)continue;const n=$(o.message.content,"\n"),i=R(n,s);if(i?.trim())return i.trim()}const t=e.filter(e=>"system"===e.type&&("hook_progress"===e.subtype||"hook_response"===e.subtype)).map(e=>e.stdout).join(""),o=R(t,s);return o?.trim()?o.trim():e.filter(e=>"assistant"===e.type).map(e=>$(e.message.content,"\n")).join("\n").trim()||null}(c);if(m&&"completed"===o)return function(e,t,o){if(!markTaskNotified(e,o))return;y({value:`<${r}>\n<${a}>${e}</${a}>\n<${u}>remote_agent</${u}>\n<${n}>completed</${n}>\n<${i}>Remote review completed</${i}>\n</${r}>\nThe remote review produced the following findings:\n\n${t}`,mode:"task-notification"})}(e,m,t.setAppState),A(e),void removeRemoteAgentMetadata(e);j(e,t.setAppState,e=>({...e,status:"failed"}));const l=h&&"success"!==h.subtype?"remote session returned an error":N&&!M?"remote session exceeded 30 minutes":"no review output — orchestrator may have exited early";return enqueueRemoteReviewFailureNotification(e,l,t.setAppState),A(e),void removeRemoteAgentMetadata(e)}return enqueueRemoteNotification(e,f.title,o,t.setAppState,f.toolUseId),A(e),void removeRemoteAgentMetadata(e)}}catch(o){k(o),p=0;try{const o=t.getAppState(),s=o.tasks?.[e];if(s?.isRemoteReview&&"running"===s.status&&Date.now()-s.pollStartedAt>l)return j(e,t.setAppState,e=>({...e,status:"failed",endTime:Date.now()})),enqueueRemoteReviewFailureNotification(e,"remote session exceeded 30 minutes",t.setAppState),A(e),void removeRemoteAgentMetadata(e)}catch{}}m&&setTimeout(poll,1e3)}};return poll(),()=>{m=!1}}export const RemoteAgentTask={name:"RemoteAgentTask",type:"remote_agent",async kill(e,t){let o,s,n,i=!1;j(e,t,e=>"running"!==e.status?e:(o=e.toolUseId,s=e.description,n=e.sessionId,i=!0,{...e,status:"killed",notified:!0,endTime:Date.now()})),i&&(v(e,"stopped",{toolUseId:o,summary:s}),n&&M(n).catch(e=>f(`RemoteAgentTask archive failed: ${String(e)}`))),A(e),removeRemoteAgentMetadata(e),f(`RemoteAgentTask ${e} killed, archiving session ${n??"unknown"}`)}};export function getRemoteTaskSessionUrl(t){return e(t,process.env.SESSION_INGRESS_URL)}
1
+ import{getRemoteSessionUrl as e}from"../../constants/product.js";import{OUTPUT_FILE_TAG as t,REMOTE_REVIEW_PROGRESS_TAG as o,REMOTE_REVIEW_TAG as s,STATUS_TAG as n,SUMMARY_TAG as i,TASK_ID_TAG as a,TASK_NOTIFICATION_TAG as r,TASK_TYPE_TAG as u,TOOL_USE_ID_TAG as m,ULTRAPLAN_TAG as l}from"../../constants/xml.js";import{createTaskStateBase as p,generateTaskId as c}from"../../Task.js";import{TodoWriteTool as d}from"../../tools/TodoWriteTool/TodoWriteTool.js";import{checkBackgroundRemoteSessionEligibility as g}from"../../utils/background/remote/remoteSession.js";import{logForDebugging as f}from"../../utils/debug.js";import{logError as k}from"../../utils/log.js";import{enqueuePendingNotification as y}from"../../utils/messageQueueManager.js";import{extractTag as R,extractTextContent as $}from"../../utils/messages.js";import{emitTaskTerminatedSdk as v}from"../../utils/sdkEventQueue.js";import{deleteRemoteAgentMetadata as w,listRemoteAgentMetadata as h,writeRemoteAgentMetadata as T}from"../../utils/sessionStorage.js";import{jsonStringify as _}from"../../utils/slowOperations.js";import{appendTaskOutput as S,evictTaskOutput as A,getTaskOutputPath as b,initTaskOutput as I}from"../../utils/task/diskOutput.js";import{registerTask as x,updateTaskState as j}from"../../utils/task/framework.js";import{fetchSession as U}from"../../utils/teleport/api.js";import{archiveRemoteSession as M,pollRemoteSessionEvents as L}from"../../utils/teleport.js";const N=["remote-agent","ultraplan","ultrareview","autofix-pr","background-pr"];function isRemoteTaskType(e){return N.includes(e??"")}const E=new Map;export function registerCompletionChecker(e,t){E.set(e,t)}async function removeRemoteAgentMetadata(e){try{await w(e)}catch(e){f(`removeRemoteAgentMetadata failed: ${String(e)}`)}}export async function checkRemoteAgentEligibility({skipBundle:e=!1}={}){const t=await g({skipBundle:e});return t.length>0?{eligible:!1,errors:t}:{eligible:!0}}export function formatPreconditionError(e){switch(e.type){case"not_logged_in":return"Ejecuta /login e inicia sesión con tu cuenta Context (no Console).";case"no_remote_environment":return"No cloud environment available. Set one up at https://claude.ai/code/onboarding?magic=env-setup";case"not_in_git_repo":return"Background tasks require a git repository. Initialize git or run from a git repository.";case"no_git_remote":return"Background tasks require a GitHub remote. Add one with `git remote add origin REPO_URL`.";case"github_app_not_installed":return"The Claude GitHub app must be installed on this repository first.\nhttps://github.com/apps/claude/installations/new";case"policy_blocked":return"Remote sessions are disabled by your organization's policy. Contact your organization admin to enable them."}}function enqueueRemoteNotification(e,o,s,l,p){if(!markTaskNotified(e,l))return;const c="completed"===s?"completed successfully":"failed"===s?"failed":"was stopped",d=p?`\n<${m}>${p}</${m}>`:"",g=b(e);y({value:`<${r}>\n<${a}>${e}</${a}>${d}\n<${u}>remote_agent</${u}>\n<${t}>${g}</${t}>\n<${n}>${s}</${n}>\n<${i}>Remote task "${o}" ${c}</${i}>\n</${r}>`,mode:"task-notification"})}function markTaskNotified(e,t){let o=!1;return j(e,t,e=>e.notified?e:(o=!0,{...e,notified:!0})),o}export function extractPlanFromLog(e){for(let t=e.length-1;t>=0;t--){const o=e[t];if("assistant"!==o?.type)continue;const s=$(o.message.content,"\n"),n=R(s,l);if(n?.trim())return n.trim()}return null}export function enqueueUltraplanFailureNotification(e,t,o,s){if(!markTaskNotified(e,s))return;const m=getRemoteTaskSessionUrl(t);y({value:`<${r}>\n<${a}>${e}</${a}>\n<${u}>remote_agent</${u}>\n<${n}>failed</${n}>\n<${i}>Ultraplan failed: ${o}</${i}>\n</${r}>\nThe remote Ultraplan session did not produce a plan (${o}). Inspect the session at ${m} and tell the user to retry locally with plan mode.`,mode:"task-notification"})}function enqueueRemoteReviewFailureNotification(e,t,o){if(!markTaskNotified(e,o))return;y({value:`<${r}>\n<${a}>${e}</${a}>\n<${u}>remote_agent</${u}>\n<${n}>failed</${n}>\n<${i}>Remote review failed: ${t}</${i}>\n</${r}>\nRemote review did not produce output (${t}). Tell the user to retry /ultrareview, or use /review for a local review instead.`,mode:"task-notification"})}function extractTodoListFromLog(e){const t=e.findLast(e=>"assistant"===e.type&&e.message.content.some(e=>"tool_use"===e.type&&e.name===d.name));if(!t)return[];const o=t.message.content.find(e=>"tool_use"===e.type&&e.name===d.name)?.input;if(!o)return[];const s=d.inputSchema.safeParse(o);return s.success?s.data.todos:[]}export function registerRemoteAgentTask(e){const{remoteTaskType:t,session:o,command:s,context:n,toolUseId:i,isRemoteReview:a,isUltraplan:r,isLongRunning:u,remoteTaskMetadata:m}=e,l=c("remote_agent");I(l);const d={...p(l,"remote_agent",o.title,i),type:"remote_agent",remoteTaskType:t,status:"running",sessionId:o.id,command:s,title:o.title,todoList:[],log:[],isRemoteReview:a,isUltraplan:r,isLongRunning:u,pollStartedAt:Date.now(),remoteTaskMetadata:m};x(d,n.setAppState),async function(e){try{await T(e.taskId,e)}catch(e){f(`persistRemoteAgentMetadata failed: ${String(e)}`)}}({taskId:l,remoteTaskType:t,sessionId:o.id,title:o.title,command:s,spawnedAt:Date.now(),toolUseId:i,isUltraplan:r,isRemoteReview:a,isLongRunning:u,remoteTaskMetadata:m});const g=startRemoteSessionPolling(l,n);return{taskId:l,sessionId:o.id,cleanup:g}}export async function restoreRemoteAgentTasks(e){try{await async function(e){const t=await h();if(0===t.length)return;for(const o of t){let t;try{t=(await U(o.sessionId)).session_status}catch(e){e instanceof Error&&e.message.startsWith("Session not found:")?(f(`restoreRemoteAgentTasks: dropping ${o.taskId} (404: ${String(e)})`),removeRemoteAgentMetadata(o.taskId)):f(`restoreRemoteAgentTasks: skipping ${o.taskId} (recoverable: ${String(e)})`);continue}if("archived"===t){removeRemoteAgentMetadata(o.taskId);continue}const s={...p(o.taskId,"remote_agent",o.title,o.toolUseId),type:"remote_agent",remoteTaskType:isRemoteTaskType(o.remoteTaskType)?o.remoteTaskType:"remote-agent",status:"running",sessionId:o.sessionId,command:o.command,title:o.title,todoList:[],log:[],isRemoteReview:o.isRemoteReview,isUltraplan:o.isUltraplan,isLongRunning:o.isLongRunning,startTime:o.spawnedAt,pollStartedAt:Date.now(),remoteTaskMetadata:o.remoteTaskMetadata};x(s,e.setAppState),I(o.taskId),startRemoteSessionPolling(o.taskId,e)}}(e)}catch(e){f(`restoreRemoteAgentTasks failed: ${String(e)}`)}}function startRemoteSessionPolling(e,t){let m=!0;const l=18e5;let p=0,c=null,d=[],g=null;const poll=async()=>{if(m){try{const m=t.getAppState(),f=m.tasks?.[e];if(!f||"running"!==f.status)return;const k=await L(f.sessionId,c);c=k.lastEventId;const v=k.newEvents.length>0;if(v){d=[...d,...k.newEvents];const t=k.newEvents.map(e=>"assistant"===e.type?e.message.content.filter(e=>"text"===e.type).map(e=>"text"in e?e.text:"").join("\n"):_(e)).join("\n");t&&S(e,t+"\n")}if("archived"===k.sessionStatus)return j(e,t.setAppState,e=>"running"===e.status?{...e,status:"completed",endTime:Date.now()}:e),enqueueRemoteNotification(e,f.title,"completed",t.setAppState,f.toolUseId),A(e),void removeRemoteAgentMetadata(e);const w=E.get(f.remoteTaskType);if(w){const o=await w(f.remoteTaskMetadata);if(null!==o)return j(e,t.setAppState,e=>"running"===e.status?{...e,status:"completed",endTime:Date.now()}:e),enqueueRemoteNotification(e,o,"completed",t.setAppState,f.toolUseId),A(e),void removeRemoteAgentMetadata(e)}const h=f.isUltraplan||f.isLongRunning?void 0:d.findLast(e=>"result"===e.type);let T;if(f.isRemoteReview&&v&&null===g&&(g=function(e){for(let t=e.length-1;t>=0;t--){const o=e[t];if("system"===o?.type&&("hook_progress"===o.subtype||"hook_response"===o.subtype)){const e=R(o.stdout,s);if(e?.trim())return e.trim()}}for(let t=e.length-1;t>=0;t--){const o=e[t];if("assistant"!==o?.type)continue;const n=$(o.message.content,"\n"),i=R(n,s);if(i?.trim())return i.trim()}const t=e.filter(e=>"system"===e.type&&("hook_progress"===e.subtype||"hook_response"===e.subtype)).map(e=>e.stdout).join(""),o=R(t,s);return o?.trim()?o.trim():null}(k.newEvents)),f.isRemoteReview&&v){const e=`<${o}>`,t=`</${o}>`;for(const o of k.newEvents)if("system"===o.type&&("hook_progress"===o.subtype||"hook_response"===o.subtype)){const s=o.stdout,n=s.lastIndexOf(t),i=-1===n?-1:s.lastIndexOf(e,n);if(-1!==i&&n>i)try{const t=JSON.parse(s.slice(i+e.length,n));T={stage:t.stage,bugsFound:t.bugs_found??0,bugsVerified:t.bugs_verified??0,bugsRefuted:t.bugs_refuted??0}}catch{}}}const b=d.some(e=>"assistant"===e.type||f.isRemoteReview&&"system"===e.type&&("hook_progress"===e.subtype||"hook_response"===e.subtype));"idle"===k.sessionStatus&&!v&&b?p++:p=0;const I=p>=5,x=d.some(e=>"system"===e.type&&("hook_started"===e.subtype||"hook_progress"===e.subtype||"hook_response"===e.subtype)&&"SessionStart"===e.hook_event),U=d.some(e=>"assistant"===e.type),M=f.isRemoteReview&&(null!==g||!x&&I&&U),N=f.isRemoteReview&&Date.now()-f.pollStartedAt>l,q=h?"success"===h.subtype?"completed":"failed":M||N?"completed":d.length>0?"running":"starting";let D=!1;if(j(e,t.setAppState,e=>{if("running"!==e.status)return D=!0,e;return!v&&("running"===q||"starting"===q)?e:{...e,status:"starting"===q?"running":q,log:d,todoList:v?extractTodoListFromLog(d):e.todoList,reviewProgress:T??e.reviewProgress,endTime:h||M||N?Date.now():void 0}}),D)return;if(h||M||N){const o=h&&"success"!==h.subtype?"failed":"completed";if(f.isRemoteReview){const m=g??function(e){for(let t=e.length-1;t>=0;t--){const o=e[t];if("system"===o?.type&&("hook_progress"===o.subtype||"hook_response"===o.subtype)){const e=R(o.stdout,s);if(e?.trim())return e.trim()}}for(let t=e.length-1;t>=0;t--){const o=e[t];if("assistant"!==o?.type)continue;const n=$(o.message.content,"\n"),i=R(n,s);if(i?.trim())return i.trim()}const t=e.filter(e=>"system"===e.type&&("hook_progress"===e.subtype||"hook_response"===e.subtype)).map(e=>e.stdout).join(""),o=R(t,s);return o?.trim()?o.trim():e.filter(e=>"assistant"===e.type).map(e=>$(e.message.content,"\n")).join("\n").trim()||null}(d);if(m&&"completed"===o)return function(e,t,o){if(!markTaskNotified(e,o))return;y({value:`<${r}>\n<${a}>${e}</${a}>\n<${u}>remote_agent</${u}>\n<${n}>completed</${n}>\n<${i}>Remote review completed</${i}>\n</${r}>\nThe remote review produced the following findings:\n\n${t}`,mode:"task-notification"})}(e,m,t.setAppState),A(e),void removeRemoteAgentMetadata(e);j(e,t.setAppState,e=>({...e,status:"failed"}));const l=h&&"success"!==h.subtype?"remote session returned an error":N&&!M?"remote session exceeded 30 minutes":"no review output — orchestrator may have exited early";return enqueueRemoteReviewFailureNotification(e,l,t.setAppState),A(e),void removeRemoteAgentMetadata(e)}return enqueueRemoteNotification(e,f.title,o,t.setAppState,f.toolUseId),A(e),void removeRemoteAgentMetadata(e)}}catch(o){k(o),p=0;try{const o=t.getAppState(),s=o.tasks?.[e];if(s?.isRemoteReview&&"running"===s.status&&Date.now()-s.pollStartedAt>l)return j(e,t.setAppState,e=>({...e,status:"failed",endTime:Date.now()})),enqueueRemoteReviewFailureNotification(e,"remote session exceeded 30 minutes",t.setAppState),A(e),void removeRemoteAgentMetadata(e)}catch{}}m&&setTimeout(poll,1e3)}};return poll(),()=>{m=!1}}export const RemoteAgentTask={name:"RemoteAgentTask",type:"remote_agent",async kill(e,t){let o,s,n,i=!1;j(e,t,e=>"running"!==e.status?e:(o=e.toolUseId,s=e.description,n=e.sessionId,i=!0,{...e,status:"killed",notified:!0,endTime:Date.now()})),i&&(v(e,"stopped",{toolUseId:o,summary:s}),n&&M(n).catch(e=>f(`RemoteAgentTask archive failed: ${String(e)}`))),A(e),removeRemoteAgentMetadata(e),f(`RemoteAgentTask ${e} killed, archiving session ${n??"unknown"}`)}};export function getRemoteTaskSessionUrl(t){return e(t,process.env.SESSION_INGRESS_URL)}
@@ -1 +1 @@
1
- import{feature as e}from"../../recovery/bunBundleShim.js";import{jsx as t}from"react/jsx-runtime";import{createRequire as o}from"module";const s=o(import.meta.url);import{buildTool as n,toolMatchesName as r}from"../../Tool.js";import{getQuerySourceForAgent as a}from"../../utils/promptCategory.js";import{z as i}from"zod/v4";import{clearInvokedSkillsForAgent as l,getSdkAgentProgressSummariesEnabled as p}from"../../bootstrap/state.js";import{enhanceSystemPromptWithEnvDetails as m,getSystemPrompt as c}from"../../constants/prompts.js";import{isCoordinatorMode as u}from"../../coordinator/coordinatorMode.js";import{startAgentSummarization as d}from"../../services/AgentSummary/agentSummary.js";import{getFeatureValue_CACHED_MAY_BE_STALE as g}from"../../services/analytics/growthbook.js";import{logEvent as f}from"../../services/analytics/index.js";import{clearDumpState as y}from"../../services/api/dumpPrompts.js";import{completeAgentTask as h,createActivityDescriptionResolver as _,createProgressTracker as w,enqueueAgentNotification as k,failAgentTask as T,getProgressUpdate as b,getTokenCountFromTracker as A,isLocalAgentTask as C,killAsyncAgent as I,registerAgentForeground as v,registerAsyncAgent as S,unregisterAgentForeground as j,updateAgentProgress as D,updateProgressFromMessage as U}from"../../tasks/LocalAgentTask/LocalAgentTask.js";import{checkRemoteAgentEligibility as P,formatPreconditionError as O,getRemoteTaskSessionUrl as R,registerRemoteAgentTask as x}from"../../tasks/RemoteAgentTask/RemoteAgentTask.js";import{assembleToolPool as $}from"../../tools.js";import{asAgentId as E}from"../../types/ids.js";import{runWithAgentContext as M}from"../../utils/agentContext.js";import{isAgentSwarmsEnabled as B}from"../../utils/agentSwarmsEnabled.js";import{getCwd as N,runWithCwdOverride as L}from"../../utils/cwd.js";import{logForDebugging as F}from"../../utils/debug.js";import{isEnvTruthy as q}from"../../utils/envUtils.js";import{AbortError as K,errorMessage as X,toError as W}from"../../utils/errors.js";import{lazySchema as z}from"../../utils/lazySchema.js";import{createUserMessage as G,extractTextContent as J,isSyntheticMessage as H,normalizeMessages as Y}from"../../utils/messages.js";import{getAgentModel as Q}from"../../utils/model/agent.js";import{runWithProviderOverride as V}from"../../utils/model/providerOverrideContext.js";import{providerPreferenceToApiProvider as Z}from"../../utils/model/providers.js";import{permissionModeSchema as ee}from"../../utils/permissions/PermissionMode.js";import{filterDeniedAgents as te,getDenyRuleForAgent as oe}from"../../utils/permissions/permissions.js";import{enqueueSdkEvent as se}from"../../utils/sdkEventQueue.js";import{writeAgentMetadata as ne}from"../../utils/sessionStorage.js";import{sleep as re}from"../../utils/sleep.js";import{buildEffectiveSystemPrompt as ae}from"../../utils/systemPrompt.js";import{asSystemPrompt as ie}from"../../utils/systemPromptType.js";import{getTaskOutputPath as le}from"../../utils/task/diskOutput.js";import{getParentSessionId as pe,isTeammate as me}from"../../utils/teammate.js";import{isInProcessTeammate as ce}from"../../utils/teammateContext.js";import{teleportToRemote as ue}from"../../utils/teleport.js";import{getAssistantMessageContentLength as de}from"../../utils/tokens.js";import{createAgentId as ge}from"../../utils/uuid.js";import{createAgentWorktree as fe,hasWorktreeChanges as ye,removeAgentWorktree as he}from"../../utils/worktree.js";import{BASH_TOOL_NAME as _e}from"../BashTool/toolName.js";import{BackgroundHint as we}from"../BashTool/UI.js";import{FILE_READ_TOOL_NAME as ke}from"../FileReadTool/prompt.js";import{spawnTeammate as Te}from"../shared/spawnMultiAgent.js";import{setAgentColor as be}from"./agentColorManager.js";import{agentToolResultSchema as Ae,classifyHandoffIfNeeded as Ce,emitTaskProgress as Ie,extractPartialResult as ve,finalizeAgentTool as Se,getLastToolUseName as je,runAsyncAgentLifecycle as De}from"./agentToolUtils.js";import{GENERAL_PURPOSE_AGENT as Ue}from"./built-in/generalPurposeAgent.js";import{AGENT_TOOL_NAME as Pe,LEGACY_AGENT_TOOL_NAME as Oe,ONE_SHOT_BUILTIN_AGENT_TYPES as Re}from"./constants.js";import{buildForkedMessages as xe,buildWorktreeNotice as $e,FORK_AGENT as Ee,isForkSubagentEnabled as Me,isInForkChild as Be}from"./forkSubagent.js";import{filterAgentsByMcpRequirements as Ne,hasRequiredMcpServers as Le,isBuiltInAgent as Fe}from"./loadAgentsDir.js";import{getPrompt as qe}from"./prompt.js";import{runAgent as Ke}from"./runAgent.js";import{renderGroupedAgentToolUse as Xe,renderToolResultMessage as We,renderToolUseErrorMessage as ze,renderToolUseMessage as Ge,renderToolUseProgressMessage as Je,renderToolUseRejectedMessage as He,renderToolUseTag as Ye,userFacingName as Qe,userFacingNameBackgroundColor as Ve}from"./UI.js";const Ze=e("PROACTIVE")||e("KAIROS")?s("../../proactive/index.js"):null,et=q(process.env.CONTEXT_CODE_DISABLE_BACKGROUND_TASKS)||q(process.env.CLAUDE_CODE_DISABLE_BACKGROUND_TASKS);const tt=z(()=>i.object({description:i.string().describe("A short (3-5 word) description of the task"),prompt:i.string().describe("The task for the agent to perform"),subagent_type:i.string().optional().describe("The type of specialized agent to use for this task"),model:i.enum(["sonnet","opus","haiku"]).optional().describe("Optional model override for this agent. Takes precedence over the agent definition's model frontmatter. If omitted, uses the agent definition's model, or inherits from the parent."),run_in_background:i.boolean().optional().describe("Set to true to run this agent in the background. You will be notified when it completes.")})),ot=z(()=>{const e=i.object({name:i.string().optional().describe("Name for the spawned agent. Makes it addressable via SendMessage({to: name}) while running."),team_name:i.string().optional().describe("Team name for spawning. Uses current team context if omitted."),mode:ee().optional().describe('Permission mode for spawned teammate (e.g., "plan" to require plan approval).')});return tt().merge(e).extend({isolation:i.enum(["worktree"]).optional().describe('Isolation mode. "worktree" creates a temporary git worktree so the agent works on an isolated copy of the repo.'),cwd:i.string().optional().describe('Absolute path to run the agent in. Overrides the working directory for all filesystem and shell operations within this agent. Mutually exclusive with isolation: "worktree".')})});export const inputSchema=z(()=>{const t=e("KAIROS")?ot():ot().omit({cwd:!0});return et||Me()?t.omit({run_in_background:!0}):t});export const outputSchema=z(()=>{const e=Ae().extend({status:i.literal("completed"),prompt:i.string()}),t=i.object({status:i.literal("async_launched"),agentId:i.string().describe("The ID of the async agent"),description:i.string().describe("The description of the task"),prompt:i.string().describe("The prompt for the agent"),outputFile:i.string().describe("Path to the output file for checking agent progress"),canReadOutputFile:i.boolean().optional().describe("Whether the calling agent has Read/Bash tools to check progress")});return i.union([e,t])});export const AgentTool=n({async prompt({agents:t,tools:o,getToolPermissionContext:s,allowedAgentTypes:n}){const r=await s(),a=[];for(const e of o)if(e.name?.startsWith("mcp__")){const t=e.name.split("__")[1];t&&!a.includes(t)&&a.push(t)}const i=Ne(t,a),l=te(i,r,Pe),p=!!e("COORDINATOR_MODE")&&(q(process.env.CONTEXT_CODE_COORDINATOR_MODE)||q(process.env.CLAUDE_CODE_COORDINATOR_MODE));return await qe(l,p,n)},name:Pe,searchHint:"delegate work to a subagent",aliases:[Oe],maxResultSizeChars:1e5,description:async()=>"Launch a new agent",get inputSchema(){return inputSchema()},get outputSchema(){return outputSchema()},async call({prompt:o,subagent_type:s,description:n,model:i,run_in_background:P,name:O,team_name:R,mode:x,isolation:z,cwd:ee},ue,Ae,Oe,Re){const Ne=Date.now(),qe=u()?void 0:i,Xe=ue.getAppState(),We=Xe.toolPermissionContext.mode,ze=ue.setAppStateForTasks??ue.setAppState;if(R&&!B())throw new Error("Agent Teams is not yet available on your plan.");const Ge=function(e,t){return B()?e.team_name||t.teamContext?.teamName:void 0}({team_name:R},Xe);if(me()&&Ge&&O)throw new Error("Teammates cannot spawn other teammates — the team roster is flat. To spawn a subagent instead, omit the `name` parameter.");if(ce()&&Ge&&!0===P)throw new Error("In-process teammates cannot spawn background agents. Use run_in_background=false for synchronous subagents.");if(Ge&&O){const e=s?ue.options.agentDefinitions.activeAgents.find(e=>e.agentType===s):void 0;e?.color&&be(s,e.color);const t=await Te({name:O,prompt:o,description:n,team_name:Ge,use_splitpane:!0,plan_mode_required:"plan"===x,model:qe??e?.model,agent_type:s,invokingRequestId:Oe?.requestId},ue);return{data:{status:"teammate_spawned",prompt:o,...t.data}}}const Je=s??(Me()?void 0:Ue.agentType),He=void 0===Je;let Ye;if(He){if(ue.options.querySource===`agent:builtin:${Ee.agentType}`||Be(ue.messages))throw new Error("Fork is not available inside a forked worker. Complete your task directly using your tools.");Ye=Ee}else{const e=ue.options.agentDefinitions.activeAgents,{allowedAgentTypes:t}=ue.options.agentDefinitions,o=te(t?e.filter(e=>t.includes(e.agentType)):e,Xe.toolPermissionContext,Pe),s=o.find(e=>e.agentType===Je);if(!s){if(e.find(e=>e.agentType===Je)){const e=oe(Xe.toolPermissionContext,Pe,Je);throw new Error(`Agent type '${Je}' has been denied by permission rule '${Pe}(${Je})' from ${e?.source??"settings"}.`)}throw new Error(`Agent type '${Je}' not found. Available agents: ${o.map(e=>e.agentType).join(", ")}`)}Ye=s}if(ce()&&Ge&&!0===Ye.background)throw new Error(`In-process teammates cannot spawn background agents. Agent '${Ye.agentType}' has background: true in its definition.`);const Qe=Ye.requiredMcpServers;if(Qe?.length){const e=Xe.mcp.clients.some(e=>"pending"===e.type&&Qe.some(t=>e.name.toLowerCase().includes(t.toLowerCase())));let t=Xe;if(e){const e=3e4,o=500,s=Date.now()+e;for(;Date.now()<s;){await re(o),t=ue.getAppState();if(t.mcp.clients.some(e=>"failed"===e.type&&Qe.some(t=>e.name.toLowerCase().includes(t.toLowerCase()))))break;if(!t.mcp.clients.some(e=>"pending"===e.type&&Qe.some(t=>e.name.toLowerCase().includes(t.toLowerCase()))))break}}const o=[];for(const e of t.mcp.tools)if(e.name?.startsWith("mcp__")){const t=e.name.split("__")[1];t&&!o.includes(t)&&o.push(t)}if(!Le(Ye,o)){const e=Qe.filter(e=>!o.some(t=>t.toLowerCase().includes(e.toLowerCase())));throw new Error(`Agent '${Ye.agentType}' requires MCP servers matching: ${e.join(", ")}. MCP servers with tools: ${o.length>0?o.join(", "):"none"}. Use /mcp to configure and authenticate the required MCP servers.`)}}Ye.color&&be(Ye.agentType,Ye.color);const Ve=Z(Ye.provider),withAgentProvider=e=>V(Ve,e),tt=withAgentProvider(()=>Q(Ye.model,ue.options.mainLoopModel,He?void 0:qe,We));f("tengu_agent_tool_selected",{agent_type:Ye.agentType,model:tt,source:Ye.source,color:Ye.color,is_built_in_agent:Fe(Ye),is_resume:!1,is_async:(!0===P||!0===Ye.background)&&!et,is_fork:He});const ot=z??Ye.isolation;let st,nt,rt;if(He){if(ue.renderedSystemPrompt)nt=ue.renderedSystemPrompt;else{const e=Xe.agent?Xe.agentDefinitions.activeAgents.find(e=>e.agentType===Xe.agent):void 0,t=Array.from(Xe.toolPermissionContext.additionalWorkingDirectories.keys()),o=await c(ue.options.tools,ue.options.mainLoopModel,t,ue.options.mcpClients);nt=ae({mainThreadAgentDefinition:e,toolUseContext:ue,customSystemPrompt:ue.options.customSystemPrompt,defaultSystemPrompt:o,appendSystemPrompt:ue.options.appendSystemPrompt})}rt=xe(o,Oe)}else{try{const e=Array.from(Xe.toolPermissionContext.additionalWorkingDirectories.keys()),t=Ye.getSystemPrompt({toolUseContext:ue});Ye.memory&&f("tengu_agent_memory_loaded",{scope:Ye.memory,source:"subagent"}),st=await withAgentProvider(()=>m([t],tt,e))}catch(e){F(`Failed to get system prompt for agent ${Ye.agentType}: ${X(e)}`)}rt=[G({content:o})]}const at={prompt:o,resolvedAgentModel:tt,isBuiltInAgent:Fe(Ye),startTime:Ne,agentType:Ye.agentType,isAsync:(!0===P||!0===Ye.background)&&!et},it=!!e("COORDINATOR_MODE")&&(q(process.env.CONTEXT_CODE_COORDINATOR_MODE)||q(process.env.CLAUDE_CODE_COORDINATOR_MODE)),lt=Me(),pt=!!e("KAIROS")&&Xe.kairosEnabled,mt=(!0===P||!0===Ye.background||it||lt||pt||(Ze?.isProactiveActive()??!1))&&!et,ct={...Xe.toolPermissionContext,mode:Ye.permissionMode??"acceptEdits"},ut=$(ct,Xe.mcp.tools),dt=ge();let gt=null;if("worktree"===ot){const e=`agent-${dt.slice(0,8)}`;gt=await fe(e)}He&&gt&&rt.push(G({content:$e(N(),gt.worktreePath)}));const ft={agentDefinition:Ye,promptMessages:rt,toolUseContext:ue,canUseTool:Ae,isAsync:mt,querySource:ue.options.querySource??a(Ye.agentType,Fe(Ye)),model:He?void 0:qe,override:He?{systemPrompt:nt}:!st||gt||ee?void 0:{systemPrompt:ie(st)},availableTools:He?ue.options.tools:ut,forkContextMessages:He?ue.messages:void 0,...He&&{useExactTools:!0},worktreePath:gt?.worktreePath,description:n},yt=ee??gt?.worktreePath,wrapWithCwd=e=>yt?L(yt,e):e(),cleanupWorktreeIfNeeded=async()=>{if(!gt)return{};const{worktreePath:e,worktreeBranch:t,headCommit:o,gitRoot:s,hookBased:r}=gt;if(gt=null,r)return F(`Hook-based agent worktree kept at: ${e}`),{worktreePath:e};if(o){if(!await ye(e,o))return await he(e,t,s),ne(E(dt),{agentType:Ye.agentType,description:n}).catch(e=>F(`Failed to clear worktree metadata: ${e}`)),{}}return F(`Agent worktree has changes, keeping: ${e}`),{worktreePath:e,worktreeBranch:t}};if(mt){const e=dt,t=S({agentId:e,description:n,prompt:o,selectedAgent:Ye,setAppState:ze,toolUseId:ue.toolUseId});O&&ze(t=>{const o=new Map(t.agentNameRegistry);return o.set(O,E(e)),{...t,agentNameRegistry:o}});const s={agentId:e,parentSessionId:pe(),agentType:"subagent",subagentName:Ye.agentType,isBuiltIn:Fe(Ye),invokingRequestId:Oe?.requestId,invocationKind:"spawn",invocationEmitted:!1};withAgentProvider(()=>M(s,()=>wrapWithCwd(()=>De({taskId:t.agentId,abortController:t.abortController,makeStream:e=>Ke({...ft,override:{...ft.override,agentId:E(t.agentId),abortController:t.abortController},onCacheSafeParams:e}),metadata:at,description:n,toolUseContext:ue,rootSetAppState:ze,agentIdForCleanup:e,enableSummarization:it||Me()||p(),getWorktreeResult:cleanupWorktreeIfNeeded}))));const a=ue.options.tools.some(e=>r(e,ke)||r(e,_e));return{data:{isAsync:!0,status:"async_launched",agentId:t.agentId,description:n,prompt:o,outputFile:le(t.agentId),canReadOutputFile:a}}}{const s=E(dt),a={agentId:s,parentSessionId:pe(),agentType:"subagent",subagentName:Ye.agentType,isBuiltIn:Fe(Ye),invokingRequestId:Oe?.requestId,invocationKind:"spawn",invocationEmitted:!1};return withAgentProvider(()=>M(a,()=>wrapWithCwd(async()=>{const i=[],m=Date.now(),c=w(),u=_(ue.options.tools);if(rt.length>0){const e=Y(rt).find(e=>"user"===e.type);e&&"user"===e.type&&Re&&Re({toolUseID:`agent_${Oe.message.id}`,data:{message:e,type:"agent_progress",prompt:o,agentId:s}})}let S,P,O;if(!et){const e=v({agentId:s,description:n,prompt:o,selectedAgent:Ye,setAppState:ze,toolUseId:ue.toolUseId,autoBackgroundMs:(q(process.env.CONTEXT_AUTO_BACKGROUND_TASKS)||q(process.env.CLAUDE_AUTO_BACKGROUND_TASKS)||g("tengu_auto_background_agents",!1)?12e4:0)||void 0});S=e.taskId,P=e.backgroundSignal.then(()=>({type:"background"})),O=e.cancelAutoBackground}let R,x=!1,$=!1;const B=S,N=Ke({...ft,override:{...ft.override,agentId:s},onCacheSafeParams:B&&p()?e=>{const{stop:t}=d(B,s,e,ze);R=t}:void 0})[Symbol.asyncIterator]();let L,z=!1,G={};try{for(;;){const g=Date.now()-m;!et&&!x&&g>=2e3&&ue.setToolJSX&&(x=!0,ue.setToolJSX({jsx:t(we,{}),shouldHidePromptInput:!1,shouldContinueAnimation:!0,showSpinner:!0}));const v=N.next(),j=P?await Promise.race([v.then(e=>({type:"message",result:e})),P]):{type:"message",result:await v};if("background"===j.type&&S){const t=ue.getAppState().tasks[S];if(C(t)&&t.isBackgrounded){const m=S;$=!0,R?.(),withAgentProvider(()=>M(a,async()=>{let o;try{await Promise.race([N.return(void 0).catch(()=>{}),re(1e3)]);const s=w(),r=_(ue.options.tools);for(const e of i)U(s,e,r,ue.options.tools);for await(const e of Ke({...ft,isAsync:!0,override:{...ft.override,agentId:E(m),abortController:t.abortController},onCacheSafeParams:p()?e=>{const{stop:t}=d(m,E(m),e,ze);o=t}:void 0})){i.push(e),U(s,e,r,ue.options.tools),D(m,b(s),ze);const t=je(e);t&&Ie(s,m,ue.toolUseId,n,Ne,t)}const a=Se(i,m,at);h(a,ze);let l=J(a.content,"\n");if(e("TRANSCRIPT_CLASSIFIER")){const e=ue.getAppState(),o=await Ce({agentMessages:i,tools:ue.options.tools,toolPermissionContext:e.toolPermissionContext,abortSignal:t.abortController.signal,subagentType:Ye.agentType,totalToolUseCount:a.totalToolUseCount});o&&(l=`${o}\n\n${l}`)}const c=await cleanupWorktreeIfNeeded();k({taskId:m,description:n,status:"completed",setAppState:ze,finalMessage:l,usage:{totalTokens:A(s),toolUses:a.totalToolUseCount,durationMs:a.totalDurationMs},toolUseId:ue.toolUseId,...c})}catch(e){if(e instanceof K){I(m,ze),f("tengu_agent_tool_terminated",{agent_type:at.agentType,model:at.resolvedAgentModel,duration_ms:Date.now()-at.startTime,is_async:!0,is_built_in_agent:at.isBuiltInAgent,reason:"user_cancel_background"});const e=await cleanupWorktreeIfNeeded(),t=ve(i);return void k({taskId:m,description:n,status:"killed",setAppState:ze,toolUseId:ue.toolUseId,finalMessage:t,...e})}const t=X(e);T(m,t,ze);const o=await cleanupWorktreeIfNeeded();k({taskId:m,description:n,status:"failed",error:t,setAppState:ze,toolUseId:ue.toolUseId,...o})}finally{o?.(),l(s),y(s)}}));const c=ue.options.tools.some(e=>r(e,ke)||r(e,_e));return{data:{isAsync:!0,status:"async_launched",agentId:m,description:n,prompt:o,outputFile:le(m),canReadOutputFile:c}}}}if("message"!==j.type)continue;const{result:O}=j;if(O.done)break;const B=O.value;if(i.push(B),U(c,B,u,ue.options.tools),S){const e=je(B);e&&(Ie(c,S,ue.toolUseId,n,m,e),p()&&D(S,b(c),ze))}if("progress"!==B.type||"bash_progress"!==B.data.type&&"powershell_progress"!==B.data.type||!Re||Re({toolUseID:B.toolUseID,data:B.data}),"assistant"!==B.type&&"user"!==B.type)continue;if("assistant"===B.type){const e=de(B);e>0&&ue.setResponseLength(t=>t+e)}const L=Y([B]);for(const e of L)for(const t of e.message.content)"tool_use"!==t.type&&"tool_result"!==t.type||Re&&Re({toolUseID:`agent_${Oe.message.id}`,data:{message:e,type:"agent_progress",prompt:"",agentId:s}})}}catch(e){if(e instanceof K)throw z=!0,f("tengu_agent_tool_terminated",{agent_type:at.agentType,model:at.resolvedAgentModel,duration_ms:Date.now()-at.startTime,is_async:!1,is_built_in_agent:at.isBuiltInAgent,reason:"user_cancel_sync"}),e;F(`Sync agent error: ${X(e)}`,{level:"error"}),L=W(e)}finally{if(ue.setToolJSX&&ue.setToolJSX(null),R?.(),S&&(j(S,ze),!$)){const e=b(c);se({type:"system",subtype:"task_notification",task_id:S,tool_use_id:ue.toolUseId,status:L?"failed":z?"stopped":"completed",output_file:"",summary:n,usage:{total_tokens:e.tokenCount,tool_uses:e.toolUseCount,duration_ms:Date.now()-m}})}l(s),$||y(s),O?.(),$||(G=await cleanupWorktreeIfNeeded())}const Q=i.findLast(e=>"system"!==e.type&&"progress"!==e.type);if(Q&&H(Q))throw f("tengu_agent_tool_terminated",{agent_type:at.agentType,model:at.resolvedAgentModel,duration_ms:Date.now()-at.startTime,is_async:!1,is_built_in_agent:at.isBuiltInAgent,reason:"user_cancel_sync"}),new K;if(L){if(!i.some(e=>"assistant"===e.type))throw L;F(`Sync agent recovering from error with ${i.length} messages`)}const V=Se(i,s,at);if(e("TRANSCRIPT_CLASSIFIER")){const e=ue.getAppState(),t=await Ce({agentMessages:i,tools:ue.options.tools,toolPermissionContext:e.toolPermissionContext,abortSignal:ue.abortController.signal,subagentType:Ye.agentType,totalToolUseCount:V.totalToolUseCount});t&&(V.content=[{type:"text",text:t},...V.content])}return{data:{status:"completed",prompt:o,...V,...G}}})))}},isReadOnly:()=>!0,toAutoClassifierInput(e){const t=e,o=[t.subagent_type,t.mode?`mode=${t.mode}`:void 0].filter(e=>void 0!==e);return`${o.length>0?`(${o.join(", ")}): `:": "}${t.prompt}`},isConcurrencySafe:()=>!0,userFacingName:Qe,userFacingNameBackgroundColor:Ve,getActivityDescription:e=>e?.description??"Running task",async checkPermissions(e,t){t.getAppState();return{behavior:"allow",updatedInput:e}},mapToolResultToToolResultBlockParam(e,t){const o=e;if("object"==typeof o&&null!==o&&"status"in o&&"teammate_spawned"===o.status){const e=o;return{tool_use_id:t,type:"tool_result",content:[{type:"text",text:`Spawned successfully.\nagent_id: ${e.teammate_id}\nname: ${e.name}\nteam_name: ${e.team_name}\nThe agent is now running and will receive instructions via mailbox.`}]}}if("status"in o&&"remote_launched"===o.status){const e=o;return{tool_use_id:t,type:"tool_result",content:[{type:"text",text:`Remote agent launched in CCR.\ntaskId: ${e.taskId}\nsession_url: ${e.sessionUrl}\noutput_file: ${e.outputFile}\nThe agent is running remotely. You will be notified automatically when it completes.\nBriefly tell the user what you launched and end your response.`}]}}if("async_launched"===e.status){return{tool_use_id:t,type:"tool_result",content:[{type:"text",text:`${`Async agent launched successfully.\nagentId: ${e.agentId} (internal ID - do not mention to user. Use SendMessage with to: '${e.agentId}' to continue this agent.)\nThe agent is working in the background. You will be notified automatically when it completes.`}\n${e.canReadOutputFile?`Do not duplicate this agent's work — avoid working with the same files or topics it is using. Work on non-overlapping tasks, or briefly tell the user what you launched and end your response.\noutput_file: ${e.outputFile}\nIf asked, you can check progress before completion by using ${ke} or ${_e} tail on the output file.`:"Briefly tell the user what you launched and end your response. Do not generate any other text — agent results will arrive in a subsequent message."}`}]}}if("completed"===e.status){const o=e,s=o.worktreePath?`\nworktreePath: ${o.worktreePath}\nworktreeBranch: ${o.worktreeBranch}`:"",n=e.content.length>0?e.content:[{type:"text",text:"(Subagent completed but returned no output.)"}];return e.agentType&&Re.has(e.agentType)&&!s?{tool_use_id:t,type:"tool_result",content:n}:{tool_use_id:t,type:"tool_result",content:[...n,{type:"text",text:`agentId: ${e.agentId} (use SendMessage with to: '${e.agentId}' to continue this agent)${s}\n<usage>total_tokens: ${e.totalTokens}\ntool_uses: ${e.totalToolUseCount}\nduration_ms: ${e.totalDurationMs}</usage>`}]}}throw new Error(`Unexpected agent tool result status: ${e.status}`)},renderToolResultMessage:We,renderToolUseMessage:Ge,renderToolUseTag:Ye,renderToolUseProgressMessage:Je,renderToolUseRejectedMessage:He,renderToolUseErrorMessage:ze,renderGroupedToolUse:Xe});
1
+ import{feature as e}from"../../recovery/bunBundleShim.js";import{jsx as t}from"react/jsx-runtime";import{createRequire as o}from"module";const s=o(import.meta.url);import{buildTool as n,toolMatchesName as r}from"../../Tool.js";import{getQuerySourceForAgent as a}from"../../utils/promptCategory.js";import{z as i}from"zod/v4";import{clearInvokedSkillsForAgent as l,getSdkAgentProgressSummariesEnabled as p}from"../../bootstrap/state.js";import{enhanceSystemPromptWithEnvDetails as m,getSystemPrompt as c}from"../../constants/prompts.js";import{isCoordinatorMode as u}from"../../coordinator/coordinatorMode.js";import{startAgentSummarization as d}from"../../services/AgentSummary/agentSummary.js";import{getFeatureValue_CACHED_MAY_BE_STALE as g}from"../../services/analytics/growthbook.js";import{logEvent as f}from"../../services/analytics/index.js";import{clearDumpState as y}from"../../services/api/dumpPrompts.js";import{completeAgentTask as h,createActivityDescriptionResolver as _,createProgressTracker as w,enqueueAgentNotification as k,failAgentTask as T,getProgressUpdate as b,getTokenCountFromTracker as A,isLocalAgentTask as C,killAsyncAgent as I,registerAgentForeground as S,registerAsyncAgent as v,unregisterAgentForeground as j,updateAgentProgress as D,updateProgressFromMessage as P}from"../../tasks/LocalAgentTask/LocalAgentTask.js";import{checkRemoteAgentEligibility as U,formatPreconditionError as O,getRemoteTaskSessionUrl as R,registerRemoteAgentTask as x}from"../../tasks/RemoteAgentTask/RemoteAgentTask.js";import{assembleToolPool as $}from"../../tools.js";import{asAgentId as E}from"../../types/ids.js";import{runWithAgentContext as M}from"../../utils/agentContext.js";import{isAgentSwarmsEnabled as B}from"../../utils/agentSwarmsEnabled.js";import{getCwd as L,runWithCwdOverride as N}from"../../utils/cwd.js";import{logForDebugging as F}from"../../utils/debug.js";import{isEnvTruthy as q}from"../../utils/envUtils.js";import{AbortError as K,errorMessage as z,toError as X}from"../../utils/errors.js";import{lazySchema as W}from"../../utils/lazySchema.js";import{createUserMessage as G,extractTextContent as J,isSyntheticMessage as H,normalizeMessages as Y}from"../../utils/messages.js";import{getAgentModel as Q}from"../../utils/model/agent.js";import{runWithProviderOverride as V}from"../../utils/model/providerOverrideContext.js";import{providerPreferenceToApiProvider as Z}from"../../utils/model/providers.js";import{permissionModeSchema as ee}from"../../utils/permissions/PermissionMode.js";import{filterDeniedAgents as te,getDenyRuleForAgent as oe}from"../../utils/permissions/permissions.js";import{enqueueSdkEvent as se}from"../../utils/sdkEventQueue.js";import{writeAgentMetadata as ne}from"../../utils/sessionStorage.js";import{sleep as re}from"../../utils/sleep.js";import{buildEffectiveSystemPrompt as ae}from"../../utils/systemPrompt.js";import{asSystemPrompt as ie}from"../../utils/systemPromptType.js";import{getTaskOutputPath as le}from"../../utils/task/diskOutput.js";import{getParentSessionId as pe,isTeammate as me}from"../../utils/teammate.js";import{isInProcessTeammate as ce}from"../../utils/teammateContext.js";import{teleportToRemote as ue}from"../../utils/teleport.js";import{getAssistantMessageContentLength as de}from"../../utils/tokens.js";import{createAgentId as ge}from"../../utils/uuid.js";import{createAgentWorktree as fe,hasWorktreeChanges as ye,removeAgentWorktree as he}from"../../utils/worktree.js";import{BASH_TOOL_NAME as _e}from"../BashTool/toolName.js";import{BackgroundHint as we}from"../BashTool/UI.js";import{FILE_READ_TOOL_NAME as ke}from"../FileReadTool/prompt.js";import{spawnTeammate as Te}from"../shared/spawnMultiAgent.js";import{setAgentColor as be}from"./agentColorManager.js";import{agentToolResultSchema as Ae,classifyHandoffIfNeeded as Ce,emitTaskProgress as Ie,extractPartialResult as Se,finalizeAgentTool as ve,getLastToolUseName as je,runAsyncAgentLifecycle as De}from"./agentToolUtils.js";import{GENERAL_PURPOSE_AGENT as Pe}from"./built-in/generalPurposeAgent.js";import{AGENT_TOOL_NAME as Ue,LEGACY_AGENT_TOOL_NAME as Oe,ONE_SHOT_BUILTIN_AGENT_TYPES as Re}from"./constants.js";import{buildForkedMessages as xe,buildWorktreeNotice as $e,FORK_AGENT as Ee,isForkSubagentEnabled as Me,isInForkChild as Be}from"./forkSubagent.js";import{filterAgentsByMcpRequirements as Le,hasRequiredMcpServers as Ne,isBuiltInAgent as Fe}from"./loadAgentsDir.js";import{getPrompt as qe}from"./prompt.js";import{runAgent as Ke}from"./runAgent.js";import{renderGroupedAgentToolUse as ze,renderToolResultMessage as Xe,renderToolUseErrorMessage as We,renderToolUseMessage as Ge,renderToolUseProgressMessage as Je,renderToolUseRejectedMessage as He,renderToolUseTag as Ye,userFacingName as Qe,userFacingNameBackgroundColor as Ve}from"./UI.js";const Ze=e("PROACTIVE")||e("KAIROS")?s("../../proactive/index.js"):null,et=q(process.env.CONTEXT_CODE_DISABLE_BACKGROUND_TASKS)||q(process.env.CLAUDE_CODE_DISABLE_BACKGROUND_TASKS);const tt=W(()=>i.object({description:i.string().describe("A short (3-5 word) description of the task"),prompt:i.string().describe("The task for the agent to perform"),subagent_type:i.string().optional().describe("The type of specialized agent to use for this task"),model:i.enum(["sonnet","opus","haiku"]).optional().describe("Optional model override for this agent. Takes precedence over the agent definition's model frontmatter. If omitted, uses the agent definition's model, or inherits from the parent."),run_in_background:i.boolean().optional().describe("Set to true to run this agent in the background. You will be notified when it completes.")})),ot=W(()=>{const e=i.object({name:i.string().optional().describe("Name for the spawned agent. Makes it addressable via SendMessage({to: name}) while running."),team_name:i.string().optional().describe("Team name for spawning. Uses current team context if omitted."),mode:ee().optional().describe('Permission mode for spawned teammate (e.g., "plan" to require plan approval).')});return tt().merge(e).extend({isolation:i.enum(["worktree"]).optional().describe('Isolation mode. "worktree" creates a temporary git worktree so the agent works on an isolated copy of the repo.'),cwd:i.string().optional().describe('Absolute path to run the agent in. Overrides the working directory for all filesystem and shell operations within this agent. Mutually exclusive with isolation: "worktree".')})});export const inputSchema=W(()=>{const t=e("KAIROS")?ot():ot().omit({cwd:!0});return et||Me()?t.omit({run_in_background:!0}):t});export const outputSchema=W(()=>{const e=Ae().extend({status:i.literal("completed"),prompt:i.string()}),t=i.object({status:i.literal("async_launched"),agentId:i.string().describe("The ID of the async agent"),description:i.string().describe("The description of the task"),prompt:i.string().describe("The prompt for the agent"),outputFile:i.string().describe("Path to the output file for checking agent progress"),canReadOutputFile:i.boolean().optional().describe("Whether the calling agent has Read/Bash tools to check progress")});return i.union([e,t])});export const AgentTool=n({async prompt({agents:t,tools:o,getToolPermissionContext:s,allowedAgentTypes:n}){const r=await s(),a=[];for(const e of o)if(e.name?.startsWith("mcp__")){const t=e.name.split("__")[1];t&&!a.includes(t)&&a.push(t)}const i=Le(t,a),l=te(i,r,Ue),p=!!e("COORDINATOR_MODE")&&(q(process.env.CONTEXT_CODE_COORDINATOR_MODE)||q(process.env.CLAUDE_CODE_COORDINATOR_MODE));return await qe(l,p,n)},name:Ue,searchHint:"delegate work to a subagent",aliases:[Oe],maxResultSizeChars:1e5,description:async()=>"Launch a new agent",get inputSchema(){return inputSchema()},get outputSchema(){return outputSchema()},async call({prompt:o,subagent_type:s,description:n,model:i,run_in_background:U,name:O,team_name:R,mode:x,isolation:W,cwd:ee},ue,Ae,Oe,Re){const Le=Date.now(),qe=u()?void 0:i,ze=ue.getAppState(),Xe=ze.toolPermissionContext.mode,We=ue.setAppStateForTasks??ue.setAppState;if(R&&!B())throw new Error("Agent Teams aún no está disponible en tu plan.");const Ge=function(e,t){return B()?e.team_name||t.teamContext?.teamName:void 0}({team_name:R},ze);if(me()&&Ge&&O)throw new Error("Los compañeros no pueden lanzar otros compañeros — la lista del equipo es plana. Para lanzar un subagente, omite el parámetro `name`.");if(ce()&&Ge&&!0===U)throw new Error("Los compañeros en proceso no pueden lanzar agentes en segundo plano. Usa run_in_background=false para subagentes síncronos.");if(Ge&&O){const e=s?ue.options.agentDefinitions.activeAgents.find(e=>e.agentType===s):void 0;e?.color&&be(s,e.color);const t=await Te({name:O,prompt:o,description:n,team_name:Ge,use_splitpane:!0,plan_mode_required:"plan"===x,model:qe??e?.model,agent_type:s,invokingRequestId:Oe?.requestId},ue);return{data:{status:"teammate_spawned",prompt:o,...t.data}}}const Je=s??(Me()?void 0:Pe.agentType),He=void 0===Je;let Ye;if(He){if(ue.options.querySource===`agent:builtin:${Ee.agentType}`||Be(ue.messages))throw new Error("Fork no está disponible dentro de un worker bifurcado. Completa tu tarea directamente con tus herramientas.");Ye=Ee}else{const e=ue.options.agentDefinitions.activeAgents,{allowedAgentTypes:t}=ue.options.agentDefinitions,o=te(t?e.filter(e=>t.includes(e.agentType)):e,ze.toolPermissionContext,Ue),s=o.find(e=>e.agentType===Je);if(!s){if(e.find(e=>e.agentType===Je)){const e=oe(ze.toolPermissionContext,Ue,Je);throw new Error(`Agent type '${Je}' has been denied by permission rule '${Ue}(${Je})' from ${e?.source??"settings"}.`)}throw new Error(`Agent type '${Je}' not found. Available agents: ${o.map(e=>e.agentType).join(", ")}`)}Ye=s}if(ce()&&Ge&&!0===Ye.background)throw new Error(`In-process teammates cannot spawn background agents. Agent '${Ye.agentType}' has background: true in its definition.`);const Qe=Ye.requiredMcpServers;if(Qe?.length){const e=ze.mcp.clients.some(e=>"pending"===e.type&&Qe.some(t=>e.name.toLowerCase().includes(t.toLowerCase())));let t=ze;if(e){const e=3e4,o=500,s=Date.now()+e;for(;Date.now()<s;){await re(o),t=ue.getAppState();if(t.mcp.clients.some(e=>"failed"===e.type&&Qe.some(t=>e.name.toLowerCase().includes(t.toLowerCase()))))break;if(!t.mcp.clients.some(e=>"pending"===e.type&&Qe.some(t=>e.name.toLowerCase().includes(t.toLowerCase()))))break}}const o=[];for(const e of t.mcp.tools)if(e.name?.startsWith("mcp__")){const t=e.name.split("__")[1];t&&!o.includes(t)&&o.push(t)}if(!Ne(Ye,o)){const e=Qe.filter(e=>!o.some(t=>t.toLowerCase().includes(e.toLowerCase())));throw new Error(`Agent '${Ye.agentType}' requires MCP servers matching: ${e.join(", ")}. MCP servers with tools: ${o.length>0?o.join(", "):"none"}. Use /mcp to configure and authenticate the required MCP servers.`)}}Ye.color&&be(Ye.agentType,Ye.color);const Ve=Z(Ye.provider),withAgentProvider=e=>V(Ve,e),tt=withAgentProvider(()=>Q(Ye.model,ue.options.mainLoopModel,He?void 0:qe,Xe));f("tengu_agent_tool_selected",{agent_type:Ye.agentType,model:tt,source:Ye.source,color:Ye.color,is_built_in_agent:Fe(Ye),is_resume:!1,is_async:(!0===U||!0===Ye.background)&&!et,is_fork:He});const ot=W??Ye.isolation;let st,nt,rt;if(He){if(ue.renderedSystemPrompt)nt=ue.renderedSystemPrompt;else{const e=ze.agent?ze.agentDefinitions.activeAgents.find(e=>e.agentType===ze.agent):void 0,t=Array.from(ze.toolPermissionContext.additionalWorkingDirectories.keys()),o=await c(ue.options.tools,ue.options.mainLoopModel,t,ue.options.mcpClients);nt=ae({mainThreadAgentDefinition:e,toolUseContext:ue,customSystemPrompt:ue.options.customSystemPrompt,defaultSystemPrompt:o,appendSystemPrompt:ue.options.appendSystemPrompt})}rt=xe(o,Oe)}else{try{const e=Array.from(ze.toolPermissionContext.additionalWorkingDirectories.keys()),t=Ye.getSystemPrompt({toolUseContext:ue});Ye.memory&&f("tengu_agent_memory_loaded",{scope:Ye.memory,source:"subagent"}),st=await withAgentProvider(()=>m([t],tt,e))}catch(e){F(`Failed to get system prompt for agent ${Ye.agentType}: ${z(e)}`)}rt=[G({content:o})]}const at={prompt:o,resolvedAgentModel:tt,isBuiltInAgent:Fe(Ye),startTime:Le,agentType:Ye.agentType,isAsync:(!0===U||!0===Ye.background)&&!et},it=!!e("COORDINATOR_MODE")&&(q(process.env.CONTEXT_CODE_COORDINATOR_MODE)||q(process.env.CLAUDE_CODE_COORDINATOR_MODE)),lt=Me(),pt=!!e("KAIROS")&&ze.kairosEnabled,mt=(!0===U||!0===Ye.background||it||lt||pt||(Ze?.isProactiveActive()??!1))&&!et,ct={...ze.toolPermissionContext,mode:Ye.permissionMode??"acceptEdits"},ut=$(ct,ze.mcp.tools),dt=ge();let gt=null;if("worktree"===ot){const e=`agent-${dt.slice(0,8)}`;gt=await fe(e)}He&&gt&&rt.push(G({content:$e(L(),gt.worktreePath)}));const ft={agentDefinition:Ye,promptMessages:rt,toolUseContext:ue,canUseTool:Ae,isAsync:mt,querySource:ue.options.querySource??a(Ye.agentType,Fe(Ye)),model:He?void 0:qe,override:He?{systemPrompt:nt}:!st||gt||ee?void 0:{systemPrompt:ie(st)},availableTools:He?ue.options.tools:ut,forkContextMessages:He?ue.messages:void 0,...He&&{useExactTools:!0},worktreePath:gt?.worktreePath,description:n},yt=ee??gt?.worktreePath,wrapWithCwd=e=>yt?N(yt,e):e(),cleanupWorktreeIfNeeded=async()=>{if(!gt)return{};const{worktreePath:e,worktreeBranch:t,headCommit:o,gitRoot:s,hookBased:r}=gt;if(gt=null,r)return F(`Hook-based agent worktree kept at: ${e}`),{worktreePath:e};if(o){if(!await ye(e,o))return await he(e,t,s),ne(E(dt),{agentType:Ye.agentType,description:n}).catch(e=>F(`Failed to clear worktree metadata: ${e}`)),{}}return F(`Agent worktree has changes, keeping: ${e}`),{worktreePath:e,worktreeBranch:t}};if(mt){const e=dt,t=v({agentId:e,description:n,prompt:o,selectedAgent:Ye,setAppState:We,toolUseId:ue.toolUseId});O&&We(t=>{const o=new Map(t.agentNameRegistry);return o.set(O,E(e)),{...t,agentNameRegistry:o}});const s={agentId:e,parentSessionId:pe(),agentType:"subagent",subagentName:Ye.agentType,isBuiltIn:Fe(Ye),invokingRequestId:Oe?.requestId,invocationKind:"spawn",invocationEmitted:!1};withAgentProvider(()=>M(s,()=>wrapWithCwd(()=>De({taskId:t.agentId,abortController:t.abortController,makeStream:e=>Ke({...ft,override:{...ft.override,agentId:E(t.agentId),abortController:t.abortController},onCacheSafeParams:e}),metadata:at,description:n,toolUseContext:ue,rootSetAppState:We,agentIdForCleanup:e,enableSummarization:it||Me()||p(),getWorktreeResult:cleanupWorktreeIfNeeded}))));const a=ue.options.tools.some(e=>r(e,ke)||r(e,_e));return{data:{isAsync:!0,status:"async_launched",agentId:t.agentId,description:n,prompt:o,outputFile:le(t.agentId),canReadOutputFile:a}}}{const s=E(dt),a={agentId:s,parentSessionId:pe(),agentType:"subagent",subagentName:Ye.agentType,isBuiltIn:Fe(Ye),invokingRequestId:Oe?.requestId,invocationKind:"spawn",invocationEmitted:!1};return withAgentProvider(()=>M(a,()=>wrapWithCwd(async()=>{const i=[],m=Date.now(),c=w(),u=_(ue.options.tools);if(rt.length>0){const e=Y(rt).find(e=>"user"===e.type);e&&"user"===e.type&&Re&&Re({toolUseID:`agent_${Oe.message.id}`,data:{message:e,type:"agent_progress",prompt:o,agentId:s}})}let v,U,O;if(!et){const e=S({agentId:s,description:n,prompt:o,selectedAgent:Ye,setAppState:We,toolUseId:ue.toolUseId,autoBackgroundMs:(q(process.env.CONTEXT_AUTO_BACKGROUND_TASKS)||q(process.env.CLAUDE_AUTO_BACKGROUND_TASKS)||g("tengu_auto_background_agents",!1)?12e4:0)||void 0});v=e.taskId,U=e.backgroundSignal.then(()=>({type:"background"})),O=e.cancelAutoBackground}let R,x=!1,$=!1;const B=v,L=Ke({...ft,override:{...ft.override,agentId:s},onCacheSafeParams:B&&p()?e=>{const{stop:t}=d(B,s,e,We);R=t}:void 0})[Symbol.asyncIterator]();let N,W=!1,G={};try{for(;;){const g=Date.now()-m;!et&&!x&&g>=2e3&&ue.setToolJSX&&(x=!0,ue.setToolJSX({jsx:t(we,{}),shouldHidePromptInput:!1,shouldContinueAnimation:!0,showSpinner:!0}));const S=L.next(),j=U?await Promise.race([S.then(e=>({type:"message",result:e})),U]):{type:"message",result:await S};if("background"===j.type&&v){const t=ue.getAppState().tasks[v];if(C(t)&&t.isBackgrounded){const m=v;$=!0,R?.(),withAgentProvider(()=>M(a,async()=>{let o;try{await Promise.race([L.return(void 0).catch(()=>{}),re(1e3)]);const s=w(),r=_(ue.options.tools);for(const e of i)P(s,e,r,ue.options.tools);for await(const e of Ke({...ft,isAsync:!0,override:{...ft.override,agentId:E(m),abortController:t.abortController},onCacheSafeParams:p()?e=>{const{stop:t}=d(m,E(m),e,We);o=t}:void 0})){i.push(e),P(s,e,r,ue.options.tools),D(m,b(s),We);const t=je(e);t&&Ie(s,m,ue.toolUseId,n,Le,t)}const a=ve(i,m,at);h(a,We);let l=J(a.content,"\n");if(e("TRANSCRIPT_CLASSIFIER")){const e=ue.getAppState(),o=await Ce({agentMessages:i,tools:ue.options.tools,toolPermissionContext:e.toolPermissionContext,abortSignal:t.abortController.signal,subagentType:Ye.agentType,totalToolUseCount:a.totalToolUseCount});o&&(l=`${o}\n\n${l}`)}const c=await cleanupWorktreeIfNeeded();k({taskId:m,description:n,status:"completed",setAppState:We,finalMessage:l,usage:{totalTokens:A(s),toolUses:a.totalToolUseCount,durationMs:a.totalDurationMs},toolUseId:ue.toolUseId,...c})}catch(e){if(e instanceof K){I(m,We),f("tengu_agent_tool_terminated",{agent_type:at.agentType,model:at.resolvedAgentModel,duration_ms:Date.now()-at.startTime,is_async:!0,is_built_in_agent:at.isBuiltInAgent,reason:"user_cancel_background"});const e=await cleanupWorktreeIfNeeded(),t=Se(i);return void k({taskId:m,description:n,status:"killed",setAppState:We,toolUseId:ue.toolUseId,finalMessage:t,...e})}const t=z(e);T(m,t,We);const o=await cleanupWorktreeIfNeeded();k({taskId:m,description:n,status:"failed",error:t,setAppState:We,toolUseId:ue.toolUseId,...o})}finally{o?.(),l(s),y(s)}}));const c=ue.options.tools.some(e=>r(e,ke)||r(e,_e));return{data:{isAsync:!0,status:"async_launched",agentId:m,description:n,prompt:o,outputFile:le(m),canReadOutputFile:c}}}}if("message"!==j.type)continue;const{result:O}=j;if(O.done)break;const B=O.value;if(i.push(B),P(c,B,u,ue.options.tools),v){const e=je(B);e&&(Ie(c,v,ue.toolUseId,n,m,e),p()&&D(v,b(c),We))}if("progress"!==B.type||"bash_progress"!==B.data.type&&"powershell_progress"!==B.data.type||!Re||Re({toolUseID:B.toolUseID,data:B.data}),"assistant"!==B.type&&"user"!==B.type)continue;if("assistant"===B.type){const e=de(B);e>0&&ue.setResponseLength(t=>t+e)}const N=Y([B]);for(const e of N)for(const t of e.message.content)"tool_use"!==t.type&&"tool_result"!==t.type||Re&&Re({toolUseID:`agent_${Oe.message.id}`,data:{message:e,type:"agent_progress",prompt:"",agentId:s}})}}catch(e){if(e instanceof K)throw W=!0,f("tengu_agent_tool_terminated",{agent_type:at.agentType,model:at.resolvedAgentModel,duration_ms:Date.now()-at.startTime,is_async:!1,is_built_in_agent:at.isBuiltInAgent,reason:"user_cancel_sync"}),e;F(`Sync agent error: ${z(e)}`,{level:"error"}),N=X(e)}finally{if(ue.setToolJSX&&ue.setToolJSX(null),R?.(),v&&(j(v,We),!$)){const e=b(c);se({type:"system",subtype:"task_notification",task_id:v,tool_use_id:ue.toolUseId,status:N?"failed":W?"stopped":"completed",output_file:"",summary:n,usage:{total_tokens:e.tokenCount,tool_uses:e.toolUseCount,duration_ms:Date.now()-m}})}l(s),$||y(s),O?.(),$||(G=await cleanupWorktreeIfNeeded())}const Q=i.findLast(e=>"system"!==e.type&&"progress"!==e.type);if(Q&&H(Q))throw f("tengu_agent_tool_terminated",{agent_type:at.agentType,model:at.resolvedAgentModel,duration_ms:Date.now()-at.startTime,is_async:!1,is_built_in_agent:at.isBuiltInAgent,reason:"user_cancel_sync"}),new K;if(N){if(!i.some(e=>"assistant"===e.type))throw N;F(`Sync agent recovering from error with ${i.length} messages`)}const V=ve(i,s,at);if(e("TRANSCRIPT_CLASSIFIER")){const e=ue.getAppState(),t=await Ce({agentMessages:i,tools:ue.options.tools,toolPermissionContext:e.toolPermissionContext,abortSignal:ue.abortController.signal,subagentType:Ye.agentType,totalToolUseCount:V.totalToolUseCount});t&&(V.content=[{type:"text",text:t},...V.content])}return{data:{status:"completed",prompt:o,...V,...G}}})))}},isReadOnly:()=>!0,toAutoClassifierInput(e){const t=e,o=[t.subagent_type,t.mode?`mode=${t.mode}`:void 0].filter(e=>void 0!==e);return`${o.length>0?`(${o.join(", ")}): `:": "}${t.prompt}`},isConcurrencySafe:()=>!0,userFacingName:Qe,userFacingNameBackgroundColor:Ve,getActivityDescription:e=>e?.description??"Running task",async checkPermissions(e,t){t.getAppState();return{behavior:"allow",updatedInput:e}},mapToolResultToToolResultBlockParam(e,t){const o=e;if("object"==typeof o&&null!==o&&"status"in o&&"teammate_spawned"===o.status){const e=o;return{tool_use_id:t,type:"tool_result",content:[{type:"text",text:`Spawned successfully.\nagent_id: ${e.teammate_id}\nname: ${e.name}\nteam_name: ${e.team_name}\nThe agent is now running and will receive instructions via mailbox.`}]}}if("status"in o&&"remote_launched"===o.status){const e=o;return{tool_use_id:t,type:"tool_result",content:[{type:"text",text:`Remote agent launched in CCR.\ntaskId: ${e.taskId}\nsession_url: ${e.sessionUrl}\noutput_file: ${e.outputFile}\nThe agent is running remotely. You will be notified automatically when it completes.\nBriefly tell the user what you launched and end your response.`}]}}if("async_launched"===e.status){return{tool_use_id:t,type:"tool_result",content:[{type:"text",text:`${`Async agent launched successfully.\nagentId: ${e.agentId} (internal ID - do not mention to user. Use SendMessage with to: '${e.agentId}' to continue this agent.)\nThe agent is working in the background. You will be notified automatically when it completes.`}\n${e.canReadOutputFile?`Do not duplicate this agent's work — avoid working with the same files or topics it is using. Work on non-overlapping tasks, or briefly tell the user what you launched and end your response.\noutput_file: ${e.outputFile}\nIf asked, you can check progress before completion by using ${ke} or ${_e} tail on the output file.`:"Briefly tell the user what you launched and end your response. Do not generate any other text — agent results will arrive in a subsequent message."}`}]}}if("completed"===e.status){const o=e,s=o.worktreePath?`\nworktreePath: ${o.worktreePath}\nworktreeBranch: ${o.worktreeBranch}`:"",n=e.content.length>0?e.content:[{type:"text",text:"(Subagent completed but returned no output.)"}];return e.agentType&&Re.has(e.agentType)&&!s?{tool_use_id:t,type:"tool_result",content:n}:{tool_use_id:t,type:"tool_result",content:[...n,{type:"text",text:`agentId: ${e.agentId} (use SendMessage with to: '${e.agentId}' to continue this agent)${s}\n<usage>total_tokens: ${e.totalTokens}\ntool_uses: ${e.totalToolUseCount}\nduration_ms: ${e.totalDurationMs}</usage>`}]}}throw new Error(`Unexpected agent tool result status: ${e.status}`)},renderToolResultMessage:Xe,renderToolUseMessage:Ge,renderToolUseTag:Ye,renderToolUseProgressMessage:Je,renderToolUseRejectedMessage:He,renderToolUseErrorMessage:We,renderGroupedToolUse:ze});
@@ -1 +1 @@
1
- import{feature as e}from"../../recovery/bunBundleShim.js";import{getRemoteControlAtStartup as o}from"../../utils/config.js";import{EDITOR_MODES as t,NOTIFICATION_CHANNELS as n,TEAMMATE_MODES as i}from"../../utils/configConstants.js";import{getModelOptions as s}from"../../utils/model/modelOptions.js";import{validateModel as r}from"../../utils/model/validateModel.js";import{THEME_NAMES as a,THEME_SETTINGS as l}from"../../utils/theme.js";export const SUPPORTED_SETTINGS={theme:{source:"global",type:"string",description:"Color theme for the UI",options:e("AUTO_THEME")?l:a},editorMode:{source:"global",type:"string",description:"Key binding mode",options:t},verbose:{source:"global",type:"boolean",description:"Show detailed debug output",appStateKey:"verbose"},preferredNotifChannel:{source:"global",type:"string",description:"Preferred notification channel",options:n},autoCompactEnabled:{source:"global",type:"boolean",description:"Auto-compact when context is full"},autoMemoryEnabled:{source:"settings",type:"boolean",description:"Enable auto-memory"},autoDreamEnabled:{source:"settings",type:"boolean",description:"Enable background memory consolidation"},fileCheckpointingEnabled:{source:"global",type:"boolean",description:"Enable file checkpointing for code rewind"},showTurnDuration:{source:"global",type:"boolean",description:'Show turn duration message after responses (e.g., "Cooked for 1m 6s")'},terminalProgressBarEnabled:{source:"global",type:"boolean",description:"Show OSC 9;4 progress indicator in supported terminals"},todoFeatureEnabled:{source:"global",type:"boolean",description:"Enable todo/task tracking"},model:{source:"settings",type:"string",description:"Override the default model",appStateKey:"mainLoopModel",getOptions:()=>{try{return s().filter(e=>null!==e.value).map(e=>e.value)}catch{return["sonnet","opus","haiku"]}},validateOnWrite:e=>r(String(e)),formatOnRead:e=>null===e?"default":e},alwaysThinkingEnabled:{source:"settings",type:"boolean",description:"Enable extended thinking (false to disable)",appStateKey:"thinkingEnabled"},"permissions.defaultMode":{source:"settings",type:"string",description:"Default permission mode for tool usage",options:e("TRANSCRIPT_CLASSIFIER")?["default","plan","acceptEdits","dontAsk","auto"]:["default","plan","acceptEdits","dontAsk"]},language:{source:"settings",type:"string",description:'Idioma preferido para las respuestas de Context y el dictado local (por ejemplo, "japanese", "spanish")'},teammateMode:{source:"global",type:"string",description:'How to spawn teammates: "tmux" for traditional tmux, "in-process" for same process, "auto" to choose automatically',options:i},..."ant"===process.env.USER_TYPE?{classifierPermissionsEnabled:{source:"settings",type:"boolean",description:"Enable AI-based classification for Bash(prompt:...) permission rules"}}:{},...e("VOICE_MODE")?{voiceEnabled:{source:"settings",type:"boolean",description:"Activar dictado local (mantener pulsado para hablar)"}}:{},...e("BRIDGE_MODE")?{remoteControlAtStartup:{source:"global",type:"boolean",description:"Enable Remote Control for all sessions (true | false | default)",formatOnRead:()=>o()}}:{},...e("KAIROS")||e("KAIROS_PUSH_NOTIFICATION")?{taskCompleteNotifEnabled:{source:"global",type:"boolean",description:"Push to your mobile device when idle after Claude finishes (requires Remote Control)"},inputNeededNotifEnabled:{source:"global",type:"boolean",description:"Push to your mobile device when a permission prompt or question is waiting (requires Remote Control)"},agentPushNotifEnabled:{source:"global",type:"boolean",description:"Allow Claude to push to your mobile device when it deems it appropriate (requires Remote Control)"}}:{}};export function isSupported(e){return e in SUPPORTED_SETTINGS}export function getConfig(e){return SUPPORTED_SETTINGS[e]}export function getAllKeys(){return Object.keys(SUPPORTED_SETTINGS)}export function getOptionsForSetting(e){const o=SUPPORTED_SETTINGS[e];if(o)return o.options?[...o.options]:o.getOptions?o.getOptions():void 0}export function getPath(e){const o=SUPPORTED_SETTINGS[e];return o?.path??e.split(".")}
1
+ import{feature as e}from"../../recovery/bunBundleShim.js";import{getRemoteControlAtStartup as o}from"../../utils/config.js";import{EDITOR_MODES as t,NOTIFICATION_CHANNELS as n,TEAMMATE_MODES as i}from"../../utils/configConstants.js";import{getModelOptions as r}from"../../utils/model/modelOptions.js";import{validateModel as s}from"../../utils/model/validateModel.js";import{THEME_NAMES as a,THEME_SETTINGS as l}from"../../utils/theme.js";export const SUPPORTED_SETTINGS={theme:{source:"global",type:"string",description:"Color theme for the UI",options:e("AUTO_THEME")?l:a},editorMode:{source:"global",type:"string",description:"Key binding mode",options:t},verbose:{source:"global",type:"boolean",description:"Show detailed debug output",appStateKey:"verbose"},preferredNotifChannel:{source:"global",type:"string",description:"Preferred notification channel",options:n},autoCompactEnabled:{source:"global",type:"boolean",description:"Auto-compact when context is full"},autoMemoryEnabled:{source:"settings",type:"boolean",description:"Enable auto-memory"},autoDreamEnabled:{source:"settings",type:"boolean",description:"Enable background memory consolidation"},fileCheckpointingEnabled:{source:"global",type:"boolean",description:"Enable file checkpointing for code rewind"},showTurnDuration:{source:"global",type:"boolean",description:'Show turn duration message after responses (e.g., "Cooked for 1m 6s")'},terminalProgressBarEnabled:{source:"global",type:"boolean",description:"Show OSC 9;4 progress indicator in supported terminals"},todoFeatureEnabled:{source:"global",type:"boolean",description:"Enable todo/task tracking"},model:{source:"settings",type:"string",description:"Override the default model",appStateKey:"mainLoopModel",getOptions:()=>{try{return r().filter(e=>null!==e.value).map(e=>e.value)}catch{return["sonnet","opus","haiku"]}},validateOnWrite:e=>s(String(e)),formatOnRead:e=>null===e?"default":e},alwaysThinkingEnabled:{source:"settings",type:"boolean",description:"Enable extended thinking (false to disable)",appStateKey:"thinkingEnabled"},"permissions.defaultMode":{source:"settings",type:"string",description:"Default permission mode for tool usage",options:e("TRANSCRIPT_CLASSIFIER")?["default","plan","acceptEdits","dontAsk","auto"]:["default","plan","acceptEdits","dontAsk"]},language:{source:"settings",type:"string",description:'Idioma preferido para las respuestas de Context y el dictado local (por ejemplo, "japanese", "spanish")'},teammateMode:{source:"global",type:"string",description:'How to spawn teammates: "tmux" for traditional tmux, "in-process" for same process, "auto" to choose automatically',options:i},..."ant"===process.env.USER_TYPE?{classifierPermissionsEnabled:{source:"settings",type:"boolean",description:"Enable AI-based classification for Bash(prompt:...) permission rules"}}:{},...e("VOICE_MODE")?{voiceEnabled:{source:"settings",type:"boolean",description:"Activar dictado local (mantener pulsado para hablar)"}}:{},...e("BRIDGE_MODE")?{remoteControlAtStartup:{source:"global",type:"boolean",description:"Enable Remote Control for all sessions (true | false | default)",formatOnRead:()=>o()}}:{},...e("KAIROS")||e("KAIROS_PUSH_NOTIFICATION")?{taskCompleteNotifEnabled:{source:"global",type:"boolean",description:"Enviar push a tu móvil cuando Context termine y quede inactivo (requiere Remote Control)"},inputNeededNotifEnabled:{source:"global",type:"boolean",description:"Enviar push a tu móvil cuando haya un prompt de permiso o pregunta esperando (requiere Remote Control)"},agentPushNotifEnabled:{source:"global",type:"boolean",description:"Permitir a Context enviar push a tu móvil cuando lo considere apropiado (requiere Remote Control)"}}:{}};export function isSupported(e){return e in SUPPORTED_SETTINGS}export function getConfig(e){return SUPPORTED_SETTINGS[e]}export function getAllKeys(){return Object.keys(SUPPORTED_SETTINGS)}export function getOptionsForSetting(e){const o=SUPPORTED_SETTINGS[e];if(o)return o.options?[...o.options]:o.getOptions?o.getOptions():void 0}export function getPath(e){const o=SUPPORTED_SETTINGS[e];return o?.path??e.split(".")}
@@ -1 +1 @@
1
- import{z as e}from"zod/v4";import{getSessionId as t,setOriginalCwd as r}from"../../bootstrap/state.js";import{clearSystemPromptSections as o}from"../../constants/systemPromptSections.js";import{logEvent as s}from"../../services/analytics/index.js";import{buildTool as a}from"../../Tool.js";import{clearMemoryFileCaches as i}from"../../utils/claudemd.js";import{getCwd as n}from"../../utils/cwd.js";import{findCanonicalGitRoot as m}from"../../utils/git.js";import{lazySchema as c}from"../../utils/lazySchema.js";import{getPlanSlug as l,getPlansDirectory as p}from"../../utils/plans.js";import{setCwd as d}from"../../utils/Shell.js";import{saveWorktreeState as h}from"../../utils/sessionStorage.js";import{createWorktreeForSession as u,getCurrentWorktreeSession as w,validateWorktreeSlug as g}from"../../utils/worktree.js";import{ENTER_WORKTREE_TOOL_NAME as k}from"./constants.js";import{getEnterWorktreeToolPrompt as f}from"./prompt.js";import{renderToolResultMessage as j,renderToolUseMessage as y}from"./UI.js";const P=c(()=>e.strictObject({name:e.string().superRefine((e,t)=>{try{g(e)}catch(e){t.addIssue({code:"custom",message:e.message})}}).optional().describe('Optional name for the worktree. Each "/"-separated segment may contain only letters, digits, dots, underscores, and dashes; max 64 chars total. A random name is generated if not provided.')})),T=c(()=>e.object({worktreePath:e.string(),worktreeBranch:e.string().optional(),message:e.string()}));export const EnterWorktreeTool=a({name:k,searchHint:"create an isolated git worktree and switch into it",maxResultSizeChars:1e5,description:async()=>"Creates an isolated worktree (via git or configured hooks) and switches the session into it",prompt:async()=>f(),get inputSchema(){return P()},get outputSchema(){return T()},userFacingName:()=>"Creating worktree",shouldDefer:!0,toAutoClassifierInput:e=>e.name??"",renderToolUseMessage:y,renderToolResultMessage:j,async call(e){if(w())throw new Error("Already in a worktree session");const a=m(n());a&&a!==n()&&(process.chdir(a),d(a));const c=e.name??l(),g=await u(t(),c);process.chdir(g.worktreePath),d(g.worktreePath),r(n()),h(g),o(),i(),p.cache.clear?.(),s("tengu_worktree_created",{mid_session:!0});const k=g.worktreeBranch?` on branch ${g.worktreeBranch}`:"";return{data:{worktreePath:g.worktreePath,worktreeBranch:g.worktreeBranch,message:`Created worktree at ${g.worktreePath}${k}. The session is now working in the worktree. Use ExitWorktree to leave mid-session, or exit the session to be prompted.`}}},mapToolResultToToolResultBlockParam:({message:e},t)=>({type:"tool_result",content:e,tool_use_id:t})});
1
+ import{z as e}from"zod/v4";import{getSessionId as t,setOriginalCwd as r}from"../../bootstrap/state.js";import{clearSystemPromptSections as o}from"../../constants/systemPromptSections.js";import{logEvent as s}from"../../services/analytics/index.js";import{buildTool as a}from"../../Tool.js";import{clearMemoryFileCaches as i}from"../../utils/claudemd.js";import{getCwd as n}from"../../utils/cwd.js";import{findCanonicalGitRoot as m}from"../../utils/git.js";import{lazySchema as c}from"../../utils/lazySchema.js";import{getPlanSlug as l,getPlansDirectory as p}from"../../utils/plans.js";import{setCwd as d}from"../../utils/Shell.js";import{saveWorktreeState as h}from"../../utils/sessionStorage.js";import{createWorktreeForSession as u,getCurrentWorktreeSession as w,validateWorktreeSlug as g}from"../../utils/worktree.js";import{ENTER_WORKTREE_TOOL_NAME as k}from"./constants.js";import{getEnterWorktreeToolPrompt as f}from"./prompt.js";import{renderToolResultMessage as j,renderToolUseMessage as y}from"./UI.js";const P=c(()=>e.strictObject({name:e.string().superRefine((e,t)=>{try{g(e)}catch(e){t.addIssue({code:"custom",message:e.message})}}).optional().describe('Optional name for the worktree. Each "/"-separated segment may contain only letters, digits, dots, underscores, and dashes; max 64 chars total. A random name is generated if not provided.')})),T=c(()=>e.object({worktreePath:e.string(),worktreeBranch:e.string().optional(),message:e.string()}));export const EnterWorktreeTool=a({name:k,searchHint:"create an isolated git worktree and switch into it",maxResultSizeChars:1e5,description:async()=>"Creates an isolated worktree (via git or configured hooks) and switches the session into it",prompt:async()=>f(),get inputSchema(){return P()},get outputSchema(){return T()},userFacingName:()=>"Creating worktree",shouldDefer:!0,toAutoClassifierInput:e=>e.name??"",renderToolUseMessage:y,renderToolResultMessage:j,async call(e){if(w())throw new Error("Ya estás en una sesión de worktree");const a=m(n());a&&a!==n()&&(process.chdir(a),d(a));const c=e.name??l(),g=await u(t(),c);process.chdir(g.worktreePath),d(g.worktreePath),r(n()),h(g),o(),i(),p.cache.clear?.(),s("tengu_worktree_created",{mid_session:!0});const k=g.worktreeBranch?` on branch ${g.worktreeBranch}`:"";return{data:{worktreePath:g.worktreePath,worktreeBranch:g.worktreeBranch,message:`Created worktree at ${g.worktreePath}${k}. The session is now working in the worktree. Use ExitWorktree to leave mid-session, or exit the session to be prompted.`}}},mapToolResultToToolResultBlockParam:({message:e},t)=>({type:"tool_result",content:e,tool_use_id:t})});
@@ -1 +1 @@
1
- import{z as e}from"zod/v4";import{getOriginalCwd as t,getProjectRoot as r,setOriginalCwd as o,setProjectRoot as s}from"../../bootstrap/state.js";import{clearSystemPromptSections as i}from"../../constants/systemPromptSections.js";import{logEvent as n}from"../../services/analytics/index.js";import{buildTool as a}from"../../Tool.js";import{count as m}from"../../utils/array.js";import{clearMemoryFileCaches as c}from"../../utils/claudemd.js";import{execFileNoThrow as l}from"../../utils/execFileNoThrow.js";import{updateHooksConfigSnapshot as u}from"../../utils/hooks/hooksConfigSnapshot.js";import{lazySchema as d}from"../../utils/lazySchema.js";import{getPlansDirectory as h}from"../../utils/plans.js";import{setCwd as p}from"../../utils/Shell.js";import{saveWorktreeState as w}from"../../utils/sessionStorage.js";import{cleanupWorktree as g,getCurrentWorktreeSession as k,keepWorktree as f,killTmuxSession as v}from"../../utils/worktree.js";import{EXIT_WORKTREE_TOOL_NAME as C}from"./constants.js";import{getExitWorktreeToolPrompt as $}from"./prompt.js";import{renderToolResultMessage as j,renderToolUseMessage as y}from"./UI.js";const x=d(()=>e.strictObject({action:e.enum(["keep","remove"]).describe('"keep" leaves the worktree and branch on disk; "remove" deletes both.'),discard_changes:e.boolean().optional().describe('Required true when action is "remove" and the worktree has uncommitted files or unmerged commits. The tool will refuse and list them otherwise.')})),b=d(()=>e.object({action:e.enum(["keep","remove"]),originalCwd:e.string(),worktreePath:e.string(),worktreeBranch:e.string().optional(),tmuxSessionName:e.string().optional(),discardedFiles:e.number().optional(),discardedCommits:e.number().optional(),message:e.string()}));async function countWorktreeChanges(e,t){const r=await l("git",["-C",e,"status","--porcelain"]);if(0!==r.code)return null;const o=m(r.stdout.split("\n"),e=>""!==e.trim());if(!t)return null;const s=await l("git",["-C",e,"rev-list","--count",`${t}..HEAD`]);if(0!==s.code)return null;return{changedFiles:o,commits:parseInt(s.stdout.trim(),10)||0}}function restoreSessionToOriginalCwd(e,t){p(e),o(e),t&&(s(e),u()),w(null),i(),c(),h.cache.clear?.()}export const ExitWorktreeTool=a({name:C,searchHint:"exit a worktree session and return to the original directory",maxResultSizeChars:1e5,description:async()=>"Exits a worktree session created by EnterWorktree and restores the original working directory",prompt:async()=>$(),get inputSchema(){return x()},get outputSchema(){return b()},userFacingName:()=>"Exiting worktree",shouldDefer:!0,isDestructive:e=>"remove"===e.action,toAutoClassifierInput:e=>e.action,async validateInput(e){const t=k();if(!t)return{result:!1,message:"No-op: there is no active EnterWorktree session to exit. This tool only operates on worktrees created by EnterWorktree in the current session — it will not touch worktrees created manually or in a previous session. No filesystem changes were made.",errorCode:1};if("remove"===e.action&&!e.discard_changes){const e=await countWorktreeChanges(t.worktreePath,t.originalHeadCommit);if(null===e)return{result:!1,message:`Could not verify worktree state at ${t.worktreePath}. Refusing to remove without explicit confirmation. Re-invoke with discard_changes: true to proceed — or use action: "keep" to preserve the worktree.`,errorCode:3};const{changedFiles:r,commits:o}=e;if(r>0||o>0){const e=[];return r>0&&e.push(`${r} uncommitted ${1===r?"file":"files"}`),o>0&&e.push(`${o} ${1===o?"commit":"commits"} on ${t.worktreeBranch??"the worktree branch"}`),{result:!1,message:`Worktree has ${e.join(" and ")}. Removing will discard this work permanently. Confirm with the user, then re-invoke with discard_changes: true — or use action: "keep" to preserve the worktree.`,errorCode:2}}}return{result:!0}},renderToolUseMessage:y,renderToolResultMessage:j,async call(e){const o=k();if(!o)throw new Error("Not in a worktree session");const{originalCwd:s,worktreePath:i,worktreeBranch:a,tmuxSessionName:m,originalHeadCommit:c}=o,l=r()===t(),{changedFiles:u,commits:d}=await countWorktreeChanges(i,c)??{changedFiles:0,commits:0};if("keep"===e.action){await f(),restoreSessionToOriginalCwd(s,l),n("tengu_worktree_kept",{mid_session:!0,commits:d,changed_files:u});return{data:{action:"keep",originalCwd:s,worktreePath:i,worktreeBranch:a,tmuxSessionName:m,message:`Exited worktree. Your work is preserved at ${i}${a?` on branch ${a}`:""}. Session is now back in ${s}.${m?` Tmux session ${m} is still running; reattach with: tmux attach -t ${m}`:""}`}}}m&&await v(m),await g(),restoreSessionToOriginalCwd(s,l),n("tengu_worktree_removed",{mid_session:!0,commits:d,changed_files:u});const h=[];d>0&&h.push(`${d} ${1===d?"commit":"commits"}`),u>0&&h.push(`${u} uncommitted ${1===u?"file":"files"}`);return{data:{action:"remove",originalCwd:s,worktreePath:i,worktreeBranch:a,discardedFiles:u,discardedCommits:d,message:`Exited and removed worktree at ${i}.${h.length>0?` Discarded ${h.join(" and ")}.`:""} Session is now back in ${s}.`}}},mapToolResultToToolResultBlockParam:({message:e},t)=>({type:"tool_result",content:e,tool_use_id:t})});
1
+ import{z as e}from"zod/v4";import{getOriginalCwd as t,getProjectRoot as r,setOriginalCwd as o,setProjectRoot as s}from"../../bootstrap/state.js";import{clearSystemPromptSections as i}from"../../constants/systemPromptSections.js";import{logEvent as n}from"../../services/analytics/index.js";import{buildTool as a}from"../../Tool.js";import{count as m}from"../../utils/array.js";import{clearMemoryFileCaches as c}from"../../utils/claudemd.js";import{execFileNoThrow as l}from"../../utils/execFileNoThrow.js";import{updateHooksConfigSnapshot as u}from"../../utils/hooks/hooksConfigSnapshot.js";import{lazySchema as d}from"../../utils/lazySchema.js";import{getPlansDirectory as h}from"../../utils/plans.js";import{setCwd as p}from"../../utils/Shell.js";import{saveWorktreeState as w}from"../../utils/sessionStorage.js";import{cleanupWorktree as g,getCurrentWorktreeSession as k,keepWorktree as f,killTmuxSession as v}from"../../utils/worktree.js";import{EXIT_WORKTREE_TOOL_NAME as C}from"./constants.js";import{getExitWorktreeToolPrompt as $}from"./prompt.js";import{renderToolResultMessage as j,renderToolUseMessage as y}from"./UI.js";const x=d(()=>e.strictObject({action:e.enum(["keep","remove"]).describe('"keep" leaves the worktree and branch on disk; "remove" deletes both.'),discard_changes:e.boolean().optional().describe('Required true when action is "remove" and the worktree has uncommitted files or unmerged commits. The tool will refuse and list them otherwise.')})),b=d(()=>e.object({action:e.enum(["keep","remove"]),originalCwd:e.string(),worktreePath:e.string(),worktreeBranch:e.string().optional(),tmuxSessionName:e.string().optional(),discardedFiles:e.number().optional(),discardedCommits:e.number().optional(),message:e.string()}));async function countWorktreeChanges(e,t){const r=await l("git",["-C",e,"status","--porcelain"]);if(0!==r.code)return null;const o=m(r.stdout.split("\n"),e=>""!==e.trim());if(!t)return null;const s=await l("git",["-C",e,"rev-list","--count",`${t}..HEAD`]);if(0!==s.code)return null;return{changedFiles:o,commits:parseInt(s.stdout.trim(),10)||0}}function restoreSessionToOriginalCwd(e,t){p(e),o(e),t&&(s(e),u()),w(null),i(),c(),h.cache.clear?.()}export const ExitWorktreeTool=a({name:C,searchHint:"exit a worktree session and return to the original directory",maxResultSizeChars:1e5,description:async()=>"Exits a worktree session created by EnterWorktree and restores the original working directory",prompt:async()=>$(),get inputSchema(){return x()},get outputSchema(){return b()},userFacingName:()=>"Exiting worktree",shouldDefer:!0,isDestructive:e=>"remove"===e.action,toAutoClassifierInput:e=>e.action,async validateInput(e){const t=k();if(!t)return{result:!1,message:"No-op: there is no active EnterWorktree session to exit. This tool only operates on worktrees created by EnterWorktree in the current session — it will not touch worktrees created manually or in a previous session. No filesystem changes were made.",errorCode:1};if("remove"===e.action&&!e.discard_changes){const e=await countWorktreeChanges(t.worktreePath,t.originalHeadCommit);if(null===e)return{result:!1,message:`Could not verify worktree state at ${t.worktreePath}. Refusing to remove without explicit confirmation. Re-invoke with discard_changes: true to proceed — or use action: "keep" to preserve the worktree.`,errorCode:3};const{changedFiles:r,commits:o}=e;if(r>0||o>0){const e=[];return r>0&&e.push(`${r} uncommitted ${1===r?"file":"files"}`),o>0&&e.push(`${o} ${1===o?"commit":"commits"} on ${t.worktreeBranch??"the worktree branch"}`),{result:!1,message:`Worktree has ${e.join(" and ")}. Removing will discard this work permanently. Confirm with the user, then re-invoke with discard_changes: true — or use action: "keep" to preserve the worktree.`,errorCode:2}}}return{result:!0}},renderToolUseMessage:y,renderToolResultMessage:j,async call(e){const o=k();if(!o)throw new Error("No estás en una sesión de worktree");const{originalCwd:s,worktreePath:i,worktreeBranch:a,tmuxSessionName:m,originalHeadCommit:c}=o,l=r()===t(),{changedFiles:u,commits:d}=await countWorktreeChanges(i,c)??{changedFiles:0,commits:0};if("keep"===e.action){await f(),restoreSessionToOriginalCwd(s,l),n("tengu_worktree_kept",{mid_session:!0,commits:d,changed_files:u});return{data:{action:"keep",originalCwd:s,worktreePath:i,worktreeBranch:a,tmuxSessionName:m,message:`Exited worktree. Your work is preserved at ${i}${a?` on branch ${a}`:""}. Session is now back in ${s}.${m?` Tmux session ${m} is still running; reattach with: tmux attach -t ${m}`:""}`}}}m&&await v(m),await g(),restoreSessionToOriginalCwd(s,l),n("tengu_worktree_removed",{mid_session:!0,commits:d,changed_files:u});const h=[];d>0&&h.push(`${d} ${1===d?"commit":"commits"}`),u>0&&h.push(`${u} uncommitted ${1===u?"file":"files"}`);return{data:{action:"remove",originalCwd:s,worktreePath:i,worktreeBranch:a,discardedFiles:u,discardedCommits:d,message:`Exited and removed worktree at ${i}.${h.length>0?` Discarded ${h.join(" and ")}.`:""} Session is now back in ${s}.`}}},mapToolResultToToolResultBlockParam:({message:e},t)=>({type:"tool_result",content:e,tool_use_id:t})});
@@ -1 +1 @@
1
- import{z as e}from"zod/v4";import{buildTool as t}from"../../Tool.js";import{formatFileSize as o}from"../../utils/format.js";import{lazySchema as r}from"../../utils/lazySchema.js";import{getRuleByContentsForTool as s}from"../../utils/permissions/permissions.js";import{isPreapprovedHost as n}from"./preapproved.js";import{DESCRIPTION as a,WEB_FETCH_TOOL_NAME as i}from"./prompt.js";import{getToolUseSummary as c,renderToolResultMessage as u,renderToolUseMessage as l,renderToolUseProgressMessage as d}from"./UI.js";import{applyPromptToMarkdown as p,getURLMarkdownContent as m,isPreapprovedUrl as h,MAX_MARKDOWN_LENGTH as g}from"./utils.js";const f=r(()=>e.strictObject({url:e.string().url().describe("The URL to fetch content from"),prompt:e.string().describe("The prompt to run on the fetched content")})),b=r(()=>e.object({bytes:e.number().describe("Size of the fetched content in bytes"),code:e.number().describe("HTTP response code"),codeText:e.string().describe("HTTP response code text"),result:e.string().describe("Processed result from applying the prompt to the content"),durationMs:e.number().describe("Time taken to fetch and process the content"),url:e.string().describe("The URL that was fetched")}));export const WebFetchTool=t({name:i,searchHint:"fetch and extract content from a URL",maxResultSizeChars:1e5,shouldDefer:!0,async description(e){const{url:t}=e;try{return`Claude wants to fetch content from ${new URL(t).hostname}`}catch{return"Claude wants to fetch content from this URL"}},userFacingName:()=>"Fetch",getToolUseSummary:c,getActivityDescription(e){const t=c(e);return t?`Fetching ${t}`:"Fetching web page"},get inputSchema(){return f()},get outputSchema(){return b()},isConcurrencySafe:()=>!0,isReadOnly:()=>!0,toAutoClassifierInput:e=>e.prompt?`${e.url}: ${e.prompt}`:e.url,async checkPermissions(e,t){const o=t.getAppState().toolPermissionContext;try{const{url:t}=e,o=new URL(t);if(n(o.hostname,o.pathname))return{behavior:"allow",updatedInput:e,decisionReason:{type:"other",reason:"Preapproved host"}}}catch{}const r=function(e){try{const t=WebFetchTool.inputSchema.safeParse(e);if(!t.success)return`input:${e.toString()}`;const{url:o}=t.data;return`domain:${new URL(o).hostname}`}catch{return`input:${e.toString()}`}}(e),a=s(o,WebFetchTool,"deny").get(r);if(a)return{behavior:"deny",message:`${WebFetchTool.name} denied access to ${r}.`,decisionReason:{type:"rule",rule:a}};const i=s(o,WebFetchTool,"ask").get(r);if(i)return{behavior:"ask",message:`Claude requested permissions to use ${WebFetchTool.name}, but you haven't granted it yet.`,decisionReason:{type:"rule",rule:i},suggestions:buildSuggestions(r)};const c=s(o,WebFetchTool,"allow").get(r);return c?{behavior:"allow",updatedInput:e,decisionReason:{type:"rule",rule:c}}:{behavior:"ask",message:`Claude requested permissions to use ${WebFetchTool.name}, but you haven't granted it yet.`,suggestions:buildSuggestions(r)}},prompt:async e=>`IMPORTANT: WebFetch WILL FAIL for authenticated or private URLs. Before using this tool, check if the URL points to an authenticated service (e.g. Google Docs, Confluence, Jira, GitHub). If so, look for a specialized MCP tool that provides authenticated access.\n${a}`,async validateInput(e){const{url:t}=e;try{new URL(t)}catch{return{result:!1,message:`Error: Invalid URL "${t}". The URL provided could not be parsed.`,meta:{reason:"invalid_url"},errorCode:1}}return{result:!0}},renderToolUseMessage:l,renderToolUseProgressMessage:d,renderToolResultMessage:u,async call({url:e,prompt:t},{abortController:r,options:{isNonInteractiveSession:s}}){const n=Date.now(),a=await m(e,r);if("type"in a&&"redirect"===a.type){const o=301===a.statusCode?"Moved Permanently":308===a.statusCode?"Permanent Redirect":307===a.statusCode?"Temporary Redirect":"Found",r=`REDIRECT DETECTED: The URL redirects to a different host.\n\nOriginal URL: ${a.originalUrl}\nRedirect URL: ${a.redirectUrl}\nStatus: ${a.statusCode} ${o}\n\nTo complete your request, I need to fetch content from the redirected URL. Please use WebFetch again with these parameters:\n- url: "${a.redirectUrl}"\n- prompt: "${t}"`;return{data:{bytes:Buffer.byteLength(r),code:a.statusCode,codeText:o,result:r,durationMs:Date.now()-n,url:e}}}const{content:i,bytes:c,code:u,codeText:l,contentType:d,persistedPath:f,persistedSize:b}=a,y=h(e);let T;T=y&&d.includes("text/markdown")&&i.length<g?i:await p(t,i,r.signal,s,y),f&&(T+=`\n\n[Binary content (${d}, ${o(b??c)}) also saved to ${f}]`);return{data:{bytes:c,code:u,codeText:l,result:T,durationMs:Date.now()-n,url:e}}},mapToolResultToToolResultBlockParam:({result:e},t)=>({tool_use_id:t,type:"tool_result",content:e})});function buildSuggestions(e){return[{type:"addRules",destination:"localSettings",rules:[{toolName:i,ruleContent:e}],behavior:"allow"}]}
1
+ import{z as e}from"zod/v4";import{buildTool as t}from"../../Tool.js";import{formatFileSize as o}from"../../utils/format.js";import{lazySchema as r}from"../../utils/lazySchema.js";import{getRuleByContentsForTool as s}from"../../utils/permissions/permissions.js";import{isPreapprovedHost as n}from"./preapproved.js";import{DESCRIPTION as i,WEB_FETCH_TOOL_NAME as a}from"./prompt.js";import{getToolUseSummary as c,renderToolResultMessage as u,renderToolUseMessage as l,renderToolUseProgressMessage as d}from"./UI.js";import{applyPromptToMarkdown as p,getURLMarkdownContent as m,isPreapprovedUrl as h,MAX_MARKDOWN_LENGTH as g}from"./utils.js";const b=r(()=>e.strictObject({url:e.string().url().describe("The URL to fetch content from"),prompt:e.string().describe("The prompt to run on the fetched content")})),f=r(()=>e.object({bytes:e.number().describe("Size of the fetched content in bytes"),code:e.number().describe("HTTP response code"),codeText:e.string().describe("HTTP response code text"),result:e.string().describe("Processed result from applying the prompt to the content"),durationMs:e.number().describe("Time taken to fetch and process the content"),url:e.string().describe("The URL that was fetched")}));export const WebFetchTool=t({name:a,searchHint:"fetch and extract content from a URL",maxResultSizeChars:1e5,shouldDefer:!0,async description(e){const{url:t}=e;try{return`Context quiere obtener contenido de ${new URL(t).hostname}`}catch{return"Context quiere obtener contenido de esta URL"}},userFacingName:()=>"Fetch",getToolUseSummary:c,getActivityDescription(e){const t=c(e);return t?`Fetching ${t}`:"Fetching web page"},get inputSchema(){return b()},get outputSchema(){return f()},isConcurrencySafe:()=>!0,isReadOnly:()=>!0,toAutoClassifierInput:e=>e.prompt?`${e.url}: ${e.prompt}`:e.url,async checkPermissions(e,t){const o=t.getAppState().toolPermissionContext;try{const{url:t}=e,o=new URL(t);if(n(o.hostname,o.pathname))return{behavior:"allow",updatedInput:e,decisionReason:{type:"other",reason:"Preapproved host"}}}catch{}const r=function(e){try{const t=WebFetchTool.inputSchema.safeParse(e);if(!t.success)return`input:${e.toString()}`;const{url:o}=t.data;return`domain:${new URL(o).hostname}`}catch{return`input:${e.toString()}`}}(e),i=s(o,WebFetchTool,"deny").get(r);if(i)return{behavior:"deny",message:`${WebFetchTool.name} denied access to ${r}.`,decisionReason:{type:"rule",rule:i}};const a=s(o,WebFetchTool,"ask").get(r);if(a)return{behavior:"ask",message:`Claude requested permissions to use ${WebFetchTool.name}, but you haven't granted it yet.`,decisionReason:{type:"rule",rule:a},suggestions:buildSuggestions(r)};const c=s(o,WebFetchTool,"allow").get(r);return c?{behavior:"allow",updatedInput:e,decisionReason:{type:"rule",rule:c}}:{behavior:"ask",message:`Claude requested permissions to use ${WebFetchTool.name}, but you haven't granted it yet.`,suggestions:buildSuggestions(r)}},prompt:async e=>`IMPORTANT: WebFetch WILL FAIL for authenticated or private URLs. Before using this tool, check if the URL points to an authenticated service (e.g. Google Docs, Confluence, Jira, GitHub). If so, look for a specialized MCP tool that provides authenticated access.\n${i}`,async validateInput(e){const{url:t}=e;try{new URL(t)}catch{return{result:!1,message:`Error: Invalid URL "${t}". The URL provided could not be parsed.`,meta:{reason:"invalid_url"},errorCode:1}}return{result:!0}},renderToolUseMessage:l,renderToolUseProgressMessage:d,renderToolResultMessage:u,async call({url:e,prompt:t},{abortController:r,options:{isNonInteractiveSession:s}}){const n=Date.now(),i=await m(e,r);if("type"in i&&"redirect"===i.type){const o=301===i.statusCode?"Moved Permanently":308===i.statusCode?"Permanent Redirect":307===i.statusCode?"Temporary Redirect":"Found",r=`REDIRECT DETECTED: The URL redirects to a different host.\n\nOriginal URL: ${i.originalUrl}\nRedirect URL: ${i.redirectUrl}\nStatus: ${i.statusCode} ${o}\n\nTo complete your request, I need to fetch content from the redirected URL. Please use WebFetch again with these parameters:\n- url: "${i.redirectUrl}"\n- prompt: "${t}"`;return{data:{bytes:Buffer.byteLength(r),code:i.statusCode,codeText:o,result:r,durationMs:Date.now()-n,url:e}}}const{content:a,bytes:c,code:u,codeText:l,contentType:d,persistedPath:b,persistedSize:f}=i,y=h(e);let T;T=y&&d.includes("text/markdown")&&a.length<g?a:await p(t,a,r.signal,s,y),b&&(T+=`\n\n[Binary content (${d}, ${o(f??c)}) also saved to ${b}]`);return{data:{bytes:c,code:u,codeText:l,result:T,durationMs:Date.now()-n,url:e}}},mapToolResultToToolResultBlockParam:({result:e},t)=>({tool_use_id:t,type:"tool_result",content:e})});function buildSuggestions(e){return[{type:"addRules",destination:"localSettings",rules:[{toolName:a,ruleContent:e}],behavior:"allow"}]}
@@ -1 +1 @@
1
- import{feature as e}from"../../recovery/bunBundleShim.js";import{logForDebugging as t}from"../debug.js";import{errorMessage as o}from"../errors.js";import{withResolvers as r}from"../withResolvers.js";import{isLockHeldLocally as i,releaseComputerUseLock as s}from"./computerUseLock.js";import{unregisterEscHotkey as u}from"./escHotkey.js";export async function cleanupComputerUseAfterTurn(e){const p=e.getAppState(),m=p.computerUseMcpState?.hiddenDuringTurn;if(m&&m.size>0){const{unhideComputerUseApps:i}=await import("./executor.js"),s=i([...m]).catch(e=>t(`[Computer Use MCP] auto-unhide failed: ${o(e)}`)),u=r(),p=setTimeout(u.resolve,5e3);await Promise.race([s,u.promise]).finally(()=>clearTimeout(p)),e.setAppState(e=>void 0===e.computerUseMcpState?.hiddenDuringTurn?e:{...e,computerUseMcpState:{...e.computerUseMcpState,hiddenDuringTurn:void 0}})}if(i()){try{u()}catch(e){t(`[Computer Use MCP] unregisterEscHotkey failed: ${o(e)}`)}await s()&&e.sendOSNotification?.({message:"Claude is done using your computer",notificationType:"computer_use_exit"})}}
1
+ import{feature as e}from"../../recovery/bunBundleShim.js";import{logForDebugging as t}from"../debug.js";import{errorMessage as r}from"../errors.js";import{withResolvers as o}from"../withResolvers.js";import{isLockHeldLocally as i,releaseComputerUseLock as s}from"./computerUseLock.js";import{unregisterEscHotkey as u}from"./escHotkey.js";export async function cleanupComputerUseAfterTurn(e){const p=e.getAppState(),m=p.computerUseMcpState?.hiddenDuringTurn;if(m&&m.size>0){const{unhideComputerUseApps:i}=await import("./executor.js"),s=i([...m]).catch(e=>t(`[Computer Use MCP] auto-unhide failed: ${r(e)}`)),u=o(),p=setTimeout(u.resolve,5e3);await Promise.race([s,u.promise]).finally(()=>clearTimeout(p)),e.setAppState(e=>void 0===e.computerUseMcpState?.hiddenDuringTurn?e:{...e,computerUseMcpState:{...e.computerUseMcpState,hiddenDuringTurn:void 0}})}if(i()){try{u()}catch(e){t(`[Computer Use MCP] unregisterEscHotkey failed: ${r(e)}`)}await s()&&e.sendOSNotification?.({message:"Context terminó de usar tu computadora",notificationType:"computer_use_exit"})}}
@@ -1 +1 @@
1
- import{feature as e}from"../../recovery/bunBundleShim.js";import{bindSessionContext as t,DEFAULT_GRANT_FLAGS as o}from"@ant/computer-use-mcp";import*as r from"react";import{getSessionId as s}from"../../bootstrap/state.js";import{ComputerUseApproval as p}from"../../components/permissions/ComputerUseApproval/ComputerUseApproval.js";import{logForDebugging as a}from"../debug.js";import{checkComputerUseLock as i,tryAcquireComputerUseLock as n}from"./computerUseLock.js";import{registerEscHotkey as d}from"./escHotkey.js";import{getChicagoCoordinateMode as c}from"./gates.js";import{getComputerUseHostAdapter as l}from"./hostAdapter.js";import{getComputerUseMCPRenderingOverrides as u}from"./toolRendering.js";let m,y;function tuc(){return y}function formatLockHeld(e){return`Computer use is in use by another Claude session (${e.slice(0,8)}…). Wait for that session to finish or run /exit there.`}export function buildSessionContext(){return{getAllowedApps:()=>tuc().getAppState().computerUseMcpState?.allowedApps??[],getGrantFlags:()=>tuc().getAppState().computerUseMcpState?.grantFlags??o,getUserDeniedBundleIds:()=>[],getSelectedDisplayId:()=>tuc().getAppState().computerUseMcpState?.selectedDisplayId,getDisplayPinnedByModel:()=>tuc().getAppState().computerUseMcpState?.displayPinnedByModel??!1,getDisplayResolvedForApps:()=>tuc().getAppState().computerUseMcpState?.displayResolvedForApps,getLastScreenshotDims:()=>{const e=tuc().getAppState().computerUseMcpState?.lastScreenshotDims;return e?{...e,displayId:e.displayId??0,originX:e.originX??0,originY:e.originY??0}:void 0},onPermissionRequest:(e,t)=>async function(e){const t=tuc(),s=t.setToolJSX;if(!s)return{granted:[],denied:[],flags:o};try{return await new Promise((o,a)=>{const i=t.abortController.signal;if(i.aborted)return void a(new Error("Computer Use permission dialog aborted"));const onAbort=()=>{i.removeEventListener("abort",onAbort),a(new Error("Computer Use permission dialog aborted"))};i.addEventListener("abort",onAbort),s({jsx:r.createElement(p,{request:e,onDone:e=>{i.removeEventListener("abort",onAbort),o(e)}}),shouldHidePromptInput:!0})})}finally{s(null)}}(e),onAllowedAppsChanged:(e,t)=>tuc().setAppState(o=>{const r=o.computerUseMcpState,s=r?.allowedApps,p=r?.grantFlags,a=s?.length===e.length&&e.every((e,t)=>s[t]?.bundleId===e.bundleId),i=p?.clipboardRead===t.clipboardRead&&p?.clipboardWrite===t.clipboardWrite&&p?.systemKeyCombos===t.systemKeyCombos;return a&&i?o:{...o,computerUseMcpState:{...r,allowedApps:[...e],grantFlags:t}}}),onAppsHidden:e=>{0!==e.length&&tuc().setAppState(t=>{const o=t.computerUseMcpState,r=o?.hiddenDuringTurn;return r&&e.every(e=>r.has(e))?t:{...t,computerUseMcpState:{...o,hiddenDuringTurn:new Set([...r??[],...e])}}})},onResolvedDisplayUpdated:e=>tuc().setAppState(t=>{const o=t.computerUseMcpState;return o?.selectedDisplayId!==e||o.displayPinnedByModel||void 0!==o.displayResolvedForApps?{...t,computerUseMcpState:{...o,selectedDisplayId:e,displayPinnedByModel:!1,displayResolvedForApps:void 0}}:t}),onDisplayPinned:e=>tuc().setAppState(t=>{const o=t.computerUseMcpState,r=void 0!==e,s=r?o?.displayResolvedForApps:void 0;return o?.selectedDisplayId===e&&o?.displayPinnedByModel===r&&o?.displayResolvedForApps===s?t:{...t,computerUseMcpState:{...o,selectedDisplayId:e,displayPinnedByModel:r,displayResolvedForApps:s}}}),onDisplayResolvedForApps:e=>tuc().setAppState(t=>{const o=t.computerUseMcpState;return o?.displayResolvedForApps===e?t:{...t,computerUseMcpState:{...o,displayResolvedForApps:e}}}),onScreenshotCaptured:e=>tuc().setAppState(t=>{const o=t.computerUseMcpState,r=o?.lastScreenshotDims;return r?.width===e.width&&r?.height===e.height&&r?.displayWidth===e.displayWidth&&r?.displayHeight===e.displayHeight&&r?.displayId===e.displayId&&r?.originX===e.originX&&r?.originY===e.originY?t:{...t,computerUseMcpState:{...o,lastScreenshotDims:e}}}),checkCuLock:async()=>{const e=await i();switch(e.kind){case"free":return{holder:void 0,isSelf:!1};case"held_by_self":return{holder:s(),isSelf:!0};case"blocked":return{holder:e.by,isSelf:!1}}},acquireCuLock:async()=>{const e=await n();if("blocked"===e.kind)throw new Error(formatLockHeld(e.by));if(e.fresh){const e=d(()=>{a("[cu-esc] user escape, aborting turn"),tuc().abortController.abort()});tuc().sendOSNotification?.({message:e?"Claude está usando tu computadora · presiona Esc para detener":"Claude está usando tu computadora · presiona Ctrl+C para detener",notificationType:"computer_use_enter"})}},formatLockHeldMessage:formatLockHeld}}export function getComputerUseMCPToolOverrides(e){return{...u(e),call:async(o,r)=>{y=r;const{dispatch:s}=function(){if(m)return m;const e=buildSessionContext();return m={ctx:e,dispatch:t(l(),c(),e)},m}(),{telemetry:p,...i}=await s(e,o);p?.error_kind&&a(`[Computer Use MCP] ${e} error_kind=${p.error_kind}`);return{data:Array.isArray(i.content)?i.content.map(e=>"image"===e.type?{type:"image",source:{type:"base64",media_type:e.mimeType??"image/jpeg",data:e.data}}:{type:"text",text:"text"===e.type?e.text:""}):i.content}}}}
1
+ import{feature as e}from"../../recovery/bunBundleShim.js";import{bindSessionContext as t,DEFAULT_GRANT_FLAGS as o}from"@ant/computer-use-mcp";import*as r from"react";import{getSessionId as s}from"../../bootstrap/state.js";import{ComputerUseApproval as p}from"../../components/permissions/ComputerUseApproval/ComputerUseApproval.js";import{logForDebugging as i}from"../debug.js";import{checkComputerUseLock as n,tryAcquireComputerUseLock as a}from"./computerUseLock.js";import{registerEscHotkey as d}from"./escHotkey.js";import{getChicagoCoordinateMode as c}from"./gates.js";import{getComputerUseHostAdapter as l}from"./hostAdapter.js";import{getComputerUseMCPRenderingOverrides as u}from"./toolRendering.js";let m,y;function tuc(){return y}function formatLockHeld(e){return`Computer use is in use by another Claude session (${e.slice(0,8)}…). Wait for that session to finish or run /exit there.`}export function buildSessionContext(){return{getAllowedApps:()=>tuc().getAppState().computerUseMcpState?.allowedApps??[],getGrantFlags:()=>tuc().getAppState().computerUseMcpState?.grantFlags??o,getUserDeniedBundleIds:()=>[],getSelectedDisplayId:()=>tuc().getAppState().computerUseMcpState?.selectedDisplayId,getDisplayPinnedByModel:()=>tuc().getAppState().computerUseMcpState?.displayPinnedByModel??!1,getDisplayResolvedForApps:()=>tuc().getAppState().computerUseMcpState?.displayResolvedForApps,getLastScreenshotDims:()=>{const e=tuc().getAppState().computerUseMcpState?.lastScreenshotDims;return e?{...e,displayId:e.displayId??0,originX:e.originX??0,originY:e.originY??0}:void 0},onPermissionRequest:(e,t)=>async function(e){const t=tuc(),s=t.setToolJSX;if(!s)return{granted:[],denied:[],flags:o};try{return await new Promise((o,i)=>{const n=t.abortController.signal;if(n.aborted)return void i(new Error("Computer Use permission dialog aborted"));const onAbort=()=>{n.removeEventListener("abort",onAbort),i(new Error("Computer Use permission dialog aborted"))};n.addEventListener("abort",onAbort),s({jsx:r.createElement(p,{request:e,onDone:e=>{n.removeEventListener("abort",onAbort),o(e)}}),shouldHidePromptInput:!0})})}finally{s(null)}}(e),onAllowedAppsChanged:(e,t)=>tuc().setAppState(o=>{const r=o.computerUseMcpState,s=r?.allowedApps,p=r?.grantFlags,i=s?.length===e.length&&e.every((e,t)=>s[t]?.bundleId===e.bundleId),n=p?.clipboardRead===t.clipboardRead&&p?.clipboardWrite===t.clipboardWrite&&p?.systemKeyCombos===t.systemKeyCombos;return i&&n?o:{...o,computerUseMcpState:{...r,allowedApps:[...e],grantFlags:t}}}),onAppsHidden:e=>{0!==e.length&&tuc().setAppState(t=>{const o=t.computerUseMcpState,r=o?.hiddenDuringTurn;return r&&e.every(e=>r.has(e))?t:{...t,computerUseMcpState:{...o,hiddenDuringTurn:new Set([...r??[],...e])}}})},onResolvedDisplayUpdated:e=>tuc().setAppState(t=>{const o=t.computerUseMcpState;return o?.selectedDisplayId!==e||o.displayPinnedByModel||void 0!==o.displayResolvedForApps?{...t,computerUseMcpState:{...o,selectedDisplayId:e,displayPinnedByModel:!1,displayResolvedForApps:void 0}}:t}),onDisplayPinned:e=>tuc().setAppState(t=>{const o=t.computerUseMcpState,r=void 0!==e,s=r?o?.displayResolvedForApps:void 0;return o?.selectedDisplayId===e&&o?.displayPinnedByModel===r&&o?.displayResolvedForApps===s?t:{...t,computerUseMcpState:{...o,selectedDisplayId:e,displayPinnedByModel:r,displayResolvedForApps:s}}}),onDisplayResolvedForApps:e=>tuc().setAppState(t=>{const o=t.computerUseMcpState;return o?.displayResolvedForApps===e?t:{...t,computerUseMcpState:{...o,displayResolvedForApps:e}}}),onScreenshotCaptured:e=>tuc().setAppState(t=>{const o=t.computerUseMcpState,r=o?.lastScreenshotDims;return r?.width===e.width&&r?.height===e.height&&r?.displayWidth===e.displayWidth&&r?.displayHeight===e.displayHeight&&r?.displayId===e.displayId&&r?.originX===e.originX&&r?.originY===e.originY?t:{...t,computerUseMcpState:{...o,lastScreenshotDims:e}}}),checkCuLock:async()=>{const e=await n();switch(e.kind){case"free":return{holder:void 0,isSelf:!1};case"held_by_self":return{holder:s(),isSelf:!0};case"blocked":return{holder:e.by,isSelf:!1}}},acquireCuLock:async()=>{const e=await a();if("blocked"===e.kind)throw new Error(formatLockHeld(e.by));if(e.fresh){const e=d(()=>{i("[cu-esc] user escape, aborting turn"),tuc().abortController.abort()});tuc().sendOSNotification?.({message:e?"Context está usando tu computadora · presiona Esc para detener":"Context está usando tu computadora · presiona Ctrl+C para detener",notificationType:"computer_use_enter"})}},formatLockHeldMessage:formatLockHeld}}export function getComputerUseMCPToolOverrides(e){return{...u(e),call:async(o,r)=>{y=r;const{dispatch:s}=function(){if(m)return m;const e=buildSessionContext();return m={ctx:e,dispatch:t(l(),c(),e)},m}(),{telemetry:p,...n}=await s(e,o);p?.error_kind&&i(`[Computer Use MCP] ${e} error_kind=${p.error_kind}`);return{data:Array.isArray(n.content)?n.content.map(e=>"image"===e.type?{type:"image",source:{type:"base64",media_type:e.mimeType??"image/jpeg",data:e.data}}:{type:"text",text:"text"===e.type?e.text:""}):n.content}}}}
@@ -1 +1 @@
1
- import{createHash as e}from"crypto";import{diffLines as t}from"diff";import{chmod as i,copyFile as r,link as s,mkdir as n,readFile as a,stat as o,unlink as c}from"fs/promises";import{dirname as l,isAbsolute as u,join as f,relative as d}from"path";import{getIsNonInteractiveSession as p,getOriginalCwd as h,getSessionId as y}from"../bootstrap/state.js";import{logEvent as F}from"../services/analytics/index.js";import{notifyVscodeFileUpdated as k}from"../services/mcp/vscodeSdkMcp.js";import{inspect as m}from"util";import{getGlobalConfig as _}from"./config.js";import{logForDebugging as w}from"./debug.js";import{getClaudeConfigHomeDir as g,isEnvTruthy as E}from"./envUtils.js";import{getErrnoCode as b,isENOENT as v}from"./errors.js";import{pathExists as N}from"./file.js";import{logError as H}from"./log.js";import{recordFileHistorySnapshot as C}from"./sessionStorage.js";export function fileHistoryEnabled(){return p()?(E(process.env.CONTEXT_CODE_ENABLE_SDK_FILE_CHECKPOINTING)||E(process.env.CLAUDE_CODE_ENABLE_SDK_FILE_CHECKPOINTING))&&!E(process.env.CONTEXT_CODE_DISABLE_FILE_CHECKPOINTING)&&!E(process.env.CLAUDE_CODE_DISABLE_FILE_CHECKPOINTING):!1!==_().fileCheckpointingEnabled&&!E(process.env.CONTEXT_CODE_DISABLE_FILE_CHECKPOINTING)&&!E(process.env.CLAUDE_CODE_DISABLE_FILE_CHECKPOINTING)}export async function fileHistoryTrackEdit(e,t,i){if(!fileHistoryEnabled())return;const r=maybeShortenFilePath(t);let s;if(e(e=>(s=e,e)),!s)return;const n=s.snapshots.at(-1);if(!n)return H(new Error("FileHistory: Missing most recent snapshot")),void F("tengu_file_history_track_edit_failed",{});if(n.trackedFileBackups[r])return;let a;try{a=await createBackup(t,1)}catch(e){return H(e),void F("tengu_file_history_track_edit_failed",{})}const o=null===a.backupFileName;e(e=>{try{const s=e.snapshots.at(-1);if(!s||s.trackedFileBackups[r])return e;const n=e.trackedFiles.has(r)?e.trackedFiles:new Set(e.trackedFiles).add(r),c={...s,trackedFileBackups:{...s.trackedFileBackups,[r]:a}},l={...e,snapshots:(()=>{const t=e.snapshots.slice();return t[t.length-1]=c,t})(),trackedFiles:n};return maybeDumpStateForDebug(l),C(i,c,!0).catch(e=>{H(new Error(`FileHistory: Failed to record snapshot: ${e}`))}),F("tengu_file_history_track_edit_success",{isNewFile:o,version:a.version}),w(`FileHistory: Tracked file modification for ${t}`),l}catch(t){return H(t),F("tengu_file_history_track_edit_failed",{}),e}})}export async function fileHistoryMakeSnapshot(e,t){if(!fileHistoryEnabled())return;let i;if(e(e=>(i=e,e)),!i)return;const r={},s=i.snapshots.at(-1);s&&(w(`FileHistory: Making snapshot for message ${t}`),await Promise.all(Array.from(i.trackedFiles,async e=>{try{const t=maybeExpandFilePath(e),i=s.trackedFileBackups[e],n=i?i.version+1:1;let a;try{a=await o(t)}catch(e){if(!v(e))throw e}if(!a)return r[e]={backupFileName:null,version:n,backupTime:new Date},F("tengu_file_history_backup_deleted_file",{version:n}),void w(`FileHistory: Missing tracked file: ${e}`);if(i&&null!==i.backupFileName&&!await checkOriginFileChanged(t,i.backupFileName,a))return void(r[e]=i);r[e]=await createBackup(t,n)}catch(e){H(e),F("tengu_file_history_backup_file_failed",{})}}))),e(e=>{try{const i=e.snapshots.at(-1);if(i)for(const t of e.trackedFiles){if(t in r)continue;const e=i.trackedFileBackups[t];e&&(r[t]=e)}const s=new Date,n={messageId:t,trackedFileBackups:r,timestamp:s},a=[...e.snapshots,n],o={...e,snapshots:a.length>100?a.slice(-100):a,snapshotSequence:(e.snapshotSequence??0)+1};return maybeDumpStateForDebug(o),async function(e,t){const i=e.snapshots.at(-1),r=t.snapshots.at(-1);if(!r)return;for(const e of t.trackedFiles){const t=maybeExpandFilePath(e),s=i?.trackedFileBackups[e],n=r.trackedFileBackups[e];if(s?.backupFileName===n?.backupFileName&&s?.version===n?.version)continue;let a=null;if(s?.backupFileName){const e=resolveBackupPath(s.backupFileName);a=await readFileAsyncOrNull(e)}let o=null;if(n?.backupFileName){const e=resolveBackupPath(n.backupFileName);o=await readFileAsyncOrNull(e)}a!==o&&k(t,a,o)}}(e,o).catch(H),C(t,n,!1).catch(e=>{H(new Error(`FileHistory: Failed to record snapshot: ${e}`))}),w(`FileHistory: Added snapshot for ${t}, tracking ${e.trackedFiles.size} files`),F("tengu_file_history_snapshot_success",{trackedFilesCount:e.trackedFiles.size,snapshotCount:o.snapshots.length}),o}catch(t){return H(t),F("tengu_file_history_snapshot_failed",{}),e}})}export async function fileHistoryRewind(e,t){if(!fileHistoryEnabled())return;let i;if(e(e=>(i=e,e)),!i)return;const r=i.snapshots.findLast(e=>e.messageId===t);if(!r)throw H(new Error(`FileHistory: Snapshot for ${t} not found`)),F("tengu_file_history_rewind_failed",{trackedFilesCount:i.trackedFiles.size,snapshotFound:!1}),new Error("The selected snapshot was not found");try{w(`FileHistory: [Rewind] Rewinding to snapshot for ${t}`);const e=await async function(e,t){const i=[];for(const r of e.trackedFiles)try{const s=maybeExpandFilePath(r),n=t.trackedFileBackups[r],a=n?n.backupFileName:getBackupFileNameFirstVersion(r,e);if(void 0===a){H(new Error("FileHistory: Error finding the backup file to apply")),F("tengu_file_history_rewind_restore_file_failed",{dryRun:!1});continue}if(null===a){try{await c(s),w(`FileHistory: [Rewind] Deleted ${s}`),i.push(s)}catch(e){if(!v(e))throw e}continue}await checkOriginFileChanged(s,a)&&(await restoreBackup(s,a),w(`FileHistory: [Rewind] Restored ${s} from ${a}`),i.push(s))}catch(e){H(e),F("tengu_file_history_rewind_restore_file_failed",{dryRun:!1})}return i}(i,r);w(`FileHistory: [Rewind] Finished rewinding to ${t}`),F("tengu_file_history_rewind_success",{trackedFilesCount:i.trackedFiles.size,filesChangedCount:e.length})}catch(e){throw H(e),F("tengu_file_history_rewind_failed",{trackedFilesCount:i.trackedFiles.size,snapshotFound:!0}),e}}export function fileHistoryCanRestore(e,t){return!!fileHistoryEnabled()&&e.snapshots.some(e=>e.messageId===t)}export async function fileHistoryGetDiffStats(e,i){if(!fileHistoryEnabled())return;const r=e.snapshots.findLast(e=>e.messageId===i);if(!r)return;const s=await Promise.all(Array.from(e.trackedFiles,async i=>{try{const s=maybeExpandFilePath(i),n=r.trackedFileBackups[i],a=n?n.backupFileName:getBackupFileNameFirstVersion(i,e);if(void 0===a)return H(new Error("FileHistory: Error finding the backup file to apply")),F("tengu_file_history_rewind_restore_file_failed",{dryRun:!0}),null;const o=await async function(e,i){const r=[];let s=0,n=0;try{const a=i?resolveBackupPath(i):void 0,[o,c]=await Promise.all([readFileAsyncOrNull(e),a?readFileAsyncOrNull(a):null]);if(null===o&&null===c)return{filesChanged:r,insertions:s,deletions:n};r.push(e);t(o??"",c??"").forEach(e=>{e.added&&(s+=e.count||0),e.removed&&(n+=e.count||0)})}catch(e){H(new Error(`FileHistory: Error generating diffStats: ${e}`))}return{filesChanged:r,insertions:s,deletions:n}}(s,null===a?void 0:a);return o?.insertions||o?.deletions||null===a&&await N(s)?{filePath:s,stats:o}:null}catch(e){return H(e),F("tengu_file_history_rewind_restore_file_failed",{dryRun:!0}),null}})),n=[];let a=0,o=0;for(const e of s)e&&(n.push(e.filePath),a+=e.stats?.insertions||0,o+=e.stats?.deletions||0);return{filesChanged:n,insertions:a,deletions:o}}export async function fileHistoryHasAnyChanges(e,t){if(!fileHistoryEnabled())return!1;const i=e.snapshots.findLast(e=>e.messageId===t);if(!i)return!1;for(const t of e.trackedFiles)try{const r=maybeExpandFilePath(t),s=i.trackedFileBackups[t],n=s?s.backupFileName:getBackupFileNameFirstVersion(t,e);if(void 0===n)continue;if(null===n){if(await N(r))return!0;continue}if(await checkOriginFileChanged(r,n))return!0}catch(e){H(e)}return!1}export async function checkOriginFileChanged(e,t,i){const r=resolveBackupPath(t);let s=i??null;if(!s)try{s=await o(e)}catch(e){if(!v(e))return!0}let n=null;try{n=await o(r)}catch(e){if(!v(e))return!0}return function(e,t,i){if(null===e!=(null===t))return!0;if(null===e||null===t)return!1;if(e.mode!==t.mode||e.size!==t.size)return!0;if(e.mtimeMs<t.mtimeMs)return!1;return i()}(s,n,async()=>{try{const[t,i]=await Promise.all([a(e,"utf-8"),a(r,"utf-8")]);return t!==i}catch{return!0}})}function resolveBackupPath(e,t){const i=g();return f(i,"file-history",t||y(),e)}async function createBackup(t,s){if(null===t)return{backupFileName:null,version:s,backupTime:new Date};const a=function(t,i){return`${e("sha256").update(t).digest("hex").slice(0,16)}@v${i}`}(t,s),c=resolveBackupPath(a);let u;try{u=await o(t)}catch(e){if(v(e))return{backupFileName:null,version:s,backupTime:new Date};throw e}try{await r(t,c)}catch(e){if(!v(e))throw e;await n(l(c),{recursive:!0}),await r(t,c)}return await i(c,u.mode),F("tengu_file_history_backup_file_created",{version:s,fileSize:u.size}),{backupFileName:a,version:s,backupTime:new Date}}async function restoreBackup(e,t){const s=resolveBackupPath(t);let a;try{a=await o(s)}catch(e){if(v(e))return F("tengu_file_history_rewind_restore_file_failed",{}),void H(new Error(`FileHistory: [Rewind] Backup file not found: ${s}`));throw e}try{await r(s,e)}catch(t){if(!v(t))throw t;await n(l(e),{recursive:!0}),await r(s,e)}await i(e,a.mode)}function getBackupFileNameFirstVersion(e,t){for(const i of t.snapshots){const t=i.trackedFileBackups[e];if(void 0!==t&&1===t.version)return t.backupFileName}}function maybeShortenFilePath(e){if(!u(e))return e;const t=h();return e.startsWith(t)?d(t,e):e}function maybeExpandFilePath(e){return u(e)?e:f(h(),e)}export function fileHistoryRestoreStateFromLog(e,t){if(!fileHistoryEnabled())return;const i=[],r=new Set;for(const t of e){const e={};for(const[i,s]of Object.entries(t.trackedFileBackups)){const t=maybeShortenFilePath(i);r.add(t),e[t]=s}i.push({...t,trackedFileBackups:e})}t({snapshots:i,trackedFiles:r,snapshotSequence:i.length})}export async function copyFileHistoryForResume(e){if(!fileHistoryEnabled())return;const t=e.fileHistorySnapshots;if(!t||0===e.messages.length)return;const i=e.messages[e.messages.length-1],a=i?.sessionId;if(!a)return void H(new Error("FileHistory: Failed to copy backups on restore (no previous session id)"));const o=y();if(a!==o)try{const e=f(g(),"file-history",o);await n(e,{recursive:!0});let i=0;await Promise.allSettled(t.map(async t=>{const n=Object.values(t.trackedFileBackups).filter(e=>null!==e.backupFileName);(await Promise.allSettled(n.map(async({backupFileName:t})=>{const i=resolveBackupPath(t,a),n=f(e,t);try{await s(i,n)}catch(e){const s=b(e);if("EEXIST"===s)return;if("ENOENT"===s)throw H(new Error(`FileHistory: Failed to copy backup ${t} on restore (backup file does not exist in ${a})`)),e;H(new Error("FileHistory: Error hard linking backup file from previous session"));try{await r(i,n)}catch(e){throw H(new Error("FileHistory: Error copying over backup from previous session")),e}}w(`FileHistory: Copied backup ${t} from session ${a} to ${o}`)}))).some(e=>"rejected"===e.status)?i++:C(t.messageId,t,!1).catch(e=>{H(new Error("FileHistory: Failed to record copy backup snapshot"))})})),i>0&&F("tengu_file_history_resume_copy_failed",{numSnapshots:t.length,failedSnapshots:i})}catch(e){H(e)}else w(`FileHistory: No need to copy file history for resuming with same session id: ${o}`)}async function readFileAsyncOrNull(e){try{return await a(e,"utf-8")}catch{return null}}const B=!1;function maybeDumpStateForDebug(e){B&&console.error(m(e,!1,5))}
1
+ import{createHash as e}from"crypto";import{diffLines as t}from"diff";import{chmod as i,copyFile as r,link as s,mkdir as n,readFile as a,stat as o,unlink as c}from"fs/promises";import{dirname as l,isAbsolute as u,join as f,relative as d}from"path";import{getIsNonInteractiveSession as p,getOriginalCwd as h,getSessionId as y}from"../bootstrap/state.js";import{logEvent as F}from"../services/analytics/index.js";import{notifyVscodeFileUpdated as k}from"../services/mcp/vscodeSdkMcp.js";import{inspect as m}from"util";import{getGlobalConfig as _}from"./config.js";import{logForDebugging as w}from"./debug.js";import{getClaudeConfigHomeDir as g,isEnvTruthy as E}from"./envUtils.js";import{getErrnoCode as b,isENOENT as v}from"./errors.js";import{pathExists as N}from"./file.js";import{logError as H}from"./log.js";import{recordFileHistorySnapshot as C}from"./sessionStorage.js";export function fileHistoryEnabled(){return p()?(E(process.env.CONTEXT_CODE_ENABLE_SDK_FILE_CHECKPOINTING)||E(process.env.CLAUDE_CODE_ENABLE_SDK_FILE_CHECKPOINTING))&&!E(process.env.CONTEXT_CODE_DISABLE_FILE_CHECKPOINTING)&&!E(process.env.CLAUDE_CODE_DISABLE_FILE_CHECKPOINTING):!1!==_().fileCheckpointingEnabled&&!E(process.env.CONTEXT_CODE_DISABLE_FILE_CHECKPOINTING)&&!E(process.env.CLAUDE_CODE_DISABLE_FILE_CHECKPOINTING)}export async function fileHistoryTrackEdit(e,t,i){if(!fileHistoryEnabled())return;const r=maybeShortenFilePath(t);let s;if(e(e=>(s=e,e)),!s)return;const n=s.snapshots.at(-1);if(!n)return H(new Error("FileHistory: Missing most recent snapshot")),void F("tengu_file_history_track_edit_failed",{});if(n.trackedFileBackups[r])return;let a;try{a=await createBackup(t,1)}catch(e){return H(e),void F("tengu_file_history_track_edit_failed",{})}const o=null===a.backupFileName;e(e=>{try{const s=e.snapshots.at(-1);if(!s||s.trackedFileBackups[r])return e;const n=e.trackedFiles.has(r)?e.trackedFiles:new Set(e.trackedFiles).add(r),c={...s,trackedFileBackups:{...s.trackedFileBackups,[r]:a}},l={...e,snapshots:(()=>{const t=e.snapshots.slice();return t[t.length-1]=c,t})(),trackedFiles:n};return maybeDumpStateForDebug(l),C(i,c,!0).catch(e=>{H(new Error(`FileHistory: Failed to record snapshot: ${e}`))}),F("tengu_file_history_track_edit_success",{isNewFile:o,version:a.version}),w(`FileHistory: Tracked file modification for ${t}`),l}catch(t){return H(t),F("tengu_file_history_track_edit_failed",{}),e}})}export async function fileHistoryMakeSnapshot(e,t){if(!fileHistoryEnabled())return;let i;if(e(e=>(i=e,e)),!i)return;const r={},s=i.snapshots.at(-1);s&&(w(`FileHistory: Making snapshot for message ${t}`),await Promise.all(Array.from(i.trackedFiles,async e=>{try{const t=maybeExpandFilePath(e),i=s.trackedFileBackups[e],n=i?i.version+1:1;let a;try{a=await o(t)}catch(e){if(!v(e))throw e}if(!a)return r[e]={backupFileName:null,version:n,backupTime:new Date},F("tengu_file_history_backup_deleted_file",{version:n}),void w(`FileHistory: Missing tracked file: ${e}`);if(i&&null!==i.backupFileName&&!await checkOriginFileChanged(t,i.backupFileName,a))return void(r[e]=i);r[e]=await createBackup(t,n)}catch(e){H(e),F("tengu_file_history_backup_file_failed",{})}}))),e(e=>{try{const i=e.snapshots.at(-1);if(i)for(const t of e.trackedFiles){if(t in r)continue;const e=i.trackedFileBackups[t];e&&(r[t]=e)}const s=new Date,n={messageId:t,trackedFileBackups:r,timestamp:s},a=[...e.snapshots,n],o={...e,snapshots:a.length>100?a.slice(-100):a,snapshotSequence:(e.snapshotSequence??0)+1};return maybeDumpStateForDebug(o),async function(e,t){const i=e.snapshots.at(-1),r=t.snapshots.at(-1);if(!r)return;for(const e of t.trackedFiles){const t=maybeExpandFilePath(e),s=i?.trackedFileBackups[e],n=r.trackedFileBackups[e];if(s?.backupFileName===n?.backupFileName&&s?.version===n?.version)continue;let a=null;if(s?.backupFileName){const e=resolveBackupPath(s.backupFileName);a=await readFileAsyncOrNull(e)}let o=null;if(n?.backupFileName){const e=resolveBackupPath(n.backupFileName);o=await readFileAsyncOrNull(e)}a!==o&&k(t,a,o)}}(e,o).catch(H),C(t,n,!1).catch(e=>{H(new Error(`FileHistory: Failed to record snapshot: ${e}`))}),w(`FileHistory: Added snapshot for ${t}, tracking ${e.trackedFiles.size} files`),F("tengu_file_history_snapshot_success",{trackedFilesCount:e.trackedFiles.size,snapshotCount:o.snapshots.length}),o}catch(t){return H(t),F("tengu_file_history_snapshot_failed",{}),e}})}export async function fileHistoryRewind(e,t){if(!fileHistoryEnabled())return;let i;if(e(e=>(i=e,e)),!i)return;const r=i.snapshots.findLast(e=>e.messageId===t);if(!r)throw H(new Error(`FileHistory: Snapshot for ${t} not found`)),F("tengu_file_history_rewind_failed",{trackedFilesCount:i.trackedFiles.size,snapshotFound:!1}),new Error("No se encontró la instantánea seleccionada");try{w(`FileHistory: [Rewind] Rewinding to snapshot for ${t}`);const e=await async function(e,t){const i=[];for(const r of e.trackedFiles)try{const s=maybeExpandFilePath(r),n=t.trackedFileBackups[r],a=n?n.backupFileName:getBackupFileNameFirstVersion(r,e);if(void 0===a){H(new Error("FileHistory: Error finding the backup file to apply")),F("tengu_file_history_rewind_restore_file_failed",{dryRun:!1});continue}if(null===a){try{await c(s),w(`FileHistory: [Rewind] Deleted ${s}`),i.push(s)}catch(e){if(!v(e))throw e}continue}await checkOriginFileChanged(s,a)&&(await restoreBackup(s,a),w(`FileHistory: [Rewind] Restored ${s} from ${a}`),i.push(s))}catch(e){H(e),F("tengu_file_history_rewind_restore_file_failed",{dryRun:!1})}return i}(i,r);w(`FileHistory: [Rewind] Finished rewinding to ${t}`),F("tengu_file_history_rewind_success",{trackedFilesCount:i.trackedFiles.size,filesChangedCount:e.length})}catch(e){throw H(e),F("tengu_file_history_rewind_failed",{trackedFilesCount:i.trackedFiles.size,snapshotFound:!0}),e}}export function fileHistoryCanRestore(e,t){return!!fileHistoryEnabled()&&e.snapshots.some(e=>e.messageId===t)}export async function fileHistoryGetDiffStats(e,i){if(!fileHistoryEnabled())return;const r=e.snapshots.findLast(e=>e.messageId===i);if(!r)return;const s=await Promise.all(Array.from(e.trackedFiles,async i=>{try{const s=maybeExpandFilePath(i),n=r.trackedFileBackups[i],a=n?n.backupFileName:getBackupFileNameFirstVersion(i,e);if(void 0===a)return H(new Error("FileHistory: Error finding the backup file to apply")),F("tengu_file_history_rewind_restore_file_failed",{dryRun:!0}),null;const o=await async function(e,i){const r=[];let s=0,n=0;try{const a=i?resolveBackupPath(i):void 0,[o,c]=await Promise.all([readFileAsyncOrNull(e),a?readFileAsyncOrNull(a):null]);if(null===o&&null===c)return{filesChanged:r,insertions:s,deletions:n};r.push(e);t(o??"",c??"").forEach(e=>{e.added&&(s+=e.count||0),e.removed&&(n+=e.count||0)})}catch(e){H(new Error(`FileHistory: Error generating diffStats: ${e}`))}return{filesChanged:r,insertions:s,deletions:n}}(s,null===a?void 0:a);return o?.insertions||o?.deletions||null===a&&await N(s)?{filePath:s,stats:o}:null}catch(e){return H(e),F("tengu_file_history_rewind_restore_file_failed",{dryRun:!0}),null}})),n=[];let a=0,o=0;for(const e of s)e&&(n.push(e.filePath),a+=e.stats?.insertions||0,o+=e.stats?.deletions||0);return{filesChanged:n,insertions:a,deletions:o}}export async function fileHistoryHasAnyChanges(e,t){if(!fileHistoryEnabled())return!1;const i=e.snapshots.findLast(e=>e.messageId===t);if(!i)return!1;for(const t of e.trackedFiles)try{const r=maybeExpandFilePath(t),s=i.trackedFileBackups[t],n=s?s.backupFileName:getBackupFileNameFirstVersion(t,e);if(void 0===n)continue;if(null===n){if(await N(r))return!0;continue}if(await checkOriginFileChanged(r,n))return!0}catch(e){H(e)}return!1}export async function checkOriginFileChanged(e,t,i){const r=resolveBackupPath(t);let s=i??null;if(!s)try{s=await o(e)}catch(e){if(!v(e))return!0}let n=null;try{n=await o(r)}catch(e){if(!v(e))return!0}return function(e,t,i){if(null===e!=(null===t))return!0;if(null===e||null===t)return!1;if(e.mode!==t.mode||e.size!==t.size)return!0;if(e.mtimeMs<t.mtimeMs)return!1;return i()}(s,n,async()=>{try{const[t,i]=await Promise.all([a(e,"utf-8"),a(r,"utf-8")]);return t!==i}catch{return!0}})}function resolveBackupPath(e,t){const i=g();return f(i,"file-history",t||y(),e)}async function createBackup(t,s){if(null===t)return{backupFileName:null,version:s,backupTime:new Date};const a=function(t,i){return`${e("sha256").update(t).digest("hex").slice(0,16)}@v${i}`}(t,s),c=resolveBackupPath(a);let u;try{u=await o(t)}catch(e){if(v(e))return{backupFileName:null,version:s,backupTime:new Date};throw e}try{await r(t,c)}catch(e){if(!v(e))throw e;await n(l(c),{recursive:!0}),await r(t,c)}return await i(c,u.mode),F("tengu_file_history_backup_file_created",{version:s,fileSize:u.size}),{backupFileName:a,version:s,backupTime:new Date}}async function restoreBackup(e,t){const s=resolveBackupPath(t);let a;try{a=await o(s)}catch(e){if(v(e))return F("tengu_file_history_rewind_restore_file_failed",{}),void H(new Error(`FileHistory: [Rewind] Backup file not found: ${s}`));throw e}try{await r(s,e)}catch(t){if(!v(t))throw t;await n(l(e),{recursive:!0}),await r(s,e)}await i(e,a.mode)}function getBackupFileNameFirstVersion(e,t){for(const i of t.snapshots){const t=i.trackedFileBackups[e];if(void 0!==t&&1===t.version)return t.backupFileName}}function maybeShortenFilePath(e){if(!u(e))return e;const t=h();return e.startsWith(t)?d(t,e):e}function maybeExpandFilePath(e){return u(e)?e:f(h(),e)}export function fileHistoryRestoreStateFromLog(e,t){if(!fileHistoryEnabled())return;const i=[],r=new Set;for(const t of e){const e={};for(const[i,s]of Object.entries(t.trackedFileBackups)){const t=maybeShortenFilePath(i);r.add(t),e[t]=s}i.push({...t,trackedFileBackups:e})}t({snapshots:i,trackedFiles:r,snapshotSequence:i.length})}export async function copyFileHistoryForResume(e){if(!fileHistoryEnabled())return;const t=e.fileHistorySnapshots;if(!t||0===e.messages.length)return;const i=e.messages[e.messages.length-1],a=i?.sessionId;if(!a)return void H(new Error("FileHistory: Failed to copy backups on restore (no previous session id)"));const o=y();if(a!==o)try{const e=f(g(),"file-history",o);await n(e,{recursive:!0});let i=0;await Promise.allSettled(t.map(async t=>{const n=Object.values(t.trackedFileBackups).filter(e=>null!==e.backupFileName);(await Promise.allSettled(n.map(async({backupFileName:t})=>{const i=resolveBackupPath(t,a),n=f(e,t);try{await s(i,n)}catch(e){const s=b(e);if("EEXIST"===s)return;if("ENOENT"===s)throw H(new Error(`FileHistory: Failed to copy backup ${t} on restore (backup file does not exist in ${a})`)),e;H(new Error("FileHistory: Error hard linking backup file from previous session"));try{await r(i,n)}catch(e){throw H(new Error("FileHistory: Error copying over backup from previous session")),e}}w(`FileHistory: Copied backup ${t} from session ${a} to ${o}`)}))).some(e=>"rejected"===e.status)?i++:C(t.messageId,t,!1).catch(e=>{H(new Error("FileHistory: Failed to record copy backup snapshot"))})})),i>0&&F("tengu_file_history_resume_copy_failed",{numSnapshots:t.length,failedSnapshots:i})}catch(e){H(e)}else w(`FileHistory: No need to copy file history for resuming with same session id: ${o}`)}async function readFileAsyncOrNull(e){try{return await a(e,"utf-8")}catch{return null}}const B=!1;function maybeDumpStateForDebug(e){B&&console.error(m(e,!1,5))}
@@ -0,0 +1 @@
1
+ import{getLastInteractionTime as e}from"../bootstrap/state.js";import{getGlobalConfig as t,saveGlobalConfig as n}from"./config.js";const s=3e5,r={enabled:!1,timer:null,startedAt:0,lastTickAt:0,recoveryAttempts:0,stdinStalled:!1,pendingRecoveryAt:null,callbacks:{},env:function(){const e=process.platform,t=process.env.MSYSTEM,n=process.env.TERM_PROGRAM,s="win32"===e&&Boolean(t);return{platform:e,msystem:t,termProgram:n,isGitBashOnWindows:s}}()};function debugLog(e){process.env.CONTEXT_HEARTBEAT_DEBUG&&process.stderr.write(`[heartbeat] ${e}\n`)}function tick(){const t=Date.now();r.lastTickAt=t;const n=e(),o=t-n;if(debugLog(`tick: sinceLastInteraction=${Math.round(o/1e3)}s, stalled=${r.stdinStalled}, recoveryAttempts=${r.recoveryAttempts}`),r.stdinStalled&&o<s)return r.stdinStalled=!1,r.pendingRecoveryAt=null,debugLog("stdin recovered"),void r.callbacks.onStdinRecovered?.();!r.stdinStalled&&o>=s?n>0&&(debugLog(`stdin stall detectado tras ${Math.round(o/1e3)}s`),function(){try{if(process.stdin.isTTY&&"function"==typeof process.stdin.setRawMode){const e=process.stdin.isRaw;process.stdin.pause(),process.stdin.setRawMode(!1),process.stdin.setRawMode(e),process.stdin.resume(),debugLog("stdin recovery: setRawMode flip ejecutado")}else debugLog("stdin recovery: no TTY, omitido")}catch(e){debugLog(`stdin recovery error: ${e.message}`)}r.recoveryAttempts+=1,r.pendingRecoveryAt=Date.now()}()):null!==r.pendingRecoveryAt&&!r.stdinStalled&&t-r.pendingRecoveryAt>=3e4&&o>=s&&(debugLog("recuperación fallida, marcando stdin como colgado"),r.stdinStalled=!0,r.pendingRecoveryAt=null,r.callbacks.onStdinStalled?.())}export function startHeartbeat(e={}){r.enabled||(r.enabled=!0,r.startedAt=Date.now(),r.lastTickAt=r.startedAt,r.recoveryAttempts=0,r.stdinStalled=!1,r.pendingRecoveryAt=null,r.callbacks=e,debugLog(`started platform=${r.env.platform} msystem=${r.env.msystem??"-"} term=${r.env.termProgram??"-"}`),function(){if(r.env.isGitBashOnWindows)try{if(t().heartbeatGitBashWarningShown)return;r.callbacks.onGitBashDetected?.(),n(e=>({...e,heartbeatGitBashWarningShown:!0}))}catch(e){debugLog(`error mostrando aviso Git Bash: ${e.message}`)}}(),r.timer=setInterval(tick,15e3),r.timer.unref?.())}export function stopHeartbeat(){r.enabled&&(r.enabled=!1,r.timer&&(clearInterval(r.timer),r.timer=null),debugLog("stopped"))}export function getHeartbeatStatus(){const t=e();return{enabled:r.enabled,startedAt:r.startedAt,lastTickAt:r.lastTickAt,lastStdinEventAt:t>0?t:null,recoveryAttempts:r.recoveryAttempts,stdinStalled:r.stdinStalled,env:r.env}}
@@ -1 +1 @@
1
- import{isEnvTruthy as e}from"../envUtils.js";import{getSecureStorage as r}from"../secureStorage/index.js";import{isProviderBaseUrlCustomized as o}from"./providerBaseUrls.js";import{getProviderOverride as i}from"./providerOverrideContext.js";import{getStoredActiveProviderPreference as n}from"./providerProfilesDb.js";import{listProviderProfiles as t}from"./providerProfiles.js";export function providerPreferenceToApiProvider(e){if(e)return"claude"===e?"firstParty":e}export function isOpenAIProviderConfigured(){return e(process.env.CLAUDE_CODE_USE_OPENAI)||Boolean(process.env.OPENAI_API_KEY)||Boolean(process.env.OPENAI_API_TOKEN)||Boolean(process.env.OPENAI_OAUTH_TOKEN)||function(){try{const e=r().read(),o=Object.entries(e?.providerProfileOauth??{}).some(([e,r])=>e.startsWith("openai/")&&"object"==typeof r&&null!==r&&"string"==typeof r.accessToken&&r.accessToken.trim());return Boolean(o||e?.openAiOauth?.accessToken)}catch{return!1}}()}export function isOpenRouterProviderConfigured(){try{const e=r().read(),o=Object.entries(e?.providerProfileApiKeys??{}).some(([e,r])=>e.startsWith("openrouter/")&&"string"==typeof r&&r.trim());return Boolean(process.env.OPENROUTER_API_KEY||process.env.OPENROUTER_API_TOKEN||e?.providerApiKeys?.openrouter||o)}catch{return Boolean(process.env.OPENROUTER_API_KEY||process.env.OPENROUTER_API_TOKEN)}}export function isOllamaProviderConfigured(){try{const e=n();return Boolean(process.env.OLLAMA_BASE_URL||o("ollama")||t("ollama").length>0||"ollama"===e)}catch{return Boolean(process.env.OLLAMA_BASE_URL)}}export function isOllamaCloudProviderConfigured(){if(isOllamaProviderConfigured())return!0;try{const e=r().read(),i=Object.entries(e?.providerProfileApiKeys??{}).some(([e,r])=>e.startsWith("ollama-cloud/")&&"string"==typeof r&&r.trim()),t=n();return Boolean(process.env.OLLAMA_CLOUD_BASE_URL||process.env.OLLAMA_BASE_URL||process.env.OLLAMA_API_KEY||e?.providerApiKeys?.["ollama-cloud"]||i||o("ollama-cloud")||"ollama-cloud"===t||"ollama"===t)}catch{return Boolean(process.env.OLLAMA_CLOUD_BASE_URL||process.env.OLLAMA_BASE_URL||process.env.OLLAMA_API_KEY)}}export function isGeminiApiProviderConfigured(){try{const e=r().read(),o=Object.entries(e?.providerProfileApiKeys??{}).some(([e,r])=>e.startsWith("gemini-api/")&&"string"==typeof r&&r.trim());return Boolean(process.env.GEMINI_API_KEY||process.env.GOOGLE_API_KEY||e?.providerApiKeys?.["gemini-api"]||o)}catch{return Boolean(process.env.GEMINI_API_KEY||process.env.GOOGLE_API_KEY)}}export function isGeminiGoogleProviderConfigured(){try{const e=n();return Boolean(process.env.GEMINI_OAUTH_TOKEN||process.env.GOOGLE_OAUTH_ACCESS_TOKEN||process.env.GOOGLE_APPLICATION_CREDENTIALS||process.env.GEMINI_GOOGLE_PROJECT_ID||process.env.GOOGLE_CLOUD_PROJECT||process.env.GCLOUD_PROJECT||Object.entries(storage?.providerProfileOauth??{}).some(([e,r])=>e.startsWith("gemini-google/")&&"object"==typeof r&&null!==r&&"string"==typeof r.accessToken&&r.accessToken.trim())||"gemini-google"===e)}catch{return Boolean(process.env.GEMINI_OAUTH_TOKEN||process.env.GOOGLE_OAUTH_ACCESS_TOKEN||process.env.GOOGLE_APPLICATION_CREDENTIALS||process.env.GEMINI_GOOGLE_PROJECT_ID||process.env.GOOGLE_CLOUD_PROJECT||process.env.GCLOUD_PROJECT)}}export function isZAIProviderConfigured(){try{const e=r().read(),o=Object.entries(e?.providerProfileApiKeys??{}).some(([e,r])=>e.startsWith("zai/")&&"string"==typeof r&&r.trim());return Boolean(process.env.ZAI_API_KEY||e?.providerApiKeys?.zai||o)}catch{return Boolean(process.env.ZAI_API_KEY)}}export function isMiniMaxProviderConfigured(){try{const e=r().read(),o=Object.entries(e?.providerProfileApiKeys??{}).some(([e,r])=>e.startsWith("minimax/")&&"string"==typeof r&&r.trim());return Boolean(process.env.MINIMAX_API_KEY||e?.providerApiKeys?.minimax||o)}catch{return Boolean(process.env.MINIMAX_API_KEY)}}export function isNvidiaProviderConfigured(){try{const e=r().read(),o=Object.entries(e?.providerProfileApiKeys??{}).some(([e,r])=>e.startsWith("nvidia/")&&"string"==typeof r&&r.trim());return Boolean(process.env.NVIDIA_API_KEY||e?.providerApiKeys?.nvidia||o)}catch{return Boolean(process.env.NVIDIA_API_KEY)}}export function isDeepSeekProviderConfigured(){try{const e=r().read(),o=Object.entries(e?.providerProfileApiKeys??{}).some(([e,r])=>e.startsWith("deepseek/")&&"string"==typeof r&&r.trim());return Boolean(process.env.DEEPSEEK_API_KEY||e?.providerApiKeys?.deepseek||o)}catch{return Boolean(process.env.DEEPSEEK_API_KEY)}}export function isOpenAICompatibleProvider(e){return"openai"===e||"openrouter"===e||"ollama"===e||"ollama-cloud"===e||"gemini-api"===e||"gemini-google"===e||"zai"===e||"nvidia"===e||"deepseek"===e}export function hasDualProviderSessions(){return(isOpenAIProviderConfigured()||isOpenRouterProviderConfigured()||isOllamaProviderConfigured()||isOllamaCloudProviderConfigured()||isGeminiApiProviderConfigured()||isGeminiGoogleProviderConfigured()||isZAIProviderConfigured()||isMiniMaxProviderConfigured()||isNvidiaProviderConfigured()||isDeepSeekProviderConfigured())&&function(){try{const e=r().read(),o=Object.entries(e?.providerProfileOauth??{}).some(([e,r])=>e.startsWith("claude/")&&"object"==typeof r&&null!==r&&"string"==typeof r.accessToken&&r.accessToken.trim());return Boolean(o)}catch{return!1}}()}export function getAPIProvider(){const r=i();if(r)return r;if(e(process.env.CLAUDE_CODE_USE_BEDROCK))return"bedrock";if(e(process.env.CLAUDE_CODE_USE_VERTEX))return"vertex";if(e(process.env.CLAUDE_CODE_USE_FOUNDRY))return"foundry";try{const e=n();if("claude"===e)return"firstParty";if("openai"===e)return"openai";if("openrouter"===e)return"openrouter";if("ollama"===e)return"ollama";if("ollama-cloud"===e)return"ollama-cloud";if("gemini-api"===e)return"gemini-api";if("gemini-google"===e)return"gemini-google";if("zai"===e)return"zai";if("minimax"===e)return"minimax";if("nvidia"===e)return"nvidia";if("deepseek"===e)return"deepseek"}catch{}const o=isOpenAIProviderConfigured(),t=isOpenRouterProviderConfigured(),s=isOllamaProviderConfigured(),a=isOllamaCloudProviderConfigured(),p=isGeminiApiProviderConfigured(),c=isGeminiGoogleProviderConfigured(),d=isZAIProviderConfigured(),u=isMiniMaxProviderConfigured(),l=isNvidiaProviderConfigured(),v=isDeepSeekProviderConfigured();return o?"openai":t?"openrouter":d?"zai":u?"minimax":l?"nvidia":v?"deepseek":p?"gemini-api":c?"gemini-google":a?"ollama-cloud":s?"ollama":"firstParty"}export function getAPIProviderForStatsig(){return getAPIProvider()}export function isFirstPartyAnthropicBaseUrl(){const e=process.env.ANTHROPIC_BASE_URL;if(!e)return!0;try{const r=new URL(e).host,o=["api.anthropic.com"];return"ant"===process.env.USER_TYPE&&o.push("api-staging.anthropic.com"),o.includes(r)}catch{return!1}}
1
+ import{isEnvTruthy as e}from"../envUtils.js";import{getSecureStorage as r}from"../secureStorage/index.js";import{isProviderBaseUrlCustomized as o}from"./providerBaseUrls.js";import{getProviderOverride as i}from"./providerOverrideContext.js";import{getStoredActiveProviderPreference as n}from"./providerProfilesDb.js";import{listProviderProfiles as t}from"./providerProfiles.js";export function providerPreferenceToApiProvider(e){if(e)return"claude"===e?"firstParty":e}export function isOpenAIProviderConfigured(){return e(process.env.CLAUDE_CODE_USE_OPENAI)||Boolean(process.env.OPENAI_API_KEY)||Boolean(process.env.OPENAI_API_TOKEN)||Boolean(process.env.OPENAI_OAUTH_TOKEN)||function(){try{const e=r().read(),o=Object.entries(e?.providerProfileOauth??{}).some(([e,r])=>e.startsWith("openai/")&&"object"==typeof r&&null!==r&&"string"==typeof r.accessToken&&r.accessToken.trim());return Boolean(o||e?.openAiOauth?.accessToken)}catch{return!1}}()}export function isOpenRouterProviderConfigured(){try{const e=r().read(),o=Object.entries(e?.providerProfileApiKeys??{}).some(([e,r])=>e.startsWith("openrouter/")&&"string"==typeof r&&r.trim());return Boolean(process.env.OPENROUTER_API_KEY||process.env.OPENROUTER_API_TOKEN||e?.providerApiKeys?.openrouter||o)}catch{return Boolean(process.env.OPENROUTER_API_KEY||process.env.OPENROUTER_API_TOKEN)}}export function isOllamaProviderConfigured(){try{const e=n();return Boolean(process.env.OLLAMA_BASE_URL||o("ollama")||t("ollama").length>0||"ollama"===e)}catch{return Boolean(process.env.OLLAMA_BASE_URL)}}export function isOllamaCloudProviderConfigured(){if(isOllamaProviderConfigured())return!0;try{const e=r().read(),i=Object.entries(e?.providerProfileApiKeys??{}).some(([e,r])=>e.startsWith("ollama-cloud/")&&"string"==typeof r&&r.trim()),t=n();return Boolean(process.env.OLLAMA_CLOUD_BASE_URL||process.env.OLLAMA_BASE_URL||process.env.OLLAMA_API_KEY||e?.providerApiKeys?.["ollama-cloud"]||i||o("ollama-cloud")||"ollama-cloud"===t||"ollama"===t)}catch{return Boolean(process.env.OLLAMA_CLOUD_BASE_URL||process.env.OLLAMA_BASE_URL||process.env.OLLAMA_API_KEY)}}export function isGeminiApiProviderConfigured(){try{const e=r().read(),o=Object.entries(e?.providerProfileApiKeys??{}).some(([e,r])=>e.startsWith("gemini-api/")&&"string"==typeof r&&r.trim());return Boolean(process.env.GEMINI_API_KEY||process.env.GOOGLE_API_KEY||e?.providerApiKeys?.["gemini-api"]||o)}catch{return Boolean(process.env.GEMINI_API_KEY||process.env.GOOGLE_API_KEY)}}export function isGeminiGoogleProviderConfigured(){try{const e=n();return Boolean(process.env.GEMINI_OAUTH_TOKEN||process.env.GOOGLE_OAUTH_ACCESS_TOKEN||process.env.GOOGLE_APPLICATION_CREDENTIALS||process.env.GEMINI_GOOGLE_PROJECT_ID||process.env.GOOGLE_CLOUD_PROJECT||process.env.GCLOUD_PROJECT||Object.entries(storage?.providerProfileOauth??{}).some(([e,r])=>e.startsWith("gemini-google/")&&"object"==typeof r&&null!==r&&"string"==typeof r.accessToken&&r.accessToken.trim())||"gemini-google"===e)}catch{return Boolean(process.env.GEMINI_OAUTH_TOKEN||process.env.GOOGLE_OAUTH_ACCESS_TOKEN||process.env.GOOGLE_APPLICATION_CREDENTIALS||process.env.GEMINI_GOOGLE_PROJECT_ID||process.env.GOOGLE_CLOUD_PROJECT||process.env.GCLOUD_PROJECT)}}export function isZAIProviderConfigured(){try{const e=r().read(),o=Object.entries(e?.providerProfileApiKeys??{}).some(([e,r])=>e.startsWith("zai/")&&"string"==typeof r&&r.trim());return Boolean(process.env.ZAI_API_KEY||e?.providerApiKeys?.zai||o)}catch{return Boolean(process.env.ZAI_API_KEY)}}export function isMiniMaxProviderConfigured(){try{const e=r().read(),o=Object.entries(e?.providerProfileApiKeys??{}).some(([e,r])=>e.startsWith("minimax/")&&"string"==typeof r&&r.trim());return Boolean(process.env.MINIMAX_API_KEY||e?.providerApiKeys?.minimax||o)}catch{return Boolean(process.env.MINIMAX_API_KEY)}}export function isNvidiaProviderConfigured(){try{const e=r().read(),o=Object.entries(e?.providerProfileApiKeys??{}).some(([e,r])=>e.startsWith("nvidia/")&&"string"==typeof r&&r.trim());return Boolean(process.env.NVIDIA_API_KEY||e?.providerApiKeys?.nvidia||o)}catch{return Boolean(process.env.NVIDIA_API_KEY)}}export function isDeepSeekProviderConfigured(){try{const e=r().read(),o=Object.entries(e?.providerProfileApiKeys??{}).some(([e,r])=>e.startsWith("deepseek/")&&"string"==typeof r&&r.trim());return Boolean(process.env.DEEPSEEK_API_KEY||e?.providerApiKeys?.deepseek||o)}catch{return Boolean(process.env.DEEPSEEK_API_KEY)}}export function isOpenAICompatibleProvider(e){return"openai"===e||"openrouter"===e||"ollama"===e||"ollama-cloud"===e||"gemini-api"===e||"gemini-google"===e||"zai"===e||"minimax"===e||"nvidia"===e||"deepseek"===e}export function hasDualProviderSessions(){return(isOpenAIProviderConfigured()||isOpenRouterProviderConfigured()||isOllamaProviderConfigured()||isOllamaCloudProviderConfigured()||isGeminiApiProviderConfigured()||isGeminiGoogleProviderConfigured()||isZAIProviderConfigured()||isMiniMaxProviderConfigured()||isNvidiaProviderConfigured()||isDeepSeekProviderConfigured())&&function(){try{const e=r().read(),o=Object.entries(e?.providerProfileOauth??{}).some(([e,r])=>e.startsWith("claude/")&&"object"==typeof r&&null!==r&&"string"==typeof r.accessToken&&r.accessToken.trim());return Boolean(o)}catch{return!1}}()}export function getAPIProvider(){const r=i();if(r)return r;if(e(process.env.CLAUDE_CODE_USE_BEDROCK))return"bedrock";if(e(process.env.CLAUDE_CODE_USE_VERTEX))return"vertex";if(e(process.env.CLAUDE_CODE_USE_FOUNDRY))return"foundry";try{const e=n();if("claude"===e)return"firstParty";if("openai"===e)return"openai";if("openrouter"===e)return"openrouter";if("ollama"===e)return"ollama";if("ollama-cloud"===e)return"ollama-cloud";if("gemini-api"===e)return"gemini-api";if("gemini-google"===e)return"gemini-google";if("zai"===e)return"zai";if("minimax"===e)return"minimax";if("nvidia"===e)return"nvidia";if("deepseek"===e)return"deepseek"}catch{}const o=isOpenAIProviderConfigured(),t=isOpenRouterProviderConfigured(),s=isOllamaProviderConfigured(),a=isOllamaCloudProviderConfigured(),p=isGeminiApiProviderConfigured(),c=isGeminiGoogleProviderConfigured(),d=isZAIProviderConfigured(),u=isMiniMaxProviderConfigured(),l=isNvidiaProviderConfigured(),v=isDeepSeekProviderConfigured();return o?"openai":t?"openrouter":d?"zai":u?"minimax":l?"nvidia":v?"deepseek":p?"gemini-api":c?"gemini-google":a?"ollama-cloud":s?"ollama":"firstParty"}export function getAPIProviderForStatsig(){return getAPIProvider()}export function isFirstPartyAnthropicBaseUrl(){const e=process.env.ANTHROPIC_BASE_URL;if(!e)return!0;try{const r=new URL(e).host,o=["api.anthropic.com"];return"ant"===process.env.USER_TYPE&&o.push("api-staging.anthropic.com"),o.includes(r)}catch{return!1}}