@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,670 @@
1
+ /**
2
+ * Tool Registry - AI SDK Tools
3
+ *
4
+ * Central registry for all AI SDK tools in the TENEX system.
5
+ */
6
+
7
+ import { config as configService } from "@/services/ConfigService";
8
+ import { isMetaModelConfiguration } from "@/services/config/types";
9
+ import type { NudgeToolPermissions } from "@/services/nudge";
10
+ import { isOnlyToolMode } from "@/services/nudge";
11
+ import type { Tool as CoreTool } from "ai";
12
+ import type {
13
+ AISdkTool,
14
+ ToolExecutionContext,
15
+ ToolFactory,
16
+ ToolName,
17
+ ToolRegistryContext,
18
+ } from "./types";
19
+
20
+ // Helper to coerce MCP tool types without triggering TypeScript infinite recursion
21
+ // The MCP SDK returns tools with compatible structure but different generic params
22
+ function asTool<T>(tool: T): CoreTool<unknown, unknown> {
23
+ return tool as CoreTool<unknown, unknown>;
24
+ }
25
+ import { logger } from "@/utils/logger";
26
+ import { CORE_AGENT_TOOLS } from "@/agents/constants";
27
+ import { createAgentsDiscoverTool } from "./implementations/agents_discover";
28
+ import { createAgentsHireTool } from "./implementations/agents_hire";
29
+ import { createAgentsListTool } from "./implementations/agents_list";
30
+ import { createAgentsPublishTool } from "./implementations/agents_publish";
31
+ import { createAgentsReadTool } from "./implementations/agents_read";
32
+ import { createAgentsWriteTool } from "./implementations/agents_write";
33
+ import { createAskTool } from "./implementations/ask";
34
+ import { createConversationGetTool } from "./implementations/conversation_get";
35
+ import { createConversationListTool } from "./implementations/conversation_list";
36
+ import { createConversationSearchTool } from "./implementations/conversation_search";
37
+ import { createDelegateTool } from "./implementations/delegate";
38
+ import { createDelegateCrossProjectTool } from "./implementations/delegate_crossproject";
39
+ import { createDelegateFollowupTool } from "./implementations/delegate_followup";
40
+ import { createFsEditTool } from "./implementations/fs_edit";
41
+ import { createFsGlobTool } from "./implementations/fs_glob";
42
+ import { createFsGrepTool } from "./implementations/fs_grep";
43
+ import { createFsReadTool } from "./implementations/fs_read";
44
+ import { createFsWriteTool } from "./implementations/fs_write";
45
+ import { createKillTool } from "./implementations/kill";
46
+ import { createLessonLearnTool } from "./implementations/learn";
47
+ import { createLessonDeleteTool } from "./implementations/lesson_delete";
48
+ import { createLessonGetTool } from "./implementations/lesson_get";
49
+ import { createLessonsListTool } from "./implementations/lessons_list";
50
+ import { createProjectListTool } from "./implementations/project_list";
51
+ import { createRAGAddDocumentsTool } from "./implementations/rag_add_documents";
52
+ import { createRAGCreateCollectionTool } from "./implementations/rag_create_collection";
53
+ import { createRAGDeleteCollectionTool } from "./implementations/rag_delete_collection";
54
+ import { createRAGListCollectionsTool } from "./implementations/rag_list_collections";
55
+ import { createRAGQueryTool } from "./implementations/rag_query";
56
+ import { createRAGSubscriptionCreateTool } from "./implementations/rag_subscription_create";
57
+ import { createRAGSubscriptionDeleteTool } from "./implementations/rag_subscription_delete";
58
+ import { createRAGSubscriptionGetTool } from "./implementations/rag_subscription_get";
59
+ import { createRAGSubscriptionListTool } from "./implementations/rag_subscription_list";
60
+ import { createMcpResourceReadTool } from "./implementations/mcp_resource_read";
61
+ import { createMcpSubscribeTool } from "./implementations/mcp_subscribe";
62
+ import { createMcpSubscriptionStopTool } from "./implementations/mcp_subscription_stop";
63
+ import { McpSubscriptionService } from "@/services/mcp/McpSubscriptionService";
64
+ import { createReportDeleteTool } from "./implementations/report_delete";
65
+ import { createReportReadTool } from "./implementations/report_read";
66
+ import { createReportWriteTool } from "./implementations/report_write";
67
+ import { createReportsListTool } from "./implementations/reports_list";
68
+ import { createScheduleTaskTool } from "./implementations/schedule_task";
69
+ import { createCancelScheduledTaskTool } from "./implementations/schedule_task_cancel";
70
+ import { createScheduleTaskOnceTool } from "./implementations/schedule_task_once";
71
+ import { createListScheduledTasksTool } from "./implementations/schedule_tasks_list";
72
+ import { createShellTool } from "./implementations/shell";
73
+ import { createUploadBlobTool } from "./implementations/upload_blob";
74
+
75
+ // Todo tools
76
+ import { createTodoWriteTool } from "./implementations/todo";
77
+
78
+ // Web tools
79
+ import { createWebFetchTool } from "./implementations/web_fetch";
80
+ import { createWebSearchTool } from "./implementations/web_search";
81
+
82
+ // Nostr tools
83
+ import { createNostrFetchTool } from "./implementations/nostr_fetch";
84
+ import { createNostrPublishAsUserTool } from "./implementations/nostr_publish_as_user";
85
+
86
+ // Unified search tool
87
+ import { createSearchTool } from "./implementations/search";
88
+
89
+ // Image generation tools
90
+ import { createGenerateImageTool } from "./implementations/generate_image";
91
+
92
+ // Meta model tools
93
+ import { createChangeModelTool } from "./implementations/change_model";
94
+
95
+ // Home-scoped filesystem tools
96
+ import {
97
+ createHomeFsGrepTool,
98
+ createHomeFsReadTool,
99
+ createHomeFsWriteTool,
100
+ } from "./implementations/home_fs";
101
+
102
+ /**
103
+ * Metadata about tools that doesn't require instantiation.
104
+ * Tools declare hasSideEffects: false if they are read-only operations.
105
+ * Default (not listed) = true (has side effects).
106
+ */
107
+ const toolMetadata: Partial<Record<ToolName, { hasSideEffects: boolean }>> = {
108
+ // Read-only tools - these don't modify any state
109
+ fs_read: { hasSideEffects: false },
110
+ fs_glob: { hasSideEffects: false },
111
+ fs_grep: { hasSideEffects: false },
112
+ home_fs_read: { hasSideEffects: false },
113
+ home_fs_grep: { hasSideEffects: false },
114
+ conversation_get: { hasSideEffects: false },
115
+ conversation_list: { hasSideEffects: false },
116
+ conversation_search: { hasSideEffects: false },
117
+ lesson_get: { hasSideEffects: false },
118
+ lessons_list: { hasSideEffects: false },
119
+ agents_list: { hasSideEffects: false },
120
+ agents_read: { hasSideEffects: false },
121
+ agents_discover: { hasSideEffects: false },
122
+ project_list: { hasSideEffects: false },
123
+ reports_list: { hasSideEffects: false },
124
+ report_read: { hasSideEffects: false },
125
+ schedule_tasks_list: { hasSideEffects: false },
126
+ rag_list_collections: { hasSideEffects: false },
127
+ rag_query: { hasSideEffects: false },
128
+ rag_subscription_list: { hasSideEffects: false },
129
+ rag_subscription_get: { hasSideEffects: false },
130
+ mcp_resource_read: { hasSideEffects: false },
131
+ // mcp_subscribe and mcp_subscription_stop have side effects (not listed = true by default)
132
+ web_fetch: { hasSideEffects: false },
133
+ web_search: { hasSideEffects: false },
134
+ nostr_fetch: { hasSideEffects: false },
135
+ search: { hasSideEffects: false },
136
+ };
137
+
138
+ /**
139
+ * Tools that require conversation context to function.
140
+ * These are filtered out when no conversation is available (e.g., MCP context).
141
+ */
142
+ const CONVERSATION_REQUIRED_TOOLS: Set<ToolName> = new Set([
143
+ "todo_write",
144
+ "conversation_get", // Needs conversation for current-conversation optimization
145
+ "change_model", // Needs conversation to persist variant override
146
+ "mcp_subscribe", // Needs conversation to bind subscription to it
147
+ ]);
148
+
149
+ /**
150
+ * Registry of tool factories.
151
+ * All tools receive ToolExecutionContext - tools that don't need
152
+ * agentPublisher/ralNumber simply ignore those fields.
153
+ */
154
+ const toolFactories: Record<ToolName, ToolFactory> = {
155
+ // Agent tools
156
+ agents_publish: createAgentsPublishTool,
157
+ agents_discover: createAgentsDiscoverTool,
158
+ agents_hire: createAgentsHireTool,
159
+ agents_list: createAgentsListTool,
160
+ agents_read: createAgentsReadTool,
161
+ agents_write: createAgentsWriteTool,
162
+
163
+ // Ask tool
164
+ ask: createAskTool,
165
+
166
+ // File search tools
167
+ fs_glob: createFsGlobTool,
168
+ fs_grep: createFsGrepTool,
169
+
170
+ // Conversation tools
171
+ conversation_get: createConversationGetTool,
172
+ conversation_list: createConversationListTool,
173
+
174
+ // Project tools
175
+ project_list: createProjectListTool,
176
+
177
+ // Delegation tools
178
+ delegate_crossproject: createDelegateCrossProjectTool,
179
+ delegate_followup: createDelegateFollowupTool,
180
+ delegate: createDelegateTool,
181
+
182
+ // Lesson tools
183
+ lesson_delete: createLessonDeleteTool,
184
+ lesson_get: createLessonGetTool,
185
+ lesson_learn: createLessonLearnTool,
186
+ lessons_list: createLessonsListTool,
187
+
188
+ fs_read: createFsReadTool,
189
+ fs_write: createFsWriteTool,
190
+ fs_edit: createFsEditTool,
191
+
192
+ // Report tools
193
+ report_delete: createReportDeleteTool,
194
+ report_read: createReportReadTool,
195
+ report_write: createReportWriteTool,
196
+ reports_list: createReportsListTool,
197
+
198
+ // Schedule tools
199
+ schedule_task_cancel: createCancelScheduledTaskTool,
200
+ schedule_task: createScheduleTaskTool,
201
+ schedule_task_once: createScheduleTaskOnceTool,
202
+ schedule_tasks_list: createListScheduledTasksTool,
203
+
204
+ // Conversation search
205
+ conversation_search: createConversationSearchTool,
206
+
207
+ // Unified search across all project knowledge
208
+ search: createSearchTool,
209
+
210
+ shell: createShellTool,
211
+ kill: createKillTool,
212
+
213
+ // Upload tools
214
+ upload_blob: createUploadBlobTool,
215
+
216
+ // RAG tools
217
+ rag_create_collection: createRAGCreateCollectionTool,
218
+ rag_add_documents: createRAGAddDocumentsTool,
219
+ rag_query: createRAGQueryTool,
220
+ rag_delete_collection: createRAGDeleteCollectionTool,
221
+ rag_list_collections: createRAGListCollectionsTool,
222
+
223
+ // RAG subscription tools
224
+ rag_subscription_create: createRAGSubscriptionCreateTool,
225
+ rag_subscription_list: createRAGSubscriptionListTool,
226
+ rag_subscription_get: createRAGSubscriptionGetTool,
227
+ rag_subscription_delete: createRAGSubscriptionDeleteTool,
228
+
229
+ // MCP tools
230
+ mcp_resource_read: createMcpResourceReadTool,
231
+ mcp_subscribe: createMcpSubscribeTool as ToolFactory,
232
+ mcp_subscription_stop: createMcpSubscriptionStopTool,
233
+
234
+ // Todo tools - require ConversationToolContext (filtered out when no conversation)
235
+ todo_write: createTodoWriteTool as ToolFactory,
236
+
237
+ // Web tools
238
+ web_fetch: createWebFetchTool,
239
+ web_search: createWebSearchTool,
240
+
241
+ // Nostr tools
242
+ nostr_fetch: createNostrFetchTool,
243
+ nostr_publish_as_user: createNostrPublishAsUserTool,
244
+
245
+ // Image generation
246
+ generate_image: createGenerateImageTool,
247
+
248
+ // Meta model tools - requires ConversationToolContext (filtered out when no conversation)
249
+ change_model: createChangeModelTool as ToolFactory,
250
+
251
+ // Home-scoped filesystem tools (for agents without fs_* tools)
252
+ home_fs_read: createHomeFsReadTool,
253
+ home_fs_write: createHomeFsWriteTool,
254
+ home_fs_grep: createHomeFsGrepTool,
255
+ };
256
+
257
+ /**
258
+ * Get a single tool by name
259
+ * @param name - The tool name
260
+ * @param context - Tool execution context
261
+ * @returns The instantiated AI SDK tool or undefined if not found
262
+ */
263
+ export function getTool(
264
+ name: ToolName,
265
+ context: ToolExecutionContext
266
+ ): AISdkTool<unknown, unknown> | undefined {
267
+ const factory = toolFactories[name];
268
+ const ret = factory ? factory(context) : undefined;
269
+ return ret;
270
+ }
271
+
272
+ /**
273
+ * Get multiple tools by name
274
+ * @param names - Array of tool names
275
+ * @param context - Tool execution context
276
+ * @returns Array of instantiated AI SDK tools
277
+ */
278
+ export function getTools(
279
+ names: ToolName[],
280
+ context: ToolExecutionContext
281
+ ): AISdkTool<unknown, unknown>[] {
282
+ return names
283
+ .map((name) => getTool(name, context))
284
+ .filter((tool): tool is AISdkTool<unknown, unknown> => tool !== undefined);
285
+ }
286
+
287
+ /**
288
+ * Get all available tools
289
+ * @param context - Tool execution context
290
+ * @returns Array of all instantiated AI SDK tools
291
+ */
292
+ export function getAllTools(context: ToolExecutionContext): AISdkTool<unknown, unknown>[] {
293
+ const toolNames = Object.keys(toolFactories) as ToolName[];
294
+ return toolNames
295
+ .map((name) => getTool(name, context))
296
+ .filter((tool): tool is AISdkTool<unknown, unknown> => !!tool);
297
+ }
298
+
299
+ /**
300
+ * Get all available tool names
301
+ * @returns Array of all tool names in the registry
302
+ */
303
+ export function getAllToolNames(): ToolName[] {
304
+ return Object.keys(toolFactories) as ToolName[];
305
+ }
306
+
307
+ /** File editing tools - auto-injected when fs_write is available */
308
+ const FILE_EDIT_TOOLS: ToolName[] = ["fs_edit"];
309
+
310
+ /** File search tools - auto-injected when fs_read is available */
311
+ const FILE_SEARCH_TOOLS: ToolName[] = ["fs_glob", "fs_grep"];
312
+
313
+ /** Todo tools - for restricted agent execution (reminder mode) */
314
+ const TODO_TOOLS: ToolName[] = ["todo_write"];
315
+
316
+ /** Meta model tools - auto-injected when agent uses a meta model configuration */
317
+ const META_MODEL_TOOLS: ToolName[] = ["change_model"];
318
+
319
+ /** Home-scoped filesystem tools - auto-injected when agent lacks fs_* tools */
320
+ const HOME_FS_TOOLS: ToolName[] = ["home_fs_read", "home_fs_write", "home_fs_grep"];
321
+
322
+ /** Full filesystem tool names - used to check if agent has fs access */
323
+ const FS_TOOL_NAMES: ToolName[] = ["fs_read", "fs_write", "fs_edit", "fs_glob", "fs_grep"];
324
+
325
+ /**
326
+ * Check if an agent has stoppable MCP subscriptions (ACTIVE or ERROR).
327
+ * Wrapped in a function to handle cases where the service isn't initialized.
328
+ */
329
+ function mcpSubscriptionServiceHasStoppableSubscriptions(agentPubkey: string): boolean {
330
+ try {
331
+ const service = McpSubscriptionService.getInstance();
332
+ return service.hasStoppableSubscriptions(agentPubkey);
333
+ } catch {
334
+ return false;
335
+ }
336
+ }
337
+
338
+ /**
339
+ * Get tools as a keyed object (for AI SDK usage)
340
+ * @param names - Tool names to include (can include MCP tool names)
341
+ * @param context - Registry context
342
+ * @param nudgePermissions - Optional tool permissions from nudge events
343
+ * @returns Object with tools keyed by name (returns the underlying CoreTool)
344
+ */
345
+ export function getToolsObject(
346
+ names: string[],
347
+ context: ToolRegistryContext,
348
+ nudgePermissions?: NudgeToolPermissions
349
+ ): Record<string, CoreTool<unknown, unknown>> {
350
+ const tools: Record<string, CoreTool<unknown, unknown>> = {};
351
+
352
+ // Check if conversation is available
353
+ const hasConversation = context.getConversation?.() !== undefined;
354
+
355
+ // === ONLY-TOOL MODE: STRICT EXCLUSIVITY ===
356
+ // When only-tool mode is active, return EXACTLY those tools - no auto-injection whatsoever.
357
+ // This is a security feature: the nudge author has complete control over available tools.
358
+ //
359
+ // IMPORTANT: Core agent tools (like 'kill') are NOT auto-injected in only-tool mode.
360
+ // If the nudge author wants core tools, they must explicitly include them in onlyTools.
361
+ // This ensures the nudge author has complete, unambiguous control over the tool set.
362
+ if (nudgePermissions && isOnlyToolMode(nudgePermissions)) {
363
+ const onlyToolNames = nudgePermissions.onlyTools!;
364
+ logger.debug("[ToolRegistry] Nudge only-tool mode: strict exclusive tool set", {
365
+ originalTools: names.length,
366
+ onlyTools: onlyToolNames,
367
+ });
368
+
369
+ // Separate regular tools and MCP tools
370
+ const regularTools: ToolName[] = [];
371
+ const mcpToolNames: string[] = [];
372
+
373
+ for (const name of onlyToolNames) {
374
+ if (name.startsWith("mcp__")) {
375
+ mcpToolNames.push(name);
376
+ } else if (name in toolFactories) {
377
+ // Filter out conversation-required tools when no conversation available
378
+ if (CONVERSATION_REQUIRED_TOOLS.has(name as ToolName) && !hasConversation) {
379
+ logger.debug(`Filtering out tool '${name}' - requires conversation context`);
380
+ continue;
381
+ }
382
+ regularTools.push(name as ToolName);
383
+ }
384
+ }
385
+
386
+ // Add ONLY the explicitly requested regular tools - NO auto-injection
387
+ for (const name of regularTools) {
388
+ const tool = getTool(name, context as ToolExecutionContext);
389
+ if (tool) {
390
+ tools[name] = tool;
391
+ }
392
+ }
393
+
394
+ // Add ONLY the explicitly requested MCP tools - NO auto-injection
395
+ if (mcpToolNames.length > 0 && "mcpManager" in context && context.mcpManager) {
396
+ try {
397
+ const allMcpTools = context.mcpManager.getCachedTools();
398
+ for (const name of mcpToolNames) {
399
+ if (allMcpTools[name]) {
400
+ tools[name] = asTool(allMcpTools[name]);
401
+ }
402
+ }
403
+ } catch (error) {
404
+ console.debug("Could not load MCP tools:", error);
405
+ }
406
+ }
407
+
408
+ // Return immediately - no further processing or auto-injection
409
+ return tools;
410
+ }
411
+
412
+ // === ALLOW/DENY MODE OR NO NUDGE PERMISSIONS ===
413
+ // In allow/deny mode, the base tool set is modified by allow-tool and deny-tool directives.
414
+ //
415
+ // POLICY:
416
+ // 1. Initial filtering: deny-tool removes tools from base set
417
+ // 2. Auto-injection: Core tools, etc. are added
418
+ // 3. Final enforcement: deny-tool is re-applied to block any auto-injected tools
419
+ // - This ensures deny-tool CAN block core tools if explicitly denied (e.g., deny-tool: kill)
420
+ // - Provides flexibility: nudges can restrict even critical tools when needed
421
+ let effectiveNames = names;
422
+
423
+ if (nudgePermissions) {
424
+ // allow-tool / deny-tool mode
425
+ let modifiedNames = [...names];
426
+
427
+ // Add allowed tools (that aren't already in the list)
428
+ if (nudgePermissions.allowTools && nudgePermissions.allowTools.length > 0) {
429
+ for (const allowTool of nudgePermissions.allowTools) {
430
+ if (!modifiedNames.includes(allowTool)) {
431
+ modifiedNames.push(allowTool);
432
+ }
433
+ }
434
+ logger.debug("[ToolRegistry] Nudge allow-tool: added tools", {
435
+ allowedTools: nudgePermissions.allowTools,
436
+ });
437
+ }
438
+
439
+ // Remove denied tools
440
+ if (nudgePermissions.denyTools && nudgePermissions.denyTools.length > 0) {
441
+ modifiedNames = modifiedNames.filter(
442
+ (name) => !nudgePermissions.denyTools!.includes(name)
443
+ );
444
+ logger.debug("[ToolRegistry] Nudge deny-tool: removed tools", {
445
+ deniedTools: nudgePermissions.denyTools,
446
+ });
447
+ }
448
+
449
+ effectiveNames = modifiedNames;
450
+ }
451
+
452
+ // Separate regular tools and MCP tools
453
+ const regularTools: ToolName[] = [];
454
+ const mcpToolNames: string[] = [];
455
+
456
+ for (const name of effectiveNames) {
457
+ if (name.startsWith("mcp__")) {
458
+ mcpToolNames.push(name);
459
+ } else if (name in toolFactories) {
460
+ // Filter out conversation-required tools when no conversation available
461
+ if (CONVERSATION_REQUIRED_TOOLS.has(name as ToolName) && !hasConversation) {
462
+ logger.debug(`Filtering out tool '${name}' - requires conversation context`);
463
+ continue;
464
+ }
465
+ regularTools.push(name as ToolName);
466
+ }
467
+ }
468
+
469
+ // Auto-inject core agent tools for all agents (critical system capabilities)
470
+ // GATING: Only inject when conversation context is present to prevent leakage into non-agent contexts
471
+ // Contexts without conversations (e.g., isolated tool execution) are excluded from core tool injection
472
+ if (hasConversation) {
473
+ for (const coreToolName of CORE_AGENT_TOOLS) {
474
+ if (!regularTools.includes(coreToolName)) {
475
+ regularTools.push(coreToolName);
476
+ }
477
+ }
478
+ }
479
+
480
+ // Auto-inject edit tool when fs_write is available
481
+ if (regularTools.includes("fs_write")) {
482
+ for (const editToolName of FILE_EDIT_TOOLS) {
483
+ if (!regularTools.includes(editToolName)) {
484
+ regularTools.push(editToolName);
485
+ }
486
+ }
487
+ }
488
+
489
+ // Auto-inject search tools when fs_read is available
490
+ // fs_read implies full read capability: glob + grep
491
+ if (regularTools.includes("fs_read")) {
492
+ for (const searchToolName of FILE_SEARCH_TOOLS) {
493
+ if (!regularTools.includes(searchToolName)) {
494
+ regularTools.push(searchToolName);
495
+ }
496
+ }
497
+ }
498
+
499
+ // Auto-inject change_model tool when agent uses a meta model configuration
500
+ // Only inject if we have conversation context (needed for variant override persistence)
501
+ if (hasConversation && "agent" in context && context.agent?.llmConfig) {
502
+ try {
503
+ const rawConfig = configService.getRawLLMConfig(context.agent.llmConfig);
504
+ if (isMetaModelConfiguration(rawConfig)) {
505
+ for (const metaToolName of META_MODEL_TOOLS) {
506
+ if (!regularTools.includes(metaToolName)) {
507
+ regularTools.push(metaToolName);
508
+ }
509
+ }
510
+ }
511
+ } catch {
512
+ // Config not loaded or not available - skip meta model tool injection
513
+ }
514
+ }
515
+
516
+ // Auto-inject home_fs_* tools when agent lacks any fs_* tools
517
+ // This gives restricted agents filesystem access limited to their home directory
518
+ const hasAnyFsTool = FS_TOOL_NAMES.some((fsToolName) => regularTools.includes(fsToolName));
519
+ if (!hasAnyFsTool) {
520
+ for (const homeFsToolName of HOME_FS_TOOLS) {
521
+ if (!regularTools.includes(homeFsToolName)) {
522
+ regularTools.push(homeFsToolName);
523
+ }
524
+ }
525
+ }
526
+
527
+ // Auto-inject mcp_subscription_stop when agent has active MCP subscriptions
528
+ if (hasConversation && "agent" in context && context.agent?.pubkey) {
529
+ try {
530
+ if (mcpSubscriptionServiceHasStoppableSubscriptions(context.agent.pubkey)) {
531
+ if (!regularTools.includes("mcp_subscription_stop")) {
532
+ regularTools.push("mcp_subscription_stop");
533
+ }
534
+ }
535
+ } catch {
536
+ // McpSubscriptionService not initialized - skip injection
537
+ }
538
+ }
539
+
540
+ // === FINAL DENY-TOOL ENFORCEMENT ===
541
+ // Apply deny-tool filtering AFTER all auto-injection (core tools, edit, meta-model)
542
+ // This ensures deny-tool can block even core tools if explicitly denied
543
+ if (nudgePermissions?.denyTools && nudgePermissions.denyTools.length > 0) {
544
+ const beforeDenyCount = regularTools.length;
545
+ const deniedTools = regularTools.filter((name) => nudgePermissions.denyTools!.includes(name));
546
+
547
+ if (deniedTools.length > 0) {
548
+ // Remove denied tools (including auto-injected ones)
549
+ const filtered = regularTools.filter((name) => !nudgePermissions.denyTools!.includes(name));
550
+ regularTools.length = 0;
551
+ regularTools.push(...filtered);
552
+
553
+ logger.info("[ToolRegistry] Final deny-tool enforcement: blocked auto-injected tools", {
554
+ deniedTools,
555
+ beforeCount: beforeDenyCount,
556
+ afterCount: regularTools.length,
557
+ });
558
+ }
559
+ }
560
+
561
+ // Add regular tools (cast to ToolExecutionContext - filtered tools won't need conversation)
562
+ for (const name of regularTools) {
563
+ const tool = getTool(name, context as ToolExecutionContext);
564
+ if (tool) {
565
+ // Tools are now CoreTool instances with getHumanReadableContent as non-enumerable property
566
+ tools[name] = tool;
567
+ }
568
+ }
569
+
570
+ // Add only requested MCP tools (only for full registry context)
571
+ if (mcpToolNames.length > 0 && "mcpManager" in context && context.mcpManager) {
572
+ try {
573
+ const allMcpTools = context.mcpManager.getCachedTools();
574
+ for (const name of mcpToolNames) {
575
+ if (allMcpTools[name]) {
576
+ tools[name] = asTool(allMcpTools[name]);
577
+ }
578
+ }
579
+ } catch (error) {
580
+ console.debug("Could not load MCP tools:", error);
581
+ }
582
+ }
583
+
584
+ return tools;
585
+ }
586
+
587
+ /**
588
+ * Get all tools as a keyed object
589
+ * @param context - Tool execution context
590
+ * @returns Object with all tools keyed by name (returns the underlying CoreTool)
591
+ */
592
+ export function getAllToolsObject(
593
+ context: ToolExecutionContext
594
+ ): Record<string, CoreTool<unknown, unknown>> {
595
+ const tools: Record<string, CoreTool<unknown, unknown>> = {};
596
+
597
+ const toolNames = Object.keys(toolFactories) as ToolName[];
598
+ for (const name of toolNames) {
599
+ const tool = getTool(name, context);
600
+ if (tool) {
601
+ // Tools are now CoreTool instances with getHumanReadableContent as non-enumerable property
602
+ tools[name] = tool;
603
+ }
604
+ }
605
+
606
+ return tools;
607
+ }
608
+
609
+ /**
610
+ * Check if a tool name is valid
611
+ * @param name - The tool name to check
612
+ * @returns True if the tool name is valid
613
+ */
614
+ export function isValidToolName(name: string): boolean {
615
+ return name in toolFactories;
616
+ }
617
+
618
+ /**
619
+ * Get all available tool names
620
+ * @returns Array of all tool names
621
+ */
622
+ export function getAllAvailableToolNames(): string[] {
623
+ return getAllToolNames();
624
+ }
625
+
626
+ /**
627
+ * Check if a tool has side effects.
628
+ * Returns true (has side effects) by default for unknown tools (safe default).
629
+ * @param toolName - The tool name to check
630
+ * @returns true if the tool has side effects, false if it's read-only
631
+ */
632
+ export function toolHasSideEffects(toolName: string): boolean {
633
+ if (toolName in toolMetadata) {
634
+ return toolMetadata[toolName as ToolName]?.hasSideEffects !== false;
635
+ }
636
+
637
+ // MCP tools are assumed to have side effects by default
638
+ // This is the safe default - assume side effects unless explicitly declared otherwise
639
+ return true;
640
+ }
641
+
642
+ /**
643
+ * Get the list of todo tool names.
644
+ * Used for restricted agent execution in reminder mode.
645
+ * @returns Array of todo tool names
646
+ */
647
+ export function getTodoToolNames(): ToolName[] {
648
+ return [...TODO_TOOLS];
649
+ }
650
+
651
+ /**
652
+ * Get todo tools as a keyed object.
653
+ * Used for creating restricted tool sets for reminder mode.
654
+ * @param context - Tool execution context
655
+ * @returns Object with todo tools keyed by name
656
+ */
657
+ export function getTodoToolsObject(
658
+ context: ToolExecutionContext
659
+ ): Record<string, CoreTool<unknown, unknown>> {
660
+ const tools: Record<string, CoreTool<unknown, unknown>> = {};
661
+
662
+ for (const name of TODO_TOOLS) {
663
+ const tool = getTool(name, context);
664
+ if (tool) {
665
+ tools[name] = tool;
666
+ }
667
+ }
668
+
669
+ return tools;
670
+ }