@tenex-chat/backend 0.9.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/README.md +194 -0
- package/dist/backend-wrapper.cjs +3 -0
- package/dist/src/index.js +331928 -0
- package/package.json +103 -0
- package/src/agents/AgentRegistry.ts +418 -0
- package/src/agents/AgentStorage.ts +1133 -0
- package/src/agents/ConfigResolver.ts +229 -0
- package/src/agents/agent-installer.ts +236 -0
- package/src/agents/agent-loader.ts +241 -0
- package/src/agents/constants.ts +82 -0
- package/src/agents/errors.ts +48 -0
- package/src/agents/execution/AgentExecutor.ts +561 -0
- package/src/agents/execution/ExecutionContextFactory.ts +112 -0
- package/src/agents/execution/MessageCompiler.ts +597 -0
- package/src/agents/execution/MessageSyncer.ts +100 -0
- package/src/agents/execution/PostCompletionChecker.ts +278 -0
- package/src/agents/execution/ProgressMonitor.ts +50 -0
- package/src/agents/execution/RALResolver.ts +177 -0
- package/src/agents/execution/SessionManager.ts +181 -0
- package/src/agents/execution/StreamCallbacks.ts +312 -0
- package/src/agents/execution/StreamExecutionHandler.ts +579 -0
- package/src/agents/execution/StreamSetup.ts +313 -0
- package/src/agents/execution/ToolEventHandlers.ts +239 -0
- package/src/agents/execution/ToolExecutionTracker.ts +498 -0
- package/src/agents/execution/ToolResultUtils.ts +97 -0
- package/src/agents/execution/ToolSupervisionWrapper.ts +174 -0
- package/src/agents/execution/constants.ts +16 -0
- package/src/agents/execution/index.ts +3 -0
- package/src/agents/execution/types.ts +96 -0
- package/src/agents/execution/utils.ts +26 -0
- package/src/agents/index.ts +4 -0
- package/src/agents/script-installer.ts +266 -0
- package/src/agents/supervision/SupervisorLLMService.ts +253 -0
- package/src/agents/supervision/SupervisorOrchestrator.ts +471 -0
- package/src/agents/supervision/heuristics/ConsecutiveToolsWithoutTodoHeuristic.ts +73 -0
- package/src/agents/supervision/heuristics/DelegationClaimHeuristic.ts +80 -0
- package/src/agents/supervision/heuristics/HeuristicRegistry.ts +114 -0
- package/src/agents/supervision/heuristics/PendingTodosHeuristic.ts +93 -0
- package/src/agents/supervision/heuristics/SilentAgentHeuristic.ts +54 -0
- package/src/agents/supervision/heuristics/index.ts +5 -0
- package/src/agents/supervision/index.ts +28 -0
- package/src/agents/supervision/registerHeuristics.ts +110 -0
- package/src/agents/supervision/supervisionHealthCheck.ts +123 -0
- package/src/agents/supervision/types.ts +171 -0
- package/src/agents/tool-names.ts +46 -0
- package/src/agents/tool-normalization.ts +184 -0
- package/src/agents/types/index.ts +2 -0
- package/src/agents/types/runtime.ts +74 -0
- package/src/agents/types/storage.ts +145 -0
- package/src/commands/agent/import/index.ts +6 -0
- package/src/commands/agent/import/openclaw-distiller.ts +57 -0
- package/src/commands/agent/import/openclaw-reader.ts +141 -0
- package/src/commands/agent/import/openclaw.ts +154 -0
- package/src/commands/agent/index.ts +6 -0
- package/src/commands/agent.ts +215 -0
- package/src/commands/daemon.ts +198 -0
- package/src/commands/doctor.ts +134 -0
- package/src/commands/setup/embed.ts +228 -0
- package/src/commands/setup/global-system-prompt.ts +223 -0
- package/src/commands/setup/image.ts +179 -0
- package/src/commands/setup/index.ts +16 -0
- package/src/commands/setup/interactive.ts +95 -0
- package/src/commands/setup/llm.ts +38 -0
- package/src/commands/setup/onboarding.ts +294 -0
- package/src/commands/setup/providers.ts +27 -0
- package/src/constants.ts +34 -0
- package/src/conversations/ConversationDiskReader.ts +148 -0
- package/src/conversations/ConversationRegistry.ts +728 -0
- package/src/conversations/ConversationStore.ts +868 -0
- package/src/conversations/MessageBuilder.ts +866 -0
- package/src/conversations/executionTime.ts +62 -0
- package/src/conversations/formatters/DelegationXmlFormatter.ts +64 -0
- package/src/conversations/formatters/ThreadedConversationFormatter.ts +303 -0
- package/src/conversations/formatters/index.ts +9 -0
- package/src/conversations/formatters/utils/MessageFormatter.ts +46 -0
- package/src/conversations/formatters/utils/TimestampFormatter.ts +56 -0
- package/src/conversations/formatters/utils/TreeBuilder.ts +131 -0
- package/src/conversations/formatters/utils/TreeRenderer.ts +49 -0
- package/src/conversations/index.ts +2 -0
- package/src/conversations/persistence/ToolMessageStorage.ts +143 -0
- package/src/conversations/search/ConversationIndexManager.ts +393 -0
- package/src/conversations/search/QueryParser.ts +114 -0
- package/src/conversations/search/SearchEngine.ts +175 -0
- package/src/conversations/search/SnippetExtractor.ts +345 -0
- package/src/conversations/search/embeddings/ConversationEmbeddingService.ts +484 -0
- package/src/conversations/search/embeddings/ConversationIndexingJob.ts +320 -0
- package/src/conversations/search/embeddings/IndexingStateManager.ts +338 -0
- package/src/conversations/search/embeddings/index.ts +18 -0
- package/src/conversations/search/index.ts +49 -0
- package/src/conversations/search/types.ts +124 -0
- package/src/conversations/services/CategoryManager.ts +160 -0
- package/src/conversations/services/ConversationResolver.ts +296 -0
- package/src/conversations/services/ConversationSummarizer.ts +234 -0
- package/src/conversations/services/MetadataDebounceManager.ts +188 -0
- package/src/conversations/services/index.ts +2 -0
- package/src/conversations/types.ts +148 -0
- package/src/conversations/utils/content-utils.ts +69 -0
- package/src/conversations/utils/image-placeholder.ts +281 -0
- package/src/conversations/utils/image-url-utils.ts +171 -0
- package/src/conversations/utils/multimodal-content.ts +90 -0
- package/src/conversations/utils/tool-result-truncator.ts +159 -0
- package/src/daemon/Daemon.ts +1883 -0
- package/src/daemon/ProjectRuntime.ts +657 -0
- package/src/daemon/RestartState.ts +152 -0
- package/src/daemon/RuntimeLifecycle.ts +268 -0
- package/src/daemon/SubscriptionManager.ts +305 -0
- package/src/daemon/UnixSocketTransport.ts +318 -0
- package/src/daemon/filters/SubscriptionFilterBuilder.ts +119 -0
- package/src/daemon/index.ts +9 -0
- package/src/daemon/routing/DaemonRouter.ts +491 -0
- package/src/daemon/types.ts +150 -0
- package/src/daemon/utils/routing-log.ts +76 -0
- package/src/daemon/utils/telemetry.ts +173 -0
- package/src/event-handler/agentDeletion.ts +383 -0
- package/src/event-handler/index.ts +749 -0
- package/src/event-handler/newConversation.ts +165 -0
- package/src/event-handler/project.ts +166 -0
- package/src/event-handler/reply.ts +18 -0
- package/src/events/NDKAgentDefinition.ts +292 -0
- package/src/events/NDKAgentLesson.ts +106 -0
- package/src/events/NDKEventMetadata.ts +34 -0
- package/src/events/NDKMCPTool.ts +60 -0
- package/src/events/NDKProjectStatus.ts +384 -0
- package/src/events/index.ts +4 -0
- package/src/index.ts +126 -0
- package/src/lib/agent-home.ts +334 -0
- package/src/lib/error-formatter.ts +200 -0
- package/src/lib/fs/filesystem.ts +128 -0
- package/src/lib/fs/index.ts +1 -0
- package/src/lib/json-parser.ts +30 -0
- package/src/lib/string.ts +15 -0
- package/src/lib/time.ts +74 -0
- package/src/llm/ChunkHandler.ts +277 -0
- package/src/llm/FinishHandler.ts +250 -0
- package/src/llm/LLMConfigEditor.ts +154 -0
- package/src/llm/LLMServiceFactory.ts +230 -0
- package/src/llm/MessageProcessor.ts +90 -0
- package/src/llm/RecordingState.ts +37 -0
- package/src/llm/StreamPublisher.ts +40 -0
- package/src/llm/TracingUtils.ts +77 -0
- package/src/llm/chunk-validators.ts +57 -0
- package/src/llm/constants.ts +6 -0
- package/src/llm/index.ts +12 -0
- package/src/llm/meta/MetaModelResolver.ts +352 -0
- package/src/llm/meta/index.ts +11 -0
- package/src/llm/middleware/flight-recorder.ts +188 -0
- package/src/llm/providers/MockProvider.ts +332 -0
- package/src/llm/providers/agent/ClaudeCodeProvider.ts +343 -0
- package/src/llm/providers/agent/ClaudeCodeToolsAdapter.ts +203 -0
- package/src/llm/providers/agent/CodexAppServerProvider.ts +214 -0
- package/src/llm/providers/agent/CodexAppServerToolsAdapter.ts +91 -0
- package/src/llm/providers/agent/index.ts +10 -0
- package/src/llm/providers/base/AgentProvider.ts +107 -0
- package/src/llm/providers/base/BaseProvider.ts +114 -0
- package/src/llm/providers/base/StandardProvider.ts +38 -0
- package/src/llm/providers/base/index.ts +9 -0
- package/src/llm/providers/index.ts +106 -0
- package/src/llm/providers/key-manager.ts +238 -0
- package/src/llm/providers/ollama-models.ts +105 -0
- package/src/llm/providers/openrouter-models.ts +102 -0
- package/src/llm/providers/provider-ids.ts +18 -0
- package/src/llm/providers/registry/ProviderRegistry.ts +414 -0
- package/src/llm/providers/registry/index.ts +7 -0
- package/src/llm/providers/standard/AnthropicProvider.ts +71 -0
- package/src/llm/providers/standard/OllamaProvider.ts +59 -0
- package/src/llm/providers/standard/OpenAIProvider.ts +44 -0
- package/src/llm/providers/standard/OpenRouterProvider.ts +103 -0
- package/src/llm/providers/standard/index.ts +10 -0
- package/src/llm/providers/types.ts +194 -0
- package/src/llm/providers/usage-metadata.ts +78 -0
- package/src/llm/service.ts +713 -0
- package/src/llm/types.ts +167 -0
- package/src/llm/utils/ConfigurationManager.ts +650 -0
- package/src/llm/utils/ConfigurationTester.ts +229 -0
- package/src/llm/utils/ModelSelector.ts +212 -0
- package/src/llm/utils/ProviderConfigUI.ts +177 -0
- package/src/llm/utils/claudeCodePromptCompiler.ts +141 -0
- package/src/llm/utils/codex-models.ts +53 -0
- package/src/llm/utils/context-window-cache.ts +30 -0
- package/src/llm/utils/models-dev-cache.ts +267 -0
- package/src/llm/utils/provider-setup.ts +50 -0
- package/src/llm/utils/tool-errors.ts +78 -0
- package/src/llm/utils/usage.ts +74 -0
- package/src/logging/EventRoutingLogger.ts +205 -0
- package/src/nostr/AgentEventDecoder.ts +357 -0
- package/src/nostr/AgentEventEncoder.ts +677 -0
- package/src/nostr/AgentProfilePublisher.ts +657 -0
- package/src/nostr/AgentPublisher.ts +437 -0
- package/src/nostr/BlossomService.ts +226 -0
- package/src/nostr/InterventionPublisher.ts +132 -0
- package/src/nostr/TagExtractor.ts +228 -0
- package/src/nostr/collectEvents.ts +83 -0
- package/src/nostr/constants.ts +38 -0
- package/src/nostr/encryption.ts +26 -0
- package/src/nostr/index.ts +31 -0
- package/src/nostr/keys.ts +17 -0
- package/src/nostr/kinds.ts +37 -0
- package/src/nostr/ndkClient.ts +72 -0
- package/src/nostr/relays.ts +43 -0
- package/src/nostr/trace-context.ts +39 -0
- package/src/nostr/types.ts +227 -0
- package/src/nostr/utils.ts +84 -0
- package/src/prompts/core/FragmentRegistry.ts +30 -0
- package/src/prompts/core/PromptBuilder.ts +98 -0
- package/src/prompts/core/index.ts +3 -0
- package/src/prompts/core/types.ts +13 -0
- package/src/prompts/fragments/00-global-system-prompt.ts +44 -0
- package/src/prompts/fragments/01-agent-identity.ts +69 -0
- package/src/prompts/fragments/02-agent-home-directory.ts +114 -0
- package/src/prompts/fragments/03-system-reminders-explanation.ts +14 -0
- package/src/prompts/fragments/04-relay-configuration.ts +38 -0
- package/src/prompts/fragments/05-delegation-chain.ts +45 -0
- package/src/prompts/fragments/06-agent-todos.ts +74 -0
- package/src/prompts/fragments/06-todo-usage-guidance.ts +34 -0
- package/src/prompts/fragments/07-meta-project-context.ts +234 -0
- package/src/prompts/fragments/08-active-conversations.ts +382 -0
- package/src/prompts/fragments/09-recent-conversations.ts +153 -0
- package/src/prompts/fragments/10-referenced-article.ts +21 -0
- package/src/prompts/fragments/11-nudges.ts +134 -0
- package/src/prompts/fragments/12-skills.ts +127 -0
- package/src/prompts/fragments/13-available-nudges.ts +122 -0
- package/src/prompts/fragments/15-available-agents.ts +53 -0
- package/src/prompts/fragments/16-stay-in-your-lane.ts +41 -0
- package/src/prompts/fragments/17-todo-before-delegation.ts +39 -0
- package/src/prompts/fragments/20-voice-mode.ts +62 -0
- package/src/prompts/fragments/22-scheduled-tasks.ts +175 -0
- package/src/prompts/fragments/24-retrieved-lessons.ts +26 -0
- package/src/prompts/fragments/25-rag-instructions.ts +333 -0
- package/src/prompts/fragments/26-mcp-resources.ts +237 -0
- package/src/prompts/fragments/27-memorized-reports.ts +77 -0
- package/src/prompts/fragments/28-agent-directed-monitoring.ts +32 -0
- package/src/prompts/fragments/29-rag-collections.ts +50 -0
- package/src/prompts/fragments/30-worktree-context.ts +98 -0
- package/src/prompts/fragments/31-agents-md-guidance.ts +96 -0
- package/src/prompts/fragments/32-process-metrics.ts +72 -0
- package/src/prompts/fragments/debug-mode.ts +48 -0
- package/src/prompts/fragments/delegation-completion.ts +44 -0
- package/src/prompts/fragments/index.ts +91 -0
- package/src/prompts/index.ts +21 -0
- package/src/prompts/utils/systemPromptBuilder.ts +777 -0
- package/src/scripts/migrate-prefix-index.ts +157 -0
- package/src/services/AgentDefinitionMonitor.ts +701 -0
- package/src/services/ConfigService.ts +723 -0
- package/src/services/CooldownRegistry.ts +199 -0
- package/src/services/LLMOperationsRegistry.ts +424 -0
- package/src/services/OwnerAgentListService.ts +354 -0
- package/src/services/PubkeyService.ts +308 -0
- package/src/services/agents/AgentMetadataStore.ts +72 -0
- package/src/services/agents/AgentResolution.ts +59 -0
- package/src/services/agents/EscalationService.ts +281 -0
- package/src/services/agents/NDKAgentDiscovery.ts +95 -0
- package/src/services/agents/index.ts +7 -0
- package/src/services/agents-md/AgentsMdService.ts +184 -0
- package/src/services/agents-md/SystemReminderInjector.ts +238 -0
- package/src/services/agents-md/index.ts +11 -0
- package/src/services/apns/APNsClient.ts +203 -0
- package/src/services/apns/APNsService.ts +358 -0
- package/src/services/apns/index.ts +11 -0
- package/src/services/apns/types.ts +80 -0
- package/src/services/compression/CompressionService.ts +445 -0
- package/src/services/compression/compression-schema.ts +28 -0
- package/src/services/compression/compression-types.ts +74 -0
- package/src/services/compression/compression-utils.ts +587 -0
- package/src/services/config/types.ts +394 -0
- package/src/services/dispatch/AgentDispatchService.ts +937 -0
- package/src/services/dispatch/AgentRouter.ts +181 -0
- package/src/services/dispatch/DelegationCompletionHandler.ts +232 -0
- package/src/services/embedding/EmbeddingProvider.ts +188 -0
- package/src/services/embedding/index.ts +5 -0
- package/src/services/event-context/EventContextService.ts +108 -0
- package/src/services/event-context/index.ts +2 -0
- package/src/services/heuristics/ContextBuilder.ts +106 -0
- package/src/services/heuristics/HeuristicEngine.ts +200 -0
- package/src/services/heuristics/formatters.ts +58 -0
- package/src/services/heuristics/index.ts +12 -0
- package/src/services/heuristics/rules/index.ts +25 -0
- package/src/services/heuristics/rules/todoBeforeDelegation.ts +69 -0
- package/src/services/heuristics/rules/todoReminderOnToolUse.ts +63 -0
- package/src/services/heuristics/types.ts +144 -0
- package/src/services/image/ImageGenerationService.ts +389 -0
- package/src/services/image/index.ts +12 -0
- package/src/services/intervention/InterventionService.ts +1352 -0
- package/src/services/intervention/index.ts +7 -0
- package/src/services/mcp/MCPManager.ts +683 -0
- package/src/services/mcp/McpNotificationDelivery.ts +139 -0
- package/src/services/mcp/McpSubscriptionService.ts +653 -0
- package/src/services/mcp/mcpInstaller.ts +130 -0
- package/src/services/nip46/Nip46SigningLog.ts +81 -0
- package/src/services/nip46/Nip46SigningService.ts +467 -0
- package/src/services/nip46/index.ts +4 -0
- package/src/services/nudge/NudgeService.ts +224 -0
- package/src/services/nudge/NudgeWhitelistService.ts +382 -0
- package/src/services/nudge/index.ts +5 -0
- package/src/services/nudge/types.ts +83 -0
- package/src/services/projects/ProjectContext.ts +672 -0
- package/src/services/projects/ProjectContextStore.ts +102 -0
- package/src/services/projects/index.ts +6 -0
- package/src/services/prompt-compiler/index.ts +15 -0
- package/src/services/prompt-compiler/prompt-compiler-service.ts +1143 -0
- package/src/services/pubkey-gate/PubkeyGateService.ts +93 -0
- package/src/services/pubkey-gate/index.ts +1 -0
- package/src/services/rag/EmbeddingProviderFactory.ts +292 -0
- package/src/services/rag/LanceDBMaintenanceService.ts +211 -0
- package/src/services/rag/RAGDatabaseService.ts +173 -0
- package/src/services/rag/RAGOperations.ts +682 -0
- package/src/services/rag/RAGService.ts +240 -0
- package/src/services/rag/RagSubscriptionService.ts +618 -0
- package/src/services/rag/rag-utils.ts +174 -0
- package/src/services/ral/PendingDelegationsRegistry.ts +168 -0
- package/src/services/ral/RALRegistry.ts +2782 -0
- package/src/services/ral/index.ts +4 -0
- package/src/services/ral/types.ts +292 -0
- package/src/services/reports/LocalReportStore.ts +380 -0
- package/src/services/reports/ReportEmbeddingService.ts +430 -0
- package/src/services/reports/ReportService.ts +440 -0
- package/src/services/reports/articleUtils.ts +52 -0
- package/src/services/reports/index.ts +7 -0
- package/src/services/scheduling/SchedulerService.ts +1057 -0
- package/src/services/scheduling/errors.ts +14 -0
- package/src/services/scheduling/index.ts +7 -0
- package/src/services/scheduling/utils.ts +77 -0
- package/src/services/search/SearchProviderRegistry.ts +78 -0
- package/src/services/search/UnifiedSearchService.ts +218 -0
- package/src/services/search/index.ts +47 -0
- package/src/services/search/projectFilter.ts +22 -0
- package/src/services/search/providers/ConversationSearchProvider.ts +48 -0
- package/src/services/search/providers/LessonSearchProvider.ts +75 -0
- package/src/services/search/providers/ReportSearchProvider.ts +49 -0
- package/src/services/search/types.ts +144 -0
- package/src/services/skill/SkillService.ts +482 -0
- package/src/services/skill/index.ts +2 -0
- package/src/services/skill/types.ts +70 -0
- package/src/services/status/OperationsStatusService.ts +276 -0
- package/src/services/status/ProjectStatusService.ts +522 -0
- package/src/services/status/index.ts +11 -0
- package/src/services/storage/PrefixKVStore.ts +242 -0
- package/src/services/storage/index.ts +1 -0
- package/src/services/system-reminder/SystemReminderUtils.ts +96 -0
- package/src/services/system-reminder/index.ts +7 -0
- package/src/services/trust-pubkeys/TrustPubkeyService.ts +325 -0
- package/src/services/trust-pubkeys/index.ts +2 -0
- package/src/telemetry/ConversationSpanManager.ts +111 -0
- package/src/telemetry/EventLoopMonitor.ts +206 -0
- package/src/telemetry/LLMSpanRegistry.ts +20 -0
- package/src/telemetry/NostrSpanProcessor.ts +89 -0
- package/src/telemetry/ToolCallSpanProcessor.ts +66 -0
- package/src/telemetry/diagnostics.ts +27 -0
- package/src/telemetry/setup.ts +120 -0
- package/src/tools/implementations/agents_discover.ts +121 -0
- package/src/tools/implementations/agents_hire.ts +127 -0
- package/src/tools/implementations/agents_list.ts +96 -0
- package/src/tools/implementations/agents_publish.ts +611 -0
- package/src/tools/implementations/agents_read.ts +173 -0
- package/src/tools/implementations/agents_write.ts +200 -0
- package/src/tools/implementations/ask.ts +411 -0
- package/src/tools/implementations/change_model.ts +141 -0
- package/src/tools/implementations/conversation_get.ts +661 -0
- package/src/tools/implementations/conversation_list.ts +377 -0
- package/src/tools/implementations/conversation_search.ts +370 -0
- package/src/tools/implementations/delegate.ts +327 -0
- package/src/tools/implementations/delegate_crossproject.ts +209 -0
- package/src/tools/implementations/delegate_followup.ts +300 -0
- package/src/tools/implementations/fs_edit.ts +162 -0
- package/src/tools/implementations/fs_glob.ts +182 -0
- package/src/tools/implementations/fs_grep.ts +513 -0
- package/src/tools/implementations/fs_read.ts +332 -0
- package/src/tools/implementations/fs_write.ts +113 -0
- package/src/tools/implementations/generate_image.ts +259 -0
- package/src/tools/implementations/home_fs.ts +515 -0
- package/src/tools/implementations/kill.ts +651 -0
- package/src/tools/implementations/learn.ts +166 -0
- package/src/tools/implementations/lesson-formatter.ts +38 -0
- package/src/tools/implementations/lesson_delete.ts +164 -0
- package/src/tools/implementations/lesson_get.ts +105 -0
- package/src/tools/implementations/lessons_list.ts +153 -0
- package/src/tools/implementations/mcp_resource_read.ts +161 -0
- package/src/tools/implementations/mcp_subscribe.ts +158 -0
- package/src/tools/implementations/mcp_subscription_stop.ts +85 -0
- package/src/tools/implementations/nostr_fetch.ts +149 -0
- package/src/tools/implementations/nostr_publish_as_user.ts +353 -0
- package/src/tools/implementations/project_list.ts +146 -0
- package/src/tools/implementations/rag_add_documents.ts +573 -0
- package/src/tools/implementations/rag_create_collection.ts +65 -0
- package/src/tools/implementations/rag_delete_collection.ts +68 -0
- package/src/tools/implementations/rag_list_collections.ts +77 -0
- package/src/tools/implementations/rag_query.ts +107 -0
- package/src/tools/implementations/rag_subscription_create.ts +105 -0
- package/src/tools/implementations/rag_subscription_delete.ts +80 -0
- package/src/tools/implementations/rag_subscription_get.ts +123 -0
- package/src/tools/implementations/rag_subscription_list.ts +128 -0
- package/src/tools/implementations/report_delete.ts +79 -0
- package/src/tools/implementations/report_read.ts +160 -0
- package/src/tools/implementations/report_write.ts +278 -0
- package/src/tools/implementations/reports_list.ts +77 -0
- package/src/tools/implementations/schedule_task.ts +104 -0
- package/src/tools/implementations/schedule_task_cancel.ts +62 -0
- package/src/tools/implementations/schedule_task_once.ts +128 -0
- package/src/tools/implementations/schedule_tasks_list.ts +79 -0
- package/src/tools/implementations/search.ts +160 -0
- package/src/tools/implementations/shell.ts +553 -0
- package/src/tools/implementations/todo.ts +260 -0
- package/src/tools/implementations/upload_blob.ts +381 -0
- package/src/tools/implementations/web_fetch.ts +153 -0
- package/src/tools/implementations/web_search.ts +250 -0
- package/src/tools/registry.ts +670 -0
- package/src/tools/types.ts +177 -0
- package/src/tools/utils.ts +256 -0
- package/src/types/event-ids.ts +320 -0
- package/src/types/index.ts +46 -0
- package/src/utils/agentFetcher.ts +107 -0
- package/src/utils/cli-error.ts +29 -0
- package/src/utils/conversation-id.ts +27 -0
- package/src/utils/conversation-utils.ts +1 -0
- package/src/utils/delegation-chain.ts +357 -0
- package/src/utils/error-handler.ts +42 -0
- package/src/utils/git/gitignore.ts +69 -0
- package/src/utils/git/index.ts +2 -0
- package/src/utils/git/initializeGitRepo.ts +204 -0
- package/src/utils/git/worktree.ts +260 -0
- package/src/utils/lessonFormatter.ts +70 -0
- package/src/utils/lessonTrust.ts +24 -0
- package/src/utils/lockfile.ts +123 -0
- package/src/utils/logger.ts +149 -0
- package/src/utils/nostr-entity-parser.ts +365 -0
- package/src/utils/process.ts +49 -0
- package/src/wrapper.ts +262 -0
- package/tsconfig.json +41 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import type { ModelMessage, TextPart, ImagePart } from "ai";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Extract text content from a message content field.
|
|
5
|
+
* Handles both string content and multimodal content (TextPart + ImagePart arrays).
|
|
6
|
+
*
|
|
7
|
+
* For multimodal content, extracts the text part and notes any images.
|
|
8
|
+
*/
|
|
9
|
+
function extractTextContent(content: ModelMessage["content"]): string {
|
|
10
|
+
if (typeof content === "string") {
|
|
11
|
+
return content;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (!Array.isArray(content)) {
|
|
15
|
+
return JSON.stringify(content);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Handle multimodal content (arrays of parts)
|
|
19
|
+
const parts: string[] = [];
|
|
20
|
+
let imageCount = 0;
|
|
21
|
+
|
|
22
|
+
for (const part of content) {
|
|
23
|
+
if ((part as TextPart).type === "text") {
|
|
24
|
+
parts.push((part as TextPart).text);
|
|
25
|
+
} else if ((part as ImagePart).type === "image") {
|
|
26
|
+
imageCount++;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// If there were images, note them at the end
|
|
31
|
+
if (imageCount > 0) {
|
|
32
|
+
parts.push(`[${imageCount} image${imageCount > 1 ? "s" : ""} attached]`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return parts.join("\n");
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* System prompt type for Claude Code.
|
|
40
|
+
* Can be a string for custom system prompt, or use preset with append for
|
|
41
|
+
* Claude Code's built-in instructions plus custom content.
|
|
42
|
+
*/
|
|
43
|
+
export type ClaudeCodeSystemPrompt = string | {
|
|
44
|
+
type: "preset";
|
|
45
|
+
preset: "claude_code";
|
|
46
|
+
append?: string;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Compiles system messages for Claude Code's systemPrompt.append.
|
|
51
|
+
* Uses the new systemPrompt API (replacing deprecated customSystemPrompt/appendSystemPrompt).
|
|
52
|
+
*
|
|
53
|
+
* IMPORTANT: Only system messages are included in systemPrompt.append.
|
|
54
|
+
* User/assistant messages are passed separately via the messages array to streamText().
|
|
55
|
+
* This separation is critical for session resumption to work correctly - if conversation
|
|
56
|
+
* history is duplicated in both systemPrompt.append AND messages, it creates a session
|
|
57
|
+
* state that can't be reconstructed on resume.
|
|
58
|
+
*
|
|
59
|
+
* Note: Multimodal content (images) is converted to text descriptions since
|
|
60
|
+
* Claude Code uses a text-based prompt compilation approach.
|
|
61
|
+
*/
|
|
62
|
+
export function compileMessagesForClaudeCode(messages: ModelMessage[]): {
|
|
63
|
+
systemPrompt?: ClaudeCodeSystemPrompt;
|
|
64
|
+
} {
|
|
65
|
+
if (messages.length === 0) {
|
|
66
|
+
return { systemPrompt: undefined };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Extract only system messages - user/assistant go in messages array
|
|
70
|
+
const systemMessages = messages.filter((m) => m.role === "system");
|
|
71
|
+
|
|
72
|
+
if (systemMessages.length === 0) {
|
|
73
|
+
return { systemPrompt: undefined };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Combine all system messages into the append content
|
|
77
|
+
const appendParts: string[] = [];
|
|
78
|
+
|
|
79
|
+
for (const msg of systemMessages) {
|
|
80
|
+
const content =
|
|
81
|
+
typeof msg.content === "string"
|
|
82
|
+
? msg.content
|
|
83
|
+
: extractTextContent(msg.content);
|
|
84
|
+
appendParts.push(content);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const appendContent = appendParts.join("\n\n");
|
|
88
|
+
|
|
89
|
+
// Use Claude Code's built-in preset with our system content appended
|
|
90
|
+
return {
|
|
91
|
+
systemPrompt: {
|
|
92
|
+
type: "preset",
|
|
93
|
+
preset: "claude_code",
|
|
94
|
+
append: appendContent,
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Converts system messages to user messages for active Claude Code sessions.
|
|
101
|
+
* When resuming a session, Claude Code doesn't receive new system messages,
|
|
102
|
+
* so we convert them to user messages to ensure they're delivered.
|
|
103
|
+
*
|
|
104
|
+
* Note: Multimodal content is preserved for user messages (they support images),
|
|
105
|
+
* but system messages with multimodal content are converted to text descriptions.
|
|
106
|
+
*/
|
|
107
|
+
export function convertSystemMessagesForResume(messages: ModelMessage[]): ModelMessage[] {
|
|
108
|
+
// For resuming sessions, we need to convert system messages that appear
|
|
109
|
+
// after the conversation started into user messages
|
|
110
|
+
|
|
111
|
+
// Find the first non-system message (start of conversation)
|
|
112
|
+
const conversationStartIndex = messages.findIndex((m) => m.role !== "system");
|
|
113
|
+
|
|
114
|
+
if (conversationStartIndex === -1) {
|
|
115
|
+
// All messages are system messages, no conversion needed
|
|
116
|
+
return messages;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Convert messages, preserving order
|
|
120
|
+
const convertedMessages = messages.map((msg, index) => {
|
|
121
|
+
// Keep initial system messages as-is (they were part of initial prompt)
|
|
122
|
+
if (index < conversationStartIndex) {
|
|
123
|
+
return msg;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Convert subsequent system messages to user messages with clear marker
|
|
127
|
+
if (msg.role === "system") {
|
|
128
|
+
// Use extractTextContent to handle multimodal content gracefully
|
|
129
|
+
const content = extractTextContent(msg.content);
|
|
130
|
+
return {
|
|
131
|
+
role: "user" as const,
|
|
132
|
+
content: `[System Context]: ${content}`,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Keep user and assistant messages as-is (preserving multimodal content)
|
|
137
|
+
return msg;
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
return convertedMessages as ModelMessage[];
|
|
141
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codex Model Discovery Utilities
|
|
3
|
+
*
|
|
4
|
+
* Provides functions to discover available Codex models and their capabilities,
|
|
5
|
+
* including supported reasoning effort levels.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { listModels } from "ai-sdk-provider-codex-app-server";
|
|
9
|
+
import type { ModelInfo } from "ai-sdk-provider-codex-app-server";
|
|
10
|
+
|
|
11
|
+
export interface CodexModelOption {
|
|
12
|
+
id: string;
|
|
13
|
+
displayName: string;
|
|
14
|
+
description: string;
|
|
15
|
+
supportedReasoningEfforts: string[];
|
|
16
|
+
defaultReasoningEffort: string;
|
|
17
|
+
isDefault: boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* List available Codex models with their reasoning effort options
|
|
22
|
+
*/
|
|
23
|
+
export async function listCodexModels(): Promise<CodexModelOption[]> {
|
|
24
|
+
const { models } = await listModels();
|
|
25
|
+
|
|
26
|
+
return models.map((model: ModelInfo) => ({
|
|
27
|
+
id: model.id,
|
|
28
|
+
displayName: model.displayName,
|
|
29
|
+
description: model.description,
|
|
30
|
+
supportedReasoningEfforts: model.supportedReasoningEfforts.map(
|
|
31
|
+
(e) => e.reasoningEffort
|
|
32
|
+
),
|
|
33
|
+
defaultReasoningEffort: model.defaultReasoningEffort,
|
|
34
|
+
isDefault: model.isDefault,
|
|
35
|
+
}));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Get the default Codex model
|
|
40
|
+
*/
|
|
41
|
+
export async function getDefaultCodexModel(): Promise<CodexModelOption | undefined> {
|
|
42
|
+
const models = await listCodexModels();
|
|
43
|
+
return models.find((m) => m.isDefault);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Format model info for display
|
|
48
|
+
*/
|
|
49
|
+
export function formatCodexModel(model: CodexModelOption): string {
|
|
50
|
+
const efforts = model.supportedReasoningEfforts.join(", ");
|
|
51
|
+
const defaultMark = model.isDefault ? " (default)" : "";
|
|
52
|
+
return `${model.id}${defaultMark}\n ${model.description}\n Reasoning: ${efforts} (default: ${model.defaultReasoningEffort})`;
|
|
53
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context window cache for LLM models
|
|
3
|
+
* Delegates to models-dev-cache for model metadata
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { getContextWindowFromModelsdev, clearModelsDevCache } from "./models-dev-cache";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Get context window for a model
|
|
10
|
+
* Returns undefined if not found
|
|
11
|
+
*/
|
|
12
|
+
export function getContextWindow(provider: string, model: string): number | undefined {
|
|
13
|
+
return getContextWindowFromModelsdev(provider, model);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Resolve context window for a model (async)
|
|
18
|
+
* No-op since models-dev-cache handles loading
|
|
19
|
+
*/
|
|
20
|
+
export async function resolveContextWindow(_provider: string, _model: string): Promise<void> {
|
|
21
|
+
// models-dev-cache loads data at startup via ensureCacheLoaded()
|
|
22
|
+
// Nothing to do here
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Clear the cache (for testing)
|
|
27
|
+
*/
|
|
28
|
+
export function clearCache(): void {
|
|
29
|
+
clearModelsDevCache();
|
|
30
|
+
}
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* models.dev cache for LLM model metadata
|
|
3
|
+
*
|
|
4
|
+
* Fetches model information from https://models.dev/api.json and caches to disk.
|
|
5
|
+
* Uses stale-while-revalidate: serves cached data immediately, refreshes in background if stale.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import * as path from "node:path";
|
|
9
|
+
import { ensureDirectory, fileExists, readJsonFile, writeJsonFile, getFileStats } from "@/lib/fs";
|
|
10
|
+
import { config } from "@/services/ConfigService";
|
|
11
|
+
import { logger } from "@/utils/logger";
|
|
12
|
+
|
|
13
|
+
const MODELS_DEV_API_URL = "https://models.dev/api.json";
|
|
14
|
+
const CACHE_FILE_NAME = "models-dev.json";
|
|
15
|
+
const STALE_THRESHOLD_MS = 24 * 60 * 60 * 1000; // 24 hours
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Model limits from models.dev
|
|
19
|
+
*/
|
|
20
|
+
export interface ModelLimits {
|
|
21
|
+
/** Context window size in tokens */
|
|
22
|
+
context: number;
|
|
23
|
+
/** Max output tokens */
|
|
24
|
+
output: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* models.dev API response structure
|
|
29
|
+
*/
|
|
30
|
+
interface ModelsDevResponse {
|
|
31
|
+
[provider: string]: {
|
|
32
|
+
models: {
|
|
33
|
+
[modelId: string]: {
|
|
34
|
+
limit?: {
|
|
35
|
+
context?: number;
|
|
36
|
+
output?: number;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Cached data structure
|
|
45
|
+
*/
|
|
46
|
+
interface CacheData {
|
|
47
|
+
fetchedAt: number;
|
|
48
|
+
data: ModelsDevResponse;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// In-memory cache (loaded from disk)
|
|
52
|
+
let cache: ModelsDevResponse | null = null;
|
|
53
|
+
let cacheLoadPromise: Promise<void> | null = null;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Provider ID mapping from our providers to models.dev providers
|
|
57
|
+
*/
|
|
58
|
+
const PROVIDER_MAPPING: Record<string, string | null> = {
|
|
59
|
+
anthropic: "anthropic",
|
|
60
|
+
openai: "openai",
|
|
61
|
+
openrouter: "openrouter",
|
|
62
|
+
// These providers are not in models.dev (local/custom)
|
|
63
|
+
ollama: null,
|
|
64
|
+
"claude-code": null,
|
|
65
|
+
"codex-app-server": null,
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Get the cache file path
|
|
70
|
+
*/
|
|
71
|
+
function getCacheFilePath(): string {
|
|
72
|
+
return path.join(config.getConfigPath("cache"), CACHE_FILE_NAME);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Fetch data from models.dev API
|
|
77
|
+
*/
|
|
78
|
+
async function fetchFromApi(): Promise<ModelsDevResponse | null> {
|
|
79
|
+
try {
|
|
80
|
+
const response = await fetch(MODELS_DEV_API_URL);
|
|
81
|
+
if (!response.ok) {
|
|
82
|
+
logger.warn("Failed to fetch models.dev API", {
|
|
83
|
+
status: response.status,
|
|
84
|
+
statusText: response.statusText,
|
|
85
|
+
});
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
return (await response.json()) as ModelsDevResponse;
|
|
89
|
+
} catch (error) {
|
|
90
|
+
logger.warn("Error fetching models.dev API", { error });
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Load cache from disk
|
|
97
|
+
*/
|
|
98
|
+
async function loadFromDisk(): Promise<CacheData | null> {
|
|
99
|
+
const cacheFile = getCacheFilePath();
|
|
100
|
+
if (!(await fileExists(cacheFile))) {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
return readJsonFile<CacheData>(cacheFile);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Save cache to disk
|
|
108
|
+
*/
|
|
109
|
+
async function saveToDisk(data: ModelsDevResponse): Promise<void> {
|
|
110
|
+
const cacheFile = getCacheFilePath();
|
|
111
|
+
await ensureDirectory(path.dirname(cacheFile));
|
|
112
|
+
const cacheData: CacheData = {
|
|
113
|
+
fetchedAt: Date.now(),
|
|
114
|
+
data,
|
|
115
|
+
};
|
|
116
|
+
await writeJsonFile(cacheFile, cacheData);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Check if cache is stale (older than 24 hours)
|
|
121
|
+
*/
|
|
122
|
+
async function isCacheStale(): Promise<boolean> {
|
|
123
|
+
const cacheFile = getCacheFilePath();
|
|
124
|
+
const stats = await getFileStats(cacheFile);
|
|
125
|
+
if (!stats) return true;
|
|
126
|
+
|
|
127
|
+
const age = Date.now() - stats.mtimeMs;
|
|
128
|
+
return age > STALE_THRESHOLD_MS;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Refresh cache from API (runs in background)
|
|
133
|
+
*/
|
|
134
|
+
async function refreshInBackground(): Promise<void> {
|
|
135
|
+
const freshData = await fetchFromApi();
|
|
136
|
+
if (freshData) {
|
|
137
|
+
cache = freshData;
|
|
138
|
+
await saveToDisk(freshData);
|
|
139
|
+
logger.debug("models.dev cache refreshed");
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Ensure cache is loaded (call at startup)
|
|
145
|
+
* Blocks until cache is ready. Fetches from API if no cached data exists.
|
|
146
|
+
*/
|
|
147
|
+
export async function ensureCacheLoaded(): Promise<void> {
|
|
148
|
+
// If already loading, wait for that
|
|
149
|
+
if (cacheLoadPromise) {
|
|
150
|
+
await cacheLoadPromise;
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// If already loaded, check for background refresh
|
|
155
|
+
if (cache) {
|
|
156
|
+
if (await isCacheStale()) {
|
|
157
|
+
// Trigger background refresh, don't wait
|
|
158
|
+
refreshInBackground().catch((err) =>
|
|
159
|
+
logger.warn("Background cache refresh failed", { error: err })
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Start loading
|
|
166
|
+
cacheLoadPromise = (async () => {
|
|
167
|
+
// Try to load from disk first
|
|
168
|
+
const diskCache = await loadFromDisk();
|
|
169
|
+
if (diskCache?.data) {
|
|
170
|
+
cache = diskCache.data;
|
|
171
|
+
logger.debug("models.dev cache loaded from disk");
|
|
172
|
+
|
|
173
|
+
// Check if stale and trigger background refresh
|
|
174
|
+
if (await isCacheStale()) {
|
|
175
|
+
refreshInBackground().catch((err) =>
|
|
176
|
+
logger.warn("Background cache refresh failed", { error: err })
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// No cache on disk, fetch from API
|
|
183
|
+
logger.debug("models.dev cache not found, fetching from API");
|
|
184
|
+
const freshData = await fetchFromApi();
|
|
185
|
+
if (freshData) {
|
|
186
|
+
cache = freshData;
|
|
187
|
+
await saveToDisk(freshData);
|
|
188
|
+
logger.debug("models.dev cache fetched and saved");
|
|
189
|
+
} else {
|
|
190
|
+
logger.warn("Could not load models.dev data - model limits will be unavailable");
|
|
191
|
+
}
|
|
192
|
+
})();
|
|
193
|
+
|
|
194
|
+
try {
|
|
195
|
+
await cacheLoadPromise;
|
|
196
|
+
} finally {
|
|
197
|
+
cacheLoadPromise = null;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Force refresh cache from API
|
|
203
|
+
*/
|
|
204
|
+
export async function refreshCache(): Promise<void> {
|
|
205
|
+
const freshData = await fetchFromApi();
|
|
206
|
+
if (freshData) {
|
|
207
|
+
cache = freshData;
|
|
208
|
+
await saveToDisk(freshData);
|
|
209
|
+
logger.info("models.dev cache force refreshed");
|
|
210
|
+
} else {
|
|
211
|
+
throw new Error("Failed to refresh models.dev cache");
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Get model limits for a specific provider and model
|
|
217
|
+
*
|
|
218
|
+
* @param provider Our provider ID (e.g., "anthropic", "openai", "openrouter")
|
|
219
|
+
* @param model Model ID (e.g., "claude-opus-4-5-20251101", "gpt-4o")
|
|
220
|
+
* @returns Model limits or undefined if not found/unsupported
|
|
221
|
+
*/
|
|
222
|
+
export function getModelLimits(provider: string, model: string): ModelLimits | undefined {
|
|
223
|
+
if (!cache) {
|
|
224
|
+
return undefined;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Map our provider ID to models.dev provider ID
|
|
228
|
+
const modelsDevProvider = PROVIDER_MAPPING[provider];
|
|
229
|
+
if (modelsDevProvider === null || modelsDevProvider === undefined) {
|
|
230
|
+
// Provider not supported by models.dev
|
|
231
|
+
return undefined;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const providerData = cache[modelsDevProvider];
|
|
235
|
+
if (!providerData?.models) {
|
|
236
|
+
return undefined;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
const modelData = providerData.models[model];
|
|
240
|
+
if (!modelData?.limit) {
|
|
241
|
+
return undefined;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const { context, output } = modelData.limit;
|
|
245
|
+
if (context === undefined || output === undefined) {
|
|
246
|
+
return undefined;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return { context, output };
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Get just the context window for a model
|
|
254
|
+
* Convenience function for backwards compatibility with context-window-cache
|
|
255
|
+
*/
|
|
256
|
+
export function getContextWindowFromModelsdev(provider: string, model: string): number | undefined {
|
|
257
|
+
const limits = getModelLimits(provider, model);
|
|
258
|
+
return limits?.context;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Clear in-memory cache (for testing)
|
|
263
|
+
*/
|
|
264
|
+
export function clearModelsDevCache(): void {
|
|
265
|
+
cache = null;
|
|
266
|
+
cacheLoadPromise = null;
|
|
267
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import inquirer from "inquirer";
|
|
2
|
+
|
|
3
|
+
import { AI_SDK_PROVIDERS } from "@/llm/types";
|
|
4
|
+
import type { ProviderCredentials, TenexProviders } from "@/services/config/types";
|
|
5
|
+
import { hasApiKey } from "@/llm/providers/key-manager";
|
|
6
|
+
import { ProviderConfigUI } from "@/llm/utils/ProviderConfigUI";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Interactive flow for configuring provider credentials.
|
|
10
|
+
* Returns an updated TenexProviders object (merges into the existing map).
|
|
11
|
+
*/
|
|
12
|
+
export async function runProviderSetup(
|
|
13
|
+
existingProviders: TenexProviders
|
|
14
|
+
): Promise<TenexProviders> {
|
|
15
|
+
const providers: Record<string, ProviderCredentials> = {
|
|
16
|
+
...existingProviders.providers,
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const choices = AI_SDK_PROVIDERS.map((provider) => {
|
|
20
|
+
const isConfigured = hasApiKey(providers[provider]?.apiKey);
|
|
21
|
+
const name = ProviderConfigUI.getProviderDisplayName(provider);
|
|
22
|
+
return {
|
|
23
|
+
name: isConfigured ? `${name} (configured)` : name,
|
|
24
|
+
value: provider,
|
|
25
|
+
};
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const { selected } = await inquirer.prompt([
|
|
29
|
+
{
|
|
30
|
+
type: "checkbox",
|
|
31
|
+
name: "selected",
|
|
32
|
+
message: "Select providers to configure:",
|
|
33
|
+
choices,
|
|
34
|
+
},
|
|
35
|
+
]);
|
|
36
|
+
|
|
37
|
+
if (!selected || selected.length === 0) {
|
|
38
|
+
return existingProviders;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
for (const provider of selected) {
|
|
42
|
+
const providerConfig = await ProviderConfigUI.configureProvider(provider, providers);
|
|
43
|
+
providers[provider] = {
|
|
44
|
+
...providers[provider],
|
|
45
|
+
apiKey: providerConfig.apiKey,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return { providers };
|
|
50
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { AISdkTool } from "@/tools/types";
|
|
2
|
+
import type { StepResult } from "ai";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Extract invalid tool calls from step results.
|
|
6
|
+
* Used to detect and report dynamic tool validation errors.
|
|
7
|
+
*/
|
|
8
|
+
export function getInvalidToolCalls(
|
|
9
|
+
steps: StepResult<Record<string, AISdkTool>>[]
|
|
10
|
+
): Array<{ toolName: string; error: string }> {
|
|
11
|
+
const invalidToolCalls: Array<{ toolName: string; error: string }> = [];
|
|
12
|
+
|
|
13
|
+
for (const step of steps) {
|
|
14
|
+
if (step.toolCalls) {
|
|
15
|
+
for (const toolCall of step.toolCalls) {
|
|
16
|
+
// Check if this is a dynamic tool call that's invalid
|
|
17
|
+
if (
|
|
18
|
+
"dynamic" in toolCall &&
|
|
19
|
+
toolCall.dynamic === true &&
|
|
20
|
+
toolCall.invalid === true &&
|
|
21
|
+
toolCall.error
|
|
22
|
+
) {
|
|
23
|
+
const error =
|
|
24
|
+
typeof toolCall.error === "object" &&
|
|
25
|
+
toolCall.error !== null &&
|
|
26
|
+
"name" in toolCall.error
|
|
27
|
+
? (toolCall.error as { name: string }).name
|
|
28
|
+
: "Unknown error";
|
|
29
|
+
invalidToolCalls.push({
|
|
30
|
+
toolName: toolCall.toolName,
|
|
31
|
+
error,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return invalidToolCalls;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Check if a tool result indicates an error.
|
|
43
|
+
* AI SDK wraps tool execution errors in error-text or error-json formats.
|
|
44
|
+
*/
|
|
45
|
+
export function isToolResultError(result: unknown): boolean {
|
|
46
|
+
if (typeof result !== "object" || result === null) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
const res = result as Record<string, unknown>;
|
|
50
|
+
// Check for AI SDK's known error formats
|
|
51
|
+
return (
|
|
52
|
+
(res.type === "error-text" && typeof res.text === "string") ||
|
|
53
|
+
(res.type === "error-json" && typeof res.json === "object")
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Extract error details from tool result for better logging.
|
|
59
|
+
* Returns null if the result is not an error format.
|
|
60
|
+
*/
|
|
61
|
+
export function extractErrorDetails(result: unknown): { message: string; type: string } | null {
|
|
62
|
+
if (typeof result !== "object" || result === null) {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
const res = result as Record<string, unknown>;
|
|
66
|
+
|
|
67
|
+
if (res.type === "error-text" && typeof res.text === "string") {
|
|
68
|
+
return { message: res.text, type: "error-text" };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (res.type === "error-json" && typeof res.json === "object") {
|
|
72
|
+
const errorJson = res.json as Record<string, unknown>;
|
|
73
|
+
const message = errorJson.message || errorJson.error || JSON.stringify(errorJson);
|
|
74
|
+
return { message: String(message), type: "error-json" };
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { LanguageModelUsage } from "ai";
|
|
2
|
+
import type { LanguageModelUsageWithCostUsd } from "../types";
|
|
3
|
+
|
|
4
|
+
interface OpenRouterUsage {
|
|
5
|
+
promptTokens?: number;
|
|
6
|
+
completionTokens?: number;
|
|
7
|
+
totalTokens?: number;
|
|
8
|
+
cost?: number;
|
|
9
|
+
promptTokensDetails?: {
|
|
10
|
+
cachedTokens?: number;
|
|
11
|
+
};
|
|
12
|
+
completionTokensDetails?: {
|
|
13
|
+
reasoningTokens?: number;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface StepProviderMetadata {
|
|
18
|
+
openrouter?: {
|
|
19
|
+
usage?: OpenRouterUsage;
|
|
20
|
+
};
|
|
21
|
+
[key: string]: unknown;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
type StepUsage = Partial<Pick<LanguageModelUsage, "inputTokens" | "outputTokens">>;
|
|
25
|
+
|
|
26
|
+
export interface StepWithProviderMetadata {
|
|
27
|
+
usage?: StepUsage;
|
|
28
|
+
providerMetadata?: StepProviderMetadata;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Calculate cumulative usage from an array of steps.
|
|
33
|
+
* Returns undefined if no steps provided.
|
|
34
|
+
* Extracts token counts, cost, and detailed token breakdowns from OpenRouter providerMetadata.
|
|
35
|
+
*/
|
|
36
|
+
export function calculateCumulativeUsage(
|
|
37
|
+
steps: StepWithProviderMetadata[]
|
|
38
|
+
): LanguageModelUsageWithCostUsd | undefined {
|
|
39
|
+
if (steps.length === 0) {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const inputTokens = steps.reduce((sum, step) => {
|
|
44
|
+
const openrouterUsage = step.providerMetadata?.openrouter?.usage;
|
|
45
|
+
return sum + (openrouterUsage?.promptTokens ?? step.usage?.inputTokens ?? 0);
|
|
46
|
+
}, 0);
|
|
47
|
+
const outputTokens = steps.reduce((sum, step) => {
|
|
48
|
+
const openrouterUsage = step.providerMetadata?.openrouter?.usage;
|
|
49
|
+
return sum + (openrouterUsage?.completionTokens ?? step.usage?.outputTokens ?? 0);
|
|
50
|
+
}, 0);
|
|
51
|
+
const costUsd = steps.reduce((sum, step) => {
|
|
52
|
+
const openrouterUsage = step.providerMetadata?.openrouter?.usage;
|
|
53
|
+
return sum + (openrouterUsage?.cost ?? 0);
|
|
54
|
+
}, 0);
|
|
55
|
+
const cachedInputTokens = steps.reduce((sum, step) => {
|
|
56
|
+
const openrouterUsage = step.providerMetadata?.openrouter?.usage;
|
|
57
|
+
return sum + (openrouterUsage?.promptTokensDetails?.cachedTokens ?? 0);
|
|
58
|
+
}, 0);
|
|
59
|
+
const reasoningTokens = steps.reduce((sum, step) => {
|
|
60
|
+
const openrouterUsage = step.providerMetadata?.openrouter?.usage;
|
|
61
|
+
return sum + (openrouterUsage?.completionTokensDetails?.reasoningTokens ?? 0);
|
|
62
|
+
}, 0);
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
inputTokens,
|
|
66
|
+
outputTokens,
|
|
67
|
+
totalTokens: inputTokens + outputTokens,
|
|
68
|
+
costUsd: costUsd > 0 ? costUsd : undefined,
|
|
69
|
+
cachedInputTokens: cachedInputTokens > 0 ? cachedInputTokens : undefined,
|
|
70
|
+
reasoningTokens: reasoningTokens > 0 ? reasoningTokens : undefined,
|
|
71
|
+
inputTokenDetails: { noCacheTokens: undefined, cacheReadTokens: undefined, cacheWriteTokens: undefined },
|
|
72
|
+
outputTokenDetails: { textTokens: undefined, reasoningTokens: undefined },
|
|
73
|
+
} as LanguageModelUsageWithCostUsd;
|
|
74
|
+
}
|