@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,128 @@
|
|
|
1
|
+
import type { Stats } from "node:fs";
|
|
2
|
+
import * as fsPromises from "node:fs/promises";
|
|
3
|
+
import * as os from "node:os";
|
|
4
|
+
import * as path from "node:path";
|
|
5
|
+
import { formatAnyError } from "@/lib/error-formatter";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Unified file system utilities combining patterns from CLI and shared packages
|
|
9
|
+
* Provides both sync and async operations with consistent error handling
|
|
10
|
+
*
|
|
11
|
+
* @module filesystem
|
|
12
|
+
* @description
|
|
13
|
+
* This module provides a comprehensive set of file system utilities with:
|
|
14
|
+
* - Path resolution and expansion (home directory ~)
|
|
15
|
+
* - Directory and file existence checks
|
|
16
|
+
* - JSON file read/write operations
|
|
17
|
+
* - Text file operations
|
|
18
|
+
* - Directory listing and management
|
|
19
|
+
* - File copying and deletion
|
|
20
|
+
* - Consistent error handling across all operations
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
// File operations
|
|
24
|
+
export async function readFile(filePath: string, encoding?: BufferEncoding): Promise<string>;
|
|
25
|
+
export async function readFile(filePath: string, encoding: null): Promise<Buffer>;
|
|
26
|
+
export async function readFile(
|
|
27
|
+
filePath: string,
|
|
28
|
+
encoding?: BufferEncoding | null
|
|
29
|
+
): Promise<string | Buffer> {
|
|
30
|
+
return await fsPromises.readFile(filePath, encoding as BufferEncoding | null | undefined);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function expandHome(filePath: string): string {
|
|
34
|
+
if (filePath.startsWith("~")) {
|
|
35
|
+
return path.join(os.homedir(), filePath.slice(1));
|
|
36
|
+
}
|
|
37
|
+
return filePath;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function resolvePath(filePath: string): string {
|
|
41
|
+
return path.resolve(expandHome(filePath));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Directory operations
|
|
45
|
+
export async function ensureDirectory(dirPath: string): Promise<void> {
|
|
46
|
+
try {
|
|
47
|
+
await fsPromises.access(dirPath);
|
|
48
|
+
} catch (err: unknown) {
|
|
49
|
+
if (err instanceof Error && "code" in err && err.code === "ENOENT") {
|
|
50
|
+
await fsPromises.mkdir(dirPath, { recursive: true });
|
|
51
|
+
} else {
|
|
52
|
+
throw err;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export async function directoryExists(dirPath: string): Promise<boolean> {
|
|
58
|
+
try {
|
|
59
|
+
const stat = await fsPromises.stat(dirPath);
|
|
60
|
+
return stat.isDirectory();
|
|
61
|
+
} catch (err: unknown) {
|
|
62
|
+
if (err instanceof Error && "code" in err && err.code === "ENOENT") {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
throw err;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Path existence check (works for both files and directories)
|
|
70
|
+
export async function pathExists(filePath: string): Promise<boolean> {
|
|
71
|
+
try {
|
|
72
|
+
await fsPromises.access(filePath);
|
|
73
|
+
return true;
|
|
74
|
+
} catch {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// File operations
|
|
80
|
+
export async function fileExists(filePath: string): Promise<boolean> {
|
|
81
|
+
try {
|
|
82
|
+
const stat = await fsPromises.stat(filePath);
|
|
83
|
+
return stat.isFile();
|
|
84
|
+
} catch (err: unknown) {
|
|
85
|
+
if (err instanceof Error && "code" in err && err.code === "ENOENT") {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
throw err;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// JSON operations with error handling
|
|
93
|
+
export async function readJsonFile<T>(filePath: string): Promise<T | null> {
|
|
94
|
+
try {
|
|
95
|
+
const content = await fsPromises.readFile(resolvePath(filePath), "utf-8");
|
|
96
|
+
return JSON.parse(content) as T;
|
|
97
|
+
} catch (err: unknown) {
|
|
98
|
+
if (err instanceof Error && "code" in err && err.code === "ENOENT") {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
// Use console.error since lib/ layer should not depend on TENEX logger
|
|
102
|
+
console.error(`Failed to read JSON file ${filePath}: ${formatAnyError(err)}`);
|
|
103
|
+
throw err;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export async function writeJsonFile<T>(
|
|
108
|
+
filePath: string,
|
|
109
|
+
data: T,
|
|
110
|
+
options?: { spaces?: number }
|
|
111
|
+
): Promise<void> {
|
|
112
|
+
const resolvedPath = resolvePath(filePath);
|
|
113
|
+
await ensureDirectory(path.dirname(resolvedPath));
|
|
114
|
+
const spaces = options?.spaces ?? 2;
|
|
115
|
+
await fsPromises.writeFile(resolvedPath, JSON.stringify(data, null, spaces));
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// File stats
|
|
119
|
+
export async function getFileStats(filePath: string): Promise<Stats | null> {
|
|
120
|
+
try {
|
|
121
|
+
return await fsPromises.stat(resolvePath(filePath));
|
|
122
|
+
} catch (err: unknown) {
|
|
123
|
+
if (err instanceof Error && "code" in err && err.code === "ENOENT") {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
throw err;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./filesystem.js";
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Safely parse JSON with markdown code block cleanup
|
|
3
|
+
* @param text The text to parse, potentially containing markdown code blocks
|
|
4
|
+
* @param context Optional context for error logging
|
|
5
|
+
* @returns Parsed object or null if parsing fails
|
|
6
|
+
*/
|
|
7
|
+
export function safeParseJSON<T = unknown>(text: string, context?: string): T | null {
|
|
8
|
+
try {
|
|
9
|
+
// Clean up response - remove markdown code blocks if present
|
|
10
|
+
let cleanText = text.trim();
|
|
11
|
+
|
|
12
|
+
// Remove ```json or ``` wrapper if present
|
|
13
|
+
if (cleanText.startsWith("```json")) {
|
|
14
|
+
cleanText = cleanText.replace(/^```json\s*/, "").replace(/```\s*$/, "");
|
|
15
|
+
} else if (cleanText.startsWith("```")) {
|
|
16
|
+
cleanText = cleanText.replace(/^```\s*/, "").replace(/```\s*$/, "");
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return JSON.parse(cleanText);
|
|
20
|
+
} catch (error) {
|
|
21
|
+
if (context) {
|
|
22
|
+
// Use console.error since lib/ should not depend on TENEX logger
|
|
23
|
+
console.error(`[JSON Parser] Failed to parse JSON in ${context}`, {
|
|
24
|
+
error: error instanceof Error ? error.message : String(error),
|
|
25
|
+
text: text.substring(0, 200),
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts a string to kebab-case format
|
|
3
|
+
* @param str - The input string to convert
|
|
4
|
+
* @returns The kebab-case formatted string
|
|
5
|
+
* @example
|
|
6
|
+
* toKebabCase("HelloWorld") // "hello-world"
|
|
7
|
+
* toKebabCase("hello_world") // "hello-world"
|
|
8
|
+
* toKebabCase("Hello World") // "hello-world"
|
|
9
|
+
*/
|
|
10
|
+
export function toKebabCase(str: string): string {
|
|
11
|
+
return str
|
|
12
|
+
.replace(/([a-z])([A-Z])/g, "$1-$2")
|
|
13
|
+
.replace(/[\s_]+/g, "-")
|
|
14
|
+
.toLowerCase();
|
|
15
|
+
}
|
package/src/lib/time.ts
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Time formatting utilities
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Format a timestamp into a human-readable "time ago" string (long form)
|
|
7
|
+
* Example: "2 hours ago", "45 minutes ago"
|
|
8
|
+
*/
|
|
9
|
+
export function formatTimeAgo(timestamp: number): string {
|
|
10
|
+
const now = Date.now();
|
|
11
|
+
const diff = now - timestamp;
|
|
12
|
+
const seconds = Math.floor(diff / 1000);
|
|
13
|
+
const minutes = Math.floor(seconds / 60);
|
|
14
|
+
const hours = Math.floor(minutes / 60);
|
|
15
|
+
const days = Math.floor(hours / 24);
|
|
16
|
+
const weeks = Math.floor(days / 7);
|
|
17
|
+
const months = Math.floor(days / 30);
|
|
18
|
+
|
|
19
|
+
if (months > 0) {
|
|
20
|
+
return `${months} month${months > 1 ? "s" : ""} ago`;
|
|
21
|
+
}
|
|
22
|
+
if (weeks > 0) {
|
|
23
|
+
return `${weeks} week${weeks > 1 ? "s" : ""} ago`;
|
|
24
|
+
}
|
|
25
|
+
if (days > 0) {
|
|
26
|
+
return `${days} day${days > 1 ? "s" : ""} ago`;
|
|
27
|
+
}
|
|
28
|
+
if (hours > 0) {
|
|
29
|
+
return `${hours} hour${hours > 1 ? "s" : ""} ago`;
|
|
30
|
+
}
|
|
31
|
+
if (minutes > 0) {
|
|
32
|
+
return `${minutes} minute${minutes > 1 ? "s" : ""} ago`;
|
|
33
|
+
}
|
|
34
|
+
if (seconds > 30) {
|
|
35
|
+
return `${seconds} seconds ago`;
|
|
36
|
+
}
|
|
37
|
+
return "just now";
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Format a Unix timestamp (in seconds) into a short relative time string
|
|
42
|
+
* Example: "2h ago", "45m ago", "3d ago"
|
|
43
|
+
* @param timestampSeconds - Unix timestamp in seconds
|
|
44
|
+
*/
|
|
45
|
+
export function formatRelativeTimeShort(timestampSeconds: number): string {
|
|
46
|
+
const now = Math.floor(Date.now() / 1000);
|
|
47
|
+
const diff = now - timestampSeconds;
|
|
48
|
+
|
|
49
|
+
if (diff < 60) {
|
|
50
|
+
return "just now";
|
|
51
|
+
} else if (diff < 3600) {
|
|
52
|
+
const minutes = Math.floor(diff / 60);
|
|
53
|
+
return `${minutes}m ago`;
|
|
54
|
+
} else if (diff < 86400) {
|
|
55
|
+
const hours = Math.floor(diff / 3600);
|
|
56
|
+
return `${hours}h ago`;
|
|
57
|
+
} else {
|
|
58
|
+
const days = Math.floor(diff / 86400);
|
|
59
|
+
return `${days}d ago`;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Format uptime from a start time
|
|
65
|
+
*/
|
|
66
|
+
export function formatUptime(startTime: Date | null): string {
|
|
67
|
+
if (!startTime) return "N/A";
|
|
68
|
+
const now = new Date();
|
|
69
|
+
const diff = now.getTime() - startTime.getTime();
|
|
70
|
+
const hours = Math.floor(diff / 3600000);
|
|
71
|
+
const minutes = Math.floor((diff % 3600000) / 60000);
|
|
72
|
+
const seconds = Math.floor((diff % 60000) / 1000);
|
|
73
|
+
return `${hours}h ${minutes}m ${seconds}s`;
|
|
74
|
+
}
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import type { AISdkTool } from "@/tools/types";
|
|
2
|
+
import { logger } from "@/utils/logger";
|
|
3
|
+
import { trace } from "@opentelemetry/api";
|
|
4
|
+
import type { TextStreamPart } from "ai";
|
|
5
|
+
import type { EventEmitter } from "tseep";
|
|
6
|
+
import { shouldIgnoreChunk } from "./chunk-validators";
|
|
7
|
+
import type { LanguageModelUsageWithCostUsd, LLMServiceEventMap } from "./types";
|
|
8
|
+
|
|
9
|
+
export interface ChunkHandlerState {
|
|
10
|
+
previousChunkType?: string;
|
|
11
|
+
cachedContentForComplete: string;
|
|
12
|
+
getCurrentStepUsage: () => LanguageModelUsageWithCostUsd | undefined;
|
|
13
|
+
getModelContextWindow: () => number | undefined;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Handles streaming chunks from the LLM.
|
|
18
|
+
* Extracted from LLMService to reduce file size.
|
|
19
|
+
*/
|
|
20
|
+
export class ChunkHandler {
|
|
21
|
+
private state: ChunkHandlerState;
|
|
22
|
+
private emitter: EventEmitter<LLMServiceEventMap>;
|
|
23
|
+
|
|
24
|
+
constructor(
|
|
25
|
+
emitter: EventEmitter<LLMServiceEventMap>,
|
|
26
|
+
state: ChunkHandlerState
|
|
27
|
+
) {
|
|
28
|
+
this.emitter = emitter;
|
|
29
|
+
this.state = state;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Main entry point for handling incoming chunks
|
|
34
|
+
*/
|
|
35
|
+
handleChunk(event: { chunk: TextStreamPart<Record<string, AISdkTool>> }): void {
|
|
36
|
+
const chunk = event.chunk;
|
|
37
|
+
|
|
38
|
+
// Validate chunk before any processing - some LLMs send chunks that should be ignored
|
|
39
|
+
if (shouldIgnoreChunk(chunk)) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Emit raw-chunk event for consumers (e.g., local streaming)
|
|
44
|
+
logger.debug("[LLMService] emitting raw-chunk", { chunkType: chunk.type });
|
|
45
|
+
this.emitter.emit("raw-chunk", { chunk: event.chunk });
|
|
46
|
+
|
|
47
|
+
// Emit chunk-type-change event BEFORE processing the new chunk
|
|
48
|
+
// This allows listeners to flush buffers before new content of a different type arrives
|
|
49
|
+
if (this.state.previousChunkType !== undefined && this.state.previousChunkType !== chunk.type) {
|
|
50
|
+
this.emitter.emit("chunk-type-change", {
|
|
51
|
+
from: this.state.previousChunkType,
|
|
52
|
+
to: chunk.type,
|
|
53
|
+
});
|
|
54
|
+
// Clear cached content after emitting chunk-type-change.
|
|
55
|
+
// IMPORTANT: AgentExecutor listens to chunk-type-change and publishes the content
|
|
56
|
+
// buffer as a kind:1 event BEFORE this clearing happens. Without that publish,
|
|
57
|
+
// interim text (e.g., "I'll fetch that naddr...") would be lost.
|
|
58
|
+
// See: src/agents/execution/AgentExecutor.ts chunk-type-change handler
|
|
59
|
+
this.state.cachedContentForComplete = "";
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Update previousChunkType AFTER emitting the change event
|
|
63
|
+
this.state.previousChunkType = chunk.type;
|
|
64
|
+
|
|
65
|
+
switch (chunk.type) {
|
|
66
|
+
case "text-delta":
|
|
67
|
+
this.handleTextDelta(chunk.text);
|
|
68
|
+
break;
|
|
69
|
+
case "reasoning-delta": {
|
|
70
|
+
// Handle reasoning-delta separately - emit reasoning event
|
|
71
|
+
// The AI SDK may transform our custom reasoning-delta chunks
|
|
72
|
+
// to use 'text' property instead of 'delta'
|
|
73
|
+
interface ReasoningDeltaChunk {
|
|
74
|
+
delta?: string;
|
|
75
|
+
text?: string;
|
|
76
|
+
}
|
|
77
|
+
const reasoningChunk = chunk as ReasoningDeltaChunk;
|
|
78
|
+
const reasoningContent = reasoningChunk.delta || reasoningChunk.text;
|
|
79
|
+
if (reasoningContent) {
|
|
80
|
+
this.handleReasoningDelta(reasoningContent);
|
|
81
|
+
}
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
case "tool-call":
|
|
85
|
+
this.handleToolCall(chunk.toolCallId, chunk.toolName, chunk.input);
|
|
86
|
+
break;
|
|
87
|
+
case "tool-result":
|
|
88
|
+
this.handleToolResult(chunk.toolCallId, chunk.toolName, chunk.output);
|
|
89
|
+
break;
|
|
90
|
+
case "tool-error": {
|
|
91
|
+
this.handleToolError(chunk.toolCallId, chunk.toolName, chunk.error);
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
case "tool-input-start":
|
|
95
|
+
// Tool input is starting to stream
|
|
96
|
+
trace.getActiveSpan()?.addEvent("llm.tool_input_start", {
|
|
97
|
+
"tool.call_id": chunk.id,
|
|
98
|
+
"tool.name": chunk.toolName,
|
|
99
|
+
});
|
|
100
|
+
break;
|
|
101
|
+
case "tool-input-delta":
|
|
102
|
+
// Tool input is being incrementally streamed - too verbose for traces
|
|
103
|
+
break;
|
|
104
|
+
case "reasoning-start":
|
|
105
|
+
trace.getActiveSpan()?.addEvent("llm.reasoning_start", {
|
|
106
|
+
"reasoning.id": chunk.id,
|
|
107
|
+
});
|
|
108
|
+
break;
|
|
109
|
+
case "reasoning-end":
|
|
110
|
+
trace.getActiveSpan()?.addEvent("llm.reasoning_end", {
|
|
111
|
+
"reasoning.id": chunk.id,
|
|
112
|
+
});
|
|
113
|
+
break;
|
|
114
|
+
case "error": {
|
|
115
|
+
// Extract detailed error information
|
|
116
|
+
const errorMsg =
|
|
117
|
+
chunk.error instanceof Error ? chunk.error.message : String(chunk.error);
|
|
118
|
+
const errorStack = chunk.error instanceof Error ? chunk.error.stack : undefined;
|
|
119
|
+
|
|
120
|
+
logger.error("[LLMService] ❌ Error chunk received", {
|
|
121
|
+
errorMessage: errorMsg,
|
|
122
|
+
errorStack,
|
|
123
|
+
errorType: chunk.error?.constructor?.name,
|
|
124
|
+
fullError: chunk.error,
|
|
125
|
+
});
|
|
126
|
+
this.emitter.emit("stream-error", { error: chunk.error });
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
default:
|
|
130
|
+
// Record unknown chunk types for debugging
|
|
131
|
+
trace.getActiveSpan()?.addEvent("llm.unknown_chunk_type", {
|
|
132
|
+
"chunk.type": chunk.type,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
private handleTextDelta(text: string): void {
|
|
138
|
+
this.emitter.emit("content", { delta: text });
|
|
139
|
+
this.state.cachedContentForComplete += text;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
private handleReasoningDelta(text: string): void {
|
|
143
|
+
// Skip useless "[REDACTED]" reasoning events
|
|
144
|
+
if (text.trim() === "[REDACTED]") {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
this.emitter.emit("reasoning", { delta: text });
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
private handleToolCall(toolCallId: string, toolName: string, args: unknown): void {
|
|
151
|
+
trace.getActiveSpan()?.addEvent("llm.tool_will_execute", {
|
|
152
|
+
"tool.name": toolName,
|
|
153
|
+
"tool.call_id": toolCallId,
|
|
154
|
+
});
|
|
155
|
+
const usage = this.state.getCurrentStepUsage();
|
|
156
|
+
this.emitter.emit("tool-will-execute", {
|
|
157
|
+
toolName,
|
|
158
|
+
toolCallId,
|
|
159
|
+
args,
|
|
160
|
+
usage: usage
|
|
161
|
+
? { ...usage, contextWindow: this.state.getModelContextWindow() }
|
|
162
|
+
: undefined,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
private handleToolResult(toolCallId: string, toolName: string, result: unknown): void {
|
|
167
|
+
const hasError = isToolResultError(result);
|
|
168
|
+
|
|
169
|
+
if (hasError) {
|
|
170
|
+
const errorDetails = extractErrorDetails(result);
|
|
171
|
+
logger.error(`[LLMService] Tool '${toolName}' execution failed`, {
|
|
172
|
+
toolCallId,
|
|
173
|
+
toolName,
|
|
174
|
+
errorType: errorDetails?.type || "unknown",
|
|
175
|
+
errorMessage: errorDetails?.message || "No error details available",
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
trace.getActiveSpan()?.addEvent("llm.tool_did_execute", {
|
|
180
|
+
"tool.name": toolName,
|
|
181
|
+
"tool.call_id": toolCallId,
|
|
182
|
+
"tool.error": hasError,
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
this.emitter.emit("tool-did-execute", {
|
|
186
|
+
toolName,
|
|
187
|
+
toolCallId,
|
|
188
|
+
result,
|
|
189
|
+
error: hasError,
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
private handleToolError(toolCallId: string, toolName: string, error: unknown): void {
|
|
194
|
+
// Handle tool execution errors - emit as tool-did-execute with error flag
|
|
195
|
+
const errorMsg =
|
|
196
|
+
error instanceof Error ? error.message : String(error);
|
|
197
|
+
const errorStack = error instanceof Error ? (error as Error).stack : undefined;
|
|
198
|
+
|
|
199
|
+
logger.error(`[LLMService] Tool '${toolName}' threw an error`, {
|
|
200
|
+
toolCallId,
|
|
201
|
+
toolName,
|
|
202
|
+
error: errorMsg,
|
|
203
|
+
stack: errorStack,
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
// Log BOTH error event AND execution complete event for consistency
|
|
207
|
+
const activeSpan = trace.getActiveSpan();
|
|
208
|
+
activeSpan?.addEvent("llm.tool_error", {
|
|
209
|
+
"tool.name": toolName,
|
|
210
|
+
"tool.call_id": toolCallId,
|
|
211
|
+
"tool.error_message": errorMsg,
|
|
212
|
+
"tool.error_type": error?.constructor?.name || "Error",
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
// IMPORTANT: Also log tool_did_execute for error cases
|
|
216
|
+
// This ensures trace analysis can find tool completion regardless of success/failure
|
|
217
|
+
activeSpan?.addEvent("llm.tool_did_execute", {
|
|
218
|
+
"tool.name": toolName,
|
|
219
|
+
"tool.call_id": toolCallId,
|
|
220
|
+
"tool.error": true,
|
|
221
|
+
"tool.error_message": errorMsg.substring(0, 200),
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
// Emit tool-did-execute with error info so it gets persisted to conversation
|
|
225
|
+
// Format the error as a result object that the LLM can understand
|
|
226
|
+
this.emitter.emit("tool-did-execute", {
|
|
227
|
+
toolName,
|
|
228
|
+
toolCallId,
|
|
229
|
+
result: {
|
|
230
|
+
type: "error-text",
|
|
231
|
+
text: `Tool execution failed: ${errorMsg}`,
|
|
232
|
+
},
|
|
233
|
+
error: true,
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Get the current cached content
|
|
239
|
+
*/
|
|
240
|
+
getCachedContent(): string {
|
|
241
|
+
return this.state.cachedContentForComplete;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Clear the cached content
|
|
246
|
+
*/
|
|
247
|
+
clearCachedContent(): void {
|
|
248
|
+
this.state.cachedContentForComplete = "";
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Check if a tool result indicates an error
|
|
254
|
+
*/
|
|
255
|
+
function isToolResultError(result: unknown): boolean {
|
|
256
|
+
if (result && typeof result === "object") {
|
|
257
|
+
const obj = result as Record<string, unknown>;
|
|
258
|
+
return obj.type === "error-text" || obj.type === "error";
|
|
259
|
+
}
|
|
260
|
+
return false;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Extract error details from a tool result
|
|
265
|
+
*/
|
|
266
|
+
function extractErrorDetails(result: unknown): { type: string; message: string } | undefined {
|
|
267
|
+
if (result && typeof result === "object") {
|
|
268
|
+
const obj = result as Record<string, unknown>;
|
|
269
|
+
if (obj.type === "error-text" || obj.type === "error") {
|
|
270
|
+
return {
|
|
271
|
+
type: String(obj.type),
|
|
272
|
+
message: String(obj.text || obj.message || "Unknown error"),
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
return undefined;
|
|
277
|
+
}
|