@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,205 @@
|
|
|
1
|
+
import * as fs from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import type { NDKEvent, NDKFilter } from "@nostr-dev-kit/ndk";
|
|
4
|
+
|
|
5
|
+
type RoutingDecision = "routed" | "dropped" | "project_event";
|
|
6
|
+
type RoutingMethod = "a_tag" | "p_tag_agent" | "none";
|
|
7
|
+
type RuntimeAction = "existing" | "started" | "none";
|
|
8
|
+
|
|
9
|
+
interface EventRoutingLogEntry {
|
|
10
|
+
timestamp: string;
|
|
11
|
+
eventId: string;
|
|
12
|
+
kind: number;
|
|
13
|
+
author: string;
|
|
14
|
+
tags: string[][];
|
|
15
|
+
routingDecision: RoutingDecision;
|
|
16
|
+
targetProjectId: string | null;
|
|
17
|
+
routingMethod: RoutingMethod;
|
|
18
|
+
matchedTags: string[];
|
|
19
|
+
runtimeAction: RuntimeAction;
|
|
20
|
+
reason: string | null;
|
|
21
|
+
contentPreview?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface SubscriptionFilterLogEntry {
|
|
25
|
+
timestamp: string;
|
|
26
|
+
type: "subscription_filter_update";
|
|
27
|
+
filters: NDKFilter[];
|
|
28
|
+
filterCount: number;
|
|
29
|
+
whitelistedAuthors: number;
|
|
30
|
+
trackedProjects: number;
|
|
31
|
+
trackedAgents: number;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Logger for event routing decisions in the daemon.
|
|
36
|
+
* Creates JSONL files with complete audit trail of all routing decisions.
|
|
37
|
+
*/
|
|
38
|
+
export class EventRoutingLogger {
|
|
39
|
+
private logDir: string | null = null;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Initialize the logger with the daemon directory
|
|
43
|
+
*/
|
|
44
|
+
initialize(daemonDir: string): void {
|
|
45
|
+
this.logDir = join(daemonDir, "logs", "routing");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Check if the logger has been initialized
|
|
50
|
+
*/
|
|
51
|
+
isInitialized(): boolean {
|
|
52
|
+
return this.logDir !== null;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
private async ensureLogDirectory(): Promise<void> {
|
|
56
|
+
if (!this.logDir) {
|
|
57
|
+
throw new Error("[EventRoutingLogger] Not initialized. Call initialize() first.");
|
|
58
|
+
}
|
|
59
|
+
try {
|
|
60
|
+
await fs.mkdir(this.logDir, { recursive: true });
|
|
61
|
+
} catch (error) {
|
|
62
|
+
if (error instanceof Error && "code" in error && error.code !== "EEXIST") {
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
private getLogFileName(): string {
|
|
69
|
+
const now = new Date();
|
|
70
|
+
const date = now.toISOString().split("T")[0];
|
|
71
|
+
const hours = now.getHours();
|
|
72
|
+
const minutes = now.getMinutes();
|
|
73
|
+
// Round down to nearest 5-minute increment
|
|
74
|
+
const roundedMinutes = Math.floor(minutes / 5) * 5;
|
|
75
|
+
const timeStr = `${hours.toString().padStart(2, "0")}:${roundedMinutes.toString().padStart(2, "0")}`;
|
|
76
|
+
return `${date}_${timeStr}.jsonl`;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
private getLogFilePath(filename: string): string {
|
|
80
|
+
if (!this.logDir) {
|
|
81
|
+
throw new Error("[EventRoutingLogger] Not initialized. Call initialize() first.");
|
|
82
|
+
}
|
|
83
|
+
return join(this.logDir, filename);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Log an event routing decision
|
|
88
|
+
*/
|
|
89
|
+
async logRoutingDecision(params: {
|
|
90
|
+
event: NDKEvent;
|
|
91
|
+
routingDecision: RoutingDecision;
|
|
92
|
+
targetProjectId: string | null;
|
|
93
|
+
routingMethod: RoutingMethod;
|
|
94
|
+
matchedTags?: string[];
|
|
95
|
+
runtimeAction?: RuntimeAction;
|
|
96
|
+
reason?: string;
|
|
97
|
+
}): Promise<void> {
|
|
98
|
+
if (!this.isInitialized()) {
|
|
99
|
+
console.warn("[EventRoutingLogger] Not initialized. Skipping log.");
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
await this.ensureLogDirectory();
|
|
104
|
+
|
|
105
|
+
const logEntry: EventRoutingLogEntry = {
|
|
106
|
+
timestamp: new Date().toISOString(),
|
|
107
|
+
eventId: params.event.id,
|
|
108
|
+
kind: params.event.kind || 0,
|
|
109
|
+
author: params.event.pubkey,
|
|
110
|
+
tags: params.event.tags,
|
|
111
|
+
routingDecision: params.routingDecision,
|
|
112
|
+
targetProjectId: params.targetProjectId,
|
|
113
|
+
routingMethod: params.routingMethod,
|
|
114
|
+
matchedTags: params.matchedTags || [],
|
|
115
|
+
runtimeAction: params.runtimeAction || "none",
|
|
116
|
+
reason: params.reason || null,
|
|
117
|
+
contentPreview: params.event.content?.slice(0, 100) || undefined,
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const filename = this.getLogFileName();
|
|
121
|
+
const filepath = this.getLogFilePath(filename);
|
|
122
|
+
|
|
123
|
+
try {
|
|
124
|
+
// Append to JSONL file (one JSON object per line)
|
|
125
|
+
await fs.appendFile(filepath, `${JSON.stringify(logEntry)}\n`, "utf-8");
|
|
126
|
+
} catch (error) {
|
|
127
|
+
console.error("[EventRoutingLogger] Failed to write log:", error);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Log subscription filter updates
|
|
133
|
+
*/
|
|
134
|
+
async logSubscriptionFilters(params: {
|
|
135
|
+
filters: NDKFilter[];
|
|
136
|
+
whitelistedAuthors: number;
|
|
137
|
+
trackedProjects: number;
|
|
138
|
+
trackedAgents: number;
|
|
139
|
+
}): Promise<void> {
|
|
140
|
+
if (!this.isInitialized()) {
|
|
141
|
+
console.warn("[EventRoutingLogger] Not initialized. Skipping filter log.");
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
await this.ensureLogDirectory();
|
|
146
|
+
|
|
147
|
+
const logEntry: SubscriptionFilterLogEntry = {
|
|
148
|
+
timestamp: new Date().toISOString(),
|
|
149
|
+
type: "subscription_filter_update",
|
|
150
|
+
filters: params.filters,
|
|
151
|
+
filterCount: params.filters.length,
|
|
152
|
+
whitelistedAuthors: params.whitelistedAuthors,
|
|
153
|
+
trackedProjects: params.trackedProjects,
|
|
154
|
+
trackedAgents: params.trackedAgents,
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
const filename = this.getLogFileName();
|
|
158
|
+
const filepath = this.getLogFilePath(filename);
|
|
159
|
+
|
|
160
|
+
try {
|
|
161
|
+
// Append to JSONL file (one JSON object per line)
|
|
162
|
+
await fs.appendFile(filepath, `${JSON.stringify(logEntry)}\n`, "utf-8");
|
|
163
|
+
} catch (error) {
|
|
164
|
+
console.error("[EventRoutingLogger] Failed to write filter log:", error);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Get recent log files
|
|
170
|
+
*/
|
|
171
|
+
async getRecentLogs(limit = 10): Promise<string[]> {
|
|
172
|
+
if (!this.logDir) {
|
|
173
|
+
console.warn("[EventRoutingLogger] Not initialized. Cannot get recent logs.");
|
|
174
|
+
return [];
|
|
175
|
+
}
|
|
176
|
+
try {
|
|
177
|
+
await this.ensureLogDirectory();
|
|
178
|
+
const files = await fs.readdir(this.logDir);
|
|
179
|
+
const jsonlFiles = files
|
|
180
|
+
.filter((f) => f.endsWith(".jsonl"))
|
|
181
|
+
.sort()
|
|
182
|
+
.reverse()
|
|
183
|
+
.slice(0, limit);
|
|
184
|
+
return jsonlFiles.map((f) => this.getLogFilePath(f));
|
|
185
|
+
} catch (error) {
|
|
186
|
+
console.error("[EventRoutingLogger] Failed to list logs:", error);
|
|
187
|
+
return [];
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Read a specific log file (JSONL format)
|
|
193
|
+
*/
|
|
194
|
+
async readLog(filename: string): Promise<EventRoutingLogEntry[] | null> {
|
|
195
|
+
try {
|
|
196
|
+
const filepath = this.getLogFilePath(filename);
|
|
197
|
+
const content = await fs.readFile(filepath, "utf-8");
|
|
198
|
+
const lines = content.split("\n").filter((line) => line.trim());
|
|
199
|
+
return lines.map((line) => JSON.parse(line));
|
|
200
|
+
} catch (error) {
|
|
201
|
+
console.error(`[EventRoutingLogger] Failed to read log ${filename}:`, error);
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
import type { AgentInstance } from "@/agents/types";
|
|
2
|
+
import { NDKKind } from "@/nostr/kinds";
|
|
3
|
+
import { getProjectContext } from "@/services/projects";
|
|
4
|
+
import type { NDKEvent } from "@nostr-dev-kit/ndk";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* AgentEventDecoder - Utilities for decoding and analyzing Nostr events
|
|
8
|
+
*
|
|
9
|
+
* This class provides static methods for extracting information from Nostr events
|
|
10
|
+
* and determining their types, targets, and relationships.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
// biome-ignore lint/complexity/noStaticOnlyClass: Static utility class for decoding event semantics
|
|
14
|
+
export class AgentEventDecoder {
|
|
15
|
+
/**
|
|
16
|
+
* Check if an event is directed to the system (project or agents)
|
|
17
|
+
*/
|
|
18
|
+
static isDirectedToSystem(event: NDKEvent, systemAgents: Map<string, AgentInstance>): boolean {
|
|
19
|
+
const pTags = event.tags.filter((tag) => tag[0] === "p");
|
|
20
|
+
if (pTags.length === 0) return false;
|
|
21
|
+
|
|
22
|
+
const mentionedPubkeys = pTags
|
|
23
|
+
.map((tag) => tag[1])
|
|
24
|
+
.filter((pubkey): pubkey is string => !!pubkey);
|
|
25
|
+
|
|
26
|
+
const systemPubkeys = new Set([...Array.from(systemAgents.values()).map((a) => a.pubkey)]);
|
|
27
|
+
|
|
28
|
+
// Add project manager pubkey if available
|
|
29
|
+
const projectCtx = getProjectContext();
|
|
30
|
+
if (projectCtx.projectManager?.pubkey) {
|
|
31
|
+
systemPubkeys.add(projectCtx.projectManager.pubkey);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return mentionedPubkeys.some((pubkey) => systemPubkeys.has(pubkey));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Check if event is from an agent in the system
|
|
39
|
+
*/
|
|
40
|
+
static isEventFromAgent(event: NDKEvent, systemAgents: Map<string, AgentInstance>): boolean {
|
|
41
|
+
const agentPubkeys = new Set(Array.from(systemAgents.values()).map((a) => a.pubkey));
|
|
42
|
+
return agentPubkeys.has(event.pubkey);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Get the event ID this event is replying to (if any).
|
|
47
|
+
* For kind:1 events, this is the 'e' tag value.
|
|
48
|
+
*/
|
|
49
|
+
static getReplyTarget(event: NDKEvent): string | undefined {
|
|
50
|
+
return event.tagValue("e");
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Get mentioned pubkeys from event
|
|
55
|
+
*/
|
|
56
|
+
static getMentionedPubkeys(event: NDKEvent): string[] {
|
|
57
|
+
return event.tags
|
|
58
|
+
.filter((tag) => tag[0] === "p")
|
|
59
|
+
.map((tag) => tag[1])
|
|
60
|
+
.filter((pubkey): pubkey is string => !!pubkey);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Check if this is an agent's internal message (completion, delegation, etc)
|
|
65
|
+
*/
|
|
66
|
+
static isAgentInternalMessage(event: NDKEvent): boolean {
|
|
67
|
+
// Events with tool tags are internal agent operations
|
|
68
|
+
if (event.tagValue("tool")) {
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Status events are internal
|
|
73
|
+
if (event.tagValue("status")) {
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Check if event is a delegation request (kind:1 from agent to agent)
|
|
82
|
+
*/
|
|
83
|
+
static isDelegationRequest(
|
|
84
|
+
event: NDKEvent,
|
|
85
|
+
systemAgents?: Map<string, AgentInstance>
|
|
86
|
+
): boolean {
|
|
87
|
+
if (event.kind !== 1) return false;
|
|
88
|
+
|
|
89
|
+
// If we have system agents, verify it's from an agent
|
|
90
|
+
if (systemAgents) {
|
|
91
|
+
const isFromAgent = AgentEventDecoder.isEventFromAgent(event, systemAgents);
|
|
92
|
+
if (!isFromAgent) return false;
|
|
93
|
+
|
|
94
|
+
// Check if p-tag points to another agent
|
|
95
|
+
const pTag = event.tagValue("p");
|
|
96
|
+
if (pTag && Array.from(systemAgents.values()).some((a) => a.pubkey === pTag)) {
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
} else {
|
|
100
|
+
// Fallback: just check if it has a p-tag (less accurate)
|
|
101
|
+
return !!event.tagValue("p");
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Check if event is a delegation completion (kind:1 with status:completed)
|
|
109
|
+
*/
|
|
110
|
+
static isDelegationCompletion(event: NDKEvent): boolean {
|
|
111
|
+
return event.kind === 1 && event.tagValue("status") === "completed";
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Get the delegation request ID from a completion event
|
|
116
|
+
* Checks all e-tags to find the first valid delegation request ID
|
|
117
|
+
*/
|
|
118
|
+
static getDelegationRequestId(event: NDKEvent): string | undefined {
|
|
119
|
+
if (AgentEventDecoder.isDelegationCompletion(event)) {
|
|
120
|
+
// Check all e-tags to find a delegation request ID
|
|
121
|
+
// For explicit completions, we return the first e-tag as the most likely candidate
|
|
122
|
+
// The DelegationCompletionHandler will validate if it's actually a tracked delegation
|
|
123
|
+
const eTags = event.getMatchingTags("e");
|
|
124
|
+
if (eTags.length > 0 && eTags[0][1]) {
|
|
125
|
+
return eTags[0][1]; // Return the first e-tag value
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return undefined;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Check if event is a status event
|
|
133
|
+
*/
|
|
134
|
+
static isStatusEvent(event: NDKEvent): boolean {
|
|
135
|
+
return event.kind === NDKKind.TenexProjectStatus;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Extract error type from error event
|
|
140
|
+
*/
|
|
141
|
+
static getErrorType(event: NDKEvent): string | undefined {
|
|
142
|
+
return event.tagValue("error");
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Check if event has a specific tool tag
|
|
147
|
+
*/
|
|
148
|
+
static hasTool(event: NDKEvent, toolName: string): boolean {
|
|
149
|
+
return event.tagValue("tool") === toolName;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Get all tool tags from event
|
|
154
|
+
*/
|
|
155
|
+
static getToolTags(event: NDKEvent): Array<{ name: string; args?: unknown }> {
|
|
156
|
+
return event.tags
|
|
157
|
+
.filter((tag) => tag[0] === "tool")
|
|
158
|
+
.map((tag) => ({
|
|
159
|
+
name: tag[1],
|
|
160
|
+
args: tag[2] ? JSON.parse(tag[2]) : undefined,
|
|
161
|
+
}));
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Get participant pubkeys from an event
|
|
166
|
+
* Participants are specified in "participant" tags
|
|
167
|
+
*/
|
|
168
|
+
static getParticipants(event: NDKEvent): string[] {
|
|
169
|
+
// Get all participant tags
|
|
170
|
+
const participantTags = event.tags.filter((tag) => tag[0] === "participant");
|
|
171
|
+
return participantTags.map((tag) => tag[1]).filter((pubkey) => !!pubkey);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Extract nudge event IDs from event tags
|
|
176
|
+
* Returns an array of event IDs from all ['nudge', '<id>'] tags
|
|
177
|
+
*/
|
|
178
|
+
static extractNudgeEventIds(event: NDKEvent): string[] {
|
|
179
|
+
return event.tags
|
|
180
|
+
.filter((tag) => tag[0] === "nudge")
|
|
181
|
+
.map((tag) => tag[1])
|
|
182
|
+
.filter((id): id is string => !!id);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Extract skill event IDs from event tags
|
|
187
|
+
* Returns an array of event IDs from all ['skill', '<id>'] tags
|
|
188
|
+
*/
|
|
189
|
+
static extractSkillEventIds(event: NDKEvent): string[] {
|
|
190
|
+
return event.tags
|
|
191
|
+
.filter((tag) => tag[0] === "skill")
|
|
192
|
+
.map((tag) => tag[1])
|
|
193
|
+
.filter((id): id is string => !!id);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// ============================================================================
|
|
197
|
+
// Daemon-specific event classification methods
|
|
198
|
+
// These are used by the daemon for routing and filtering decisions
|
|
199
|
+
// ============================================================================
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Event kinds that should never be routed to projects.
|
|
203
|
+
* These events are informational or transient and don't require processing.
|
|
204
|
+
* - kind:0 (Metadata) and kind:3 (Contacts) are global identity events
|
|
205
|
+
* - Status events are daemon-level only
|
|
206
|
+
*/
|
|
207
|
+
private static readonly NEVER_ROUTE_EVENT_KINDS = [
|
|
208
|
+
NDKKind.Metadata, // kind:0 - user profile metadata
|
|
209
|
+
NDKKind.Contacts, // kind:3 - contact list
|
|
210
|
+
NDKKind.TenexProjectStatus,
|
|
211
|
+
NDKKind.TenexOperationsStatus,
|
|
212
|
+
];
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Check if an event kind should never be routed to projects
|
|
216
|
+
* @param event - The event to check
|
|
217
|
+
* @returns True if the event should not be routed
|
|
218
|
+
*/
|
|
219
|
+
static isNeverRouteKind(event: NDKEvent): boolean {
|
|
220
|
+
return event.kind !== undefined && this.NEVER_ROUTE_EVENT_KINDS.includes(event.kind);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Check if this is a project event (kind 31933)
|
|
225
|
+
* @param event - The event to check
|
|
226
|
+
* @returns True if this is a project creation/update event
|
|
227
|
+
*/
|
|
228
|
+
static isProjectEvent(event: NDKEvent): boolean {
|
|
229
|
+
return event.kind === 31933;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Check if this is a lesson event (kind 4129)
|
|
234
|
+
* @param event - The event to check
|
|
235
|
+
* @returns True if this is an agent lesson event
|
|
236
|
+
*/
|
|
237
|
+
static isLessonEvent(event: NDKEvent): boolean {
|
|
238
|
+
return event.kind === NDKKind.AgentLesson;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Extract project ID from a project event
|
|
243
|
+
* Format: "31933:authorPubkey:dTag"
|
|
244
|
+
* @param event - Project event (kind 31933)
|
|
245
|
+
* @returns Project ID string or null if not a valid project event
|
|
246
|
+
*/
|
|
247
|
+
static extractProjectId(event: NDKEvent): string | null {
|
|
248
|
+
if (!this.isProjectEvent(event)) {
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const dTag = event.tags.find((t) => t[0] === "d")?.[1];
|
|
253
|
+
if (!dTag) {
|
|
254
|
+
return null;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
return `31933:${event.pubkey}:${dTag}`;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Extract agent definition ID from a lesson event
|
|
262
|
+
* @param event - Lesson event (kind 4129)
|
|
263
|
+
* @returns Agent definition event ID or null
|
|
264
|
+
*/
|
|
265
|
+
static extractAgentDefinitionIdFromLesson(event: NDKEvent): string | null {
|
|
266
|
+
if (!this.isLessonEvent(event)) {
|
|
267
|
+
return null;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Lesson events reference agent definitions via e-tag
|
|
271
|
+
const eTag = event.tags.find((t) => t[0] === "e")?.[1];
|
|
272
|
+
return eTag || null;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Check if event has project A-tags
|
|
277
|
+
* @param event - The event to check
|
|
278
|
+
* @returns True if event has A-tags referencing projects (31933:...)
|
|
279
|
+
*/
|
|
280
|
+
static hasProjectATags(event: NDKEvent): boolean {
|
|
281
|
+
const aTags = event.tags.filter((t) => t[0] === "a");
|
|
282
|
+
return aTags.some((t) => t[1]?.startsWith("31933:"));
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Extract project A-tags from an event
|
|
287
|
+
* @param event - The event to analyze
|
|
288
|
+
* @returns Array of project IDs from A-tags
|
|
289
|
+
*/
|
|
290
|
+
static extractProjectATags(event: NDKEvent): string[] {
|
|
291
|
+
const aTags = event.tags.filter((t) => t[0] === "a");
|
|
292
|
+
return aTags
|
|
293
|
+
.filter((t) => t[1]?.startsWith("31933:"))
|
|
294
|
+
.map((t) => t[1])
|
|
295
|
+
.filter((id): id is string => !!id);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Classify event type for daemon routing
|
|
300
|
+
* @param event - The event to classify
|
|
301
|
+
* @returns Event classification for routing decisions
|
|
302
|
+
*/
|
|
303
|
+
static classifyForDaemon(
|
|
304
|
+
event: NDKEvent
|
|
305
|
+
): "never_route" | "project" | "lesson" | "lesson_comment" | "conversation" | "boot" | "unknown" {
|
|
306
|
+
if (this.isNeverRouteKind(event)) return "never_route";
|
|
307
|
+
if (this.isProjectEvent(event)) return "project";
|
|
308
|
+
if (this.isLessonEvent(event)) return "lesson";
|
|
309
|
+
if (this.isLessonCommentEvent(event)) return "lesson_comment";
|
|
310
|
+
if (event.kind === NDKKind.Text) {
|
|
311
|
+
return "conversation";
|
|
312
|
+
}
|
|
313
|
+
if (event.kind === NDKKind.TenexBootProject) {
|
|
314
|
+
return "boot";
|
|
315
|
+
}
|
|
316
|
+
return "unknown";
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Check if an event is a lesson comment (kind NDKKind.Comment with #K: [NDKKind.AgentLesson])
|
|
321
|
+
* @param event - The event to check
|
|
322
|
+
* @returns True if this is a lesson comment event
|
|
323
|
+
*/
|
|
324
|
+
static isLessonCommentEvent(event: NDKEvent): boolean {
|
|
325
|
+
if (event.kind !== NDKKind.Comment) return false;
|
|
326
|
+
// NIP-22: #K tag indicates the kind of the root event
|
|
327
|
+
const kTag = event.tagValue("K");
|
|
328
|
+
return kTag === String(NDKKind.AgentLesson); // Comments on lessons
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Check if an event is a config update
|
|
333
|
+
* @param event - The event to check
|
|
334
|
+
* @returns True if this is a config update event
|
|
335
|
+
*/
|
|
336
|
+
static isConfigUpdate(event: NDKEvent): boolean {
|
|
337
|
+
return event.kind === NDKKind.TenexAgentConfigUpdate;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Check if an event is a metadata event
|
|
342
|
+
* @param event - The event to check
|
|
343
|
+
* @returns True if this is a metadata event
|
|
344
|
+
*/
|
|
345
|
+
static isMetadata(event: NDKEvent): boolean {
|
|
346
|
+
return event.kind === NDKKind.Metadata;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Check if an event is a stop command
|
|
351
|
+
* @param event - The event to check
|
|
352
|
+
* @returns True if this is a stop command event
|
|
353
|
+
*/
|
|
354
|
+
static isStopCommand(event: NDKEvent): boolean {
|
|
355
|
+
return event.kind === NDKKind.TenexStopCommand;
|
|
356
|
+
}
|
|
357
|
+
}
|