@vybestack/llxprt-code-core 0.1.12 → 0.1.13-hotfix1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/adapters/IStreamAdapter.d.ts +18 -0
- package/dist/src/adapters/IStreamAdapter.js +7 -0
- package/dist/src/adapters/IStreamAdapter.js.map +1 -0
- package/dist/src/code_assist/oauth2.d.ts +1 -1
- package/dist/src/code_assist/oauth2.js +51 -29
- package/dist/src/code_assist/oauth2.js.map +1 -1
- package/dist/src/code_assist/oauth2.test.js +36 -7
- package/dist/src/code_assist/oauth2.test.js.map +1 -1
- package/dist/src/code_assist/server.test.js +10 -2
- package/dist/src/code_assist/server.test.js.map +1 -1
- package/dist/src/config/config.d.ts +28 -5
- package/dist/src/config/config.js +29 -4
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/config.test.js +2 -3
- package/dist/src/config/config.test.js.map +1 -1
- package/dist/src/core/client.d.ts +4 -2
- package/dist/src/core/client.js +68 -7
- package/dist/src/core/client.js.map +1 -1
- package/dist/src/core/client.test.js +8 -0
- package/dist/src/core/client.test.js.map +1 -1
- package/dist/src/core/contentGenerator.d.ts +3 -2
- package/dist/src/core/contentGenerator.js +6 -8
- package/dist/src/core/contentGenerator.js.map +1 -1
- package/dist/src/core/contentGenerator.test.js +12 -5
- package/dist/src/core/contentGenerator.test.js.map +1 -1
- package/dist/src/core/coreToolScheduler.test.js +4 -2
- package/dist/src/core/coreToolScheduler.test.js.map +1 -1
- package/dist/src/core/geminiChat.js +50 -3
- package/dist/src/core/geminiChat.js.map +1 -1
- package/dist/src/core/modelCheck.d.ts +1 -1
- package/dist/src/core/modelCheck.js +10 -3
- package/dist/src/core/modelCheck.js.map +1 -1
- package/dist/src/core/nonInteractiveToolExecutor.test.js +3 -0
- package/dist/src/core/nonInteractiveToolExecutor.test.js.map +1 -1
- package/dist/src/core/prompts.d.ts +1 -1
- package/dist/src/core/prompts.js +14 -2
- package/dist/src/core/prompts.js.map +1 -1
- package/dist/src/core/turn.js +6 -0
- package/dist/src/core/turn.js.map +1 -1
- package/dist/src/index.d.ts +29 -1
- package/dist/src/index.js +33 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcp/oauth-provider.d.ts +142 -0
- package/dist/src/mcp/oauth-provider.js +446 -0
- package/dist/src/mcp/oauth-provider.js.map +1 -0
- package/dist/src/mcp/oauth-provider.test.js +520 -0
- package/dist/src/mcp/oauth-provider.test.js.map +1 -0
- package/dist/src/mcp/oauth-token-storage.d.ts +81 -0
- package/dist/src/mcp/oauth-token-storage.js +149 -0
- package/dist/src/mcp/oauth-token-storage.js.map +1 -0
- package/dist/src/mcp/oauth-token-storage.test.d.ts +6 -0
- package/dist/src/mcp/oauth-token-storage.test.js +205 -0
- package/dist/src/mcp/oauth-token-storage.test.js.map +1 -0
- package/dist/src/mcp/oauth-utils.d.ts +109 -0
- package/dist/src/mcp/oauth-utils.js +183 -0
- package/dist/src/mcp/oauth-utils.js.map +1 -0
- package/dist/src/mcp/oauth-utils.test.d.ts +6 -0
- package/dist/src/mcp/oauth-utils.test.js +144 -0
- package/dist/src/mcp/oauth-utils.test.js.map +1 -0
- package/dist/src/parsers/TextToolCallParser.d.ts +35 -0
- package/dist/src/parsers/TextToolCallParser.js +248 -0
- package/dist/src/parsers/TextToolCallParser.js.map +1 -0
- package/dist/src/parsers/TextToolCallParser.test.d.ts +1 -0
- package/dist/src/parsers/TextToolCallParser.test.js +225 -0
- package/dist/src/parsers/TextToolCallParser.test.js.map +1 -0
- package/dist/src/providers/ContentGeneratorRole.d.ts +14 -0
- package/dist/src/providers/ContentGeneratorRole.js +16 -0
- package/dist/src/providers/ContentGeneratorRole.js.map +1 -0
- package/dist/src/providers/IMessage.d.ts +38 -0
- package/dist/src/providers/IMessage.js +17 -0
- package/dist/src/providers/IMessage.js.map +1 -0
- package/dist/src/providers/IModel.d.ts +23 -0
- package/dist/src/providers/IModel.js +17 -0
- package/dist/src/providers/IModel.js.map +1 -0
- package/dist/src/providers/IProvider.d.ts +36 -0
- package/dist/src/providers/IProvider.js +17 -0
- package/dist/src/providers/IProvider.js.map +1 -0
- package/dist/src/providers/IProviderConfig.d.ts +31 -0
- package/dist/src/providers/IProviderConfig.js +7 -0
- package/dist/src/providers/IProviderConfig.js.map +1 -0
- package/dist/src/providers/IProviderManager.d.ts +53 -0
- package/dist/src/providers/IProviderManager.js +7 -0
- package/dist/src/providers/IProviderManager.js.map +1 -0
- package/dist/src/providers/ITool.d.ts +23 -0
- package/dist/src/providers/ITool.js +17 -0
- package/dist/src/providers/ITool.js.map +1 -0
- package/dist/src/providers/ProviderContentGenerator.d.ts +1 -1
- package/dist/src/providers/ProviderManager.d.ts +24 -0
- package/dist/src/providers/ProviderManager.gemini-switch.test.d.ts +6 -0
- package/dist/src/providers/ProviderManager.gemini-switch.test.js +57 -0
- package/dist/src/providers/ProviderManager.gemini-switch.test.js.map +1 -0
- package/dist/src/providers/ProviderManager.js +116 -0
- package/dist/src/providers/ProviderManager.js.map +1 -0
- package/dist/src/providers/ProviderManager.test.d.ts +6 -0
- package/dist/src/providers/ProviderManager.test.js +284 -0
- package/dist/src/providers/ProviderManager.test.js.map +1 -0
- package/dist/src/providers/adapters/GeminiCompatibleWrapper.d.ts +2 -1
- package/dist/src/providers/adapters/GeminiCompatibleWrapper.js +15 -2
- package/dist/src/providers/adapters/GeminiCompatibleWrapper.js.map +1 -1
- package/dist/src/providers/adapters/GeminiCompatibleWrapper.test.js +20 -0
- package/dist/src/providers/adapters/GeminiCompatibleWrapper.test.js.map +1 -1
- package/dist/src/providers/anthropic/AnthropicProvider.d.ts +57 -0
- package/dist/src/providers/anthropic/AnthropicProvider.js +490 -0
- package/dist/src/providers/anthropic/AnthropicProvider.js.map +1 -0
- package/dist/src/providers/anthropic/AnthropicProvider.test.d.ts +1 -0
- package/dist/src/providers/anthropic/AnthropicProvider.test.js +486 -0
- package/dist/src/providers/anthropic/AnthropicProvider.test.js.map +1 -0
- package/dist/src/providers/errors.d.ts +13 -0
- package/dist/src/providers/errors.js +19 -0
- package/dist/src/providers/errors.js.map +1 -0
- package/dist/src/providers/gemini/GeminiProvider.d.ts +97 -0
- package/dist/src/providers/gemini/GeminiProvider.integration.test.d.ts +6 -0
- package/dist/src/providers/gemini/GeminiProvider.integration.test.js +90 -0
- package/dist/src/providers/gemini/GeminiProvider.integration.test.js.map +1 -0
- package/dist/src/providers/gemini/GeminiProvider.js +937 -0
- package/dist/src/providers/gemini/GeminiProvider.js.map +1 -0
- package/dist/src/providers/gemini/GeminiProvider.test.d.ts +6 -0
- package/dist/src/providers/gemini/GeminiProvider.test.js +136 -0
- package/dist/src/providers/gemini/GeminiProvider.test.js.map +1 -0
- package/dist/src/providers/integration/TEST_INSTRUCTIONS.md +197 -0
- package/dist/src/providers/integration/multi-provider.integration.test.d.ts +6 -0
- package/dist/src/providers/integration/multi-provider.integration.test.js +292 -0
- package/dist/src/providers/integration/multi-provider.integration.test.js.map +1 -0
- package/dist/src/providers/openai/ConversationCache.accumTokens.test.d.ts +1 -0
- package/dist/src/providers/openai/ConversationCache.accumTokens.test.js +97 -0
- package/dist/src/providers/openai/ConversationCache.accumTokens.test.js.map +1 -0
- package/dist/src/providers/openai/ConversationCache.d.ts +20 -0
- package/dist/src/providers/openai/ConversationCache.js +109 -0
- package/dist/src/providers/openai/ConversationCache.js.map +1 -0
- package/dist/src/providers/openai/ConversationCache.test.d.ts +1 -0
- package/dist/src/providers/openai/ConversationCache.test.js +113 -0
- package/dist/src/providers/openai/ConversationCache.test.js.map +1 -0
- package/dist/src/providers/openai/IChatGenerateParams.d.ts +11 -0
- package/dist/src/providers/openai/IChatGenerateParams.js +2 -0
- package/dist/src/providers/openai/IChatGenerateParams.js.map +1 -0
- package/dist/src/providers/openai/OpenAIProvider.callResponses.stateless.test.d.ts +1 -0
- package/dist/src/providers/openai/OpenAIProvider.callResponses.stateless.test.js +189 -0
- package/dist/src/providers/openai/OpenAIProvider.callResponses.stateless.test.js.map +1 -0
- package/dist/src/providers/openai/OpenAIProvider.d.ts +80 -0
- package/dist/src/providers/openai/OpenAIProvider.integration.test.d.ts +6 -0
- package/dist/src/providers/openai/OpenAIProvider.integration.test.js +125 -0
- package/dist/src/providers/openai/OpenAIProvider.integration.test.js.map +1 -0
- package/dist/src/providers/openai/OpenAIProvider.js +523 -0
- package/dist/src/providers/openai/OpenAIProvider.js.map +1 -0
- package/dist/src/providers/openai/OpenAIProvider.responses.test.d.ts +1 -0
- package/dist/src/providers/openai/OpenAIProvider.responses.test.js +326 -0
- package/dist/src/providers/openai/OpenAIProvider.responses.test.js.map +1 -0
- package/dist/src/providers/openai/OpenAIProvider.responsesIntegration.test.d.ts +1 -0
- package/dist/src/providers/openai/OpenAIProvider.responsesIntegration.test.js +213 -0
- package/dist/src/providers/openai/OpenAIProvider.responsesIntegration.test.js.map +1 -0
- package/dist/src/providers/openai/OpenAIProvider.shouldUseResponses.test.d.ts +1 -0
- package/dist/src/providers/openai/OpenAIProvider.shouldUseResponses.test.js +58 -0
- package/dist/src/providers/openai/OpenAIProvider.shouldUseResponses.test.js.map +1 -0
- package/dist/src/providers/openai/OpenAIProvider.stateful.integration.test.d.ts +6 -0
- package/dist/src/providers/openai/OpenAIProvider.stateful.integration.test.js +105 -0
- package/dist/src/providers/openai/OpenAIProvider.stateful.integration.test.js.map +1 -0
- package/dist/src/providers/openai/OpenAIProvider.switch.test.d.ts +1 -0
- package/dist/src/providers/openai/OpenAIProvider.switch.test.js +256 -0
- package/dist/src/providers/openai/OpenAIProvider.switch.test.js.map +1 -0
- package/dist/src/providers/openai/OpenAIProvider.test.d.ts +16 -0
- package/dist/src/providers/openai/OpenAIProvider.test.js +214 -0
- package/dist/src/providers/openai/OpenAIProvider.test.js.map +1 -0
- package/dist/src/providers/openai/RESPONSES_API_MODELS.d.ts +2 -0
- package/dist/src/providers/openai/RESPONSES_API_MODELS.js +14 -0
- package/dist/src/providers/openai/RESPONSES_API_MODELS.js.map +1 -0
- package/dist/src/providers/openai/ResponsesContextTrim.integration.test.d.ts +1 -0
- package/dist/src/providers/openai/ResponsesContextTrim.integration.test.js +210 -0
- package/dist/src/providers/openai/ResponsesContextTrim.integration.test.js.map +1 -0
- package/dist/src/providers/openai/__tests__/formatArrayResponse.test.d.ts +1 -0
- package/dist/src/providers/openai/__tests__/formatArrayResponse.test.js +65 -0
- package/dist/src/providers/openai/__tests__/formatArrayResponse.test.js.map +1 -0
- package/dist/src/providers/openai/buildResponsesRequest.d.ts +73 -0
- package/dist/src/providers/openai/buildResponsesRequest.js +165 -0
- package/dist/src/providers/openai/buildResponsesRequest.js.map +1 -0
- package/dist/src/providers/openai/buildResponsesRequest.stripToolCalls.test.d.ts +1 -0
- package/dist/src/providers/openai/buildResponsesRequest.stripToolCalls.test.js +129 -0
- package/dist/src/providers/openai/buildResponsesRequest.stripToolCalls.test.js.map +1 -0
- package/dist/src/providers/openai/buildResponsesRequest.test.d.ts +1 -0
- package/dist/src/providers/openai/buildResponsesRequest.test.js +406 -0
- package/dist/src/providers/openai/buildResponsesRequest.test.js.map +1 -0
- package/dist/src/providers/openai/buildResponsesRequest.undefined.test.d.ts +1 -0
- package/dist/src/providers/openai/buildResponsesRequest.undefined.test.js +50 -0
- package/dist/src/providers/openai/buildResponsesRequest.undefined.test.js.map +1 -0
- package/dist/src/providers/openai/docs/accessing-provider-info.md +172 -0
- package/dist/src/providers/openai/docs/params-mapping.md +91 -0
- package/dist/src/providers/openai/docs/responses-api-tool-calls.md +96 -0
- package/dist/src/providers/openai/estimateRemoteTokens.d.ts +26 -0
- package/dist/src/providers/openai/estimateRemoteTokens.js +75 -0
- package/dist/src/providers/openai/estimateRemoteTokens.js.map +1 -0
- package/dist/src/providers/openai/estimateRemoteTokens.test.d.ts +1 -0
- package/dist/src/providers/openai/estimateRemoteTokens.test.js +125 -0
- package/dist/src/providers/openai/estimateRemoteTokens.test.js.map +1 -0
- package/dist/src/providers/openai/getOpenAIProviderInfo.d.ts +46 -0
- package/dist/src/providers/openai/getOpenAIProviderInfo.js +75 -0
- package/dist/src/providers/openai/getOpenAIProviderInfo.js.map +1 -0
- package/dist/src/providers/openai/parseResponsesStream.d.ts +3 -0
- package/dist/src/providers/openai/parseResponsesStream.js +462 -0
- package/dist/src/providers/openai/parseResponsesStream.js.map +1 -0
- package/dist/src/providers/openai/parseResponsesStream.responsesToolCalls.test.d.ts +1 -0
- package/dist/src/providers/openai/parseResponsesStream.responsesToolCalls.test.js +192 -0
- package/dist/src/providers/openai/parseResponsesStream.responsesToolCalls.test.js.map +1 -0
- package/dist/src/providers/openai/parseResponsesStream.test.d.ts +1 -0
- package/dist/src/providers/openai/parseResponsesStream.test.js +151 -0
- package/dist/src/providers/openai/parseResponsesStream.test.js.map +1 -0
- package/dist/src/providers/tokenizers/AnthropicTokenizer.d.ts +19 -0
- package/dist/src/providers/tokenizers/AnthropicTokenizer.js +37 -0
- package/dist/src/providers/tokenizers/AnthropicTokenizer.js.map +1 -0
- package/dist/src/providers/tokenizers/ITokenizer.d.ts +18 -0
- package/dist/src/providers/tokenizers/ITokenizer.js +17 -0
- package/dist/src/providers/tokenizers/ITokenizer.js.map +1 -0
- package/dist/src/providers/tokenizers/OpenAITokenizer.d.ts +24 -0
- package/dist/src/providers/tokenizers/OpenAITokenizer.js +56 -0
- package/dist/src/providers/tokenizers/OpenAITokenizer.js.map +1 -0
- package/dist/src/providers/types/IProviderConfig.d.ts +102 -0
- package/dist/src/providers/types/IProviderConfig.js +17 -0
- package/dist/src/providers/types/IProviderConfig.js.map +1 -0
- package/dist/src/providers/types.d.ts +4 -69
- package/dist/src/services/ideContext.d.ts +2 -0
- package/dist/src/services/ideContext.js +8 -0
- package/dist/src/services/ideContext.js.map +1 -1
- package/dist/src/services/ideContext.test.js +10 -0
- package/dist/src/services/ideContext.test.js.map +1 -1
- package/dist/src/services/loopDetectionService.d.ts +17 -1
- package/dist/src/services/loopDetectionService.js +117 -2
- package/dist/src/services/loopDetectionService.js.map +1 -1
- package/dist/src/services/loopDetectionService.test.js +109 -2
- package/dist/src/services/loopDetectionService.test.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +2 -0
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +40 -2
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.d.ts +2 -0
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js +4 -0
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js.map +1 -1
- package/dist/src/telemetry/sdk.js +0 -2
- package/dist/src/telemetry/sdk.js.map +1 -1
- package/dist/src/telemetry/types.d.ts +2 -1
- package/dist/src/telemetry/types.js +1 -0
- package/dist/src/telemetry/types.js.map +1 -1
- package/dist/src/telemetry/uiTelemetry.d.ts +1 -0
- package/dist/src/telemetry/uiTelemetry.js +7 -0
- package/dist/src/telemetry/uiTelemetry.js.map +1 -1
- package/dist/src/telemetry/uiTelemetry.test.js +92 -0
- package/dist/src/telemetry/uiTelemetry.test.js.map +1 -1
- package/dist/src/tools/IToolFormatter.d.ts +40 -0
- package/dist/src/tools/IToolFormatter.js +17 -0
- package/dist/src/tools/IToolFormatter.js.map +1 -0
- package/dist/src/tools/ToolFormatter.d.ts +45 -0
- package/dist/src/tools/ToolFormatter.js +216 -0
- package/dist/src/tools/ToolFormatter.js.map +1 -0
- package/dist/src/tools/ToolFormatter.test.d.ts +16 -0
- package/dist/src/tools/ToolFormatter.test.js +349 -0
- package/dist/src/tools/ToolFormatter.test.js.map +1 -0
- package/dist/src/tools/ToolFormatter.toResponsesTool.test.d.ts +1 -0
- package/dist/src/tools/ToolFormatter.toResponsesTool.test.js +241 -0
- package/dist/src/tools/ToolFormatter.toResponsesTool.test.js.map +1 -0
- package/dist/src/tools/edit.d.ts +7 -1
- package/dist/src/tools/edit.js +19 -7
- package/dist/src/tools/edit.js.map +1 -1
- package/dist/src/tools/glob.js +2 -2
- package/dist/src/tools/glob.js.map +1 -1
- package/dist/src/tools/grep.js +2 -2
- package/dist/src/tools/grep.js.map +1 -1
- package/dist/src/tools/ls.js +2 -2
- package/dist/src/tools/ls.js.map +1 -1
- package/dist/src/tools/mcp-client.d.ts +0 -2
- package/dist/src/tools/mcp-client.js +8 -20
- package/dist/src/tools/mcp-client.js.map +1 -1
- package/dist/src/tools/mcp-client.test.js +1 -72
- package/dist/src/tools/mcp-client.test.js.map +1 -1
- package/dist/src/tools/mcp-tool.d.ts +11 -5
- package/dist/src/tools/mcp-tool.js +33 -9
- package/dist/src/tools/mcp-tool.js.map +1 -1
- package/dist/src/tools/mcp-tool.test.js +40 -24
- package/dist/src/tools/mcp-tool.test.js.map +1 -1
- package/dist/src/tools/memoryTool.js +2 -2
- package/dist/src/tools/memoryTool.js.map +1 -1
- package/dist/src/tools/read-file.d.ts +2 -1
- package/dist/src/tools/read-file.js +5 -2
- package/dist/src/tools/read-file.js.map +1 -1
- package/dist/src/tools/read-many-files.js +2 -2
- package/dist/src/tools/read-many-files.js.map +1 -1
- package/dist/src/tools/shell.js +2 -2
- package/dist/src/tools/shell.js.map +1 -1
- package/dist/src/tools/todo-read.js +2 -2
- package/dist/src/tools/todo-read.js.map +1 -1
- package/dist/src/tools/todo-write.js +2 -2
- package/dist/src/tools/todo-write.js.map +1 -1
- package/dist/src/tools/tool-registry.d.ts +0 -1
- package/dist/src/tools/tool-registry.js +11 -8
- package/dist/src/tools/tool-registry.js.map +1 -1
- package/dist/src/tools/tool-registry.test.js +36 -10
- package/dist/src/tools/tool-registry.test.js.map +1 -1
- package/dist/src/tools/tools.d.ts +37 -2
- package/dist/src/tools/tools.js +25 -2
- package/dist/src/tools/tools.js.map +1 -1
- package/dist/src/tools/web-fetch.integration.test.d.ts +6 -0
- package/dist/src/tools/web-fetch.integration.test.js +532 -0
- package/dist/src/tools/web-fetch.integration.test.js.map +1 -0
- package/dist/src/tools/web-fetch.js +57 -50
- package/dist/src/tools/web-fetch.js.map +1 -1
- package/dist/src/tools/web-search.js +34 -6
- package/dist/src/tools/web-search.js.map +1 -1
- package/dist/src/tools/web-search.test.d.ts +6 -0
- package/dist/src/tools/web-search.test.js +229 -0
- package/dist/src/tools/web-search.test.js.map +1 -0
- package/dist/src/tools/write-file.js +12 -5
- package/dist/src/tools/write-file.js.map +1 -1
- package/dist/src/utils/browser.d.ts +13 -0
- package/dist/src/utils/browser.js +49 -0
- package/dist/src/utils/browser.js.map +1 -0
- package/dist/src/utils/errors.js +4 -4
- package/dist/src/utils/errors.js.map +1 -1
- package/dist/src/utils/memoryDiscovery.js +5 -1
- package/dist/src/utils/memoryDiscovery.js.map +1 -1
- package/dist/src/utils/quotaErrorDetection.js +0 -2
- package/dist/src/utils/quotaErrorDetection.js.map +1 -1
- package/dist/src/utils/retry.d.ts +6 -0
- package/dist/src/utils/retry.js +1 -1
- package/dist/src/utils/retry.js.map +1 -1
- package/dist/src/utils/user_account.js +6 -1
- package/dist/src/utils/user_account.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +6 -3
- package/dist/src/tools/web-fetch.test.js +0 -70
- package/dist/src/tools/web-fetch.test.js.map +0 -1
- package/dist/vybestack-llxprt-code-core-0.1.12.tgz +0 -0
- /package/dist/src/{tools/web-fetch.test.d.ts → mcp/oauth-provider.test.d.ts} +0 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { parseResponsesStream } from './parseResponsesStream.js';
|
|
3
|
+
function createSSEStream(chunks) {
|
|
4
|
+
const encoder = new TextEncoder();
|
|
5
|
+
let index = 0;
|
|
6
|
+
return new ReadableStream({
|
|
7
|
+
async pull(controller) {
|
|
8
|
+
if (index < chunks.length) {
|
|
9
|
+
const chunk = chunks[index++];
|
|
10
|
+
controller.enqueue(encoder.encode(chunk));
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
controller.close();
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
describe('parseResponsesStream - Responses API Tool Calls', () => {
|
|
19
|
+
it('should parse complete tool calls from Responses API events', async () => {
|
|
20
|
+
const chunks = [
|
|
21
|
+
'data: {"type":"response.output_item.added","sequence_number":4,"output_index":1,"item":{"id":"fc_123","type":"function_call","status":"in_progress","arguments":"","call_id":"call_abc123","name":"get_weather"}}\n\n',
|
|
22
|
+
'event: response.function_call_arguments.delta\n',
|
|
23
|
+
'data: {"type":"response.function_call_arguments.delta","sequence_number":5,"item_id":"fc_123","output_index":1,"delta":"{\\"location\\":"}\n\n',
|
|
24
|
+
'event: response.function_call_arguments.delta\n',
|
|
25
|
+
'data: {"type":"response.function_call_arguments.delta","sequence_number":6,"item_id":"fc_123","output_index":1,"delta":"\\"San Francisco, CA\\"}"}\n\n',
|
|
26
|
+
'event: response.function_call_arguments.done\n',
|
|
27
|
+
'data: {"type":"response.function_call_arguments.done","sequence_number":7,"item_id":"fc_123","output_index":1,"arguments":"{\\"location\\":\\"San Francisco, CA\\"}"}\n\n',
|
|
28
|
+
'data: {"type":"response.output_item.done","sequence_number":8,"output_index":1,"item":{"id":"fc_123","type":"function_call","status":"completed","arguments":"{\\"location\\":\\"San Francisco, CA\\"}","call_id":"call_abc123","name":"get_weather"}}\n\n',
|
|
29
|
+
];
|
|
30
|
+
const stream = createSSEStream(chunks);
|
|
31
|
+
const messages = [];
|
|
32
|
+
for await (const message of parseResponsesStream(stream)) {
|
|
33
|
+
messages.push(message);
|
|
34
|
+
}
|
|
35
|
+
// Should have one message with tool calls
|
|
36
|
+
const toolCallMessage = messages.find((m) => m.tool_calls);
|
|
37
|
+
expect(toolCallMessage).toBeDefined();
|
|
38
|
+
expect(toolCallMessage?.tool_calls).toHaveLength(1);
|
|
39
|
+
expect(toolCallMessage?.tool_calls?.[0]).toEqual({
|
|
40
|
+
id: 'call_abc123',
|
|
41
|
+
type: 'function',
|
|
42
|
+
function: {
|
|
43
|
+
name: 'get_weather',
|
|
44
|
+
arguments: '{"location":"San Francisco, CA"}',
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
it('should handle tool calls with streaming arguments', async () => {
|
|
49
|
+
const chunks = [
|
|
50
|
+
'data: {"type":"response.output_item.added","sequence_number":1,"output_index":0,"item":{"id":"fc_456","type":"function_call","status":"in_progress","arguments":"","call_id":"call_def456","name":"search_products"}}\n\n',
|
|
51
|
+
'data: {"type":"response.function_call_arguments.delta","sequence_number":2,"item_id":"fc_456","output_index":0,"delta":"{\\"query\\":"}\n\n',
|
|
52
|
+
'data: {"type":"response.function_call_arguments.delta","sequence_number":3,"item_id":"fc_456","output_index":0,"delta":"\\"laptop\\","}\n\n',
|
|
53
|
+
'data: {"type":"response.function_call_arguments.delta","sequence_number":4,"item_id":"fc_456","output_index":0,"delta":"\\"max_price\\":"}\n\n',
|
|
54
|
+
'data: {"type":"response.function_call_arguments.delta","sequence_number":5,"item_id":"fc_456","output_index":0,"delta":"1500}"}\n\n',
|
|
55
|
+
'data: {"type":"response.output_item.done","sequence_number":6,"output_index":0,"item":{"id":"fc_456","type":"function_call","status":"completed","arguments":"{\\"query\\":\\"laptop\\",\\"max_price\\":1500}","call_id":"call_def456","name":"search_products"}}\n\n',
|
|
56
|
+
];
|
|
57
|
+
const stream = createSSEStream(chunks);
|
|
58
|
+
const messages = [];
|
|
59
|
+
for await (const message of parseResponsesStream(stream)) {
|
|
60
|
+
messages.push(message);
|
|
61
|
+
}
|
|
62
|
+
const toolCallMessage = messages.find((m) => m.tool_calls);
|
|
63
|
+
expect(toolCallMessage?.tool_calls?.[0]).toEqual({
|
|
64
|
+
id: 'call_def456',
|
|
65
|
+
type: 'function',
|
|
66
|
+
function: {
|
|
67
|
+
name: 'search_products',
|
|
68
|
+
arguments: '{"query":"laptop","max_price":1500}',
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
it('should handle multiple concurrent tool calls', async () => {
|
|
73
|
+
const chunks = [
|
|
74
|
+
// First tool call starts
|
|
75
|
+
'data: {"type":"response.output_item.added","sequence_number":1,"output_index":0,"item":{"id":"fc_001","type":"function_call","status":"in_progress","arguments":"","call_id":"call_001","name":"tool1"}}\n\n',
|
|
76
|
+
// Second tool call starts
|
|
77
|
+
'data: {"type":"response.output_item.added","sequence_number":2,"output_index":1,"item":{"id":"fc_002","type":"function_call","status":"in_progress","arguments":"","call_id":"call_002","name":"tool2"}}\n\n',
|
|
78
|
+
// Arguments for first tool
|
|
79
|
+
'data: {"type":"response.function_call_arguments.delta","sequence_number":3,"item_id":"fc_001","output_index":0,"delta":"{\\"a\\":1}"}\n\n',
|
|
80
|
+
// Arguments for second tool
|
|
81
|
+
'data: {"type":"response.function_call_arguments.delta","sequence_number":4,"item_id":"fc_002","output_index":1,"delta":"{\\"b\\":2}"}\n\n',
|
|
82
|
+
// Complete first tool
|
|
83
|
+
'data: {"type":"response.output_item.done","sequence_number":5,"output_index":0,"item":{"id":"fc_001","type":"function_call","status":"completed","arguments":"{\\"a\\":1}","call_id":"call_001","name":"tool1"}}\n\n',
|
|
84
|
+
// Complete second tool
|
|
85
|
+
'data: {"type":"response.output_item.done","sequence_number":6,"output_index":1,"item":{"id":"fc_002","type":"function_call","status":"completed","arguments":"{\\"b\\":2}","call_id":"call_002","name":"tool2"}}\n\n',
|
|
86
|
+
];
|
|
87
|
+
const stream = createSSEStream(chunks);
|
|
88
|
+
const messages = [];
|
|
89
|
+
for await (const message of parseResponsesStream(stream)) {
|
|
90
|
+
messages.push(message);
|
|
91
|
+
}
|
|
92
|
+
const toolCallMessages = messages.filter((m) => m.tool_calls);
|
|
93
|
+
expect(toolCallMessages).toHaveLength(2);
|
|
94
|
+
const tool1 = toolCallMessages.find((m) => m.tool_calls?.[0].function.name === 'tool1');
|
|
95
|
+
expect(tool1?.tool_calls?.[0]).toEqual({
|
|
96
|
+
id: 'call_001',
|
|
97
|
+
type: 'function',
|
|
98
|
+
function: {
|
|
99
|
+
name: 'tool1',
|
|
100
|
+
arguments: '{"a":1}',
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
const tool2 = toolCallMessages.find((m) => m.tool_calls?.[0].function.name === 'tool2');
|
|
104
|
+
expect(tool2?.tool_calls?.[0]).toEqual({
|
|
105
|
+
id: 'call_002',
|
|
106
|
+
type: 'function',
|
|
107
|
+
function: {
|
|
108
|
+
name: 'tool2',
|
|
109
|
+
arguments: '{"b":2}',
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
it('should handle tool calls with empty arguments', async () => {
|
|
114
|
+
const chunks = [
|
|
115
|
+
'data: {"type":"response.output_item.added","sequence_number":1,"output_index":0,"item":{"id":"fc_empty","type":"function_call","status":"in_progress","arguments":"","call_id":"call_empty","name":"no_args_tool"}}\n\n',
|
|
116
|
+
'data: {"type":"response.output_item.done","sequence_number":2,"output_index":0,"item":{"id":"fc_empty","type":"function_call","status":"completed","arguments":"","call_id":"call_empty","name":"no_args_tool"}}\n\n',
|
|
117
|
+
];
|
|
118
|
+
const stream = createSSEStream(chunks);
|
|
119
|
+
const messages = [];
|
|
120
|
+
for await (const message of parseResponsesStream(stream)) {
|
|
121
|
+
messages.push(message);
|
|
122
|
+
}
|
|
123
|
+
const toolCallMessage = messages.find((m) => m.tool_calls);
|
|
124
|
+
expect(toolCallMessage?.tool_calls?.[0]).toEqual({
|
|
125
|
+
id: 'call_empty',
|
|
126
|
+
type: 'function',
|
|
127
|
+
function: {
|
|
128
|
+
name: 'no_args_tool',
|
|
129
|
+
arguments: '',
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
it('should interleave text content and tool calls', async () => {
|
|
134
|
+
const chunks = [
|
|
135
|
+
'data: {"type":"response.output_text.delta","delta":"Let me search for that..."}\n\n',
|
|
136
|
+
'data: {"type":"response.output_item.added","sequence_number":2,"output_index":1,"item":{"id":"fc_search","type":"function_call","status":"in_progress","arguments":"","call_id":"call_search","name":"search"}}\n\n',
|
|
137
|
+
'data: {"type":"response.function_call_arguments.delta","sequence_number":3,"item_id":"fc_search","output_index":1,"delta":"{\\"query\\":\\"test\\"}"}\n\n',
|
|
138
|
+
'data: {"type":"response.output_item.done","sequence_number":4,"output_index":1,"item":{"id":"fc_search","type":"function_call","status":"completed","arguments":"{\\"query\\":\\"test\\"}","call_id":"call_search","name":"search"}}\n\n',
|
|
139
|
+
];
|
|
140
|
+
const stream = createSSEStream(chunks);
|
|
141
|
+
const messages = [];
|
|
142
|
+
for await (const message of parseResponsesStream(stream)) {
|
|
143
|
+
messages.push(message);
|
|
144
|
+
}
|
|
145
|
+
// Should have content message and tool call message
|
|
146
|
+
expect(messages.some((m) => m.content === 'Let me search for that...')).toBe(true);
|
|
147
|
+
expect(messages.some((m) => m.tool_calls)).toBe(true);
|
|
148
|
+
});
|
|
149
|
+
it('should handle usage data in response.completed event', async () => {
|
|
150
|
+
const chunks = [
|
|
151
|
+
'data: {"type":"response.output_item.added","sequence_number":1,"output_index":0,"item":{"id":"fc_test","type":"function_call","status":"in_progress","arguments":"","call_id":"call_test","name":"test_tool"}}\n\n',
|
|
152
|
+
'data: {"type":"response.function_call_arguments.delta","sequence_number":2,"item_id":"fc_test","output_index":0,"delta":"{\\"test\\":true}"}\n\n',
|
|
153
|
+
'data: {"type":"response.output_item.done","sequence_number":3,"output_index":0,"item":{"id":"fc_test","type":"function_call","status":"completed","arguments":"{\\"test\\":true}","call_id":"call_test","name":"test_tool"}}\n\n',
|
|
154
|
+
'data: {"type":"response.completed","sequence_number":4,"response":{"id":"resp_123","object":"response","model":"o3","status":"completed","usage":{"input_tokens":62,"output_tokens":23,"total_tokens":85}}}\n\n',
|
|
155
|
+
];
|
|
156
|
+
const stream = createSSEStream(chunks);
|
|
157
|
+
const messages = [];
|
|
158
|
+
for await (const message of parseResponsesStream(stream)) {
|
|
159
|
+
messages.push(message);
|
|
160
|
+
}
|
|
161
|
+
// Should have tool call message and usage message
|
|
162
|
+
expect(messages.some((m) => m.tool_calls)).toBe(true);
|
|
163
|
+
const usageMessage = messages.find((m) => m.usage);
|
|
164
|
+
expect(usageMessage?.usage).toEqual({
|
|
165
|
+
prompt_tokens: 62,
|
|
166
|
+
completion_tokens: 23,
|
|
167
|
+
total_tokens: 85,
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
it('should handle tool calls without call_id (using item id)', async () => {
|
|
171
|
+
const chunks = [
|
|
172
|
+
'data: {"type":"response.output_item.added","sequence_number":1,"output_index":0,"item":{"id":"fc_no_call_id","type":"function_call","status":"in_progress","arguments":"","name":"test_tool"}}\n\n',
|
|
173
|
+
'data: {"type":"response.function_call_arguments.delta","sequence_number":2,"item_id":"fc_no_call_id","output_index":0,"delta":"{\\"test\\":true}"}\n\n',
|
|
174
|
+
'data: {"type":"response.output_item.done","sequence_number":3,"output_index":0,"item":{"id":"fc_no_call_id","type":"function_call","status":"completed","arguments":"{\\"test\\":true}","name":"test_tool"}}\n\n',
|
|
175
|
+
];
|
|
176
|
+
const stream = createSSEStream(chunks);
|
|
177
|
+
const messages = [];
|
|
178
|
+
for await (const message of parseResponsesStream(stream)) {
|
|
179
|
+
messages.push(message);
|
|
180
|
+
}
|
|
181
|
+
const toolCallMessage = messages.find((m) => m.tool_calls);
|
|
182
|
+
expect(toolCallMessage?.tool_calls?.[0]).toEqual({
|
|
183
|
+
id: 'fc_no_call_id', // Falls back to item.id when call_id is not provided
|
|
184
|
+
type: 'function',
|
|
185
|
+
function: {
|
|
186
|
+
name: 'test_tool',
|
|
187
|
+
arguments: '{"test":true}',
|
|
188
|
+
},
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
//# sourceMappingURL=parseResponsesStream.responsesToolCalls.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parseResponsesStream.responsesToolCalls.test.js","sourceRoot":"","sources":["../../../../src/providers/openai/parseResponsesStream.responsesToolCalls.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { parseResponsesStream, parseErrorResponse, } from './parseResponsesStream.js';
|
|
3
|
+
import { ContentGeneratorRole } from '../ContentGeneratorRole.js';
|
|
4
|
+
function createSSEStream(chunks) {
|
|
5
|
+
const encoder = new TextEncoder();
|
|
6
|
+
let index = 0;
|
|
7
|
+
return new ReadableStream({
|
|
8
|
+
async pull(controller) {
|
|
9
|
+
if (index < chunks.length) {
|
|
10
|
+
const chunk = chunks[index++];
|
|
11
|
+
controller.enqueue(encoder.encode(chunk));
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
controller.close();
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
describe('parseResponsesStream', () => {
|
|
20
|
+
it.skip('should parse content chunks correctly', async () => {
|
|
21
|
+
// SKIPPING: Test data uses OpenAI chat completion format but parser expects Responses API format
|
|
22
|
+
const chunks = [
|
|
23
|
+
'data: {"id":"resp-123","model":"gpt-4o","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"Hello"}}]}\n\n',
|
|
24
|
+
'data: {"id":"resp-123","model":"gpt-4o","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":" world"}}]}\n\n',
|
|
25
|
+
'data: {"id":"resp-123","model":"gpt-4o","object":"chat.completion.chunk","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}\n\n',
|
|
26
|
+
'data: [DONE]\n\n',
|
|
27
|
+
];
|
|
28
|
+
const stream = createSSEStream(chunks);
|
|
29
|
+
const messages = [];
|
|
30
|
+
for await (const message of parseResponsesStream(stream)) {
|
|
31
|
+
messages.push(message);
|
|
32
|
+
}
|
|
33
|
+
expect(messages).toHaveLength(2);
|
|
34
|
+
expect(messages[0]).toEqual({
|
|
35
|
+
role: ContentGeneratorRole.ASSISTANT,
|
|
36
|
+
content: 'Hello',
|
|
37
|
+
});
|
|
38
|
+
expect(messages[1]).toEqual({
|
|
39
|
+
role: ContentGeneratorRole.ASSISTANT,
|
|
40
|
+
content: ' world',
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
it.skip('should parse tool calls correctly', async () => {
|
|
44
|
+
// SKIPPING: Test data uses OpenAI chat completion format but parser expects Responses API format
|
|
45
|
+
const chunks = [
|
|
46
|
+
'data: {"id":"resp-123","model":"gpt-4o","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"id":"call_123","type":"function","function":{"name":"search","arguments":"{\\"q"}}]}}]}\n\n',
|
|
47
|
+
'data: {"id":"resp-123","model":"gpt-4o","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"uery\\": \\"test\\"}"}}]}}]}\n\n',
|
|
48
|
+
'data: {"id":"resp-123","model":"gpt-4o","object":"chat.completion.chunk","choices":[{"index":0,"delta":{},"finish_reason":"tool_calls"}]}\n\n',
|
|
49
|
+
'data: [DONE]\n\n',
|
|
50
|
+
];
|
|
51
|
+
const stream = createSSEStream(chunks);
|
|
52
|
+
const messages = [];
|
|
53
|
+
for await (const message of parseResponsesStream(stream)) {
|
|
54
|
+
messages.push(message);
|
|
55
|
+
}
|
|
56
|
+
expect(messages).toHaveLength(1);
|
|
57
|
+
expect(messages[0]).toEqual({
|
|
58
|
+
role: ContentGeneratorRole.ASSISTANT,
|
|
59
|
+
content: '',
|
|
60
|
+
tool_calls: [
|
|
61
|
+
{
|
|
62
|
+
id: 'call_123',
|
|
63
|
+
type: 'function',
|
|
64
|
+
function: {
|
|
65
|
+
name: 'search',
|
|
66
|
+
arguments: '{"query": "test"}',
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
it.skip('should parse usage data correctly', async () => {
|
|
73
|
+
// SKIPPING: Test data uses OpenAI chat completion format but parser expects Responses API format
|
|
74
|
+
const chunks = [
|
|
75
|
+
'data: {"id":"resp-123","model":"gpt-4o","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"Test response"}}]}\n\n',
|
|
76
|
+
'data: {"id":"resp-123","model":"gpt-4o","object":"chat.completion.chunk","choices":[{"index":0,"delta":{},"finish_reason":"stop"}],"usage":{"prompt_tokens":10,"completion_tokens":2,"total_tokens":12}}\n\n',
|
|
77
|
+
'data: [DONE]\n\n',
|
|
78
|
+
];
|
|
79
|
+
const stream = createSSEStream(chunks);
|
|
80
|
+
const messages = [];
|
|
81
|
+
for await (const message of parseResponsesStream(stream)) {
|
|
82
|
+
messages.push(message);
|
|
83
|
+
}
|
|
84
|
+
// Should have content message and final message with usage
|
|
85
|
+
expect(messages.length).toBeGreaterThanOrEqual(2);
|
|
86
|
+
const lastMessage = messages[messages.length - 1];
|
|
87
|
+
expect(lastMessage.usage).toEqual({
|
|
88
|
+
prompt_tokens: 10,
|
|
89
|
+
completion_tokens: 2,
|
|
90
|
+
total_tokens: 12,
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
it.skip('should handle split chunks correctly', async () => {
|
|
94
|
+
// SKIPPING: Test data uses OpenAI chat completion format but parser expects Responses API format
|
|
95
|
+
const chunks = [
|
|
96
|
+
'data: {"id":"resp-123","model":"gpt-4o","object":"chat.completion.chunk","choices":[{"index":0,"delta"',
|
|
97
|
+
':{"content":"Hello world"}}]}\n\ndata: [DONE]\n\n',
|
|
98
|
+
];
|
|
99
|
+
const stream = createSSEStream(chunks);
|
|
100
|
+
const messages = [];
|
|
101
|
+
for await (const message of parseResponsesStream(stream)) {
|
|
102
|
+
messages.push(message);
|
|
103
|
+
}
|
|
104
|
+
expect(messages.length).toBeGreaterThanOrEqual(1);
|
|
105
|
+
expect(messages.some((m) => m.content === 'Hello world')).toBe(true);
|
|
106
|
+
});
|
|
107
|
+
it.skip('should skip invalid JSON chunks', async () => {
|
|
108
|
+
// SKIPPING: Test data uses OpenAI chat completion format but parser expects Responses API format
|
|
109
|
+
const chunks = [
|
|
110
|
+
'data: invalid json\n\n',
|
|
111
|
+
'data: {"id":"resp-123","model":"gpt-4o","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"Valid"}}]}\n\n',
|
|
112
|
+
'data: [DONE]\n\n',
|
|
113
|
+
];
|
|
114
|
+
const stream = createSSEStream(chunks);
|
|
115
|
+
const messages = [];
|
|
116
|
+
for await (const message of parseResponsesStream(stream)) {
|
|
117
|
+
messages.push(message);
|
|
118
|
+
}
|
|
119
|
+
expect(messages).toHaveLength(1);
|
|
120
|
+
expect(messages[0].content).toBe('Valid');
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
describe('parseErrorResponse', () => {
|
|
124
|
+
it('should parse 409 conflict error', () => {
|
|
125
|
+
const error = parseErrorResponse(409, '{"error":{"message":"Conversation already exists"}}', 'Responses');
|
|
126
|
+
expect(error.message).toBe('Conflict: Conversation already exists');
|
|
127
|
+
});
|
|
128
|
+
it('should parse 410 gone error', () => {
|
|
129
|
+
const error = parseErrorResponse(410, '{"error":{"message":"Conversation expired"}}', 'Responses');
|
|
130
|
+
expect(error.message).toBe('Gone: Conversation expired');
|
|
131
|
+
});
|
|
132
|
+
it('should parse 429 rate limit error', () => {
|
|
133
|
+
const error = parseErrorResponse(429, '{"error":{"message":"Too many requests"}}', 'Responses');
|
|
134
|
+
expect(error.message).toBe('Rate limit exceeded: Too many requests');
|
|
135
|
+
});
|
|
136
|
+
it('should parse 5xx server errors', () => {
|
|
137
|
+
const error500 = parseErrorResponse(500, '{"error":{"message":"Internal error"}}', 'Responses');
|
|
138
|
+
expect(error500.message).toBe('Server error: Internal error');
|
|
139
|
+
const error503 = parseErrorResponse(503, '{"error":{"message":"Service unavailable"}}', 'Responses');
|
|
140
|
+
expect(error503.message).toBe('Server error: Service unavailable');
|
|
141
|
+
});
|
|
142
|
+
it('should handle invalid JSON in error response', () => {
|
|
143
|
+
const error = parseErrorResponse(500, 'Not JSON', 'Responses');
|
|
144
|
+
expect(error.message).toBe('Server error: Responses API error: 500');
|
|
145
|
+
});
|
|
146
|
+
it('should handle unknown status codes', () => {
|
|
147
|
+
const error = parseErrorResponse(418, '{"error":{"message":"I am a teapot"}}', 'Responses');
|
|
148
|
+
expect(error.message).toBe('I am a teapot');
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
//# sourceMappingURL=parseResponsesStream.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parseResponsesStream.test.js","sourceRoot":"","sources":["../../../../src/providers/openai/parseResponsesStream.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ITokenizer } from './ITokenizer.js';
|
|
2
|
+
export declare class AnthropicTokenizer implements ITokenizer {
|
|
3
|
+
/**
|
|
4
|
+
* Count tokens for Anthropic models
|
|
5
|
+
*
|
|
6
|
+
* Anthropic uses a tokenizer similar to Claude's tiktoken-based tokenizer.
|
|
7
|
+
* Since there's no official @anthropic-ai/tokenizer package available,
|
|
8
|
+
* we use a character-based estimation that aligns with typical Claude tokenization:
|
|
9
|
+
* - Average ~3.5-4 characters per token for English text
|
|
10
|
+
* - More conservative estimate for code and special characters
|
|
11
|
+
*
|
|
12
|
+
* This estimation should be within 10-15% of actual token counts for most content.
|
|
13
|
+
*
|
|
14
|
+
* @param text The text to tokenize
|
|
15
|
+
* @param model The model name (for model-specific tokenization if needed)
|
|
16
|
+
* @returns Estimated token count
|
|
17
|
+
*/
|
|
18
|
+
countTokens(text: string, _model: string): Promise<number>;
|
|
19
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export class AnthropicTokenizer {
|
|
2
|
+
/**
|
|
3
|
+
* Count tokens for Anthropic models
|
|
4
|
+
*
|
|
5
|
+
* Anthropic uses a tokenizer similar to Claude's tiktoken-based tokenizer.
|
|
6
|
+
* Since there's no official @anthropic-ai/tokenizer package available,
|
|
7
|
+
* we use a character-based estimation that aligns with typical Claude tokenization:
|
|
8
|
+
* - Average ~3.5-4 characters per token for English text
|
|
9
|
+
* - More conservative estimate for code and special characters
|
|
10
|
+
*
|
|
11
|
+
* This estimation should be within 10-15% of actual token counts for most content.
|
|
12
|
+
*
|
|
13
|
+
* @param text The text to tokenize
|
|
14
|
+
* @param model The model name (for model-specific tokenization if needed)
|
|
15
|
+
* @returns Estimated token count
|
|
16
|
+
*/
|
|
17
|
+
async countTokens(text, _model) {
|
|
18
|
+
// Base estimation: ~4 characters per token
|
|
19
|
+
let baseEstimate = text.length / 4;
|
|
20
|
+
// Adjust for code content (more tokens due to special characters)
|
|
21
|
+
const codeIndicators = /[{}[\]()<>:;=,\n\t]/g;
|
|
22
|
+
const codeMatches = text.match(codeIndicators);
|
|
23
|
+
if (codeMatches && codeMatches.length > text.length * 0.1) {
|
|
24
|
+
// If more than 10% special characters, it's likely code
|
|
25
|
+
baseEstimate = text.length / 3.5;
|
|
26
|
+
}
|
|
27
|
+
// Adjust for whitespace (multiple spaces/newlines count as fewer tokens)
|
|
28
|
+
const whitespaceRuns = text.match(/\s{2,}/g);
|
|
29
|
+
if (whitespaceRuns) {
|
|
30
|
+
const extraWhitespace = whitespaceRuns.reduce((sum, run) => sum + run.length - 1, 0);
|
|
31
|
+
baseEstimate -= extraWhitespace / 4;
|
|
32
|
+
}
|
|
33
|
+
// Round up to be conservative (better to overestimate than underestimate)
|
|
34
|
+
return Math.ceil(baseEstimate);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=AnthropicTokenizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AnthropicTokenizer.js","sourceRoot":"","sources":["../../../../src/providers/tokenizers/AnthropicTokenizer.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,kBAAkB;IAC7B;;;;;;;;;;;;;;OAcG;IACH,KAAK,CAAC,WAAW,CAAC,IAAY,EAAE,MAAc;QAC5C,2CAA2C;QAC3C,IAAI,YAAY,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QAEnC,kEAAkE;QAClE,MAAM,cAAc,GAAG,sBAAsB,CAAC;QAC9C,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QAC/C,IAAI,WAAW,IAAI,WAAW,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;YAC1D,wDAAwD;YACxD,YAAY,GAAG,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC;QACnC,CAAC;QAED,yEAAyE;QACzE,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAC7C,IAAI,cAAc,EAAE,CAAC;YACnB,MAAM,eAAe,GAAG,cAAc,CAAC,MAAM,CAC3C,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,EAClC,CAAC,CACF,CAAC;YACF,YAAY,IAAI,eAAe,GAAG,CAAC,CAAC;QACtC,CAAC;QAED,0EAA0E;QAC1E,OAAO,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACjC,CAAC;CACF"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2025 Vybestack LLC
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
export interface ITokenizer {
|
|
17
|
+
countTokens(text: string, model: string): Promise<number>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2025 Vybestack LLC
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=ITokenizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ITokenizer.js","sourceRoot":"","sources":["../../../../src/providers/tokenizers/ITokenizer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2025 Vybestack LLC
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import { ITokenizer } from './ITokenizer.js';
|
|
17
|
+
export declare class OpenAITokenizer implements ITokenizer {
|
|
18
|
+
private encoderCache;
|
|
19
|
+
countTokens(text: string, model: string): Promise<number>;
|
|
20
|
+
/**
|
|
21
|
+
* Clean up encoder resources
|
|
22
|
+
*/
|
|
23
|
+
dispose(): void;
|
|
24
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2025 Vybestack LLC
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import { encoding_for_model } from '@dqbd/tiktoken';
|
|
17
|
+
export class OpenAITokenizer {
|
|
18
|
+
encoderCache = new Map();
|
|
19
|
+
async countTokens(text, model) {
|
|
20
|
+
try {
|
|
21
|
+
// Get or create encoder for the model
|
|
22
|
+
let encoder = this.encoderCache.get(model);
|
|
23
|
+
if (!encoder) {
|
|
24
|
+
// Try to get encoder for the specific model
|
|
25
|
+
try {
|
|
26
|
+
encoder = encoding_for_model(model);
|
|
27
|
+
this.encoderCache.set(model, encoder);
|
|
28
|
+
}
|
|
29
|
+
catch (_error) {
|
|
30
|
+
// Fall back to cl100k_base encoding for newer models
|
|
31
|
+
console.warn(`No specific encoding for model ${model}, using cl100k_base`);
|
|
32
|
+
encoder = encoding_for_model('gpt-4');
|
|
33
|
+
this.encoderCache.set(model, encoder);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
// Count tokens
|
|
37
|
+
const tokens = encoder.encode(text);
|
|
38
|
+
return tokens.length;
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
console.error('Error counting tokens:', error);
|
|
42
|
+
// Fallback: rough estimate based on characters
|
|
43
|
+
return Math.ceil(text.length / 4);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Clean up encoder resources
|
|
48
|
+
*/
|
|
49
|
+
dispose() {
|
|
50
|
+
for (const encoder of this.encoderCache.values()) {
|
|
51
|
+
encoder.free();
|
|
52
|
+
}
|
|
53
|
+
this.encoderCache.clear();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=OpenAITokenizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OpenAITokenizer.js","sourceRoot":"","sources":["../../../../src/providers/tokenizers/OpenAITokenizer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,kBAAkB,EAAiB,MAAM,gBAAgB,CAAC;AAGnE,MAAM,OAAO,eAAe;IAClB,YAAY,GAAG,IAAI,GAAG,EAG3B,CAAC;IAEJ,KAAK,CAAC,WAAW,CAAC,IAAY,EAAE,KAAa;QAC3C,IAAI,CAAC;YACH,sCAAsC;YACtC,IAAI,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAC3C,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,4CAA4C;gBAC5C,IAAI,CAAC;oBACH,OAAO,GAAG,kBAAkB,CAAC,KAAsB,CAAC,CAAC;oBACrD,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;gBACxC,CAAC;gBAAC,OAAO,MAAM,EAAE,CAAC;oBAChB,qDAAqD;oBACrD,OAAO,CAAC,IAAI,CACV,kCAAkC,KAAK,qBAAqB,CAC7D,CAAC;oBACF,OAAO,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;oBACtC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;gBACxC,CAAC;YACH,CAAC;YAED,eAAe;YACf,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACpC,OAAO,MAAM,CAAC,MAAM,CAAC;QACvB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,wBAAwB,EAAE,KAAK,CAAC,CAAC;YAC/C,+CAA+C;YAC/C,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;IAED;;OAEG;IACH,OAAO;QACL,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,EAAE,CAAC;YACjD,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,CAAC;QACD,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC;IAC5B,CAAC;CACF"}
|