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