@within-7/minto 0.4.1 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Tool.js +7 -0
- package/dist/Tool.js.map +2 -2
- package/dist/commands/agents/AgentsCommand.js +1 -1
- package/dist/commands/agents/AgentsCommand.js.map +2 -2
- package/dist/commands/agents/constants.js +2 -2
- package/dist/commands/agents/constants.js.map +2 -2
- package/dist/commands/clear.js +4 -3
- package/dist/commands/clear.js.map +2 -2
- package/dist/commands/compact.js +2 -2
- package/dist/commands/compact.js.map +1 -1
- package/dist/commands/context.js +3 -1
- package/dist/commands/context.js.map +2 -2
- package/dist/commands/login.js +128 -0
- package/dist/commands/login.js.map +7 -0
- package/dist/commands/memory.js +33 -82
- package/dist/commands/memory.js.map +2 -2
- package/dist/commands/quit.js +3 -1
- package/dist/commands/quit.js.map +2 -2
- package/dist/commands/resume.js +39 -239
- package/dist/commands/resume.js.map +2 -2
- package/dist/commands/tasks.js +1 -1
- package/dist/commands/tasks.js.map +2 -2
- package/dist/commands/terminalSetup.js +6 -2
- package/dist/commands/terminalSetup.js.map +2 -2
- package/dist/commands.js +2 -0
- package/dist/commands.js.map +2 -2
- package/dist/components/AgentDetailView.js +126 -0
- package/dist/components/AgentDetailView.js.map +7 -0
- package/dist/components/AgentThinkingBlock.js +1 -1
- package/dist/components/AgentThinkingBlock.js.map +2 -2
- package/dist/components/AgentViewBanner.js +22 -0
- package/dist/components/AgentViewBanner.js.map +7 -0
- package/dist/components/HeaderBar.js +1 -1
- package/dist/components/HeaderBar.js.map +2 -2
- package/dist/components/Help.js +8 -1
- package/dist/components/Help.js.map +2 -2
- package/dist/components/HotkeyHelpPanel.js +26 -8
- package/dist/components/HotkeyHelpPanel.js.map +2 -2
- package/dist/components/IdleNotificationBar.js +10 -0
- package/dist/components/IdleNotificationBar.js.map +7 -0
- package/dist/components/ModelSelector/ModelSelector.js +55 -20
- package/dist/components/ModelSelector/ModelSelector.js.map +2 -2
- package/dist/components/PromptInput.js +186 -115
- package/dist/components/PromptInput.js.map +2 -2
- package/dist/components/RewindPanel.js +272 -0
- package/dist/components/RewindPanel.js.map +7 -0
- package/dist/components/Spinner.js +10 -21
- package/dist/components/Spinner.js.map +2 -2
- package/dist/components/StreamingTextPreview.js +29 -0
- package/dist/components/StreamingTextPreview.js.map +7 -0
- package/dist/components/SubagentBlock.js +3 -2
- package/dist/components/SubagentBlock.js.map +2 -2
- package/dist/components/SubagentProgress.js +4 -4
- package/dist/components/SubagentProgress.js.map +2 -2
- package/dist/components/TabbedListView/SearchInput.js +1 -1
- package/dist/components/TabbedListView/SearchInput.js.map +2 -2
- package/dist/components/TabbedListView/TabbedListView.js +87 -41
- package/dist/components/TabbedListView/TabbedListView.js.map +2 -2
- package/dist/components/TaskCard.js +4 -4
- package/dist/components/TaskCard.js.map +2 -2
- package/dist/components/TeamMemberPanel.js +107 -0
- package/dist/components/TeamMemberPanel.js.map +7 -0
- package/dist/components/ThinkingSelector.js +84 -0
- package/dist/components/ThinkingSelector.js.map +7 -0
- package/dist/components/TitledDivider.js +26 -0
- package/dist/components/TitledDivider.js.map +7 -0
- package/dist/components/TodoPanel.js +31 -30
- package/dist/components/TodoPanel.js.map +2 -2
- package/dist/components/TokenWarning.js +28 -7
- package/dist/components/TokenWarning.js.map +2 -2
- package/dist/components/messages/AssistantTextMessage.js +5 -2
- package/dist/components/messages/AssistantTextMessage.js.map +2 -2
- package/dist/components/messages/AssistantToolUseMessage.js +9 -1
- package/dist/components/messages/AssistantToolUseMessage.js.map +2 -2
- package/dist/components/messages/DefaultToolResultFallback.js +11 -0
- package/dist/components/messages/DefaultToolResultFallback.js.map +7 -0
- package/dist/components/messages/ParallelTasksGroupView.js +14 -6
- package/dist/components/messages/ParallelTasksGroupView.js.map +2 -2
- package/dist/components/messages/TaskInModuleView.js +27 -27
- package/dist/components/messages/TaskInModuleView.js.map +2 -2
- package/dist/components/messages/UserGuidanceMessage.js +26 -0
- package/dist/components/messages/UserGuidanceMessage.js.map +7 -0
- package/dist/components/messages/UserPromptMessage.js +2 -1
- package/dist/components/messages/UserPromptMessage.js.map +2 -2
- package/dist/components/messages/UserTeamNotificationMessage.js +91 -0
- package/dist/components/messages/UserTeamNotificationMessage.js.map +7 -0
- package/dist/components/messages/UserTextMessage.js +8 -0
- package/dist/components/messages/UserTextMessage.js.map +2 -2
- package/dist/components/messages/UserToolResultMessage/UserToolRejectMessage.js +4 -2
- package/dist/components/messages/UserToolResultMessage/UserToolRejectMessage.js.map +2 -2
- package/dist/components/messages/UserToolResultMessage/UserToolResultMessage.js +18 -1
- package/dist/components/messages/UserToolResultMessage/UserToolResultMessage.js.map +2 -2
- package/dist/components/messages/UserToolResultMessage/UserToolSuccessMessage.js +12 -1
- package/dist/components/messages/UserToolResultMessage/UserToolSuccessMessage.js.map +2 -2
- package/dist/components/permissions/PermissionRequest.js +4 -0
- package/dist/components/permissions/PermissionRequest.js.map +2 -2
- package/dist/components/permissions/PlanApprovalRequest.js +164 -0
- package/dist/components/permissions/PlanApprovalRequest.js.map +7 -0
- package/dist/constants/agentTeams.js +17 -0
- package/dist/constants/agentTeams.js.map +7 -0
- package/dist/constants/macros.js +2 -1
- package/dist/constants/macros.js.map +2 -2
- package/dist/constants/prompts/agentPrompt.js +1 -0
- package/dist/constants/prompts/agentPrompt.js.map +2 -2
- package/dist/constants/prompts/autoMemory.js +39 -0
- package/dist/constants/prompts/autoMemory.js.map +7 -0
- package/dist/constants/prompts/codeConventions.js +1 -13
- package/dist/constants/prompts/codeConventions.js.map +2 -2
- package/dist/constants/prompts/doingTasks.js +21 -2
- package/dist/constants/prompts/doingTasks.js.map +2 -2
- package/dist/constants/prompts/envInfo.js +6 -7
- package/dist/constants/prompts/envInfo.js.map +2 -2
- package/dist/constants/prompts/index.js +27 -5
- package/dist/constants/prompts/index.js.map +2 -2
- package/dist/constants/prompts/taskManagement.js +2 -43
- package/dist/constants/prompts/taskManagement.js.map +2 -2
- package/dist/constants/prompts/teamOverlays.js +50 -0
- package/dist/constants/prompts/teamOverlays.js.map +7 -0
- package/dist/constants/prompts/toneAndStyle.js +4 -29
- package/dist/constants/prompts/toneAndStyle.js.map +2 -2
- package/dist/constants/prompts/toolUsagePolicy.js +7 -22
- package/dist/constants/prompts/toolUsagePolicy.js.map +2 -2
- package/dist/constants/toolInputExamples.js +2 -2
- package/dist/constants/toolInputExamples.js.map +2 -2
- package/dist/context.js +39 -6
- package/dist/context.js.map +2 -2
- package/dist/core/backupManager.js +1 -1
- package/dist/core/backupManager.js.map +2 -2
- package/dist/core/permissions/rules/planModeRule.js +1 -1
- package/dist/core/permissions/rules/planModeRule.js.map +1 -1
- package/dist/core/permissions/rules/safeModeRule.js +1 -1
- package/dist/core/permissions/rules/safeModeRule.js.map +1 -1
- package/dist/engine/AgentEngine.js +902 -0
- package/dist/engine/AgentEngine.js.map +7 -0
- package/dist/engine/EngineRegistry.js +89 -0
- package/dist/engine/EngineRegistry.js.map +7 -0
- package/dist/engine/foregroundAdapter.js +191 -0
- package/dist/engine/foregroundAdapter.js.map +7 -0
- package/dist/engine/index.js +15 -0
- package/dist/engine/index.js.map +7 -0
- package/dist/engine/types.js +1 -0
- package/dist/engine/types.js.map +7 -0
- package/dist/entrypoints/cli.js +410 -79
- package/dist/entrypoints/cli.js.map +3 -3
- package/dist/hooks/useAgentEngine.js +129 -0
- package/dist/hooks/useAgentEngine.js.map +7 -0
- package/dist/hooks/useAgentTokenStats.js +0 -16
- package/dist/hooks/useAgentTokenStats.js.map +2 -2
- package/dist/hooks/useCanUseTool.js +47 -2
- package/dist/hooks/useCanUseTool.js.map +2 -2
- package/dist/hooks/useDeferredLoading.js +4 -1
- package/dist/hooks/useDeferredLoading.js.map +2 -2
- package/dist/hooks/useIdleNotifications.js +66 -0
- package/dist/hooks/useIdleNotifications.js.map +7 -0
- package/dist/hooks/useSessionTracking.js +9 -7
- package/dist/hooks/useSessionTracking.js.map +2 -2
- package/dist/hooks/useTeamMembers.js +51 -0
- package/dist/hooks/useTeamMembers.js.map +7 -0
- package/dist/i18n/locales/en.js +77 -12
- package/dist/i18n/locales/en.js.map +2 -2
- package/dist/i18n/locales/zh-CN.js +77 -12
- package/dist/i18n/locales/zh-CN.js.map +2 -2
- package/dist/i18n/types.js.map +1 -1
- package/dist/messages.js.map +2 -2
- package/dist/permissions.js +113 -7
- package/dist/permissions.js.map +2 -2
- package/dist/query.js +135 -37
- package/dist/query.js.map +2 -2
- package/dist/screens/REPL.js +504 -361
- package/dist/screens/REPL.js.map +3 -3
- package/dist/screens/ResumeConversation.js +199 -14
- package/dist/screens/ResumeConversation.js.map +2 -2
- package/dist/services/adapters/base.js.map +1 -1
- package/dist/services/agentTeams/backends/headless.js +108 -0
- package/dist/services/agentTeams/backends/headless.js.map +7 -0
- package/dist/services/agentTeams/backends/inProcess.js +102 -0
- package/dist/services/agentTeams/backends/inProcess.js.map +7 -0
- package/dist/services/agentTeams/backends/resolver.js +18 -0
- package/dist/services/agentTeams/backends/resolver.js.map +7 -0
- package/dist/services/agentTeams/backends/tmux.js +168 -0
- package/dist/services/agentTeams/backends/tmux.js.map +7 -0
- package/dist/services/agentTeams/backends/types.js +1 -0
- package/dist/services/agentTeams/backends/types.js.map +7 -0
- package/dist/services/agentTeams/heartbeat.js +88 -0
- package/dist/services/agentTeams/heartbeat.js.map +7 -0
- package/dist/services/agentTeams/index.js +42 -2
- package/dist/services/agentTeams/index.js.map +2 -2
- package/dist/services/agentTeams/injectionChannel.js +105 -0
- package/dist/services/agentTeams/injectionChannel.js.map +7 -0
- package/dist/services/agentTeams/mailbox.js +410 -30
- package/dist/services/agentTeams/mailbox.js.map +2 -2
- package/dist/services/agentTeams/messageFormatter.js +80 -0
- package/dist/services/agentTeams/messageFormatter.js.map +7 -0
- package/dist/services/agentTeams/permissionDelegation.js +71 -0
- package/dist/services/agentTeams/permissionDelegation.js.map +7 -0
- package/dist/services/agentTeams/teamEvents.js +45 -0
- package/dist/services/agentTeams/teamEvents.js.map +7 -0
- package/dist/services/agentTeams/teamManager.js +251 -34
- package/dist/services/agentTeams/teamManager.js.map +2 -2
- package/dist/services/agentTeams/teamTaskStore.js +290 -61
- package/dist/services/agentTeams/teamTaskStore.js.map +2 -2
- package/dist/services/agentTeams/teammateSpawner.js +99 -18
- package/dist/services/agentTeams/teammateSpawner.js.map +2 -2
- package/dist/services/hookExecutor.js +51 -8
- package/dist/services/hookExecutor.js.map +2 -2
- package/dist/services/llm/anthropicProvider.js +56 -59
- package/dist/services/llm/anthropicProvider.js.map +2 -2
- package/dist/services/llm/dispatch.js +24 -5
- package/dist/services/llm/dispatch.js.map +2 -2
- package/dist/services/llm/openaiProvider.js +115 -136
- package/dist/services/llm/openaiProvider.js.map +3 -3
- package/dist/services/llm/types.js +89 -15
- package/dist/services/llm/types.js.map +2 -2
- package/dist/services/mcpClient.js +80 -4
- package/dist/services/mcpClient.js.map +2 -2
- package/dist/services/mintoAuth.js +299 -0
- package/dist/services/mintoAuth.js.map +7 -0
- package/dist/services/oauth.js +3 -3
- package/dist/services/oauth.js.map +2 -2
- package/dist/services/openai.js +91 -20
- package/dist/services/openai.js.map +2 -2
- package/dist/services/plugins/pluginRuntime.js +11 -5
- package/dist/services/plugins/pluginRuntime.js.map +2 -2
- package/dist/services/plugins/pluginValidation.js +4 -2
- package/dist/services/plugins/pluginValidation.js.map +2 -2
- package/dist/services/sandbox/sandboxController.js +11 -3
- package/dist/services/sandbox/sandboxController.js.map +2 -2
- package/dist/services/sessionMemoryInjector.js +77 -0
- package/dist/services/sessionMemoryInjector.js.map +7 -0
- package/dist/services/systemReminder.js +130 -8
- package/dist/services/systemReminder.js.map +2 -2
- package/dist/services/taskStore.js +199 -8
- package/dist/services/taskStore.js.map +3 -3
- package/dist/services/topicDetector.js +169 -0
- package/dist/services/topicDetector.js.map +7 -0
- package/dist/tools/AskExpertModelTool/AskExpertModelTool.js +0 -13
- package/dist/tools/AskExpertModelTool/AskExpertModelTool.js.map +2 -2
- package/dist/tools/BashTool/BashTool.js +51 -28
- package/dist/tools/BashTool/BashTool.js.map +2 -2
- package/dist/tools/BashTool/prompt.js +95 -118
- package/dist/tools/BashTool/prompt.js.map +2 -2
- package/dist/tools/BashTool/utils.js +39 -1
- package/dist/tools/BashTool/utils.js.map +2 -2
- package/dist/tools/EnterWorktreeTool/EnterWorktreeTool.js +121 -0
- package/dist/tools/EnterWorktreeTool/EnterWorktreeTool.js.map +7 -0
- package/dist/tools/EnterWorktreeTool/prompt.js +22 -0
- package/dist/tools/EnterWorktreeTool/prompt.js.map +7 -0
- package/dist/tools/FileEditTool/FileEditTool.js +9 -4
- package/dist/tools/FileEditTool/FileEditTool.js.map +2 -2
- package/dist/tools/FileEditTool/prompt.js +3 -7
- package/dist/tools/FileEditTool/prompt.js.map +2 -2
- package/dist/tools/FileReadTool/FileReadTool.js +125 -3
- package/dist/tools/FileReadTool/FileReadTool.js.map +2 -2
- package/dist/tools/FileReadTool/prompt.js +1 -2
- package/dist/tools/FileReadTool/prompt.js.map +2 -2
- package/dist/tools/FileWriteTool/prompt.js +3 -5
- package/dist/tools/FileWriteTool/prompt.js.map +2 -2
- package/dist/tools/GlobTool/GlobTool.js +3 -2
- package/dist/tools/GlobTool/GlobTool.js.map +2 -2
- package/dist/tools/GrepTool/GrepTool.js +16 -5
- package/dist/tools/GrepTool/GrepTool.js.map +2 -2
- package/dist/tools/ListMcpResourcesTool/ListMcpResourcesTool.js.map +2 -2
- package/dist/tools/MCPSearchTool/MCPSearchTool.js +172 -0
- package/dist/tools/MCPSearchTool/MCPSearchTool.js.map +7 -0
- package/dist/tools/MCPSearchTool/prompt.js +77 -0
- package/dist/tools/MCPSearchTool/prompt.js.map +7 -0
- package/dist/tools/MultiEditTool/prompt.js +4 -7
- package/dist/tools/MultiEditTool/prompt.js.map +2 -2
- package/dist/tools/PlanModeTool/EnterPlanModeTool.js +12 -8
- package/dist/tools/PlanModeTool/EnterPlanModeTool.js.map +2 -2
- package/dist/tools/PlanModeTool/ExitPlanModeTool.js +54 -1
- package/dist/tools/PlanModeTool/ExitPlanModeTool.js.map +2 -2
- package/dist/tools/PlanModeTool/prompt.js +23 -74
- package/dist/tools/PlanModeTool/prompt.js.map +2 -2
- package/dist/tools/SendMessageTool/SendMessageTool.js +341 -0
- package/dist/tools/SendMessageTool/SendMessageTool.js.map +7 -0
- package/dist/tools/SendMessageTool/prompt.js +44 -0
- package/dist/tools/SendMessageTool/prompt.js.map +7 -0
- package/dist/tools/TaskCreateTool/prompt.js +15 -4
- package/dist/tools/TaskCreateTool/prompt.js.map +2 -2
- package/dist/tools/TaskListTool/prompt.js +18 -3
- package/dist/tools/TaskListTool/prompt.js.map +2 -2
- package/dist/tools/TaskOutputTool/prompt.js +4 -3
- package/dist/tools/TaskOutputTool/prompt.js.map +2 -2
- package/dist/tools/TaskTool/TaskTool.js +762 -98
- package/dist/tools/TaskTool/TaskTool.js.map +3 -3
- package/dist/tools/TaskTool/constants.js +8 -2
- package/dist/tools/TaskTool/constants.js.map +2 -2
- package/dist/tools/TaskTool/prompt.js +74 -70
- package/dist/tools/TaskTool/prompt.js.map +2 -2
- package/dist/tools/TaskUpdateTool/TaskUpdateTool.js +15 -1
- package/dist/tools/TaskUpdateTool/TaskUpdateTool.js.map +2 -2
- package/dist/tools/TeamCreateTool/TeamCreateTool.js +129 -0
- package/dist/tools/TeamCreateTool/TeamCreateTool.js.map +7 -0
- package/dist/tools/TeamCreateTool/prompt.js +58 -0
- package/dist/tools/TeamCreateTool/prompt.js.map +7 -0
- package/dist/tools/TeamDeleteTool/TeamDeleteTool.js +151 -0
- package/dist/tools/TeamDeleteTool/TeamDeleteTool.js.map +7 -0
- package/dist/tools/TeamDeleteTool/prompt.js +16 -0
- package/dist/tools/TeamDeleteTool/prompt.js.map +7 -0
- package/dist/tools/URLFetcherTool/URLFetcherTool.js +106 -15
- package/dist/tools/URLFetcherTool/URLFetcherTool.js.map +2 -2
- package/dist/tools/URLFetcherTool/prompt.js +3 -2
- package/dist/tools/URLFetcherTool/prompt.js.map +2 -2
- package/dist/tools/WebSearchTool/WebSearchTool.js +2 -1
- package/dist/tools/WebSearchTool/WebSearchTool.js.map +2 -2
- package/dist/tools/WebSearchTool/prompt.js +5 -4
- package/dist/tools/WebSearchTool/prompt.js.map +2 -2
- package/dist/tools.js +100 -20
- package/dist/tools.js.map +2 -2
- package/dist/types/PermissionMode.js +35 -6
- package/dist/types/PermissionMode.js.map +2 -2
- package/dist/types/hooks.js +2 -0
- package/dist/types/hooks.js.map +2 -2
- package/dist/types/plugin.js +2 -0
- package/dist/types/plugin.js.map +3 -3
- package/dist/utils/CircuitBreaker.js +15 -9
- package/dist/utils/CircuitBreaker.js.map +2 -2
- package/dist/utils/agentLoader.js +249 -112
- package/dist/utils/agentLoader.js.map +2 -2
- package/dist/utils/animationManager.js +40 -3
- package/dist/utils/animationManager.js.map +2 -2
- package/dist/utils/ask.js +7 -6
- package/dist/utils/ask.js.map +2 -2
- package/dist/utils/atomicWrite.js +23 -0
- package/dist/utils/atomicWrite.js.map +7 -0
- package/dist/utils/autoCompactCore.js +73 -56
- package/dist/utils/autoCompactCore.js.map +2 -2
- package/dist/utils/autoMemoryPaths.js +89 -0
- package/dist/utils/autoMemoryPaths.js.map +7 -0
- package/dist/utils/config.js +63 -38
- package/dist/utils/config.js.map +2 -2
- package/dist/utils/configSchema.js +13 -8
- package/dist/utils/configSchema.js.map +2 -2
- package/dist/utils/credentials/index.js +14 -0
- package/dist/utils/credentials/index.js.map +2 -2
- package/dist/utils/dualPath.js +24 -0
- package/dist/utils/dualPath.js.map +7 -0
- package/dist/utils/exit.js +66 -7
- package/dist/utils/exit.js.map +2 -2
- package/dist/utils/externalEditor.js +155 -0
- package/dist/utils/externalEditor.js.map +7 -0
- package/dist/utils/fileLock.js +67 -0
- package/dist/utils/fileLock.js.map +7 -0
- package/dist/utils/format.js +24 -14
- package/dist/utils/format.js.map +2 -2
- package/dist/utils/globalErrorHandler.js +5 -96
- package/dist/utils/globalErrorHandler.js.map +3 -3
- package/dist/utils/groupHandlers/parallelTasksHandler.js +5 -3
- package/dist/utils/groupHandlers/parallelTasksHandler.js.map +2 -2
- package/dist/utils/groupHandlers/taskHandler.js +2 -2
- package/dist/utils/groupHandlers/taskHandler.js.map +2 -2
- package/dist/utils/hookManager.js +64 -6
- package/dist/utils/hookManager.js.map +2 -2
- package/dist/utils/log.js +6 -2
- package/dist/utils/log.js.map +2 -2
- package/dist/utils/markdown.js +237 -19
- package/dist/utils/markdown.js.map +2 -2
- package/dist/utils/messageContextManager.js +18 -5
- package/dist/utils/messageContextManager.js.map +2 -2
- package/dist/utils/messageGroupManager.js +1 -1
- package/dist/utils/messageGroupManager.js.map +2 -2
- package/dist/utils/messages.js +104 -46
- package/dist/utils/messages.js.map +2 -2
- package/dist/utils/model.js +2 -2
- package/dist/utils/model.js.map +2 -2
- package/dist/utils/pasteCache.js +8 -4
- package/dist/utils/pasteCache.js.map +2 -2
- package/dist/utils/pluginLoader.js +18 -0
- package/dist/utils/pluginLoader.js.map +2 -2
- package/dist/utils/secureKeyStorage.js +36 -7
- package/dist/utils/secureKeyStorage.js.map +2 -2
- package/dist/utils/simpleMode.js +7 -0
- package/dist/utils/simpleMode.js.map +7 -0
- package/dist/utils/streamingState.js +11 -1
- package/dist/utils/streamingState.js.map +2 -2
- package/dist/utils/taskDisplayUtils.js +2 -1
- package/dist/utils/taskDisplayUtils.js.map +2 -2
- package/dist/utils/teamConfig.js +2 -2
- package/dist/utils/teamConfig.js.map +2 -2
- package/dist/utils/thinking.js +6 -2
- package/dist/utils/thinking.js.map +3 -3
- package/dist/utils/tokenProgress.js +55 -0
- package/dist/utils/tokenProgress.js.map +7 -0
- package/dist/utils/toolRiskClassification.js +26 -17
- package/dist/utils/toolRiskClassification.js.map +2 -2
- package/dist/utils/tooling/toolError.js +12 -0
- package/dist/utils/tooling/toolError.js.map +7 -0
- package/dist/version.js +2 -2
- package/dist/version.js.map +1 -1
- package/package.json +10 -8
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { Box, Text } from "ink";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { rmSync, existsSync } from "fs";
|
|
5
|
+
import { execFileSync } from "child_process";
|
|
6
|
+
import { join } from "path";
|
|
7
|
+
import { homedir } from "os";
|
|
8
|
+
import { FallbackToolUseRejectedMessage } from "../../components/FallbackToolUseRejectedMessage.js";
|
|
9
|
+
import { createToolErrorResult } from "../../utils/tooling/toolError.js";
|
|
10
|
+
import {
|
|
11
|
+
isAgentTeamsEnabled,
|
|
12
|
+
getActiveTeams,
|
|
13
|
+
disbandTeam
|
|
14
|
+
} from "../../services/agentTeams/index.js";
|
|
15
|
+
import { DESCRIPTION, PROMPT } from "./prompt.js";
|
|
16
|
+
import { getTheme } from "../../utils/theme.js";
|
|
17
|
+
import { debug as debugLogger } from "../../utils/debugLogger.js";
|
|
18
|
+
const inputSchema = z.strictObject({});
|
|
19
|
+
const TeamDeleteTool = {
|
|
20
|
+
name: "TeamDelete",
|
|
21
|
+
async description() {
|
|
22
|
+
return DESCRIPTION;
|
|
23
|
+
},
|
|
24
|
+
async prompt() {
|
|
25
|
+
return PROMPT;
|
|
26
|
+
},
|
|
27
|
+
inputSchema,
|
|
28
|
+
userFacingName() {
|
|
29
|
+
return "Delete Team";
|
|
30
|
+
},
|
|
31
|
+
async isEnabled() {
|
|
32
|
+
return isAgentTeamsEnabled();
|
|
33
|
+
},
|
|
34
|
+
isReadOnly() {
|
|
35
|
+
return false;
|
|
36
|
+
},
|
|
37
|
+
isConcurrencySafe() {
|
|
38
|
+
return false;
|
|
39
|
+
},
|
|
40
|
+
needsPermissions() {
|
|
41
|
+
return false;
|
|
42
|
+
},
|
|
43
|
+
renderToolUseMessage() {
|
|
44
|
+
return null;
|
|
45
|
+
},
|
|
46
|
+
renderToolUseRejectedMessage() {
|
|
47
|
+
return /* @__PURE__ */ React.createElement(FallbackToolUseRejectedMessage, null);
|
|
48
|
+
},
|
|
49
|
+
renderToolResultMessage(output) {
|
|
50
|
+
if (!output) {
|
|
51
|
+
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Text, null, "\xA0\xA0\u23BF \xA0"), /* @__PURE__ */ React.createElement(Text, null, "Team deleted"));
|
|
52
|
+
}
|
|
53
|
+
const color = output.success ? getTheme().success : getTheme().error;
|
|
54
|
+
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Text, null, "\xA0\xA0\u23BF \xA0"), /* @__PURE__ */ React.createElement(Text, { color }, output.message));
|
|
55
|
+
},
|
|
56
|
+
renderResultForAssistant(result) {
|
|
57
|
+
return JSON.stringify(result);
|
|
58
|
+
},
|
|
59
|
+
async *call() {
|
|
60
|
+
try {
|
|
61
|
+
const teams = getActiveTeams();
|
|
62
|
+
if (teams.length === 0) {
|
|
63
|
+
yield {
|
|
64
|
+
type: "result",
|
|
65
|
+
data: { success: false, message: "No active team to delete" },
|
|
66
|
+
resultForAssistant: JSON.stringify({
|
|
67
|
+
success: false,
|
|
68
|
+
message: "No active team to delete."
|
|
69
|
+
})
|
|
70
|
+
};
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const team = teams[0];
|
|
74
|
+
const workingMembers = team.members.filter(
|
|
75
|
+
(m) => m.status === "working" && m.name !== "team-lead"
|
|
76
|
+
);
|
|
77
|
+
if (workingMembers.length > 0) {
|
|
78
|
+
const names = workingMembers.map((m) => m.name).join(", ");
|
|
79
|
+
yield {
|
|
80
|
+
type: "result",
|
|
81
|
+
data: {
|
|
82
|
+
success: false,
|
|
83
|
+
message: `TeamDelete failed: team still has ${workingMembers.length} working member(s): ${names}. Send shutdown_request first, or wait for them to finish, then call TeamDelete.`
|
|
84
|
+
},
|
|
85
|
+
resultForAssistant: JSON.stringify({
|
|
86
|
+
success: false,
|
|
87
|
+
message: `TeamDelete blocked by working members: ${names}. Send shutdown_request or wait for them to finish.`
|
|
88
|
+
})
|
|
89
|
+
};
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
for (const member of team.members) {
|
|
93
|
+
if (member.worktreePath) {
|
|
94
|
+
try {
|
|
95
|
+
if (existsSync(member.worktreePath)) {
|
|
96
|
+
execFileSync(
|
|
97
|
+
"git",
|
|
98
|
+
["worktree", "remove", member.worktreePath, "--force"],
|
|
99
|
+
{
|
|
100
|
+
stdio: "pipe",
|
|
101
|
+
timeout: 1e4
|
|
102
|
+
}
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
} catch {
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
for (const member of team.members) {
|
|
110
|
+
if (member.tmuxPaneId && member.tmuxPaneId !== "in-process" && member.tmuxPaneId !== "unknown") {
|
|
111
|
+
try {
|
|
112
|
+
execFileSync("tmux", ["kill-pane", "-t", member.tmuxPaneId], {
|
|
113
|
+
stdio: "pipe",
|
|
114
|
+
timeout: 5e3
|
|
115
|
+
});
|
|
116
|
+
} catch {
|
|
117
|
+
debugLogger.info("TEAM_DELETE_PANE_CLEANUP_SKIP", {
|
|
118
|
+
memberId: member.id,
|
|
119
|
+
paneId: member.tmuxPaneId
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
disbandTeam(team.name);
|
|
125
|
+
const teamsDir = join(homedir(), ".minto", "teams", team.name);
|
|
126
|
+
const tasksDir = join(homedir(), ".minto", "tasks", team.name);
|
|
127
|
+
if (existsSync(teamsDir)) {
|
|
128
|
+
rmSync(teamsDir, { recursive: true, force: true });
|
|
129
|
+
}
|
|
130
|
+
if (existsSync(tasksDir)) {
|
|
131
|
+
rmSync(tasksDir, { recursive: true, force: true });
|
|
132
|
+
}
|
|
133
|
+
const result = {
|
|
134
|
+
success: true,
|
|
135
|
+
message: `Team "${team.name}" disbanded`,
|
|
136
|
+
team_name: team.name
|
|
137
|
+
};
|
|
138
|
+
yield {
|
|
139
|
+
type: "result",
|
|
140
|
+
data: result,
|
|
141
|
+
resultForAssistant: this.renderResultForAssistant(result)
|
|
142
|
+
};
|
|
143
|
+
} catch (error) {
|
|
144
|
+
yield createToolErrorResult(error, "Error deleting team");
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
export {
|
|
149
|
+
TeamDeleteTool
|
|
150
|
+
};
|
|
151
|
+
//# sourceMappingURL=TeamDeleteTool.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/tools/TeamDeleteTool/TeamDeleteTool.tsx"],
|
|
4
|
+
"sourcesContent": ["import { Box, Text } from 'ink'\nimport * as React from 'react'\nimport { z } from 'zod'\nimport { rmSync, existsSync } from 'fs'\nimport { execFileSync } from 'child_process'\nimport { join } from 'path'\nimport { homedir } from 'os'\nimport { FallbackToolUseRejectedMessage } from '@components/FallbackToolUseRejectedMessage'\nimport { createToolErrorResult } from '@utils/tooling/toolError'\nimport { Tool } from '@tool'\nimport {\n isAgentTeamsEnabled,\n getActiveTeams,\n disbandTeam,\n} from '@services/agentTeams'\nimport { DESCRIPTION, PROMPT } from './prompt'\nimport { getTheme } from '@utils/theme'\nimport { debug as debugLogger } from '@utils/debugLogger'\n\nconst inputSchema = z.strictObject({})\n\nexport const TeamDeleteTool = {\n name: 'TeamDelete',\n async description() {\n return DESCRIPTION\n },\n async prompt() {\n return PROMPT\n },\n inputSchema,\n userFacingName() {\n return 'Delete Team'\n },\n async isEnabled() {\n return isAgentTeamsEnabled()\n },\n isReadOnly() {\n return false\n },\n isConcurrencySafe() {\n return false\n },\n needsPermissions() {\n return false\n },\n renderToolUseMessage() {\n return null\n },\n renderToolUseRejectedMessage() {\n return <FallbackToolUseRejectedMessage />\n },\n renderToolResultMessage(output: { success: boolean; message: string }) {\n if (!output) {\n return (\n <Box flexDirection=\"row\">\n <Text> \u23BF </Text>\n <Text>Team deleted</Text>\n </Box>\n )\n }\n const color = output.success ? getTheme().success : getTheme().error\n return (\n <Box flexDirection=\"row\">\n <Text> \u23BF </Text>\n <Text color={color}>{output.message}</Text>\n </Box>\n )\n },\n renderResultForAssistant(result: {\n success: boolean\n message: string\n team_name?: string\n }) {\n return JSON.stringify(result)\n },\n async *call() {\n try {\n const teams = getActiveTeams()\n if (teams.length === 0) {\n yield {\n type: 'result' as const,\n data: { success: false, message: 'No active team to delete' },\n resultForAssistant: JSON.stringify({\n success: false,\n message: 'No active team to delete.',\n }),\n }\n return\n }\n\n const team = teams[0]!\n\n // Only block on teammates that are actively working (mid-query).\n // Idle/stopped teammates are safe to force-stop \u2014 disbandTeam() handles cleanup.\n const workingMembers = team.members.filter(\n m => m.status === 'working' && m.name !== 'team-lead',\n )\n if (workingMembers.length > 0) {\n const names = workingMembers.map(m => m.name).join(', ')\n yield {\n type: 'result' as const,\n data: {\n success: false,\n message: `TeamDelete failed: team still has ${workingMembers.length} working member(s): ${names}. Send shutdown_request first, or wait for them to finish, then call TeamDelete.`,\n },\n resultForAssistant: JSON.stringify({\n success: false,\n message: `TeamDelete blocked by working members: ${names}. Send shutdown_request or wait for them to finish.`,\n }),\n }\n return\n }\n\n // Clean up git worktrees for each member\n for (const member of team.members) {\n if (member.worktreePath) {\n try {\n if (existsSync(member.worktreePath)) {\n execFileSync(\n 'git',\n ['worktree', 'remove', member.worktreePath, '--force'],\n {\n stdio: 'pipe',\n timeout: 10000,\n },\n )\n }\n } catch {\n /* best-effort worktree cleanup */\n }\n }\n }\n\n // Kill tmux panes for members that have them.\n // This must happen BEFORE disbandTeam() which clears the active registry.\n // Panes may already be gone (agent finished), so each kill is wrapped in try/catch.\n for (const member of team.members) {\n if (\n member.tmuxPaneId &&\n member.tmuxPaneId !== 'in-process' &&\n member.tmuxPaneId !== 'unknown'\n ) {\n try {\n execFileSync('tmux', ['kill-pane', '-t', member.tmuxPaneId], {\n stdio: 'pipe',\n timeout: 5000,\n })\n } catch {\n // Pane may have already exited \u2014 best-effort cleanup\n debugLogger.info('TEAM_DELETE_PANE_CLEANUP_SKIP', {\n memberId: member.id,\n paneId: member.tmuxPaneId,\n })\n }\n }\n }\n\n // Disband the team (clears from active registry)\n disbandTeam(team.name)\n\n // Clean up directories\n const teamsDir = join(homedir(), '.minto', 'teams', team.name)\n const tasksDir = join(homedir(), '.minto', 'tasks', team.name)\n\n if (existsSync(teamsDir)) {\n rmSync(teamsDir, { recursive: true, force: true })\n }\n if (existsSync(tasksDir)) {\n rmSync(tasksDir, { recursive: true, force: true })\n }\n\n const result = {\n success: true,\n message: `Team \"${team.name}\" disbanded`,\n team_name: team.name,\n }\n\n yield {\n type: 'result' as const,\n data: result,\n resultForAssistant: this.renderResultForAssistant(result),\n }\n } catch (error) {\n yield createToolErrorResult(error, 'Error deleting team')\n }\n },\n} satisfies Tool\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,KAAK,YAAY;AAC1B,YAAY,WAAW;AACvB,SAAS,SAAS;AAClB,SAAS,QAAQ,kBAAkB;AACnC,SAAS,oBAAoB;AAC7B,SAAS,YAAY;AACrB,SAAS,eAAe;AACxB,SAAS,sCAAsC;AAC/C,SAAS,6BAA6B;AAEtC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,aAAa,cAAc;AACpC,SAAS,gBAAgB;AACzB,SAAS,SAAS,mBAAmB;AAErC,MAAM,cAAc,EAAE,aAAa,CAAC,CAAC;AAE9B,MAAM,iBAAiB;AAAA,EAC5B,MAAM;AAAA,EACN,MAAM,cAAc;AAClB,WAAO;AAAA,EACT;AAAA,EACA,MAAM,SAAS;AACb,WAAO;AAAA,EACT;AAAA,EACA;AAAA,EACA,iBAAiB;AACf,WAAO;AAAA,EACT;AAAA,EACA,MAAM,YAAY;AAChB,WAAO,oBAAoB;AAAA,EAC7B;AAAA,EACA,aAAa;AACX,WAAO;AAAA,EACT;AAAA,EACA,oBAAoB;AAClB,WAAO;AAAA,EACT;AAAA,EACA,mBAAmB;AACjB,WAAO;AAAA,EACT;AAAA,EACA,uBAAuB;AACrB,WAAO;AAAA,EACT;AAAA,EACA,+BAA+B;AAC7B,WAAO,oCAAC,oCAA+B;AAAA,EACzC;AAAA,EACA,wBAAwB,QAA+C;AACrE,QAAI,CAAC,QAAQ;AACX,aACE,oCAAC,OAAI,eAAc,SACjB,oCAAC,YAAK,qBAAoB,GAC1B,oCAAC,YAAK,cAAY,CACpB;AAAA,IAEJ;AACA,UAAM,QAAQ,OAAO,UAAU,SAAS,EAAE,UAAU,SAAS,EAAE;AAC/D,WACE,oCAAC,OAAI,eAAc,SACjB,oCAAC,YAAK,qBAAoB,GAC1B,oCAAC,QAAK,SAAe,OAAO,OAAQ,CACtC;AAAA,EAEJ;AAAA,EACA,yBAAyB,QAItB;AACD,WAAO,KAAK,UAAU,MAAM;AAAA,EAC9B;AAAA,EACA,OAAO,OAAO;AACZ,QAAI;AACF,YAAM,QAAQ,eAAe;AAC7B,UAAI,MAAM,WAAW,GAAG;AACtB,cAAM;AAAA,UACJ,MAAM;AAAA,UACN,MAAM,EAAE,SAAS,OAAO,SAAS,2BAA2B;AAAA,UAC5D,oBAAoB,KAAK,UAAU;AAAA,YACjC,SAAS;AAAA,YACT,SAAS;AAAA,UACX,CAAC;AAAA,QACH;AACA;AAAA,MACF;AAEA,YAAM,OAAO,MAAM,CAAC;AAIpB,YAAM,iBAAiB,KAAK,QAAQ;AAAA,QAClC,OAAK,EAAE,WAAW,aAAa,EAAE,SAAS;AAAA,MAC5C;AACA,UAAI,eAAe,SAAS,GAAG;AAC7B,cAAM,QAAQ,eAAe,IAAI,OAAK,EAAE,IAAI,EAAE,KAAK,IAAI;AACvD,cAAM;AAAA,UACJ,MAAM;AAAA,UACN,MAAM;AAAA,YACJ,SAAS;AAAA,YACT,SAAS,qCAAqC,eAAe,MAAM,uBAAuB,KAAK;AAAA,UACjG;AAAA,UACA,oBAAoB,KAAK,UAAU;AAAA,YACjC,SAAS;AAAA,YACT,SAAS,0CAA0C,KAAK;AAAA,UAC1D,CAAC;AAAA,QACH;AACA;AAAA,MACF;AAGA,iBAAW,UAAU,KAAK,SAAS;AACjC,YAAI,OAAO,cAAc;AACvB,cAAI;AACF,gBAAI,WAAW,OAAO,YAAY,GAAG;AACnC;AAAA,gBACE;AAAA,gBACA,CAAC,YAAY,UAAU,OAAO,cAAc,SAAS;AAAA,gBACrD;AAAA,kBACE,OAAO;AAAA,kBACP,SAAS;AAAA,gBACX;AAAA,cACF;AAAA,YACF;AAAA,UACF,QAAQ;AAAA,UAER;AAAA,QACF;AAAA,MACF;AAKA,iBAAW,UAAU,KAAK,SAAS;AACjC,YACE,OAAO,cACP,OAAO,eAAe,gBACtB,OAAO,eAAe,WACtB;AACA,cAAI;AACF,yBAAa,QAAQ,CAAC,aAAa,MAAM,OAAO,UAAU,GAAG;AAAA,cAC3D,OAAO;AAAA,cACP,SAAS;AAAA,YACX,CAAC;AAAA,UACH,QAAQ;AAEN,wBAAY,KAAK,iCAAiC;AAAA,cAChD,UAAU,OAAO;AAAA,cACjB,QAAQ,OAAO;AAAA,YACjB,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF;AAGA,kBAAY,KAAK,IAAI;AAGrB,YAAM,WAAW,KAAK,QAAQ,GAAG,UAAU,SAAS,KAAK,IAAI;AAC7D,YAAM,WAAW,KAAK,QAAQ,GAAG,UAAU,SAAS,KAAK,IAAI;AAE7D,UAAI,WAAW,QAAQ,GAAG;AACxB,eAAO,UAAU,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,MACnD;AACA,UAAI,WAAW,QAAQ,GAAG;AACxB,eAAO,UAAU,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,MACnD;AAEA,YAAM,SAAS;AAAA,QACb,SAAS;AAAA,QACT,SAAS,SAAS,KAAK,IAAI;AAAA,QAC3B,WAAW,KAAK;AAAA,MAClB;AAEA,YAAM;AAAA,QACJ,MAAM;AAAA,QACN,MAAM;AAAA,QACN,oBAAoB,KAAK,yBAAyB,MAAM;AAAA,MAC1D;AAAA,IACF,SAAS,OAAO;AACd,YAAM,sBAAsB,OAAO,qBAAqB;AAAA,IAC1D;AAAA,EACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const PROMPT = `Remove team and task directories when the swarm work is complete.
|
|
2
|
+
|
|
3
|
+
This operation:
|
|
4
|
+
- Removes the team directory (\`~/.minto/teams/{team-name}/\`)
|
|
5
|
+
- Removes the task directory (\`~/.minto/tasks/{team-name}/\`)
|
|
6
|
+
- Clears team context from the current session
|
|
7
|
+
|
|
8
|
+
**IMPORTANT**: TeamDelete will fail if the team still has active members. Gracefully terminate teammates first, then call TeamDelete after all teammates have shut down.
|
|
9
|
+
|
|
10
|
+
Use this when all teammates have finished their work and you want to clean up the team resources. The team name is automatically determined from the current session's team context.`;
|
|
11
|
+
const DESCRIPTION = `Remove team and task directories when the swarm work is complete`;
|
|
12
|
+
export {
|
|
13
|
+
DESCRIPTION,
|
|
14
|
+
PROMPT
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=prompt.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/tools/TeamDeleteTool/prompt.ts"],
|
|
4
|
+
"sourcesContent": ["export const PROMPT = `Remove team and task directories when the swarm work is complete.\n\nThis operation:\n- Removes the team directory (\\`~/.minto/teams/{team-name}/\\`)\n- Removes the task directory (\\`~/.minto/tasks/{team-name}/\\`)\n- Clears team context from the current session\n\n**IMPORTANT**: TeamDelete will fail if the team still has active members. Gracefully terminate teammates first, then call TeamDelete after all teammates have shut down.\n\nUse this when all teammates have finished their work and you want to clean up the team resources. The team name is automatically determined from the current session's team context.`\n\nexport const DESCRIPTION = `Remove team and task directories when the swarm work is complete`\n"],
|
|
5
|
+
"mappings": "AAAO,MAAM,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAWf,MAAM,cAAc;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -4,6 +4,7 @@ import { z } from "zod";
|
|
|
4
4
|
import fetch from "node-fetch";
|
|
5
5
|
import { Cost } from "../../components/Cost.js";
|
|
6
6
|
import { FallbackToolUseRejectedMessage } from "../../components/FallbackToolUseRejectedMessage.js";
|
|
7
|
+
import { DefaultToolResultFallback } from "../../components/messages/DefaultToolResultFallback.js";
|
|
7
8
|
import { DESCRIPTION, TOOL_NAME_FOR_PROMPT } from "./prompt.js";
|
|
8
9
|
import { convertHtmlToMarkdown } from "./htmlToMarkdown.js";
|
|
9
10
|
import { urlCache } from "./cache.js";
|
|
@@ -19,6 +20,55 @@ function normalizeUrl(url) {
|
|
|
19
20
|
}
|
|
20
21
|
return url;
|
|
21
22
|
}
|
|
23
|
+
function isPrivateOrReservedURL(url) {
|
|
24
|
+
try {
|
|
25
|
+
const parsed = new URL(url);
|
|
26
|
+
const hostname = parsed.hostname;
|
|
27
|
+
if (/^(127\.|10\.|192\.168\.|172\.(1[6-9]|2\d|3[01])\.)/.test(hostname))
|
|
28
|
+
return true;
|
|
29
|
+
if (hostname === "::1" || hostname === "[::1]") return true;
|
|
30
|
+
if (hostname === "localhost" || hostname.endsWith(".localhost")) return true;
|
|
31
|
+
if (hostname === "169.254.169.254" || hostname === "metadata.google.internal")
|
|
32
|
+
return true;
|
|
33
|
+
if (hostname.startsWith("169.254.")) return true;
|
|
34
|
+
if (hostname === "0.0.0.0") return true;
|
|
35
|
+
const ipv4MappedMatch = hostname.match(/^::ffff:(\d+\.\d+\.\d+\.\d+)$/i);
|
|
36
|
+
if (ipv4MappedMatch) {
|
|
37
|
+
return isPrivateOrReservedURL(`http://${ipv4MappedMatch[1]}/`);
|
|
38
|
+
}
|
|
39
|
+
if (/^\d+$/.test(hostname)) {
|
|
40
|
+
const decimal = parseInt(hostname, 10);
|
|
41
|
+
if (!isNaN(decimal) && decimal >= 0 && decimal <= 4294967295) {
|
|
42
|
+
const a = decimal >>> 24 & 255;
|
|
43
|
+
const b = decimal >>> 16 & 255;
|
|
44
|
+
const c = decimal >>> 8 & 255;
|
|
45
|
+
const d = decimal & 255;
|
|
46
|
+
return isPrivateOrReservedURL(`http://${a}.${b}.${c}.${d}/`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (/^0x[0-9a-fA-F]+$/.test(hostname)) {
|
|
50
|
+
const hex = parseInt(hostname, 16);
|
|
51
|
+
if (!isNaN(hex) && hex >= 0 && hex <= 4294967295) {
|
|
52
|
+
const a = hex >>> 24 & 255;
|
|
53
|
+
const b = hex >>> 16 & 255;
|
|
54
|
+
const c = hex >>> 8 & 255;
|
|
55
|
+
const d = hex & 255;
|
|
56
|
+
return isPrivateOrReservedURL(`http://${a}.${b}.${c}.${d}/`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
const shortIpParts = hostname.split(".");
|
|
60
|
+
if (shortIpParts.length >= 2 && shortIpParts.length <= 3 && shortIpParts.every((p) => /^\d+$/.test(p))) {
|
|
61
|
+
const first = parseInt(shortIpParts[0], 10);
|
|
62
|
+
if (first === 127 || first === 10 || first === 0 || first === 169) {
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (!["http:", "https:"].includes(parsed.protocol)) return true;
|
|
67
|
+
return false;
|
|
68
|
+
} catch {
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
22
72
|
const URLFetcherTool = {
|
|
23
73
|
name: TOOL_NAME_FOR_PROMPT,
|
|
24
74
|
async description() {
|
|
@@ -47,7 +97,7 @@ const URLFetcherTool = {
|
|
|
47
97
|
},
|
|
48
98
|
renderToolResultMessage(output) {
|
|
49
99
|
if (!output) {
|
|
50
|
-
return /* @__PURE__ */ React.createElement(
|
|
100
|
+
return /* @__PURE__ */ React.createElement(DefaultToolResultFallback, { toolName: "URL fetch" });
|
|
51
101
|
}
|
|
52
102
|
const statusText = output.fromCache ? "from cache" : "fetched";
|
|
53
103
|
return /* @__PURE__ */ React.createElement(Box, { justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Text, null, "\xA0\xA0\u23BF \xA0Content "), /* @__PURE__ */ React.createElement(Text, { bold: true }, statusText, " "), /* @__PURE__ */ React.createElement(Text, null, "and analyzed")), /* @__PURE__ */ React.createElement(Cost, { costUSD: 0, durationMs: 0, debug: false }));
|
|
@@ -60,6 +110,19 @@ const URLFetcherTool = {
|
|
|
60
110
|
},
|
|
61
111
|
async *call({ url, prompt }, {}) {
|
|
62
112
|
const normalizedUrl = normalizeUrl(url);
|
|
113
|
+
if (isPrivateOrReservedURL(normalizedUrl)) {
|
|
114
|
+
const output = {
|
|
115
|
+
url: normalizedUrl,
|
|
116
|
+
fromCache: false,
|
|
117
|
+
aiAnalysis: ""
|
|
118
|
+
};
|
|
119
|
+
yield {
|
|
120
|
+
type: "result",
|
|
121
|
+
resultForAssistant: `Error: URL ${normalizedUrl} targets a private or reserved network address and has been blocked for security reasons.`,
|
|
122
|
+
data: output
|
|
123
|
+
};
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
63
126
|
try {
|
|
64
127
|
let content;
|
|
65
128
|
let fromCache = false;
|
|
@@ -70,20 +133,47 @@ const URLFetcherTool = {
|
|
|
70
133
|
} else {
|
|
71
134
|
const abortController = new AbortController();
|
|
72
135
|
const timeout = setTimeout(() => abortController.abort(), 3e4);
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
136
|
+
const MAX_REDIRECTS = 5;
|
|
137
|
+
let currentUrl = normalizedUrl;
|
|
138
|
+
let response = null;
|
|
139
|
+
for (let redirectCount = 0; redirectCount <= MAX_REDIRECTS; redirectCount++) {
|
|
140
|
+
response = await fetch(currentUrl, {
|
|
141
|
+
method: "GET",
|
|
142
|
+
headers: {
|
|
143
|
+
"User-Agent": "Mozilla/5.0 (compatible; URLFetcher/1.0)",
|
|
144
|
+
Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
|
|
145
|
+
"Accept-Language": "en-US,en;q=0.5",
|
|
146
|
+
"Accept-Encoding": "gzip, deflate",
|
|
147
|
+
Connection: "keep-alive",
|
|
148
|
+
"Upgrade-Insecure-Requests": "1"
|
|
149
|
+
},
|
|
150
|
+
signal: abortController.signal,
|
|
151
|
+
redirect: "manual"
|
|
152
|
+
});
|
|
153
|
+
if (response.status < 300 || response.status >= 400) {
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
const locationHeader = response.headers.get("location");
|
|
157
|
+
if (!locationHeader) {
|
|
158
|
+
throw new Error(
|
|
159
|
+
`Redirect ${response.status} with no Location header`
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
const redirectUrl = new URL(locationHeader, currentUrl).toString();
|
|
163
|
+
if (isPrivateOrReservedURL(redirectUrl)) {
|
|
164
|
+
throw new Error(
|
|
165
|
+
`Redirect to ${redirectUrl} blocked: targets a private or reserved network address`
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
if (redirectCount === MAX_REDIRECTS) {
|
|
169
|
+
throw new Error(`Too many redirects (max ${MAX_REDIRECTS})`);
|
|
170
|
+
}
|
|
171
|
+
currentUrl = redirectUrl;
|
|
172
|
+
}
|
|
86
173
|
clearTimeout(timeout);
|
|
174
|
+
if (!response) {
|
|
175
|
+
throw new Error("No response received");
|
|
176
|
+
}
|
|
87
177
|
if (!response.ok) {
|
|
88
178
|
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
89
179
|
}
|
|
@@ -138,6 +228,7 @@ User request: ${prompt}`;
|
|
|
138
228
|
}
|
|
139
229
|
};
|
|
140
230
|
export {
|
|
141
|
-
URLFetcherTool
|
|
231
|
+
URLFetcherTool,
|
|
232
|
+
isPrivateOrReservedURL
|
|
142
233
|
};
|
|
143
234
|
//# sourceMappingURL=URLFetcherTool.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/tools/URLFetcherTool/URLFetcherTool.tsx"],
|
|
4
|
-
"sourcesContent": ["import { Box, Text } from 'ink'\nimport React from 'react'\nimport { z } from 'zod'\nimport fetch from 'node-fetch'\nimport { Cost } from '@components/Cost'\nimport { FallbackToolUseRejectedMessage } from '@components/FallbackToolUseRejectedMessage'\nimport { Tool, ToolUseContext } from '@tool'\nimport { DESCRIPTION, TOOL_NAME_FOR_PROMPT } from './prompt'\nimport { convertHtmlToMarkdown } from './htmlToMarkdown'\nimport { urlCache } from './cache'\nimport { queryQuick } from '@services/claude'\nimport { formatUrl, truncateText } from '@utils/format'\n\nconst inputSchema = z.strictObject({\n url: z.string().url().describe('The URL to fetch content from'),\n prompt: z.string().describe('The prompt to run on the fetched content'),\n})\n\ntype Input = z.infer<typeof inputSchema>\ntype Output = {\n url: string\n fromCache: boolean\n aiAnalysis: string\n}\n\nfunction normalizeUrl(url: string): string {\n // Auto-upgrade HTTP to HTTPS\n if (url.startsWith('http://')) {\n return url.replace('http://', 'https://')\n }\n return url\n}\n\nexport const URLFetcherTool = {\n name: TOOL_NAME_FOR_PROMPT,\n async description() {\n return DESCRIPTION\n },\n userFacingName: () => 'URL Fetcher',\n inputSchema,\n isReadOnly: () => true,\n isConcurrencySafe: () => true,\n async isEnabled() {\n return true\n },\n needsPermissions() {\n return false\n },\n async prompt() {\n return DESCRIPTION\n },\n renderToolUseMessage({ url, prompt }: Input) {\n const displayUrl = formatUrl(url, 40)\n const displayPrompt = truncateText(prompt, 30)\n return `${displayUrl} \u00B7 \"${displayPrompt}\"`\n },\n renderToolUseRejectedMessage() {\n return <FallbackToolUseRejectedMessage />\n },\n renderToolResultMessage(output: Output) {\n // Guard against undefined or null output\n if (!output) {\n return (\n <Box justifyContent=\"space-between\" width=\"100%\">\n <Box flexDirection=\"row\">\n <Text> \u23BF URL fetch completed</Text>\n </Box>\n </Box>\n )\n }\n\n const statusText = output.fromCache ? 'from cache' : 'fetched'\n\n return (\n <Box justifyContent=\"space-between\" width=\"100%\">\n <Box flexDirection=\"row\">\n <Text> \u23BF Content </Text>\n <Text bold>{statusText} </Text>\n <Text>and analyzed</Text>\n </Box>\n <Cost costUSD={0} durationMs={0} debug={false} />\n </Box>\n )\n },\n renderResultForAssistant(output: Output) {\n if (!output.aiAnalysis.trim()) {\n return `No content could be analyzed from URL: ${output.url}`\n }\n\n return output.aiAnalysis\n },\n async *call({ url, prompt }: Input, {}: ToolUseContext) {\n const normalizedUrl = normalizeUrl(url)\n\n try {\n let content: string\n let fromCache = false\n\n // Check cache first\n const cachedContent = urlCache.get(normalizedUrl)\n if (cachedContent) {\n content = cachedContent\n fromCache = true\n } else {\n // Fetch from URL with AbortController for timeout\n const abortController = new AbortController()\n const timeout = setTimeout(() => abortController.abort(), 30000)\n\n const response = await fetch(normalizedUrl, {\n method: 'GET',\n headers: {\n 'User-Agent': 'Mozilla/5.0 (compatible; URLFetcher/1.0)',\n Accept:\n 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',\n 'Accept-Language': 'en-US,en;q=0.5',\n 'Accept-Encoding': 'gzip, deflate',\n Connection: 'keep-alive',\n 'Upgrade-Insecure-Requests': '1',\n },\n signal: abortController.signal,\n redirect: 'follow',\n })\n\n clearTimeout(timeout)\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`)\n }\n\n const contentType = response.headers.get('content-type') || ''\n if (\n !contentType.includes('text/') &&\n !contentType.includes('application/')\n ) {\n throw new Error(`Unsupported content type: ${contentType}`)\n }\n\n const html = await response.text()\n content = convertHtmlToMarkdown(html)\n\n // Cache the result\n urlCache.set(normalizedUrl, content)\n fromCache = false\n }\n\n // Truncate content if too large (keep within reasonable token limits)\n const maxContentLength = 50000 // ~15k tokens approximately\n const truncatedContent =\n content.length > maxContentLength\n ? content.substring(0, maxContentLength) +\n '\\n\\n[Content truncated due to length]'\n : content\n\n // AI Analysis - always performed fresh, even with cached content\n const systemPrompt = [\n \"You are analyzing web content based on a user's specific request.\",\n 'The content has been extracted from a webpage and converted to markdown.',\n \"Provide a focused response that directly addresses the user's prompt.\",\n ]\n\n const userPrompt = `Here is the content from ${normalizedUrl}:\n\n${truncatedContent}\n\nUser request: ${prompt}`\n\n const aiResponse = await queryQuick({\n systemPrompt,\n userPrompt,\n enablePromptCaching: false,\n })\n\n const output: Output = {\n url: normalizedUrl,\n fromCache,\n aiAnalysis:\n aiResponse.message.content[0]?.text || 'Unable to analyze content',\n }\n\n yield {\n type: 'result' as const,\n resultForAssistant: this.renderResultForAssistant(output),\n data: output,\n }\n } catch (error: any) {\n const output: Output = {\n url: normalizedUrl,\n fromCache: false,\n aiAnalysis: '',\n }\n\n yield {\n type: 'result' as const,\n resultForAssistant: `Error processing URL ${normalizedUrl}: ${error.message}`,\n data: output,\n }\n }\n },\n} satisfies Tool\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,KAAK,YAAY;AAC1B,OAAO,WAAW;AAClB,SAAS,SAAS;AAClB,OAAO,WAAW;AAClB,SAAS,YAAY;AACrB,SAAS,sCAAsC;
|
|
4
|
+
"sourcesContent": ["import { Box, Text } from 'ink'\nimport React from 'react'\nimport { z } from 'zod'\nimport fetch from 'node-fetch'\nimport { Cost } from '@components/Cost'\nimport { FallbackToolUseRejectedMessage } from '@components/FallbackToolUseRejectedMessage'\nimport { DefaultToolResultFallback } from '@components/messages/DefaultToolResultFallback'\nimport { Tool, ToolUseContext } from '@tool'\nimport { DESCRIPTION, TOOL_NAME_FOR_PROMPT } from './prompt'\nimport { convertHtmlToMarkdown } from './htmlToMarkdown'\nimport { urlCache } from './cache'\nimport { queryQuick } from '@services/claude'\nimport { formatUrl, truncateText } from '@utils/format'\n\nconst inputSchema = z.strictObject({\n url: z.string().url().describe('The URL to fetch content from'),\n prompt: z.string().describe('The prompt to run on the fetched content'),\n})\n\ntype Input = z.infer<typeof inputSchema>\ntype Output = {\n url: string\n fromCache: boolean\n aiAnalysis: string\n}\n\nfunction normalizeUrl(url: string): string {\n // Auto-upgrade HTTP to HTTPS\n if (url.startsWith('http://')) {\n return url.replace('http://', 'https://')\n }\n return url\n}\n\n/**\n * SSRF protection: block requests to private/reserved network addresses.\n * Prevents server-side request forgery attacks targeting internal services,\n * cloud metadata endpoints, and localhost.\n */\nexport function isPrivateOrReservedURL(url: string): boolean {\n try {\n const parsed = new URL(url)\n const hostname = parsed.hostname\n // Block private IPv4 ranges\n if (/^(127\\.|10\\.|192\\.168\\.|172\\.(1[6-9]|2\\d|3[01])\\.)/.test(hostname))\n return true\n // Block IPv6 loopback\n if (hostname === '::1' || hostname === '[::1]') return true\n // Block localhost\n if (hostname === 'localhost' || hostname.endsWith('.localhost')) return true\n // Block cloud metadata endpoints\n if (\n hostname === '169.254.169.254' ||\n hostname === 'metadata.google.internal'\n )\n return true\n // Block link-local\n if (hostname.startsWith('169.254.')) return true\n // Block 0.0.0.0 (binds to all interfaces, often resolves to localhost)\n if (hostname === '0.0.0.0') return true\n // Block IPv4-mapped IPv6 addresses (::ffff:127.0.0.1, ::ffff:10.x.x.x, etc.)\n const ipv4MappedMatch = hostname.match(/^::ffff:(\\d+\\.\\d+\\.\\d+\\.\\d+)$/i)\n if (ipv4MappedMatch) {\n // Recursively check the embedded IPv4 address\n return isPrivateOrReservedURL(`http://${ipv4MappedMatch[1]}/`)\n }\n // Block decimal IP addresses (e.g., 2130706433 = 127.0.0.1)\n if (/^\\d+$/.test(hostname)) {\n const decimal = parseInt(hostname, 10)\n if (!isNaN(decimal) && decimal >= 0 && decimal <= 0xffffffff) {\n const a = (decimal >>> 24) & 0xff\n const b = (decimal >>> 16) & 0xff\n const c = (decimal >>> 8) & 0xff\n const d = decimal & 0xff\n return isPrivateOrReservedURL(`http://${a}.${b}.${c}.${d}/`)\n }\n }\n // Block hex IP addresses (e.g., 0x7f000001 = 127.0.0.1)\n if (/^0x[0-9a-fA-F]+$/.test(hostname)) {\n const hex = parseInt(hostname, 16)\n if (!isNaN(hex) && hex >= 0 && hex <= 0xffffffff) {\n const a = (hex >>> 24) & 0xff\n const b = (hex >>> 16) & 0xff\n const c = (hex >>> 8) & 0xff\n const d = hex & 0xff\n return isPrivateOrReservedURL(`http://${a}.${b}.${c}.${d}/`)\n }\n }\n // Block short-form IPs (e.g., 127.1 = 127.0.0.1, 127.0.1 = 127.0.0.1)\n const shortIpParts = hostname.split('.')\n if (\n shortIpParts.length >= 2 &&\n shortIpParts.length <= 3 &&\n shortIpParts.every(p => /^\\d+$/.test(p))\n ) {\n // Short-form IPs: the last part fills the remaining octets\n // e.g., 127.1 \u2192 127.0.0.1, 10.1 \u2192 10.0.0.1\n const first = parseInt(shortIpParts[0], 10)\n if (first === 127 || first === 10 || first === 0 || first === 169) {\n return true\n }\n }\n // Block non-HTTP(S) schemes\n if (!['http:', 'https:'].includes(parsed.protocol)) return true\n return false\n } catch {\n return true // Block malformed URLs\n }\n}\n\nexport const URLFetcherTool = {\n name: TOOL_NAME_FOR_PROMPT,\n async description() {\n return DESCRIPTION\n },\n userFacingName: () => 'URL Fetcher',\n inputSchema,\n isReadOnly: () => true,\n isConcurrencySafe: () => true,\n async isEnabled() {\n return true\n },\n needsPermissions() {\n return false\n },\n async prompt() {\n return DESCRIPTION\n },\n renderToolUseMessage({ url, prompt }: Input) {\n const displayUrl = formatUrl(url, 40)\n const displayPrompt = truncateText(prompt, 30)\n return `${displayUrl} \u00B7 \"${displayPrompt}\"`\n },\n renderToolUseRejectedMessage() {\n return <FallbackToolUseRejectedMessage />\n },\n renderToolResultMessage(output: Output) {\n // Guard against undefined or null output\n if (!output) {\n return <DefaultToolResultFallback toolName=\"URL fetch\" />\n }\n\n const statusText = output.fromCache ? 'from cache' : 'fetched'\n\n return (\n <Box justifyContent=\"space-between\" width=\"100%\">\n <Box flexDirection=\"row\">\n <Text> \u23BF Content </Text>\n <Text bold>{statusText} </Text>\n <Text>and analyzed</Text>\n </Box>\n <Cost costUSD={0} durationMs={0} debug={false} />\n </Box>\n )\n },\n renderResultForAssistant(output: Output) {\n if (!output.aiAnalysis.trim()) {\n return `No content could be analyzed from URL: ${output.url}`\n }\n\n return output.aiAnalysis\n },\n async *call({ url, prompt }: Input, {}: ToolUseContext) {\n const normalizedUrl = normalizeUrl(url)\n\n // SSRF protection: block private/reserved URLs\n if (isPrivateOrReservedURL(normalizedUrl)) {\n const output: Output = {\n url: normalizedUrl,\n fromCache: false,\n aiAnalysis: '',\n }\n yield {\n type: 'result' as const,\n resultForAssistant: `Error: URL ${normalizedUrl} targets a private or reserved network address and has been blocked for security reasons.`,\n data: output,\n }\n return\n }\n\n try {\n let content: string\n let fromCache = false\n\n // Check cache first\n const cachedContent = urlCache.get(normalizedUrl)\n if (cachedContent) {\n content = cachedContent\n fromCache = true\n } else {\n // Fetch from URL with AbortController for timeout\n // Use manual redirect handling to validate each redirect target against SSRF\n const abortController = new AbortController()\n const timeout = setTimeout(() => abortController.abort(), 30000)\n\n const MAX_REDIRECTS = 5\n let currentUrl = normalizedUrl\n let response: Awaited<ReturnType<typeof fetch>> | null = null\n\n for (\n let redirectCount = 0;\n redirectCount <= MAX_REDIRECTS;\n redirectCount++\n ) {\n response = await fetch(currentUrl, {\n method: 'GET',\n headers: {\n 'User-Agent': 'Mozilla/5.0 (compatible; URLFetcher/1.0)',\n Accept:\n 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',\n 'Accept-Language': 'en-US,en;q=0.5',\n 'Accept-Encoding': 'gzip, deflate',\n Connection: 'keep-alive',\n 'Upgrade-Insecure-Requests': '1',\n },\n signal: abortController.signal,\n redirect: 'manual',\n })\n\n // If not a redirect, break out\n if (response.status < 300 || response.status >= 400) {\n break\n }\n\n // Handle redirect: validate the Location header\n const locationHeader = response.headers.get('location')\n if (!locationHeader) {\n throw new Error(\n `Redirect ${response.status} with no Location header`,\n )\n }\n\n // Resolve relative redirects against the current URL\n const redirectUrl = new URL(locationHeader, currentUrl).toString()\n\n // SSRF check on redirect target\n if (isPrivateOrReservedURL(redirectUrl)) {\n throw new Error(\n `Redirect to ${redirectUrl} blocked: targets a private or reserved network address`,\n )\n }\n\n if (redirectCount === MAX_REDIRECTS) {\n throw new Error(`Too many redirects (max ${MAX_REDIRECTS})`)\n }\n\n currentUrl = redirectUrl\n }\n\n clearTimeout(timeout)\n\n if (!response) {\n throw new Error('No response received')\n }\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`)\n }\n\n const contentType = response.headers.get('content-type') || ''\n if (\n !contentType.includes('text/') &&\n !contentType.includes('application/')\n ) {\n throw new Error(`Unsupported content type: ${contentType}`)\n }\n\n const html = await response.text()\n content = convertHtmlToMarkdown(html)\n\n // Cache the result\n urlCache.set(normalizedUrl, content)\n fromCache = false\n }\n\n // Truncate content if too large (keep within reasonable token limits)\n const maxContentLength = 50000 // ~15k tokens approximately\n const truncatedContent =\n content.length > maxContentLength\n ? content.substring(0, maxContentLength) +\n '\\n\\n[Content truncated due to length]'\n : content\n\n // AI Analysis - always performed fresh, even with cached content\n const systemPrompt = [\n \"You are analyzing web content based on a user's specific request.\",\n 'The content has been extracted from a webpage and converted to markdown.',\n \"Provide a focused response that directly addresses the user's prompt.\",\n ]\n\n const userPrompt = `Here is the content from ${normalizedUrl}:\n\n${truncatedContent}\n\nUser request: ${prompt}`\n\n const aiResponse = await queryQuick({\n systemPrompt,\n userPrompt,\n enablePromptCaching: false,\n })\n\n const output: Output = {\n url: normalizedUrl,\n fromCache,\n aiAnalysis:\n aiResponse.message.content[0]?.text || 'Unable to analyze content',\n }\n\n yield {\n type: 'result' as const,\n resultForAssistant: this.renderResultForAssistant(output),\n data: output,\n }\n } catch (error: any) {\n const output: Output = {\n url: normalizedUrl,\n fromCache: false,\n aiAnalysis: '',\n }\n\n yield {\n type: 'result' as const,\n resultForAssistant: `Error processing URL ${normalizedUrl}: ${error.message}`,\n data: output,\n }\n }\n },\n} satisfies Tool\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -12,14 +12,15 @@ Capabilities:
|
|
|
12
12
|
|
|
13
13
|
Limitations:
|
|
14
14
|
- Cannot bypass bot detection or CAPTCHAs on protected sites
|
|
15
|
-
-
|
|
15
|
+
- Frequently fails on sites with anti-scraping measures (weather sites, news sites, etc.)
|
|
16
16
|
- Cannot access authenticated/private content
|
|
17
17
|
|
|
18
18
|
Usage notes:
|
|
19
19
|
- The URL must be a fully-formed valid URL (e.g., https://example.com)
|
|
20
20
|
- HTTP URLs will be automatically upgraded to HTTPS
|
|
21
21
|
- The prompt should describe what information you want to extract
|
|
22
|
-
- If
|
|
22
|
+
- IMPORTANT: If MCP scraping tools are available in <available-deferred-tools> (e.g. mcp__BrightData__scrape_as_markdown, mcp__BrightData__scrape_as_html), use ToolSearch to load them and prefer them \u2014 they bypass bot detection and handle protected sites reliably
|
|
23
|
+
- Only use this built-in fetcher when no MCP scraping tools are available, or for simple unprotected pages`;
|
|
23
24
|
export {
|
|
24
25
|
DESCRIPTION,
|
|
25
26
|
TOOL_NAME_FOR_PROMPT
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/tools/URLFetcherTool/prompt.ts"],
|
|
4
|
-
"sourcesContent": ["export const TOOL_NAME_FOR_PROMPT = 'WebFetch'\nexport const DESCRIPTION = `- Built-in URL fetcher that retrieves and analyzes web content\n- Takes a URL and a prompt as input\n- Fetches the URL content, converts HTML to markdown\n- Processes the content with the prompt using a small, fast model\n\nCapabilities:\n- Fetch and analyze public web pages\n- Extract specific information based on prompt\n- Automatic redirect handling\n- 15-minute cache for repeated access\n\nLimitations:\n- Cannot bypass bot detection or CAPTCHAs on protected sites\n-
|
|
5
|
-
"mappings": "AAAO,MAAM,uBAAuB;AAC7B,MAAM,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;",
|
|
4
|
+
"sourcesContent": ["export const TOOL_NAME_FOR_PROMPT = 'WebFetch'\nexport const DESCRIPTION = `- Built-in URL fetcher that retrieves and analyzes web content\n- Takes a URL and a prompt as input\n- Fetches the URL content, converts HTML to markdown\n- Processes the content with the prompt using a small, fast model\n\nCapabilities:\n- Fetch and analyze public web pages\n- Extract specific information based on prompt\n- Automatic redirect handling\n- 15-minute cache for repeated access\n\nLimitations:\n- Cannot bypass bot detection or CAPTCHAs on protected sites\n- Frequently fails on sites with anti-scraping measures (weather sites, news sites, etc.)\n- Cannot access authenticated/private content\n\nUsage notes:\n- The URL must be a fully-formed valid URL (e.g., https://example.com)\n- HTTP URLs will be automatically upgraded to HTTPS\n- The prompt should describe what information you want to extract\n- IMPORTANT: If MCP scraping tools are available in <available-deferred-tools> (e.g. mcp__BrightData__scrape_as_markdown, mcp__BrightData__scrape_as_html), use ToolSearch to load them and prefer them \u2014 they bypass bot detection and handle protected sites reliably\n- Only use this built-in fetcher when no MCP scraping tools are available, or for simple unprotected pages`\n"],
|
|
5
|
+
"mappings": "AAAO,MAAM,uBAAuB;AAC7B,MAAM,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -3,6 +3,7 @@ import React from "react";
|
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { Cost } from "../../components/Cost.js";
|
|
5
5
|
import { FallbackToolUseRejectedMessage } from "../../components/FallbackToolUseRejectedMessage.js";
|
|
6
|
+
import { DefaultToolResultFallback } from "../../components/messages/DefaultToolResultFallback.js";
|
|
6
7
|
import { DESCRIPTION, TOOL_NAME_FOR_PROMPT } from "./prompt.js";
|
|
7
8
|
import { searchProviders } from "./searchProviders.js";
|
|
8
9
|
const inputSchema = z.strictObject({
|
|
@@ -34,7 +35,7 @@ const WebSearchTool = {
|
|
|
34
35
|
},
|
|
35
36
|
renderToolResultMessage(output) {
|
|
36
37
|
if (!output) {
|
|
37
|
-
return /* @__PURE__ */ React.createElement(
|
|
38
|
+
return /* @__PURE__ */ React.createElement(DefaultToolResultFallback, { toolName: "Search" });
|
|
38
39
|
}
|
|
39
40
|
const resultsLength = output.results?.length ?? 0;
|
|
40
41
|
const durationMs = output.durationMs ?? 0;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/tools/WebSearchTool/WebSearchTool.tsx"],
|
|
4
|
-
"sourcesContent": ["import { Box, Text } from 'ink'\nimport React from 'react'\nimport { z } from 'zod'\nimport { Cost } from '@components/Cost'\nimport { FallbackToolUseRejectedMessage } from '@components/FallbackToolUseRejectedMessage'\nimport { Tool, ToolUseContext } from '@tool'\nimport { DESCRIPTION, TOOL_NAME_FOR_PROMPT } from './prompt'\nimport { SearchResult, searchProviders } from './searchProviders'\n\nconst inputSchema = z.strictObject({\n query: z.string().describe('The search query'),\n})\n\ntype Input = z.infer<typeof inputSchema>\ntype Output = {\n durationMs: number\n results: SearchResult[]\n}\n\nexport const WebSearchTool = {\n name: TOOL_NAME_FOR_PROMPT,\n async description() {\n return DESCRIPTION\n },\n userFacingName: () => 'Web Search',\n inputSchema,\n isReadOnly: () => true,\n isConcurrencySafe: () => true,\n async isEnabled() {\n return true\n },\n needsPermissions() {\n return false\n },\n async prompt() {\n return DESCRIPTION\n },\n renderToolUseMessage({ query }: Input) {\n return `Searching for: \"${query}\" using DuckDuckGo`\n },\n renderToolUseRejectedMessage() {\n return <FallbackToolUseRejectedMessage />\n },\n renderToolResultMessage(output: Output) {\n // Guard against undefined or null output\n if (!output) {\n return
|
|
5
|
-
"mappings": "AAAA,SAAS,KAAK,YAAY;AAC1B,OAAO,WAAW;AAClB,SAAS,SAAS;AAClB,SAAS,YAAY;AACrB,SAAS,sCAAsC;
|
|
4
|
+
"sourcesContent": ["import { Box, Text } from 'ink'\nimport React from 'react'\nimport { z } from 'zod'\nimport { Cost } from '@components/Cost'\nimport { FallbackToolUseRejectedMessage } from '@components/FallbackToolUseRejectedMessage'\nimport { DefaultToolResultFallback } from '@components/messages/DefaultToolResultFallback'\nimport { Tool, ToolUseContext } from '@tool'\nimport { DESCRIPTION, TOOL_NAME_FOR_PROMPT } from './prompt'\nimport { SearchResult, searchProviders } from './searchProviders'\n\nconst inputSchema = z.strictObject({\n query: z.string().describe('The search query'),\n})\n\ntype Input = z.infer<typeof inputSchema>\ntype Output = {\n durationMs: number\n results: SearchResult[]\n}\n\nexport const WebSearchTool = {\n name: TOOL_NAME_FOR_PROMPT,\n async description() {\n return DESCRIPTION\n },\n userFacingName: () => 'Web Search',\n inputSchema,\n isReadOnly: () => true,\n isConcurrencySafe: () => true,\n async isEnabled() {\n return true\n },\n needsPermissions() {\n return false\n },\n async prompt() {\n return DESCRIPTION\n },\n renderToolUseMessage({ query }: Input) {\n return `Searching for: \"${query}\" using DuckDuckGo`\n },\n renderToolUseRejectedMessage() {\n return <FallbackToolUseRejectedMessage />\n },\n renderToolResultMessage(output: Output) {\n // Guard against undefined or null output\n if (!output) {\n return <DefaultToolResultFallback toolName=\"Search\" />\n }\n\n const resultsLength = output.results?.length ?? 0\n const durationMs = output.durationMs ?? 0\n\n return (\n <Box justifyContent=\"space-between\" width=\"100%\">\n <Box flexDirection=\"row\">\n <Text> \u23BF Found </Text>\n <Text bold>{resultsLength} </Text>\n <Text>\n {resultsLength === 1 ? 'result' : 'results'} using DuckDuckGo\n </Text>\n </Box>\n <Cost costUSD={0} durationMs={durationMs} debug={false} />\n </Box>\n )\n },\n renderResultForAssistant(output: Output) {\n if (output.results.length === 0) {\n return `No results found using DuckDuckGo.`\n }\n\n let result = `Found ${output.results.length} search results using DuckDuckGo:\\n\\n`\n\n output.results.forEach((item, index) => {\n result += `${index + 1}. **${item.title}**\\n`\n result += ` ${item.snippet}\\n`\n result += ` Link: ${item.link}\\n\\n`\n })\n\n result += `You can reference these results to provide current, accurate information to the user.`\n return result\n },\n async *call({ query }: Input, {}: ToolUseContext) {\n const start = Date.now()\n\n try {\n const searchResults = await searchProviders.duckduckgo.search(query)\n\n const output: Output = {\n results: searchResults,\n durationMs: Date.now() - start,\n }\n\n yield {\n type: 'result' as const,\n resultForAssistant: this.renderResultForAssistant(output),\n data: output,\n }\n } catch (error: any) {\n const output: Output = {\n results: [],\n durationMs: Date.now() - start,\n }\n yield {\n type: 'result' as const,\n resultForAssistant: `An error occurred during web search with DuckDuckGo: ${error.message}`,\n data: output,\n }\n }\n },\n} satisfies Tool\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,KAAK,YAAY;AAC1B,OAAO,WAAW;AAClB,SAAS,SAAS;AAClB,SAAS,YAAY;AACrB,SAAS,sCAAsC;AAC/C,SAAS,iCAAiC;AAE1C,SAAS,aAAa,4BAA4B;AAClD,SAAuB,uBAAuB;AAE9C,MAAM,cAAc,EAAE,aAAa;AAAA,EACjC,OAAO,EAAE,OAAO,EAAE,SAAS,kBAAkB;AAC/C,CAAC;AAQM,MAAM,gBAAgB;AAAA,EAC3B,MAAM;AAAA,EACN,MAAM,cAAc;AAClB,WAAO;AAAA,EACT;AAAA,EACA,gBAAgB,MAAM;AAAA,EACtB;AAAA,EACA,YAAY,MAAM;AAAA,EAClB,mBAAmB,MAAM;AAAA,EACzB,MAAM,YAAY;AAChB,WAAO;AAAA,EACT;AAAA,EACA,mBAAmB;AACjB,WAAO;AAAA,EACT;AAAA,EACA,MAAM,SAAS;AACb,WAAO;AAAA,EACT;AAAA,EACA,qBAAqB,EAAE,MAAM,GAAU;AACrC,WAAO,mBAAmB,KAAK;AAAA,EACjC;AAAA,EACA,+BAA+B;AAC7B,WAAO,oCAAC,oCAA+B;AAAA,EACzC;AAAA,EACA,wBAAwB,QAAgB;AAEtC,QAAI,CAAC,QAAQ;AACX,aAAO,oCAAC,6BAA0B,UAAS,UAAS;AAAA,IACtD;AAEA,UAAM,gBAAgB,OAAO,SAAS,UAAU;AAChD,UAAM,aAAa,OAAO,cAAc;AAExC,WACE,oCAAC,OAAI,gBAAe,iBAAgB,OAAM,UACxC,oCAAC,OAAI,eAAc,SACjB,oCAAC,YAAK,2BAA0B,GAChC,oCAAC,QAAK,MAAI,QAAE,eAAc,GAAC,GAC3B,oCAAC,YACE,kBAAkB,IAAI,WAAW,WAAU,mBAC9C,CACF,GACA,oCAAC,QAAK,SAAS,GAAG,YAAwB,OAAO,OAAO,CAC1D;AAAA,EAEJ;AAAA,EACA,yBAAyB,QAAgB;AACvC,QAAI,OAAO,QAAQ,WAAW,GAAG;AAC/B,aAAO;AAAA,IACT;AAEA,QAAI,SAAS,SAAS,OAAO,QAAQ,MAAM;AAAA;AAAA;AAE3C,WAAO,QAAQ,QAAQ,CAAC,MAAM,UAAU;AACtC,gBAAU,GAAG,QAAQ,CAAC,OAAO,KAAK,KAAK;AAAA;AACvC,gBAAU,MAAM,KAAK,OAAO;AAAA;AAC5B,gBAAU,YAAY,KAAK,IAAI;AAAA;AAAA;AAAA,IACjC,CAAC;AAED,cAAU;AACV,WAAO;AAAA,EACT;AAAA,EACA,OAAO,KAAK,EAAE,MAAM,GAAU,CAAC,GAAmB;AAChD,UAAM,QAAQ,KAAK,IAAI;AAEvB,QAAI;AACF,YAAM,gBAAgB,MAAM,gBAAgB,WAAW,OAAO,KAAK;AAEnE,YAAM,SAAiB;AAAA,QACrB,SAAS;AAAA,QACT,YAAY,KAAK,IAAI,IAAI;AAAA,MAC3B;AAEA,YAAM;AAAA,QACJ,MAAM;AAAA,QACN,oBAAoB,KAAK,yBAAyB,MAAM;AAAA,QACxD,MAAM;AAAA,MACR;AAAA,IACF,SAAS,OAAY;AACnB,YAAM,SAAiB;AAAA,QACrB,SAAS,CAAC;AAAA,QACV,YAAY,KAAK,IAAI,IAAI;AAAA,MAC3B;AACA,YAAM;AAAA,QACJ,MAAM;AAAA,QACN,oBAAoB,wDAAwD,MAAM,OAAO;AAAA,QACzF,MAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -4,18 +4,19 @@ const DESCRIPTION = `- Built-in web search using DuckDuckGo
|
|
|
4
4
|
- Returns search result information formatted as search result blocks
|
|
5
5
|
|
|
6
6
|
Capabilities:
|
|
7
|
-
- Quick searches for general information
|
|
7
|
+
- Quick searches for general information in English
|
|
8
8
|
- Current events, news, and real-time data
|
|
9
9
|
- No authentication required
|
|
10
10
|
|
|
11
11
|
Limitations:
|
|
12
|
-
- Uses DuckDuckGo which
|
|
13
|
-
-
|
|
12
|
+
- Uses DuckDuckGo which has limited results for many queries
|
|
13
|
+
- Poor coverage for region-specific, non-English, or Chinese content
|
|
14
14
|
- Cannot bypass bot detection on restricted sites
|
|
15
15
|
|
|
16
16
|
Usage notes:
|
|
17
17
|
- Search queries should be specific and well-targeted for best results
|
|
18
|
-
- If
|
|
18
|
+
- IMPORTANT: If MCP search tools are available in <available-deferred-tools> (e.g. mcp__BrightData__search_engine), use ToolSearch to load them and prefer them \u2014 especially for non-English, regional, or specialized content where DuckDuckGo has poor coverage
|
|
19
|
+
- Only use this built-in search when no MCP search tools are available`;
|
|
19
20
|
export {
|
|
20
21
|
DESCRIPTION,
|
|
21
22
|
TOOL_NAME_FOR_PROMPT
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/tools/WebSearchTool/prompt.ts"],
|
|
4
|
-
"sourcesContent": ["export const TOOL_NAME_FOR_PROMPT = 'WebSearch'\nexport const DESCRIPTION = `- Built-in web search using DuckDuckGo\n- Provides up-to-date information for current events and recent data\n- Returns search result information formatted as search result blocks\n\nCapabilities:\n- Quick searches for general information\n- Current events, news, and real-time data\n- No authentication required\n\nLimitations:\n- Uses DuckDuckGo which
|
|
5
|
-
"mappings": "AAAO,MAAM,uBAAuB;AAC7B,MAAM,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;",
|
|
4
|
+
"sourcesContent": ["export const TOOL_NAME_FOR_PROMPT = 'WebSearch'\nexport const DESCRIPTION = `- Built-in web search using DuckDuckGo\n- Provides up-to-date information for current events and recent data\n- Returns search result information formatted as search result blocks\n\nCapabilities:\n- Quick searches for general information in English\n- Current events, news, and real-time data\n- No authentication required\n\nLimitations:\n- Uses DuckDuckGo which has limited results for many queries\n- Poor coverage for region-specific, non-English, or Chinese content\n- Cannot bypass bot detection on restricted sites\n\nUsage notes:\n- Search queries should be specific and well-targeted for best results\n- IMPORTANT: If MCP search tools are available in <available-deferred-tools> (e.g. mcp__BrightData__search_engine), use ToolSearch to load them and prefer them \u2014 especially for non-English, regional, or specialized content where DuckDuckGo has poor coverage\n- Only use this built-in search when no MCP search tools are available`\n"],
|
|
5
|
+
"mappings": "AAAO,MAAM,uBAAuB;AAC7B,MAAM,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|