@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,100 @@
|
|
|
1
|
+
import type { ModelMessage, ToolCallPart, ToolResultPart } from "ai";
|
|
2
|
+
import type { ConversationStore } from "@/conversations/ConversationStore";
|
|
3
|
+
import { RALRegistry } from "@/services/ral";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Syncs messages from AI SDK's step.messages to ConversationStore.
|
|
7
|
+
* Ensures ConversationStore never misses tool calls/results that the AI SDK tracked.
|
|
8
|
+
*
|
|
9
|
+
* This handles cases where tool-did-execute events don't fire (provider-dependent,
|
|
10
|
+
* e.g., Ollama doesn't emit tool-error chunks), ensuring tool results are never lost.
|
|
11
|
+
*
|
|
12
|
+
* Also clears tool tracking state as a fallback when tool results are observed
|
|
13
|
+
* without corresponding tool-did-execute events.
|
|
14
|
+
*/
|
|
15
|
+
export class MessageSyncer {
|
|
16
|
+
private conversationId: string;
|
|
17
|
+
|
|
18
|
+
constructor(
|
|
19
|
+
private conversationStore: ConversationStore,
|
|
20
|
+
private agentPubkey: string,
|
|
21
|
+
private ralNumber: number
|
|
22
|
+
) {
|
|
23
|
+
this.conversationId = conversationStore.id;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Sync tool messages from AI SDK to ConversationStore.
|
|
28
|
+
* Call this at the start of prepareStep before rebuilding messages.
|
|
29
|
+
*/
|
|
30
|
+
syncFromSDK(messages: ModelMessage[]): void {
|
|
31
|
+
for (const msg of messages) {
|
|
32
|
+
if (msg.role === "assistant" && Array.isArray(msg.content)) {
|
|
33
|
+
this.syncToolCalls(msg.content);
|
|
34
|
+
}
|
|
35
|
+
if (msg.role === "tool" && Array.isArray(msg.content)) {
|
|
36
|
+
this.syncToolResults(msg.content);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
private syncToolCalls(content: unknown[]): void {
|
|
42
|
+
for (const part of content) {
|
|
43
|
+
if (this.isToolCallPart(part)) {
|
|
44
|
+
if (!this.conversationStore.hasToolCall(part.toolCallId)) {
|
|
45
|
+
this.conversationStore.addMessage({
|
|
46
|
+
pubkey: this.agentPubkey,
|
|
47
|
+
ral: this.ralNumber,
|
|
48
|
+
content: "",
|
|
49
|
+
messageType: "tool-call",
|
|
50
|
+
toolData: [part],
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
private syncToolResults(content: unknown[]): void {
|
|
58
|
+
const ralRegistry = RALRegistry.getInstance();
|
|
59
|
+
|
|
60
|
+
for (const part of content) {
|
|
61
|
+
if (this.isToolResultPart(part)) {
|
|
62
|
+
if (!this.conversationStore.hasToolResult(part.toolCallId)) {
|
|
63
|
+
this.conversationStore.addMessage({
|
|
64
|
+
pubkey: this.agentPubkey,
|
|
65
|
+
ral: this.ralNumber,
|
|
66
|
+
content: "",
|
|
67
|
+
messageType: "tool-result",
|
|
68
|
+
toolData: [part],
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Fallback: Clear tool from activeTools if it wasn't cleared by tool-did-execute.
|
|
73
|
+
// This handles cases where tool-did-execute doesn't fire (provider-dependent).
|
|
74
|
+
// If the tool was already cleared, this is a no-op.
|
|
75
|
+
ralRegistry.clearToolFallback(
|
|
76
|
+
this.agentPubkey,
|
|
77
|
+
this.conversationId,
|
|
78
|
+
this.ralNumber,
|
|
79
|
+
part.toolCallId
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
private isToolCallPart(part: unknown): part is ToolCallPart {
|
|
86
|
+
return (
|
|
87
|
+
typeof part === "object" &&
|
|
88
|
+
part !== null &&
|
|
89
|
+
(part as Record<string, unknown>).type === "tool-call"
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
private isToolResultPart(part: unknown): part is ToolResultPart {
|
|
94
|
+
return (
|
|
95
|
+
typeof part === "object" &&
|
|
96
|
+
part !== null &&
|
|
97
|
+
(part as Record<string, unknown>).type === "tool-result"
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Post-completion supervision checker for agent responses.
|
|
3
|
+
*
|
|
4
|
+
* Runs heuristics to detect suspicious agent behavior before publishing.
|
|
5
|
+
* This includes todo list compliance, delegation validation, and other
|
|
6
|
+
* behavioral checks defined in the supervision system.
|
|
7
|
+
*/
|
|
8
|
+
import {
|
|
9
|
+
supervisorOrchestrator,
|
|
10
|
+
updateKnownAgentSlugs,
|
|
11
|
+
type PostCompletionContext,
|
|
12
|
+
} from "@/agents/supervision";
|
|
13
|
+
import type { AgentInstance } from "@/agents/types";
|
|
14
|
+
import type { ConversationStore } from "@/conversations/ConversationStore";
|
|
15
|
+
import type { CompleteEvent } from "@/llm/types";
|
|
16
|
+
import { AgentEventDecoder } from "@/nostr/AgentEventDecoder";
|
|
17
|
+
import { buildSystemPromptMessages } from "@/prompts/utils/systemPromptBuilder";
|
|
18
|
+
import { NudgeService } from "@/services/nudge";
|
|
19
|
+
import { getProjectContext } from "@/services/projects";
|
|
20
|
+
import { RALRegistry } from "@/services/ral";
|
|
21
|
+
import { getToolsObject } from "@/tools/registry";
|
|
22
|
+
import type { FullRuntimeContext } from "./types";
|
|
23
|
+
import { shortenConversationId } from "@/utils/conversation-id";
|
|
24
|
+
import { logger } from "@/utils/logger";
|
|
25
|
+
import { PREFIX_LENGTH } from "@/utils/nostr-entity-parser";
|
|
26
|
+
import { trace } from "@opentelemetry/api";
|
|
27
|
+
|
|
28
|
+
export interface PostCompletionCheckResult {
|
|
29
|
+
/**
|
|
30
|
+
* Whether to suppress publishing and re-engage the agent
|
|
31
|
+
*/
|
|
32
|
+
shouldReEngage: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Correction message to inject if re-engaging
|
|
35
|
+
*/
|
|
36
|
+
correctionMessage?: string;
|
|
37
|
+
/**
|
|
38
|
+
* Whether a non-re-engaging message injection was queued
|
|
39
|
+
*/
|
|
40
|
+
injectedMessage: boolean;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface PostCompletionCheckerConfig {
|
|
44
|
+
agent: AgentInstance;
|
|
45
|
+
context: FullRuntimeContext;
|
|
46
|
+
conversationStore: ConversationStore;
|
|
47
|
+
ralNumber: number;
|
|
48
|
+
completionEvent: CompleteEvent;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Run post-completion supervision check on agent response.
|
|
53
|
+
*
|
|
54
|
+
* @returns Result indicating whether to re-engage, inject messages, or proceed normally
|
|
55
|
+
*/
|
|
56
|
+
export async function checkPostCompletion(
|
|
57
|
+
config: PostCompletionCheckerConfig
|
|
58
|
+
): Promise<PostCompletionCheckResult> {
|
|
59
|
+
const { agent, context, conversationStore, ralNumber, completionEvent } = config;
|
|
60
|
+
const ralRegistry = RALRegistry.getInstance();
|
|
61
|
+
const executionId = `${agent.pubkey}:${context.conversationId}:${ralNumber}`;
|
|
62
|
+
|
|
63
|
+
logger.debug("[PostCompletionChecker] Running supervision check", {
|
|
64
|
+
agent: agent.slug,
|
|
65
|
+
ralNumber,
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// Check if we've exceeded max retries for supervision
|
|
69
|
+
if (supervisorOrchestrator.hasExceededMaxRetries(executionId)) {
|
|
70
|
+
logger.warn("[PostCompletionChecker] Supervision max retries exceeded, publishing anyway", {
|
|
71
|
+
agent: agent.slug,
|
|
72
|
+
ralNumber,
|
|
73
|
+
});
|
|
74
|
+
supervisorOrchestrator.clearState(executionId);
|
|
75
|
+
return { shouldReEngage: false, injectedMessage: false };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Build supervision context
|
|
79
|
+
const projectContext = getProjectContext();
|
|
80
|
+
|
|
81
|
+
// Get tool calls from conversation store
|
|
82
|
+
const storeMessages = conversationStore?.getAllMessages() || [];
|
|
83
|
+
const toolCallsMade = storeMessages
|
|
84
|
+
.filter(m => m.ral === ralNumber && m.messageType === "tool-call" && m.toolData)
|
|
85
|
+
.flatMap(m => m.toolData?.map(td => {
|
|
86
|
+
if (td.type === "tool-call" && "toolName" in td) {
|
|
87
|
+
return td.toolName;
|
|
88
|
+
}
|
|
89
|
+
return undefined;
|
|
90
|
+
}).filter(Boolean) as string[] || []);
|
|
91
|
+
|
|
92
|
+
// Build the system prompt for context
|
|
93
|
+
const conversation = context.getConversation();
|
|
94
|
+
|
|
95
|
+
// Fetch nudge content if triggering event has nudge tags
|
|
96
|
+
const nudgeEventIds = AgentEventDecoder.extractNudgeEventIds(context.triggeringEvent);
|
|
97
|
+
const nudgeContent = nudgeEventIds.length > 0
|
|
98
|
+
? await NudgeService.getInstance().fetchNudges(nudgeEventIds)
|
|
99
|
+
: "";
|
|
100
|
+
|
|
101
|
+
const systemPromptMessages = conversation ? await buildSystemPromptMessages({
|
|
102
|
+
agent,
|
|
103
|
+
project: projectContext.project,
|
|
104
|
+
conversation,
|
|
105
|
+
projectBasePath: context.projectBasePath,
|
|
106
|
+
workingDirectory: context.workingDirectory,
|
|
107
|
+
currentBranch: context.currentBranch,
|
|
108
|
+
availableAgents: Array.from(projectContext.agents.values()),
|
|
109
|
+
mcpManager: projectContext.mcpManager,
|
|
110
|
+
agentLessons: projectContext.agentLessons,
|
|
111
|
+
nudgeContent,
|
|
112
|
+
}) : [];
|
|
113
|
+
const systemPrompt = systemPromptMessages.map(m => m.message.content).join("\n\n");
|
|
114
|
+
|
|
115
|
+
// Update known agent slugs for delegation heuristic
|
|
116
|
+
updateKnownAgentSlugs(Array.from(projectContext.agents.values()).map(a => a.slug));
|
|
117
|
+
|
|
118
|
+
// Build conversation history
|
|
119
|
+
const conversationMessages = conversationStore
|
|
120
|
+
? await conversationStore.buildMessagesForRal(agent.pubkey, ralNumber)
|
|
121
|
+
: [];
|
|
122
|
+
|
|
123
|
+
const toolNames = agent.tools || [];
|
|
124
|
+
const toolsObject = toolNames.length > 0 ? getToolsObject(toolNames, context) : {};
|
|
125
|
+
|
|
126
|
+
// Check todo state for supervision context
|
|
127
|
+
const todos = conversationStore
|
|
128
|
+
? conversationStore.getTodos(agent.pubkey)
|
|
129
|
+
: [];
|
|
130
|
+
const hasBeenNudgedAboutTodos = conversationStore
|
|
131
|
+
? conversationStore.hasBeenNudgedAboutTodos(agent.pubkey)
|
|
132
|
+
: false;
|
|
133
|
+
|
|
134
|
+
// Get pending delegation count from RALRegistry (conversation-wide, not RAL-scoped)
|
|
135
|
+
// We check ALL pending delegations for this conversation because a delegation from
|
|
136
|
+
// an earlier RAL that hasn't completed yet should still suppress the pending-todos heuristic
|
|
137
|
+
const pendingDelegations = ralRegistry.getConversationPendingDelegations(
|
|
138
|
+
agent.pubkey,
|
|
139
|
+
context.conversationId
|
|
140
|
+
// Note: ralNumber is intentionally omitted to get conversation-wide scope
|
|
141
|
+
);
|
|
142
|
+
const pendingDelegationCount = pendingDelegations.length;
|
|
143
|
+
|
|
144
|
+
// Emit telemetry only when pending delegations exist (avoids noisy zero-count events)
|
|
145
|
+
if (pendingDelegationCount > 0) {
|
|
146
|
+
// Cap delegation IDs to first 5 to prevent unbounded output
|
|
147
|
+
const maxDelegationsToLog = 5;
|
|
148
|
+
const delegationIds = pendingDelegations
|
|
149
|
+
.slice(0, maxDelegationsToLog)
|
|
150
|
+
.map(d => d.delegationConversationId.substring(0, PREFIX_LENGTH));
|
|
151
|
+
const truncatedIndicator = pendingDelegationCount > maxDelegationsToLog
|
|
152
|
+
? ` (+${pendingDelegationCount - maxDelegationsToLog} more)`
|
|
153
|
+
: "";
|
|
154
|
+
|
|
155
|
+
logger.debug("[PostCompletionChecker] Pending delegations detected; pending-todos heuristic may be suppressed", {
|
|
156
|
+
agent: agent.slug,
|
|
157
|
+
pendingDelegationCount,
|
|
158
|
+
delegationIds: `[${delegationIds.join(", ")}]${truncatedIndicator}`,
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
trace.getActiveSpan()?.addEvent("executor.supervision_pending_delegations", {
|
|
162
|
+
"agent.slug": agent.slug,
|
|
163
|
+
"agent.pubkey": agent.pubkey.substring(0, PREFIX_LENGTH),
|
|
164
|
+
"conversation.id": shortenConversationId(context.conversationId),
|
|
165
|
+
"ral.number": ralNumber,
|
|
166
|
+
"delegation.pending_count": pendingDelegationCount,
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const supervisionContext: PostCompletionContext = {
|
|
171
|
+
agentSlug: agent.slug,
|
|
172
|
+
agentPubkey: agent.pubkey,
|
|
173
|
+
messageContent: completionEvent.message || "",
|
|
174
|
+
toolCallsMade,
|
|
175
|
+
systemPrompt,
|
|
176
|
+
conversationHistory: conversationMessages,
|
|
177
|
+
availableTools: toolsObject,
|
|
178
|
+
hasBeenNudgedAboutTodos,
|
|
179
|
+
todos: todos.map((t) => ({
|
|
180
|
+
id: t.id,
|
|
181
|
+
title: t.title,
|
|
182
|
+
status: t.status,
|
|
183
|
+
description: t.description,
|
|
184
|
+
})),
|
|
185
|
+
pendingDelegationCount,
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
const supervisionResult = await supervisorOrchestrator.checkPostCompletion(supervisionContext, executionId);
|
|
189
|
+
|
|
190
|
+
if (supervisionResult.hasViolation && supervisionResult.correctionAction) {
|
|
191
|
+
trace.getActiveSpan()?.addEvent("executor.supervision_violation", {
|
|
192
|
+
"ral.number": ralNumber,
|
|
193
|
+
"heuristic.id": supervisionResult.heuristicId || "unknown",
|
|
194
|
+
"action.type": supervisionResult.correctionAction.type,
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
logger.info("[PostCompletionChecker] Supervision detected violation", {
|
|
198
|
+
agent: agent.slug,
|
|
199
|
+
heuristic: supervisionResult.heuristicId,
|
|
200
|
+
actionType: supervisionResult.correctionAction.type,
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
// Mark agent as nudged if this was the todo nudge heuristic
|
|
204
|
+
if (supervisionResult.heuristicId === "consecutive-tools-without-todo" && conversationStore) {
|
|
205
|
+
conversationStore.setNudgedAboutTodos(agent.pubkey);
|
|
206
|
+
await conversationStore.save();
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (supervisionResult.correctionAction.type === "suppress-publish" &&
|
|
210
|
+
supervisionResult.correctionAction.reEngage) {
|
|
211
|
+
// Add telemetry for supervision correction diagnosis
|
|
212
|
+
trace.getActiveSpan()?.addEvent("executor.supervision_correction", {
|
|
213
|
+
"has_message": !!supervisionResult.correctionAction.message,
|
|
214
|
+
"message_length": supervisionResult.correctionAction.message?.length || 0,
|
|
215
|
+
"heuristic.id": supervisionResult.heuristicId || "unknown",
|
|
216
|
+
"action.type": supervisionResult.correctionAction.type,
|
|
217
|
+
"action.reEngage": supervisionResult.correctionAction.reEngage,
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
// Increment retry count
|
|
221
|
+
supervisorOrchestrator.incrementRetryCount(executionId);
|
|
222
|
+
|
|
223
|
+
// Mark this heuristic as enforced so it won't fire again in this RAL
|
|
224
|
+
if (supervisionResult.heuristicId) {
|
|
225
|
+
supervisorOrchestrator.markHeuristicEnforced(executionId, supervisionResult.heuristicId);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Inject correction message as ephemeral user message
|
|
229
|
+
if (supervisionResult.correctionAction.message) {
|
|
230
|
+
ralRegistry.queueUserMessage(
|
|
231
|
+
agent.pubkey,
|
|
232
|
+
context.conversationId,
|
|
233
|
+
ralNumber,
|
|
234
|
+
supervisionResult.correctionAction.message,
|
|
235
|
+
{ ephemeral: true }
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
return {
|
|
240
|
+
shouldReEngage: true,
|
|
241
|
+
correctionMessage: supervisionResult.correctionAction.message,
|
|
242
|
+
injectedMessage: false,
|
|
243
|
+
};
|
|
244
|
+
} else if (supervisionResult.correctionAction.type === "inject-message" &&
|
|
245
|
+
supervisionResult.correctionAction.message) {
|
|
246
|
+
// Store message for agent's NEXT turn (not current RAL).
|
|
247
|
+
// Using deferredInjections instead of ralRegistry.queueSystemMessage() ensures
|
|
248
|
+
// this does NOT count as "outstanding work" and allows the agent to complete()
|
|
249
|
+
// properly. The message will be picked up at the start of the agent's next turn.
|
|
250
|
+
conversationStore.addDeferredInjection({
|
|
251
|
+
targetPubkey: agent.pubkey,
|
|
252
|
+
role: "system",
|
|
253
|
+
content: supervisionResult.correctionAction.message,
|
|
254
|
+
queuedAt: Date.now(),
|
|
255
|
+
source: `supervision:${supervisionResult.heuristicId || "unknown"}`,
|
|
256
|
+
});
|
|
257
|
+
await conversationStore.save();
|
|
258
|
+
|
|
259
|
+
trace.getActiveSpan()?.addEvent("executor.supervision_deferred_injection", {
|
|
260
|
+
"ral.number": ralNumber,
|
|
261
|
+
"heuristic.id": supervisionResult.heuristicId || "unknown",
|
|
262
|
+
"message_length": supervisionResult.correctionAction.message.length,
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
return {
|
|
266
|
+
shouldReEngage: false,
|
|
267
|
+
injectedMessage: true,
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
} else {
|
|
271
|
+
logger.debug("[PostCompletionChecker] Supervision check passed", {
|
|
272
|
+
agent: agent.slug,
|
|
273
|
+
ralNumber,
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
return { shouldReEngage: false, injectedMessage: false };
|
|
278
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { logger } from "@/utils/logger";
|
|
2
|
+
import type { LanguageModel } from "ai";
|
|
3
|
+
import { generateText } from "ai";
|
|
4
|
+
|
|
5
|
+
export class ProgressMonitor {
|
|
6
|
+
private stepCount = 0;
|
|
7
|
+
private readonly REVIEW_THRESHOLD = 50;
|
|
8
|
+
|
|
9
|
+
constructor(private readonly reviewModel: LanguageModel) {}
|
|
10
|
+
|
|
11
|
+
async check(toolNames: string[]): Promise<boolean> {
|
|
12
|
+
this.stepCount++;
|
|
13
|
+
|
|
14
|
+
if (this.stepCount < this.REVIEW_THRESHOLD) {
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
this.stepCount = 0;
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
const toolCallSummary = toolNames.map((name, i) => `${i + 1}. ${name}`).join("\n");
|
|
22
|
+
|
|
23
|
+
const result = await generateText({
|
|
24
|
+
model: this.reviewModel,
|
|
25
|
+
messages: [
|
|
26
|
+
{
|
|
27
|
+
role: "user",
|
|
28
|
+
content: `Review these ${toolNames.length} tool calls. Is the agent making progress or stuck?\n\n${toolCallSummary}\n\nRespond with only "continue" or "stop":`,
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
maxOutputTokens: 10,
|
|
32
|
+
temperature: 0,
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const shouldContinue = result.text.trim().toLowerCase().includes("continue");
|
|
36
|
+
|
|
37
|
+
logger.info("[ProgressMonitor] Review completed", {
|
|
38
|
+
shouldContinue,
|
|
39
|
+
toolCallCount: toolNames.length,
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
return shouldContinue;
|
|
43
|
+
} catch (error) {
|
|
44
|
+
logger.error("[ProgressMonitor] Review failed, stopping", {
|
|
45
|
+
error: error instanceof Error ? error.message : String(error),
|
|
46
|
+
});
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RAL (Request/Agent Lifecycle) resolution for agent execution.
|
|
3
|
+
*
|
|
4
|
+
* Handles the logic of finding or creating a RAL for an execution:
|
|
5
|
+
* - Check for resumable RAL (completed delegations ready to continue)
|
|
6
|
+
* - Check for RAL with queued injections
|
|
7
|
+
* - Create new RAL if none found
|
|
8
|
+
*/
|
|
9
|
+
import type { Span } from "@opentelemetry/api";
|
|
10
|
+
import { RALRegistry } from "@/services/ral";
|
|
11
|
+
import { ConversationStore } from "@/conversations/ConversationStore";
|
|
12
|
+
import type { DelegationMarker } from "@/conversations/types";
|
|
13
|
+
|
|
14
|
+
export interface RALResolutionContext {
|
|
15
|
+
agentPubkey: string;
|
|
16
|
+
conversationId: string;
|
|
17
|
+
/** Project ID for multi-project isolation in daemon mode */
|
|
18
|
+
projectId: string;
|
|
19
|
+
triggeringEventId: string;
|
|
20
|
+
span: Span;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface RALResolutionResult {
|
|
24
|
+
ralNumber: number;
|
|
25
|
+
isResumption: boolean;
|
|
26
|
+
/** Delegation markers that need to be published to Nostr */
|
|
27
|
+
markersToPublish?: Array<{
|
|
28
|
+
delegationConversationId: string;
|
|
29
|
+
recipientPubkey: string;
|
|
30
|
+
parentConversationId: string;
|
|
31
|
+
status: "completed" | "aborted";
|
|
32
|
+
completedAt: number;
|
|
33
|
+
abortReason?: string;
|
|
34
|
+
}>;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Resolve which RAL to use for this execution.
|
|
39
|
+
*
|
|
40
|
+
* Priority:
|
|
41
|
+
* 1. Resumable RAL - has completed delegations ready to continue
|
|
42
|
+
* 2. Injection RAL - has queued injections
|
|
43
|
+
* 3. New RAL - create fresh for this execution
|
|
44
|
+
*/
|
|
45
|
+
export async function resolveRAL(ctx: RALResolutionContext): Promise<RALResolutionResult> {
|
|
46
|
+
const { agentPubkey, conversationId, projectId, triggeringEventId, span } = ctx;
|
|
47
|
+
const ralRegistry = RALRegistry.getInstance();
|
|
48
|
+
|
|
49
|
+
// Check for a resumable RAL (one with completed delegations ready to continue)
|
|
50
|
+
const resumableRal = ralRegistry.findResumableRAL(agentPubkey, conversationId);
|
|
51
|
+
|
|
52
|
+
// Also check for RAL with queued injections
|
|
53
|
+
const injectionRal = !resumableRal
|
|
54
|
+
? ralRegistry.findRALWithInjections(agentPubkey, conversationId)
|
|
55
|
+
: undefined;
|
|
56
|
+
|
|
57
|
+
let ralNumber: number;
|
|
58
|
+
let isResumption = false;
|
|
59
|
+
let markersToPublish: Array<{
|
|
60
|
+
delegationConversationId: string;
|
|
61
|
+
recipientPubkey: string;
|
|
62
|
+
parentConversationId: string;
|
|
63
|
+
status: "completed" | "aborted";
|
|
64
|
+
completedAt: number;
|
|
65
|
+
abortReason?: string;
|
|
66
|
+
}> = [];
|
|
67
|
+
|
|
68
|
+
if (resumableRal) {
|
|
69
|
+
// Resume existing RAL instead of creating a new one
|
|
70
|
+
ralNumber = resumableRal.ralNumber;
|
|
71
|
+
isResumption = true;
|
|
72
|
+
|
|
73
|
+
// Get delegations from conversation storage
|
|
74
|
+
const completedDelegations = ralRegistry.getConversationCompletedDelegations(
|
|
75
|
+
agentPubkey, conversationId, resumableRal.ralNumber
|
|
76
|
+
);
|
|
77
|
+
const pendingDelegations = ralRegistry.getConversationPendingDelegations(
|
|
78
|
+
agentPubkey, conversationId, resumableRal.ralNumber
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
// Get the parent conversation store to update/insert markers
|
|
82
|
+
const parentStore = ConversationStore.get(conversationId);
|
|
83
|
+
|
|
84
|
+
// Update delegation markers for each completed delegation (or create if not found)
|
|
85
|
+
// Markers are expanded lazily when building messages
|
|
86
|
+
if (parentStore) {
|
|
87
|
+
for (const completion of completedDelegations) {
|
|
88
|
+
// Try to update existing pending marker first
|
|
89
|
+
const updated = parentStore.updateDelegationMarker(
|
|
90
|
+
completion.delegationConversationId,
|
|
91
|
+
{
|
|
92
|
+
status: completion.status,
|
|
93
|
+
completedAt: completion.completedAt,
|
|
94
|
+
abortReason: completion.status === "aborted" ? completion.abortReason : undefined,
|
|
95
|
+
}
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
// If no pending marker found, create a new one (backward compatibility)
|
|
99
|
+
if (!updated) {
|
|
100
|
+
const marker: DelegationMarker = {
|
|
101
|
+
delegationConversationId: completion.delegationConversationId,
|
|
102
|
+
recipientPubkey: completion.recipientPubkey,
|
|
103
|
+
parentConversationId: conversationId,
|
|
104
|
+
completedAt: completion.completedAt,
|
|
105
|
+
status: completion.status,
|
|
106
|
+
abortReason: completion.status === "aborted" ? completion.abortReason : undefined,
|
|
107
|
+
};
|
|
108
|
+
parentStore.addDelegationMarker(marker, agentPubkey, ralNumber);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Collect markers to publish to Nostr
|
|
112
|
+
markersToPublish.push({
|
|
113
|
+
delegationConversationId: completion.delegationConversationId,
|
|
114
|
+
recipientPubkey: completion.recipientPubkey,
|
|
115
|
+
parentConversationId: conversationId,
|
|
116
|
+
status: completion.status,
|
|
117
|
+
completedAt: completion.completedAt,
|
|
118
|
+
abortReason: completion.status === "aborted" ? completion.abortReason : undefined,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Save the store after adding/updating markers
|
|
123
|
+
await parentStore.save();
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Separate counts for telemetry
|
|
127
|
+
const abortedCount = completedDelegations.filter(d => d.status === "aborted").length;
|
|
128
|
+
const successfulCount = completedDelegations.filter(d => d.status !== "aborted").length;
|
|
129
|
+
|
|
130
|
+
// Clear completed delegations after inserting markers
|
|
131
|
+
// This prevents re-processing on subsequent executions
|
|
132
|
+
ralRegistry.clearCompletedDelegations(agentPubkey, conversationId, ralNumber);
|
|
133
|
+
|
|
134
|
+
span.addEvent("executor.ral_resumed", {
|
|
135
|
+
"ral.number": ralNumber,
|
|
136
|
+
"delegation.completed_count": successfulCount,
|
|
137
|
+
"delegation.aborted_count": abortedCount,
|
|
138
|
+
"delegation.pending_count": pendingDelegations.length,
|
|
139
|
+
"delegation.markers_inserted": completedDelegations.length,
|
|
140
|
+
});
|
|
141
|
+
} else if (injectionRal) {
|
|
142
|
+
// Resume RAL with queued injections
|
|
143
|
+
ralNumber = injectionRal.ralNumber;
|
|
144
|
+
isResumption = true;
|
|
145
|
+
|
|
146
|
+
const injectionRalPending = ralRegistry.getConversationPendingDelegations(
|
|
147
|
+
agentPubkey, conversationId, injectionRal.ralNumber
|
|
148
|
+
);
|
|
149
|
+
span.addEvent("executor.ral_resumed_for_injection", {
|
|
150
|
+
"ral.number": ralNumber,
|
|
151
|
+
"injection.count": injectionRal.queuedInjections.length,
|
|
152
|
+
pending_delegations: injectionRalPending.length,
|
|
153
|
+
});
|
|
154
|
+
} else {
|
|
155
|
+
// Create a new RAL for this execution
|
|
156
|
+
// Pass projectId for multi-project isolation and trace context for stop event correlation
|
|
157
|
+
const spanContext = span.spanContext();
|
|
158
|
+
ralNumber = ralRegistry.create(
|
|
159
|
+
agentPubkey,
|
|
160
|
+
conversationId,
|
|
161
|
+
projectId,
|
|
162
|
+
triggeringEventId,
|
|
163
|
+
{ traceId: spanContext.traceId, spanId: spanContext.spanId }
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
span.setAttributes({
|
|
168
|
+
"ral.number": ralNumber,
|
|
169
|
+
"ral.is_resumption": isResumption,
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
return {
|
|
173
|
+
ralNumber,
|
|
174
|
+
isResumption,
|
|
175
|
+
markersToPublish: markersToPublish.length > 0 ? markersToPublish : undefined,
|
|
176
|
+
};
|
|
177
|
+
}
|