@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,160 @@
1
+ import type { ToolExecutionContext } from "@/tools/types";
2
+ import { getLocalReportStore, InvalidSlugError } from "@/services/reports";
3
+ import type { AISdkTool } from "@/tools/types";
4
+ import { logger } from "@/utils/logger";
5
+ import { tool } from "ai";
6
+ import { z } from "zod";
7
+ import { nip19 } from "nostr-tools";
8
+
9
+ const reportReadSchema = z.object({
10
+ identifier: z
11
+ .string()
12
+ .describe("The report identifier - can be a slug (e.g., 'my-report'), an naddr (e.g., 'naddr1...'), or a nostr: URI (e.g., 'nostr:naddr1...')"),
13
+ });
14
+
15
+ type ReportReadInput = z.infer<typeof reportReadSchema>;
16
+
17
+ interface ReportReadOutput {
18
+ success: boolean;
19
+ slug?: string;
20
+ content?: string;
21
+ message?: string;
22
+ }
23
+
24
+ /**
25
+ * Core implementation of report reading functionality
26
+ * Reads exclusively from local file storage
27
+ */
28
+ async function executeReportRead(
29
+ input: ReportReadInput,
30
+ context: ToolExecutionContext
31
+ ): Promise<ReportReadOutput> {
32
+ const { identifier } = input;
33
+
34
+ logger.info("📖 Reading report from local storage", {
35
+ identifier,
36
+ agent: context.agent.name,
37
+ });
38
+
39
+ const localStore = getLocalReportStore();
40
+
41
+ // Clean the identifier - extract slug if it's an naddr or has nostr: prefix
42
+ let slug = identifier;
43
+
44
+ // Remove nostr: prefix if present
45
+ if (slug.startsWith("nostr:")) {
46
+ slug = slug.slice(6);
47
+ }
48
+
49
+ // If it looks like an naddr, decode it to extract the slug (d-tag)
50
+ // Reports are NDKArticle events (kind 30023)
51
+ if (slug.startsWith("naddr1")) {
52
+ try {
53
+ const decoded = nip19.decode(slug);
54
+ if (decoded.type === "naddr") {
55
+ // Verify this is a report (kind 30023) - NDKArticle
56
+ if (decoded.data.kind !== 30023) {
57
+ return {
58
+ success: false,
59
+ message: `Invalid naddr kind ${decoded.data.kind} - report_read only accepts kind 30023 (NDKArticle) naddrs. Got: ${identifier}`,
60
+ };
61
+ }
62
+ if (decoded.data.identifier) {
63
+ slug = decoded.data.identifier;
64
+ logger.debug("📖 Decoded naddr to slug", {
65
+ originalIdentifier: identifier,
66
+ extractedSlug: slug,
67
+ kind: decoded.data.kind,
68
+ agent: context.agent.name,
69
+ });
70
+ } else {
71
+ return {
72
+ success: false,
73
+ message: `Invalid naddr format - missing identifier (d-tag) in: ${identifier}`,
74
+ };
75
+ }
76
+ } else {
77
+ return {
78
+ success: false,
79
+ message: `Invalid naddr format - could not extract report slug from: ${identifier}`,
80
+ };
81
+ }
82
+ } catch (decodeError) {
83
+ logger.warn("📖 Failed to decode naddr identifier", {
84
+ identifier,
85
+ error: decodeError instanceof Error ? decodeError.message : String(decodeError),
86
+ agent: context.agent.name,
87
+ });
88
+ return {
89
+ success: false,
90
+ message: `Failed to decode naddr identifier: ${identifier}. Please provide a valid slug or naddr.`,
91
+ };
92
+ }
93
+ }
94
+
95
+ // Validate the slug for path safety
96
+ try {
97
+ localStore.validateSlug(slug);
98
+ } catch (error) {
99
+ if (error instanceof InvalidSlugError) {
100
+ return {
101
+ success: false,
102
+ message: error.message,
103
+ };
104
+ }
105
+ throw error;
106
+ }
107
+
108
+ // Read from local storage
109
+ const content = await localStore.readReport(slug);
110
+
111
+ if (!content) {
112
+ logger.info("📭 No local report found", {
113
+ slug,
114
+ path: localStore.getReportPath(slug),
115
+ agent: context.agent.name,
116
+ });
117
+
118
+ return {
119
+ success: false,
120
+ message: `No report found with slug: ${slug}. The report may not have been written yet or synced from Nostr.`,
121
+ };
122
+ }
123
+
124
+ logger.info("✅ Report read successfully from local storage", {
125
+ slug,
126
+ contentLength: content.length,
127
+ agent: context.agent.name,
128
+ });
129
+
130
+ return {
131
+ success: true,
132
+ slug,
133
+ content,
134
+ };
135
+ }
136
+
137
+ /**
138
+ * Create an AI SDK tool for reading reports
139
+ */
140
+ export function createReportReadTool(context: ToolExecutionContext): AISdkTool {
141
+ const aiTool = tool({
142
+ description: "Read a report by slug identifier",
143
+
144
+ inputSchema: reportReadSchema,
145
+
146
+ execute: async (input: ReportReadInput) => {
147
+ return await executeReportRead(input, context);
148
+ },
149
+ });
150
+
151
+ Object.defineProperty(aiTool, "getHumanReadableContent", {
152
+ value: ({ identifier }: ReportReadInput) => {
153
+ return `Reading report: ${identifier}`;
154
+ },
155
+ enumerable: false,
156
+ configurable: true,
157
+ });
158
+
159
+ return aiTool as AISdkTool;
160
+ }
@@ -0,0 +1,278 @@
1
+ import type { ToolExecutionContext } from "@/tools/types";
2
+ import { PendingDelegationsRegistry } from "@/services/ral";
3
+ import { ReportService, getLocalReportStore, InvalidSlugError } from "@/services/reports";
4
+ import { getReportEmbeddingService } from "@/services/reports/ReportEmbeddingService";
5
+ import { getProjectContext } from "@/services/projects";
6
+ import type { AISdkTool } from "@/tools/types";
7
+ import { logger } from "@/utils/logger";
8
+ import { tool } from "ai";
9
+ import { z } from "zod";
10
+
11
+ const reportWriteSchema = z.object({
12
+ slug: z.string().describe("The slug identifier for the article, used as the d-tag"),
13
+ title: z.string().describe("The title of the report"),
14
+ summary: z.string().describe("A one-line summary of the report"),
15
+ content: z.string().describe("The full content of the report in markdown format"),
16
+ hashtags: z
17
+ .array(z.string())
18
+ .default([])
19
+ .describe("Array of hashtags to add to the article (without the # prefix)"),
20
+ memorize: z
21
+ .boolean()
22
+ .default(false)
23
+ .describe(
24
+ "When true, the report content will be automatically added to this agent's system prompt as persistent context. Use this for reports that are fundamental to your role (e.g., architecture decisions, domain knowledge, project conventions) that you want to always have available."
25
+ ),
26
+ memorize_team: z
27
+ .boolean()
28
+ .default(false)
29
+ .describe(
30
+ "⚠️ HIGH CONTEXT COST - When true, the report content will be injected into the system prompt of ALL agents in the project, not just the authoring agent. Use ONLY for SHORT documents that are critical for EVERY agent to know. Examples: critical project-wide conventions, emergency procedures, or announcements that affect all agents. NEVER use for long documents or agent-specific information."
31
+ ),
32
+ });
33
+
34
+ type ReportWriteInput = z.infer<typeof reportWriteSchema>;
35
+ type ReportWriteOutput = {
36
+ success: boolean;
37
+ articleId: string;
38
+ slug: string;
39
+ message: string;
40
+ /** Addressable event references for a-tagging on the tool use event */
41
+ referencedAddressableEvents: string[];
42
+ /** Warning messages for non-fatal issues (e.g., local write failed but Nostr succeeded) */
43
+ warnings?: string[];
44
+ };
45
+
46
+ /**
47
+ * Format report content for local storage with metadata header
48
+ */
49
+ function formatReportContent(data: {
50
+ title: string;
51
+ summary: string;
52
+ content: string;
53
+ hashtags?: string[];
54
+ }): string {
55
+ const lines: string[] = [];
56
+
57
+ // Add title
58
+ lines.push(`# ${data.title}`);
59
+ lines.push("");
60
+
61
+ // Add summary
62
+ if (data.summary) {
63
+ lines.push(`> ${data.summary}`);
64
+ lines.push("");
65
+ }
66
+
67
+ // Add hashtags if present
68
+ if (data.hashtags && data.hashtags.length > 0) {
69
+ lines.push(`**Tags:** ${data.hashtags.map((t) => `#${t}`).join(" ")}`);
70
+ lines.push("");
71
+ }
72
+
73
+ lines.push("---");
74
+ lines.push("");
75
+
76
+ // Add content
77
+ lines.push(data.content);
78
+
79
+ return lines.join("\n");
80
+ }
81
+
82
+ // Core implementation - extracted from existing execute function
83
+ async function executeReportWrite(
84
+ input: ReportWriteInput,
85
+ context: ToolExecutionContext
86
+ ): Promise<ReportWriteOutput> {
87
+ const { slug, title, summary, content, hashtags, memorize, memorize_team } = input;
88
+
89
+ logger.info("📝 Writing report", {
90
+ slug,
91
+ title,
92
+ memorize,
93
+ memorize_team,
94
+ agent: context.agent.name,
95
+ });
96
+
97
+ const reportService = new ReportService();
98
+ const localStore = getLocalReportStore();
99
+
100
+ // Step 1: Validate slug BEFORE publishing to Nostr
101
+ // This prevents orphaned Nostr reports that can't be read back locally
102
+ try {
103
+ localStore.validateSlug(slug);
104
+ } catch (error) {
105
+ if (error instanceof InvalidSlugError) {
106
+ throw new Error(
107
+ `Invalid report slug "${slug}": ${error.message}. ` +
108
+ "Slugs can only contain alphanumeric characters, hyphens, and underscores.",
109
+ { cause: error }
110
+ );
111
+ }
112
+ throw error;
113
+ }
114
+
115
+ // Step 2: Publish to Nostr
116
+ const result = await reportService.writeReport(
117
+ {
118
+ slug,
119
+ title,
120
+ summary,
121
+ content,
122
+ hashtags,
123
+ memorize,
124
+ memorizeTeam: memorize_team,
125
+ },
126
+ context.agent
127
+ );
128
+
129
+ // Step 3: Save to local storage
130
+ // Format the content for local storage
131
+ const formattedContent = formatReportContent({ title, summary, content, hashtags });
132
+
133
+ // The created_at is now (since we just published)
134
+ const createdAt = Math.floor(Date.now() / 1000);
135
+
136
+ // Try to save locally, but don't fail if Nostr publish succeeded
137
+ let localWriteFailed = false;
138
+ let localWriteError: string | undefined;
139
+ try {
140
+ await localStore.writeReport(slug, formattedContent, {
141
+ addressableRef: result.addressableRef,
142
+ createdAt,
143
+ slug,
144
+ });
145
+
146
+ logger.info("📁 Report saved to local storage", {
147
+ slug,
148
+ path: localStore.getReportPath(slug),
149
+ });
150
+ } catch (localError) {
151
+ // Nostr publish succeeded but local save failed - log warning but don't throw
152
+ localWriteFailed = true;
153
+ localWriteError = localError instanceof Error ? localError.message : String(localError);
154
+ logger.warn("⚠️ Report published to Nostr but local save failed", {
155
+ slug,
156
+ error: localWriteError,
157
+ nostrId: result.encodedId,
158
+ });
159
+ // Continue - the report is live on Nostr and will be hydrated later
160
+ }
161
+
162
+ // Step 4: Index in RAG for semantic search
163
+ try {
164
+ const projectCtx = getProjectContext();
165
+ const projectTagId = projectCtx.project.tagId();
166
+ const reportEmbeddingService = getReportEmbeddingService();
167
+
168
+ const publishedAt = Math.floor(Date.now() / 1000);
169
+ await reportEmbeddingService.indexReport(
170
+ { slug, title, summary, content, hashtags, publishedAt },
171
+ projectTagId,
172
+ context.agent.pubkey,
173
+ context.agent.name
174
+ );
175
+ } catch (ragError) {
176
+ // Don't fail the tool if RAG indexing fails
177
+ const ragMessage = ragError instanceof Error ? ragError.message : String(ragError);
178
+ logger.warn("Failed to index report in RAG", { slug, error: ragMessage });
179
+ }
180
+
181
+ let memorizeMessage = "";
182
+ if (memorize_team) {
183
+ memorizeMessage = " ⚠️ This report has been team-memorized and will be included in the system prompt of ALL agents in the project.";
184
+ } else if (memorize) {
185
+ memorizeMessage = " This report has been memorized and will be included in your system prompt.";
186
+ }
187
+
188
+ logger.info("✅ Report written successfully", {
189
+ slug,
190
+ articleId: result.encodedId,
191
+ addressableRef: result.addressableRef,
192
+ memorize,
193
+ memorize_team,
194
+ agent: context.agent.name,
195
+ });
196
+
197
+ // Register with PendingDelegationsRegistry for a-tag correlation
198
+ PendingDelegationsRegistry.registerAddressable(
199
+ context.agent.pubkey,
200
+ context.conversationId,
201
+ result.addressableRef
202
+ );
203
+
204
+ // Build warnings array if there were any non-fatal issues
205
+ const warnings: string[] = [];
206
+ if (localWriteFailed) {
207
+ warnings.push(
208
+ `Local write failed (${localWriteError}). Report is published to Nostr and will be hydrated from subscription.`
209
+ );
210
+ }
211
+
212
+ return {
213
+ success: true,
214
+ articleId: `nostr:${result.encodedId}`,
215
+ slug,
216
+ message: `Report "${title}" published successfully.${memorizeMessage}`,
217
+ // Include addressable reference for ToolExecutionTracker to add as a-tag
218
+ referencedAddressableEvents: [result.addressableRef],
219
+ // Include warnings if any non-fatal issues occurred
220
+ ...(warnings.length > 0 && { warnings }),
221
+ };
222
+ }
223
+
224
+ // AI SDK tool factory
225
+ export function createReportWriteTool(context: ToolExecutionContext): AISdkTool {
226
+ return tool({
227
+ description: `Write reports and documentation as NDKArticle events. Use for creating persistent documentation ABOUT THE PROJECT, such as:
228
+ - Architecture documentation
229
+ - Implementation plans
230
+ - Project summaries
231
+ - Design decisions
232
+ - Technical specifications
233
+ - API documentation
234
+ - Team guidelines and conventions
235
+
236
+ Reports are stored on Nostr network and accessible via slug. Updates existing reports with same slug. Supports markdown format and hashtags for categorization. Reports can be read back with report_read or listed with reports_list.
237
+
238
+ **CRITICAL:** Only use this for content ABOUT THE PROJECT. For content about your behavior or patterns in how you work, use lesson_learn instead.
239
+
240
+ **NEVER use for:**
241
+ - Behavioral patterns or workflows
242
+ - User preferences or communication styles
243
+ - Debugging approaches or work patterns
244
+ - "I've learned to..." statements about your approach
245
+
246
+ **Memorize Parameter**: Set memorize=true when the report contains information that is fundamental to your role and should always be available in your system prompt. Use this for:
247
+ - Core architectural decisions you need to reference frequently
248
+ - Domain knowledge essential to your function
249
+ - Project conventions or patterns you must follow consistently
250
+ - Any content you want persisted across all future conversations
251
+
252
+ When memorize=true, a "memorize" tag is added to the article and the content will be automatically injected into your system prompt.
253
+
254
+ **Memorize Team Parameter** (⚠️ USE WITH EXTREME CAUTION):
255
+ Set memorize_team=true ONLY when the report MUST be visible to EVERY agent in the project.
256
+
257
+ ⚠️ **HIGH CONTEXT WINDOW COST** - This injects content into ALL agents' system prompts!
258
+
259
+ **ONLY use memorize_team for:**
260
+ - Critical project-wide conventions that ALL agents must follow
261
+ - Emergency procedures or time-sensitive announcements
262
+ - Extremely short (<500 chars) shared context that every agent needs
263
+
264
+ **NEVER use memorize_team for:**
265
+ - Long documents (architecture docs, specs, etc.)
266
+ - Agent-specific information
267
+ - Content that only some agents need
268
+ - General documentation (use regular reports instead)
269
+
270
+ When memorize_team=true, a "memorize_team" tag is added and the content will be injected into the system prompt of ALL agents.
271
+
272
+ See also: lesson_learn (for behavioral insights)`,
273
+ inputSchema: reportWriteSchema,
274
+ execute: async (input: ReportWriteInput) => {
275
+ return await executeReportWrite(input, context);
276
+ },
277
+ }) as AISdkTool;
278
+ }
@@ -0,0 +1,77 @@
1
+ import type { AISdkTool, ToolExecutionContext } from "@/tools/types";
2
+ import { ReportService } from "@/services/reports";
3
+ import { getProjectContext } from "@/services/projects";
4
+ import { logger } from "@/utils/logger";
5
+ import { tool } from "ai";
6
+ import { z } from "zod";
7
+
8
+ const reportsListSchema = z.object({});
9
+
10
+ type ReportsListInput = z.infer<typeof reportsListSchema>;
11
+
12
+ type ReportSummary = {
13
+ slug: string;
14
+ title?: string;
15
+ summary?: string;
16
+ author: string;
17
+ publishedAt?: number;
18
+ hashtags?: string[];
19
+ };
20
+
21
+ type ReportsListOutput = {
22
+ success: boolean;
23
+ reports: ReportSummary[];
24
+ };
25
+
26
+ // Core implementation - extracted from existing execute function
27
+ async function executeReportsList(
28
+ _input: ReportsListInput,
29
+ context: ToolExecutionContext
30
+ ): Promise<ReportsListOutput> {
31
+ logger.info("📚 Listing reports", {
32
+ agent: context.agent.name,
33
+ });
34
+
35
+ const reportService = new ReportService();
36
+ const projectCtx = getProjectContext();
37
+
38
+ // Fetch all reports in the project
39
+ const rawReports = await reportService.listReports();
40
+
41
+ // Transform reports: remove id, convert author hex pubkey to slug
42
+ const reports: ReportSummary[] = rawReports.map((report) => {
43
+ // Try to resolve author pubkey to agent slug
44
+ const agent = projectCtx.getAgentByPubkey(report.author);
45
+ const authorSlug = agent?.slug ?? report.author;
46
+
47
+ return {
48
+ slug: report.slug,
49
+ title: report.title,
50
+ summary: report.summary,
51
+ author: authorSlug,
52
+ publishedAt: report.publishedAt,
53
+ hashtags: report.hashtags,
54
+ };
55
+ });
56
+
57
+ logger.info("✅ Reports listed successfully", {
58
+ total: reports.length,
59
+ agent: context.agent.name,
60
+ });
61
+
62
+ return {
63
+ success: true,
64
+ reports,
65
+ };
66
+ }
67
+
68
+ // AI SDK tool factory
69
+ export function createReportsListTool(context: ToolExecutionContext): AISdkTool {
70
+ return tool({
71
+ description: "List NDKArticle reports from agents in the project",
72
+ inputSchema: reportsListSchema,
73
+ execute: async (input: ReportsListInput) => {
74
+ return await executeReportsList(input, context);
75
+ },
76
+ }) as AISdkTool;
77
+ }
@@ -0,0 +1,104 @@
1
+ import type { ToolExecutionContext } from "@/tools/types";
2
+ import { SchedulerService } from "@/services/scheduling";
3
+ import type { AISdkTool } from "@/tools/types";
4
+ import { resolveAgentSlug } from "@/services/agents";
5
+ import { logger } from "@/utils/logger";
6
+ import { tool } from "ai";
7
+ import * as cron from "node-cron";
8
+ import { z } from "zod";
9
+
10
+ /**
11
+ * Creates a tool for scheduling tasks using cron notation
12
+ */
13
+ export function createScheduleTaskTool(context: ToolExecutionContext): AISdkTool {
14
+ const aiTool = tool({
15
+ description:
16
+ "Schedule a task using cron notation (e.g., '0 9 * * *' for daily at 9am, '*/5 * * * *' for every 5 minutes)",
17
+ inputSchema: z.object({
18
+ title: z
19
+ .string()
20
+ .optional()
21
+ .describe("A human-readable title for the scheduled task (e.g., 'Daily standup reminder')"),
22
+ prompt: z.string().describe("The prompt to execute when the task runs"),
23
+ schedule: z
24
+ .string()
25
+ .describe(
26
+ "Cron expression for scheduling (e.g., '0 9 * * *' for daily at 9am, '0 * * * *' for hourly)"
27
+ ),
28
+ targetAgent: z
29
+ .string()
30
+ .nullable()
31
+ .describe(
32
+ "Target agent slug (e.g., 'architect', 'claude-code'). Only agent slugs are accepted."
33
+ ),
34
+ }),
35
+ execute: async ({ title, prompt, schedule, targetAgent }) => {
36
+ // Validate cron expression - throw for invalid input (consistent with delegate tool)
37
+ if (!cron.validate(schedule)) {
38
+ throw new Error(
39
+ `Invalid cron expression: ${schedule}. Examples: '0 9 * * *' (daily at 9am), '*/5 * * * *' (every 5 minutes), '0 0 * * 0' (weekly on Sunday)`
40
+ );
41
+ }
42
+
43
+ // Resolve target agent to pubkey if specified - throw for invalid slugs (consistent with delegate tool)
44
+ let toPubkey: string;
45
+ if (targetAgent) {
46
+ const resolution = resolveAgentSlug(targetAgent);
47
+ if (!resolution.pubkey) {
48
+ const availableSlugsStr = resolution.availableSlugs.length > 0
49
+ ? `Available agent slugs: ${resolution.availableSlugs.join(", ")}`
50
+ : "No agents available in the current project context.";
51
+ throw new Error(
52
+ `Invalid agent slug: "${targetAgent}". Only agent slugs are accepted. ${availableSlugsStr}`
53
+ );
54
+ }
55
+ toPubkey = resolution.pubkey;
56
+ } else {
57
+ // Default to self if no target specified
58
+ toPubkey = context.agent.pubkey;
59
+ }
60
+
61
+ const schedulerService = SchedulerService.getInstance();
62
+
63
+ // The agent scheduling the task is always the current agent
64
+ const fromPubkey = context.agent.pubkey;
65
+
66
+ // Add task to scheduler with both pubkeys and optional title
67
+ const taskId = await schedulerService.addTask(
68
+ schedule,
69
+ prompt,
70
+ fromPubkey,
71
+ toPubkey,
72
+ undefined, // projectId - let it be resolved from context
73
+ title
74
+ );
75
+
76
+ logger.info(
77
+ `Successfully created scheduled task ${taskId} with cron schedule: ${schedule}`
78
+ );
79
+
80
+ return {
81
+ success: true,
82
+ taskId,
83
+ message: `Task scheduled successfully with ID: ${taskId}`,
84
+ title,
85
+ schedule,
86
+ prompt,
87
+ targetAgent: targetAgent || "self",
88
+ };
89
+ },
90
+ });
91
+
92
+ // Attach getHumanReadableContent as non-enumerable property
93
+ Object.defineProperty(aiTool, "getHumanReadableContent", {
94
+ value: (args: { title?: string; prompt: string; schedule: string; targetAgent?: string }) => {
95
+ const target = args.targetAgent ? ` for ${args.targetAgent}` : "";
96
+ const titlePart = args.title ? `'${args.title}' ` : "";
97
+ return `Scheduling task ${titlePart}with cron '${args.schedule}'${target}: ${args.prompt}`;
98
+ },
99
+ enumerable: false,
100
+ configurable: true,
101
+ });
102
+
103
+ return aiTool as AISdkTool;
104
+ }
@@ -0,0 +1,62 @@
1
+ import { SchedulerService } from "@/services/scheduling";
2
+ import type { ToolExecutionContext } from "@/tools/types";
3
+ import type { AISdkTool } from "@/tools/types";
4
+ import { logger } from "@/utils/logger";
5
+ import { tool } from "ai";
6
+ import { z } from "zod";
7
+
8
+ /**
9
+ * Creates a tool for canceling scheduled tasks
10
+ */
11
+ export function createCancelScheduledTaskTool(_context: ToolExecutionContext): AISdkTool {
12
+ const aiTool = tool({
13
+ description: "Cancel a scheduled task (recurring or one-off) by its ID",
14
+ inputSchema: z.object({
15
+ taskId: z.string().describe("The ID of the task to cancel"),
16
+ }),
17
+ execute: async ({ taskId }) => {
18
+ try {
19
+ const schedulerService = SchedulerService.getInstance();
20
+
21
+ // Remove task from scheduler
22
+ const success = await schedulerService.removeTask(taskId);
23
+
24
+ if (!success) {
25
+ return {
26
+ success: false,
27
+ error: `Task ${taskId} not found or could not be removed`,
28
+ taskId,
29
+ };
30
+ }
31
+
32
+ logger.info(`Successfully cancelled scheduled task ${taskId}`);
33
+
34
+ return {
35
+ success: true,
36
+ message: `Task ${taskId} cancelled successfully`,
37
+ taskId,
38
+ };
39
+ } catch (error: unknown) {
40
+ logger.error(`Failed to cancel scheduled task ${taskId}:`, error);
41
+
42
+ return {
43
+ success: false,
44
+ error:
45
+ error instanceof Error ? error.message : "Failed to cancel scheduled task",
46
+ taskId,
47
+ };
48
+ }
49
+ },
50
+ });
51
+
52
+ // Attach getHumanReadableContent as non-enumerable property
53
+ Object.defineProperty(aiTool, "getHumanReadableContent", {
54
+ value: (args: { taskId: string }) => {
55
+ return `Canceling scheduled task ${args.taskId}`;
56
+ },
57
+ enumerable: false,
58
+ configurable: true,
59
+ });
60
+
61
+ return aiTool as AISdkTool;
62
+ }