@gguf/coder 0.3.0 → 0.3.1
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/.editorconfig +16 -0
- package/.env.example +63 -0
- package/.gitattributes +1 -0
- package/.semgrepignore +19 -0
- package/coder-dummy-file.ts +52 -0
- package/coder.config.example.json +59 -0
- package/coder.config.json +13 -0
- package/color_picker.html +36 -0
- package/package.json +2 -14
- package/scripts/extract-changelog.js +73 -0
- package/scripts/fetch-models.js +143 -0
- package/scripts/test.sh +40 -0
- package/scripts/update-homebrew-formula.sh +125 -0
- package/scripts/update-nix-version.sh +157 -0
- package/source/ai-sdk-client/AISDKClient.spec.ts +117 -0
- package/source/ai-sdk-client/AISDKClient.ts +155 -0
- package/source/ai-sdk-client/chat/chat-handler.spec.ts +121 -0
- package/source/ai-sdk-client/chat/chat-handler.ts +276 -0
- package/source/ai-sdk-client/chat/streaming-handler.spec.ts +173 -0
- package/source/ai-sdk-client/chat/streaming-handler.ts +110 -0
- package/source/ai-sdk-client/chat/tool-processor.spec.ts +92 -0
- package/source/ai-sdk-client/chat/tool-processor.ts +70 -0
- package/source/ai-sdk-client/converters/message-converter.spec.ts +220 -0
- package/source/ai-sdk-client/converters/message-converter.ts +113 -0
- package/source/ai-sdk-client/converters/tool-converter.spec.ts +90 -0
- package/source/ai-sdk-client/converters/tool-converter.ts +46 -0
- package/source/ai-sdk-client/error-handling/error-extractor.spec.ts +55 -0
- package/source/ai-sdk-client/error-handling/error-extractor.ts +15 -0
- package/source/ai-sdk-client/error-handling/error-parser.spec.ts +169 -0
- package/source/ai-sdk-client/error-handling/error-parser.ts +161 -0
- package/source/ai-sdk-client/index.ts +7 -0
- package/source/ai-sdk-client/providers/provider-factory.spec.ts +71 -0
- package/source/ai-sdk-client/providers/provider-factory.ts +41 -0
- package/source/ai-sdk-client/types.ts +9 -0
- package/source/ai-sdk-client-empty-message.spec.ts +141 -0
- package/source/ai-sdk-client-error-handling.spec.ts +186 -0
- package/source/ai-sdk-client-maxretries.spec.ts +114 -0
- package/source/ai-sdk-client-preparestep.spec.ts +279 -0
- package/source/app/App.spec.tsx +32 -0
- package/source/app/App.tsx +480 -0
- package/source/app/components/AppContainer.spec.tsx +96 -0
- package/source/app/components/AppContainer.tsx +56 -0
- package/source/app/components/ChatInterface.spec.tsx +163 -0
- package/source/app/components/ChatInterface.tsx +144 -0
- package/source/app/components/ModalSelectors.spec.tsx +141 -0
- package/source/app/components/ModalSelectors.tsx +135 -0
- package/source/app/helpers.spec.ts +97 -0
- package/source/app/helpers.ts +63 -0
- package/source/app/index.ts +4 -0
- package/source/app/types.ts +39 -0
- package/source/app/utils/appUtils.ts +294 -0
- package/source/app/utils/conversationState.ts +310 -0
- package/source/app.spec.tsx +244 -0
- package/source/cli.spec.ts +73 -0
- package/source/cli.tsx +51 -0
- package/source/client-factory.spec.ts +48 -0
- package/source/client-factory.ts +178 -0
- package/source/command-parser.spec.ts +127 -0
- package/source/command-parser.ts +36 -0
- package/source/commands/checkpoint.spec.tsx +277 -0
- package/source/commands/checkpoint.tsx +366 -0
- package/source/commands/clear.tsx +22 -0
- package/source/commands/custom-commands.tsx +121 -0
- package/source/commands/exit.ts +21 -0
- package/source/commands/export.spec.tsx +131 -0
- package/source/commands/export.tsx +79 -0
- package/source/commands/help.tsx +120 -0
- package/source/commands/index.ts +17 -0
- package/source/commands/init.tsx +339 -0
- package/source/commands/lsp-command.spec.tsx +281 -0
- package/source/commands/lsp.tsx +120 -0
- package/source/commands/mcp-command.spec.tsx +313 -0
- package/source/commands/mcp.tsx +162 -0
- package/source/commands/model-database.spec.tsx +758 -0
- package/source/commands/model-database.tsx +418 -0
- package/source/commands/model.ts +12 -0
- package/source/commands/provider.ts +12 -0
- package/source/commands/setup-config.tsx +16 -0
- package/source/commands/simple-commands.spec.tsx +175 -0
- package/source/commands/status.ts +12 -0
- package/source/commands/theme.ts +12 -0
- package/source/commands/update.spec.tsx +261 -0
- package/source/commands/update.tsx +201 -0
- package/source/commands/usage.spec.tsx +495 -0
- package/source/commands/usage.tsx +100 -0
- package/source/commands.spec.ts +436 -0
- package/source/commands.ts +83 -0
- package/source/components/assistant-message.spec.tsx +796 -0
- package/source/components/assistant-message.tsx +34 -0
- package/source/components/bash-execution-indicator.tsx +21 -0
- package/source/components/cancelling-indicator.tsx +16 -0
- package/source/components/chat-queue.spec.tsx +83 -0
- package/source/components/chat-queue.tsx +36 -0
- package/source/components/checkpoint-display.spec.tsx +219 -0
- package/source/components/checkpoint-display.tsx +126 -0
- package/source/components/checkpoint-selector.spec.tsx +173 -0
- package/source/components/checkpoint-selector.tsx +173 -0
- package/source/components/development-mode-indicator.spec.tsx +268 -0
- package/source/components/development-mode-indicator.tsx +38 -0
- package/source/components/message-box.spec.tsx +427 -0
- package/source/components/message-box.tsx +87 -0
- package/source/components/model-selector.tsx +132 -0
- package/source/components/provider-selector.tsx +75 -0
- package/source/components/random-spinner.tsx +19 -0
- package/source/components/security-disclaimer.tsx +73 -0
- package/source/components/status-connection-display.spec.tsx +133 -0
- package/source/components/status.tsx +267 -0
- package/source/components/theme-selector.tsx +126 -0
- package/source/components/tool-confirmation.tsx +190 -0
- package/source/components/tool-execution-indicator.tsx +33 -0
- package/source/components/tool-message.tsx +85 -0
- package/source/components/ui/titled-box.spec.tsx +207 -0
- package/source/components/ui/titled-box.tsx +57 -0
- package/source/components/usage/progress-bar.spec.tsx +398 -0
- package/source/components/usage/progress-bar.tsx +30 -0
- package/source/components/usage/usage-display.spec.tsx +780 -0
- package/source/components/usage/usage-display.tsx +291 -0
- package/source/components/user-input.spec.tsx +327 -0
- package/source/components/user-input.tsx +533 -0
- package/source/components/user-message.spec.tsx +230 -0
- package/source/components/user-message.tsx +84 -0
- package/source/components/welcome-message.tsx +76 -0
- package/source/config/env-substitution.ts +65 -0
- package/source/config/index.spec.ts +171 -0
- package/source/config/index.ts +154 -0
- package/source/config/paths.spec.ts +241 -0
- package/source/config/paths.ts +55 -0
- package/source/config/preferences.ts +51 -0
- package/source/config/themes.ts +315 -0
- package/source/constants.ts +130 -0
- package/source/context/mode-context.spec.ts +79 -0
- package/source/context/mode-context.ts +24 -0
- package/source/custom-commands/executor.spec.ts +142 -0
- package/source/custom-commands/executor.ts +64 -0
- package/source/custom-commands/loader.spec.ts +314 -0
- package/source/custom-commands/loader.ts +153 -0
- package/source/custom-commands/parser.ts +196 -0
- package/source/hooks/chat-handler/conversation/conversation-loop.spec.ts +39 -0
- package/source/hooks/chat-handler/conversation/conversation-loop.tsx +511 -0
- package/source/hooks/chat-handler/conversation/tool-executor.spec.ts +50 -0
- package/source/hooks/chat-handler/conversation/tool-executor.tsx +109 -0
- package/source/hooks/chat-handler/index.ts +12 -0
- package/source/hooks/chat-handler/state/streaming-state.spec.ts +26 -0
- package/source/hooks/chat-handler/state/streaming-state.ts +19 -0
- package/source/hooks/chat-handler/types.ts +38 -0
- package/source/hooks/chat-handler/useChatHandler.spec.tsx +321 -0
- package/source/hooks/chat-handler/useChatHandler.tsx +194 -0
- package/source/hooks/chat-handler/utils/context-checker.spec.ts +60 -0
- package/source/hooks/chat-handler/utils/context-checker.tsx +73 -0
- package/source/hooks/chat-handler/utils/message-helpers.spec.ts +42 -0
- package/source/hooks/chat-handler/utils/message-helpers.tsx +36 -0
- package/source/hooks/chat-handler/utils/tool-filters.spec.ts +109 -0
- package/source/hooks/chat-handler/utils/tool-filters.ts +64 -0
- package/source/hooks/useAppHandlers.tsx +291 -0
- package/source/hooks/useAppInitialization.tsx +422 -0
- package/source/hooks/useAppState.tsx +311 -0
- package/source/hooks/useDirectoryTrust.tsx +98 -0
- package/source/hooks/useInputState.ts +414 -0
- package/source/hooks/useModeHandlers.tsx +302 -0
- package/source/hooks/useNonInteractiveMode.ts +140 -0
- package/source/hooks/useTerminalWidth.tsx +81 -0
- package/source/hooks/useTheme.ts +18 -0
- package/source/hooks/useToolHandler.tsx +349 -0
- package/source/hooks/useUIState.ts +61 -0
- package/source/init/agents-template-generator.ts +421 -0
- package/source/init/existing-rules-extractor.ts +319 -0
- package/source/init/file-scanner.spec.ts +227 -0
- package/source/init/file-scanner.ts +238 -0
- package/source/init/framework-detector.ts +382 -0
- package/source/init/language-detector.ts +269 -0
- package/source/init/project-analyzer.spec.ts +231 -0
- package/source/init/project-analyzer.ts +458 -0
- package/source/lsp/index.ts +31 -0
- package/source/lsp/lsp-client.spec.ts +508 -0
- package/source/lsp/lsp-client.ts +487 -0
- package/source/lsp/lsp-manager.spec.ts +477 -0
- package/source/lsp/lsp-manager.ts +419 -0
- package/source/lsp/protocol.spec.ts +502 -0
- package/source/lsp/protocol.ts +360 -0
- package/source/lsp/server-discovery.spec.ts +654 -0
- package/source/lsp/server-discovery.ts +515 -0
- package/source/markdown-parser/html-entities.spec.ts +88 -0
- package/source/markdown-parser/html-entities.ts +45 -0
- package/source/markdown-parser/index.spec.ts +281 -0
- package/source/markdown-parser/index.ts +126 -0
- package/source/markdown-parser/table-parser.spec.ts +133 -0
- package/source/markdown-parser/table-parser.ts +114 -0
- package/source/markdown-parser/utils.spec.ts +70 -0
- package/source/markdown-parser/utils.ts +13 -0
- package/source/mcp/mcp-client.spec.ts +81 -0
- package/source/mcp/mcp-client.ts +625 -0
- package/source/mcp/transport-factory.spec.ts +406 -0
- package/source/mcp/transport-factory.ts +312 -0
- package/source/message-handler.ts +67 -0
- package/source/model-database/database-engine.spec.ts +494 -0
- package/source/model-database/database-engine.ts +50 -0
- package/source/model-database/model-database.spec.ts +363 -0
- package/source/model-database/model-database.ts +91 -0
- package/source/model-database/model-engine.spec.ts +447 -0
- package/source/model-database/model-engine.ts +65 -0
- package/source/model-database/model-fetcher.spec.ts +583 -0
- package/source/model-database/model-fetcher.ts +330 -0
- package/source/models/index.ts +1 -0
- package/source/models/models-cache.spec.ts +214 -0
- package/source/models/models-cache.ts +78 -0
- package/source/models/models-dev-client.spec.ts +379 -0
- package/source/models/models-dev-client.ts +329 -0
- package/source/models/models-types.ts +68 -0
- package/source/prompt-history.ts +155 -0
- package/source/security/command-injection.spec.ts +240 -0
- package/source/services/checkpoint-manager.spec.ts +523 -0
- package/source/services/checkpoint-manager.ts +466 -0
- package/source/services/file-snapshot.spec.ts +569 -0
- package/source/services/file-snapshot.ts +220 -0
- package/source/test-utils/render-with-theme.tsx +48 -0
- package/source/tokenization/index.ts +1 -0
- package/source/tokenization/tokenizer-factory.spec.ts +170 -0
- package/source/tokenization/tokenizer-factory.ts +125 -0
- package/source/tokenization/tokenizers/anthropic-tokenizer.spec.ts +200 -0
- package/source/tokenization/tokenizers/anthropic-tokenizer.ts +43 -0
- package/source/tokenization/tokenizers/fallback-tokenizer.spec.ts +236 -0
- package/source/tokenization/tokenizers/fallback-tokenizer.ts +26 -0
- package/source/tokenization/tokenizers/llama-tokenizer.spec.ts +224 -0
- package/source/tokenization/tokenizers/llama-tokenizer.ts +41 -0
- package/source/tokenization/tokenizers/openai-tokenizer.spec.ts +184 -0
- package/source/tokenization/tokenizers/openai-tokenizer.ts +57 -0
- package/source/tool-calling/index.ts +5 -0
- package/source/tool-calling/json-parser.spec.ts +639 -0
- package/source/tool-calling/json-parser.ts +247 -0
- package/source/tool-calling/tool-parser.spec.ts +395 -0
- package/source/tool-calling/tool-parser.ts +120 -0
- package/source/tool-calling/xml-parser.spec.ts +662 -0
- package/source/tool-calling/xml-parser.ts +289 -0
- package/source/tools/execute-bash.spec.tsx +353 -0
- package/source/tools/execute-bash.tsx +219 -0
- package/source/tools/execute-function.spec.ts +130 -0
- package/source/tools/fetch-url.spec.tsx +342 -0
- package/source/tools/fetch-url.tsx +172 -0
- package/source/tools/find-files.spec.tsx +924 -0
- package/source/tools/find-files.tsx +293 -0
- package/source/tools/index.ts +102 -0
- package/source/tools/lsp-get-diagnostics.tsx +192 -0
- package/source/tools/needs-approval.spec.ts +282 -0
- package/source/tools/read-file.spec.tsx +801 -0
- package/source/tools/read-file.tsx +387 -0
- package/source/tools/search-file-contents.spec.tsx +1273 -0
- package/source/tools/search-file-contents.tsx +293 -0
- package/source/tools/string-replace.spec.tsx +730 -0
- package/source/tools/string-replace.tsx +548 -0
- package/source/tools/tool-manager.ts +210 -0
- package/source/tools/tool-registry.spec.ts +415 -0
- package/source/tools/tool-registry.ts +228 -0
- package/source/tools/web-search.tsx +223 -0
- package/source/tools/write-file.spec.tsx +559 -0
- package/source/tools/write-file.tsx +228 -0
- package/source/types/app.ts +37 -0
- package/source/types/checkpoint.ts +48 -0
- package/source/types/commands.ts +46 -0
- package/source/types/components.ts +27 -0
- package/source/types/config.ts +103 -0
- package/source/types/core-connection-status.spec.ts +67 -0
- package/source/types/core.ts +181 -0
- package/source/types/hooks.ts +50 -0
- package/source/types/index.ts +12 -0
- package/source/types/markdown-parser.ts +11 -0
- package/source/types/mcp.ts +52 -0
- package/source/types/system.ts +16 -0
- package/source/types/tokenization.ts +41 -0
- package/source/types/ui.ts +40 -0
- package/source/types/usage.ts +58 -0
- package/source/types/utils.ts +16 -0
- package/source/usage/calculator.spec.ts +385 -0
- package/source/usage/calculator.ts +104 -0
- package/source/usage/storage.spec.ts +703 -0
- package/source/usage/storage.ts +238 -0
- package/source/usage/tracker.spec.ts +456 -0
- package/source/usage/tracker.ts +102 -0
- package/source/utils/atomic-deletion.spec.ts +194 -0
- package/source/utils/atomic-deletion.ts +127 -0
- package/source/utils/bounded-map.spec.ts +300 -0
- package/source/utils/bounded-map.ts +193 -0
- package/source/utils/checkpoint-utils.spec.ts +222 -0
- package/source/utils/checkpoint-utils.ts +92 -0
- package/source/utils/error-formatter.spec.ts +169 -0
- package/source/utils/error-formatter.ts +194 -0
- package/source/utils/file-autocomplete.spec.ts +173 -0
- package/source/utils/file-autocomplete.ts +196 -0
- package/source/utils/file-cache.spec.ts +309 -0
- package/source/utils/file-cache.ts +195 -0
- package/source/utils/file-content-loader.spec.ts +180 -0
- package/source/utils/file-content-loader.ts +179 -0
- package/source/utils/file-mention-handler.spec.ts +261 -0
- package/source/utils/file-mention-handler.ts +84 -0
- package/source/utils/file-mention-parser.spec.ts +182 -0
- package/source/utils/file-mention-parser.ts +170 -0
- package/source/utils/fuzzy-matching.spec.ts +149 -0
- package/source/utils/fuzzy-matching.ts +146 -0
- package/source/utils/indentation-normalizer.spec.ts +216 -0
- package/source/utils/indentation-normalizer.ts +76 -0
- package/source/utils/installation-detector.spec.ts +178 -0
- package/source/utils/installation-detector.ts +153 -0
- package/source/utils/logging/config.spec.ts +311 -0
- package/source/utils/logging/config.ts +210 -0
- package/source/utils/logging/console-facade.spec.ts +184 -0
- package/source/utils/logging/console-facade.ts +384 -0
- package/source/utils/logging/correlation.spec.ts +679 -0
- package/source/utils/logging/correlation.ts +474 -0
- package/source/utils/logging/formatters.spec.ts +464 -0
- package/source/utils/logging/formatters.ts +207 -0
- package/source/utils/logging/health-monitor/alerts/alert-manager.spec.ts +93 -0
- package/source/utils/logging/health-monitor/alerts/alert-manager.ts +79 -0
- package/source/utils/logging/health-monitor/checks/configuration-check.spec.ts +56 -0
- package/source/utils/logging/health-monitor/checks/configuration-check.ts +43 -0
- package/source/utils/logging/health-monitor/checks/logging-check.spec.ts +56 -0
- package/source/utils/logging/health-monitor/checks/logging-check.ts +58 -0
- package/source/utils/logging/health-monitor/checks/memory-check.spec.ts +100 -0
- package/source/utils/logging/health-monitor/checks/memory-check.ts +78 -0
- package/source/utils/logging/health-monitor/checks/performance-check.spec.ts +56 -0
- package/source/utils/logging/health-monitor/checks/performance-check.ts +56 -0
- package/source/utils/logging/health-monitor/checks/request-check.spec.ts +56 -0
- package/source/utils/logging/health-monitor/checks/request-check.ts +76 -0
- package/source/utils/logging/health-monitor/core/health-check-runner.spec.ts +70 -0
- package/source/utils/logging/health-monitor/core/health-check-runner.ts +138 -0
- package/source/utils/logging/health-monitor/core/health-monitor.spec.ts +58 -0
- package/source/utils/logging/health-monitor/core/health-monitor.ts +344 -0
- package/source/utils/logging/health-monitor/core/scoring.spec.ts +65 -0
- package/source/utils/logging/health-monitor/core/scoring.ts +91 -0
- package/source/utils/logging/health-monitor/index.ts +15 -0
- package/source/utils/logging/health-monitor/instances.ts +48 -0
- package/source/utils/logging/health-monitor/middleware/http-middleware.spec.ts +141 -0
- package/source/utils/logging/health-monitor/middleware/http-middleware.ts +75 -0
- package/source/utils/logging/health-monitor/types.ts +126 -0
- package/source/utils/logging/index.spec.ts +284 -0
- package/source/utils/logging/index.ts +236 -0
- package/source/utils/logging/integration.spec.ts +441 -0
- package/source/utils/logging/log-method-factory.spec.ts +573 -0
- package/source/utils/logging/log-method-factory.ts +233 -0
- package/source/utils/logging/log-query/aggregation/aggregator.spec.ts +277 -0
- package/source/utils/logging/log-query/aggregation/aggregator.ts +159 -0
- package/source/utils/logging/log-query/aggregation/facet-generator.spec.ts +159 -0
- package/source/utils/logging/log-query/aggregation/facet-generator.ts +47 -0
- package/source/utils/logging/log-query/index.ts +23 -0
- package/source/utils/logging/log-query/query/filter-predicates.spec.ts +247 -0
- package/source/utils/logging/log-query/query/filter-predicates.ts +154 -0
- package/source/utils/logging/log-query/query/query-builder.spec.ts +182 -0
- package/source/utils/logging/log-query/query/query-builder.ts +151 -0
- package/source/utils/logging/log-query/query/query-engine.spec.ts +214 -0
- package/source/utils/logging/log-query/query/query-engine.ts +45 -0
- package/source/utils/logging/log-query/storage/circular-buffer.spec.ts +143 -0
- package/source/utils/logging/log-query/storage/circular-buffer.ts +75 -0
- package/source/utils/logging/log-query/storage/index-manager.spec.ts +150 -0
- package/source/utils/logging/log-query/storage/index-manager.ts +71 -0
- package/source/utils/logging/log-query/storage/log-storage.spec.ts +257 -0
- package/source/utils/logging/log-query/storage/log-storage.ts +80 -0
- package/source/utils/logging/log-query/types.ts +163 -0
- package/source/utils/logging/log-query/utils/helpers.spec.ts +263 -0
- package/source/utils/logging/log-query/utils/helpers.ts +72 -0
- package/source/utils/logging/log-query/utils/sorting.spec.ts +182 -0
- package/source/utils/logging/log-query/utils/sorting.ts +61 -0
- package/source/utils/logging/logger-provider.spec.ts +262 -0
- package/source/utils/logging/logger-provider.ts +362 -0
- package/source/utils/logging/performance.spec.ts +209 -0
- package/source/utils/logging/performance.ts +757 -0
- package/source/utils/logging/pino-logger.spec.ts +425 -0
- package/source/utils/logging/pino-logger.ts +514 -0
- package/source/utils/logging/redaction.spec.ts +490 -0
- package/source/utils/logging/redaction.ts +267 -0
- package/source/utils/logging/request-tracker.spec.ts +1198 -0
- package/source/utils/logging/request-tracker.ts +803 -0
- package/source/utils/logging/transports.spec.ts +505 -0
- package/source/utils/logging/transports.ts +305 -0
- package/source/utils/logging/types.ts +216 -0
- package/source/utils/message-builder.spec.ts +179 -0
- package/source/utils/message-builder.ts +101 -0
- package/source/utils/message-queue.tsx +486 -0
- package/source/utils/paste-detection.spec.ts +69 -0
- package/source/utils/paste-detection.ts +124 -0
- package/source/utils/paste-roundtrip.spec.ts +442 -0
- package/source/utils/paste-utils.spec.ts +128 -0
- package/source/utils/paste-utils.ts +52 -0
- package/source/utils/programming-language-helper.spec.ts +74 -0
- package/source/utils/programming-language-helper.ts +32 -0
- package/source/utils/prompt-assembly.spec.ts +221 -0
- package/source/utils/prompt-processor.ts +173 -0
- package/source/utils/tool-args-parser.spec.ts +136 -0
- package/source/utils/tool-args-parser.ts +54 -0
- package/source/utils/tool-cancellation.spec.ts +230 -0
- package/source/utils/tool-cancellation.ts +28 -0
- package/source/utils/tool-result-display.spec.tsx +469 -0
- package/source/utils/tool-result-display.tsx +90 -0
- package/source/utils/update-checker.spec.ts +383 -0
- package/source/utils/update-checker.ts +183 -0
- package/source/wizard/config-wizard.spec.tsx +103 -0
- package/source/wizard/config-wizard.tsx +382 -0
- package/source/wizard/steps/location-step.spec.tsx +186 -0
- package/source/wizard/steps/location-step.tsx +147 -0
- package/source/wizard/steps/mcp-step.spec.tsx +607 -0
- package/source/wizard/steps/mcp-step.tsx +632 -0
- package/source/wizard/steps/provider-step.spec.tsx +342 -0
- package/source/wizard/steps/provider-step.tsx +957 -0
- package/source/wizard/steps/summary-step.spec.tsx +749 -0
- package/source/wizard/steps/summary-step.tsx +228 -0
- package/source/wizard/templates/mcp-templates.spec.ts +613 -0
- package/source/wizard/templates/mcp-templates.ts +570 -0
- package/source/wizard/templates/provider-templates.spec.ts +152 -0
- package/source/wizard/templates/provider-templates.ts +485 -0
- package/source/wizard/utils/fetch-cloud-models.spec.ts +428 -0
- package/source/wizard/utils/fetch-cloud-models.ts +223 -0
- package/source/wizard/utils/fetch-local-models.spec.ts +297 -0
- package/source/wizard/utils/fetch-local-models.ts +192 -0
- package/source/wizard/validation-array.spec.ts +264 -0
- package/source/wizard/validation.spec.ts +373 -0
- package/source/wizard/validation.ts +232 -0
- package/source/app/prompts/main-prompt.md +0 -122
|
@@ -0,0 +1,495 @@
|
|
|
1
|
+
import test from 'ava';
|
|
2
|
+
import {render} from 'ink-testing-library';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import {themes} from '../config/themes.js';
|
|
5
|
+
import {ThemeContext} from '../hooks/useTheme.js';
|
|
6
|
+
import type {Message} from '../types/core.js';
|
|
7
|
+
import {usageCommand} from './usage.js';
|
|
8
|
+
|
|
9
|
+
console.log(`\nusage.spec.tsx – ${React.version}`);
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Note: These tests make real API calls to models.dev via getModelContextLimit().
|
|
13
|
+
* The API has a cache and fallback mechanisms, so it should be reliable.
|
|
14
|
+
* If CI fails due to network issues, we may need to add a proper mocking solution.
|
|
15
|
+
* All tests have reasonable timeouts (default 10s) to prevent hanging.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
// Mock ThemeProvider for testing
|
|
19
|
+
const MockThemeProvider = ({children}: {children: React.ReactNode}) => {
|
|
20
|
+
const mockTheme = {
|
|
21
|
+
currentTheme: 'tokyo-night' as const,
|
|
22
|
+
colors: themes['tokyo-night'].colors,
|
|
23
|
+
setCurrentTheme: () => {},
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<ThemeContext.Provider value={mockTheme}>{children}</ThemeContext.Provider>
|
|
28
|
+
);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// Helper to create mock metadata
|
|
32
|
+
function createMockMetadata(provider = 'test-provider', model = 'test-model') {
|
|
33
|
+
return {
|
|
34
|
+
provider,
|
|
35
|
+
model,
|
|
36
|
+
tokens: 100,
|
|
37
|
+
getMessageTokens: (message: Message) => {
|
|
38
|
+
// Simple mock: count characters as rough token estimate
|
|
39
|
+
return Math.ceil(message.content.length / 4);
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Helper to create messages
|
|
45
|
+
function createMessages(): Message[] {
|
|
46
|
+
return [
|
|
47
|
+
{role: 'user', content: 'Hello, how are you?'},
|
|
48
|
+
{role: 'assistant', content: 'I am doing well, thank you!'},
|
|
49
|
+
{role: 'user', content: 'Can you help me with a task?'},
|
|
50
|
+
];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// ============================================================================
|
|
54
|
+
// Command Metadata Tests
|
|
55
|
+
// ============================================================================
|
|
56
|
+
|
|
57
|
+
test('usage command has correct name', t => {
|
|
58
|
+
t.is(usageCommand.name, 'usage');
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test('usage command has description', t => {
|
|
62
|
+
t.truthy(usageCommand.description);
|
|
63
|
+
t.is(typeof usageCommand.description, 'string');
|
|
64
|
+
t.true(usageCommand.description.length > 0);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test('usage command handler is a function', t => {
|
|
68
|
+
t.is(typeof usageCommand.handler, 'function');
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// ============================================================================
|
|
72
|
+
// Command Handler Tests
|
|
73
|
+
// ============================================================================
|
|
74
|
+
|
|
75
|
+
test('usage command handler returns valid React element', async t => {
|
|
76
|
+
const messages = createMessages();
|
|
77
|
+
const metadata = createMockMetadata();
|
|
78
|
+
|
|
79
|
+
const result = await usageCommand.handler([], messages, metadata);
|
|
80
|
+
|
|
81
|
+
t.truthy(result);
|
|
82
|
+
t.true(React.isValidElement(result));
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test('usage command handler with empty messages', async t => {
|
|
86
|
+
const messages: Message[] = [];
|
|
87
|
+
const metadata = createMockMetadata();
|
|
88
|
+
|
|
89
|
+
const result = await usageCommand.handler([], messages, metadata);
|
|
90
|
+
|
|
91
|
+
t.truthy(result);
|
|
92
|
+
t.true(React.isValidElement(result));
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
test('usage command handler with different providers', async t => {
|
|
96
|
+
const messages = createMessages();
|
|
97
|
+
|
|
98
|
+
// Test with different provider names
|
|
99
|
+
const providers = ['openai', 'anthropic', 'ollama'];
|
|
100
|
+
|
|
101
|
+
for (const provider of providers) {
|
|
102
|
+
const metadata = createMockMetadata(provider, 'test-model');
|
|
103
|
+
const result = await usageCommand.handler([], messages, metadata);
|
|
104
|
+
|
|
105
|
+
t.truthy(result);
|
|
106
|
+
t.true(React.isValidElement(result));
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
test('usage command handler with different models', async t => {
|
|
111
|
+
const messages = createMessages();
|
|
112
|
+
|
|
113
|
+
// Test with a realistic model name that might be found or use fallback
|
|
114
|
+
const metadata = createMockMetadata('test-provider', 'gpt-4');
|
|
115
|
+
const result = await usageCommand.handler([], messages, metadata);
|
|
116
|
+
|
|
117
|
+
t.truthy(result);
|
|
118
|
+
t.true(React.isValidElement(result));
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
test('usage command handler with system messages', async t => {
|
|
122
|
+
const messages: Message[] = [
|
|
123
|
+
{role: 'system', content: 'You are a helpful assistant.'},
|
|
124
|
+
{role: 'user', content: 'Hello'},
|
|
125
|
+
{role: 'assistant', content: 'Hi there!'},
|
|
126
|
+
];
|
|
127
|
+
const metadata = createMockMetadata();
|
|
128
|
+
|
|
129
|
+
const result = await usageCommand.handler([], messages, metadata);
|
|
130
|
+
|
|
131
|
+
t.truthy(result);
|
|
132
|
+
t.true(React.isValidElement(result));
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
test('usage command handler with tool messages', async t => {
|
|
136
|
+
const messages: Message[] = [
|
|
137
|
+
{role: 'user', content: 'List files'},
|
|
138
|
+
{
|
|
139
|
+
role: 'assistant',
|
|
140
|
+
content: '',
|
|
141
|
+
tool_calls: [
|
|
142
|
+
{
|
|
143
|
+
id: 'call_1',
|
|
144
|
+
function: {name: 'search_files', arguments: {pattern: '**/*.ts'}},
|
|
145
|
+
},
|
|
146
|
+
],
|
|
147
|
+
},
|
|
148
|
+
{role: 'tool', content: 'file1.ts\nfile2.ts', tool_call_id: 'call_1'},
|
|
149
|
+
];
|
|
150
|
+
const metadata = createMockMetadata();
|
|
151
|
+
|
|
152
|
+
const result = await usageCommand.handler([], messages, metadata);
|
|
153
|
+
|
|
154
|
+
t.truthy(result);
|
|
155
|
+
t.true(React.isValidElement(result));
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
test('usage command handler with multiple message types', async t => {
|
|
159
|
+
const messages: Message[] = [
|
|
160
|
+
{role: 'system', content: 'You are a helpful assistant.'},
|
|
161
|
+
{role: 'user', content: 'Hello'},
|
|
162
|
+
{role: 'assistant', content: 'Hi! How can I help?'},
|
|
163
|
+
{role: 'user', content: 'Search for files'},
|
|
164
|
+
{
|
|
165
|
+
role: 'assistant',
|
|
166
|
+
content: '',
|
|
167
|
+
tool_calls: [
|
|
168
|
+
{
|
|
169
|
+
id: 'call_1',
|
|
170
|
+
function: {name: 'search_files', arguments: {pattern: '*.ts'}},
|
|
171
|
+
},
|
|
172
|
+
],
|
|
173
|
+
},
|
|
174
|
+
{role: 'tool', content: 'Results here', tool_call_id: 'call_1'},
|
|
175
|
+
{role: 'assistant', content: 'Here are the files I found.'},
|
|
176
|
+
];
|
|
177
|
+
const metadata = createMockMetadata();
|
|
178
|
+
|
|
179
|
+
const result = await usageCommand.handler([], messages, metadata);
|
|
180
|
+
|
|
181
|
+
t.truthy(result);
|
|
182
|
+
t.true(React.isValidElement(result));
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
// ============================================================================
|
|
186
|
+
// Component Rendering Tests
|
|
187
|
+
// ============================================================================
|
|
188
|
+
|
|
189
|
+
test('usage command renders without crashing', async t => {
|
|
190
|
+
const messages = createMessages();
|
|
191
|
+
const metadata = createMockMetadata();
|
|
192
|
+
|
|
193
|
+
const result = await usageCommand.handler([], messages, metadata);
|
|
194
|
+
const {lastFrame} = render(<MockThemeProvider>{result}</MockThemeProvider>);
|
|
195
|
+
|
|
196
|
+
t.truthy(lastFrame());
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
test('usage command displays provider name', async t => {
|
|
200
|
+
const messages = createMessages();
|
|
201
|
+
const metadata = createMockMetadata('openai', 'gpt-4');
|
|
202
|
+
|
|
203
|
+
const result = await usageCommand.handler([], messages, metadata);
|
|
204
|
+
const {lastFrame} = render(<MockThemeProvider>{result}</MockThemeProvider>);
|
|
205
|
+
|
|
206
|
+
const output = lastFrame();
|
|
207
|
+
t.truthy(output);
|
|
208
|
+
t.regex(output!, /openai/i);
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
test('usage command displays model name', async t => {
|
|
212
|
+
const messages = createMessages();
|
|
213
|
+
const metadata = createMockMetadata('anthropic', 'claude-3-opus');
|
|
214
|
+
|
|
215
|
+
const result = await usageCommand.handler([], messages, metadata);
|
|
216
|
+
const {lastFrame} = render(<MockThemeProvider>{result}</MockThemeProvider>);
|
|
217
|
+
|
|
218
|
+
const output = lastFrame();
|
|
219
|
+
t.truthy(output);
|
|
220
|
+
t.regex(output!, /claude-3-opus/);
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
test('usage command displays context usage header', async t => {
|
|
224
|
+
const messages = createMessages();
|
|
225
|
+
const metadata = createMockMetadata();
|
|
226
|
+
|
|
227
|
+
const result = await usageCommand.handler([], messages, metadata);
|
|
228
|
+
const {lastFrame} = render(<MockThemeProvider>{result}</MockThemeProvider>);
|
|
229
|
+
|
|
230
|
+
const output = lastFrame();
|
|
231
|
+
t.truthy(output);
|
|
232
|
+
t.regex(output!, /Context Usage/);
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
test('usage command displays overall usage section', async t => {
|
|
236
|
+
const messages = createMessages();
|
|
237
|
+
const metadata = createMockMetadata();
|
|
238
|
+
|
|
239
|
+
const result = await usageCommand.handler([], messages, metadata);
|
|
240
|
+
const {lastFrame} = render(<MockThemeProvider>{result}</MockThemeProvider>);
|
|
241
|
+
|
|
242
|
+
const output = lastFrame();
|
|
243
|
+
t.truthy(output);
|
|
244
|
+
t.regex(output!, /Overall Usage/);
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
test('usage command displays category breakdown', async t => {
|
|
248
|
+
const messages = createMessages();
|
|
249
|
+
const metadata = createMockMetadata();
|
|
250
|
+
|
|
251
|
+
const result = await usageCommand.handler([], messages, metadata);
|
|
252
|
+
const {lastFrame} = render(<MockThemeProvider>{result}</MockThemeProvider>);
|
|
253
|
+
|
|
254
|
+
const output = lastFrame();
|
|
255
|
+
t.truthy(output);
|
|
256
|
+
t.regex(output!, /Breakdown by Category/);
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
test('usage command displays system prompt category', async t => {
|
|
260
|
+
const messages = createMessages();
|
|
261
|
+
const metadata = createMockMetadata();
|
|
262
|
+
|
|
263
|
+
const result = await usageCommand.handler([], messages, metadata);
|
|
264
|
+
const {lastFrame} = render(<MockThemeProvider>{result}</MockThemeProvider>);
|
|
265
|
+
|
|
266
|
+
const output = lastFrame();
|
|
267
|
+
t.truthy(output);
|
|
268
|
+
t.regex(output!, /System Prompt/);
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
test('usage command displays user messages category', async t => {
|
|
272
|
+
const messages = createMessages();
|
|
273
|
+
const metadata = createMockMetadata();
|
|
274
|
+
|
|
275
|
+
const result = await usageCommand.handler([], messages, metadata);
|
|
276
|
+
const {lastFrame} = render(<MockThemeProvider>{result}</MockThemeProvider>);
|
|
277
|
+
|
|
278
|
+
const output = lastFrame();
|
|
279
|
+
t.truthy(output);
|
|
280
|
+
t.regex(output!, /User Messages/);
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
test('usage command displays assistant messages category', async t => {
|
|
284
|
+
const messages = createMessages();
|
|
285
|
+
const metadata = createMockMetadata();
|
|
286
|
+
|
|
287
|
+
const result = await usageCommand.handler([], messages, metadata);
|
|
288
|
+
const {lastFrame} = render(<MockThemeProvider>{result}</MockThemeProvider>);
|
|
289
|
+
|
|
290
|
+
const output = lastFrame();
|
|
291
|
+
t.truthy(output);
|
|
292
|
+
t.regex(output!, /Assistant Messages/);
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
test('usage command displays tool messages category', async t => {
|
|
296
|
+
const messages = createMessages();
|
|
297
|
+
const metadata = createMockMetadata();
|
|
298
|
+
|
|
299
|
+
const result = await usageCommand.handler([], messages, metadata);
|
|
300
|
+
const {lastFrame} = render(<MockThemeProvider>{result}</MockThemeProvider>);
|
|
301
|
+
|
|
302
|
+
const output = lastFrame();
|
|
303
|
+
t.truthy(output);
|
|
304
|
+
t.regex(output!, /Tool Messages/);
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
test('usage command displays tool definitions category', async t => {
|
|
308
|
+
const messages = createMessages();
|
|
309
|
+
const metadata = createMockMetadata();
|
|
310
|
+
|
|
311
|
+
const result = await usageCommand.handler([], messages, metadata);
|
|
312
|
+
const {lastFrame} = render(<MockThemeProvider>{result}</MockThemeProvider>);
|
|
313
|
+
|
|
314
|
+
const output = lastFrame();
|
|
315
|
+
t.truthy(output);
|
|
316
|
+
t.regex(output!, /Tool Definitions/);
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
test('usage command displays model information section', async t => {
|
|
320
|
+
const messages = createMessages();
|
|
321
|
+
const metadata = createMockMetadata();
|
|
322
|
+
|
|
323
|
+
const result = await usageCommand.handler([], messages, metadata);
|
|
324
|
+
const {lastFrame} = render(<MockThemeProvider>{result}</MockThemeProvider>);
|
|
325
|
+
|
|
326
|
+
const output = lastFrame();
|
|
327
|
+
t.truthy(output);
|
|
328
|
+
t.regex(output!, /Model Information/);
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
test('usage command displays recent activity section', async t => {
|
|
332
|
+
const messages = createMessages();
|
|
333
|
+
const metadata = createMockMetadata();
|
|
334
|
+
|
|
335
|
+
const result = await usageCommand.handler([], messages, metadata);
|
|
336
|
+
const {lastFrame} = render(<MockThemeProvider>{result}</MockThemeProvider>);
|
|
337
|
+
|
|
338
|
+
const output = lastFrame();
|
|
339
|
+
t.truthy(output);
|
|
340
|
+
t.regex(output!, /Recent Activity/);
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
test('usage command displays tokenizer name', async t => {
|
|
344
|
+
const messages = createMessages();
|
|
345
|
+
const metadata = createMockMetadata();
|
|
346
|
+
|
|
347
|
+
const result = await usageCommand.handler([], messages, metadata);
|
|
348
|
+
const {lastFrame} = render(<MockThemeProvider>{result}</MockThemeProvider>);
|
|
349
|
+
|
|
350
|
+
const output = lastFrame();
|
|
351
|
+
t.truthy(output);
|
|
352
|
+
// Should display "Tokenizer:" label
|
|
353
|
+
t.regex(output!, /Tokenizer:/);
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
test('usage command displays available tokens', async t => {
|
|
357
|
+
const messages = createMessages();
|
|
358
|
+
const metadata = createMockMetadata();
|
|
359
|
+
|
|
360
|
+
const result = await usageCommand.handler([], messages, metadata);
|
|
361
|
+
const {lastFrame} = render(<MockThemeProvider>{result}</MockThemeProvider>);
|
|
362
|
+
|
|
363
|
+
const output = lastFrame();
|
|
364
|
+
t.truthy(output);
|
|
365
|
+
t.regex(output!, /Available:/);
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
// ============================================================================
|
|
369
|
+
// Edge Cases
|
|
370
|
+
// ============================================================================
|
|
371
|
+
|
|
372
|
+
test('usage command handles very long messages', async t => {
|
|
373
|
+
const longContent = 'a'.repeat(10000);
|
|
374
|
+
const messages: Message[] = [
|
|
375
|
+
{role: 'user', content: longContent},
|
|
376
|
+
{role: 'assistant', content: 'Short response'},
|
|
377
|
+
];
|
|
378
|
+
const metadata = createMockMetadata();
|
|
379
|
+
|
|
380
|
+
const result = await usageCommand.handler([], messages, metadata);
|
|
381
|
+
|
|
382
|
+
t.truthy(result);
|
|
383
|
+
t.true(React.isValidElement(result));
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
test('usage command handles messages with special characters', async t => {
|
|
387
|
+
const messages: Message[] = [
|
|
388
|
+
{role: 'user', content: 'Hello 你好 مرحبا'},
|
|
389
|
+
{role: 'assistant', content: 'Response with émojis 🚀 and symbols ®™©'},
|
|
390
|
+
];
|
|
391
|
+
const metadata = createMockMetadata();
|
|
392
|
+
|
|
393
|
+
const result = await usageCommand.handler([], messages, metadata);
|
|
394
|
+
|
|
395
|
+
t.truthy(result);
|
|
396
|
+
t.true(React.isValidElement(result));
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
test('usage command handles empty message content', async t => {
|
|
400
|
+
const messages: Message[] = [
|
|
401
|
+
{role: 'user', content: ''},
|
|
402
|
+
{role: 'assistant', content: ''},
|
|
403
|
+
];
|
|
404
|
+
const metadata = createMockMetadata();
|
|
405
|
+
|
|
406
|
+
const result = await usageCommand.handler([], messages, metadata);
|
|
407
|
+
|
|
408
|
+
t.truthy(result);
|
|
409
|
+
t.true(React.isValidElement(result));
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
test('usage command handles single message', async t => {
|
|
413
|
+
const messages: Message[] = [{role: 'user', content: 'Only message'}];
|
|
414
|
+
const metadata = createMockMetadata();
|
|
415
|
+
|
|
416
|
+
const result = await usageCommand.handler([], messages, metadata);
|
|
417
|
+
|
|
418
|
+
t.truthy(result);
|
|
419
|
+
t.true(React.isValidElement(result));
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
test('usage command handles many messages', async t => {
|
|
423
|
+
// Create 100 messages
|
|
424
|
+
const messages: Message[] = [];
|
|
425
|
+
for (let i = 0; i < 100; i++) {
|
|
426
|
+
messages.push({
|
|
427
|
+
role: i % 2 === 0 ? 'user' : 'assistant',
|
|
428
|
+
content: `Message ${i}`,
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
const metadata = createMockMetadata();
|
|
432
|
+
|
|
433
|
+
const result = await usageCommand.handler([], messages, metadata);
|
|
434
|
+
|
|
435
|
+
t.truthy(result);
|
|
436
|
+
t.true(React.isValidElement(result));
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
// ============================================================================
|
|
440
|
+
// Custom Token Counter Tests
|
|
441
|
+
// ============================================================================
|
|
442
|
+
|
|
443
|
+
test('usage command uses custom getMessageTokens function', async t => {
|
|
444
|
+
const messages = createMessages();
|
|
445
|
+
let callCount = 0;
|
|
446
|
+
|
|
447
|
+
const metadata = {
|
|
448
|
+
provider: 'test-provider',
|
|
449
|
+
model: 'test-model',
|
|
450
|
+
tokens: 100,
|
|
451
|
+
getMessageTokens: (_message: Message) => {
|
|
452
|
+
callCount++;
|
|
453
|
+
return 10; // Fixed token count for testing
|
|
454
|
+
},
|
|
455
|
+
};
|
|
456
|
+
|
|
457
|
+
const result = await usageCommand.handler([], messages, metadata);
|
|
458
|
+
|
|
459
|
+
t.truthy(result);
|
|
460
|
+
t.true(React.isValidElement(result));
|
|
461
|
+
// Should have been called for each non-system message
|
|
462
|
+
t.true(callCount > 0);
|
|
463
|
+
});
|
|
464
|
+
|
|
465
|
+
test('usage command with custom token counter returning zero', async t => {
|
|
466
|
+
const messages = createMessages();
|
|
467
|
+
|
|
468
|
+
const metadata = {
|
|
469
|
+
provider: 'test-provider',
|
|
470
|
+
model: 'test-model',
|
|
471
|
+
tokens: 0,
|
|
472
|
+
getMessageTokens: () => 0,
|
|
473
|
+
};
|
|
474
|
+
|
|
475
|
+
const result = await usageCommand.handler([], messages, metadata);
|
|
476
|
+
|
|
477
|
+
t.truthy(result);
|
|
478
|
+
t.true(React.isValidElement(result));
|
|
479
|
+
});
|
|
480
|
+
|
|
481
|
+
test('usage command with custom token counter returning large values', async t => {
|
|
482
|
+
const messages = createMessages();
|
|
483
|
+
|
|
484
|
+
const metadata = {
|
|
485
|
+
provider: 'test-provider',
|
|
486
|
+
model: 'test-model',
|
|
487
|
+
tokens: 1000000,
|
|
488
|
+
getMessageTokens: () => 100000,
|
|
489
|
+
};
|
|
490
|
+
|
|
491
|
+
const result = await usageCommand.handler([], messages, metadata);
|
|
492
|
+
|
|
493
|
+
t.truthy(result);
|
|
494
|
+
t.true(React.isValidElement(result));
|
|
495
|
+
});
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* /usage command
|
|
3
|
+
* Displays token usage statistics
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import {UsageDisplay} from '@/components/usage/usage-display';
|
|
7
|
+
import {getToolManager} from '@/message-handler';
|
|
8
|
+
import {getModelContextLimit} from '@/models/index';
|
|
9
|
+
import {createTokenizer} from '@/tokenization/index';
|
|
10
|
+
import type {Command} from '@/types/commands';
|
|
11
|
+
import type {Message} from '@/types/core';
|
|
12
|
+
import {
|
|
13
|
+
calculateTokenBreakdown,
|
|
14
|
+
calculateToolDefinitionsTokens,
|
|
15
|
+
} from '@/usage/calculator';
|
|
16
|
+
import {processPromptTemplate} from '@/utils/prompt-processor';
|
|
17
|
+
import React from 'react';
|
|
18
|
+
|
|
19
|
+
export const usageCommand: Command = {
|
|
20
|
+
name: 'usage',
|
|
21
|
+
description: 'Display token usage statistics',
|
|
22
|
+
handler: async (
|
|
23
|
+
_args: string[],
|
|
24
|
+
messages: Message[],
|
|
25
|
+
metadata: {
|
|
26
|
+
provider: string;
|
|
27
|
+
model: string;
|
|
28
|
+
tokens: number;
|
|
29
|
+
getMessageTokens: (message: Message) => number;
|
|
30
|
+
},
|
|
31
|
+
) => {
|
|
32
|
+
const {provider, model, getMessageTokens} = metadata;
|
|
33
|
+
|
|
34
|
+
// Create tokenizer for accurate breakdown
|
|
35
|
+
const tokenizer = createTokenizer(provider, model);
|
|
36
|
+
|
|
37
|
+
// Generate the system prompt to include in token calculation
|
|
38
|
+
const toolManager = getToolManager();
|
|
39
|
+
const systemPrompt = processPromptTemplate();
|
|
40
|
+
|
|
41
|
+
// Create system message to include in token calculation
|
|
42
|
+
const systemMessage: Message = {
|
|
43
|
+
role: 'system',
|
|
44
|
+
content: systemPrompt,
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
// Calculate token breakdown from messages including system prompt
|
|
48
|
+
// Note: We don't use getMessageTokens for the system message since it's freshly generated
|
|
49
|
+
// and won't be in the cache. Instead, we use the tokenizer directly for accurate counting.
|
|
50
|
+
const baseBreakdown = calculateTokenBreakdown(
|
|
51
|
+
[systemMessage, ...messages],
|
|
52
|
+
tokenizer,
|
|
53
|
+
message => {
|
|
54
|
+
// For system message, always use tokenizer directly to avoid cache misses
|
|
55
|
+
if (message.role === 'system') {
|
|
56
|
+
return tokenizer.countTokens(message);
|
|
57
|
+
}
|
|
58
|
+
// For other messages, use cached token counts
|
|
59
|
+
return getMessageTokens(message);
|
|
60
|
+
},
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
// Extract tokenizer name before cleanup
|
|
64
|
+
const tokenizerName = tokenizer.getName();
|
|
65
|
+
|
|
66
|
+
// Clean up tokenizer resources
|
|
67
|
+
if (tokenizer.free) {
|
|
68
|
+
tokenizer.free();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Calculate tool definitions tokens and create final breakdown (immutable)
|
|
72
|
+
// Note: Tool definitions are sent separately to the API and add token overhead
|
|
73
|
+
const toolDefinitions = toolManager
|
|
74
|
+
? calculateToolDefinitionsTokens(
|
|
75
|
+
Object.keys(toolManager.getToolRegistry()).length,
|
|
76
|
+
)
|
|
77
|
+
: 0;
|
|
78
|
+
|
|
79
|
+
const breakdown = {
|
|
80
|
+
...baseBreakdown,
|
|
81
|
+
toolDefinitions,
|
|
82
|
+
total: baseBreakdown.total + toolDefinitions,
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// Get context limit from models.dev
|
|
86
|
+
const contextLimit = await getModelContextLimit(model);
|
|
87
|
+
|
|
88
|
+
return React.createElement(UsageDisplay, {
|
|
89
|
+
key: `usage-${Date.now()}`,
|
|
90
|
+
provider,
|
|
91
|
+
model,
|
|
92
|
+
contextLimit,
|
|
93
|
+
currentTokens: breakdown.total,
|
|
94
|
+
breakdown,
|
|
95
|
+
messages,
|
|
96
|
+
tokenizerName,
|
|
97
|
+
getMessageTokens,
|
|
98
|
+
});
|
|
99
|
+
},
|
|
100
|
+
};
|