@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.
Files changed (427) hide show
  1. package/README.md +194 -0
  2. package/dist/backend-wrapper.cjs +3 -0
  3. package/dist/src/index.js +331928 -0
  4. package/package.json +103 -0
  5. package/src/agents/AgentRegistry.ts +418 -0
  6. package/src/agents/AgentStorage.ts +1133 -0
  7. package/src/agents/ConfigResolver.ts +229 -0
  8. package/src/agents/agent-installer.ts +236 -0
  9. package/src/agents/agent-loader.ts +241 -0
  10. package/src/agents/constants.ts +82 -0
  11. package/src/agents/errors.ts +48 -0
  12. package/src/agents/execution/AgentExecutor.ts +561 -0
  13. package/src/agents/execution/ExecutionContextFactory.ts +112 -0
  14. package/src/agents/execution/MessageCompiler.ts +597 -0
  15. package/src/agents/execution/MessageSyncer.ts +100 -0
  16. package/src/agents/execution/PostCompletionChecker.ts +278 -0
  17. package/src/agents/execution/ProgressMonitor.ts +50 -0
  18. package/src/agents/execution/RALResolver.ts +177 -0
  19. package/src/agents/execution/SessionManager.ts +181 -0
  20. package/src/agents/execution/StreamCallbacks.ts +312 -0
  21. package/src/agents/execution/StreamExecutionHandler.ts +579 -0
  22. package/src/agents/execution/StreamSetup.ts +313 -0
  23. package/src/agents/execution/ToolEventHandlers.ts +239 -0
  24. package/src/agents/execution/ToolExecutionTracker.ts +498 -0
  25. package/src/agents/execution/ToolResultUtils.ts +97 -0
  26. package/src/agents/execution/ToolSupervisionWrapper.ts +174 -0
  27. package/src/agents/execution/constants.ts +16 -0
  28. package/src/agents/execution/index.ts +3 -0
  29. package/src/agents/execution/types.ts +96 -0
  30. package/src/agents/execution/utils.ts +26 -0
  31. package/src/agents/index.ts +4 -0
  32. package/src/agents/script-installer.ts +266 -0
  33. package/src/agents/supervision/SupervisorLLMService.ts +253 -0
  34. package/src/agents/supervision/SupervisorOrchestrator.ts +471 -0
  35. package/src/agents/supervision/heuristics/ConsecutiveToolsWithoutTodoHeuristic.ts +73 -0
  36. package/src/agents/supervision/heuristics/DelegationClaimHeuristic.ts +80 -0
  37. package/src/agents/supervision/heuristics/HeuristicRegistry.ts +114 -0
  38. package/src/agents/supervision/heuristics/PendingTodosHeuristic.ts +93 -0
  39. package/src/agents/supervision/heuristics/SilentAgentHeuristic.ts +54 -0
  40. package/src/agents/supervision/heuristics/index.ts +5 -0
  41. package/src/agents/supervision/index.ts +28 -0
  42. package/src/agents/supervision/registerHeuristics.ts +110 -0
  43. package/src/agents/supervision/supervisionHealthCheck.ts +123 -0
  44. package/src/agents/supervision/types.ts +171 -0
  45. package/src/agents/tool-names.ts +46 -0
  46. package/src/agents/tool-normalization.ts +184 -0
  47. package/src/agents/types/index.ts +2 -0
  48. package/src/agents/types/runtime.ts +74 -0
  49. package/src/agents/types/storage.ts +145 -0
  50. package/src/commands/agent/import/index.ts +6 -0
  51. package/src/commands/agent/import/openclaw-distiller.ts +57 -0
  52. package/src/commands/agent/import/openclaw-reader.ts +141 -0
  53. package/src/commands/agent/import/openclaw.ts +154 -0
  54. package/src/commands/agent/index.ts +6 -0
  55. package/src/commands/agent.ts +215 -0
  56. package/src/commands/daemon.ts +198 -0
  57. package/src/commands/doctor.ts +134 -0
  58. package/src/commands/setup/embed.ts +228 -0
  59. package/src/commands/setup/global-system-prompt.ts +223 -0
  60. package/src/commands/setup/image.ts +179 -0
  61. package/src/commands/setup/index.ts +16 -0
  62. package/src/commands/setup/interactive.ts +95 -0
  63. package/src/commands/setup/llm.ts +38 -0
  64. package/src/commands/setup/onboarding.ts +294 -0
  65. package/src/commands/setup/providers.ts +27 -0
  66. package/src/constants.ts +34 -0
  67. package/src/conversations/ConversationDiskReader.ts +148 -0
  68. package/src/conversations/ConversationRegistry.ts +728 -0
  69. package/src/conversations/ConversationStore.ts +868 -0
  70. package/src/conversations/MessageBuilder.ts +866 -0
  71. package/src/conversations/executionTime.ts +62 -0
  72. package/src/conversations/formatters/DelegationXmlFormatter.ts +64 -0
  73. package/src/conversations/formatters/ThreadedConversationFormatter.ts +303 -0
  74. package/src/conversations/formatters/index.ts +9 -0
  75. package/src/conversations/formatters/utils/MessageFormatter.ts +46 -0
  76. package/src/conversations/formatters/utils/TimestampFormatter.ts +56 -0
  77. package/src/conversations/formatters/utils/TreeBuilder.ts +131 -0
  78. package/src/conversations/formatters/utils/TreeRenderer.ts +49 -0
  79. package/src/conversations/index.ts +2 -0
  80. package/src/conversations/persistence/ToolMessageStorage.ts +143 -0
  81. package/src/conversations/search/ConversationIndexManager.ts +393 -0
  82. package/src/conversations/search/QueryParser.ts +114 -0
  83. package/src/conversations/search/SearchEngine.ts +175 -0
  84. package/src/conversations/search/SnippetExtractor.ts +345 -0
  85. package/src/conversations/search/embeddings/ConversationEmbeddingService.ts +484 -0
  86. package/src/conversations/search/embeddings/ConversationIndexingJob.ts +320 -0
  87. package/src/conversations/search/embeddings/IndexingStateManager.ts +338 -0
  88. package/src/conversations/search/embeddings/index.ts +18 -0
  89. package/src/conversations/search/index.ts +49 -0
  90. package/src/conversations/search/types.ts +124 -0
  91. package/src/conversations/services/CategoryManager.ts +160 -0
  92. package/src/conversations/services/ConversationResolver.ts +296 -0
  93. package/src/conversations/services/ConversationSummarizer.ts +234 -0
  94. package/src/conversations/services/MetadataDebounceManager.ts +188 -0
  95. package/src/conversations/services/index.ts +2 -0
  96. package/src/conversations/types.ts +148 -0
  97. package/src/conversations/utils/content-utils.ts +69 -0
  98. package/src/conversations/utils/image-placeholder.ts +281 -0
  99. package/src/conversations/utils/image-url-utils.ts +171 -0
  100. package/src/conversations/utils/multimodal-content.ts +90 -0
  101. package/src/conversations/utils/tool-result-truncator.ts +159 -0
  102. package/src/daemon/Daemon.ts +1883 -0
  103. package/src/daemon/ProjectRuntime.ts +657 -0
  104. package/src/daemon/RestartState.ts +152 -0
  105. package/src/daemon/RuntimeLifecycle.ts +268 -0
  106. package/src/daemon/SubscriptionManager.ts +305 -0
  107. package/src/daemon/UnixSocketTransport.ts +318 -0
  108. package/src/daemon/filters/SubscriptionFilterBuilder.ts +119 -0
  109. package/src/daemon/index.ts +9 -0
  110. package/src/daemon/routing/DaemonRouter.ts +491 -0
  111. package/src/daemon/types.ts +150 -0
  112. package/src/daemon/utils/routing-log.ts +76 -0
  113. package/src/daemon/utils/telemetry.ts +173 -0
  114. package/src/event-handler/agentDeletion.ts +383 -0
  115. package/src/event-handler/index.ts +749 -0
  116. package/src/event-handler/newConversation.ts +165 -0
  117. package/src/event-handler/project.ts +166 -0
  118. package/src/event-handler/reply.ts +18 -0
  119. package/src/events/NDKAgentDefinition.ts +292 -0
  120. package/src/events/NDKAgentLesson.ts +106 -0
  121. package/src/events/NDKEventMetadata.ts +34 -0
  122. package/src/events/NDKMCPTool.ts +60 -0
  123. package/src/events/NDKProjectStatus.ts +384 -0
  124. package/src/events/index.ts +4 -0
  125. package/src/index.ts +126 -0
  126. package/src/lib/agent-home.ts +334 -0
  127. package/src/lib/error-formatter.ts +200 -0
  128. package/src/lib/fs/filesystem.ts +128 -0
  129. package/src/lib/fs/index.ts +1 -0
  130. package/src/lib/json-parser.ts +30 -0
  131. package/src/lib/string.ts +15 -0
  132. package/src/lib/time.ts +74 -0
  133. package/src/llm/ChunkHandler.ts +277 -0
  134. package/src/llm/FinishHandler.ts +250 -0
  135. package/src/llm/LLMConfigEditor.ts +154 -0
  136. package/src/llm/LLMServiceFactory.ts +230 -0
  137. package/src/llm/MessageProcessor.ts +90 -0
  138. package/src/llm/RecordingState.ts +37 -0
  139. package/src/llm/StreamPublisher.ts +40 -0
  140. package/src/llm/TracingUtils.ts +77 -0
  141. package/src/llm/chunk-validators.ts +57 -0
  142. package/src/llm/constants.ts +6 -0
  143. package/src/llm/index.ts +12 -0
  144. package/src/llm/meta/MetaModelResolver.ts +352 -0
  145. package/src/llm/meta/index.ts +11 -0
  146. package/src/llm/middleware/flight-recorder.ts +188 -0
  147. package/src/llm/providers/MockProvider.ts +332 -0
  148. package/src/llm/providers/agent/ClaudeCodeProvider.ts +343 -0
  149. package/src/llm/providers/agent/ClaudeCodeToolsAdapter.ts +203 -0
  150. package/src/llm/providers/agent/CodexAppServerProvider.ts +214 -0
  151. package/src/llm/providers/agent/CodexAppServerToolsAdapter.ts +91 -0
  152. package/src/llm/providers/agent/index.ts +10 -0
  153. package/src/llm/providers/base/AgentProvider.ts +107 -0
  154. package/src/llm/providers/base/BaseProvider.ts +114 -0
  155. package/src/llm/providers/base/StandardProvider.ts +38 -0
  156. package/src/llm/providers/base/index.ts +9 -0
  157. package/src/llm/providers/index.ts +106 -0
  158. package/src/llm/providers/key-manager.ts +238 -0
  159. package/src/llm/providers/ollama-models.ts +105 -0
  160. package/src/llm/providers/openrouter-models.ts +102 -0
  161. package/src/llm/providers/provider-ids.ts +18 -0
  162. package/src/llm/providers/registry/ProviderRegistry.ts +414 -0
  163. package/src/llm/providers/registry/index.ts +7 -0
  164. package/src/llm/providers/standard/AnthropicProvider.ts +71 -0
  165. package/src/llm/providers/standard/OllamaProvider.ts +59 -0
  166. package/src/llm/providers/standard/OpenAIProvider.ts +44 -0
  167. package/src/llm/providers/standard/OpenRouterProvider.ts +103 -0
  168. package/src/llm/providers/standard/index.ts +10 -0
  169. package/src/llm/providers/types.ts +194 -0
  170. package/src/llm/providers/usage-metadata.ts +78 -0
  171. package/src/llm/service.ts +713 -0
  172. package/src/llm/types.ts +167 -0
  173. package/src/llm/utils/ConfigurationManager.ts +650 -0
  174. package/src/llm/utils/ConfigurationTester.ts +229 -0
  175. package/src/llm/utils/ModelSelector.ts +212 -0
  176. package/src/llm/utils/ProviderConfigUI.ts +177 -0
  177. package/src/llm/utils/claudeCodePromptCompiler.ts +141 -0
  178. package/src/llm/utils/codex-models.ts +53 -0
  179. package/src/llm/utils/context-window-cache.ts +30 -0
  180. package/src/llm/utils/models-dev-cache.ts +267 -0
  181. package/src/llm/utils/provider-setup.ts +50 -0
  182. package/src/llm/utils/tool-errors.ts +78 -0
  183. package/src/llm/utils/usage.ts +74 -0
  184. package/src/logging/EventRoutingLogger.ts +205 -0
  185. package/src/nostr/AgentEventDecoder.ts +357 -0
  186. package/src/nostr/AgentEventEncoder.ts +677 -0
  187. package/src/nostr/AgentProfilePublisher.ts +657 -0
  188. package/src/nostr/AgentPublisher.ts +437 -0
  189. package/src/nostr/BlossomService.ts +226 -0
  190. package/src/nostr/InterventionPublisher.ts +132 -0
  191. package/src/nostr/TagExtractor.ts +228 -0
  192. package/src/nostr/collectEvents.ts +83 -0
  193. package/src/nostr/constants.ts +38 -0
  194. package/src/nostr/encryption.ts +26 -0
  195. package/src/nostr/index.ts +31 -0
  196. package/src/nostr/keys.ts +17 -0
  197. package/src/nostr/kinds.ts +37 -0
  198. package/src/nostr/ndkClient.ts +72 -0
  199. package/src/nostr/relays.ts +43 -0
  200. package/src/nostr/trace-context.ts +39 -0
  201. package/src/nostr/types.ts +227 -0
  202. package/src/nostr/utils.ts +84 -0
  203. package/src/prompts/core/FragmentRegistry.ts +30 -0
  204. package/src/prompts/core/PromptBuilder.ts +98 -0
  205. package/src/prompts/core/index.ts +3 -0
  206. package/src/prompts/core/types.ts +13 -0
  207. package/src/prompts/fragments/00-global-system-prompt.ts +44 -0
  208. package/src/prompts/fragments/01-agent-identity.ts +69 -0
  209. package/src/prompts/fragments/02-agent-home-directory.ts +114 -0
  210. package/src/prompts/fragments/03-system-reminders-explanation.ts +14 -0
  211. package/src/prompts/fragments/04-relay-configuration.ts +38 -0
  212. package/src/prompts/fragments/05-delegation-chain.ts +45 -0
  213. package/src/prompts/fragments/06-agent-todos.ts +74 -0
  214. package/src/prompts/fragments/06-todo-usage-guidance.ts +34 -0
  215. package/src/prompts/fragments/07-meta-project-context.ts +234 -0
  216. package/src/prompts/fragments/08-active-conversations.ts +382 -0
  217. package/src/prompts/fragments/09-recent-conversations.ts +153 -0
  218. package/src/prompts/fragments/10-referenced-article.ts +21 -0
  219. package/src/prompts/fragments/11-nudges.ts +134 -0
  220. package/src/prompts/fragments/12-skills.ts +127 -0
  221. package/src/prompts/fragments/13-available-nudges.ts +122 -0
  222. package/src/prompts/fragments/15-available-agents.ts +53 -0
  223. package/src/prompts/fragments/16-stay-in-your-lane.ts +41 -0
  224. package/src/prompts/fragments/17-todo-before-delegation.ts +39 -0
  225. package/src/prompts/fragments/20-voice-mode.ts +62 -0
  226. package/src/prompts/fragments/22-scheduled-tasks.ts +175 -0
  227. package/src/prompts/fragments/24-retrieved-lessons.ts +26 -0
  228. package/src/prompts/fragments/25-rag-instructions.ts +333 -0
  229. package/src/prompts/fragments/26-mcp-resources.ts +237 -0
  230. package/src/prompts/fragments/27-memorized-reports.ts +77 -0
  231. package/src/prompts/fragments/28-agent-directed-monitoring.ts +32 -0
  232. package/src/prompts/fragments/29-rag-collections.ts +50 -0
  233. package/src/prompts/fragments/30-worktree-context.ts +98 -0
  234. package/src/prompts/fragments/31-agents-md-guidance.ts +96 -0
  235. package/src/prompts/fragments/32-process-metrics.ts +72 -0
  236. package/src/prompts/fragments/debug-mode.ts +48 -0
  237. package/src/prompts/fragments/delegation-completion.ts +44 -0
  238. package/src/prompts/fragments/index.ts +91 -0
  239. package/src/prompts/index.ts +21 -0
  240. package/src/prompts/utils/systemPromptBuilder.ts +777 -0
  241. package/src/scripts/migrate-prefix-index.ts +157 -0
  242. package/src/services/AgentDefinitionMonitor.ts +701 -0
  243. package/src/services/ConfigService.ts +723 -0
  244. package/src/services/CooldownRegistry.ts +199 -0
  245. package/src/services/LLMOperationsRegistry.ts +424 -0
  246. package/src/services/OwnerAgentListService.ts +354 -0
  247. package/src/services/PubkeyService.ts +308 -0
  248. package/src/services/agents/AgentMetadataStore.ts +72 -0
  249. package/src/services/agents/AgentResolution.ts +59 -0
  250. package/src/services/agents/EscalationService.ts +281 -0
  251. package/src/services/agents/NDKAgentDiscovery.ts +95 -0
  252. package/src/services/agents/index.ts +7 -0
  253. package/src/services/agents-md/AgentsMdService.ts +184 -0
  254. package/src/services/agents-md/SystemReminderInjector.ts +238 -0
  255. package/src/services/agents-md/index.ts +11 -0
  256. package/src/services/apns/APNsClient.ts +203 -0
  257. package/src/services/apns/APNsService.ts +358 -0
  258. package/src/services/apns/index.ts +11 -0
  259. package/src/services/apns/types.ts +80 -0
  260. package/src/services/compression/CompressionService.ts +445 -0
  261. package/src/services/compression/compression-schema.ts +28 -0
  262. package/src/services/compression/compression-types.ts +74 -0
  263. package/src/services/compression/compression-utils.ts +587 -0
  264. package/src/services/config/types.ts +394 -0
  265. package/src/services/dispatch/AgentDispatchService.ts +937 -0
  266. package/src/services/dispatch/AgentRouter.ts +181 -0
  267. package/src/services/dispatch/DelegationCompletionHandler.ts +232 -0
  268. package/src/services/embedding/EmbeddingProvider.ts +188 -0
  269. package/src/services/embedding/index.ts +5 -0
  270. package/src/services/event-context/EventContextService.ts +108 -0
  271. package/src/services/event-context/index.ts +2 -0
  272. package/src/services/heuristics/ContextBuilder.ts +106 -0
  273. package/src/services/heuristics/HeuristicEngine.ts +200 -0
  274. package/src/services/heuristics/formatters.ts +58 -0
  275. package/src/services/heuristics/index.ts +12 -0
  276. package/src/services/heuristics/rules/index.ts +25 -0
  277. package/src/services/heuristics/rules/todoBeforeDelegation.ts +69 -0
  278. package/src/services/heuristics/rules/todoReminderOnToolUse.ts +63 -0
  279. package/src/services/heuristics/types.ts +144 -0
  280. package/src/services/image/ImageGenerationService.ts +389 -0
  281. package/src/services/image/index.ts +12 -0
  282. package/src/services/intervention/InterventionService.ts +1352 -0
  283. package/src/services/intervention/index.ts +7 -0
  284. package/src/services/mcp/MCPManager.ts +683 -0
  285. package/src/services/mcp/McpNotificationDelivery.ts +139 -0
  286. package/src/services/mcp/McpSubscriptionService.ts +653 -0
  287. package/src/services/mcp/mcpInstaller.ts +130 -0
  288. package/src/services/nip46/Nip46SigningLog.ts +81 -0
  289. package/src/services/nip46/Nip46SigningService.ts +467 -0
  290. package/src/services/nip46/index.ts +4 -0
  291. package/src/services/nudge/NudgeService.ts +224 -0
  292. package/src/services/nudge/NudgeWhitelistService.ts +382 -0
  293. package/src/services/nudge/index.ts +5 -0
  294. package/src/services/nudge/types.ts +83 -0
  295. package/src/services/projects/ProjectContext.ts +672 -0
  296. package/src/services/projects/ProjectContextStore.ts +102 -0
  297. package/src/services/projects/index.ts +6 -0
  298. package/src/services/prompt-compiler/index.ts +15 -0
  299. package/src/services/prompt-compiler/prompt-compiler-service.ts +1143 -0
  300. package/src/services/pubkey-gate/PubkeyGateService.ts +93 -0
  301. package/src/services/pubkey-gate/index.ts +1 -0
  302. package/src/services/rag/EmbeddingProviderFactory.ts +292 -0
  303. package/src/services/rag/LanceDBMaintenanceService.ts +211 -0
  304. package/src/services/rag/RAGDatabaseService.ts +173 -0
  305. package/src/services/rag/RAGOperations.ts +682 -0
  306. package/src/services/rag/RAGService.ts +240 -0
  307. package/src/services/rag/RagSubscriptionService.ts +618 -0
  308. package/src/services/rag/rag-utils.ts +174 -0
  309. package/src/services/ral/PendingDelegationsRegistry.ts +168 -0
  310. package/src/services/ral/RALRegistry.ts +2782 -0
  311. package/src/services/ral/index.ts +4 -0
  312. package/src/services/ral/types.ts +292 -0
  313. package/src/services/reports/LocalReportStore.ts +380 -0
  314. package/src/services/reports/ReportEmbeddingService.ts +430 -0
  315. package/src/services/reports/ReportService.ts +440 -0
  316. package/src/services/reports/articleUtils.ts +52 -0
  317. package/src/services/reports/index.ts +7 -0
  318. package/src/services/scheduling/SchedulerService.ts +1057 -0
  319. package/src/services/scheduling/errors.ts +14 -0
  320. package/src/services/scheduling/index.ts +7 -0
  321. package/src/services/scheduling/utils.ts +77 -0
  322. package/src/services/search/SearchProviderRegistry.ts +78 -0
  323. package/src/services/search/UnifiedSearchService.ts +218 -0
  324. package/src/services/search/index.ts +47 -0
  325. package/src/services/search/projectFilter.ts +22 -0
  326. package/src/services/search/providers/ConversationSearchProvider.ts +48 -0
  327. package/src/services/search/providers/LessonSearchProvider.ts +75 -0
  328. package/src/services/search/providers/ReportSearchProvider.ts +49 -0
  329. package/src/services/search/types.ts +144 -0
  330. package/src/services/skill/SkillService.ts +482 -0
  331. package/src/services/skill/index.ts +2 -0
  332. package/src/services/skill/types.ts +70 -0
  333. package/src/services/status/OperationsStatusService.ts +276 -0
  334. package/src/services/status/ProjectStatusService.ts +522 -0
  335. package/src/services/status/index.ts +11 -0
  336. package/src/services/storage/PrefixKVStore.ts +242 -0
  337. package/src/services/storage/index.ts +1 -0
  338. package/src/services/system-reminder/SystemReminderUtils.ts +96 -0
  339. package/src/services/system-reminder/index.ts +7 -0
  340. package/src/services/trust-pubkeys/TrustPubkeyService.ts +325 -0
  341. package/src/services/trust-pubkeys/index.ts +2 -0
  342. package/src/telemetry/ConversationSpanManager.ts +111 -0
  343. package/src/telemetry/EventLoopMonitor.ts +206 -0
  344. package/src/telemetry/LLMSpanRegistry.ts +20 -0
  345. package/src/telemetry/NostrSpanProcessor.ts +89 -0
  346. package/src/telemetry/ToolCallSpanProcessor.ts +66 -0
  347. package/src/telemetry/diagnostics.ts +27 -0
  348. package/src/telemetry/setup.ts +120 -0
  349. package/src/tools/implementations/agents_discover.ts +121 -0
  350. package/src/tools/implementations/agents_hire.ts +127 -0
  351. package/src/tools/implementations/agents_list.ts +96 -0
  352. package/src/tools/implementations/agents_publish.ts +611 -0
  353. package/src/tools/implementations/agents_read.ts +173 -0
  354. package/src/tools/implementations/agents_write.ts +200 -0
  355. package/src/tools/implementations/ask.ts +411 -0
  356. package/src/tools/implementations/change_model.ts +141 -0
  357. package/src/tools/implementations/conversation_get.ts +661 -0
  358. package/src/tools/implementations/conversation_list.ts +377 -0
  359. package/src/tools/implementations/conversation_search.ts +370 -0
  360. package/src/tools/implementations/delegate.ts +327 -0
  361. package/src/tools/implementations/delegate_crossproject.ts +209 -0
  362. package/src/tools/implementations/delegate_followup.ts +300 -0
  363. package/src/tools/implementations/fs_edit.ts +162 -0
  364. package/src/tools/implementations/fs_glob.ts +182 -0
  365. package/src/tools/implementations/fs_grep.ts +513 -0
  366. package/src/tools/implementations/fs_read.ts +332 -0
  367. package/src/tools/implementations/fs_write.ts +113 -0
  368. package/src/tools/implementations/generate_image.ts +259 -0
  369. package/src/tools/implementations/home_fs.ts +515 -0
  370. package/src/tools/implementations/kill.ts +651 -0
  371. package/src/tools/implementations/learn.ts +166 -0
  372. package/src/tools/implementations/lesson-formatter.ts +38 -0
  373. package/src/tools/implementations/lesson_delete.ts +164 -0
  374. package/src/tools/implementations/lesson_get.ts +105 -0
  375. package/src/tools/implementations/lessons_list.ts +153 -0
  376. package/src/tools/implementations/mcp_resource_read.ts +161 -0
  377. package/src/tools/implementations/mcp_subscribe.ts +158 -0
  378. package/src/tools/implementations/mcp_subscription_stop.ts +85 -0
  379. package/src/tools/implementations/nostr_fetch.ts +149 -0
  380. package/src/tools/implementations/nostr_publish_as_user.ts +353 -0
  381. package/src/tools/implementations/project_list.ts +146 -0
  382. package/src/tools/implementations/rag_add_documents.ts +573 -0
  383. package/src/tools/implementations/rag_create_collection.ts +65 -0
  384. package/src/tools/implementations/rag_delete_collection.ts +68 -0
  385. package/src/tools/implementations/rag_list_collections.ts +77 -0
  386. package/src/tools/implementations/rag_query.ts +107 -0
  387. package/src/tools/implementations/rag_subscription_create.ts +105 -0
  388. package/src/tools/implementations/rag_subscription_delete.ts +80 -0
  389. package/src/tools/implementations/rag_subscription_get.ts +123 -0
  390. package/src/tools/implementations/rag_subscription_list.ts +128 -0
  391. package/src/tools/implementations/report_delete.ts +79 -0
  392. package/src/tools/implementations/report_read.ts +160 -0
  393. package/src/tools/implementations/report_write.ts +278 -0
  394. package/src/tools/implementations/reports_list.ts +77 -0
  395. package/src/tools/implementations/schedule_task.ts +104 -0
  396. package/src/tools/implementations/schedule_task_cancel.ts +62 -0
  397. package/src/tools/implementations/schedule_task_once.ts +128 -0
  398. package/src/tools/implementations/schedule_tasks_list.ts +79 -0
  399. package/src/tools/implementations/search.ts +160 -0
  400. package/src/tools/implementations/shell.ts +553 -0
  401. package/src/tools/implementations/todo.ts +260 -0
  402. package/src/tools/implementations/upload_blob.ts +381 -0
  403. package/src/tools/implementations/web_fetch.ts +153 -0
  404. package/src/tools/implementations/web_search.ts +250 -0
  405. package/src/tools/registry.ts +670 -0
  406. package/src/tools/types.ts +177 -0
  407. package/src/tools/utils.ts +256 -0
  408. package/src/types/event-ids.ts +320 -0
  409. package/src/types/index.ts +46 -0
  410. package/src/utils/agentFetcher.ts +107 -0
  411. package/src/utils/cli-error.ts +29 -0
  412. package/src/utils/conversation-id.ts +27 -0
  413. package/src/utils/conversation-utils.ts +1 -0
  414. package/src/utils/delegation-chain.ts +357 -0
  415. package/src/utils/error-handler.ts +42 -0
  416. package/src/utils/git/gitignore.ts +69 -0
  417. package/src/utils/git/index.ts +2 -0
  418. package/src/utils/git/initializeGitRepo.ts +204 -0
  419. package/src/utils/git/worktree.ts +260 -0
  420. package/src/utils/lessonFormatter.ts +70 -0
  421. package/src/utils/lessonTrust.ts +24 -0
  422. package/src/utils/lockfile.ts +123 -0
  423. package/src/utils/logger.ts +149 -0
  424. package/src/utils/nostr-entity-parser.ts +365 -0
  425. package/src/utils/process.ts +49 -0
  426. package/src/wrapper.ts +262 -0
  427. 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
+ }