@vybestack/llxprt-code-core 0.1.19-beta → 0.1.19-gamma
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -2
- package/dist/index.d.ts +6 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/src/auth/anthropic-device-flow.d.ts +53 -0
- package/dist/src/auth/anthropic-device-flow.js +208 -0
- package/dist/src/auth/anthropic-device-flow.js.map +1 -0
- package/dist/src/auth/precedence.d.ts +55 -0
- package/dist/src/auth/precedence.js +211 -0
- package/dist/src/auth/precedence.js.map +1 -0
- package/dist/src/auth/qwen-device-flow.d.ts +45 -0
- package/dist/src/auth/qwen-device-flow.js +179 -0
- package/dist/src/auth/qwen-device-flow.js.map +1 -0
- package/dist/src/auth/token-store.d.ts +66 -0
- package/dist/src/auth/token-store.js +151 -0
- package/dist/src/auth/token-store.js.map +1 -0
- package/dist/src/auth/types.d.ts +130 -0
- package/dist/src/auth/types.js +60 -0
- package/dist/src/auth/types.js.map +1 -0
- package/dist/src/config/config.d.ts +7 -1
- package/dist/src/config/config.js +42 -4
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/endpoints.d.ts +60 -0
- package/dist/src/config/endpoints.js +126 -0
- package/dist/src/config/endpoints.js.map +1 -0
- package/dist/src/config/profileManager.d.ts +14 -4
- package/dist/src/config/profileManager.js +90 -11
- package/dist/src/config/profileManager.js.map +1 -1
- package/dist/src/core/client.js +9 -12
- package/dist/src/core/client.js.map +1 -1
- package/dist/src/core/contentGenerator.d.ts +4 -1
- package/dist/src/core/contentGenerator.js +3 -0
- package/dist/src/core/contentGenerator.js.map +1 -1
- package/dist/src/core/subagent.js +12 -10
- package/dist/src/core/subagent.js.map +1 -1
- package/dist/src/index.d.ts +9 -0
- package/dist/src/index.js +9 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/providers/BaseProvider.d.ts +149 -0
- package/dist/src/providers/BaseProvider.js +315 -0
- package/dist/src/providers/BaseProvider.js.map +1 -0
- package/dist/src/providers/IProvider.d.ts +1 -0
- package/dist/src/providers/LoggingProviderWrapper.d.ts +1 -0
- package/dist/src/providers/LoggingProviderWrapper.js +3 -0
- package/dist/src/providers/LoggingProviderWrapper.js.map +1 -1
- package/dist/src/providers/ProviderManager.d.ts +0 -1
- package/dist/src/providers/ProviderManager.js +23 -14
- package/dist/src/providers/ProviderManager.js.map +1 -1
- package/dist/src/providers/anthropic/AnthropicProvider.d.ts +20 -6
- package/dist/src/providers/anthropic/AnthropicProvider.js +172 -26
- package/dist/src/providers/anthropic/AnthropicProvider.js.map +1 -1
- package/dist/src/providers/gemini/GeminiProvider.d.ts +16 -7
- package/dist/src/providers/gemini/GeminiProvider.js +163 -148
- package/dist/src/providers/gemini/GeminiProvider.js.map +1 -1
- package/dist/src/providers/openai/OpenAIProvider.d.ts +53 -6
- package/dist/src/providers/openai/OpenAIProvider.js +373 -40
- package/dist/src/providers/openai/OpenAIProvider.js.map +1 -1
- package/dist/src/providers/openai/RESPONSES_API_MODELS.d.ts +1 -1
- package/dist/src/providers/openai/RESPONSES_API_MODELS.js +1 -0
- package/dist/src/providers/openai/RESPONSES_API_MODELS.js.map +1 -1
- package/dist/src/providers/openai/syntheticToolResponses.d.ts +52 -0
- package/dist/src/providers/openai/syntheticToolResponses.js +129 -0
- package/dist/src/providers/openai/syntheticToolResponses.js.map +1 -0
- package/dist/src/settings/SettingsService.d.ts +32 -0
- package/dist/src/settings/SettingsService.js +204 -0
- package/dist/src/settings/SettingsService.js.map +1 -0
- package/dist/src/settings/settingsServiceInstance.d.ts +12 -0
- package/dist/src/settings/settingsServiceInstance.js +24 -0
- package/dist/src/settings/settingsServiceInstance.js.map +1 -0
- package/dist/src/settings/types.d.ts +141 -0
- package/dist/src/settings/types.js +5 -0
- package/dist/src/settings/types.js.map +1 -0
- package/package.json +4 -2
- package/dist/src/code_assist/converter.test.d.ts +0 -6
- package/dist/src/code_assist/converter.test.js +0 -279
- package/dist/src/code_assist/converter.test.js.map +0 -1
- package/dist/src/code_assist/oauth2.test.d.ts +0 -6
- package/dist/src/code_assist/oauth2.test.js +0 -370
- package/dist/src/code_assist/oauth2.test.js.map +0 -1
- package/dist/src/code_assist/server.test.d.ts +0 -6
- package/dist/src/code_assist/server.test.js +0 -134
- package/dist/src/code_assist/server.test.js.map +0 -1
- package/dist/src/code_assist/setup.test.d.ts +0 -6
- package/dist/src/code_assist/setup.test.js +0 -65
- package/dist/src/code_assist/setup.test.js.map +0 -1
- package/dist/src/config/config.alwaysAllow.test.d.ts +0 -6
- package/dist/src/config/config.alwaysAllow.test.js +0 -84
- package/dist/src/config/config.alwaysAllow.test.js.map +0 -1
- package/dist/src/config/config.ephemeral.test.d.ts +0 -6
- package/dist/src/config/config.ephemeral.test.js +0 -152
- package/dist/src/config/config.ephemeral.test.js.map +0 -1
- package/dist/src/config/config.test.d.ts +0 -6
- package/dist/src/config/config.test.js +0 -369
- package/dist/src/config/config.test.js.map +0 -1
- package/dist/src/config/flashFallback.test.d.ts +0 -6
- package/dist/src/config/flashFallback.test.js +0 -91
- package/dist/src/config/flashFallback.test.js.map +0 -1
- package/dist/src/core/client.test.d.ts +0 -6
- package/dist/src/core/client.test.js +0 -1322
- package/dist/src/core/client.test.js.map +0 -1
- package/dist/src/core/contentGenerator.test.d.ts +0 -6
- package/dist/src/core/contentGenerator.test.js +0 -103
- package/dist/src/core/contentGenerator.test.js.map +0 -1
- package/dist/src/core/coreToolScheduler.test.d.ts +0 -6
- package/dist/src/core/coreToolScheduler.test.js +0 -637
- package/dist/src/core/coreToolScheduler.test.js.map +0 -1
- package/dist/src/core/geminiChat.test.d.ts +0 -6
- package/dist/src/core/geminiChat.test.js +0 -425
- package/dist/src/core/geminiChat.test.js.map +0 -1
- package/dist/src/core/googleGenAIWrapper.test.d.ts +0 -6
- package/dist/src/core/googleGenAIWrapper.test.js +0 -104
- package/dist/src/core/googleGenAIWrapper.test.js.map +0 -1
- package/dist/src/core/logger.test.d.ts +0 -6
- package/dist/src/core/logger.test.js +0 -467
- package/dist/src/core/logger.test.js.map +0 -1
- package/dist/src/core/nonInteractiveToolExecutor.test.d.ts +0 -6
- package/dist/src/core/nonInteractiveToolExecutor.test.js +0 -165
- package/dist/src/core/nonInteractiveToolExecutor.test.js.map +0 -1
- package/dist/src/core/prompts-async.test.d.ts +0 -6
- package/dist/src/core/prompts-async.test.js +0 -115
- package/dist/src/core/prompts-async.test.js.map +0 -1
- package/dist/src/core/prompts.test.d.ts +0 -6
- package/dist/src/core/prompts.test.js +0 -68
- package/dist/src/core/prompts.test.js.map +0 -1
- package/dist/src/core/subagent.test.d.ts +0 -6
- package/dist/src/core/subagent.test.js +0 -519
- package/dist/src/core/subagent.test.js.map +0 -1
- package/dist/src/core/tokenLimits.test.d.ts +0 -6
- package/dist/src/core/tokenLimits.test.js +0 -66
- package/dist/src/core/tokenLimits.test.js.map +0 -1
- package/dist/src/core/turn.test.d.ts +0 -6
- package/dist/src/core/turn.test.js +0 -366
- package/dist/src/core/turn.test.js.map +0 -1
- package/dist/src/hooks/tool-render-suppression-hook.test.d.ts +0 -6
- package/dist/src/hooks/tool-render-suppression-hook.test.js +0 -59
- package/dist/src/hooks/tool-render-suppression-hook.test.js.map +0 -1
- package/dist/src/ide/ide-installer.test.d.ts +0 -6
- package/dist/src/ide/ide-installer.test.js +0 -55
- package/dist/src/ide/ide-installer.test.js.map +0 -1
- package/dist/src/ide/ideContext.test.d.ts +0 -6
- package/dist/src/ide/ideContext.test.js +0 -265
- package/dist/src/ide/ideContext.test.js.map +0 -1
- package/dist/src/index.test.d.ts +0 -6
- package/dist/src/index.test.js +0 -12
- package/dist/src/index.test.js.map +0 -1
- package/dist/src/integration-tests/todo-system.test.d.ts +0 -6
- package/dist/src/integration-tests/todo-system.test.js +0 -46
- package/dist/src/integration-tests/todo-system.test.js.map +0 -1
- package/dist/src/mcp/google-auth-provider.test.d.ts +0 -6
- package/dist/src/mcp/google-auth-provider.test.js +0 -54
- package/dist/src/mcp/google-auth-provider.test.js.map +0 -1
- package/dist/src/mcp/oauth-provider.test.d.ts +0 -6
- package/dist/src/mcp/oauth-provider.test.js +0 -602
- package/dist/src/mcp/oauth-provider.test.js.map +0 -1
- package/dist/src/mcp/oauth-token-storage.test.d.ts +0 -6
- package/dist/src/mcp/oauth-token-storage.test.js +0 -205
- package/dist/src/mcp/oauth-token-storage.test.js.map +0 -1
- package/dist/src/mcp/oauth-utils.test.d.ts +0 -6
- package/dist/src/mcp/oauth-utils.test.js +0 -144
- package/dist/src/mcp/oauth-utils.test.js.map +0 -1
- package/dist/src/parsers/TextToolCallParser.multibyte.test.d.ts +0 -1
- package/dist/src/parsers/TextToolCallParser.multibyte.test.js +0 -42
- package/dist/src/parsers/TextToolCallParser.multibyte.test.js.map +0 -1
- package/dist/src/parsers/TextToolCallParser.test.d.ts +0 -1
- package/dist/src/parsers/TextToolCallParser.test.js +0 -225
- package/dist/src/parsers/TextToolCallParser.test.js.map +0 -1
- package/dist/src/prompt-config/TemplateEngine.test.d.ts +0 -1
- package/dist/src/prompt-config/TemplateEngine.test.js +0 -494
- package/dist/src/prompt-config/TemplateEngine.test.js.map +0 -1
- package/dist/src/prompt-config/prompt-cache.test.d.ts +0 -6
- package/dist/src/prompt-config/prompt-cache.test.js +0 -437
- package/dist/src/prompt-config/prompt-cache.test.js.map +0 -1
- package/dist/src/prompt-config/prompt-installer.test.d.ts +0 -7
- package/dist/src/prompt-config/prompt-installer.test.js +0 -503
- package/dist/src/prompt-config/prompt-installer.test.js.map +0 -1
- package/dist/src/prompt-config/prompt-loader.test.d.ts +0 -5
- package/dist/src/prompt-config/prompt-loader.test.js +0 -413
- package/dist/src/prompt-config/prompt-loader.test.js.map +0 -1
- package/dist/src/prompt-config/prompt-resolver.test.d.ts +0 -1
- package/dist/src/prompt-config/prompt-resolver.test.js +0 -529
- package/dist/src/prompt-config/prompt-resolver.test.js.map +0 -1
- package/dist/src/prompt-config/prompt-service.test.d.ts +0 -1
- package/dist/src/prompt-config/prompt-service.test.js +0 -811
- package/dist/src/prompt-config/prompt-service.test.js.map +0 -1
- package/dist/src/providers/ProviderManager.gemini-switch.test.d.ts +0 -6
- package/dist/src/providers/ProviderManager.gemini-switch.test.js +0 -57
- package/dist/src/providers/ProviderManager.gemini-switch.test.js.map +0 -1
- package/dist/src/providers/ProviderManager.test.d.ts +0 -6
- package/dist/src/providers/ProviderManager.test.js +0 -284
- package/dist/src/providers/ProviderManager.test.js.map +0 -1
- package/dist/src/providers/adapters/GeminiCompatibleWrapper.test.d.ts +0 -6
- package/dist/src/providers/adapters/GeminiCompatibleWrapper.test.js +0 -273
- package/dist/src/providers/adapters/GeminiCompatibleWrapper.test.js.map +0 -1
- package/dist/src/providers/anthropic/AnthropicProvider.modelParams.test.d.ts +0 -1
- package/dist/src/providers/anthropic/AnthropicProvider.modelParams.test.js +0 -48
- package/dist/src/providers/anthropic/AnthropicProvider.modelParams.test.js.map +0 -1
- package/dist/src/providers/anthropic/AnthropicProvider.test.d.ts +0 -1
- package/dist/src/providers/anthropic/AnthropicProvider.test.js +0 -487
- package/dist/src/providers/anthropic/AnthropicProvider.test.js.map +0 -1
- package/dist/src/providers/gemini/GeminiProvider.integration.test.d.ts +0 -6
- package/dist/src/providers/gemini/GeminiProvider.integration.test.js +0 -126
- package/dist/src/providers/gemini/GeminiProvider.integration.test.js.map +0 -1
- package/dist/src/providers/gemini/GeminiProvider.test.d.ts +0 -6
- package/dist/src/providers/gemini/GeminiProvider.test.js +0 -136
- package/dist/src/providers/gemini/GeminiProvider.test.js.map +0 -1
- package/dist/src/providers/integration/multi-provider.integration.test.d.ts +0 -6
- package/dist/src/providers/integration/multi-provider.integration.test.js +0 -292
- package/dist/src/providers/integration/multi-provider.integration.test.js.map +0 -1
- package/dist/src/providers/openai/ConversationCache.accumTokens.test.d.ts +0 -1
- package/dist/src/providers/openai/ConversationCache.accumTokens.test.js +0 -97
- package/dist/src/providers/openai/ConversationCache.accumTokens.test.js.map +0 -1
- package/dist/src/providers/openai/ConversationCache.test.d.ts +0 -1
- package/dist/src/providers/openai/ConversationCache.test.js +0 -113
- package/dist/src/providers/openai/ConversationCache.test.js.map +0 -1
- package/dist/src/providers/openai/OpenAIProvider.callResponses.stateless.test.d.ts +0 -1
- package/dist/src/providers/openai/OpenAIProvider.callResponses.stateless.test.js +0 -189
- package/dist/src/providers/openai/OpenAIProvider.callResponses.stateless.test.js.map +0 -1
- package/dist/src/providers/openai/OpenAIProvider.integration.test.d.ts +0 -6
- package/dist/src/providers/openai/OpenAIProvider.integration.test.js +0 -125
- package/dist/src/providers/openai/OpenAIProvider.integration.test.js.map +0 -1
- package/dist/src/providers/openai/OpenAIProvider.responses.test.d.ts +0 -1
- package/dist/src/providers/openai/OpenAIProvider.responses.test.js +0 -350
- package/dist/src/providers/openai/OpenAIProvider.responses.test.js.map +0 -1
- package/dist/src/providers/openai/OpenAIProvider.responsesIntegration.test.d.ts +0 -1
- package/dist/src/providers/openai/OpenAIProvider.responsesIntegration.test.js +0 -213
- package/dist/src/providers/openai/OpenAIProvider.responsesIntegration.test.js.map +0 -1
- package/dist/src/providers/openai/OpenAIProvider.shouldUseResponses.test.d.ts +0 -1
- package/dist/src/providers/openai/OpenAIProvider.shouldUseResponses.test.js +0 -59
- package/dist/src/providers/openai/OpenAIProvider.shouldUseResponses.test.js.map +0 -1
- package/dist/src/providers/openai/OpenAIProvider.stateful.integration.test.d.ts +0 -6
- package/dist/src/providers/openai/OpenAIProvider.stateful.integration.test.js +0 -105
- package/dist/src/providers/openai/OpenAIProvider.stateful.integration.test.js.map +0 -1
- package/dist/src/providers/openai/OpenAIProvider.switch.test.d.ts +0 -1
- package/dist/src/providers/openai/OpenAIProvider.switch.test.js +0 -256
- package/dist/src/providers/openai/OpenAIProvider.switch.test.js.map +0 -1
- package/dist/src/providers/openai/OpenAIProvider.test.d.ts +0 -16
- package/dist/src/providers/openai/OpenAIProvider.test.js +0 -620
- package/dist/src/providers/openai/OpenAIProvider.test.js.map +0 -1
- package/dist/src/providers/openai/ResponsesContextTrim.integration.test.d.ts +0 -1
- package/dist/src/providers/openai/ResponsesContextTrim.integration.test.js +0 -210
- package/dist/src/providers/openai/ResponsesContextTrim.integration.test.js.map +0 -1
- package/dist/src/providers/openai/__tests__/formatArrayResponse.test.d.ts +0 -1
- package/dist/src/providers/openai/__tests__/formatArrayResponse.test.js +0 -65
- package/dist/src/providers/openai/__tests__/formatArrayResponse.test.js.map +0 -1
- package/dist/src/providers/openai/buildResponsesRequest.stripToolCalls.test.d.ts +0 -1
- package/dist/src/providers/openai/buildResponsesRequest.stripToolCalls.test.js +0 -129
- package/dist/src/providers/openai/buildResponsesRequest.stripToolCalls.test.js.map +0 -1
- package/dist/src/providers/openai/buildResponsesRequest.test.d.ts +0 -1
- package/dist/src/providers/openai/buildResponsesRequest.test.js +0 -406
- package/dist/src/providers/openai/buildResponsesRequest.test.js.map +0 -1
- package/dist/src/providers/openai/buildResponsesRequest.undefined.test.d.ts +0 -1
- package/dist/src/providers/openai/buildResponsesRequest.undefined.test.js +0 -50
- package/dist/src/providers/openai/buildResponsesRequest.undefined.test.js.map +0 -1
- package/dist/src/providers/openai/estimateRemoteTokens.test.d.ts +0 -1
- package/dist/src/providers/openai/estimateRemoteTokens.test.js +0 -125
- package/dist/src/providers/openai/estimateRemoteTokens.test.js.map +0 -1
- package/dist/src/providers/openai/parseResponsesStream.responsesToolCalls.test.d.ts +0 -1
- package/dist/src/providers/openai/parseResponsesStream.responsesToolCalls.test.js +0 -192
- package/dist/src/providers/openai/parseResponsesStream.responsesToolCalls.test.js.map +0 -1
- package/dist/src/providers/openai/parseResponsesStream.test.d.ts +0 -1
- package/dist/src/providers/openai/parseResponsesStream.test.js +0 -151
- package/dist/src/providers/openai/parseResponsesStream.test.js.map +0 -1
- package/dist/src/services/fileDiscoveryService.test.d.ts +0 -6
- package/dist/src/services/fileDiscoveryService.test.js +0 -143
- package/dist/src/services/fileDiscoveryService.test.js.map +0 -1
- package/dist/src/services/gitService.test.d.ts +0 -6
- package/dist/src/services/gitService.test.js +0 -209
- package/dist/src/services/gitService.test.js.map +0 -1
- package/dist/src/services/loopDetectionService.test.d.ts +0 -6
- package/dist/src/services/loopDetectionService.test.js +0 -484
- package/dist/src/services/loopDetectionService.test.js.map +0 -1
- package/dist/src/services/shellExecutionService.multibyte.test.d.ts +0 -6
- package/dist/src/services/shellExecutionService.multibyte.test.js +0 -72
- package/dist/src/services/shellExecutionService.multibyte.test.js.map +0 -1
- package/dist/src/services/shellExecutionService.test.d.ts +0 -6
- package/dist/src/services/shellExecutionService.test.js +0 -272
- package/dist/src/services/shellExecutionService.test.js.map +0 -1
- package/dist/src/services/shellExecutionService.windows.multibyte.test.d.ts +0 -6
- package/dist/src/services/shellExecutionService.windows.multibyte.test.js +0 -98
- package/dist/src/services/shellExecutionService.windows.multibyte.test.js.map +0 -1
- package/dist/src/services/shellExecutionService.windows.test.d.ts +0 -6
- package/dist/src/services/shellExecutionService.windows.test.js +0 -79
- package/dist/src/services/shellExecutionService.windows.test.js.map +0 -1
- package/dist/src/services/tool-call-tracker-service.test.d.ts +0 -6
- package/dist/src/services/tool-call-tracker-service.test.js +0 -99
- package/dist/src/services/tool-call-tracker-service.test.js.map +0 -1
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.d.ts +0 -6
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js +0 -187
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js.map +0 -1
- package/dist/src/telemetry/loggers.test.d.ts +0 -6
- package/dist/src/telemetry/loggers.test.js +0 -573
- package/dist/src/telemetry/loggers.test.js.map +0 -1
- package/dist/src/telemetry/metrics.test.d.ts +0 -6
- package/dist/src/telemetry/metrics.test.js +0 -212
- package/dist/src/telemetry/metrics.test.js.map +0 -1
- package/dist/src/telemetry/telemetry.test.d.ts +0 -6
- package/dist/src/telemetry/telemetry.test.js +0 -54
- package/dist/src/telemetry/telemetry.test.js.map +0 -1
- package/dist/src/telemetry/uiTelemetry.test.d.ts +0 -6
- package/dist/src/telemetry/uiTelemetry.test.js +0 -518
- package/dist/src/telemetry/uiTelemetry.test.js.map +0 -1
- package/dist/src/tools/ToolFormatter.test.d.ts +0 -16
- package/dist/src/tools/ToolFormatter.test.js +0 -349
- package/dist/src/tools/ToolFormatter.test.js.map +0 -1
- package/dist/src/tools/ToolFormatter.toResponsesTool.test.d.ts +0 -1
- package/dist/src/tools/ToolFormatter.toResponsesTool.test.js +0 -241
- package/dist/src/tools/ToolFormatter.toResponsesTool.test.js.map +0 -1
- package/dist/src/tools/diffOptions.test.d.ts +0 -6
- package/dist/src/tools/diffOptions.test.js +0 -119
- package/dist/src/tools/diffOptions.test.js.map +0 -1
- package/dist/src/tools/edit.test.d.ts +0 -6
- package/dist/src/tools/edit.test.js +0 -689
- package/dist/src/tools/edit.test.js.map +0 -1
- package/dist/src/tools/glob.test.d.ts +0 -6
- package/dist/src/tools/glob.test.js +0 -332
- package/dist/src/tools/glob.test.js.map +0 -1
- package/dist/src/tools/grep.test.d.ts +0 -6
- package/dist/src/tools/grep.test.js +0 -272
- package/dist/src/tools/grep.test.js.map +0 -1
- package/dist/src/tools/ls.test.d.ts +0 -6
- package/dist/src/tools/ls.test.js +0 -357
- package/dist/src/tools/ls.test.js.map +0 -1
- package/dist/src/tools/mcp-client.test.d.ts +0 -6
- package/dist/src/tools/mcp-client.test.js +0 -617
- package/dist/src/tools/mcp-client.test.js.map +0 -1
- package/dist/src/tools/mcp-tool.test.d.ts +0 -6
- package/dist/src/tools/mcp-tool.test.js +0 -501
- package/dist/src/tools/mcp-tool.test.js.map +0 -1
- package/dist/src/tools/memoryTool.test.d.ts +0 -6
- package/dist/src/tools/memoryTool.test.js +0 -266
- package/dist/src/tools/memoryTool.test.js.map +0 -1
- package/dist/src/tools/modifiable-tool.test.d.ts +0 -6
- package/dist/src/tools/modifiable-tool.test.js +0 -193
- package/dist/src/tools/modifiable-tool.test.js.map +0 -1
- package/dist/src/tools/read-file.test.d.ts +0 -6
- package/dist/src/tools/read-file.test.js +0 -319
- package/dist/src/tools/read-file.test.js.map +0 -1
- package/dist/src/tools/read-many-files.test.d.ts +0 -6
- package/dist/src/tools/read-many-files.test.js +0 -644
- package/dist/src/tools/read-many-files.test.js.map +0 -1
- package/dist/src/tools/shell.multibyte.test.d.ts +0 -6
- package/dist/src/tools/shell.multibyte.test.js +0 -75
- package/dist/src/tools/shell.multibyte.test.js.map +0 -1
- package/dist/src/tools/shell.test.d.ts +0 -6
- package/dist/src/tools/shell.test.js +0 -367
- package/dist/src/tools/shell.test.js.map +0 -1
- package/dist/src/tools/todo-pause.spec.d.ts +0 -6
- package/dist/src/tools/todo-pause.spec.js +0 -287
- package/dist/src/tools/todo-pause.spec.js.map +0 -1
- package/dist/src/tools/todo-read.test.d.ts +0 -6
- package/dist/src/tools/todo-read.test.js +0 -162
- package/dist/src/tools/todo-read.test.js.map +0 -1
- package/dist/src/tools/todo-schemas.test.d.ts +0 -6
- package/dist/src/tools/todo-schemas.test.js +0 -341
- package/dist/src/tools/todo-schemas.test.js.map +0 -1
- package/dist/src/tools/todo-store.test.d.ts +0 -6
- package/dist/src/tools/todo-store.test.js +0 -169
- package/dist/src/tools/todo-store.test.js.map +0 -1
- package/dist/src/tools/todo-write.test.d.ts +0 -6
- package/dist/src/tools/todo-write.test.js +0 -226
- package/dist/src/tools/todo-write.test.js.map +0 -1
- package/dist/src/tools/tool-registry.test.d.ts +0 -6
- package/dist/src/tools/tool-registry.test.js +0 -468
- package/dist/src/tools/tool-registry.test.js.map +0 -1
- package/dist/src/tools/tools.test.d.ts +0 -6
- package/dist/src/tools/tools.test.js +0 -117
- package/dist/src/tools/tools.test.js.map +0 -1
- package/dist/src/tools/web-fetch.integration.test.d.ts +0 -6
- package/dist/src/tools/web-fetch.integration.test.js +0 -532
- package/dist/src/tools/web-fetch.integration.test.js.map +0 -1
- package/dist/src/tools/web-search.test.d.ts +0 -6
- package/dist/src/tools/web-search.test.js +0 -230
- package/dist/src/tools/web-search.test.js.map +0 -1
- package/dist/src/tools/write-file.test.d.ts +0 -6
- package/dist/src/tools/write-file.test.js +0 -465
- package/dist/src/tools/write-file.test.js.map +0 -1
- package/dist/src/utils/bfsFileSearch.test.d.ts +0 -6
- package/dist/src/utils/bfsFileSearch.test.js +0 -191
- package/dist/src/utils/bfsFileSearch.test.js.map +0 -1
- package/dist/src/utils/editCorrector.test.d.ts +0 -6
- package/dist/src/utils/editCorrector.test.js +0 -564
- package/dist/src/utils/editCorrector.test.js.map +0 -1
- package/dist/src/utils/editor.test.d.ts +0 -6
- package/dist/src/utils/editor.test.js +0 -445
- package/dist/src/utils/editor.test.js.map +0 -1
- package/dist/src/utils/environmentContext.test.d.ts +0 -6
- package/dist/src/utils/environmentContext.test.js +0 -139
- package/dist/src/utils/environmentContext.test.js.map +0 -1
- package/dist/src/utils/errorReporting.test.d.ts +0 -6
- package/dist/src/utils/errorReporting.test.js +0 -130
- package/dist/src/utils/errorReporting.test.js.map +0 -1
- package/dist/src/utils/fileUtils.test.d.ts +0 -6
- package/dist/src/utils/fileUtils.test.js +0 -363
- package/dist/src/utils/fileUtils.test.js.map +0 -1
- package/dist/src/utils/filesearch/crawlCache.test.d.ts +0 -6
- package/dist/src/utils/filesearch/crawlCache.test.js +0 -103
- package/dist/src/utils/filesearch/crawlCache.test.js.map +0 -1
- package/dist/src/utils/filesearch/fileSearch.test.d.ts +0 -6
- package/dist/src/utils/filesearch/fileSearch.test.js +0 -654
- package/dist/src/utils/filesearch/fileSearch.test.js.map +0 -1
- package/dist/src/utils/filesearch/ignore.test.d.ts +0 -6
- package/dist/src/utils/filesearch/ignore.test.js +0 -57
- package/dist/src/utils/filesearch/ignore.test.js.map +0 -1
- package/dist/src/utils/filesearch/result-cache.test.d.ts +0 -6
- package/dist/src/utils/filesearch/result-cache.test.js +0 -47
- package/dist/src/utils/filesearch/result-cache.test.js.map +0 -1
- package/dist/src/utils/flashFallback.integration.test.d.ts +0 -6
- package/dist/src/utils/flashFallback.integration.test.js +0 -120
- package/dist/src/utils/flashFallback.integration.test.js.map +0 -1
- package/dist/src/utils/generateContentResponseUtilities.test.d.ts +0 -6
- package/dist/src/utils/generateContentResponseUtilities.test.js +0 -273
- package/dist/src/utils/generateContentResponseUtilities.test.js.map +0 -1
- package/dist/src/utils/getFolderStructure.test.d.ts +0 -6
- package/dist/src/utils/getFolderStructure.test.js +0 -282
- package/dist/src/utils/getFolderStructure.test.js.map +0 -1
- package/dist/src/utils/gitIgnoreParser.test.d.ts +0 -6
- package/dist/src/utils/gitIgnoreParser.test.js +0 -154
- package/dist/src/utils/gitIgnoreParser.test.js.map +0 -1
- package/dist/src/utils/memoryDiscovery.test.d.ts +0 -6
- package/dist/src/utils/memoryDiscovery.test.js +0 -181
- package/dist/src/utils/memoryDiscovery.test.js.map +0 -1
- package/dist/src/utils/memoryImportProcessor.test.d.ts +0 -6
- package/dist/src/utils/memoryImportProcessor.test.js +0 -715
- package/dist/src/utils/memoryImportProcessor.test.js.map +0 -1
- package/dist/src/utils/nextSpeakerChecker.test.d.ts +0 -6
- package/dist/src/utils/nextSpeakerChecker.test.js +0 -172
- package/dist/src/utils/nextSpeakerChecker.test.js.map +0 -1
- package/dist/src/utils/partUtils.test.d.ts +0 -6
- package/dist/src/utils/partUtils.test.js +0 -130
- package/dist/src/utils/partUtils.test.js.map +0 -1
- package/dist/src/utils/paths.test.d.ts +0 -6
- package/dist/src/utils/paths.test.js +0 -153
- package/dist/src/utils/paths.test.js.map +0 -1
- package/dist/src/utils/retry.test.d.ts +0 -6
- package/dist/src/utils/retry.test.js +0 -322
- package/dist/src/utils/retry.test.js.map +0 -1
- package/dist/src/utils/safeJsonStringify.test.d.ts +0 -6
- package/dist/src/utils/safeJsonStringify.test.js +0 -61
- package/dist/src/utils/safeJsonStringify.test.js.map +0 -1
- package/dist/src/utils/sanitization.test.d.ts +0 -6
- package/dist/src/utils/sanitization.test.js +0 -81
- package/dist/src/utils/sanitization.test.js.map +0 -1
- package/dist/src/utils/schemaValidator.test.d.ts +0 -6
- package/dist/src/utils/schemaValidator.test.js +0 -146
- package/dist/src/utils/schemaValidator.test.js.map +0 -1
- package/dist/src/utils/secure-browser-launcher.test.d.ts +0 -6
- package/dist/src/utils/secure-browser-launcher.test.js +0 -149
- package/dist/src/utils/secure-browser-launcher.test.js.map +0 -1
- package/dist/src/utils/shell-utils.shellReplacement.test.d.ts +0 -6
- package/dist/src/utils/shell-utils.shellReplacement.test.js +0 -149
- package/dist/src/utils/shell-utils.shellReplacement.test.js.map +0 -1
- package/dist/src/utils/shell-utils.test.d.ts +0 -6
- package/dist/src/utils/shell-utils.test.js +0 -200
- package/dist/src/utils/shell-utils.test.js.map +0 -1
- package/dist/src/utils/summarizer.test.d.ts +0 -6
- package/dist/src/utils/summarizer.test.js +0 -131
- package/dist/src/utils/summarizer.test.js.map +0 -1
- package/dist/src/utils/systemEncoding.test.d.ts +0 -6
- package/dist/src/utils/systemEncoding.test.js +0 -368
- package/dist/src/utils/systemEncoding.test.js.map +0 -1
- package/dist/src/utils/toolOutputLimiter.test.d.ts +0 -6
- package/dist/src/utils/toolOutputLimiter.test.js +0 -164
- package/dist/src/utils/toolOutputLimiter.test.js.map +0 -1
- package/dist/src/utils/unicodeUtils.test.d.ts +0 -6
- package/dist/src/utils/unicodeUtils.test.js +0 -120
- package/dist/src/utils/unicodeUtils.test.js.map +0 -1
- package/dist/src/utils/user_account.test.d.ts +0 -6
- package/dist/src/utils/user_account.test.js +0 -153
- package/dist/src/utils/user_account.test.js.map +0 -1
- package/dist/src/utils/user_id.test.d.ts +0 -6
- package/dist/src/utils/user_id.test.js +0 -21
- package/dist/src/utils/user_id.test.js.map +0 -1
- package/dist/src/utils/workspaceContext.test.d.ts +0 -6
- package/dist/src/utils/workspaceContext.test.js +0 -209
- package/dist/src/utils/workspaceContext.test.js.map +0 -1
|
@@ -1,715 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright 2025 Google LLC
|
|
4
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
-
*/
|
|
6
|
-
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
7
|
-
import * as fs from 'fs/promises';
|
|
8
|
-
import * as path from 'path';
|
|
9
|
-
import { marked } from 'marked';
|
|
10
|
-
import { processImports, validateImportPath } from './memoryImportProcessor.js';
|
|
11
|
-
// Helper function to create platform-agnostic test paths
|
|
12
|
-
const testPath = (...segments) => {
|
|
13
|
-
// Start with the first segment as is (might be an absolute path on Windows)
|
|
14
|
-
let result = segments[0];
|
|
15
|
-
// Join remaining segments with the platform-specific separator
|
|
16
|
-
for (let i = 1; i < segments.length; i++) {
|
|
17
|
-
if (segments[i].startsWith('/') || segments[i].startsWith('\\')) {
|
|
18
|
-
// If segment starts with a separator, remove the trailing separator from the result
|
|
19
|
-
result = path.normalize(result.replace(/[\\/]+$/, '') + segments[i]);
|
|
20
|
-
}
|
|
21
|
-
else {
|
|
22
|
-
// Otherwise join with the platform separator
|
|
23
|
-
result = path.join(result, segments[i]);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
return path.normalize(result);
|
|
27
|
-
};
|
|
28
|
-
// Mock fs/promises
|
|
29
|
-
vi.mock('fs/promises');
|
|
30
|
-
const mockedFs = vi.mocked(fs);
|
|
31
|
-
// Mock console methods to capture warnings
|
|
32
|
-
const originalConsoleWarn = console.warn;
|
|
33
|
-
const originalConsoleError = console.error;
|
|
34
|
-
const originalConsoleDebug = console.debug;
|
|
35
|
-
// Helper functions using marked for parsing and validation
|
|
36
|
-
const parseMarkdown = (content) => marked.lexer(content);
|
|
37
|
-
const findMarkdownComments = (content) => {
|
|
38
|
-
const tokens = parseMarkdown(content);
|
|
39
|
-
const comments = [];
|
|
40
|
-
function walkTokens(tokenList) {
|
|
41
|
-
for (const token of tokenList) {
|
|
42
|
-
const t = token;
|
|
43
|
-
if (t.type === 'html' && t.raw.includes('<!--')) {
|
|
44
|
-
comments.push(t.raw.trim());
|
|
45
|
-
}
|
|
46
|
-
if (t.tokens) {
|
|
47
|
-
walkTokens(t.tokens);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
walkTokens(tokens);
|
|
52
|
-
return comments;
|
|
53
|
-
};
|
|
54
|
-
const findCodeBlocks = (content) => {
|
|
55
|
-
const tokens = parseMarkdown(content);
|
|
56
|
-
const codeBlocks = [];
|
|
57
|
-
function walkTokens(tokenList) {
|
|
58
|
-
for (const token of tokenList) {
|
|
59
|
-
const t = token;
|
|
60
|
-
if (t.type === 'code') {
|
|
61
|
-
codeBlocks.push({
|
|
62
|
-
type: 'code_block',
|
|
63
|
-
content: t.text,
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
else if (t.type === 'codespan') {
|
|
67
|
-
codeBlocks.push({
|
|
68
|
-
type: 'inline_code',
|
|
69
|
-
content: t.text,
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
if (t.tokens) {
|
|
73
|
-
walkTokens(t.tokens);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
walkTokens(tokens);
|
|
78
|
-
return codeBlocks;
|
|
79
|
-
};
|
|
80
|
-
describe('memoryImportProcessor', () => {
|
|
81
|
-
beforeEach(() => {
|
|
82
|
-
vi.clearAllMocks();
|
|
83
|
-
// Mock console methods
|
|
84
|
-
console.warn = vi.fn();
|
|
85
|
-
console.error = vi.fn();
|
|
86
|
-
console.debug = vi.fn();
|
|
87
|
-
});
|
|
88
|
-
afterEach(() => {
|
|
89
|
-
// Restore console methods
|
|
90
|
-
console.warn = originalConsoleWarn;
|
|
91
|
-
console.error = originalConsoleError;
|
|
92
|
-
console.debug = originalConsoleDebug;
|
|
93
|
-
});
|
|
94
|
-
describe('processImports', () => {
|
|
95
|
-
it('should process basic md file imports', async () => {
|
|
96
|
-
const content = 'Some content @./test.md more content';
|
|
97
|
-
const basePath = testPath('test', 'path');
|
|
98
|
-
const importedContent = '# Imported Content\nThis is imported.';
|
|
99
|
-
mockedFs.access.mockResolvedValue(undefined);
|
|
100
|
-
mockedFs.readFile.mockResolvedValue(importedContent);
|
|
101
|
-
const result = await processImports(content, basePath, true);
|
|
102
|
-
// Use marked to find HTML comments (import markers)
|
|
103
|
-
const comments = findMarkdownComments(result.content);
|
|
104
|
-
expect(comments.some((c) => c.includes('Imported from: ./test.md'))).toBe(true);
|
|
105
|
-
expect(comments.some((c) => c.includes('End of import from: ./test.md'))).toBe(true);
|
|
106
|
-
// Verify the imported content is present
|
|
107
|
-
expect(result.content).toContain(importedContent);
|
|
108
|
-
// Verify the markdown structure is valid
|
|
109
|
-
const tokens = parseMarkdown(result.content);
|
|
110
|
-
expect(tokens).toBeDefined();
|
|
111
|
-
expect(tokens.length).toBeGreaterThan(0);
|
|
112
|
-
expect(mockedFs.readFile).toHaveBeenCalledWith(path.resolve(basePath, './test.md'), 'utf-8');
|
|
113
|
-
});
|
|
114
|
-
it('should import non-md files just like md files', async () => {
|
|
115
|
-
const content = 'Some content @./instructions.txt more content';
|
|
116
|
-
const basePath = testPath('test', 'path');
|
|
117
|
-
const importedContent = '# Instructions\nThis is a text file with markdown.';
|
|
118
|
-
mockedFs.access.mockResolvedValue(undefined);
|
|
119
|
-
mockedFs.readFile.mockResolvedValue(importedContent);
|
|
120
|
-
const result = await processImports(content, basePath, true);
|
|
121
|
-
// Use marked to find import comments
|
|
122
|
-
const comments = findMarkdownComments(result.content);
|
|
123
|
-
expect(comments.some((c) => c.includes('Imported from: ./instructions.txt'))).toBe(true);
|
|
124
|
-
expect(comments.some((c) => c.includes('End of import from: ./instructions.txt'))).toBe(true);
|
|
125
|
-
// Use marked to parse and validate the imported content structure
|
|
126
|
-
const tokens = parseMarkdown(result.content);
|
|
127
|
-
// Find headers in the parsed content
|
|
128
|
-
const headers = tokens.filter((token) => token.type === 'heading');
|
|
129
|
-
expect(headers.some((h) => h.text === 'Instructions')).toBe(true);
|
|
130
|
-
// Verify the imported content is present
|
|
131
|
-
expect(result.content).toContain(importedContent);
|
|
132
|
-
expect(console.warn).not.toHaveBeenCalled();
|
|
133
|
-
expect(mockedFs.readFile).toHaveBeenCalledWith(path.resolve(basePath, './instructions.txt'), 'utf-8');
|
|
134
|
-
});
|
|
135
|
-
it('should handle circular imports', async () => {
|
|
136
|
-
const content = 'Content @./circular.md more content';
|
|
137
|
-
const basePath = testPath('test', 'path');
|
|
138
|
-
const circularContent = 'Circular @./main.md content';
|
|
139
|
-
mockedFs.access.mockResolvedValue(undefined);
|
|
140
|
-
mockedFs.readFile.mockResolvedValue(circularContent);
|
|
141
|
-
// Set up the import state to simulate we're already processing main.md
|
|
142
|
-
const importState = {
|
|
143
|
-
processedFiles: new Set(),
|
|
144
|
-
maxDepth: 10,
|
|
145
|
-
currentDepth: 0,
|
|
146
|
-
currentFile: testPath('test', 'path', 'main.md'), // Simulate we're processing main.md
|
|
147
|
-
};
|
|
148
|
-
const result = await processImports(content, basePath, true, importState);
|
|
149
|
-
// The circular import should be detected when processing the nested import
|
|
150
|
-
expect(result.content).toContain('<!-- File already processed: ./main.md -->');
|
|
151
|
-
});
|
|
152
|
-
it('should handle file not found errors', async () => {
|
|
153
|
-
const content = 'Content @./nonexistent.md more content';
|
|
154
|
-
const basePath = testPath('test', 'path');
|
|
155
|
-
mockedFs.access.mockRejectedValue(new Error('File not found'));
|
|
156
|
-
const result = await processImports(content, basePath, true);
|
|
157
|
-
expect(result.content).toContain('<!-- Import failed: ./nonexistent.md - File not found -->');
|
|
158
|
-
expect(console.error).toHaveBeenCalledWith('[ERROR] [ImportProcessor]', 'Failed to import ./nonexistent.md: File not found');
|
|
159
|
-
});
|
|
160
|
-
it('should respect max depth limit', async () => {
|
|
161
|
-
const content = 'Content @./deep.md more content';
|
|
162
|
-
const basePath = testPath('test', 'path');
|
|
163
|
-
const deepContent = 'Deep @./deeper.md content';
|
|
164
|
-
mockedFs.access.mockResolvedValue(undefined);
|
|
165
|
-
mockedFs.readFile.mockResolvedValue(deepContent);
|
|
166
|
-
const importState = {
|
|
167
|
-
processedFiles: new Set(),
|
|
168
|
-
maxDepth: 1,
|
|
169
|
-
currentDepth: 1,
|
|
170
|
-
};
|
|
171
|
-
const result = await processImports(content, basePath, true, importState);
|
|
172
|
-
expect(console.warn).toHaveBeenCalledWith('[WARN] [ImportProcessor]', 'Maximum import depth (1) reached. Stopping import processing.');
|
|
173
|
-
expect(result.content).toBe(content);
|
|
174
|
-
});
|
|
175
|
-
it('should handle nested imports recursively', async () => {
|
|
176
|
-
const content = 'Main @./nested.md content';
|
|
177
|
-
const basePath = testPath('test', 'path');
|
|
178
|
-
const nestedContent = 'Nested @./inner.md content';
|
|
179
|
-
const innerContent = 'Inner content';
|
|
180
|
-
mockedFs.access.mockResolvedValue(undefined);
|
|
181
|
-
mockedFs.readFile
|
|
182
|
-
.mockResolvedValueOnce(nestedContent)
|
|
183
|
-
.mockResolvedValueOnce(innerContent);
|
|
184
|
-
const result = await processImports(content, basePath, true);
|
|
185
|
-
expect(result.content).toContain('<!-- Imported from: ./nested.md -->');
|
|
186
|
-
expect(result.content).toContain('<!-- Imported from: ./inner.md -->');
|
|
187
|
-
expect(result.content).toContain(innerContent);
|
|
188
|
-
});
|
|
189
|
-
it('should handle absolute paths in imports', async () => {
|
|
190
|
-
const content = 'Content @/absolute/path/file.md more content';
|
|
191
|
-
const basePath = testPath('test', 'path');
|
|
192
|
-
const importedContent = 'Absolute path content';
|
|
193
|
-
mockedFs.access.mockResolvedValue(undefined);
|
|
194
|
-
mockedFs.readFile.mockResolvedValue(importedContent);
|
|
195
|
-
const result = await processImports(content, basePath, true);
|
|
196
|
-
expect(result.content).toContain('<!-- Import failed: /absolute/path/file.md - Path traversal attempt -->');
|
|
197
|
-
});
|
|
198
|
-
it('should handle multiple imports in same content', async () => {
|
|
199
|
-
const content = 'Start @./first.md middle @./second.md end';
|
|
200
|
-
const basePath = testPath('test', 'path');
|
|
201
|
-
const firstContent = 'First content';
|
|
202
|
-
const secondContent = 'Second content';
|
|
203
|
-
mockedFs.access.mockResolvedValue(undefined);
|
|
204
|
-
mockedFs.readFile
|
|
205
|
-
.mockResolvedValueOnce(firstContent)
|
|
206
|
-
.mockResolvedValueOnce(secondContent);
|
|
207
|
-
const result = await processImports(content, basePath, true);
|
|
208
|
-
expect(result.content).toContain('<!-- Imported from: ./first.md -->');
|
|
209
|
-
expect(result.content).toContain('<!-- Imported from: ./second.md -->');
|
|
210
|
-
expect(result.content).toContain(firstContent);
|
|
211
|
-
expect(result.content).toContain(secondContent);
|
|
212
|
-
});
|
|
213
|
-
it('should ignore imports inside code blocks', async () => {
|
|
214
|
-
const content = [
|
|
215
|
-
'Normal content @./should-import.md',
|
|
216
|
-
'```',
|
|
217
|
-
'code block with @./should-not-import.md',
|
|
218
|
-
'```',
|
|
219
|
-
'More content @./should-import2.md',
|
|
220
|
-
].join('\n');
|
|
221
|
-
const projectRoot = testPath('test', 'project');
|
|
222
|
-
const basePath = testPath(projectRoot, 'src');
|
|
223
|
-
const importedContent1 = 'Imported 1';
|
|
224
|
-
const importedContent2 = 'Imported 2';
|
|
225
|
-
// Only the imports outside code blocks should be processed
|
|
226
|
-
mockedFs.access.mockResolvedValue(undefined);
|
|
227
|
-
mockedFs.readFile
|
|
228
|
-
.mockResolvedValueOnce(importedContent1)
|
|
229
|
-
.mockResolvedValueOnce(importedContent2);
|
|
230
|
-
const result = await processImports(content, basePath, true, undefined, projectRoot);
|
|
231
|
-
// Use marked to verify imported content is present
|
|
232
|
-
expect(result.content).toContain(importedContent1);
|
|
233
|
-
expect(result.content).toContain(importedContent2);
|
|
234
|
-
// Use marked to find code blocks and verify the import wasn't processed
|
|
235
|
-
const codeBlocks = findCodeBlocks(result.content);
|
|
236
|
-
const hasUnprocessedImport = codeBlocks.some((block) => block.content.includes('@./should-not-import.md'));
|
|
237
|
-
expect(hasUnprocessedImport).toBe(true);
|
|
238
|
-
// Verify no import comment was created for the code block import
|
|
239
|
-
const comments = findMarkdownComments(result.content);
|
|
240
|
-
expect(comments.some((c) => c.includes('should-not-import.md'))).toBe(false);
|
|
241
|
-
});
|
|
242
|
-
it('should ignore imports inside inline code', async () => {
|
|
243
|
-
const content = [
|
|
244
|
-
'Normal content @./should-import.md',
|
|
245
|
-
'`code with import @./should-not-import.md`',
|
|
246
|
-
'More content @./should-import2.md',
|
|
247
|
-
].join('\n');
|
|
248
|
-
const projectRoot = testPath('test', 'project');
|
|
249
|
-
const basePath = testPath(projectRoot, 'src');
|
|
250
|
-
const importedContent1 = 'Imported 1';
|
|
251
|
-
const importedContent2 = 'Imported 2';
|
|
252
|
-
mockedFs.access.mockResolvedValue(undefined);
|
|
253
|
-
mockedFs.readFile
|
|
254
|
-
.mockResolvedValueOnce(importedContent1)
|
|
255
|
-
.mockResolvedValueOnce(importedContent2);
|
|
256
|
-
const result = await processImports(content, basePath, true, undefined, projectRoot);
|
|
257
|
-
// Verify imported content is present
|
|
258
|
-
expect(result.content).toContain(importedContent1);
|
|
259
|
-
expect(result.content).toContain(importedContent2);
|
|
260
|
-
// Use marked to find inline code spans
|
|
261
|
-
const codeBlocks = findCodeBlocks(result.content);
|
|
262
|
-
const inlineCodeSpans = codeBlocks.filter((block) => block.type === 'inline_code');
|
|
263
|
-
// Verify the inline code span still contains the unprocessed import
|
|
264
|
-
expect(inlineCodeSpans.some((span) => span.content.includes('@./should-not-import.md'))).toBe(true);
|
|
265
|
-
// Verify no import comments were created for inline code imports
|
|
266
|
-
const comments = findMarkdownComments(result.content);
|
|
267
|
-
expect(comments.some((c) => c.includes('should-not-import.md'))).toBe(false);
|
|
268
|
-
});
|
|
269
|
-
it('should handle nested tokens and non-unique content correctly', async () => {
|
|
270
|
-
// This test verifies the robust findCodeRegions implementation
|
|
271
|
-
// that recursively walks the token tree and handles non-unique content
|
|
272
|
-
const content = [
|
|
273
|
-
'Normal content @./should-import.md',
|
|
274
|
-
'Paragraph with `inline code @./should-not-import.md` and more text.',
|
|
275
|
-
'Another paragraph with the same `inline code @./should-not-import.md` text.',
|
|
276
|
-
'More content @./should-import2.md',
|
|
277
|
-
].join('\n');
|
|
278
|
-
const projectRoot = testPath('test', 'project');
|
|
279
|
-
const basePath = testPath(projectRoot, 'src');
|
|
280
|
-
const importedContent1 = 'Imported 1';
|
|
281
|
-
const importedContent2 = 'Imported 2';
|
|
282
|
-
mockedFs.access.mockResolvedValue(undefined);
|
|
283
|
-
mockedFs.readFile
|
|
284
|
-
.mockResolvedValueOnce(importedContent1)
|
|
285
|
-
.mockResolvedValueOnce(importedContent2);
|
|
286
|
-
const result = await processImports(content, basePath, true, undefined, projectRoot);
|
|
287
|
-
// Should process imports outside code regions
|
|
288
|
-
expect(result.content).toContain(importedContent1);
|
|
289
|
-
expect(result.content).toContain(importedContent2);
|
|
290
|
-
// Should preserve imports inside inline code (both occurrences)
|
|
291
|
-
expect(result.content).toContain('`inline code @./should-not-import.md`');
|
|
292
|
-
// Should not have processed the imports inside code regions
|
|
293
|
-
expect(result.content).not.toContain('<!-- Imported from: ./should-not-import.md -->');
|
|
294
|
-
});
|
|
295
|
-
it('should allow imports from parent and subdirectories within project root', async () => {
|
|
296
|
-
const content = 'Parent import: @../parent.md Subdir import: @./components/sub.md';
|
|
297
|
-
const projectRoot = testPath('test', 'project');
|
|
298
|
-
const basePath = testPath(projectRoot, 'src');
|
|
299
|
-
const importedParent = 'Parent file content';
|
|
300
|
-
const importedSub = 'Subdir file content';
|
|
301
|
-
mockedFs.access.mockResolvedValue(undefined);
|
|
302
|
-
mockedFs.readFile
|
|
303
|
-
.mockResolvedValueOnce(importedParent)
|
|
304
|
-
.mockResolvedValueOnce(importedSub);
|
|
305
|
-
const result = await processImports(content, basePath, true, undefined, projectRoot);
|
|
306
|
-
expect(result.content).toContain(importedParent);
|
|
307
|
-
expect(result.content).toContain(importedSub);
|
|
308
|
-
});
|
|
309
|
-
it('should reject imports outside project root', async () => {
|
|
310
|
-
const content = 'Outside import: @../../../etc/passwd';
|
|
311
|
-
const projectRoot = testPath('test', 'project');
|
|
312
|
-
const basePath = testPath(projectRoot, 'src');
|
|
313
|
-
const result = await processImports(content, basePath, true, undefined, projectRoot);
|
|
314
|
-
expect(result.content).toContain('<!-- Import failed: ../../../etc/passwd - Path traversal attempt -->');
|
|
315
|
-
});
|
|
316
|
-
it('should build import tree structure', async () => {
|
|
317
|
-
const content = 'Main content @./nested.md @./simple.md';
|
|
318
|
-
const projectRoot = testPath('test', 'project');
|
|
319
|
-
const basePath = testPath(projectRoot, 'src');
|
|
320
|
-
const nestedContent = 'Nested @./inner.md content';
|
|
321
|
-
const simpleContent = 'Simple content';
|
|
322
|
-
const innerContent = 'Inner content';
|
|
323
|
-
mockedFs.access.mockResolvedValue(undefined);
|
|
324
|
-
mockedFs.readFile
|
|
325
|
-
.mockResolvedValueOnce(nestedContent)
|
|
326
|
-
.mockResolvedValueOnce(simpleContent)
|
|
327
|
-
.mockResolvedValueOnce(innerContent);
|
|
328
|
-
const result = await processImports(content, basePath, true);
|
|
329
|
-
// Use marked to find and validate import comments
|
|
330
|
-
const comments = findMarkdownComments(result.content);
|
|
331
|
-
const importComments = comments.filter((c) => c.includes('Imported from:'));
|
|
332
|
-
expect(importComments.some((c) => c.includes('./nested.md'))).toBe(true);
|
|
333
|
-
expect(importComments.some((c) => c.includes('./simple.md'))).toBe(true);
|
|
334
|
-
expect(importComments.some((c) => c.includes('./inner.md'))).toBe(true);
|
|
335
|
-
// Use marked to validate the markdown structure is well-formed
|
|
336
|
-
const tokens = parseMarkdown(result.content);
|
|
337
|
-
expect(tokens).toBeDefined();
|
|
338
|
-
expect(tokens.length).toBeGreaterThan(0);
|
|
339
|
-
// Verify the content contains expected text using marked parsing
|
|
340
|
-
const textContent = tokens
|
|
341
|
-
.filter((token) => token.type === 'paragraph')
|
|
342
|
-
.map((token) => token.raw)
|
|
343
|
-
.join(' ');
|
|
344
|
-
expect(textContent).toContain('Main content');
|
|
345
|
-
expect(textContent).toContain('Nested');
|
|
346
|
-
expect(textContent).toContain('Simple content');
|
|
347
|
-
expect(textContent).toContain('Inner content');
|
|
348
|
-
// Verify import tree structure
|
|
349
|
-
expect(result.importTree.path).toBe('unknown'); // No currentFile set in test
|
|
350
|
-
expect(result.importTree.imports).toHaveLength(2);
|
|
351
|
-
// First import: nested.md
|
|
352
|
-
// Prefix with underscore to indicate they're intentionally unused
|
|
353
|
-
const _expectedNestedPath = testPath(projectRoot, 'src', 'nested.md');
|
|
354
|
-
const _expectedInnerPath = testPath(projectRoot, 'src', 'inner.md');
|
|
355
|
-
const _expectedSimplePath = testPath(projectRoot, 'src', 'simple.md');
|
|
356
|
-
// Check that the paths match using includes to handle potential absolute/relative differences
|
|
357
|
-
expect(result.importTree.imports[0].path).toContain('nested.md');
|
|
358
|
-
expect(result.importTree.imports[0].imports).toHaveLength(1);
|
|
359
|
-
expect(result.importTree.imports[0].imports[0].path).toContain('inner.md');
|
|
360
|
-
expect(result.importTree.imports[0].imports[0].imports).toBeUndefined();
|
|
361
|
-
// Second import: simple.md
|
|
362
|
-
expect(result.importTree.imports[1].path).toContain('simple.md');
|
|
363
|
-
expect(result.importTree.imports[1].imports).toBeUndefined();
|
|
364
|
-
});
|
|
365
|
-
it('should produce flat output in Claude-style with unique files in order', async () => {
|
|
366
|
-
const content = 'Main @./nested.md content @./simple.md';
|
|
367
|
-
const projectRoot = testPath('test', 'project');
|
|
368
|
-
const basePath = testPath(projectRoot, 'src');
|
|
369
|
-
const nestedContent = 'Nested @./inner.md content';
|
|
370
|
-
const simpleContent = 'Simple content';
|
|
371
|
-
const innerContent = 'Inner content';
|
|
372
|
-
mockedFs.access.mockResolvedValue(undefined);
|
|
373
|
-
mockedFs.readFile
|
|
374
|
-
.mockResolvedValueOnce(nestedContent)
|
|
375
|
-
.mockResolvedValueOnce(simpleContent)
|
|
376
|
-
.mockResolvedValueOnce(innerContent);
|
|
377
|
-
const result = await processImports(content, basePath, true, undefined, projectRoot, 'flat');
|
|
378
|
-
// Use marked to parse the output and validate structure
|
|
379
|
-
const tokens = parseMarkdown(result.content);
|
|
380
|
-
expect(tokens).toBeDefined();
|
|
381
|
-
// Find all file markers using marked parsing
|
|
382
|
-
const fileMarkers = [];
|
|
383
|
-
const endMarkers = [];
|
|
384
|
-
function walkTokens(tokenList) {
|
|
385
|
-
for (const token of tokenList) {
|
|
386
|
-
const t = token;
|
|
387
|
-
if (t.type === 'paragraph' && t.raw.includes('--- File:')) {
|
|
388
|
-
const match = t.raw.match(/--- File: (.+?) ---/);
|
|
389
|
-
if (match) {
|
|
390
|
-
// Normalize the path before adding to fileMarkers
|
|
391
|
-
fileMarkers.push(path.normalize(match[1]));
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
if (t.type === 'paragraph' && t.raw.includes('--- End of File:')) {
|
|
395
|
-
const match = t.raw.match(/--- End of File: (.+?) ---/);
|
|
396
|
-
if (match) {
|
|
397
|
-
// Normalize the path before adding to endMarkers
|
|
398
|
-
endMarkers.push(path.normalize(match[1]));
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
if (t.tokens) {
|
|
402
|
-
walkTokens(t.tokens);
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
walkTokens(tokens);
|
|
407
|
-
// Verify all expected files are present
|
|
408
|
-
const expectedFiles = ['nested.md', 'simple.md', 'inner.md'];
|
|
409
|
-
// Check that each expected file is present in the content
|
|
410
|
-
expectedFiles.forEach((file) => {
|
|
411
|
-
expect(result.content).toContain(file);
|
|
412
|
-
});
|
|
413
|
-
// Verify content is present
|
|
414
|
-
expect(result.content).toContain('Main @./nested.md content @./simple.md');
|
|
415
|
-
expect(result.content).toContain('Nested @./inner.md content');
|
|
416
|
-
expect(result.content).toContain('Simple content');
|
|
417
|
-
expect(result.content).toContain('Inner content');
|
|
418
|
-
// Verify end markers exist
|
|
419
|
-
expect(endMarkers.length).toBeGreaterThan(0);
|
|
420
|
-
});
|
|
421
|
-
it('should not duplicate files in flat output if imported multiple times', async () => {
|
|
422
|
-
const content = 'Main @./dup.md again @./dup.md';
|
|
423
|
-
const projectRoot = testPath('test', 'project');
|
|
424
|
-
const basePath = testPath(projectRoot, 'src');
|
|
425
|
-
const dupContent = 'Duplicated content';
|
|
426
|
-
// Reset mocks
|
|
427
|
-
mockedFs.access.mockReset();
|
|
428
|
-
mockedFs.readFile.mockReset();
|
|
429
|
-
// Set up mocks
|
|
430
|
-
mockedFs.access.mockResolvedValue(undefined);
|
|
431
|
-
mockedFs.readFile.mockResolvedValue(dupContent);
|
|
432
|
-
const result = await processImports(content, basePath, true, // followImports
|
|
433
|
-
undefined, // allowedPaths
|
|
434
|
-
projectRoot, 'flat');
|
|
435
|
-
// Verify readFile was called only once for dup.md
|
|
436
|
-
expect(mockedFs.readFile).toHaveBeenCalledTimes(1);
|
|
437
|
-
// Check that the content contains the file content only once
|
|
438
|
-
const contentStr = result.content;
|
|
439
|
-
const firstIndex = contentStr.indexOf('Duplicated content');
|
|
440
|
-
const lastIndex = contentStr.lastIndexOf('Duplicated content');
|
|
441
|
-
expect(firstIndex).toBeGreaterThan(-1); // Content should exist
|
|
442
|
-
expect(firstIndex).toBe(lastIndex); // Should only appear once
|
|
443
|
-
});
|
|
444
|
-
it('should handle nested imports in flat output', async () => {
|
|
445
|
-
const content = 'Root @./a.md';
|
|
446
|
-
const projectRoot = testPath('test', 'project');
|
|
447
|
-
const basePath = testPath(projectRoot, 'src');
|
|
448
|
-
const aContent = 'A @./b.md';
|
|
449
|
-
const bContent = 'B content';
|
|
450
|
-
mockedFs.access.mockResolvedValue(undefined);
|
|
451
|
-
mockedFs.readFile
|
|
452
|
-
.mockResolvedValueOnce(aContent)
|
|
453
|
-
.mockResolvedValueOnce(bContent);
|
|
454
|
-
const result = await processImports(content, basePath, true, undefined, projectRoot, 'flat');
|
|
455
|
-
// Verify all files are present by checking for their basenames
|
|
456
|
-
expect(result.content).toContain('a.md');
|
|
457
|
-
expect(result.content).toContain('b.md');
|
|
458
|
-
// Verify content is in the correct order
|
|
459
|
-
const contentStr = result.content;
|
|
460
|
-
const aIndex = contentStr.indexOf('a.md');
|
|
461
|
-
const bIndex = contentStr.indexOf('b.md');
|
|
462
|
-
const rootIndex = contentStr.indexOf('Root @./a.md');
|
|
463
|
-
expect(rootIndex).toBeLessThan(aIndex);
|
|
464
|
-
expect(aIndex).toBeLessThan(bIndex);
|
|
465
|
-
// Verify content is present
|
|
466
|
-
expect(result.content).toContain('Root @./a.md');
|
|
467
|
-
expect(result.content).toContain('A @./b.md');
|
|
468
|
-
expect(result.content).toContain('B content');
|
|
469
|
-
});
|
|
470
|
-
it('should build import tree structure', async () => {
|
|
471
|
-
const content = 'Main content @./nested.md @./simple.md';
|
|
472
|
-
const projectRoot = testPath('test', 'project');
|
|
473
|
-
const basePath = testPath(projectRoot, 'src');
|
|
474
|
-
const nestedContent = 'Nested @./inner.md content';
|
|
475
|
-
const simpleContent = 'Simple content';
|
|
476
|
-
const innerContent = 'Inner content';
|
|
477
|
-
mockedFs.access.mockResolvedValue(undefined);
|
|
478
|
-
mockedFs.readFile
|
|
479
|
-
.mockResolvedValueOnce(nestedContent)
|
|
480
|
-
.mockResolvedValueOnce(simpleContent)
|
|
481
|
-
.mockResolvedValueOnce(innerContent);
|
|
482
|
-
const result = await processImports(content, basePath, true);
|
|
483
|
-
// Use marked to find and validate import comments
|
|
484
|
-
const comments = findMarkdownComments(result.content);
|
|
485
|
-
const importComments = comments.filter((c) => c.includes('Imported from:'));
|
|
486
|
-
expect(importComments.some((c) => c.includes('./nested.md'))).toBe(true);
|
|
487
|
-
expect(importComments.some((c) => c.includes('./simple.md'))).toBe(true);
|
|
488
|
-
expect(importComments.some((c) => c.includes('./inner.md'))).toBe(true);
|
|
489
|
-
// Use marked to validate the markdown structure is well-formed
|
|
490
|
-
const tokens = parseMarkdown(result.content);
|
|
491
|
-
expect(tokens).toBeDefined();
|
|
492
|
-
expect(tokens.length).toBeGreaterThan(0);
|
|
493
|
-
// Verify the content contains expected text using marked parsing
|
|
494
|
-
const textContent = tokens
|
|
495
|
-
.filter((token) => token.type === 'paragraph')
|
|
496
|
-
.map((token) => token.raw)
|
|
497
|
-
.join(' ');
|
|
498
|
-
expect(textContent).toContain('Main content');
|
|
499
|
-
expect(textContent).toContain('Nested');
|
|
500
|
-
expect(textContent).toContain('Simple content');
|
|
501
|
-
expect(textContent).toContain('Inner content');
|
|
502
|
-
// Verify import tree structure
|
|
503
|
-
expect(result.importTree.path).toBe('unknown'); // No currentFile set in test
|
|
504
|
-
expect(result.importTree.imports).toHaveLength(2);
|
|
505
|
-
// First import: nested.md
|
|
506
|
-
// Prefix with underscore to indicate they're intentionally unused
|
|
507
|
-
const _expectedNestedPath = testPath(projectRoot, 'src', 'nested.md');
|
|
508
|
-
const _expectedInnerPath = testPath(projectRoot, 'src', 'inner.md');
|
|
509
|
-
const _expectedSimplePath = testPath(projectRoot, 'src', 'simple.md');
|
|
510
|
-
// Check that the paths match using includes to handle potential absolute/relative differences
|
|
511
|
-
expect(result.importTree.imports[0].path).toContain('nested.md');
|
|
512
|
-
expect(result.importTree.imports[0].imports).toHaveLength(1);
|
|
513
|
-
expect(result.importTree.imports[0].imports[0].path).toContain('inner.md');
|
|
514
|
-
expect(result.importTree.imports[0].imports[0].imports).toBeUndefined();
|
|
515
|
-
// Second import: simple.md
|
|
516
|
-
expect(result.importTree.imports[1].path).toContain('simple.md');
|
|
517
|
-
expect(result.importTree.imports[1].imports).toBeUndefined();
|
|
518
|
-
});
|
|
519
|
-
it('should produce flat output in Claude-style with unique files in order', async () => {
|
|
520
|
-
const content = 'Main @./nested.md content @./simple.md';
|
|
521
|
-
const projectRoot = testPath('test', 'project');
|
|
522
|
-
const basePath = testPath(projectRoot, 'src');
|
|
523
|
-
const nestedContent = 'Nested @./inner.md content';
|
|
524
|
-
const simpleContent = 'Simple content';
|
|
525
|
-
const innerContent = 'Inner content';
|
|
526
|
-
mockedFs.access.mockResolvedValue(undefined);
|
|
527
|
-
mockedFs.readFile
|
|
528
|
-
.mockResolvedValueOnce(nestedContent)
|
|
529
|
-
.mockResolvedValueOnce(simpleContent)
|
|
530
|
-
.mockResolvedValueOnce(innerContent);
|
|
531
|
-
const result = await processImports(content, basePath, true, undefined, projectRoot, 'flat');
|
|
532
|
-
// Verify all expected files are present by checking for their basenames
|
|
533
|
-
expect(result.content).toContain('nested.md');
|
|
534
|
-
expect(result.content).toContain('simple.md');
|
|
535
|
-
expect(result.content).toContain('inner.md');
|
|
536
|
-
// Verify content is present
|
|
537
|
-
expect(result.content).toContain('Nested @./inner.md content');
|
|
538
|
-
expect(result.content).toContain('Simple content');
|
|
539
|
-
expect(result.content).toContain('Inner content');
|
|
540
|
-
});
|
|
541
|
-
it('should not duplicate files in flat output if imported multiple times', async () => {
|
|
542
|
-
const content = 'Main @./dup.md again @./dup.md';
|
|
543
|
-
const projectRoot = testPath('test', 'project');
|
|
544
|
-
const basePath = testPath(projectRoot, 'src');
|
|
545
|
-
const dupContent = 'Duplicated content';
|
|
546
|
-
// Create a normalized path for the duplicate file
|
|
547
|
-
const dupFilePath = path.normalize(path.join(basePath, 'dup.md'));
|
|
548
|
-
// Mock the file system access
|
|
549
|
-
mockedFs.access.mockImplementation((filePath) => {
|
|
550
|
-
const pathStr = filePath.toString();
|
|
551
|
-
if (path.normalize(pathStr) === dupFilePath) {
|
|
552
|
-
return Promise.resolve();
|
|
553
|
-
}
|
|
554
|
-
return Promise.reject(new Error(`File not found: ${pathStr}`));
|
|
555
|
-
});
|
|
556
|
-
// Mock the file reading
|
|
557
|
-
mockedFs.readFile.mockImplementation((filePath) => {
|
|
558
|
-
const pathStr = filePath.toString();
|
|
559
|
-
if (path.normalize(pathStr) === dupFilePath) {
|
|
560
|
-
return Promise.resolve(dupContent);
|
|
561
|
-
}
|
|
562
|
-
return Promise.reject(new Error(`File not found: ${pathStr}`));
|
|
563
|
-
});
|
|
564
|
-
const result = await processImports(content, basePath, true, // debugMode
|
|
565
|
-
undefined, // importState
|
|
566
|
-
projectRoot, 'flat');
|
|
567
|
-
// In flat mode, the output should only contain the main file content with import markers
|
|
568
|
-
// The imported file content should not be included in the flat output
|
|
569
|
-
expect(result.content).toContain('Main @./dup.md again @./dup.md');
|
|
570
|
-
// The imported file content should not appear in the output
|
|
571
|
-
// This is the current behavior of the implementation
|
|
572
|
-
expect(result.content).not.toContain(dupContent);
|
|
573
|
-
// The file marker should not appear in the output
|
|
574
|
-
// since the imported file content is not included in flat mode
|
|
575
|
-
const fileMarker = `--- File: ${dupFilePath} ---`;
|
|
576
|
-
expect(result.content).not.toContain(fileMarker);
|
|
577
|
-
expect(result.content).not.toContain('--- End of File: ' + dupFilePath);
|
|
578
|
-
// The main file path should be in the output
|
|
579
|
-
// Since we didn't pass an importState, it will use the basePath as the file path
|
|
580
|
-
const mainFilePath = path.normalize(path.resolve(basePath));
|
|
581
|
-
expect(result.content).toContain(`--- File: ${mainFilePath} ---`);
|
|
582
|
-
expect(result.content).toContain(`--- End of File: ${mainFilePath}`);
|
|
583
|
-
});
|
|
584
|
-
it('should handle nested imports in flat output', async () => {
|
|
585
|
-
const content = 'Root @./a.md';
|
|
586
|
-
const projectRoot = testPath('test', 'project');
|
|
587
|
-
const basePath = testPath(projectRoot, 'src');
|
|
588
|
-
const aContent = 'A @./b.md';
|
|
589
|
-
const bContent = 'B content';
|
|
590
|
-
mockedFs.access.mockResolvedValue(undefined);
|
|
591
|
-
mockedFs.readFile
|
|
592
|
-
.mockResolvedValueOnce(aContent)
|
|
593
|
-
.mockResolvedValueOnce(bContent);
|
|
594
|
-
const result = await processImports(content, basePath, true, undefined, projectRoot, 'flat');
|
|
595
|
-
// Verify all files are present by checking for their basenames
|
|
596
|
-
expect(result.content).toContain('a.md');
|
|
597
|
-
expect(result.content).toContain('b.md');
|
|
598
|
-
// Verify content is in the correct order
|
|
599
|
-
const contentStr = result.content;
|
|
600
|
-
const aIndex = contentStr.indexOf('a.md');
|
|
601
|
-
const bIndex = contentStr.indexOf('b.md');
|
|
602
|
-
const rootIndex = contentStr.indexOf('Root @./a.md');
|
|
603
|
-
expect(rootIndex).toBeLessThan(aIndex);
|
|
604
|
-
expect(aIndex).toBeLessThan(bIndex);
|
|
605
|
-
// Verify content is present
|
|
606
|
-
expect(result.content).toContain('Root @./a.md');
|
|
607
|
-
expect(result.content).toContain('A @./b.md');
|
|
608
|
-
expect(result.content).toContain('B content');
|
|
609
|
-
});
|
|
610
|
-
});
|
|
611
|
-
describe('validateImportPath', () => {
|
|
612
|
-
it('should reject URLs', () => {
|
|
613
|
-
const basePath = testPath('base');
|
|
614
|
-
const allowedPath = testPath('allowed');
|
|
615
|
-
expect(validateImportPath('https://example.com/file.md', basePath, [
|
|
616
|
-
allowedPath,
|
|
617
|
-
])).toBe(false);
|
|
618
|
-
expect(validateImportPath('http://example.com/file.md', basePath, [
|
|
619
|
-
allowedPath,
|
|
620
|
-
])).toBe(false);
|
|
621
|
-
expect(validateImportPath('file:///path/to/file.md', basePath, [allowedPath])).toBe(false);
|
|
622
|
-
});
|
|
623
|
-
it('should allow paths within allowed directories', () => {
|
|
624
|
-
const basePath = path.resolve(testPath('base'));
|
|
625
|
-
const allowedPath = path.resolve(testPath('allowed'));
|
|
626
|
-
// Test relative paths - resolve them against basePath
|
|
627
|
-
const relativePath = './file.md';
|
|
628
|
-
const _resolvedRelativePath = path.resolve(basePath, relativePath);
|
|
629
|
-
expect(validateImportPath(relativePath, basePath, [basePath])).toBe(true);
|
|
630
|
-
// Test parent directory access (should be allowed if parent is in allowed paths)
|
|
631
|
-
const parentPath = path.dirname(basePath);
|
|
632
|
-
if (parentPath !== basePath) {
|
|
633
|
-
// Only test if parent is different
|
|
634
|
-
const parentRelativePath = '../file.md';
|
|
635
|
-
const _resolvedParentPath = path.resolve(basePath, parentRelativePath);
|
|
636
|
-
expect(validateImportPath(parentRelativePath, basePath, [parentPath])).toBe(true);
|
|
637
|
-
const _resolvedSubPath = path.resolve(basePath, 'sub');
|
|
638
|
-
const resultSub = validateImportPath('sub', basePath, [basePath]);
|
|
639
|
-
expect(resultSub).toBe(true);
|
|
640
|
-
}
|
|
641
|
-
// Test allowed path access - use a file within the allowed directory
|
|
642
|
-
const allowedSubPath = 'nested';
|
|
643
|
-
const allowedFilePath = path.join(allowedPath, allowedSubPath, 'file.md');
|
|
644
|
-
expect(validateImportPath(allowedFilePath, basePath, [allowedPath])).toBe(true);
|
|
645
|
-
});
|
|
646
|
-
it('should reject paths outside allowed directories', () => {
|
|
647
|
-
const basePath = path.resolve(testPath('base'));
|
|
648
|
-
const allowedPath = path.resolve(testPath('allowed'));
|
|
649
|
-
const forbiddenPath = path.resolve(testPath('forbidden'));
|
|
650
|
-
// Forbidden path should be blocked
|
|
651
|
-
expect(validateImportPath(forbiddenPath, basePath, [allowedPath])).toBe(false);
|
|
652
|
-
// Relative path to forbidden directory should be blocked
|
|
653
|
-
const relativeToForbidden = path.relative(basePath, path.join(forbiddenPath, 'file.md'));
|
|
654
|
-
expect(validateImportPath(relativeToForbidden, basePath, [allowedPath])).toBe(false);
|
|
655
|
-
// Path that tries to escape the base directory should be blocked
|
|
656
|
-
const escapingPath = path.join('..', '..', 'sensitive', 'file.md');
|
|
657
|
-
expect(validateImportPath(escapingPath, basePath, [basePath])).toBe(false);
|
|
658
|
-
});
|
|
659
|
-
it('should handle multiple allowed directories', () => {
|
|
660
|
-
const basePath = path.resolve(testPath('base'));
|
|
661
|
-
const allowed1 = path.resolve(testPath('allowed1'));
|
|
662
|
-
const allowed2 = path.resolve(testPath('allowed2'));
|
|
663
|
-
// File not in any allowed path
|
|
664
|
-
const otherPath = path.resolve(testPath('other', 'file.md'));
|
|
665
|
-
expect(validateImportPath(otherPath, basePath, [allowed1, allowed2])).toBe(false);
|
|
666
|
-
// File in first allowed path
|
|
667
|
-
const file1 = path.join(allowed1, 'nested', 'file.md');
|
|
668
|
-
expect(validateImportPath(file1, basePath, [allowed1, allowed2])).toBe(true);
|
|
669
|
-
// File in second allowed path
|
|
670
|
-
const file2 = path.join(allowed2, 'nested', 'file.md');
|
|
671
|
-
expect(validateImportPath(file2, basePath, [allowed1, allowed2])).toBe(true);
|
|
672
|
-
// Test with relative path to allowed directory
|
|
673
|
-
const relativeToAllowed1 = path.relative(basePath, file1);
|
|
674
|
-
expect(validateImportPath(relativeToAllowed1, basePath, [allowed1, allowed2])).toBe(true);
|
|
675
|
-
});
|
|
676
|
-
it('should handle relative paths correctly', () => {
|
|
677
|
-
const basePath = path.resolve(testPath('base'));
|
|
678
|
-
const parentPath = path.resolve(testPath('parent'));
|
|
679
|
-
// Current directory file access
|
|
680
|
-
expect(validateImportPath('file.md', basePath, [basePath])).toBe(true);
|
|
681
|
-
// Explicit current directory file access
|
|
682
|
-
expect(validateImportPath('./file.md', basePath, [basePath])).toBe(true);
|
|
683
|
-
// Parent directory access - should be blocked unless parent is in allowed paths
|
|
684
|
-
const parentFile = path.join(parentPath, 'file.md');
|
|
685
|
-
const relativeToParent = path.relative(basePath, parentFile);
|
|
686
|
-
expect(validateImportPath(relativeToParent, basePath, [basePath])).toBe(false);
|
|
687
|
-
// Parent directory access when parent is in allowed paths
|
|
688
|
-
expect(validateImportPath(relativeToParent, basePath, [basePath, parentPath])).toBe(true);
|
|
689
|
-
// Nested relative path
|
|
690
|
-
const nestedPath = path.join('nested', 'sub', 'file.md');
|
|
691
|
-
expect(validateImportPath(nestedPath, basePath, [basePath])).toBe(true);
|
|
692
|
-
});
|
|
693
|
-
it('should handle absolute paths correctly', () => {
|
|
694
|
-
const basePath = path.resolve(testPath('base'));
|
|
695
|
-
const allowedPath = path.resolve(testPath('allowed'));
|
|
696
|
-
const forbiddenPath = path.resolve(testPath('forbidden'));
|
|
697
|
-
// Allowed path should work - file directly in allowed directory
|
|
698
|
-
const allowedFilePath = path.join(allowedPath, 'file.md');
|
|
699
|
-
expect(validateImportPath(allowedFilePath, basePath, [allowedPath])).toBe(true);
|
|
700
|
-
// Allowed path should work - file in subdirectory of allowed directory
|
|
701
|
-
const allowedNestedPath = path.join(allowedPath, 'nested', 'file.md');
|
|
702
|
-
expect(validateImportPath(allowedNestedPath, basePath, [allowedPath])).toBe(true);
|
|
703
|
-
// Forbidden path should be blocked
|
|
704
|
-
const forbiddenFilePath = path.join(forbiddenPath, 'file.md');
|
|
705
|
-
expect(validateImportPath(forbiddenFilePath, basePath, [allowedPath])).toBe(false);
|
|
706
|
-
// Relative path to allowed directory should work
|
|
707
|
-
const relativeToAllowed = path.relative(basePath, allowedFilePath);
|
|
708
|
-
expect(validateImportPath(relativeToAllowed, basePath, [allowedPath])).toBe(true);
|
|
709
|
-
// Path that resolves to the same file but via different relative segments
|
|
710
|
-
const dotPath = path.join('.', '..', path.basename(allowedPath), 'file.md');
|
|
711
|
-
expect(validateImportPath(dotPath, basePath, [allowedPath])).toBe(true);
|
|
712
|
-
});
|
|
713
|
-
});
|
|
714
|
-
});
|
|
715
|
-
//# sourceMappingURL=memoryImportProcessor.test.js.map
|