@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,515 @@
1
+ /**
2
+ * Home-scoped filesystem tools for restricted agents.
3
+ *
4
+ * These tools provide filesystem access ONLY within the agent's home directory.
5
+ * They are auto-injected for agents that don't have fs_* tools configured.
6
+ *
7
+ * Security: All paths are validated via resolveHomeScopedPath() which:
8
+ * - Resolves symlinks to prevent escape attacks
9
+ * - Validates path traversal (../) attempts
10
+ * - Supports both relative and absolute path inputs
11
+ */
12
+
13
+ import { exec } from "node:child_process";
14
+ import { mkdir, readdir, readFile, stat, writeFile } from "node:fs/promises";
15
+ import { dirname, relative } from "node:path";
16
+ import { promisify } from "node:util";
17
+ import {
18
+ getAgentHomeDirectory,
19
+ HomeScopeViolationError,
20
+ resolveHomeScopedPath,
21
+ } from "@/lib/agent-home";
22
+ import { formatAnyError } from "@/lib/error-formatter";
23
+ import {
24
+ createExpectedError,
25
+ getFsErrorDescription,
26
+ isExpectedFsError,
27
+ } from "@/tools/utils";
28
+ import { tool } from "ai";
29
+ import { z } from "zod";
30
+ import type { AISdkTool, ToolExecutionContext } from "../types";
31
+
32
+ const execAsync = promisify(exec);
33
+
34
+ // Constants
35
+ const DEFAULT_LINE_LIMIT = 2000;
36
+ const MAX_LINE_LENGTH = 2000;
37
+ const MAX_GREP_CONTENT_SIZE = 50_000; // 50KB threshold
38
+
39
+ // ============================================================================
40
+ // home_fs_read
41
+ // ============================================================================
42
+
43
+ const homeReadSchema = z.object({
44
+ path: z
45
+ .string()
46
+ .describe(
47
+ "Path to the file or directory to read. Can be relative (to your home) or absolute (must be within your home). Example: 'notes.txt' or '+REMINDERS.md'"
48
+ ),
49
+ description: z
50
+ .string()
51
+ .min(1, "Description is required and cannot be empty")
52
+ .describe(
53
+ "REQUIRED: A clear, concise description of why you're reading this file (5-10 words). Helps provide human-readable context for the operation."
54
+ ),
55
+ offset: z
56
+ .number()
57
+ .min(1)
58
+ .optional()
59
+ .describe("Line number to start reading from (1-based). Defaults to line 1."),
60
+ limit: z
61
+ .number()
62
+ .min(1)
63
+ .optional()
64
+ .describe(`Maximum number of lines to read. Defaults to ${DEFAULT_LINE_LIMIT}.`),
65
+ });
66
+
67
+ async function executeHomeRead(
68
+ path: string,
69
+ agentPubkey: string,
70
+ offset?: number,
71
+ limit?: number
72
+ ): Promise<string> {
73
+ // Resolve and validate path is within home
74
+ const resolvedPath = resolveHomeScopedPath(path, agentPubkey);
75
+
76
+ const stats = await stat(resolvedPath);
77
+
78
+ if (stats.isDirectory()) {
79
+ const files = await readdir(resolvedPath);
80
+ const fileList = files.map((file) => ` - ${file}`).join("\n");
81
+ return `Directory listing for ${path}:\n${fileList}\n\nTo read a specific file, specify the filename.`;
82
+ }
83
+
84
+ const rawContent = await readFile(resolvedPath, "utf-8");
85
+ const lines = rawContent.split("\n");
86
+ const totalLines = lines.length;
87
+
88
+ // 1-based offset, default to line 1
89
+ const startLine = offset ?? 1;
90
+ const startIndex = startLine - 1;
91
+
92
+ if (startIndex >= totalLines) {
93
+ return `File has only ${totalLines} line(s), but offset ${offset} was requested.`;
94
+ }
95
+
96
+ // Apply limit
97
+ const effectiveLimit = limit ?? DEFAULT_LINE_LIMIT;
98
+ const endIndex = Math.min(startIndex + effectiveLimit, totalLines);
99
+ const selectedLines = lines.slice(startIndex, endIndex);
100
+
101
+ // Format with line numbers and truncate long lines
102
+ const numberedLines = selectedLines
103
+ .map((line, idx) => {
104
+ const lineNum = startIndex + idx + 1;
105
+ const truncatedLine =
106
+ line.length > MAX_LINE_LENGTH ? line.slice(0, MAX_LINE_LENGTH) + "..." : line;
107
+ return `${lineNum.toString().padStart(6)}\t${truncatedLine}`;
108
+ })
109
+ .join("\n");
110
+
111
+ // Add info about truncation if we didn't read the whole file
112
+ const remainingLines = totalLines - endIndex;
113
+ if (remainingLines > 0) {
114
+ return `${numberedLines}\n\n[Showing lines ${startLine}-${endIndex} of ${totalLines}. ${remainingLines} more lines available. Use offset=${endIndex + 1} to continue.]`;
115
+ }
116
+
117
+ return numberedLines;
118
+ }
119
+
120
+ export function createHomeFsReadTool(context: ToolExecutionContext): AISdkTool {
121
+ const toolInstance = tool({
122
+ description:
123
+ `Read a file or directory from your home directory. This tool ONLY operates within your home directory. You cannot access files outside your home. ` +
124
+ `Returns file contents with line numbers (up to ${DEFAULT_LINE_LIMIT} lines). Use offset (1-based) and limit to paginate large files. ` +
125
+ `Paths can be relative (resolved against your home) or absolute (must be within your home).`,
126
+
127
+ inputSchema: homeReadSchema,
128
+
129
+ execute: async ({
130
+ path,
131
+ description: _description,
132
+ offset,
133
+ limit,
134
+ }: {
135
+ path: string;
136
+ description: string;
137
+ offset?: number;
138
+ limit?: number;
139
+ }) => {
140
+ try {
141
+ return await executeHomeRead(path, context.agent.pubkey, offset, limit);
142
+ } catch (error: unknown) {
143
+ // Home scope violations return friendly error message
144
+ if (error instanceof HomeScopeViolationError) {
145
+ return createExpectedError(error.message);
146
+ }
147
+
148
+ // Expected FS errors (file not found, permission denied, etc.)
149
+ if (isExpectedFsError(error)) {
150
+ const code = (error as NodeJS.ErrnoException).code;
151
+ const description = getFsErrorDescription(code);
152
+ return createExpectedError(`${description}: ${path}`);
153
+ }
154
+
155
+ throw new Error(`Failed to read ${path}: ${formatAnyError(error)}`, {
156
+ cause: error,
157
+ });
158
+ }
159
+ },
160
+ });
161
+
162
+ Object.defineProperty(toolInstance, "getHumanReadableContent", {
163
+ value: ({ path, description }: { path: string; description: string }) => {
164
+ return `Reading ${path} (${description})`;
165
+ },
166
+ enumerable: false,
167
+ configurable: true,
168
+ });
169
+
170
+ return toolInstance as AISdkTool;
171
+ }
172
+
173
+ // ============================================================================
174
+ // home_fs_write
175
+ // ============================================================================
176
+
177
+ const homeWriteSchema = z.object({
178
+ path: z
179
+ .string()
180
+ .describe(
181
+ "Path to the file to write. Can be relative (to your home) or absolute (must be within your home). Parent directories are created automatically."
182
+ ),
183
+ content: z.string().describe("The content to write to the file."),
184
+ description: z
185
+ .string()
186
+ .min(1, "Description is required and cannot be empty")
187
+ .describe(
188
+ "REQUIRED: A clear, concise description of why you're writing this file (5-10 words). Helps provide human-readable context for the operation."
189
+ ),
190
+ });
191
+
192
+ async function executeHomeWrite(
193
+ path: string,
194
+ content: string,
195
+ agentPubkey: string
196
+ ): Promise<string> {
197
+ // Resolve and validate path is within home
198
+ const resolvedPath = resolveHomeScopedPath(path, agentPubkey);
199
+
200
+ // Create parent directories if they don't exist
201
+ const parentDir = dirname(resolvedPath);
202
+ await mkdir(parentDir, { recursive: true });
203
+
204
+ // Write the file
205
+ await writeFile(resolvedPath, content, "utf-8");
206
+
207
+ return `Successfully wrote ${content.length} bytes to ${path}`;
208
+ }
209
+
210
+ export function createHomeFsWriteTool(context: ToolExecutionContext): AISdkTool {
211
+ const toolInstance = tool({
212
+ description:
213
+ "Write content to a file in your home directory. This tool ONLY operates within your home directory. You cannot write files outside your home. " +
214
+ "Creates parent directories automatically if they don't exist. Overwrites existing files. " +
215
+ "Paths can be relative (resolved against your home) or absolute (must be within your home).",
216
+
217
+ inputSchema: homeWriteSchema,
218
+
219
+ execute: async ({ path, content, description: _description }: { path: string; content: string; description: string }) => {
220
+ try {
221
+ return await executeHomeWrite(path, content, context.agent.pubkey);
222
+ } catch (error: unknown) {
223
+ // Home scope violations return friendly error message
224
+ if (error instanceof HomeScopeViolationError) {
225
+ return createExpectedError(error.message);
226
+ }
227
+
228
+ // Expected FS errors
229
+ if (isExpectedFsError(error)) {
230
+ const code = (error as NodeJS.ErrnoException).code;
231
+ const description = getFsErrorDescription(code);
232
+ return createExpectedError(`${description}: ${path}`);
233
+ }
234
+
235
+ throw new Error(`Failed to write ${path}: ${formatAnyError(error)}`, {
236
+ cause: error,
237
+ });
238
+ }
239
+ },
240
+ });
241
+
242
+ Object.defineProperty(toolInstance, "getHumanReadableContent", {
243
+ value: ({ path, description }: { path: string; description: string }) => {
244
+ return `Writing ${path} (${description})`;
245
+ },
246
+ enumerable: false,
247
+ configurable: true,
248
+ });
249
+
250
+ return toolInstance as AISdkTool;
251
+ }
252
+
253
+ // ============================================================================
254
+ // home_fs_grep
255
+ // ============================================================================
256
+
257
+ const homeGrepSchema = z.object({
258
+ pattern: z
259
+ .string()
260
+ .describe("Regex pattern to search for in file contents (e.g., 'TODO', 'function\\s+\\w+')."),
261
+ description: z
262
+ .string()
263
+ .min(1, "Description is required and cannot be empty")
264
+ .describe(
265
+ "REQUIRED: A clear, concise description of why you're searching for this pattern (5-10 words). Helps provide human-readable context for the operation."
266
+ ),
267
+ path: z
268
+ .string()
269
+ .optional()
270
+ .describe(
271
+ "Path within your home to search. Can be relative or absolute (must be within home). Defaults to your entire home directory."
272
+ ),
273
+ output_mode: z
274
+ .enum(["files_with_matches", "content", "count"])
275
+ .default("files_with_matches")
276
+ .describe(
277
+ "Output mode: 'files_with_matches' (file paths only), 'content' (matching lines), 'count' (match counts per file)."
278
+ ),
279
+ "-i": z.boolean().optional().describe("Case-insensitive search."),
280
+ head_limit: z
281
+ .number()
282
+ .default(100)
283
+ .describe("Limit output to first N entries. Use 0 for unlimited."),
284
+ });
285
+
286
+ type HomeGrepInput = z.infer<typeof homeGrepSchema>;
287
+
288
+ async function isRipgrepAvailable(): Promise<boolean> {
289
+ try {
290
+ await execAsync("which rg", { timeout: 1000 });
291
+ return true;
292
+ } catch {
293
+ return false;
294
+ }
295
+ }
296
+
297
+ function buildHomeGrepCommand(
298
+ input: HomeGrepInput,
299
+ searchPath: string,
300
+ useRipgrep: boolean
301
+ ): string {
302
+ const { pattern, output_mode, "-i": caseInsensitive } = input;
303
+
304
+ const parts: string[] = [];
305
+
306
+ if (useRipgrep) {
307
+ parts.push("rg");
308
+ if (output_mode === "files_with_matches") {
309
+ parts.push("-l");
310
+ } else if (output_mode === "count") {
311
+ parts.push("-c");
312
+ } else {
313
+ parts.push("-n"); // Line numbers for content mode
314
+ }
315
+ if (caseInsensitive) {
316
+ parts.push("-i");
317
+ }
318
+ } else {
319
+ parts.push("grep", "-r", "-E");
320
+ if (output_mode === "files_with_matches") {
321
+ parts.push("-l");
322
+ } else if (output_mode === "count") {
323
+ parts.push("-c");
324
+ } else {
325
+ parts.push("-n"); // Line numbers for content mode
326
+ }
327
+ if (caseInsensitive) {
328
+ parts.push("-i");
329
+ }
330
+ parts.push("--binary-files=without-match");
331
+ }
332
+
333
+ // Pattern (escape for shell)
334
+ parts.push(`'${pattern.replace(/'/g, "'\\''")}'`);
335
+
336
+ // Search path (escape single quotes to prevent shell injection)
337
+ parts.push(`'${searchPath.replace(/'/g, "'\\''")}'`);
338
+
339
+ return parts.join(" ");
340
+ }
341
+
342
+ function applyPagination(lines: string[], limit: number): string[] {
343
+ return limit > 0 ? lines.slice(0, limit) : lines;
344
+ }
345
+
346
+ async function runHomeGrepCommand(
347
+ input: HomeGrepInput,
348
+ homeDir: string,
349
+ searchPath: string
350
+ ): Promise<string[]> {
351
+ const useRipgrep = await isRipgrepAvailable();
352
+ const command = buildHomeGrepCommand(input, searchPath, useRipgrep);
353
+
354
+ try {
355
+ const { stdout } = await execAsync(command, {
356
+ cwd: homeDir,
357
+ timeout: 30000,
358
+ maxBuffer: 1024 * 1024 * 10, // 10MB
359
+ });
360
+
361
+ if (!stdout.trim()) {
362
+ return [];
363
+ }
364
+
365
+ return stdout.trim().split("\n").filter(Boolean);
366
+ } catch (error) {
367
+ // Exit code 1 from grep/rg means no matches - not an error
368
+ if (error && typeof error === "object" && "code" in error && error.code === 1) {
369
+ return [];
370
+ }
371
+ // maxBuffer error - rethrow to trigger fallback
372
+ if (error && typeof error === "object" && "message" in error &&
373
+ typeof error.message === "string" && error.message.includes("maxBuffer")) {
374
+ throw error;
375
+ }
376
+ throw error;
377
+ }
378
+ }
379
+
380
+ function processGrepLines(lines: string[], outputMode: string, homeDir: string): string[] {
381
+ return lines.map((line) => {
382
+ if (outputMode === "files_with_matches") {
383
+ return relative(homeDir, line);
384
+ } else if (outputMode === "count") {
385
+ const colonIdx = line.lastIndexOf(":");
386
+ if (colonIdx > 0) {
387
+ const filePath = line.substring(0, colonIdx);
388
+ const count = line.substring(colonIdx + 1);
389
+ return `${relative(homeDir, filePath)}:${count}`;
390
+ }
391
+ } else {
392
+ // Content mode: /path/to/file:line:content
393
+ const firstColon = line.indexOf(":");
394
+ if (firstColon > 0) {
395
+ const filePath = line.substring(0, firstColon);
396
+ const rest = line.substring(firstColon);
397
+ return `${relative(homeDir, filePath)}${rest}`;
398
+ }
399
+ }
400
+ return line;
401
+ });
402
+ }
403
+
404
+ async function executeHomeGrep(input: HomeGrepInput, agentPubkey: string): Promise<string> {
405
+ const { pattern, path: inputPath, output_mode, head_limit } = input;
406
+ const homeDir = getAgentHomeDirectory(agentPubkey);
407
+
408
+ if (!pattern) {
409
+ return "Error: pattern is required";
410
+ }
411
+
412
+ // Determine and validate search path
413
+ const searchPath = inputPath ? resolveHomeScopedPath(inputPath, agentPubkey) : homeDir;
414
+
415
+ try {
416
+ let lines: string[];
417
+
418
+ try {
419
+ lines = await runHomeGrepCommand(input, homeDir, searchPath);
420
+ } catch (error) {
421
+ // Handle maxBuffer error by falling back to files_with_matches mode
422
+ if (
423
+ output_mode === "content" &&
424
+ error &&
425
+ typeof error === "object" &&
426
+ "message" in error &&
427
+ typeof error.message === "string" &&
428
+ error.message.includes("maxBuffer")
429
+ ) {
430
+ // Retry with files_with_matches mode
431
+ const fallbackInput = { ...input, output_mode: "files_with_matches" as const };
432
+ const fallbackLines = await runHomeGrepCommand(fallbackInput, homeDir, searchPath);
433
+ const fallbackProcessed = processGrepLines(fallbackLines, "files_with_matches", homeDir);
434
+ const fallbackPaginated = applyPagination(fallbackProcessed, head_limit);
435
+
436
+ return `Output exceeded buffer limit. Showing ${fallbackPaginated.length} matching files instead:\n\n${fallbackPaginated.join("\n")}`;
437
+ }
438
+ throw error;
439
+ }
440
+
441
+ if (lines.length === 0) {
442
+ return `No matches found for pattern: ${pattern}`;
443
+ }
444
+
445
+ // Convert absolute paths to relative (to home)
446
+ lines = processGrepLines(lines, output_mode, homeDir);
447
+
448
+ // Apply pagination
449
+ const paginatedLines = applyPagination(lines, head_limit);
450
+ const result = paginatedLines.join("\n");
451
+
452
+ // Check content size
453
+ if (output_mode === "content" && Buffer.byteLength(result, "utf8") > MAX_GREP_CONTENT_SIZE) {
454
+ // Fall back to files_with_matches
455
+ const uniquePaths = new Set<string>();
456
+ for (const line of lines) {
457
+ const firstColon = line.indexOf(":");
458
+ if (firstColon > 0) {
459
+ uniquePaths.add(line.substring(0, firstColon));
460
+ }
461
+ }
462
+ const fileList = Array.from(uniquePaths).slice(0, head_limit).join("\n");
463
+ return `Content output exceeded 50KB limit. Showing ${uniquePaths.size} matching files:\n\n${fileList}`;
464
+ }
465
+
466
+ const truncated = paginatedLines.length < lines.length;
467
+ if (truncated) {
468
+ return `${result}\n\n[Truncated: showing ${paginatedLines.length} of ${lines.length} results]`;
469
+ }
470
+
471
+ return result;
472
+ } catch (error) {
473
+ // Exit code 1 from grep/rg means no matches - not an error
474
+ if (error && typeof error === "object" && "code" in error && error.code === 1) {
475
+ return `No matches found for pattern: ${pattern}`;
476
+ }
477
+ throw error;
478
+ }
479
+ }
480
+
481
+ export function createHomeFsGrepTool(context: ToolExecutionContext): AISdkTool {
482
+ const toolInstance = tool({
483
+ description:
484
+ "Search for patterns in files within your home directory. This tool ONLY operates within your home directory. You cannot search files outside your home. " +
485
+ "Uses ripgrep (with grep fallback). Supports regex patterns. " +
486
+ "Output modes: 'files_with_matches' (default), 'content' (matching lines), 'count' (match counts).",
487
+
488
+ inputSchema: homeGrepSchema,
489
+
490
+ execute: async (input: HomeGrepInput) => {
491
+ try {
492
+ return await executeHomeGrep(input, context.agent.pubkey);
493
+ } catch (error: unknown) {
494
+ // Home scope violations return friendly error message
495
+ if (error instanceof HomeScopeViolationError) {
496
+ return createExpectedError(error.message);
497
+ }
498
+
499
+ const message = error instanceof Error ? error.message : String(error);
500
+ return `Search error: ${message}`;
501
+ }
502
+ },
503
+ });
504
+
505
+ Object.defineProperty(toolInstance, "getHumanReadableContent", {
506
+ value: (input: HomeGrepInput) => {
507
+ const pathInfo = input.path ? ` in ${input.path}` : " in home";
508
+ return `Searching for '${input.pattern}'${pathInfo} (${input.description})`;
509
+ },
510
+ enumerable: false,
511
+ configurable: true,
512
+ });
513
+
514
+ return toolInstance as AISdkTool;
515
+ }