@shareai-lab/kode 1.1.12 → 1.1.13
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/cli.js +44 -23
- package/dist/ProjectOnboarding.js +99 -0
- package/dist/ProjectOnboarding.js.map +7 -0
- package/dist/Tool.js +1 -0
- package/dist/Tool.js.map +7 -0
- package/dist/commands/agents.js +2087 -0
- package/dist/commands/agents.js.map +7 -0
- package/dist/commands/approvedTools.js +36 -0
- package/dist/commands/approvedTools.js.map +7 -0
- package/dist/commands/bug.js +21 -0
- package/dist/commands/bug.js.map +7 -0
- package/dist/commands/clear.js +37 -0
- package/dist/commands/clear.js.map +7 -0
- package/dist/commands/compact.js +104 -0
- package/dist/commands/compact.js.map +7 -0
- package/dist/commands/config.js +20 -0
- package/dist/commands/config.js.map +7 -0
- package/dist/commands/cost.js +19 -0
- package/dist/commands/cost.js.map +7 -0
- package/dist/commands/ctx_viz.js +152 -0
- package/dist/commands/ctx_viz.js.map +7 -0
- package/dist/commands/doctor.js +25 -0
- package/dist/commands/doctor.js.map +7 -0
- package/dist/commands/help.js +20 -0
- package/dist/commands/help.js.map +7 -0
- package/dist/commands/init.js +38 -0
- package/dist/commands/init.js.map +7 -0
- package/dist/commands/listen.js +37 -0
- package/dist/commands/listen.js.map +7 -0
- package/dist/commands/login.js +37 -0
- package/dist/commands/login.js.map +7 -0
- package/dist/commands/logout.js +33 -0
- package/dist/commands/logout.js.map +7 -0
- package/dist/commands/mcp.js +34 -0
- package/dist/commands/mcp.js.map +7 -0
- package/dist/commands/model.js +41 -0
- package/dist/commands/model.js.map +7 -0
- package/dist/commands/modelstatus.js +21 -0
- package/dist/commands/modelstatus.js.map +7 -0
- package/dist/commands/onboarding.js +36 -0
- package/dist/commands/onboarding.js.map +7 -0
- package/dist/commands/pr_comments.js +61 -0
- package/dist/commands/pr_comments.js.map +7 -0
- package/dist/commands/refreshCommands.js +37 -0
- package/dist/commands/refreshCommands.js.map +7 -0
- package/dist/commands/release-notes.js +30 -0
- package/dist/commands/release-notes.js.map +7 -0
- package/dist/commands/resume.js +35 -0
- package/dist/commands/resume.js.map +7 -0
- package/dist/commands/review.js +51 -0
- package/dist/commands/review.js.map +7 -0
- package/dist/commands/terminalSetup.js +163 -0
- package/dist/commands/terminalSetup.js.map +7 -0
- package/dist/commands.js +84 -0
- package/dist/commands.js.map +7 -0
- package/dist/components/ApproveApiKey.js +74 -0
- package/dist/components/ApproveApiKey.js.map +7 -0
- package/dist/components/AsciiLogo.js +12 -0
- package/dist/components/AsciiLogo.js.map +7 -0
- package/dist/components/AutoUpdater.js +74 -0
- package/dist/components/AutoUpdater.js.map +7 -0
- package/dist/components/Bug.js +147 -0
- package/dist/components/Bug.js.map +7 -0
- package/dist/components/Config.js +166 -0
- package/dist/components/Config.js.map +7 -0
- package/dist/components/ConsoleOAuthFlow.js +188 -0
- package/dist/components/ConsoleOAuthFlow.js.map +7 -0
- package/dist/components/Cost.js +13 -0
- package/dist/components/Cost.js.map +7 -0
- package/dist/components/CostThresholdDialog.js +38 -0
- package/dist/components/CostThresholdDialog.js.map +7 -0
- package/dist/components/CustomSelect/option-map.js +32 -0
- package/dist/components/CustomSelect/option-map.js.map +7 -0
- package/dist/components/CustomSelect/select-option.js +34 -0
- package/dist/components/CustomSelect/select-option.js.map +7 -0
- package/dist/components/CustomSelect/select.js +64 -0
- package/dist/components/CustomSelect/select.js.map +7 -0
- package/dist/components/CustomSelect/theme.js +1 -0
- package/dist/components/CustomSelect/theme.js.map +7 -0
- package/dist/components/CustomSelect/use-select-state.js +220 -0
- package/dist/components/CustomSelect/use-select-state.js.map +7 -0
- package/dist/components/CustomSelect/use-select.js +21 -0
- package/dist/components/CustomSelect/use-select.js.map +7 -0
- package/dist/components/FallbackToolUseRejectedMessage.js +11 -0
- package/dist/components/FallbackToolUseRejectedMessage.js.map +7 -0
- package/dist/components/FileEditToolUpdatedMessage.js +31 -0
- package/dist/components/FileEditToolUpdatedMessage.js.map +7 -0
- package/dist/components/Help.js +41 -0
- package/dist/components/Help.js.map +7 -0
- package/dist/components/HighlightedCode.js +30 -0
- package/dist/components/HighlightedCode.js.map +7 -0
- package/dist/components/InvalidConfigDialog.js +83 -0
- package/dist/components/InvalidConfigDialog.js.map +7 -0
- package/dist/components/Link.js +18 -0
- package/dist/components/Link.js.map +7 -0
- package/dist/components/LogSelector.js +50 -0
- package/dist/components/LogSelector.js.map +7 -0
- package/dist/components/Logo.js +89 -0
- package/dist/components/Logo.js.map +7 -0
- package/dist/components/MCPServerApprovalDialog.js +79 -0
- package/dist/components/MCPServerApprovalDialog.js.map +7 -0
- package/dist/components/MCPServerDialogCopy.js +11 -0
- package/dist/components/MCPServerDialogCopy.js.map +7 -0
- package/dist/components/MCPServerMultiselectDialog.js +80 -0
- package/dist/components/MCPServerMultiselectDialog.js.map +7 -0
- package/dist/components/Message.js +146 -0
- package/dist/components/Message.js.map +7 -0
- package/dist/components/MessageResponse.js +9 -0
- package/dist/components/MessageResponse.js.map +7 -0
- package/dist/components/MessageSelector.js +133 -0
- package/dist/components/MessageSelector.js.map +7 -0
- package/dist/components/ModeIndicator.js +38 -0
- package/dist/components/ModeIndicator.js.map +7 -0
- package/dist/components/ModelConfig.js +208 -0
- package/dist/components/ModelConfig.js.map +7 -0
- package/dist/components/ModelListManager.js +140 -0
- package/dist/components/ModelListManager.js.map +7 -0
- package/dist/components/ModelSelector.js +1985 -0
- package/dist/components/ModelSelector.js.map +7 -0
- package/dist/components/ModelStatusDisplay.js +87 -0
- package/dist/components/ModelStatusDisplay.js.map +7 -0
- package/dist/components/Onboarding.js +153 -0
- package/dist/components/Onboarding.js.map +7 -0
- package/dist/components/PressEnterToContinue.js +10 -0
- package/dist/components/PressEnterToContinue.js.map +7 -0
- package/dist/components/PromptInput.js +501 -0
- package/dist/components/PromptInput.js.map +7 -0
- package/dist/components/SentryErrorBoundary.js +27 -0
- package/dist/components/SentryErrorBoundary.js.map +7 -0
- package/dist/components/Spinner.js +101 -0
- package/dist/components/Spinner.js.map +7 -0
- package/dist/components/StickerRequestForm.js +7 -0
- package/dist/components/StickerRequestForm.js.map +7 -0
- package/dist/components/StructuredDiff.js +148 -0
- package/dist/components/StructuredDiff.js.map +7 -0
- package/dist/components/TextInput.js +100 -0
- package/dist/components/TextInput.js.map +7 -0
- package/dist/components/TodoItem.js +35 -0
- package/dist/components/TodoItem.js.map +7 -0
- package/dist/components/TokenWarning.js +19 -0
- package/dist/components/TokenWarning.js.map +7 -0
- package/dist/components/ToolUseLoader.js +24 -0
- package/dist/components/ToolUseLoader.js.map +7 -0
- package/dist/components/TrustDialog.js +76 -0
- package/dist/components/TrustDialog.js.map +7 -0
- package/dist/components/binary-feedback/BinaryFeedback.js +50 -0
- package/dist/components/binary-feedback/BinaryFeedback.js.map +7 -0
- package/dist/components/binary-feedback/BinaryFeedbackOption.js +94 -0
- package/dist/components/binary-feedback/BinaryFeedbackOption.js.map +7 -0
- package/dist/components/binary-feedback/BinaryFeedbackView.js +139 -0
- package/dist/components/binary-feedback/BinaryFeedbackView.js.map +7 -0
- package/dist/components/binary-feedback/utils.js +161 -0
- package/dist/components/binary-feedback/utils.js.map +7 -0
- package/dist/components/messages/AssistantBashOutputMessage.js +23 -0
- package/dist/components/messages/AssistantBashOutputMessage.js.map +7 -0
- package/dist/components/messages/AssistantLocalCommandOutputMessage.js +36 -0
- package/dist/components/messages/AssistantLocalCommandOutputMessage.js.map +7 -0
- package/dist/components/messages/AssistantRedactedThinkingMessage.js +12 -0
- package/dist/components/messages/AssistantRedactedThinkingMessage.js.map +7 -0
- package/dist/components/messages/AssistantTextMessage.js +78 -0
- package/dist/components/messages/AssistantTextMessage.js.map +7 -0
- package/dist/components/messages/AssistantThinkingMessage.js +27 -0
- package/dist/components/messages/AssistantThinkingMessage.js.map +7 -0
- package/dist/components/messages/AssistantToolUseMessage.js +91 -0
- package/dist/components/messages/AssistantToolUseMessage.js.map +7 -0
- package/dist/components/messages/TaskProgressMessage.js +11 -0
- package/dist/components/messages/TaskProgressMessage.js.map +7 -0
- package/dist/components/messages/TaskToolMessage.js +39 -0
- package/dist/components/messages/TaskToolMessage.js.map +7 -0
- package/dist/components/messages/UserBashInputMessage.js +18 -0
- package/dist/components/messages/UserBashInputMessage.js.map +7 -0
- package/dist/components/messages/UserCommandMessage.js +20 -0
- package/dist/components/messages/UserCommandMessage.js.map +7 -0
- package/dist/components/messages/UserKodingInputMessage.js +18 -0
- package/dist/components/messages/UserKodingInputMessage.js.map +7 -0
- package/dist/components/messages/UserPromptMessage.js +20 -0
- package/dist/components/messages/UserPromptMessage.js.map +7 -0
- package/dist/components/messages/UserTextMessage.js +25 -0
- package/dist/components/messages/UserTextMessage.js.map +7 -0
- package/dist/components/messages/UserToolResultMessage/UserToolCanceledMessage.js +10 -0
- package/dist/components/messages/UserToolResultMessage/UserToolCanceledMessage.js.map +7 -0
- package/dist/components/messages/UserToolResultMessage/UserToolErrorMessage.js +15 -0
- package/dist/components/messages/UserToolResultMessage/UserToolErrorMessage.js.map +7 -0
- package/dist/components/messages/UserToolResultMessage/UserToolRejectMessage.js +25 -0
- package/dist/components/messages/UserToolResultMessage/UserToolRejectMessage.js.map +7 -0
- package/dist/components/messages/UserToolResultMessage/UserToolResultMessage.js +47 -0
- package/dist/components/messages/UserToolResultMessage/UserToolResultMessage.js.map +7 -0
- package/dist/components/messages/UserToolResultMessage/UserToolSuccessMessage.js +23 -0
- package/dist/components/messages/UserToolResultMessage/UserToolSuccessMessage.js.map +7 -0
- package/dist/components/messages/UserToolResultMessage/utils.js +42 -0
- package/dist/components/messages/UserToolResultMessage/utils.js.map +7 -0
- package/dist/components/permissions/BashPermissionRequest/BashPermissionRequest.js +112 -0
- package/dist/components/permissions/BashPermissionRequest/BashPermissionRequest.js.map +7 -0
- package/dist/components/permissions/FallbackPermissionRequest.js +131 -0
- package/dist/components/permissions/FallbackPermissionRequest.js.map +7 -0
- package/dist/components/permissions/FileEditPermissionRequest/FileEditPermissionRequest.js +159 -0
- package/dist/components/permissions/FileEditPermissionRequest/FileEditPermissionRequest.js.map +7 -0
- package/dist/components/permissions/FileEditPermissionRequest/FileEditToolDiff.js +58 -0
- package/dist/components/permissions/FileEditPermissionRequest/FileEditToolDiff.js.map +7 -0
- package/dist/components/permissions/FileWritePermissionRequest/FileWritePermissionRequest.js +153 -0
- package/dist/components/permissions/FileWritePermissionRequest/FileWritePermissionRequest.js.map +7 -0
- package/dist/components/permissions/FileWritePermissionRequest/FileWriteToolDiff.js +70 -0
- package/dist/components/permissions/FileWritePermissionRequest/FileWriteToolDiff.js.map +7 -0
- package/dist/components/permissions/FilesystemPermissionRequest/FilesystemPermissionRequest.js +212 -0
- package/dist/components/permissions/FilesystemPermissionRequest/FilesystemPermissionRequest.js.map +7 -0
- package/dist/components/permissions/PermissionRequest.js +70 -0
- package/dist/components/permissions/PermissionRequest.js.map +7 -0
- package/dist/components/permissions/PermissionRequestTitle.js +52 -0
- package/dist/components/permissions/PermissionRequestTitle.js.map +7 -0
- package/dist/components/permissions/hooks.js +28 -0
- package/dist/components/permissions/hooks.js.map +7 -0
- package/dist/components/permissions/toolUseOptions.js +46 -0
- package/dist/components/permissions/toolUseOptions.js.map +7 -0
- package/dist/components/permissions/utils.js +21 -0
- package/dist/components/permissions/utils.js.map +7 -0
- package/dist/constants/betas.js +11 -0
- package/dist/constants/betas.js.map +7 -0
- package/dist/constants/claude-asterisk-ascii-art.js +242 -0
- package/dist/constants/claude-asterisk-ascii-art.js.map +7 -0
- package/dist/constants/figures.js +6 -0
- package/dist/constants/figures.js.map +7 -0
- package/dist/constants/keys.js +7 -0
- package/dist/constants/keys.js.map +7 -0
- package/dist/constants/macros.js +13 -0
- package/dist/constants/macros.js.map +7 -0
- package/dist/constants/modelCapabilities.js +154 -0
- package/dist/constants/modelCapabilities.js.map +7 -0
- package/dist/constants/models.js +1029 -0
- package/dist/constants/models.js.map +7 -0
- package/dist/constants/oauth.js +18 -0
- package/dist/constants/oauth.js.map +7 -0
- package/dist/constants/product.js +26 -0
- package/dist/constants/product.js.map +7 -0
- package/dist/constants/prompts.js +168 -0
- package/dist/constants/prompts.js.map +7 -0
- package/dist/constants/releaseNotes.js +9 -0
- package/dist/constants/releaseNotes.js.map +7 -0
- package/dist/context/PermissionContext.js +111 -0
- package/dist/context/PermissionContext.js.map +7 -0
- package/dist/context.js +259 -0
- package/dist/context.js.map +7 -0
- package/dist/cost-tracker.js +76 -0
- package/dist/cost-tracker.js.map +7 -0
- package/dist/entrypoints/cli.js +1101 -0
- package/dist/entrypoints/cli.js.map +7 -0
- package/dist/entrypoints/mcp.js +150 -0
- package/dist/entrypoints/mcp.js.map +7 -0
- package/dist/history.js +25 -0
- package/dist/history.js.map +7 -0
- package/dist/hooks/useApiKeyVerification.js +12 -0
- package/dist/hooks/useApiKeyVerification.js.map +7 -0
- package/dist/hooks/useArrowKeyHistory.js +50 -0
- package/dist/hooks/useArrowKeyHistory.js.map +7 -0
- package/dist/hooks/useCanUseTool.js +112 -0
- package/dist/hooks/useCanUseTool.js.map +7 -0
- package/dist/hooks/useCancelRequest.js +30 -0
- package/dist/hooks/useCancelRequest.js.map +7 -0
- package/dist/hooks/useDoublePress.js +31 -0
- package/dist/hooks/useDoublePress.js.map +7 -0
- package/dist/hooks/useExitOnCtrlCD.js +26 -0
- package/dist/hooks/useExitOnCtrlCD.js.map +7 -0
- package/dist/hooks/useInterval.js +18 -0
- package/dist/hooks/useInterval.js.map +7 -0
- package/dist/hooks/useLogMessages.js +14 -0
- package/dist/hooks/useLogMessages.js.map +7 -0
- package/dist/hooks/useLogStartupTime.js +15 -0
- package/dist/hooks/useLogStartupTime.js.map +7 -0
- package/dist/hooks/useNotifyAfterTimeout.js +42 -0
- package/dist/hooks/useNotifyAfterTimeout.js.map +7 -0
- package/dist/hooks/usePermissionRequestLogging.js +28 -0
- package/dist/hooks/usePermissionRequestLogging.js.map +7 -0
- package/dist/hooks/useTerminalSize.js +38 -0
- package/dist/hooks/useTerminalSize.js.map +7 -0
- package/dist/hooks/useTextInput.js +250 -0
- package/dist/hooks/useTextInput.js.map +7 -0
- package/dist/hooks/useUnifiedCompletion.js +929 -0
- package/dist/hooks/useUnifiedCompletion.js.map +7 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +7 -0
- package/dist/messages.js +33 -0
- package/dist/messages.js.map +7 -0
- package/dist/package.json +1 -0
- package/dist/permissions.js +194 -0
- package/dist/permissions.js.map +7 -0
- package/dist/query.js +492 -0
- package/dist/query.js.map +7 -0
- package/dist/screens/ConfigureNpmPrefix.js +128 -0
- package/dist/screens/ConfigureNpmPrefix.js.map +7 -0
- package/dist/screens/Doctor.js +143 -0
- package/dist/screens/Doctor.js.map +7 -0
- package/dist/screens/LogList.js +55 -0
- package/dist/screens/LogList.js.map +7 -0
- package/dist/screens/REPL.js +596 -0
- package/dist/screens/REPL.js.map +7 -0
- package/dist/screens/ResumeConversation.js +56 -0
- package/dist/screens/ResumeConversation.js.map +7 -0
- package/dist/services/adapters/base.js +29 -0
- package/dist/services/adapters/base.js.map +7 -0
- package/dist/services/adapters/chatCompletions.js +69 -0
- package/dist/services/adapters/chatCompletions.js.map +7 -0
- package/dist/services/adapters/responsesAPI.js +126 -0
- package/dist/services/adapters/responsesAPI.js.map +7 -0
- package/dist/services/browserMocks.js +48 -0
- package/dist/services/browserMocks.js.map +7 -0
- package/dist/services/claude.js +1605 -0
- package/dist/services/claude.js.map +7 -0
- package/dist/services/customCommands.js +359 -0
- package/dist/services/customCommands.js.map +7 -0
- package/dist/services/fileFreshness.js +280 -0
- package/dist/services/fileFreshness.js.map +7 -0
- package/dist/services/gpt5ConnectionTest.js +248 -0
- package/dist/services/gpt5ConnectionTest.js.map +7 -0
- package/dist/services/mcpClient.js +435 -0
- package/dist/services/mcpClient.js.map +7 -0
- package/dist/services/mcpServerApproval.js +55 -0
- package/dist/services/mcpServerApproval.js.map +7 -0
- package/dist/services/mentionProcessor.js +200 -0
- package/dist/services/mentionProcessor.js.map +7 -0
- package/dist/services/modelAdapterFactory.js +47 -0
- package/dist/services/modelAdapterFactory.js.map +7 -0
- package/dist/services/notifier.js +35 -0
- package/dist/services/notifier.js.map +7 -0
- package/dist/services/oauth.js +259 -0
- package/dist/services/oauth.js.map +7 -0
- package/dist/services/openai.js +998 -0
- package/dist/services/openai.js.map +7 -0
- package/dist/services/responseStateManager.js +68 -0
- package/dist/services/responseStateManager.js.map +7 -0
- package/dist/services/sentry.js +9 -0
- package/dist/services/sentry.js.map +7 -0
- package/dist/services/statsig.js +112 -0
- package/dist/services/statsig.js.map +7 -0
- package/dist/services/statsigStorage.js +75 -0
- package/dist/services/statsigStorage.js.map +7 -0
- package/dist/services/systemReminder.js +353 -0
- package/dist/services/systemReminder.js.map +7 -0
- package/dist/services/vcr.js +133 -0
- package/dist/services/vcr.js.map +7 -0
- package/dist/test/testAdapters.js +88 -0
- package/dist/test/testAdapters.js.map +1 -0
- package/dist/tools/ArchitectTool/ArchitectTool.js +119 -0
- package/dist/tools/ArchitectTool/ArchitectTool.js.map +7 -0
- package/dist/tools/ArchitectTool/prompt.js +18 -0
- package/dist/tools/ArchitectTool/prompt.js.map +7 -0
- package/dist/tools/AskExpertModelTool/AskExpertModelTool.js +423 -0
- package/dist/tools/AskExpertModelTool/AskExpertModelTool.js.map +7 -0
- package/dist/tools/BashTool/BashTool.js +188 -0
- package/dist/tools/BashTool/BashTool.js.map +7 -0
- package/dist/tools/BashTool/BashToolResultMessage.js +21 -0
- package/dist/tools/BashTool/BashToolResultMessage.js.map +7 -0
- package/dist/tools/BashTool/OutputLine.js +30 -0
- package/dist/tools/BashTool/OutputLine.js.map +7 -0
- package/dist/tools/BashTool/prompt.js +179 -0
- package/dist/tools/BashTool/prompt.js.map +7 -0
- package/dist/tools/BashTool/utils.js +51 -0
- package/dist/tools/BashTool/utils.js.map +7 -0
- package/dist/tools/FileEditTool/FileEditTool.js +228 -0
- package/dist/tools/FileEditTool/FileEditTool.js.map +7 -0
- package/dist/tools/FileEditTool/prompt.js +54 -0
- package/dist/tools/FileEditTool/prompt.js.map +7 -0
- package/dist/tools/FileEditTool/utils.js +42 -0
- package/dist/tools/FileEditTool/utils.js.map +7 -0
- package/dist/tools/FileReadTool/FileReadTool.js +272 -0
- package/dist/tools/FileReadTool/FileReadTool.js.map +7 -0
- package/dist/tools/FileReadTool/prompt.js +10 -0
- package/dist/tools/FileReadTool/prompt.js.map +7 -0
- package/dist/tools/FileWriteTool/FileWriteTool.js +204 -0
- package/dist/tools/FileWriteTool/FileWriteTool.js.map +7 -0
- package/dist/tools/FileWriteTool/prompt.js +14 -0
- package/dist/tools/FileWriteTool/prompt.js.map +7 -0
- package/dist/tools/GlobTool/GlobTool.js +88 -0
- package/dist/tools/GlobTool/GlobTool.js.map +7 -0
- package/dist/tools/GlobTool/prompt.js +12 -0
- package/dist/tools/GlobTool/prompt.js.map +7 -0
- package/dist/tools/GrepTool/GrepTool.js +107 -0
- package/dist/tools/GrepTool/GrepTool.js.map +7 -0
- package/dist/tools/GrepTool/prompt.js +15 -0
- package/dist/tools/GrepTool/prompt.js.map +7 -0
- package/dist/tools/MCPTool/MCPTool.js +90 -0
- package/dist/tools/MCPTool/MCPTool.js.map +7 -0
- package/dist/tools/MCPTool/prompt.js +7 -0
- package/dist/tools/MCPTool/prompt.js.map +7 -0
- package/dist/tools/MemoryReadTool/MemoryReadTool.js +103 -0
- package/dist/tools/MemoryReadTool/MemoryReadTool.js.map +7 -0
- package/dist/tools/MemoryReadTool/prompt.js +7 -0
- package/dist/tools/MemoryReadTool/prompt.js.map +7 -0
- package/dist/tools/MemoryWriteTool/MemoryWriteTool.js +77 -0
- package/dist/tools/MemoryWriteTool/MemoryWriteTool.js.map +7 -0
- package/dist/tools/MemoryWriteTool/prompt.js +7 -0
- package/dist/tools/MemoryWriteTool/prompt.js.map +7 -0
- package/dist/tools/MultiEditTool/MultiEditTool.js +293 -0
- package/dist/tools/MultiEditTool/MultiEditTool.js.map +7 -0
- package/dist/tools/MultiEditTool/prompt.js +48 -0
- package/dist/tools/MultiEditTool/prompt.js.map +7 -0
- package/dist/tools/NotebookEditTool/NotebookEditTool.js +238 -0
- package/dist/tools/NotebookEditTool/NotebookEditTool.js.map +7 -0
- package/dist/tools/NotebookEditTool/prompt.js +7 -0
- package/dist/tools/NotebookEditTool/prompt.js.map +7 -0
- package/dist/tools/NotebookReadTool/NotebookReadTool.js +212 -0
- package/dist/tools/NotebookReadTool/NotebookReadTool.js.map +7 -0
- package/dist/tools/NotebookReadTool/prompt.js +7 -0
- package/dist/tools/NotebookReadTool/prompt.js.map +7 -0
- package/dist/tools/StickerRequestTool/StickerRequestTool.js +86 -0
- package/dist/tools/StickerRequestTool/StickerRequestTool.js.map +7 -0
- package/dist/tools/StickerRequestTool/prompt.js +23 -0
- package/dist/tools/StickerRequestTool/prompt.js.map +7 -0
- package/dist/tools/TaskTool/TaskTool.js +308 -0
- package/dist/tools/TaskTool/TaskTool.js.map +7 -0
- package/dist/tools/TaskTool/constants.js +5 -0
- package/dist/tools/TaskTool/constants.js.map +7 -0
- package/dist/tools/TaskTool/prompt.js +82 -0
- package/dist/tools/TaskTool/prompt.js.map +7 -0
- package/dist/tools/ThinkTool/ThinkTool.js +48 -0
- package/dist/tools/ThinkTool/ThinkTool.js.map +7 -0
- package/dist/tools/ThinkTool/prompt.js +16 -0
- package/dist/tools/ThinkTool/prompt.js.map +7 -0
- package/dist/tools/TodoWriteTool/TodoWriteTool.js +216 -0
- package/dist/tools/TodoWriteTool/TodoWriteTool.js.map +7 -0
- package/dist/tools/TodoWriteTool/prompt.js +66 -0
- package/dist/tools/TodoWriteTool/prompt.js.map +7 -0
- package/dist/tools/URLFetcherTool/URLFetcherTool.js +137 -0
- package/dist/tools/URLFetcherTool/URLFetcherTool.js.map +7 -0
- package/dist/tools/URLFetcherTool/cache.js +45 -0
- package/dist/tools/URLFetcherTool/cache.js.map +7 -0
- package/dist/tools/URLFetcherTool/htmlToMarkdown.js +42 -0
- package/dist/tools/URLFetcherTool/htmlToMarkdown.js.map +7 -0
- package/dist/tools/URLFetcherTool/prompt.js +22 -0
- package/dist/tools/URLFetcherTool/prompt.js.map +7 -0
- package/dist/tools/WebSearchTool/WebSearchTool.js +86 -0
- package/dist/tools/WebSearchTool/WebSearchTool.js.map +7 -0
- package/dist/tools/WebSearchTool/prompt.js +17 -0
- package/dist/tools/WebSearchTool/prompt.js.map +7 -0
- package/dist/tools/WebSearchTool/searchProviders.js +48 -0
- package/dist/tools/WebSearchTool/searchProviders.js.map +7 -0
- package/dist/tools/lsTool/lsTool.js +201 -0
- package/dist/tools/lsTool/lsTool.js.map +7 -0
- package/dist/tools/lsTool/prompt.js +5 -0
- package/dist/tools/lsTool/prompt.js.map +7 -0
- package/dist/tools.js +64 -0
- package/dist/tools.js.map +7 -0
- package/dist/types/PermissionMode.js +82 -0
- package/dist/types/PermissionMode.js.map +7 -0
- package/dist/types/RequestContext.js +47 -0
- package/dist/types/RequestContext.js.map +7 -0
- package/dist/types/common.d.js +1 -0
- package/dist/types/common.d.js.map +7 -0
- package/dist/types/conversation.js +1 -0
- package/dist/types/conversation.js.map +7 -0
- package/dist/types/logs.js +1 -0
- package/dist/types/logs.js.map +7 -0
- package/dist/types/modelCapabilities.js +1 -0
- package/dist/types/modelCapabilities.js.map +7 -0
- package/dist/types/notebook.js +1 -0
- package/dist/types/notebook.js.map +7 -0
- package/dist/utils/Cursor.js +313 -0
- package/dist/utils/Cursor.js.map +7 -0
- package/dist/utils/PersistentShell.js +382 -0
- package/dist/utils/PersistentShell.js.map +7 -0
- package/dist/utils/advancedFuzzyMatcher.js +206 -0
- package/dist/utils/advancedFuzzyMatcher.js.map +7 -0
- package/dist/utils/agentLoader.js +199 -0
- package/dist/utils/agentLoader.js.map +7 -0
- package/dist/utils/agentStorage.js +59 -0
- package/dist/utils/agentStorage.js.map +7 -0
- package/dist/utils/array.js +7 -0
- package/dist/utils/array.js.map +7 -0
- package/dist/utils/ask.js +77 -0
- package/dist/utils/ask.js.map +7 -0
- package/dist/utils/auth.js +11 -0
- package/dist/utils/auth.js.map +7 -0
- package/dist/utils/autoCompactCore.js +149 -0
- package/dist/utils/autoCompactCore.js.map +7 -0
- package/dist/utils/autoUpdater.js +362 -0
- package/dist/utils/autoUpdater.js.map +7 -0
- package/dist/utils/betas.js +21 -0
- package/dist/utils/betas.js.map +7 -0
- package/dist/utils/browser.js +15 -0
- package/dist/utils/browser.js.map +7 -0
- package/dist/utils/cleanup.js +54 -0
- package/dist/utils/cleanup.js.map +7 -0
- package/dist/utils/commands.js +207 -0
- package/dist/utils/commands.js.map +7 -0
- package/dist/utils/commonUnixCommands.js +687 -0
- package/dist/utils/commonUnixCommands.js.map +7 -0
- package/dist/utils/config.js +655 -0
- package/dist/utils/config.js.map +7 -0
- package/dist/utils/conversationRecovery.js +35 -0
- package/dist/utils/conversationRecovery.js.map +7 -0
- package/dist/utils/debugLogger.js +891 -0
- package/dist/utils/debugLogger.js.map +7 -0
- package/dist/utils/diff.js +32 -0
- package/dist/utils/diff.js.map +7 -0
- package/dist/utils/env.js +44 -0
- package/dist/utils/env.js.map +7 -0
- package/dist/utils/errors.js +23 -0
- package/dist/utils/errors.js.map +7 -0
- package/dist/utils/exampleCommands.js +80 -0
- package/dist/utils/exampleCommands.js.map +7 -0
- package/dist/utils/execFileNoThrow.js +44 -0
- package/dist/utils/execFileNoThrow.js.map +7 -0
- package/dist/utils/expertChatStorage.js +78 -0
- package/dist/utils/expertChatStorage.js.map +7 -0
- package/dist/utils/file.js +282 -0
- package/dist/utils/file.js.map +7 -0
- package/dist/utils/fileRecoveryCore.js +41 -0
- package/dist/utils/fileRecoveryCore.js.map +7 -0
- package/dist/utils/format.js +41 -0
- package/dist/utils/format.js.map +7 -0
- package/dist/utils/fuzzyMatcher.js +252 -0
- package/dist/utils/fuzzyMatcher.js.map +7 -0
- package/dist/utils/generators.js +46 -0
- package/dist/utils/generators.js.map +7 -0
- package/dist/utils/git.js +83 -0
- package/dist/utils/git.js.map +7 -0
- package/dist/utils/globalLogger.js +54 -0
- package/dist/utils/globalLogger.js.map +7 -0
- package/dist/utils/http.js +7 -0
- package/dist/utils/http.js.map +7 -0
- package/dist/utils/imagePaste.js +29 -0
- package/dist/utils/imagePaste.js.map +7 -0
- package/dist/utils/json.js +16 -0
- package/dist/utils/json.js.map +7 -0
- package/dist/utils/log.js +298 -0
- package/dist/utils/log.js.map +7 -0
- package/dist/utils/markdown.js +187 -0
- package/dist/utils/markdown.js.map +7 -0
- package/dist/utils/messageContextManager.js +195 -0
- package/dist/utils/messageContextManager.js.map +7 -0
- package/dist/utils/messages.js +633 -0
- package/dist/utils/messages.js.map +7 -0
- package/dist/utils/model.js +687 -0
- package/dist/utils/model.js.map +7 -0
- package/dist/utils/permissions/filesystem.js +80 -0
- package/dist/utils/permissions/filesystem.js.map +7 -0
- package/dist/utils/responseState.js +20 -0
- package/dist/utils/responseState.js.map +7 -0
- package/dist/utils/ripgrep.js +131 -0
- package/dist/utils/ripgrep.js.map +7 -0
- package/dist/utils/secureFile.js +483 -0
- package/dist/utils/secureFile.js.map +7 -0
- package/dist/utils/sessionState.js +31 -0
- package/dist/utils/sessionState.js.map +7 -0
- package/dist/utils/state.js +24 -0
- package/dist/utils/state.js.map +7 -0
- package/dist/utils/style.js +31 -0
- package/dist/utils/style.js.map +7 -0
- package/dist/utils/terminal.js +43 -0
- package/dist/utils/terminal.js.map +7 -0
- package/dist/utils/theme.js +102 -0
- package/dist/utils/theme.js.map +7 -0
- package/dist/utils/thinking.js +103 -0
- package/dist/utils/thinking.js.map +7 -0
- package/dist/utils/todoStorage.js +291 -0
- package/dist/utils/todoStorage.js.map +7 -0
- package/dist/utils/tokens.js +30 -0
- package/dist/utils/tokens.js.map +7 -0
- package/dist/utils/toolExecutionController.js +109 -0
- package/dist/utils/toolExecutionController.js.map +7 -0
- package/dist/utils/unaryLogging.js +14 -0
- package/dist/utils/unaryLogging.js.map +7 -0
- package/dist/utils/user.js +40 -0
- package/dist/utils/user.js.map +7 -0
- package/dist/utils/validate.js +132 -0
- package/dist/utils/validate.js.map +7 -0
- package/dist/yoga.wasm +0 -0
- package/package.json +28 -7
- package/src/Tool.ts +4 -3
- package/src/commands/agents.tsx +10 -4
- package/src/components/messages/AssistantToolUseMessage.tsx +5 -6
- package/src/constants/macros.ts +5 -2
- package/src/entrypoints/cli.tsx +38 -19
- package/src/entrypoints/mcp.ts +1 -2
- package/src/hooks/useDoublePress.ts +0 -1
- package/src/hooks/useTextInput.ts +4 -5
- package/src/hooks/useUnifiedCompletion.ts +2 -2
- package/src/index.ts +34 -0
- package/src/query.ts +13 -8
- package/src/screens/Doctor.tsx +1 -1
- package/src/screens/REPL.tsx +13 -9
- package/src/services/openai.ts +25 -4
- package/src/tools/ArchitectTool/ArchitectTool.tsx +18 -5
- package/src/tools/AskExpertModelTool/AskExpertModelTool.tsx +21 -14
- package/src/tools/FileEditTool/FileEditTool.tsx +6 -2
- package/src/tools/FileWriteTool/FileWriteTool.tsx +7 -3
- package/src/tools/MultiEditTool/MultiEditTool.tsx +26 -4
- package/src/tools/NotebookReadTool/NotebookReadTool.tsx +1 -1
- package/src/tools/StickerRequestTool/StickerRequestTool.tsx +28 -14
- package/src/tools/TaskTool/TaskTool.tsx +8 -36
- package/src/types/common.d.ts +2 -0
- package/src/utils/generators.ts +1 -1
- package/src/utils/messageContextManager.ts +5 -0
- package/src/utils/messages.tsx +8 -2
- package/src/utils/thinking.ts +1 -1
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import { statSync } from "node:fs";
|
|
2
|
+
import { Box, Text } from "ink";
|
|
3
|
+
import * as path from "node:path";
|
|
4
|
+
import { extname, relative } from "node:path";
|
|
5
|
+
import * as React from "react";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
import { FallbackToolUseRejectedMessage } from "../../components/FallbackToolUseRejectedMessage.js";
|
|
8
|
+
import { HighlightedCode } from "../../components/HighlightedCode.js";
|
|
9
|
+
import { getCwd } from "../../utils/state.js";
|
|
10
|
+
import {
|
|
11
|
+
addLineNumbers,
|
|
12
|
+
findSimilarFile,
|
|
13
|
+
normalizeFilePath,
|
|
14
|
+
readTextContent
|
|
15
|
+
} from "../../utils/file.js";
|
|
16
|
+
import { logError } from "../../utils/log.js";
|
|
17
|
+
import { getTheme } from "../../utils/theme.js";
|
|
18
|
+
import { emitReminderEvent } from "../../services/systemReminder.js";
|
|
19
|
+
import {
|
|
20
|
+
recordFileRead,
|
|
21
|
+
generateFileModificationReminder
|
|
22
|
+
} from "../../services/fileFreshness.js";
|
|
23
|
+
import { DESCRIPTION, PROMPT } from "./prompt.js";
|
|
24
|
+
import { hasReadPermission } from "../../utils/permissions/filesystem.js";
|
|
25
|
+
import { secureFileService } from "../../utils/secureFile.js";
|
|
26
|
+
const MAX_LINES_TO_RENDER = 5;
|
|
27
|
+
const MAX_OUTPUT_SIZE = 0.25 * 1024 * 1024;
|
|
28
|
+
const IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
29
|
+
".png",
|
|
30
|
+
".jpg",
|
|
31
|
+
".jpeg",
|
|
32
|
+
".gif",
|
|
33
|
+
".bmp",
|
|
34
|
+
".webp"
|
|
35
|
+
]);
|
|
36
|
+
const MAX_WIDTH = 2e3;
|
|
37
|
+
const MAX_HEIGHT = 2e3;
|
|
38
|
+
const MAX_IMAGE_SIZE = 3.75 * 1024 * 1024;
|
|
39
|
+
const inputSchema = z.strictObject({
|
|
40
|
+
file_path: z.string().describe("The absolute path to the file to read"),
|
|
41
|
+
offset: z.number().optional().describe(
|
|
42
|
+
"The line number to start reading from. Only provide if the file is too large to read at once"
|
|
43
|
+
),
|
|
44
|
+
limit: z.number().optional().describe(
|
|
45
|
+
"The number of lines to read. Only provide if the file is too large to read at once."
|
|
46
|
+
)
|
|
47
|
+
});
|
|
48
|
+
const FileReadTool = {
|
|
49
|
+
name: "View",
|
|
50
|
+
async description() {
|
|
51
|
+
return DESCRIPTION;
|
|
52
|
+
},
|
|
53
|
+
async prompt() {
|
|
54
|
+
return PROMPT;
|
|
55
|
+
},
|
|
56
|
+
inputSchema,
|
|
57
|
+
isReadOnly() {
|
|
58
|
+
return true;
|
|
59
|
+
},
|
|
60
|
+
isConcurrencySafe() {
|
|
61
|
+
return true;
|
|
62
|
+
},
|
|
63
|
+
userFacingName() {
|
|
64
|
+
return "Read";
|
|
65
|
+
},
|
|
66
|
+
async isEnabled() {
|
|
67
|
+
return true;
|
|
68
|
+
},
|
|
69
|
+
needsPermissions({ file_path }) {
|
|
70
|
+
return !hasReadPermission(file_path || getCwd());
|
|
71
|
+
},
|
|
72
|
+
renderToolUseMessage(input, { verbose }) {
|
|
73
|
+
const { file_path, ...rest } = input;
|
|
74
|
+
const entries = [
|
|
75
|
+
["file_path", verbose ? file_path : relative(getCwd(), file_path)],
|
|
76
|
+
...Object.entries(rest)
|
|
77
|
+
];
|
|
78
|
+
return entries.map(([key, value]) => `${key}: ${JSON.stringify(value)}`).join(", ");
|
|
79
|
+
},
|
|
80
|
+
renderToolResultMessage(output) {
|
|
81
|
+
const verbose = false;
|
|
82
|
+
switch (output.type) {
|
|
83
|
+
case "image":
|
|
84
|
+
return /* @__PURE__ */ React.createElement(Box, { justifyContent: "space-between", overflowX: "hidden", width: "100%" }, /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Text, null, "\xA0\xA0\u23BF \xA0"), /* @__PURE__ */ React.createElement(Text, null, "Read image")));
|
|
85
|
+
case "text": {
|
|
86
|
+
const { filePath, content, numLines } = output.file;
|
|
87
|
+
const contentWithFallback = content || "(No content)";
|
|
88
|
+
return /* @__PURE__ */ React.createElement(Box, { justifyContent: "space-between", overflowX: "hidden", width: "100%" }, /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Text, null, "\xA0\xA0\u23BF \xA0"), /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(
|
|
89
|
+
HighlightedCode,
|
|
90
|
+
{
|
|
91
|
+
code: verbose ? contentWithFallback : contentWithFallback.split("\n").slice(0, MAX_LINES_TO_RENDER).filter((_) => _.trim() !== "").join("\n"),
|
|
92
|
+
language: extname(filePath).slice(1)
|
|
93
|
+
}
|
|
94
|
+
), !verbose && numLines > MAX_LINES_TO_RENDER && /* @__PURE__ */ React.createElement(Text, { color: getTheme().secondaryText }, "... (+", numLines - MAX_LINES_TO_RENDER, " lines)"))));
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
renderToolUseRejectedMessage() {
|
|
99
|
+
return /* @__PURE__ */ React.createElement(FallbackToolUseRejectedMessage, null);
|
|
100
|
+
},
|
|
101
|
+
async validateInput({ file_path, offset, limit }) {
|
|
102
|
+
const fullFilePath = normalizeFilePath(file_path);
|
|
103
|
+
const fileCheck = secureFileService.safeGetFileInfo(fullFilePath);
|
|
104
|
+
if (!fileCheck.success) {
|
|
105
|
+
const similarFilename = findSimilarFile(fullFilePath);
|
|
106
|
+
let message = "File does not exist.";
|
|
107
|
+
if (similarFilename) {
|
|
108
|
+
message += ` Did you mean ${similarFilename}?`;
|
|
109
|
+
}
|
|
110
|
+
return {
|
|
111
|
+
result: false,
|
|
112
|
+
message
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
const stats = fileCheck.stats;
|
|
116
|
+
const fileSize = stats.size;
|
|
117
|
+
const ext = path.extname(fullFilePath).toLowerCase();
|
|
118
|
+
if (!IMAGE_EXTENSIONS.has(ext)) {
|
|
119
|
+
if (fileSize > MAX_OUTPUT_SIZE && !offset && !limit) {
|
|
120
|
+
return {
|
|
121
|
+
result: false,
|
|
122
|
+
message: formatFileSizeError(fileSize),
|
|
123
|
+
meta: { fileSize }
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return { result: true };
|
|
128
|
+
},
|
|
129
|
+
async *call({ file_path, offset = 1, limit = void 0 }, { readFileTimestamps }) {
|
|
130
|
+
const ext = path.extname(file_path).toLowerCase();
|
|
131
|
+
const fullFilePath = normalizeFilePath(file_path);
|
|
132
|
+
recordFileRead(fullFilePath);
|
|
133
|
+
emitReminderEvent("file:read", {
|
|
134
|
+
filePath: fullFilePath,
|
|
135
|
+
extension: ext,
|
|
136
|
+
timestamp: Date.now()
|
|
137
|
+
});
|
|
138
|
+
readFileTimestamps[fullFilePath] = Date.now();
|
|
139
|
+
const modificationReminder = generateFileModificationReminder(fullFilePath);
|
|
140
|
+
if (modificationReminder) {
|
|
141
|
+
emitReminderEvent("file:modified", {
|
|
142
|
+
filePath: fullFilePath,
|
|
143
|
+
reminder: modificationReminder,
|
|
144
|
+
timestamp: Date.now()
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
if (IMAGE_EXTENSIONS.has(ext)) {
|
|
148
|
+
const data2 = await readImage(fullFilePath, ext);
|
|
149
|
+
yield {
|
|
150
|
+
type: "result",
|
|
151
|
+
data: data2,
|
|
152
|
+
resultForAssistant: this.renderResultForAssistant(data2)
|
|
153
|
+
};
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
const lineOffset = offset === 0 ? 0 : offset - 1;
|
|
157
|
+
const { content, lineCount, totalLines } = readTextContent(
|
|
158
|
+
fullFilePath,
|
|
159
|
+
lineOffset,
|
|
160
|
+
limit
|
|
161
|
+
);
|
|
162
|
+
if (!IMAGE_EXTENSIONS.has(ext) && content.length > MAX_OUTPUT_SIZE) {
|
|
163
|
+
throw new Error(formatFileSizeError(content.length));
|
|
164
|
+
}
|
|
165
|
+
const data = {
|
|
166
|
+
type: "text",
|
|
167
|
+
file: {
|
|
168
|
+
filePath: file_path,
|
|
169
|
+
content,
|
|
170
|
+
numLines: lineCount,
|
|
171
|
+
startLine: offset,
|
|
172
|
+
totalLines
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
yield {
|
|
176
|
+
type: "result",
|
|
177
|
+
data,
|
|
178
|
+
resultForAssistant: this.renderResultForAssistant(data)
|
|
179
|
+
};
|
|
180
|
+
},
|
|
181
|
+
renderResultForAssistant(data) {
|
|
182
|
+
switch (data.type) {
|
|
183
|
+
case "image":
|
|
184
|
+
return [
|
|
185
|
+
{
|
|
186
|
+
type: "image",
|
|
187
|
+
source: {
|
|
188
|
+
type: "base64",
|
|
189
|
+
data: data.file.base64,
|
|
190
|
+
media_type: data.file.type
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
];
|
|
194
|
+
case "text":
|
|
195
|
+
return addLineNumbers(data.file);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
const formatFileSizeError = (sizeInBytes) => `File content (${Math.round(sizeInBytes / 1024)}KB) exceeds maximum allowed size (${Math.round(MAX_OUTPUT_SIZE / 1024)}KB). Please use offset and limit parameters to read specific portions of the file, or use the GrepTool to search for specific content.`;
|
|
200
|
+
function createImageResponse(buffer, ext) {
|
|
201
|
+
return {
|
|
202
|
+
type: "image",
|
|
203
|
+
file: {
|
|
204
|
+
base64: buffer.toString("base64"),
|
|
205
|
+
type: `image/${ext.slice(1)}`
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
async function readImage(filePath, ext) {
|
|
210
|
+
try {
|
|
211
|
+
const stats = statSync(filePath);
|
|
212
|
+
const sharp = (await import("sharp")).default;
|
|
213
|
+
const fileReadResult = secureFileService.safeReadFile(filePath, {
|
|
214
|
+
encoding: "buffer",
|
|
215
|
+
maxFileSize: MAX_IMAGE_SIZE
|
|
216
|
+
});
|
|
217
|
+
if (!fileReadResult.success) {
|
|
218
|
+
throw new Error(`Failed to read image file: ${fileReadResult.error}`);
|
|
219
|
+
}
|
|
220
|
+
const image = sharp(fileReadResult.content);
|
|
221
|
+
const metadata = await image.metadata();
|
|
222
|
+
if (!metadata.width || !metadata.height) {
|
|
223
|
+
if (stats.size > MAX_IMAGE_SIZE) {
|
|
224
|
+
const compressedBuffer = await image.jpeg({ quality: 80 }).toBuffer();
|
|
225
|
+
return createImageResponse(compressedBuffer, "jpeg");
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
let width = metadata.width || 0;
|
|
229
|
+
let height = metadata.height || 0;
|
|
230
|
+
if (stats.size <= MAX_IMAGE_SIZE && width <= MAX_WIDTH && height <= MAX_HEIGHT) {
|
|
231
|
+
const fileReadResult2 = secureFileService.safeReadFile(filePath, {
|
|
232
|
+
encoding: "buffer",
|
|
233
|
+
maxFileSize: MAX_IMAGE_SIZE
|
|
234
|
+
});
|
|
235
|
+
if (!fileReadResult2.success) {
|
|
236
|
+
throw new Error(`Failed to read image file: ${fileReadResult2.error}`);
|
|
237
|
+
}
|
|
238
|
+
return createImageResponse(fileReadResult2.content, ext);
|
|
239
|
+
}
|
|
240
|
+
if (width > MAX_WIDTH) {
|
|
241
|
+
height = Math.round(height * MAX_WIDTH / width);
|
|
242
|
+
width = MAX_WIDTH;
|
|
243
|
+
}
|
|
244
|
+
if (height > MAX_HEIGHT) {
|
|
245
|
+
width = Math.round(width * MAX_HEIGHT / height);
|
|
246
|
+
height = MAX_HEIGHT;
|
|
247
|
+
}
|
|
248
|
+
const resizedImageBuffer = await image.resize(width, height, {
|
|
249
|
+
fit: "inside",
|
|
250
|
+
withoutEnlargement: true
|
|
251
|
+
}).toBuffer();
|
|
252
|
+
if (resizedImageBuffer.length > MAX_IMAGE_SIZE) {
|
|
253
|
+
const compressedBuffer = await image.jpeg({ quality: 80 }).toBuffer();
|
|
254
|
+
return createImageResponse(compressedBuffer, "jpeg");
|
|
255
|
+
}
|
|
256
|
+
return createImageResponse(resizedImageBuffer, ext);
|
|
257
|
+
} catch (e) {
|
|
258
|
+
logError(e);
|
|
259
|
+
const fileReadResult = secureFileService.safeReadFile(filePath, {
|
|
260
|
+
encoding: "buffer",
|
|
261
|
+
maxFileSize: MAX_IMAGE_SIZE
|
|
262
|
+
});
|
|
263
|
+
if (!fileReadResult.success) {
|
|
264
|
+
throw new Error(`Failed to read image file: ${fileReadResult.error}`);
|
|
265
|
+
}
|
|
266
|
+
return createImageResponse(fileReadResult.content, ext);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
export {
|
|
270
|
+
FileReadTool
|
|
271
|
+
};
|
|
272
|
+
//# sourceMappingURL=FileReadTool.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/tools/FileReadTool/FileReadTool.tsx"],
|
|
4
|
+
"sourcesContent": ["import { ImageBlockParam } from '@anthropic-ai/sdk/resources/index.mjs'\nimport { statSync } from 'node:fs'\nimport { Box, Text } from 'ink'\nimport * as path from 'node:path'\nimport { extname, relative } from 'node:path'\nimport * as React from 'react'\nimport { z } from 'zod'\nimport { FallbackToolUseRejectedMessage } from '../../components/FallbackToolUseRejectedMessage'\nimport { HighlightedCode } from '../../components/HighlightedCode'\nimport type { Tool } from '../../Tool'\nimport { getCwd } from '../../utils/state'\nimport {\n addLineNumbers,\n findSimilarFile,\n normalizeFilePath,\n readTextContent,\n} from '../../utils/file.js'\nimport { logError } from '../../utils/log'\nimport { getTheme } from '../../utils/theme'\nimport { emitReminderEvent } from '../../services/systemReminder'\nimport {\n recordFileRead,\n generateFileModificationReminder,\n} from '../../services/fileFreshness'\nimport { DESCRIPTION, PROMPT } from './prompt'\nimport { hasReadPermission } from '../../utils/permissions/filesystem'\nimport { secureFileService } from '../../utils/secureFile'\n\nconst MAX_LINES_TO_RENDER = 5\nconst MAX_OUTPUT_SIZE = 0.25 * 1024 * 1024 // 0.25MB in bytes\n\n// Common image extensions\nconst IMAGE_EXTENSIONS = new Set([\n '.png',\n '.jpg',\n '.jpeg',\n '.gif',\n '.bmp',\n '.webp',\n])\n\n// Maximum dimensions for images\nconst MAX_WIDTH = 2000\nconst MAX_HEIGHT = 2000\nconst MAX_IMAGE_SIZE = 3.75 * 1024 * 1024 // 5MB in bytes, with base64 encoding\n\nconst inputSchema = z.strictObject({\n file_path: z.string().describe('The absolute path to the file to read'),\n offset: z\n .number()\n .optional()\n .describe(\n 'The line number to start reading from. Only provide if the file is too large to read at once',\n ),\n limit: z\n .number()\n .optional()\n .describe(\n 'The number of lines to read. Only provide if the file is too large to read at once.',\n ),\n})\n\nexport const FileReadTool = {\n name: 'View',\n async description() {\n return DESCRIPTION\n },\n async prompt() {\n return PROMPT\n },\n inputSchema,\n isReadOnly() {\n return true\n },\n isConcurrencySafe() {\n return true // FileRead is read-only, safe for concurrent execution\n },\n userFacingName() {\n return 'Read'\n },\n async isEnabled() {\n return true\n },\n needsPermissions({ file_path }) {\n return !hasReadPermission(file_path || getCwd())\n },\n renderToolUseMessage(input, { verbose }) {\n const { file_path, ...rest } = input\n const entries = [\n ['file_path', verbose ? file_path : relative(getCwd(), file_path)],\n ...Object.entries(rest),\n ]\n return entries\n .map(([key, value]) => `${key}: ${JSON.stringify(value)}`)\n .join(', ')\n },\n renderToolResultMessage(output) {\n const verbose = false // Set default value for verbose\n // TODO: Render recursively\n switch (output.type) {\n case 'image':\n return (\n <Box justifyContent=\"space-between\" overflowX=\"hidden\" width=\"100%\">\n <Box flexDirection=\"row\">\n <Text> \u23BF </Text>\n <Text>Read image</Text>\n </Box>\n </Box>\n )\n case 'text': {\n const { filePath, content, numLines } = output.file\n const contentWithFallback = content || '(No content)'\n return (\n <Box justifyContent=\"space-between\" overflowX=\"hidden\" width=\"100%\">\n <Box flexDirection=\"row\">\n <Text> \u23BF </Text>\n <Box flexDirection=\"column\">\n <HighlightedCode\n code={\n verbose\n ? contentWithFallback\n : contentWithFallback\n .split('\\n')\n .slice(0, MAX_LINES_TO_RENDER)\n .filter(_ => _.trim() !== '')\n .join('\\n')\n }\n language={extname(filePath).slice(1)}\n />\n {!verbose && numLines > MAX_LINES_TO_RENDER && (\n <Text color={getTheme().secondaryText}>\n ... (+{numLines - MAX_LINES_TO_RENDER} lines)\n </Text>\n )}\n </Box>\n </Box>\n </Box>\n )\n }\n }\n },\n renderToolUseRejectedMessage() {\n return <FallbackToolUseRejectedMessage />\n },\n async validateInput({ file_path, offset, limit }) {\n const fullFilePath = normalizeFilePath(file_path)\n\n // Use secure file service to check if file exists and get file info\n const fileCheck = secureFileService.safeGetFileInfo(fullFilePath)\n if (!fileCheck.success) {\n // Try to find a similar file with a different extension\n const similarFilename = findSimilarFile(fullFilePath)\n let message = 'File does not exist.'\n\n // If we found a similar file, suggest it to the assistant\n if (similarFilename) {\n message += ` Did you mean ${similarFilename}?`\n }\n\n return {\n result: false,\n message,\n }\n }\n\n const stats = fileCheck.stats!\n const fileSize = stats.size\n const ext = path.extname(fullFilePath).toLowerCase()\n\n // Skip size check for image files - they have their own size limits\n if (!IMAGE_EXTENSIONS.has(ext)) {\n // If file is too large and no offset/limit provided\n if (fileSize > MAX_OUTPUT_SIZE && !offset && !limit) {\n return {\n result: false,\n message: formatFileSizeError(fileSize),\n meta: { fileSize },\n }\n }\n }\n\n return { result: true }\n },\n async *call(\n { file_path, offset = 1, limit = undefined },\n { readFileTimestamps },\n ) {\n const ext = path.extname(file_path).toLowerCase()\n const fullFilePath = normalizeFilePath(file_path)\n\n // Record file read for freshness tracking\n recordFileRead(fullFilePath)\n\n // Emit file read event for system reminders\n emitReminderEvent('file:read', {\n filePath: fullFilePath,\n extension: ext,\n timestamp: Date.now(),\n })\n\n // Update read timestamp, to invalidate stale writes\n readFileTimestamps[fullFilePath] = Date.now()\n\n // Check for file modifications and generate reminder if needed\n const modificationReminder = generateFileModificationReminder(fullFilePath)\n if (modificationReminder) {\n emitReminderEvent('file:modified', {\n filePath: fullFilePath,\n reminder: modificationReminder,\n timestamp: Date.now(),\n })\n }\n\n // If it's an image file, process and return base64 encoded contents\n if (IMAGE_EXTENSIONS.has(ext)) {\n const data = await readImage(fullFilePath, ext)\n yield {\n type: 'result',\n data,\n resultForAssistant: this.renderResultForAssistant(data),\n }\n return\n }\n\n // Handle offset properly - if offset is 0, don't subtract 1\n const lineOffset = offset === 0 ? 0 : offset - 1\n const { content, lineCount, totalLines } = readTextContent(\n fullFilePath,\n lineOffset,\n limit,\n )\n\n // Add size validation after reading for non-image files\n if (!IMAGE_EXTENSIONS.has(ext) && content.length > MAX_OUTPUT_SIZE) {\n throw new Error(formatFileSizeError(content.length))\n }\n\n const data = {\n type: 'text' as const,\n file: {\n filePath: file_path,\n content: content,\n numLines: lineCount,\n startLine: offset,\n totalLines,\n },\n }\n\n yield {\n type: 'result',\n data,\n resultForAssistant: this.renderResultForAssistant(data),\n }\n },\n renderResultForAssistant(data) {\n switch (data.type) {\n case 'image':\n return [\n {\n type: 'image',\n source: {\n type: 'base64',\n data: data.file.base64,\n media_type: data.file.type,\n },\n },\n ]\n case 'text':\n return addLineNumbers(data.file)\n }\n },\n} satisfies Tool<\n typeof inputSchema,\n | {\n type: 'text'\n file: {\n filePath: string\n content: string\n numLines: number\n startLine: number\n totalLines: number\n }\n }\n | {\n type: 'image'\n file: { base64: string; type: ImageBlockParam.Source['media_type'] }\n }\n>\n\nconst formatFileSizeError = (sizeInBytes: number) =>\n `File content (${Math.round(sizeInBytes / 1024)}KB) exceeds maximum allowed size (${Math.round(MAX_OUTPUT_SIZE / 1024)}KB). Please use offset and limit parameters to read specific portions of the file, or use the GrepTool to search for specific content.`\n\nfunction createImageResponse(\n buffer: Buffer,\n ext: string,\n): {\n type: 'image'\n file: { base64: string; type: ImageBlockParam.Source['media_type'] }\n} {\n return {\n type: 'image',\n file: {\n base64: buffer.toString('base64'),\n type: `image/${ext.slice(1)}` as ImageBlockParam.Source['media_type'],\n },\n }\n}\n\nasync function readImage(\n filePath: string,\n ext: string,\n): Promise<{\n type: 'image'\n file: { base64: string; type: ImageBlockParam.Source['media_type'] }\n}> {\n try {\n const stats = statSync(filePath)\n const sharp = (\n (await import('sharp')) as unknown as { default: typeof import('sharp') }\n ).default\n \n // Use secure file service to read the file\n const fileReadResult = secureFileService.safeReadFile(filePath, {\n encoding: 'buffer' as BufferEncoding,\n maxFileSize: MAX_IMAGE_SIZE\n })\n \n if (!fileReadResult.success) {\n throw new Error(`Failed to read image file: ${fileReadResult.error}`)\n }\n \n const image = sharp(fileReadResult.content as Buffer)\n const metadata = await image.metadata()\n\n if (!metadata.width || !metadata.height) {\n if (stats.size > MAX_IMAGE_SIZE) {\n const compressedBuffer = await image.jpeg({ quality: 80 }).toBuffer()\n return createImageResponse(compressedBuffer, 'jpeg')\n }\n }\n\n // Calculate dimensions while maintaining aspect ratio\n let width = metadata.width || 0\n let height = metadata.height || 0\n\n // Check if the original file just works\n if (\n stats.size <= MAX_IMAGE_SIZE &&\n width <= MAX_WIDTH &&\n height <= MAX_HEIGHT\n ) {\n // Use secure file service to read the file\n const fileReadResult = secureFileService.safeReadFile(filePath, {\n encoding: 'buffer' as BufferEncoding,\n maxFileSize: MAX_IMAGE_SIZE\n })\n \n if (!fileReadResult.success) {\n throw new Error(`Failed to read image file: ${fileReadResult.error}`)\n }\n \n return createImageResponse(fileReadResult.content as Buffer, ext)\n }\n\n if (width > MAX_WIDTH) {\n height = Math.round((height * MAX_WIDTH) / width)\n width = MAX_WIDTH\n }\n\n if (height > MAX_HEIGHT) {\n width = Math.round((width * MAX_HEIGHT) / height)\n height = MAX_HEIGHT\n }\n\n // Resize image and convert to buffer\n const resizedImageBuffer = await image\n .resize(width, height, {\n fit: 'inside',\n withoutEnlargement: true,\n })\n .toBuffer()\n\n // If still too large after resize, compress quality\n if (resizedImageBuffer.length > MAX_IMAGE_SIZE) {\n const compressedBuffer = await image.jpeg({ quality: 80 }).toBuffer()\n return createImageResponse(compressedBuffer, 'jpeg')\n }\n\n return createImageResponse(resizedImageBuffer, ext)\n } catch (e) {\n logError(e)\n // If any error occurs during processing, return original image\n const fileReadResult = secureFileService.safeReadFile(filePath, {\n encoding: 'buffer' as BufferEncoding,\n maxFileSize: MAX_IMAGE_SIZE\n })\n \n if (!fileReadResult.success) {\n throw new Error(`Failed to read image file: ${fileReadResult.error}`)\n }\n \n return createImageResponse(fileReadResult.content as Buffer, ext)\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["data", "fileReadResult"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { NotebookReadTool } from "../NotebookReadTool/NotebookReadTool.js";
|
|
2
|
+
const MAX_LINES_TO_READ = 2e3;
|
|
3
|
+
const MAX_LINE_LENGTH = 2e3;
|
|
4
|
+
const DESCRIPTION = "Read a file from the local filesystem.";
|
|
5
|
+
const PROMPT = `Reads a file from the local filesystem. The file_path parameter must be an absolute path, not a relative path. By default, it reads up to ${MAX_LINES_TO_READ} lines starting from the beginning of the file. You can optionally specify a line offset and limit (especially handy for long files), but it's recommended to read the whole file by not providing these parameters. Any lines longer than ${MAX_LINE_LENGTH} characters will be truncated. For image files, the tool will display the image for you. For Jupyter notebooks (.ipynb files), use the ${NotebookReadTool.name} instead.`;
|
|
6
|
+
export {
|
|
7
|
+
DESCRIPTION,
|
|
8
|
+
PROMPT
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=prompt.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/tools/FileReadTool/prompt.ts"],
|
|
4
|
+
"sourcesContent": ["import { NotebookReadTool } from '../NotebookReadTool/NotebookReadTool'\n\nconst MAX_LINES_TO_READ = 2000\nconst MAX_LINE_LENGTH = 2000\n\nexport const DESCRIPTION = 'Read a file from the local filesystem.'\nexport const PROMPT = `Reads a file from the local filesystem. The file_path parameter must be an absolute path, not a relative path. By default, it reads up to ${MAX_LINES_TO_READ} lines starting from the beginning of the file. You can optionally specify a line offset and limit (especially handy for long files), but it's recommended to read the whole file by not providing these parameters. Any lines longer than ${MAX_LINE_LENGTH} characters will be truncated. For image files, the tool will display the image for you. For Jupyter notebooks (.ipynb files), use the ${NotebookReadTool.name} instead.`\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,wBAAwB;AAEjC,MAAM,oBAAoB;AAC1B,MAAM,kBAAkB;AAEjB,MAAM,cAAc;AACpB,MAAM,SAAS,6IAA6I,iBAAiB,8OAA8O,eAAe,0IAA0I,iBAAiB,IAAI;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, statSync } from "fs";
|
|
2
|
+
import { Box, Text } from "ink";
|
|
3
|
+
import { EOL } from "os";
|
|
4
|
+
import { dirname, extname, isAbsolute, relative, resolve, sep } from "path";
|
|
5
|
+
import * as React from "react";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
import { FileEditToolUpdatedMessage } from "../../components/FileEditToolUpdatedMessage.js";
|
|
8
|
+
import { HighlightedCode } from "../../components/HighlightedCode.js";
|
|
9
|
+
import { StructuredDiff } from "../../components/StructuredDiff.js";
|
|
10
|
+
import { FallbackToolUseRejectedMessage } from "../../components/FallbackToolUseRejectedMessage.js";
|
|
11
|
+
import { logEvent } from "../../services/statsig.js";
|
|
12
|
+
import { intersperse } from "../../utils/array.js";
|
|
13
|
+
import {
|
|
14
|
+
addLineNumbers,
|
|
15
|
+
detectFileEncoding,
|
|
16
|
+
detectLineEndings,
|
|
17
|
+
detectRepoLineEndings,
|
|
18
|
+
writeTextContent
|
|
19
|
+
} from "../../utils/file.js";
|
|
20
|
+
import { logError } from "../../utils/log.js";
|
|
21
|
+
import { getCwd } from "../../utils/state.js";
|
|
22
|
+
import { getTheme } from "../../utils/theme.js";
|
|
23
|
+
import { PROMPT } from "./prompt.js";
|
|
24
|
+
import { hasWritePermission } from "../../utils/permissions/filesystem.js";
|
|
25
|
+
import { getPatch } from "../../utils/diff.js";
|
|
26
|
+
import { PROJECT_FILE } from "../../constants/product.js";
|
|
27
|
+
import { emitReminderEvent } from "../../services/systemReminder.js";
|
|
28
|
+
import { recordFileEdit } from "../../services/fileFreshness.js";
|
|
29
|
+
const MAX_LINES_TO_RENDER = 5;
|
|
30
|
+
const MAX_LINES_TO_RENDER_FOR_ASSISTANT = 16e3;
|
|
31
|
+
const TRUNCATED_MESSAGE = "<response clipped><NOTE>To save on context only part of this file has been shown to you. You should retry this tool after you have searched inside the file with Grep in order to find the line numbers of what you are looking for.</NOTE>";
|
|
32
|
+
const inputSchema = z.strictObject({
|
|
33
|
+
file_path: z.string().describe(
|
|
34
|
+
"The absolute path to the file to write (must be absolute, not relative)"
|
|
35
|
+
),
|
|
36
|
+
content: z.string().describe("The content to write to the file")
|
|
37
|
+
});
|
|
38
|
+
const FileWriteTool = {
|
|
39
|
+
name: "Replace",
|
|
40
|
+
async description() {
|
|
41
|
+
return "Write a file to the local filesystem.";
|
|
42
|
+
},
|
|
43
|
+
userFacingName: () => "Write",
|
|
44
|
+
async prompt() {
|
|
45
|
+
return PROMPT;
|
|
46
|
+
},
|
|
47
|
+
inputSchema,
|
|
48
|
+
async isEnabled() {
|
|
49
|
+
return true;
|
|
50
|
+
},
|
|
51
|
+
isReadOnly() {
|
|
52
|
+
return false;
|
|
53
|
+
},
|
|
54
|
+
isConcurrencySafe() {
|
|
55
|
+
return false;
|
|
56
|
+
},
|
|
57
|
+
needsPermissions({ file_path }) {
|
|
58
|
+
return !hasWritePermission(file_path);
|
|
59
|
+
},
|
|
60
|
+
renderToolUseMessage(input, { verbose }) {
|
|
61
|
+
return `file_path: ${verbose ? input.file_path : relative(getCwd(), input.file_path)}`;
|
|
62
|
+
},
|
|
63
|
+
renderToolUseRejectedMessage({ file_path, content } = {}, { columns, verbose } = {}) {
|
|
64
|
+
try {
|
|
65
|
+
if (!file_path) {
|
|
66
|
+
return /* @__PURE__ */ React.createElement(FallbackToolUseRejectedMessage, null);
|
|
67
|
+
}
|
|
68
|
+
const fullFilePath = isAbsolute(file_path) ? file_path : resolve(getCwd(), file_path);
|
|
69
|
+
const oldFileExists = existsSync(fullFilePath);
|
|
70
|
+
const enc = oldFileExists ? detectFileEncoding(fullFilePath) : "utf-8";
|
|
71
|
+
const oldContent = oldFileExists ? readFileSync(fullFilePath, enc) : null;
|
|
72
|
+
const type = oldContent ? "update" : "create";
|
|
73
|
+
const patch = getPatch({
|
|
74
|
+
filePath: file_path,
|
|
75
|
+
fileContents: oldContent ?? "",
|
|
76
|
+
oldStr: oldContent ?? "",
|
|
77
|
+
newStr: content
|
|
78
|
+
});
|
|
79
|
+
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Text, null, " ", "\u23BF", " ", /* @__PURE__ */ React.createElement(Text, { color: getTheme().error }, "User rejected ", type === "update" ? "update" : "write", " to", " "), /* @__PURE__ */ React.createElement(Text, { bold: true }, verbose ? file_path : relative(getCwd(), file_path))), intersperse(
|
|
80
|
+
patch.map((_) => /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", paddingLeft: 5, key: _.newStart }, /* @__PURE__ */ React.createElement(StructuredDiff, { patch: _, dim: true, width: columns - 12 }))),
|
|
81
|
+
(i) => /* @__PURE__ */ React.createElement(Box, { paddingLeft: 5, key: `ellipsis-${i}` }, /* @__PURE__ */ React.createElement(Text, { color: getTheme().secondaryText }, "..."))
|
|
82
|
+
));
|
|
83
|
+
} catch (e) {
|
|
84
|
+
logError(e);
|
|
85
|
+
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Text, null, " ", "\u23BF (No changes)"));
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
renderToolResultMessage({ filePath, content, structuredPatch, type }) {
|
|
89
|
+
const verbose = false;
|
|
90
|
+
switch (type) {
|
|
91
|
+
case "create": {
|
|
92
|
+
const contentWithFallback = content || "(No content)";
|
|
93
|
+
const numLines = content.split(EOL).length;
|
|
94
|
+
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Text, null, " ", "\u23BF Wrote ", numLines, " lines to", " ", /* @__PURE__ */ React.createElement(Text, { bold: true }, verbose ? filePath : relative(getCwd(), filePath))), /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", paddingLeft: 5 }, /* @__PURE__ */ React.createElement(
|
|
95
|
+
HighlightedCode,
|
|
96
|
+
{
|
|
97
|
+
code: verbose ? contentWithFallback : contentWithFallback.split("\n").slice(0, MAX_LINES_TO_RENDER).filter((_) => _.trim() !== "").join("\n"),
|
|
98
|
+
language: extname(filePath).slice(1)
|
|
99
|
+
}
|
|
100
|
+
), !verbose && numLines > MAX_LINES_TO_RENDER && /* @__PURE__ */ React.createElement(Text, { color: getTheme().secondaryText }, "... (+", numLines - MAX_LINES_TO_RENDER, " lines)")));
|
|
101
|
+
}
|
|
102
|
+
case "update":
|
|
103
|
+
return /* @__PURE__ */ React.createElement(
|
|
104
|
+
FileEditToolUpdatedMessage,
|
|
105
|
+
{
|
|
106
|
+
filePath,
|
|
107
|
+
structuredPatch,
|
|
108
|
+
verbose
|
|
109
|
+
}
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
async validateInput({ file_path }, { readFileTimestamps }) {
|
|
114
|
+
const fullFilePath = isAbsolute(file_path) ? file_path : resolve(getCwd(), file_path);
|
|
115
|
+
if (!existsSync(fullFilePath)) {
|
|
116
|
+
return { result: true };
|
|
117
|
+
}
|
|
118
|
+
const readTimestamp = readFileTimestamps[fullFilePath];
|
|
119
|
+
if (!readTimestamp) {
|
|
120
|
+
return {
|
|
121
|
+
result: false,
|
|
122
|
+
message: "File has not been read yet. Read it first before writing to it."
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
const stats = statSync(fullFilePath);
|
|
126
|
+
const lastWriteTime = stats.mtimeMs;
|
|
127
|
+
if (lastWriteTime > readTimestamp) {
|
|
128
|
+
return {
|
|
129
|
+
result: false,
|
|
130
|
+
message: "File has been modified since read, either by the user or by a linter. Read it again before attempting to write it."
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
return { result: true };
|
|
134
|
+
},
|
|
135
|
+
async *call({ file_path, content }, { readFileTimestamps }) {
|
|
136
|
+
const fullFilePath = isAbsolute(file_path) ? file_path : resolve(getCwd(), file_path);
|
|
137
|
+
const dir = dirname(fullFilePath);
|
|
138
|
+
const oldFileExists = existsSync(fullFilePath);
|
|
139
|
+
const enc = oldFileExists ? detectFileEncoding(fullFilePath) : "utf-8";
|
|
140
|
+
const oldContent = oldFileExists ? readFileSync(fullFilePath, enc) : null;
|
|
141
|
+
const endings = oldFileExists ? detectLineEndings(fullFilePath) : await detectRepoLineEndings(getCwd());
|
|
142
|
+
mkdirSync(dir, { recursive: true });
|
|
143
|
+
writeTextContent(fullFilePath, content, enc, endings);
|
|
144
|
+
recordFileEdit(fullFilePath, content);
|
|
145
|
+
readFileTimestamps[fullFilePath] = statSync(fullFilePath).mtimeMs;
|
|
146
|
+
if (fullFilePath.endsWith(`${sep}${PROJECT_FILE}`)) {
|
|
147
|
+
logEvent("tengu_write_claudemd", {});
|
|
148
|
+
}
|
|
149
|
+
emitReminderEvent("file:edited", {
|
|
150
|
+
filePath: fullFilePath,
|
|
151
|
+
content,
|
|
152
|
+
oldContent: oldContent || "",
|
|
153
|
+
timestamp: Date.now(),
|
|
154
|
+
operation: oldFileExists ? "update" : "create"
|
|
155
|
+
});
|
|
156
|
+
if (oldContent) {
|
|
157
|
+
const patch = getPatch({
|
|
158
|
+
filePath: file_path,
|
|
159
|
+
fileContents: oldContent,
|
|
160
|
+
oldStr: oldContent,
|
|
161
|
+
newStr: content
|
|
162
|
+
});
|
|
163
|
+
const data2 = {
|
|
164
|
+
type: "update",
|
|
165
|
+
filePath: file_path,
|
|
166
|
+
content,
|
|
167
|
+
structuredPatch: patch
|
|
168
|
+
};
|
|
169
|
+
yield {
|
|
170
|
+
type: "result",
|
|
171
|
+
data: data2,
|
|
172
|
+
resultForAssistant: this.renderResultForAssistant(data2)
|
|
173
|
+
};
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
const data = {
|
|
177
|
+
type: "create",
|
|
178
|
+
filePath: file_path,
|
|
179
|
+
content,
|
|
180
|
+
structuredPatch: []
|
|
181
|
+
};
|
|
182
|
+
yield {
|
|
183
|
+
type: "result",
|
|
184
|
+
data,
|
|
185
|
+
resultForAssistant: this.renderResultForAssistant(data)
|
|
186
|
+
};
|
|
187
|
+
},
|
|
188
|
+
renderResultForAssistant({ filePath, content, type }) {
|
|
189
|
+
switch (type) {
|
|
190
|
+
case "create":
|
|
191
|
+
return `File created successfully at: ${filePath}`;
|
|
192
|
+
case "update":
|
|
193
|
+
return `The file ${filePath} has been updated. Here's the result of running \`cat -n\` on a snippet of the edited file:
|
|
194
|
+
${addLineNumbers({
|
|
195
|
+
content: content.split(/\r?\n/).length > MAX_LINES_TO_RENDER_FOR_ASSISTANT ? content.split(/\r?\n/).slice(0, MAX_LINES_TO_RENDER_FOR_ASSISTANT).join("\n") + TRUNCATED_MESSAGE : content,
|
|
196
|
+
startLine: 1
|
|
197
|
+
})}`;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
export {
|
|
202
|
+
FileWriteTool
|
|
203
|
+
};
|
|
204
|
+
//# sourceMappingURL=FileWriteTool.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/tools/FileWriteTool/FileWriteTool.tsx"],
|
|
4
|
+
"sourcesContent": ["import { Hunk } from 'diff'\nimport { existsSync, mkdirSync, readFileSync, statSync } from 'fs'\nimport { Box, Text } from 'ink'\nimport { EOL } from 'os'\nimport { dirname, extname, isAbsolute, relative, resolve, sep } from 'path'\nimport * as React from 'react'\nimport { z } from 'zod'\nimport { FileEditToolUpdatedMessage } from '../../components/FileEditToolUpdatedMessage'\nimport { HighlightedCode } from '../../components/HighlightedCode'\nimport { StructuredDiff } from '../../components/StructuredDiff'\nimport { FallbackToolUseRejectedMessage } from '../../components/FallbackToolUseRejectedMessage'\nimport { logEvent } from '../../services/statsig'\nimport type { Tool } from '../../Tool'\nimport { intersperse } from '../../utils/array'\nimport {\n addLineNumbers,\n detectFileEncoding,\n detectLineEndings,\n detectRepoLineEndings,\n writeTextContent,\n} from '../../utils/file.js'\nimport { logError } from '../../utils/log'\nimport { getCwd } from '../../utils/state'\nimport { getTheme } from '../../utils/theme'\nimport { PROMPT } from './prompt'\nimport { hasWritePermission } from '../../utils/permissions/filesystem'\nimport { getPatch } from '../../utils/diff'\nimport { PROJECT_FILE } from '../../constants/product'\nimport { emitReminderEvent } from '../../services/systemReminder'\nimport { recordFileEdit } from '../../services/fileFreshness'\n\nconst MAX_LINES_TO_RENDER = 5\nconst MAX_LINES_TO_RENDER_FOR_ASSISTANT = 16000\nconst TRUNCATED_MESSAGE =\n '<response clipped><NOTE>To save on context only part of this file has been shown to you. You should retry this tool after you have searched inside the file with Grep in order to find the line numbers of what you are looking for.</NOTE>'\n\nconst inputSchema = z.strictObject({\n file_path: z\n .string()\n .describe(\n 'The absolute path to the file to write (must be absolute, not relative)',\n ),\n content: z.string().describe('The content to write to the file'),\n})\n\nexport const FileWriteTool = {\n name: 'Replace',\n async description() {\n return 'Write a file to the local filesystem.'\n },\n userFacingName: () => 'Write',\n async prompt() {\n return PROMPT\n },\n inputSchema,\n async isEnabled() {\n return true\n },\n isReadOnly() {\n return false\n },\n isConcurrencySafe() {\n return false // FileWriteTool modifies state/files, not safe for concurrent execution\n },\n needsPermissions({ file_path }) {\n return !hasWritePermission(file_path)\n },\n renderToolUseMessage(input, { verbose }) {\n return `file_path: ${verbose ? input.file_path : relative(getCwd(), input.file_path)}`\n },\n renderToolUseRejectedMessage({ file_path, content }: any = {}, { columns, verbose }: any = {}) {\n try {\n if (!file_path) {\n return <FallbackToolUseRejectedMessage />\n }\n const fullFilePath = isAbsolute(file_path)\n ? file_path\n : resolve(getCwd(), file_path)\n const oldFileExists = existsSync(fullFilePath)\n const enc = oldFileExists ? detectFileEncoding(fullFilePath) : 'utf-8'\n const oldContent = oldFileExists ? readFileSync(fullFilePath, enc) : null\n const type = oldContent ? 'update' : 'create'\n const patch = getPatch({\n filePath: file_path,\n fileContents: oldContent ?? '',\n oldStr: oldContent ?? '',\n newStr: content,\n })\n\n return (\n <Box flexDirection=\"column\">\n <Text>\n {' '}\u23BF{' '}\n <Text color={getTheme().error}>\n User rejected {type === 'update' ? 'update' : 'write'} to{' '}\n </Text>\n <Text bold>\n {verbose ? file_path : relative(getCwd(), file_path)}\n </Text>\n </Text>\n {intersperse(\n patch.map(_ => (\n <Box flexDirection=\"column\" paddingLeft={5} key={_.newStart}>\n <StructuredDiff patch={_} dim={true} width={columns - 12} />\n </Box>\n )),\n i => (\n <Box paddingLeft={5} key={`ellipsis-${i}`}>\n <Text color={getTheme().secondaryText}>...</Text>\n </Box>\n ),\n )}\n </Box>\n )\n } catch (e) {\n // Handle the case where while we were showing the diff, the user manually made the change.\n // TODO: Find a way to show the diff in this case\n logError(e)\n return (\n <Box flexDirection=\"column\">\n <Text>{' '}\u23BF (No changes)</Text>\n </Box>\n )\n }\n },\n renderToolResultMessage(\n { filePath, content, structuredPatch, type }\n ) {\n const verbose = false // Default to false since verbose is no longer passed\n switch (type) {\n case 'create': {\n const contentWithFallback = content || '(No content)'\n const numLines = content.split(EOL).length\n\n return (\n <Box flexDirection=\"column\">\n <Text>\n {' '}\u23BF Wrote {numLines} lines to{' '}\n <Text bold>\n {verbose ? filePath : relative(getCwd(), filePath)}\n </Text>\n </Text>\n <Box flexDirection=\"column\" paddingLeft={5}>\n <HighlightedCode\n code={\n verbose\n ? contentWithFallback\n : contentWithFallback\n .split('\\n')\n .slice(0, MAX_LINES_TO_RENDER)\n .filter(_ => _.trim() !== '')\n .join('\\n')\n }\n language={extname(filePath).slice(1)}\n />\n {!verbose && numLines > MAX_LINES_TO_RENDER && (\n <Text color={getTheme().secondaryText}>\n ... (+{numLines - MAX_LINES_TO_RENDER} lines)\n </Text>\n )}\n </Box>\n </Box>\n )\n }\n case 'update':\n return (\n <FileEditToolUpdatedMessage\n filePath={filePath}\n structuredPatch={structuredPatch}\n verbose={verbose}\n />\n )\n }\n },\n async validateInput({ file_path }, { readFileTimestamps }) {\n const fullFilePath = isAbsolute(file_path)\n ? file_path\n : resolve(getCwd(), file_path)\n if (!existsSync(fullFilePath)) {\n return { result: true }\n }\n\n const readTimestamp = readFileTimestamps[fullFilePath]\n if (!readTimestamp) {\n return {\n result: false,\n message:\n 'File has not been read yet. Read it first before writing to it.',\n }\n }\n\n // Check if file exists and get its last modified time\n const stats = statSync(fullFilePath)\n const lastWriteTime = stats.mtimeMs\n if (lastWriteTime > readTimestamp) {\n return {\n result: false,\n message:\n 'File has been modified since read, either by the user or by a linter. Read it again before attempting to write it.',\n }\n }\n\n return { result: true }\n },\n async *call({ file_path, content }, { readFileTimestamps }) {\n const fullFilePath = isAbsolute(file_path)\n ? file_path\n : resolve(getCwd(), file_path)\n const dir = dirname(fullFilePath)\n const oldFileExists = existsSync(fullFilePath)\n const enc = oldFileExists ? detectFileEncoding(fullFilePath) : 'utf-8'\n const oldContent = oldFileExists ? readFileSync(fullFilePath, enc) : null\n\n const endings = oldFileExists\n ? detectLineEndings(fullFilePath)\n : await detectRepoLineEndings(getCwd())\n\n mkdirSync(dir, { recursive: true })\n writeTextContent(fullFilePath, content, enc, endings!)\n\n // Record Agent edit operation for file freshness tracking\n recordFileEdit(fullFilePath, content)\n\n // Update read timestamp, to invalidate stale writes\n readFileTimestamps[fullFilePath] = statSync(fullFilePath).mtimeMs\n\n // Log when writing to CLAUDE.md\n if (fullFilePath.endsWith(`${sep}${PROJECT_FILE}`)) {\n logEvent('tengu_write_claudemd', {})\n }\n\n // Emit file edited event for system reminders\n emitReminderEvent('file:edited', {\n filePath: fullFilePath,\n content,\n oldContent: oldContent || '',\n timestamp: Date.now(),\n operation: oldFileExists ? 'update' : 'create',\n })\n\n if (oldContent) {\n const patch = getPatch({\n filePath: file_path,\n fileContents: oldContent,\n oldStr: oldContent,\n newStr: content,\n })\n\n const data = {\n type: 'update' as const,\n filePath: file_path,\n content,\n structuredPatch: patch,\n }\n yield {\n type: 'result',\n data,\n resultForAssistant: this.renderResultForAssistant(data),\n }\n return\n }\n\n const data = {\n type: 'create' as const,\n filePath: file_path,\n content,\n structuredPatch: [],\n }\n yield {\n type: 'result',\n data,\n resultForAssistant: this.renderResultForAssistant(data),\n }\n },\n renderResultForAssistant({ filePath, content, type }) {\n switch (type) {\n case 'create':\n return `File created successfully at: ${filePath}`\n case 'update':\n return `The file ${filePath} has been updated. Here's the result of running \\`cat -n\\` on a snippet of the edited file:\n${addLineNumbers({\n content:\n content.split(/\\r?\\n/).length > MAX_LINES_TO_RENDER_FOR_ASSISTANT\n ? content\n .split(/\\r?\\n/)\n .slice(0, MAX_LINES_TO_RENDER_FOR_ASSISTANT)\n .join('\\n') + TRUNCATED_MESSAGE\n : content,\n startLine: 1,\n})}`\n }\n },\n} satisfies Tool<\n typeof inputSchema,\n {\n type: 'create' | 'update'\n filePath: string\n content: string\n structuredPatch: Hunk[]\n }\n>\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["data"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const PROMPT = `Write a file to the local filesystem. Overwrites the existing file if there is one.
|
|
2
|
+
|
|
3
|
+
Before using this tool:
|
|
4
|
+
|
|
5
|
+
1. Use the ReadFile tool to understand the file's contents and context
|
|
6
|
+
|
|
7
|
+
2. Directory Verification (only applicable when creating new files):
|
|
8
|
+
- Use the LS tool to verify the parent directory exists and is the correct location`;
|
|
9
|
+
const DESCRIPTION = "Write a file to the local filesystem.";
|
|
10
|
+
export {
|
|
11
|
+
DESCRIPTION,
|
|
12
|
+
PROMPT
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=prompt.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/tools/FileWriteTool/prompt.ts"],
|
|
4
|
+
"sourcesContent": ["export const PROMPT = `Write a file to the local filesystem. Overwrites the existing file if there is one.\n\nBefore using this tool:\n\n1. Use the ReadFile tool to understand the file's contents and context\n\n2. Directory Verification (only applicable when creating new files):\n - Use the LS tool to verify the parent directory exists and is the correct location`\n\nexport const DESCRIPTION = 'Write a file to the local filesystem.'\n"],
|
|
5
|
+
"mappings": "AAAO,MAAM,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASf,MAAM,cAAc;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|