@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,332 @@
1
+ import { readFile, readdir, stat } from "node:fs/promises";
2
+ import type { AISdkTool, ToolExecutionContext } from "@/tools/types";
3
+ import { toolMessageStorage } from "@/conversations/persistence/ToolMessageStorage";
4
+ import { isPathWithinDirectory, isWithinAgentHome } from "@/lib/agent-home";
5
+ import { formatAnyError } from "@/lib/error-formatter";
6
+ import { llmServiceFactory } from "@/llm";
7
+ import { config } from "@/services/ConfigService";
8
+ import {
9
+ createExpectedError,
10
+ getFsErrorDescription,
11
+ isExpectedFsError,
12
+ isExpectedNotFoundError,
13
+ } from "@/tools/utils";
14
+ import { logger } from "@/utils/logger";
15
+ import { tool } from "ai";
16
+ import { z } from "zod";
17
+
18
+ const DEFAULT_LINE_LIMIT = 2000;
19
+ const MAX_LINE_LENGTH = 2000;
20
+
21
+ const readPathSchema = z.object({
22
+ path: z
23
+ .string()
24
+ .optional()
25
+ .describe("The absolute path to the file or directory to read. Required unless using 'tool' parameter."),
26
+ description: z
27
+ .string()
28
+ .min(1, "Description is required and cannot be empty")
29
+ .describe(
30
+ "REQUIRED: A clear, concise description of why you're reading this file (5-10 words). Helps provide human-readable context for the operation."
31
+ ),
32
+ offset: z
33
+ .number()
34
+ .min(1)
35
+ .optional()
36
+ .describe("Line number to start reading from (1-based). If omitted, starts from line 1."),
37
+ limit: z
38
+ .number()
39
+ .min(1)
40
+ .optional()
41
+ .describe(`Maximum number of lines to read. Defaults to ${DEFAULT_LINE_LIMIT}.`),
42
+ allowOutsideWorkingDirectory: z
43
+ .boolean()
44
+ .optional()
45
+ .describe("Set to true to read files outside the working directory. Required when path is not within the project."),
46
+ tool: z
47
+ .string()
48
+ .optional()
49
+ .describe("Event ID of a tool execution to read its result. When provided, 'path' is ignored and the tool's output is returned. Useful for retrieving truncated tool results."),
50
+ prompt: z
51
+ .string()
52
+ .optional()
53
+ .describe("Optional prompt to analyze the content. When provided, the content (file or tool result) will be processed through an LLM which will provide an explanation based on this prompt. Useful for extracting specific information or getting a summary."),
54
+ });
55
+
56
+ /**
57
+ * Fetch and format a tool execution result by event ID
58
+ */
59
+ async function executeReadToolResult(eventId: string): Promise<string> {
60
+ const messages = await toolMessageStorage.load(eventId);
61
+
62
+ if (!messages) {
63
+ throw new Error(`No tool result found for event ID: ${eventId}`);
64
+ }
65
+
66
+ // Extract tool call and result from messages
67
+ // Format: [{ role: "assistant", content: [{ type: "tool-call", ... }] }, { role: "tool", content: [{ type: "tool-result", ... }] }]
68
+ const assistantMessage = messages.find((m) => m.role === "assistant");
69
+ const toolMessage = messages.find((m) => m.role === "tool");
70
+
71
+ if (!assistantMessage || !toolMessage) {
72
+ throw new Error(`Invalid tool result format for event ID: ${eventId}`);
73
+ }
74
+
75
+ // Extract tool call details
76
+ const toolCallContent = Array.isArray(assistantMessage.content)
77
+ ? assistantMessage.content.find((c) => typeof c === "object" && "type" in c && c.type === "tool-call")
78
+ : null;
79
+
80
+ // Extract tool result
81
+ const toolResultContent = Array.isArray(toolMessage.content)
82
+ ? toolMessage.content.find((c) => typeof c === "object" && "type" in c && c.type === "tool-result")
83
+ : null;
84
+
85
+ if (!toolCallContent || !toolResultContent) {
86
+ throw new Error(`Could not extract tool call/result for event ID: ${eventId}`);
87
+ }
88
+
89
+ // Format output
90
+ const toolName = "toolName" in toolCallContent ? toolCallContent.toolName : "unknown";
91
+ const input = "input" in toolCallContent ? toolCallContent.input : {};
92
+ const output = "output" in toolResultContent ? toolResultContent.output : null;
93
+
94
+ // Extract the actual output value
95
+ let outputValue: string;
96
+ if (output && typeof output === "object" && "value" in output) {
97
+ outputValue = String(output.value);
98
+ } else if (typeof output === "string") {
99
+ outputValue = output;
100
+ } else {
101
+ outputValue = JSON.stringify(output, null, 2);
102
+ }
103
+
104
+ const inputStr = typeof input === "object" ? JSON.stringify(input, null, 2) : String(input);
105
+
106
+ return `Tool: ${toolName}\nEvent ID: ${eventId}\n\n--- Input ---\n${inputStr}\n\n--- Output ---\n${outputValue}`;
107
+ }
108
+
109
+ /**
110
+ * Core implementation of the fs_read functionality
111
+ */
112
+ async function executeFsRead(
113
+ path: string,
114
+ workingDirectory: string,
115
+ agentPubkey: string,
116
+ offset?: number,
117
+ limit?: number,
118
+ allowOutsideWorkingDirectory?: boolean,
119
+ ): Promise<string> {
120
+ if (!path.startsWith("/")) {
121
+ throw new Error(`Path must be absolute, got: ${path}`);
122
+ }
123
+
124
+ // Check if path is within working directory (using secure path normalization)
125
+ const isWithinWorkDir = isPathWithinDirectory(path, workingDirectory);
126
+
127
+ // Always allow access to agent's home directory without requiring allowOutsideWorkingDirectory
128
+ const isInAgentHome = isWithinAgentHome(path, agentPubkey);
129
+
130
+ if (!isWithinWorkDir && !isInAgentHome && !allowOutsideWorkingDirectory) {
131
+ return `Path "${path}" is outside your working directory "${workingDirectory}". If this was intentional, retry with allowOutsideWorkingDirectory: true`;
132
+ }
133
+
134
+ const stats = await stat(path);
135
+
136
+ if (stats.isDirectory()) {
137
+ const files = await readdir(path);
138
+ const fileList = files.map((file) => ` - ${file}`).join("\n");
139
+ return `Directory listing for ${path}:\n${fileList}\n\nTo read a specific file, please specify the full path to the file.`;
140
+ }
141
+
142
+ const rawContent = await readFile(path, "utf-8");
143
+ const lines = rawContent.split("\n");
144
+ const totalLines = lines.length;
145
+
146
+ // 1-based offset, default to line 1
147
+ const startLine = offset ?? 1;
148
+ const startIndex = startLine - 1;
149
+
150
+ if (startIndex >= totalLines) {
151
+ return `File has only ${totalLines} line(s), but offset ${offset} was requested.`;
152
+ }
153
+
154
+ // Apply limit (default to DEFAULT_LINE_LIMIT)
155
+ const effectiveLimit = limit ?? DEFAULT_LINE_LIMIT;
156
+ const endIndex = Math.min(startIndex + effectiveLimit, totalLines);
157
+ const selectedLines = lines.slice(startIndex, endIndex);
158
+
159
+ // Format with line numbers and truncate long lines
160
+ const numberedLines = selectedLines
161
+ .map((line, idx) => {
162
+ const lineNum = startIndex + idx + 1;
163
+ const truncatedLine = line.length > MAX_LINE_LENGTH
164
+ ? line.slice(0, MAX_LINE_LENGTH) + "..."
165
+ : line;
166
+ return `${lineNum.toString().padStart(6)}\t${truncatedLine}`;
167
+ })
168
+ .join("\n");
169
+
170
+ // Add info about truncation if we didn't read the whole file
171
+ const remainingLines = totalLines - endIndex;
172
+ if (remainingLines > 0) {
173
+ return `${numberedLines}\n\n[Showing lines ${startLine}-${endIndex} of ${totalLines}. ${remainingLines} more lines available. Use offset=${endIndex + 1} to continue.]`;
174
+ }
175
+
176
+ return numberedLines;
177
+ }
178
+
179
+ /**
180
+ * Synthesize content using an LLM based on a prompt
181
+ */
182
+ async function synthesizeContent(content: string, prompt: string, source: string): Promise<string> {
183
+ // Get LLM configuration - use summarization config if set, otherwise default
184
+ const { llms } = await config.loadConfig();
185
+ const configName = llms.summarization || llms.default;
186
+
187
+ if (!configName) {
188
+ logger.warn("No LLM configuration available for content synthesis");
189
+ return content;
190
+ }
191
+
192
+ const llmConfig = config.getLLMConfig(configName);
193
+
194
+ // Create LLM service
195
+ const llmService = llmServiceFactory.createService(llmConfig, {
196
+ agentName: "content-synthesizer",
197
+ sessionId: `synthesizer-${Date.now()}`,
198
+ });
199
+
200
+ // Generate synthesis using the LLM
201
+ const { object: result } = await llmService.generateObject(
202
+ [
203
+ {
204
+ role: "system",
205
+ content: `You are a helpful assistant that analyzes content and provides explanations based on user prompts.
206
+
207
+ CRITICAL REQUIREMENTS:
208
+ 1. VERBATIM QUOTES: You MUST include relevant parts of the content verbatim in your response. Quote the exact text that supports your analysis.
209
+ 2. PRESERVE IDENTIFIERS: All IDs, file paths, function names, variable names, and other technical identifiers must be preserved exactly as they appear.
210
+ 3. Base your analysis ONLY on what is explicitly present in the content.
211
+
212
+ FORMAT: Structure your response with:
213
+ - Your analysis/explanation
214
+ - Verbatim quotes from relevant parts (use quotation marks)
215
+ - All referenced identifiers preserved exactly`,
216
+ },
217
+ {
218
+ role: "user",
219
+ content: `Please analyze the following content based on this prompt: "${prompt}"
220
+
221
+ IMPORTANT: Include verbatim quotes from the relevant parts that support your analysis.
222
+
223
+ SOURCE: ${source}
224
+
225
+ CONTENT:
226
+ ${content}`,
227
+ },
228
+ ],
229
+ z.object({
230
+ explanation: z
231
+ .string()
232
+ .describe(
233
+ "A detailed explanation based on the user's prompt. MUST include verbatim quotes from relevant content and preserve all important identifiers."
234
+ ),
235
+ })
236
+ );
237
+
238
+ logger.info("✅ Content synthesized with prompt", {
239
+ source,
240
+ promptLength: prompt.length,
241
+ contentLength: content.length,
242
+ });
243
+
244
+ return result.explanation;
245
+ }
246
+
247
+ /**
248
+ * Create an AI SDK tool for reading paths
249
+ */
250
+ export function createFsReadTool(context: ToolExecutionContext): AISdkTool {
251
+ const toolInstance = tool({
252
+ description:
253
+ `Read a file, directory, or tool result. For files: returns contents with line numbers, up to ${DEFAULT_LINE_LIMIT} lines by default. Use offset (1-based) and limit to paginate. Lines over ${MAX_LINE_LENGTH} chars are truncated. Path must be absolute. Reading outside working directory requires allowOutsideWorkingDirectory: true. For tool results: use the 'tool' parameter with an event ID to read a tool execution's output (useful for retrieving results from other agents' tool calls).`,
254
+
255
+ inputSchema: readPathSchema,
256
+
257
+ execute: async ({ path, description, offset, limit, allowOutsideWorkingDirectory, tool: toolEventId, prompt }: { path?: string; description: string; offset?: number; limit?: number; allowOutsideWorkingDirectory?: boolean; tool?: string; prompt?: string }) => {
258
+ // Log the read operation with context
259
+ logger.info("Reading file or tool result", {
260
+ path: path || undefined,
261
+ description,
262
+ tool: toolEventId || undefined,
263
+ hasPrompt: !!prompt,
264
+ });
265
+
266
+ try {
267
+ let content: string;
268
+ let source: string;
269
+
270
+ // If tool parameter is provided, fetch tool result instead of reading a file
271
+ if (toolEventId) {
272
+ content = await executeReadToolResult(toolEventId);
273
+ source = `tool result ${toolEventId}`;
274
+ } else {
275
+ // Otherwise, read the file/directory
276
+ if (!path) {
277
+ throw new Error("Either 'path' or 'tool' parameter is required");
278
+ }
279
+ content = await executeFsRead(path, context.workingDirectory, context.agent.pubkey, offset, limit, allowOutsideWorkingDirectory);
280
+ source = path;
281
+ }
282
+
283
+ // If a prompt is provided, synthesize the content
284
+ if (prompt) {
285
+ try {
286
+ return await synthesizeContent(content, prompt, source);
287
+ } catch (synthError) {
288
+ logger.error("Failed to synthesize content, returning raw content", {
289
+ source,
290
+ error: synthError instanceof Error ? synthError.message : String(synthError),
291
+ });
292
+ return `[Synthesis failed: ${synthError instanceof Error ? synthError.message : String(synthError)}]\n\n${content}`;
293
+ }
294
+ }
295
+
296
+ return content;
297
+ } catch (error: unknown) {
298
+ const target = toolEventId ? `tool result ${toolEventId}` : path;
299
+
300
+ // Expected FS errors (file not found, permission denied, etc.) return error-text
301
+ // This ensures the error is properly communicated to the LLM without stream failures
302
+ if (isExpectedFsError(error)) {
303
+ const code = (error as NodeJS.ErrnoException).code;
304
+ const description = getFsErrorDescription(code);
305
+ return createExpectedError(`${description}: ${target}`);
306
+ }
307
+
308
+ // Expected "not found" errors (e.g., tool result not found) also return error-text
309
+ if (isExpectedNotFoundError(error)) {
310
+ return createExpectedError(error instanceof Error ? error.message : `Not found: ${target}`);
311
+ }
312
+
313
+ // Unexpected errors still throw (they'll be caught by the SDK)
314
+ throw new Error(`Failed to read ${target}: ${formatAnyError(error)}`, { cause: error });
315
+ }
316
+ },
317
+ });
318
+
319
+ Object.defineProperty(toolInstance, "getHumanReadableContent", {
320
+ value: ({ path, description, tool: toolEventId, prompt }: { path?: string; description: string; tool?: string; prompt?: string }) => {
321
+ const action = prompt ? "Analyzing" : "Reading";
322
+ if (toolEventId) {
323
+ return `${action} tool result ${toolEventId.substring(0, 16)}... (${description})`;
324
+ }
325
+ return `${action} ${path} (${description})`;
326
+ },
327
+ enumerable: false,
328
+ configurable: true,
329
+ });
330
+
331
+ return toolInstance as AISdkTool;
332
+ }
@@ -0,0 +1,113 @@
1
+ import { mkdir, writeFile } from "node:fs/promises";
2
+ import { dirname } from "node:path";
3
+ import type { AISdkTool, ToolExecutionContext } from "@/tools/types";
4
+ import { isPathWithinDirectory, isWithinAgentHome } from "@/lib/agent-home";
5
+ import { formatAnyError } from "@/lib/error-formatter";
6
+ import { getLocalReportStore } from "@/services/reports";
7
+ import {
8
+ createExpectedError,
9
+ getFsErrorDescription,
10
+ isExpectedFsError,
11
+ } from "@/tools/utils";
12
+ import { tool } from "ai";
13
+ import { z } from "zod";
14
+
15
+ const writeFileSchema = z.object({
16
+ path: z
17
+ .string()
18
+ .describe("The absolute path to the file to write"),
19
+ content: z.string().describe("The content to write to the file"),
20
+ description: z
21
+ .string()
22
+ .min(1, "Description is required and cannot be empty")
23
+ .describe(
24
+ "REQUIRED: A clear, concise description of why you're writing this file (5-10 words). Helps provide human-readable context for the operation."
25
+ ),
26
+ allowOutsideWorkingDirectory: z
27
+ .boolean()
28
+ .optional()
29
+ .describe("Set to true to write files outside the working directory. Required when path is not within the project."),
30
+ });
31
+
32
+ /**
33
+ * Core implementation of the write_file functionality
34
+ */
35
+ async function executeWriteFile(
36
+ path: string,
37
+ content: string,
38
+ workingDirectory: string,
39
+ agentPubkey: string,
40
+ allowOutsideWorkingDirectory?: boolean,
41
+ ): Promise<string> {
42
+ if (!path.startsWith("/")) {
43
+ throw new Error(`Path must be absolute, got: ${path}`);
44
+ }
45
+
46
+ // Block writes to the reports directory - agents must use report_write instead
47
+ const localReportStore = getLocalReportStore();
48
+ if (localReportStore.isPathInReportsDir(path)) {
49
+ throw new Error(
50
+ "Cannot write to reports directory directly. " +
51
+ `Path "${path}" is within the protected reports directory. ` +
52
+ "Use the report_write tool instead to create or update reports."
53
+ );
54
+ }
55
+
56
+ // Check if path is within working directory (using secure path normalization)
57
+ const isWithinWorkDir = isPathWithinDirectory(path, workingDirectory);
58
+
59
+ // Always allow access to agent's home directory without requiring allowOutsideWorkingDirectory
60
+ const isInAgentHome = isWithinAgentHome(path, agentPubkey);
61
+
62
+ if (!isWithinWorkDir && !isInAgentHome && !allowOutsideWorkingDirectory) {
63
+ return `Path "${path}" is outside your working directory "${workingDirectory}". If this was intentional, retry with allowOutsideWorkingDirectory: true`;
64
+ }
65
+
66
+ // Create parent directories if they don't exist
67
+ const parentDir = dirname(path);
68
+ await mkdir(parentDir, { recursive: true });
69
+
70
+ // Write the file
71
+ await writeFile(path, content, "utf-8");
72
+
73
+ return `Successfully wrote ${content.length} bytes to ${path}`;
74
+ }
75
+
76
+ /**
77
+ * Create an AI SDK tool for writing files
78
+ */
79
+ export function createFsWriteTool(context: ToolExecutionContext): AISdkTool {
80
+ const toolInstance = tool({
81
+ description:
82
+ "Write content to a file in the filesystem. Creates parent directories automatically if they don't exist. Overwrites existing files. Path must be absolute. Writing outside the working directory requires allowOutsideWorkingDirectory: true.",
83
+
84
+ inputSchema: writeFileSchema,
85
+
86
+ execute: async ({ path, content, description: _description, allowOutsideWorkingDirectory }: { path: string; content: string; description: string; allowOutsideWorkingDirectory?: boolean }) => {
87
+ try {
88
+ return await executeWriteFile(path, content, context.workingDirectory, context.agent.pubkey, allowOutsideWorkingDirectory);
89
+ } catch (error: unknown) {
90
+ // Expected errors (permission denied, etc.) return error-text
91
+ // This ensures the error is properly communicated to the LLM without stream failures
92
+ if (isExpectedFsError(error)) {
93
+ const code = (error as NodeJS.ErrnoException).code;
94
+ const description = getFsErrorDescription(code);
95
+ return createExpectedError(`${description}: ${path}`);
96
+ }
97
+
98
+ // Unexpected errors still throw (they'll be caught by the SDK)
99
+ throw new Error(`Failed to write ${path}: ${formatAnyError(error)}`, { cause: error });
100
+ }
101
+ },
102
+ });
103
+
104
+ Object.defineProperty(toolInstance, "getHumanReadableContent", {
105
+ value: ({ path, description }: { path: string; description: string }) => {
106
+ return `Writing ${path} (${description})`;
107
+ },
108
+ enumerable: false,
109
+ configurable: true,
110
+ });
111
+
112
+ return toolInstance as AISdkTool;
113
+ }