@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,677 @@
|
|
|
1
|
+
import { NDKAgentLesson } from "@/events/NDKAgentLesson";
|
|
2
|
+
import type { LanguageModelUsageWithCostUsd } from "@/llm/types";
|
|
3
|
+
import { NDKKind } from "@/nostr/kinds";
|
|
4
|
+
import { getNDK } from "@/nostr/ndkClient";
|
|
5
|
+
import { getProjectContext } from "@/services/projects";
|
|
6
|
+
import { shortenConversationId } from "@/utils/conversation-id";
|
|
7
|
+
import { logger } from "@/utils/logger";
|
|
8
|
+
import { NDKEvent } from "@nostr-dev-kit/ndk";
|
|
9
|
+
import { nip19 } from "nostr-tools";
|
|
10
|
+
import type {
|
|
11
|
+
AskIntent,
|
|
12
|
+
CompletionIntent,
|
|
13
|
+
ConversationIntent,
|
|
14
|
+
DelegationIntent,
|
|
15
|
+
DelegationMarkerIntent,
|
|
16
|
+
ErrorIntent,
|
|
17
|
+
EventContext,
|
|
18
|
+
InterventionReviewIntent,
|
|
19
|
+
LessonIntent,
|
|
20
|
+
ToolUseIntent,
|
|
21
|
+
} from "./types";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Centralized module for encoding and decoding agent event semantics.
|
|
25
|
+
* This module codifies the tagging structures and their meanings,
|
|
26
|
+
* ensuring consistent event creation and interpretation across the system.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Encodes agent intents into properly tagged Nostr events.
|
|
31
|
+
* All tagging logic is centralized here for consistency and testability.
|
|
32
|
+
*/
|
|
33
|
+
export class AgentEventEncoder {
|
|
34
|
+
/**
|
|
35
|
+
* Add conversation tags consistently to any event.
|
|
36
|
+
* Just e-tags the root event - no reply threading.
|
|
37
|
+
*/
|
|
38
|
+
private addConversationTags(event: NDKEvent, context: EventContext): void {
|
|
39
|
+
if (context.rootEvent.id) {
|
|
40
|
+
event.tag(["e", context.rootEvent.id]);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Determine the correct recipient pubkey for a completion event.
|
|
46
|
+
*
|
|
47
|
+
* Uses pre-resolved completionRecipientPubkey from context when available.
|
|
48
|
+
* This supports delegation chain routing where completions must route back
|
|
49
|
+
* to the immediate delegator, not the event that happened to trigger the
|
|
50
|
+
* current execution (e.g., a user responding to an ask).
|
|
51
|
+
*
|
|
52
|
+
* The recipient resolution is done by createEventContext() in EventContextService
|
|
53
|
+
* (services/event-context/, layer 3) which has access to ConversationStore. This
|
|
54
|
+
* method just uses the pre-resolved value or falls back to triggeringEvent.pubkey
|
|
55
|
+
* for direct conversations.
|
|
56
|
+
*
|
|
57
|
+
* @param context - The event context containing completionRecipientPubkey or triggeringEvent
|
|
58
|
+
* @returns The pubkey to use for the completion p-tag
|
|
59
|
+
*/
|
|
60
|
+
private getCompletionRecipientPubkey(context: EventContext): string {
|
|
61
|
+
// Use pre-resolved recipient if available (set by createEventContext from delegation chain)
|
|
62
|
+
if (context.completionRecipientPubkey) {
|
|
63
|
+
logger.debug("Completion routing via pre-resolved recipient", {
|
|
64
|
+
conversationId: context.conversationId.substring(0, 12),
|
|
65
|
+
recipientPubkey: context.completionRecipientPubkey.substring(0, 8),
|
|
66
|
+
triggeringEventPubkey: context.triggeringEvent.pubkey.substring(0, 8),
|
|
67
|
+
usingPreResolved: context.completionRecipientPubkey !== context.triggeringEvent.pubkey,
|
|
68
|
+
});
|
|
69
|
+
return context.completionRecipientPubkey;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// No pre-resolved recipient - fall back to triggering event pubkey
|
|
73
|
+
// This is the correct behavior for direct user conversations
|
|
74
|
+
return context.triggeringEvent.pubkey;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Forward branch tag from triggering event to reply event.
|
|
79
|
+
* Ensures agents carry forward the branch context from the message they're replying to.
|
|
80
|
+
*/
|
|
81
|
+
public forwardBranchTag(event: NDKEvent, context: EventContext): void {
|
|
82
|
+
const branchTag = context.triggeringEvent.tags.find((tag) => tag[0] === "branch" && tag[1]);
|
|
83
|
+
if (branchTag) {
|
|
84
|
+
event.tag(["branch", branchTag[1]]);
|
|
85
|
+
logger.debug("Forwarding branch tag", {
|
|
86
|
+
branch: branchTag[1],
|
|
87
|
+
fromEvent: context.triggeringEvent.id?.substring(0, 8),
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Encode a completion intent into a tagged event.
|
|
94
|
+
* Completions have p-tag (triggers notification) and status=completed.
|
|
95
|
+
*
|
|
96
|
+
* IMPORTANT: For delegation contexts, the p-tag targets the immediate delegator
|
|
97
|
+
* (second-to-last entry in the delegation chain), NOT the triggeringEvent.pubkey.
|
|
98
|
+
* This ensures completions route back up the delegation stack even when RAL state
|
|
99
|
+
* is lost and the execution restarts with a fresh triggeringEvent (e.g., after
|
|
100
|
+
* a human responds to an "ask" hours later).
|
|
101
|
+
*/
|
|
102
|
+
encodeCompletion(intent: CompletionIntent, context: EventContext): NDKEvent {
|
|
103
|
+
const event = new NDKEvent(getNDK());
|
|
104
|
+
event.kind = NDKKind.Text; // kind:1
|
|
105
|
+
event.content = intent.content;
|
|
106
|
+
|
|
107
|
+
this.addConversationTags(event, context);
|
|
108
|
+
|
|
109
|
+
// Determine the correct p-tag recipient
|
|
110
|
+
const recipientPubkey = this.getCompletionRecipientPubkey(context);
|
|
111
|
+
event.tag(["p", recipientPubkey]);
|
|
112
|
+
event.tag(["status", "completed"]);
|
|
113
|
+
|
|
114
|
+
if (intent.usage) {
|
|
115
|
+
this.addLLMUsageTags(event, intent.usage);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Note: LLM runtime (incremental) is added via addStandardTags() using context.llmRuntime
|
|
119
|
+
this.addStandardTags(event, context);
|
|
120
|
+
|
|
121
|
+
// For completion events, add llm-runtime-total tag when available
|
|
122
|
+
// This preserves semantic contract:
|
|
123
|
+
// - llm-runtime = incremental runtime since last publish (from addStandardTags)
|
|
124
|
+
// - llm-runtime-total = total accumulated runtime (completion-specific)
|
|
125
|
+
if (context.llmRuntimeTotal !== undefined && context.llmRuntimeTotal > 0) {
|
|
126
|
+
event.tag(["llm-runtime-total", context.llmRuntimeTotal.toString(), "ms"]);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
this.forwardBranchTag(event, context);
|
|
130
|
+
|
|
131
|
+
logger.debug("Encoded completion event", {
|
|
132
|
+
eventId: event.id,
|
|
133
|
+
recipientPubkey: recipientPubkey.substring(0, 8),
|
|
134
|
+
triggeringEventPubkey: context.triggeringEvent.pubkey?.substring(0, 8),
|
|
135
|
+
conversationId: context.conversationId?.substring(0, 12),
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
return event;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Encode a conversation intent into a tagged event.
|
|
143
|
+
* Conversations have NO p-tag (no notification) - used for mid-loop responses.
|
|
144
|
+
*/
|
|
145
|
+
encodeConversation(intent: ConversationIntent, context: EventContext): NDKEvent {
|
|
146
|
+
const event = new NDKEvent(getNDK());
|
|
147
|
+
event.kind = NDKKind.Text; // kind:1 - same as completion
|
|
148
|
+
event.content = intent.content;
|
|
149
|
+
|
|
150
|
+
this.addConversationTags(event, context);
|
|
151
|
+
// NO p-tag - that's the difference from completion
|
|
152
|
+
// NO status tag
|
|
153
|
+
|
|
154
|
+
if (intent.isReasoning) {
|
|
155
|
+
event.tag(["reasoning"]);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (intent.usage) {
|
|
159
|
+
this.addLLMUsageTags(event, intent.usage);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
this.addStandardTags(event, context);
|
|
163
|
+
this.forwardBranchTag(event, context);
|
|
164
|
+
|
|
165
|
+
return event;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Prepend recipient identifiers to message content for delegation.
|
|
170
|
+
* Uses agent slugs for known agents, npub format for external recipients.
|
|
171
|
+
*/
|
|
172
|
+
private prependRecipientsToContent(content: string, recipients: string[]): string {
|
|
173
|
+
// Check if content already starts with nostr:npub or @slug patterns
|
|
174
|
+
const hasNostrPrefix = content.startsWith("nostr:");
|
|
175
|
+
const hasSlugPrefix = content.match(/^@[\w-]+:/);
|
|
176
|
+
|
|
177
|
+
if (hasNostrPrefix || hasSlugPrefix) {
|
|
178
|
+
return content;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Get project context to look up agents
|
|
182
|
+
const projectCtx = getProjectContext();
|
|
183
|
+
const agentRegistry = projectCtx.agentRegistry;
|
|
184
|
+
|
|
185
|
+
// Build recipient identifiers
|
|
186
|
+
const recipientIdentifiers = recipients.map((pubkey) => {
|
|
187
|
+
// Check if this pubkey belongs to an agent in the system
|
|
188
|
+
const agent = agentRegistry.getAgentByPubkey(pubkey);
|
|
189
|
+
if (agent) {
|
|
190
|
+
return `@${agent.slug}`;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// For external recipients, use nostr:npub format
|
|
194
|
+
try {
|
|
195
|
+
const npub = nip19.npubEncode(pubkey);
|
|
196
|
+
return `nostr:${npub}`;
|
|
197
|
+
} catch (error) {
|
|
198
|
+
logger.warn("Failed to encode pubkey to npub", { pubkey, error });
|
|
199
|
+
return `nostr:${pubkey}`; // Fallback to hex if encoding fails
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
// Prepend recipients to content
|
|
204
|
+
return `${recipientIdentifiers.join(", ")}: ${content}`;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Encode a delegation intent into kind:1 conversation events.
|
|
209
|
+
* Creates one event per delegation, each with its own content and tags.
|
|
210
|
+
*/
|
|
211
|
+
encodeDelegation(intent: DelegationIntent, context: EventContext): NDKEvent[] {
|
|
212
|
+
return intent.delegations.map((delegation) => {
|
|
213
|
+
const event = new NDKEvent(getNDK());
|
|
214
|
+
event.kind = NDKKind.Text; // kind:1 - unified conversation format
|
|
215
|
+
|
|
216
|
+
// Prepend recipient to the content
|
|
217
|
+
event.content = this.prependRecipientsToContent(delegation.request, [
|
|
218
|
+
delegation.recipient,
|
|
219
|
+
]);
|
|
220
|
+
|
|
221
|
+
event.created_at = Math.floor(Date.now() / 1000) + 1; // we publish one second into the future because it looks more natural when the agent says "I will delegate to..." and then the delegation shows up
|
|
222
|
+
|
|
223
|
+
// No e-tag: delegation events are separate conversations
|
|
224
|
+
// The recipient starts a fresh conversation thread
|
|
225
|
+
|
|
226
|
+
// Add recipient as p-tag
|
|
227
|
+
event.tag(["p", delegation.recipient]);
|
|
228
|
+
|
|
229
|
+
// Branch metadata if provided (for worktree support)
|
|
230
|
+
if (delegation.branch) {
|
|
231
|
+
event.tag(["branch", delegation.branch]);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Add standard metadata
|
|
235
|
+
this.addStandardTags(event, context);
|
|
236
|
+
|
|
237
|
+
// Forward branch tag from triggering event if not explicitly set
|
|
238
|
+
if (!delegation.branch) {
|
|
239
|
+
this.forwardBranchTag(event, context);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
logger.debug("Encoded delegation request", {
|
|
243
|
+
recipient: delegation.recipient.substring(0, 8),
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
return event;
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Encode an Ask intent into a kind:1 event using the multi-question format.
|
|
252
|
+
* Creates an event that asks questions to the project manager/human user.
|
|
253
|
+
*/
|
|
254
|
+
encodeAsk(intent: AskIntent, context: EventContext): NDKEvent {
|
|
255
|
+
const event = new NDKEvent(getNDK());
|
|
256
|
+
event.kind = NDKKind.Text; // kind:1 - unified conversation format
|
|
257
|
+
event.content = intent.context;
|
|
258
|
+
|
|
259
|
+
// Add conversation tags
|
|
260
|
+
this.addConversationTags(event, context);
|
|
261
|
+
|
|
262
|
+
// Get project owner to ask the question to
|
|
263
|
+
const projectCtx = getProjectContext();
|
|
264
|
+
const ownerPubkey = projectCtx?.project?.pubkey;
|
|
265
|
+
|
|
266
|
+
if (ownerPubkey) {
|
|
267
|
+
event.tag(["p", ownerPubkey]);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Add title tag
|
|
271
|
+
event.tag(["title", intent.title]);
|
|
272
|
+
|
|
273
|
+
// Add question/multiselect tags
|
|
274
|
+
for (const question of intent.questions) {
|
|
275
|
+
if (question.type === "question") {
|
|
276
|
+
const tag = ["question", question.title, question.question];
|
|
277
|
+
if (question.suggestions) {
|
|
278
|
+
tag.push(...question.suggestions);
|
|
279
|
+
}
|
|
280
|
+
event.tag(tag);
|
|
281
|
+
} else if (question.type === "multiselect") {
|
|
282
|
+
const tag = ["multiselect", question.title, question.question];
|
|
283
|
+
if (question.options) {
|
|
284
|
+
tag.push(...question.options);
|
|
285
|
+
}
|
|
286
|
+
event.tag(tag);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Mark this as an ask event
|
|
291
|
+
event.tag(["intent", "ask"]);
|
|
292
|
+
|
|
293
|
+
// Add standard metadata
|
|
294
|
+
this.addStandardTags(event, context);
|
|
295
|
+
|
|
296
|
+
// Forward branch tag from triggering event
|
|
297
|
+
this.forwardBranchTag(event, context);
|
|
298
|
+
|
|
299
|
+
logger.debug("Encoded ask event", {
|
|
300
|
+
title: intent.title,
|
|
301
|
+
questionCount: intent.questions.length,
|
|
302
|
+
recipient: ownerPubkey?.substring(0, 8),
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
return event;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Add standard metadata tags that all agent events should have.
|
|
310
|
+
* Centralizes common tagging logic.
|
|
311
|
+
*/
|
|
312
|
+
public addStandardTags(event: NDKEvent, context: EventContext): void {
|
|
313
|
+
this.aTagProject(event);
|
|
314
|
+
|
|
315
|
+
// LLM metadata
|
|
316
|
+
if (context.model) {
|
|
317
|
+
// Handle both string and object formats (some providers return {model: "..."})
|
|
318
|
+
const modelString =
|
|
319
|
+
typeof context.model === "string"
|
|
320
|
+
? context.model
|
|
321
|
+
: (context.model as { model?: string }).model;
|
|
322
|
+
if (modelString) {
|
|
323
|
+
event.tag(["llm-model", modelString]);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
// Add cost metadata if available
|
|
327
|
+
if (context.cost !== undefined) {
|
|
328
|
+
// Format cost to avoid scientific notation and ensure proper decimal representation
|
|
329
|
+
// Use toFixed with enough precision (10 decimal places) then remove trailing zeros
|
|
330
|
+
const formattedCost = context.cost.toFixed(10).replace(/\.?0+$/, "");
|
|
331
|
+
event.tag(["llm-cost-usd", formattedCost]);
|
|
332
|
+
}
|
|
333
|
+
if (context.executionTime) {
|
|
334
|
+
event.tag(["execution-time", context.executionTime.toString()]);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// LLM runtime (incremental since last publish)
|
|
338
|
+
if (context.llmRuntime !== undefined && context.llmRuntime > 0) {
|
|
339
|
+
event.tag(["llm-runtime", context.llmRuntime.toString(), "ms"]);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// LLM runtime total (for completion events - used by delegation aggregation)
|
|
343
|
+
if (context.llmRuntimeTotal !== undefined && context.llmRuntimeTotal > 0) {
|
|
344
|
+
event.tag(["llm-runtime-total", context.llmRuntimeTotal.toString(), "ms"]);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// RAL metadata
|
|
348
|
+
event.tag(["llm-ral", context.ralNumber.toString()]);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Encode an error intent into an error event.
|
|
353
|
+
* Error events act as finalization: they have p-tag (triggers notification) and status=completed.
|
|
354
|
+
*/
|
|
355
|
+
encodeError(intent: ErrorIntent, context: EventContext): NDKEvent {
|
|
356
|
+
const event = new NDKEvent(getNDK());
|
|
357
|
+
event.kind = NDKKind.Text; // kind:1 - unified conversation format
|
|
358
|
+
event.content = intent.message;
|
|
359
|
+
|
|
360
|
+
// Add conversation tags
|
|
361
|
+
this.addConversationTags(event, context);
|
|
362
|
+
|
|
363
|
+
// Mark as error
|
|
364
|
+
event.tag(["error", intent.errorType || "system"]);
|
|
365
|
+
|
|
366
|
+
// Error events are finalization events - notify the user
|
|
367
|
+
event.tag(["p", context.triggeringEvent.pubkey]);
|
|
368
|
+
event.tag(["status", "completed"]);
|
|
369
|
+
|
|
370
|
+
// Add standard metadata
|
|
371
|
+
this.addStandardTags(event, context);
|
|
372
|
+
|
|
373
|
+
// Forward branch tag from triggering event
|
|
374
|
+
this.forwardBranchTag(event, context);
|
|
375
|
+
|
|
376
|
+
return event;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Add LLM usage metadata tags to an event.
|
|
381
|
+
* Centralizes the encoding of usage information from AI SDK's LanguageModelUsageWithCostUsd.
|
|
382
|
+
*/
|
|
383
|
+
private addLLMUsageTags(event: NDKEvent, usage: LanguageModelUsageWithCostUsd): void {
|
|
384
|
+
if (usage.inputTokens !== undefined) {
|
|
385
|
+
event.tag(["llm-prompt-tokens", usage.inputTokens.toString()]);
|
|
386
|
+
}
|
|
387
|
+
if (usage.outputTokens !== undefined) {
|
|
388
|
+
event.tag(["llm-completion-tokens", usage.outputTokens.toString()]);
|
|
389
|
+
}
|
|
390
|
+
if (usage.totalTokens !== undefined) {
|
|
391
|
+
event.tag(["llm-total-tokens", usage.totalTokens.toString()]);
|
|
392
|
+
} else if (usage.inputTokens !== undefined && usage.outputTokens !== undefined) {
|
|
393
|
+
// Fallback: calculate total if not provided
|
|
394
|
+
event.tag(["llm-total-tokens", (usage.inputTokens + usage.outputTokens).toString()]);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
if (usage.costUsd !== undefined) {
|
|
398
|
+
event.tag(["llm-cost-usd", usage.costUsd.toString()]);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// Add additional usage metadata if available
|
|
402
|
+
if ("reasoningTokens" in usage && usage.reasoningTokens !== undefined) {
|
|
403
|
+
event.tag(["llm-reasoning-tokens", String(usage.reasoningTokens)]);
|
|
404
|
+
}
|
|
405
|
+
if ("cachedInputTokens" in usage && usage.cachedInputTokens !== undefined) {
|
|
406
|
+
event.tag(["llm-cached-input-tokens", String(usage.cachedInputTokens)]);
|
|
407
|
+
}
|
|
408
|
+
if ("contextWindow" in usage && usage.contextWindow !== undefined) {
|
|
409
|
+
event.tag(["llm-context-window", String(usage.contextWindow)]);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
aTagProject(event: NDKEvent): undefined {
|
|
414
|
+
const projectCtx = getProjectContext();
|
|
415
|
+
event.tag(projectCtx.project.tagReference());
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* p-tags the project owner
|
|
420
|
+
*/
|
|
421
|
+
pTagProjectOwner(event: NDKEvent): undefined {
|
|
422
|
+
const projectCtx = getProjectContext();
|
|
423
|
+
event.tag(["p", projectCtx.project.pubkey]);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* Encode a lesson learned intent.
|
|
428
|
+
*/
|
|
429
|
+
encodeLesson(
|
|
430
|
+
intent: LessonIntent,
|
|
431
|
+
context: EventContext,
|
|
432
|
+
agent: { eventId?: string }
|
|
433
|
+
): NDKAgentLesson {
|
|
434
|
+
const lessonEvent = new NDKAgentLesson(getNDK());
|
|
435
|
+
|
|
436
|
+
// Set core properties
|
|
437
|
+
lessonEvent.title = intent.title;
|
|
438
|
+
lessonEvent.lesson = intent.lesson;
|
|
439
|
+
|
|
440
|
+
// Set optional properties
|
|
441
|
+
if (intent.detailed) {
|
|
442
|
+
lessonEvent.detailed = intent.detailed;
|
|
443
|
+
}
|
|
444
|
+
if (intent.category) {
|
|
445
|
+
lessonEvent.category = intent.category;
|
|
446
|
+
}
|
|
447
|
+
if (intent.hashtags && intent.hashtags.length > 0) {
|
|
448
|
+
lessonEvent.hashtags = intent.hashtags;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// Add reference to the agent event if available
|
|
452
|
+
if (agent.eventId) {
|
|
453
|
+
lessonEvent.agentDefinitionId = agent.eventId;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// Add standard metadata including project tag
|
|
457
|
+
this.addStandardTags(lessonEvent, context);
|
|
458
|
+
|
|
459
|
+
return lessonEvent;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* Encode a follow-up event to a previous delegation response.
|
|
464
|
+
* Creates a threaded reply that maintains conversation context.
|
|
465
|
+
*
|
|
466
|
+
* @param responseEvent The event being responded to
|
|
467
|
+
* @param message The follow-up message content
|
|
468
|
+
* @param context Event context for standard tags
|
|
469
|
+
* @returns The encoded follow-up event
|
|
470
|
+
*/
|
|
471
|
+
encodeFollowUp(responseEvent: NDKEvent, message: string, context: EventContext): NDKEvent {
|
|
472
|
+
// Create a reply to the response event to maintain thread
|
|
473
|
+
const followUpEvent = responseEvent.reply();
|
|
474
|
+
|
|
475
|
+
// Handle e-tag to avoid deep nesting
|
|
476
|
+
const eTagVal = responseEvent.tagValue("e");
|
|
477
|
+
if (eTagVal) {
|
|
478
|
+
followUpEvent.removeTag("e");
|
|
479
|
+
followUpEvent.tags.push(["e", eTagVal]); // Root thread tag
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
// Prepend recipient to content for follow-ups (single recipient)
|
|
483
|
+
const recipientPubkey = responseEvent.pubkey;
|
|
484
|
+
followUpEvent.content = this.prependRecipientsToContent(message, [recipientPubkey]);
|
|
485
|
+
|
|
486
|
+
// Clean out p-tags and add recipient
|
|
487
|
+
followUpEvent.tags = followUpEvent.tags.filter((t) => t[0] !== "p");
|
|
488
|
+
followUpEvent.tag(responseEvent.author);
|
|
489
|
+
|
|
490
|
+
// Add standard metadata (project tag, model, cost, execution time, ral number)
|
|
491
|
+
this.addStandardTags(followUpEvent, context);
|
|
492
|
+
|
|
493
|
+
// Forward branch tag from response event
|
|
494
|
+
const branchTag = responseEvent.tags.find((tag) => tag[0] === "branch" && tag[1]);
|
|
495
|
+
if (branchTag) {
|
|
496
|
+
followUpEvent.tag(["branch", branchTag[1]]);
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
return followUpEvent;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* Encode a tool usage event.
|
|
504
|
+
* Creates an event that tracks tool invocation with output.
|
|
505
|
+
*/
|
|
506
|
+
encodeToolUse(intent: ToolUseIntent, context: EventContext): NDKEvent {
|
|
507
|
+
const event = new NDKEvent(getNDK());
|
|
508
|
+
event.kind = NDKKind.Text; // kind:1 - unified conversation format
|
|
509
|
+
event.content = intent.content;
|
|
510
|
+
|
|
511
|
+
// Add conversation tags
|
|
512
|
+
this.addConversationTags(event, context);
|
|
513
|
+
|
|
514
|
+
// Add tool usage tags
|
|
515
|
+
event.tag(["tool", intent.toolName]);
|
|
516
|
+
|
|
517
|
+
// Add tool-args tag with JSON serialization
|
|
518
|
+
// If args are provided and can be serialized, add them
|
|
519
|
+
// If the serialized args are > 100k chars, add empty tag
|
|
520
|
+
if (intent.args !== undefined) {
|
|
521
|
+
try {
|
|
522
|
+
const serialized = JSON.stringify(intent.args);
|
|
523
|
+
if (serialized.length <= 100000) {
|
|
524
|
+
event.tag(["tool-args", serialized]);
|
|
525
|
+
} else {
|
|
526
|
+
event.tag(["tool-args"]);
|
|
527
|
+
}
|
|
528
|
+
} catch {
|
|
529
|
+
// If serialization fails, add empty tag
|
|
530
|
+
event.tag(["tool-args"]);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
// Add q-tags for referenced events (e.g., delegation event IDs)
|
|
535
|
+
// Using "q" (quote) tag to indicate these are referenced/quoted events
|
|
536
|
+
if (intent.referencedEventIds) {
|
|
537
|
+
for (const eventId of intent.referencedEventIds) {
|
|
538
|
+
event.tag(["q", eventId]);
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
// Add a-tags for referenced addressable events (e.g., NDKArticle reports)
|
|
543
|
+
// Format: "30023:pubkey:d-tag" for kind 30023 addressable events
|
|
544
|
+
if (intent.referencedAddressableEvents) {
|
|
545
|
+
for (const addressableRef of intent.referencedAddressableEvents) {
|
|
546
|
+
event.tag(["a", addressableRef]);
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
// Add standard metadata
|
|
551
|
+
this.addStandardTags(event, context);
|
|
552
|
+
|
|
553
|
+
// Forward branch tag from triggering event
|
|
554
|
+
this.forwardBranchTag(event, context);
|
|
555
|
+
|
|
556
|
+
// Add LLM usage tags if available (cumulative from previous steps)
|
|
557
|
+
if (intent.usage) {
|
|
558
|
+
this.addLLMUsageTags(event, intent.usage);
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
return event;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
/**
|
|
565
|
+
* Encode an intervention review request event.
|
|
566
|
+
* This is used by the InterventionService when a user hasn't responded
|
|
567
|
+
* to an agent's completion within the configured timeout.
|
|
568
|
+
*
|
|
569
|
+
* Event structure:
|
|
570
|
+
* - kind: 1 (text note)
|
|
571
|
+
* - content: Review request message with human-readable names (pre-resolved by caller)
|
|
572
|
+
* - tags:
|
|
573
|
+
* - ["p", targetPubkey] - The intervention agent to notify
|
|
574
|
+
* - ["context", "intervention-review"] - Context marker
|
|
575
|
+
* - ["e", conversationId] - Reference to the conversation (short form already in content)
|
|
576
|
+
* - ["a", projectTag] - Project reference (added internally via aTagProject)
|
|
577
|
+
*
|
|
578
|
+
* Note: This method does NOT call addStandardTags() since intervention events
|
|
579
|
+
* are not part of an agent execution context. However, the project tag is
|
|
580
|
+
* added internally via aTagProject() for proper project association.
|
|
581
|
+
*
|
|
582
|
+
* Names (userName, agentName) are pre-resolved by the caller (InterventionPublisher)
|
|
583
|
+
* to avoid layer violations - AgentEventEncoder (layer 2) cannot import PubkeyService (layer 3).
|
|
584
|
+
*/
|
|
585
|
+
encodeInterventionReview(intent: InterventionReviewIntent): NDKEvent {
|
|
586
|
+
const event = new NDKEvent(getNDK());
|
|
587
|
+
event.kind = NDKKind.Text; // kind:1
|
|
588
|
+
|
|
589
|
+
const shortConversationId = shortenConversationId(intent.conversationId);
|
|
590
|
+
|
|
591
|
+
event.content = `Conversation ${shortConversationId} has completed and ${intent.userName} hasn't responded. ${intent.agentName} finished their work. Please review and decide if action is needed.`;
|
|
592
|
+
|
|
593
|
+
// Target intervention agent
|
|
594
|
+
event.tag(["p", intent.targetPubkey]);
|
|
595
|
+
|
|
596
|
+
// Context marker for intervention routing
|
|
597
|
+
event.tag(["context", "intervention-review"]);
|
|
598
|
+
|
|
599
|
+
// Reference to the conversation (e-tag for event reference)
|
|
600
|
+
event.tag(["e", intent.conversationId]);
|
|
601
|
+
|
|
602
|
+
// Add project tag (intervention events need project association)
|
|
603
|
+
this.aTagProject(event);
|
|
604
|
+
|
|
605
|
+
logger.debug("Encoded intervention review event", {
|
|
606
|
+
targetPubkey: intent.targetPubkey.substring(0, 8),
|
|
607
|
+
conversationId: shortConversationId,
|
|
608
|
+
userName: intent.userName,
|
|
609
|
+
agentName: intent.agentName,
|
|
610
|
+
});
|
|
611
|
+
|
|
612
|
+
return event;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
/**
|
|
616
|
+
* Encode a delegation marker event.
|
|
617
|
+
* Delegation markers track the lifecycle of delegation conversations.
|
|
618
|
+
*
|
|
619
|
+
* Event structure:
|
|
620
|
+
* - kind: 4203 (DelegationMarker) - custom kind for delegation lifecycle tracking
|
|
621
|
+
* - content: Empty string (markers have no text content)
|
|
622
|
+
* - tags:
|
|
623
|
+
* - ["delegation-marker", status] - Marker type and status
|
|
624
|
+
* - ["e", delegationConversationId] - Reference to the delegation conversation
|
|
625
|
+
* - ["e", parentConversationId] - Reference to the parent conversation
|
|
626
|
+
* - ["p", recipientPubkey] - The agent that received the delegation
|
|
627
|
+
* - ["initiated-at", timestamp] - When delegation was initiated (optional)
|
|
628
|
+
* - ["completed-at", timestamp] - When delegation completed (optional, for completed/aborted)
|
|
629
|
+
* - ["abort-reason", reason] - Abort reason (optional, for aborted)
|
|
630
|
+
* - ["a", projectTag] - Project reference (added internally via aTagProject)
|
|
631
|
+
*/
|
|
632
|
+
encodeDelegationMarker(intent: DelegationMarkerIntent): NDKEvent {
|
|
633
|
+
const event = new NDKEvent(getNDK());
|
|
634
|
+
event.kind = NDKKind.DelegationMarker; // kind:4203 - dedicated kind prevents spam filtering
|
|
635
|
+
|
|
636
|
+
// Markers have no text content
|
|
637
|
+
event.content = "";
|
|
638
|
+
|
|
639
|
+
// Add delegation marker tag with status
|
|
640
|
+
event.tag(["delegation-marker", intent.status]);
|
|
641
|
+
|
|
642
|
+
// Add delegation conversation reference
|
|
643
|
+
event.tag(["e", intent.delegationConversationId]);
|
|
644
|
+
|
|
645
|
+
// Add parent conversation reference
|
|
646
|
+
event.tag(["e", intent.parentConversationId]);
|
|
647
|
+
|
|
648
|
+
// Add recipient agent pubkey
|
|
649
|
+
event.tag(["p", intent.recipientPubkey]);
|
|
650
|
+
|
|
651
|
+
// Add timestamp tags
|
|
652
|
+
if (intent.initiatedAt !== undefined) {
|
|
653
|
+
event.tag(["initiated-at", intent.initiatedAt.toString()]);
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
if (intent.completedAt !== undefined) {
|
|
657
|
+
event.tag(["completed-at", intent.completedAt.toString()]);
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
// Add abort reason if present
|
|
661
|
+
if (intent.abortReason) {
|
|
662
|
+
event.tag(["abort-reason", intent.abortReason]);
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
// Add project tag
|
|
666
|
+
this.aTagProject(event);
|
|
667
|
+
|
|
668
|
+
logger.debug("Encoded delegation marker event", {
|
|
669
|
+
delegationConversationId: intent.delegationConversationId.substring(0, 12),
|
|
670
|
+
parentConversationId: intent.parentConversationId.substring(0, 12),
|
|
671
|
+
recipientPubkey: intent.recipientPubkey.substring(0, 8),
|
|
672
|
+
status: intent.status,
|
|
673
|
+
});
|
|
674
|
+
|
|
675
|
+
return event;
|
|
676
|
+
}
|
|
677
|
+
}
|