@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,579 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StreamExecutionHandler - Handles LLM streaming execution with event processing
|
|
3
|
+
*
|
|
4
|
+
* This class encapsulates stream event handling and coordinates
|
|
5
|
+
* LLM streaming with message persistence and delegation handling.
|
|
6
|
+
* Callbacks are created via StreamCallbacks module.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { formatAnyError, formatStreamError } from "@/lib/error-formatter";
|
|
10
|
+
import {
|
|
11
|
+
type ChunkTypeChangeEvent,
|
|
12
|
+
type CompleteEvent,
|
|
13
|
+
type ContentEvent,
|
|
14
|
+
type RawChunkEvent,
|
|
15
|
+
type ReasoningEvent,
|
|
16
|
+
type SessionCapturedEvent,
|
|
17
|
+
type StreamErrorEvent,
|
|
18
|
+
} from "@/llm/types";
|
|
19
|
+
import { streamPublisher } from "@/llm";
|
|
20
|
+
import { PROVIDER_IDS } from "@/llm/providers/provider-ids";
|
|
21
|
+
import { shortenConversationId } from "@/utils/conversation-id";
|
|
22
|
+
import type { EventContext } from "@/nostr/types";
|
|
23
|
+
import { llmOpsRegistry } from "@/services/LLMOperationsRegistry";
|
|
24
|
+
import { RALRegistry } from "@/services/ral";
|
|
25
|
+
import type { SkillData } from "@/services/skill";
|
|
26
|
+
import { clearLLMSpanId } from "@/telemetry/LLMSpanRegistry";
|
|
27
|
+
import type { AISdkTool } from "@/tools/types";
|
|
28
|
+
import { createEventContext } from "@/services/event-context";
|
|
29
|
+
import { logger } from "@/utils/logger";
|
|
30
|
+
import { trace } from "@opentelemetry/api";
|
|
31
|
+
import type { LanguageModel, ModelMessage } from "ai";
|
|
32
|
+
import chalk from "chalk";
|
|
33
|
+
import type { LLMService } from "@/llm/service";
|
|
34
|
+
import type { MessageCompiler } from "./MessageCompiler";
|
|
35
|
+
import type { SessionManager } from "./SessionManager";
|
|
36
|
+
import type { ToolExecutionTracker } from "./ToolExecutionTracker";
|
|
37
|
+
import { createPrepareStep } from "./StreamCallbacks";
|
|
38
|
+
import { setupToolEventHandlers } from "./ToolEventHandlers";
|
|
39
|
+
import type { FullRuntimeContext, RALExecutionContext, StreamExecutionResult } from "./types";
|
|
40
|
+
import { extractLastUserMessage } from "./utils";
|
|
41
|
+
import { CompressionService } from "@/services/compression/CompressionService.js";
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Configuration for stream execution
|
|
45
|
+
*/
|
|
46
|
+
export interface StreamExecutionConfig {
|
|
47
|
+
context: FullRuntimeContext;
|
|
48
|
+
toolTracker: ToolExecutionTracker;
|
|
49
|
+
ralNumber: number;
|
|
50
|
+
toolsObject: Record<string, AISdkTool>;
|
|
51
|
+
sessionManager: SessionManager;
|
|
52
|
+
llmService: LLMService;
|
|
53
|
+
messageCompiler: MessageCompiler;
|
|
54
|
+
nudgeContent: string;
|
|
55
|
+
/** Concatenated skill content */
|
|
56
|
+
skillContent: string;
|
|
57
|
+
/** Individual skill data for system prompt rendering */
|
|
58
|
+
skills: SkillData[];
|
|
59
|
+
ephemeralMessages: Array<{ role: "user" | "system"; content: string }>;
|
|
60
|
+
abortSignal: AbortSignal;
|
|
61
|
+
metaModelSystemPrompt?: string;
|
|
62
|
+
variantSystemPrompt?: string;
|
|
63
|
+
/** Optional dedicated LLM service for compression operations */
|
|
64
|
+
compressionLlmService?: LLMService;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Handles all LLM stream event processing and coordination
|
|
69
|
+
*/
|
|
70
|
+
export class StreamExecutionHandler {
|
|
71
|
+
private contentBuffer = "";
|
|
72
|
+
private reasoningBuffer = "";
|
|
73
|
+
private result: StreamExecutionResult | undefined;
|
|
74
|
+
private lastUsedVariant: string | undefined;
|
|
75
|
+
private currentModel: LanguageModel | undefined;
|
|
76
|
+
private readonly execContext: RALExecutionContext;
|
|
77
|
+
private readonly executionSpan = trace.getActiveSpan();
|
|
78
|
+
|
|
79
|
+
constructor(private readonly config: StreamExecutionConfig) {
|
|
80
|
+
this.lastUsedVariant = config.context.conversationStore.getMetaModelVariantOverride(
|
|
81
|
+
config.context.agent.pubkey
|
|
82
|
+
);
|
|
83
|
+
this.execContext = { accumulatedMessages: [] };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Execute the stream and return the result
|
|
88
|
+
*/
|
|
89
|
+
async execute(messages: ModelMessage[]): Promise<StreamExecutionResult> {
|
|
90
|
+
const { context, llmService, toolsObject, abortSignal } = this.config;
|
|
91
|
+
const ralRegistry = RALRegistry.getInstance();
|
|
92
|
+
const conversationStore = context.conversationStore;
|
|
93
|
+
const ralNumber = this.config.ralNumber;
|
|
94
|
+
|
|
95
|
+
// Initialize execution context
|
|
96
|
+
this.execContext.accumulatedMessages = messages;
|
|
97
|
+
|
|
98
|
+
// Setup all event handlers
|
|
99
|
+
this.setupEventHandlers();
|
|
100
|
+
|
|
101
|
+
try {
|
|
102
|
+
// Mark this RAL as streaming and start timing LLM runtime
|
|
103
|
+
ralRegistry.setStreaming(context.agent.pubkey, context.conversationId, ralNumber, true);
|
|
104
|
+
const lastUserMessage = extractLastUserMessage(messages);
|
|
105
|
+
ralRegistry.startLLMStream(context.agent.pubkey, context.conversationId, ralNumber, lastUserMessage);
|
|
106
|
+
|
|
107
|
+
// DIAGNOSTIC: Capture process state at stream start for bottleneck analysis
|
|
108
|
+
const memUsage = process.memoryUsage();
|
|
109
|
+
const cpuUsage = process.cpuUsage();
|
|
110
|
+
this.executionSpan?.addEvent("executor.stream_start_process_state", {
|
|
111
|
+
"process.memory_heap_used_mb": Math.round(memUsage.heapUsed / 1024 / 1024),
|
|
112
|
+
"process.memory_heap_total_mb": Math.round(memUsage.heapTotal / 1024 / 1024),
|
|
113
|
+
"process.memory_rss_mb": Math.round(memUsage.rss / 1024 / 1024),
|
|
114
|
+
"process.memory_external_mb": Math.round(memUsage.external / 1024 / 1024),
|
|
115
|
+
"process.cpu_user_ms": Math.round(cpuUsage.user / 1000),
|
|
116
|
+
"process.cpu_system_ms": Math.round(cpuUsage.system / 1000),
|
|
117
|
+
"ral.number": ralNumber,
|
|
118
|
+
"agent.slug": context.agent.slug,
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
// Add TENEX-specific attributes to the active span
|
|
122
|
+
const activeSpan = trace.getActiveSpan();
|
|
123
|
+
if (activeSpan) {
|
|
124
|
+
activeSpan.setAttributes({
|
|
125
|
+
"tenex.agent.slug": context.agent.slug,
|
|
126
|
+
"tenex.agent.name": context.agent.name,
|
|
127
|
+
"tenex.agent.pubkey": context.agent.pubkey,
|
|
128
|
+
"tenex.conversation.id": shortenConversationId(context.conversationId),
|
|
129
|
+
"tenex.ral.number": ralNumber,
|
|
130
|
+
"tenex.delegation.chain":
|
|
131
|
+
conversationStore.metadata.delegationChain
|
|
132
|
+
?.map((e) => e.displayName)
|
|
133
|
+
.join(" -> ") ?? "",
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Subscribe to raw chunks and forward to local streaming socket
|
|
138
|
+
llmService.on("raw-chunk", (event: RawChunkEvent) => {
|
|
139
|
+
logger.debug("[StreamExecutionHandler] raw-chunk received", {
|
|
140
|
+
chunkType: event.chunk.type,
|
|
141
|
+
agentPubkey: context.agent.pubkey.substring(0, 8),
|
|
142
|
+
});
|
|
143
|
+
streamPublisher.write({
|
|
144
|
+
agent_pubkey: context.agent.pubkey,
|
|
145
|
+
conversation_id: context.conversationId,
|
|
146
|
+
data: event.chunk,
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
// Create callbacks using extracted factory functions
|
|
151
|
+
const prepareStep = createPrepareStep({
|
|
152
|
+
context,
|
|
153
|
+
llmService,
|
|
154
|
+
messageCompiler: this.config.messageCompiler,
|
|
155
|
+
ephemeralMessages: this.config.ephemeralMessages,
|
|
156
|
+
nudgeContent: this.config.nudgeContent,
|
|
157
|
+
skillContent: this.config.skillContent,
|
|
158
|
+
skills: this.config.skills,
|
|
159
|
+
ralNumber,
|
|
160
|
+
execContext: this.execContext,
|
|
161
|
+
executionSpan: this.executionSpan,
|
|
162
|
+
modelState: {
|
|
163
|
+
lastUsedVariant: this.lastUsedVariant,
|
|
164
|
+
currentModel: this.currentModel,
|
|
165
|
+
setVariant: (v) => { this.lastUsedVariant = v; },
|
|
166
|
+
setModel: (m) => { this.currentModel = m; },
|
|
167
|
+
},
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
// DIAGNOSTIC: Track when we're about to call stream()
|
|
171
|
+
const streamCallStartTime = Date.now();
|
|
172
|
+
this.executionSpan?.addEvent("executor.stream_call_starting", {
|
|
173
|
+
"stream.call_start_time": streamCallStartTime,
|
|
174
|
+
"stream.messages_count": messages.length,
|
|
175
|
+
"stream.tools_count": Object.keys(toolsObject).length,
|
|
176
|
+
"stream.abort_signal_aborted": abortSignal.aborted,
|
|
177
|
+
"ral.number": ralNumber,
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
await llmService.stream(messages, toolsObject, {
|
|
181
|
+
abortSignal,
|
|
182
|
+
prepareStep,
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
// DIAGNOSTIC: Track when stream() returns with process state comparison
|
|
186
|
+
const streamCallEndTime = Date.now();
|
|
187
|
+
const streamCallDuration = streamCallEndTime - streamCallStartTime;
|
|
188
|
+
const endMemUsage = process.memoryUsage();
|
|
189
|
+
const endCpuUsage = process.cpuUsage(cpuUsage); // Delta since start
|
|
190
|
+
this.executionSpan?.addEvent("executor.stream_call_completed", {
|
|
191
|
+
"stream.call_end_time": streamCallEndTime,
|
|
192
|
+
"stream.call_duration_ms": streamCallDuration,
|
|
193
|
+
"stream.result_set_after_stream": this.result !== undefined,
|
|
194
|
+
"stream.result_kind_after_stream": this.result?.kind ?? "undefined",
|
|
195
|
+
"stream.abort_signal_aborted_after": abortSignal.aborted,
|
|
196
|
+
"ral.number": ralNumber,
|
|
197
|
+
// Process state delta for bottleneck analysis
|
|
198
|
+
"process.memory_heap_delta_mb": Math.round((endMemUsage.heapUsed - memUsage.heapUsed) / 1024 / 1024),
|
|
199
|
+
"process.memory_rss_delta_mb": Math.round((endMemUsage.rss - memUsage.rss) / 1024 / 1024),
|
|
200
|
+
"process.cpu_user_delta_ms": Math.round(endCpuUsage.user / 1000),
|
|
201
|
+
"process.cpu_system_delta_ms": Math.round(endCpuUsage.system / 1000),
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
// Diagnostic: Track when stream method returns
|
|
205
|
+
const streamReturnTime = Date.now();
|
|
206
|
+
this.executionSpan?.addEvent("executor.stream_returned", {
|
|
207
|
+
"stream.return_time": streamReturnTime,
|
|
208
|
+
"stream.result_set": this.result !== undefined,
|
|
209
|
+
"stream.result_kind": this.result?.kind ?? "undefined",
|
|
210
|
+
"ral.number": ralNumber,
|
|
211
|
+
});
|
|
212
|
+
} catch (streamError) {
|
|
213
|
+
await this.handleStreamError(streamError, abortSignal);
|
|
214
|
+
} finally {
|
|
215
|
+
await this.cleanup();
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Flush any remaining reasoning buffer
|
|
219
|
+
if (this.reasoningBuffer.trim().length > 0) {
|
|
220
|
+
await this.flushReasoningBuffer();
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Handle session persistence for Claude Code
|
|
224
|
+
const { sessionManager, llmService: svc } = this.config;
|
|
225
|
+
if (
|
|
226
|
+
!sessionManager.getSession().sessionId &&
|
|
227
|
+
svc.provider === PROVIDER_IDS.CLAUDE_CODE &&
|
|
228
|
+
this.result?.kind === "complete"
|
|
229
|
+
) {
|
|
230
|
+
sessionManager.saveLastSentEventId(context.triggeringEvent.id);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Capture accumulated runtime for caller
|
|
234
|
+
const accumulatedRuntime = ralRegistry.getAccumulatedRuntime(
|
|
235
|
+
context.agent.pubkey,
|
|
236
|
+
context.conversationId,
|
|
237
|
+
ralNumber
|
|
238
|
+
);
|
|
239
|
+
|
|
240
|
+
// Diagnostic: Log state right before the critical result check
|
|
241
|
+
const resultCheckTime = Date.now();
|
|
242
|
+
this.executionSpan?.addEvent("executor.result_check", {
|
|
243
|
+
"result.check_time": resultCheckTime,
|
|
244
|
+
"result.is_defined": this.result !== undefined,
|
|
245
|
+
"result.kind": this.result?.kind ?? "undefined",
|
|
246
|
+
"ral.number": ralNumber,
|
|
247
|
+
"stream.accumulated_runtime_ms": accumulatedRuntime,
|
|
248
|
+
"agent.slug": context.agent.slug,
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
if (!this.result) {
|
|
252
|
+
this.executionSpan?.addEvent("executor.result_undefined_error", {
|
|
253
|
+
"error.type": "missing_result",
|
|
254
|
+
"ral.number": ralNumber,
|
|
255
|
+
"stream.accumulated_runtime_ms": accumulatedRuntime,
|
|
256
|
+
"agent.slug": context.agent.slug,
|
|
257
|
+
"agent.pubkey": context.agent.pubkey.substring(0, 8),
|
|
258
|
+
"conversation.id": shortenConversationId(context.conversationId),
|
|
259
|
+
"llm.provider": svc.provider,
|
|
260
|
+
"llm.model": svc.model,
|
|
261
|
+
});
|
|
262
|
+
throw new Error("LLM stream completed without emitting complete or stream-error event");
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Set aborted flag and reason if stop signal was triggered
|
|
266
|
+
if (this.result.kind === "complete" && abortSignal.aborted) {
|
|
267
|
+
this.result.aborted = true;
|
|
268
|
+
this.result.abortReason =
|
|
269
|
+
typeof abortSignal.reason === "string" ? abortSignal.reason : undefined;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Add accumulated runtime to result
|
|
273
|
+
if (this.result.kind === "complete") {
|
|
274
|
+
this.result.accumulatedRuntime = accumulatedRuntime;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
return this.result;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Setup all event handlers for the LLM service
|
|
282
|
+
*/
|
|
283
|
+
private setupEventHandlers(): void {
|
|
284
|
+
const { context, llmService, toolTracker, toolsObject } = this.config;
|
|
285
|
+
const agentPublisher = context.agentPublisher;
|
|
286
|
+
const eventContext = this.createEventContext();
|
|
287
|
+
const ralNumber = this.config.ralNumber;
|
|
288
|
+
|
|
289
|
+
llmService.on("content", (event: ContentEvent) => {
|
|
290
|
+
process.stdout.write(chalk.white(event.delta));
|
|
291
|
+
this.contentBuffer += event.delta;
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
llmService.on("reasoning", (event: ReasoningEvent) => {
|
|
295
|
+
process.stdout.write(chalk.gray(event.delta));
|
|
296
|
+
this.reasoningBuffer += event.delta;
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
llmService.on("chunk-type-change", async (event: ChunkTypeChangeEvent) => {
|
|
300
|
+
if (event.from === "reasoning-delta") {
|
|
301
|
+
await this.flushReasoningBuffer();
|
|
302
|
+
}
|
|
303
|
+
if (event.from === "text-delta") {
|
|
304
|
+
await this.flushContentBuffer();
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
// Track when we register the complete listener
|
|
309
|
+
const completeListenerRegisteredAt = Date.now();
|
|
310
|
+
this.executionSpan?.addEvent("executor.complete_listener_registered", {
|
|
311
|
+
"listener.registered_at": completeListenerRegisteredAt,
|
|
312
|
+
"ral.number": ralNumber,
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
llmService.on("complete", (event: CompleteEvent) => {
|
|
316
|
+
const completeReceivedTime = Date.now();
|
|
317
|
+
const timeSinceRegistration = completeReceivedTime - completeListenerRegisteredAt;
|
|
318
|
+
this.executionSpan?.addEvent("executor.complete_received", {
|
|
319
|
+
"complete.received_at": completeReceivedTime,
|
|
320
|
+
"complete.ms_since_listener_registered": timeSinceRegistration,
|
|
321
|
+
"complete.message_length": event.message?.length ?? 0,
|
|
322
|
+
"complete.steps_count": event.steps?.length ?? 0,
|
|
323
|
+
"complete.finish_reason": event.finishReason ?? "unknown",
|
|
324
|
+
"complete.result_already_set": this.result !== undefined,
|
|
325
|
+
"complete.result_kind": this.result?.kind ?? "none",
|
|
326
|
+
"ral.number": ralNumber,
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
if (!this.result) {
|
|
330
|
+
this.result = {
|
|
331
|
+
kind: "complete",
|
|
332
|
+
event,
|
|
333
|
+
messageCompiler: this.config.messageCompiler,
|
|
334
|
+
accumulatedRuntime: 0,
|
|
335
|
+
};
|
|
336
|
+
this.executionSpan?.addEvent("executor.result_set_to_complete", {
|
|
337
|
+
"ral.number": ralNumber,
|
|
338
|
+
});
|
|
339
|
+
} else {
|
|
340
|
+
this.executionSpan?.addEvent("executor.complete_ignored_result_exists", {
|
|
341
|
+
"existing_result.kind": this.result.kind,
|
|
342
|
+
"ral.number": ralNumber,
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// Trigger proactive background compression after LLM response
|
|
347
|
+
// Non-blocking - fires and forgets
|
|
348
|
+
this.triggerProactiveCompression();
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
llmService.on("stream-error", async (event: StreamErrorEvent) => {
|
|
352
|
+
const errorReceivedTime = Date.now();
|
|
353
|
+
const timeSinceRegistration = errorReceivedTime - completeListenerRegisteredAt;
|
|
354
|
+
this.executionSpan?.addEvent("executor.stream_error_received", {
|
|
355
|
+
"error.received_at": errorReceivedTime,
|
|
356
|
+
"error.ms_since_listener_registered": timeSinceRegistration,
|
|
357
|
+
"error.message": event.error instanceof Error ? event.error.message : String(event.error),
|
|
358
|
+
"error.type": event.error instanceof Error ? event.error.constructor.name : typeof event.error,
|
|
359
|
+
"error.result_already_set": this.result !== undefined,
|
|
360
|
+
"error.result_kind": this.result?.kind ?? "none",
|
|
361
|
+
"ral.number": ralNumber,
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
logger.error("[StreamExecutionHandler] Stream error from LLMService", event);
|
|
365
|
+
this.result = { kind: "error-handled" };
|
|
366
|
+
|
|
367
|
+
try {
|
|
368
|
+
const { message: errorMessage, errorType } = formatStreamError(event.error);
|
|
369
|
+
await agentPublisher.error({ message: errorMessage, errorType }, eventContext);
|
|
370
|
+
} catch (publishError) {
|
|
371
|
+
logger.error("Failed to publish stream error event", {
|
|
372
|
+
error: formatAnyError(publishError),
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
llmService.on("session-captured", ({ sessionId: capturedSessionId }: SessionCapturedEvent) => {
|
|
378
|
+
this.config.sessionManager.saveSession(capturedSessionId, context.triggeringEvent.id);
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
// Setup tool event handlers via extracted module
|
|
382
|
+
setupToolEventHandlers({
|
|
383
|
+
context,
|
|
384
|
+
llmService,
|
|
385
|
+
toolTracker,
|
|
386
|
+
toolsObject,
|
|
387
|
+
eventContext,
|
|
388
|
+
ralNumber,
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Create event context for publishing
|
|
394
|
+
*/
|
|
395
|
+
private createEventContext(): EventContext {
|
|
396
|
+
const { context, llmService } = this.config;
|
|
397
|
+
const eventContext = createEventContext(context, llmService.model);
|
|
398
|
+
|
|
399
|
+
// DIAGNOSTIC: Track event context creation to debug llm-ral=0 issues
|
|
400
|
+
this.executionSpan?.addEvent("executor.event_context_created", {
|
|
401
|
+
"context.ral_number": eventContext.ralNumber,
|
|
402
|
+
"context.conversation_id": eventContext.conversationId ? shortenConversationId(eventContext.conversationId) : "none",
|
|
403
|
+
"context.model": eventContext.model ?? "none",
|
|
404
|
+
"config.ral_number": this.config.ralNumber,
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
return eventContext;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Flush reasoning buffer to publish interim reasoning
|
|
412
|
+
*/
|
|
413
|
+
private async flushReasoningBuffer(): Promise<void> {
|
|
414
|
+
if (this.reasoningBuffer.trim().length > 0) {
|
|
415
|
+
const { context } = this.config;
|
|
416
|
+
const eventContext = this.createEventContext();
|
|
417
|
+
const contentToFlush = this.reasoningBuffer;
|
|
418
|
+
|
|
419
|
+
// Add to conversation store BEFORE publishing - capture index for eventId reconciliation
|
|
420
|
+
const messageIndex = context.conversationStore.addMessage({
|
|
421
|
+
pubkey: context.agent.pubkey,
|
|
422
|
+
ral: this.config.ralNumber,
|
|
423
|
+
content: contentToFlush,
|
|
424
|
+
messageType: "text",
|
|
425
|
+
timestamp: Math.floor(Date.now() / 1000),
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
// Clear buffer BEFORE async publish to prevent re-adding on retry
|
|
429
|
+
this.reasoningBuffer = "";
|
|
430
|
+
|
|
431
|
+
try {
|
|
432
|
+
const event = await context.agentPublisher.conversation(
|
|
433
|
+
{ content: contentToFlush, isReasoning: true },
|
|
434
|
+
eventContext
|
|
435
|
+
);
|
|
436
|
+
|
|
437
|
+
// Link the published eventId to the message for loopback deduplication
|
|
438
|
+
if (event.id && messageIndex >= 0) {
|
|
439
|
+
context.conversationStore.setEventId(messageIndex, event.id);
|
|
440
|
+
}
|
|
441
|
+
} catch (publishError) {
|
|
442
|
+
// Log but don't throw - message is already in store, just unlinked
|
|
443
|
+
// The loopback dedup will handle this gracefully (worst case: duplicate display)
|
|
444
|
+
logger.warn("[StreamExecutionHandler] Failed to publish reasoning buffer", {
|
|
445
|
+
error: publishError instanceof Error ? publishError.message : String(publishError),
|
|
446
|
+
ralNumber: this.config.ralNumber,
|
|
447
|
+
agent: context.agent.slug,
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* Flush content buffer to publish interim text
|
|
455
|
+
*/
|
|
456
|
+
private async flushContentBuffer(): Promise<void> {
|
|
457
|
+
if (this.contentBuffer.trim().length > 0) {
|
|
458
|
+
const { context } = this.config;
|
|
459
|
+
const eventContext = this.createEventContext();
|
|
460
|
+
const contentToFlush = this.contentBuffer;
|
|
461
|
+
|
|
462
|
+
// Add to conversation store BEFORE publishing - capture index for eventId reconciliation
|
|
463
|
+
const messageIndex = context.conversationStore.addMessage({
|
|
464
|
+
pubkey: context.agent.pubkey,
|
|
465
|
+
ral: this.config.ralNumber,
|
|
466
|
+
content: contentToFlush,
|
|
467
|
+
messageType: "text",
|
|
468
|
+
timestamp: Math.floor(Date.now() / 1000),
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
// Clear buffer BEFORE async publish to prevent re-adding on retry
|
|
472
|
+
this.contentBuffer = "";
|
|
473
|
+
|
|
474
|
+
try {
|
|
475
|
+
const event = await context.agentPublisher.conversation(
|
|
476
|
+
{ content: contentToFlush },
|
|
477
|
+
eventContext
|
|
478
|
+
);
|
|
479
|
+
|
|
480
|
+
// Link the published eventId to the message for loopback deduplication
|
|
481
|
+
if (event.id && messageIndex >= 0) {
|
|
482
|
+
context.conversationStore.setEventId(messageIndex, event.id);
|
|
483
|
+
}
|
|
484
|
+
} catch (publishError) {
|
|
485
|
+
// Log but don't throw - message is already in store, just unlinked
|
|
486
|
+
// The loopback dedup will handle this gracefully (worst case: duplicate display)
|
|
487
|
+
logger.warn("[StreamExecutionHandler] Failed to publish content buffer", {
|
|
488
|
+
error: publishError instanceof Error ? publishError.message : String(publishError),
|
|
489
|
+
ralNumber: this.config.ralNumber,
|
|
490
|
+
agent: context.agent.slug,
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* Handle stream errors
|
|
498
|
+
*/
|
|
499
|
+
private async handleStreamError(streamError: unknown, abortSignal: AbortSignal): Promise<void> {
|
|
500
|
+
const { context } = this.config;
|
|
501
|
+
const ralNumber = this.config.ralNumber;
|
|
502
|
+
|
|
503
|
+
if (abortSignal.aborted) {
|
|
504
|
+
this.executionSpan?.addEvent("executor.aborted_by_stop_signal", {
|
|
505
|
+
"ral.number": ralNumber,
|
|
506
|
+
"agent.slug": context.agent.slug,
|
|
507
|
+
"conversation.id": shortenConversationId(context.conversationId),
|
|
508
|
+
});
|
|
509
|
+
logger.info("[StreamExecutionHandler] Execution aborted by stop signal", {
|
|
510
|
+
agent: context.agent.slug,
|
|
511
|
+
ralNumber,
|
|
512
|
+
conversationId: context.conversationId.substring(0, 8),
|
|
513
|
+
});
|
|
514
|
+
throw streamError;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
if (this.result?.kind !== "error-handled") {
|
|
518
|
+
this.result = { kind: "error-handled" };
|
|
519
|
+
try {
|
|
520
|
+
const { message: errorMessage, errorType } = formatStreamError(streamError);
|
|
521
|
+
const eventContext = this.createEventContext();
|
|
522
|
+
await context.agentPublisher.error({ message: errorMessage, errorType }, eventContext);
|
|
523
|
+
} catch (publishError) {
|
|
524
|
+
logger.error("Failed to publish stream error event", {
|
|
525
|
+
error: formatAnyError(publishError),
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
throw streamError;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
/**
|
|
533
|
+
* Trigger proactive background compression after LLM response.
|
|
534
|
+
* Non-blocking - runs async without blocking the completion flow.
|
|
535
|
+
*/
|
|
536
|
+
private triggerProactiveCompression(): void {
|
|
537
|
+
const { context, llmService, compressionLlmService } = this.config;
|
|
538
|
+
|
|
539
|
+
try {
|
|
540
|
+
const compressionService = new CompressionService(
|
|
541
|
+
context.conversationStore,
|
|
542
|
+
llmService,
|
|
543
|
+
compressionLlmService
|
|
544
|
+
);
|
|
545
|
+
|
|
546
|
+
// Fire and forget - non-blocking
|
|
547
|
+
compressionService.maybeCompressAsync(context.conversationId);
|
|
548
|
+
|
|
549
|
+
this.executionSpan?.addEvent("compression.proactive_triggered", {
|
|
550
|
+
"conversation.id": shortenConversationId(context.conversationId),
|
|
551
|
+
});
|
|
552
|
+
} catch (error) {
|
|
553
|
+
// Non-blocking - just log if compression setup fails
|
|
554
|
+
logger.warn("[StreamExecutionHandler] Failed to trigger proactive compression", {
|
|
555
|
+
error: error instanceof Error ? error.message : String(error),
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
/**
|
|
561
|
+
* Cleanup after stream execution
|
|
562
|
+
*/
|
|
563
|
+
private async cleanup(): Promise<void> {
|
|
564
|
+
const { context, llmService } = this.config;
|
|
565
|
+
const ralNumber = this.config.ralNumber;
|
|
566
|
+
const ralRegistry = RALRegistry.getInstance();
|
|
567
|
+
|
|
568
|
+
ralRegistry.endLLMStream(context.agent.pubkey, context.conversationId, ralNumber);
|
|
569
|
+
ralRegistry.setStreaming(context.agent.pubkey, context.conversationId, ralNumber, false);
|
|
570
|
+
|
|
571
|
+
llmOpsRegistry.completeOperation(context);
|
|
572
|
+
llmService.removeAllListeners();
|
|
573
|
+
|
|
574
|
+
const currentSpan = trace.getActiveSpan();
|
|
575
|
+
if (currentSpan) {
|
|
576
|
+
clearLLMSpanId(currentSpan.spanContext().traceId);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
}
|