@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,553 @@
1
+ import { exec, spawn, type ExecException } from "node:child_process";
2
+ import { createWriteStream } from "node:fs";
3
+ import { mkdir } from "node:fs/promises";
4
+ import { tmpdir } from "node:os";
5
+ import { join } from "node:path";
6
+ import { promisify } from "node:util";
7
+ import type { AISdkTool, ToolExecutionContext } from "@/tools/types";
8
+ import { logger } from "@/utils/logger";
9
+ import { trace } from "@opentelemetry/api";
10
+ import { tool } from "ai";
11
+ import { z } from "zod";
12
+
13
+ const execAsync = promisify(exec);
14
+
15
+ /**
16
+ * Commands known to use non-zero exit codes for non-error conditions.
17
+ * These commands return exit code 1 for "no matches" or similar expected outcomes.
18
+ */
19
+ const COMMANDS_WITH_EXPECTED_NON_ZERO_EXIT: Record<string, { exitCodes: number[]; description: string }> = {
20
+ grep: { exitCodes: [1], description: "No matches found" },
21
+ rg: { exitCodes: [1], description: "No matches found" },
22
+ ripgrep: { exitCodes: [1], description: "No matches found" },
23
+ diff: { exitCodes: [1], description: "Files differ" },
24
+ cmp: { exitCodes: [1], description: "Files differ" },
25
+ test: { exitCodes: [1], description: "Condition is false" },
26
+ "[": { exitCodes: [1], description: "Condition is false" },
27
+ "[[": { exitCodes: [1], description: "Condition is false" },
28
+ };
29
+
30
+ /**
31
+ * Structure returned when a shell command completes with non-zero exit
32
+ * but it's an expected condition (not an error)
33
+ */
34
+ interface ShellExpectedNonZeroResult {
35
+ type: "expected-non-zero-exit";
36
+ command: string;
37
+ exitCode: number;
38
+ stdout: string;
39
+ stderr: string;
40
+ explanation: string;
41
+ }
42
+
43
+ /**
44
+ * Structure returned when a shell command fails unexpectedly
45
+ */
46
+ interface ShellErrorResult {
47
+ type: "shell-error";
48
+ command: string;
49
+ exitCode: number | null;
50
+ error: string;
51
+ stdout: string;
52
+ stderr: string;
53
+ signal: string | null;
54
+ }
55
+
56
+ /**
57
+ * Structure returned when a shell command is started in the background
58
+ */
59
+ interface ShellBackgroundResult {
60
+ type: "background-task";
61
+ taskId: string;
62
+ command: string;
63
+ description: string | null;
64
+ outputFile: string;
65
+ message: string;
66
+ }
67
+
68
+ type BackgroundTaskInfo = {
69
+ pid: number;
70
+ command: string;
71
+ description: string | null;
72
+ outputFile: string;
73
+ startTime: Date;
74
+ projectId: string;
75
+ };
76
+
77
+ // Track background tasks
78
+ const backgroundTasks = new Map<string, BackgroundTaskInfo>();
79
+
80
+ /**
81
+ * Generate a unique task ID for background processes
82
+ */
83
+ function generateTaskId(): string {
84
+ return Math.random().toString(36).substring(2, 9);
85
+ }
86
+
87
+ /**
88
+ * Extracts the base command from a shell command string.
89
+ * Handles pipes, redirects, and command chaining.
90
+ */
91
+ function extractBaseCommand(command: string): string {
92
+ // Remove leading whitespace and common prefixes
93
+ const trimmed = command.trim();
94
+
95
+ // Handle common patterns like "command args | ..." or "command args && ..."
96
+ // Get just the first word (the command itself)
97
+ const firstWord = trimmed.split(/\s+/)[0];
98
+
99
+ // Remove any path prefix (e.g., /usr/bin/grep -> grep)
100
+ const baseName = firstWord.split("/").pop() || firstWord;
101
+
102
+ return baseName;
103
+ }
104
+
105
+ /**
106
+ * Checks if a command's non-zero exit code is expected behavior
107
+ */
108
+ function isExpectedNonZeroExit(command: string, exitCode: number): { expected: boolean; explanation?: string } {
109
+ const baseCommand = extractBaseCommand(command);
110
+ const config = COMMANDS_WITH_EXPECTED_NON_ZERO_EXIT[baseCommand];
111
+
112
+ if (config && config.exitCodes.includes(exitCode)) {
113
+ return { expected: true, explanation: config.description };
114
+ }
115
+
116
+ return { expected: false };
117
+ }
118
+
119
+ const shellSchema = z.object({
120
+ command: z.string().describe("The shell command to execute"),
121
+ description: z
122
+ .string()
123
+ .trim()
124
+ .min(1, "Description is required and cannot be empty")
125
+ .describe(
126
+ "REQUIRED: A clear, concise description of what this command does (5-10 words). Helps provide human-readable context for the operation."
127
+ ),
128
+ cwd: z
129
+ .string()
130
+ .nullable()
131
+ .optional()
132
+ .describe("Working directory for the command (defaults to project root)"),
133
+ timeout: z
134
+ .preprocess(
135
+ // Coerce numeric strings to numbers while preserving undefined/null
136
+ // Reject empty/whitespace strings (treat as undefined) to avoid Number("") === 0
137
+ (val) => {
138
+ if (val === undefined || val === null) return val;
139
+ if (typeof val === "number") return val;
140
+ if (typeof val === "string") {
141
+ const trimmed = val.trim();
142
+ if (trimmed === "") return undefined; // Treat empty/whitespace as "not provided"
143
+ const parsed = Number(trimmed);
144
+ return Number.isNaN(parsed) ? val : parsed;
145
+ }
146
+ return val;
147
+ },
148
+ z.number().nullable().optional()
149
+ )
150
+ .describe(
151
+ `Command timeout in seconds (default: 30, max: 600). Optional for background processes.`
152
+ ),
153
+ run_in_background: z
154
+ .boolean()
155
+ .nullable()
156
+ .optional()
157
+ .describe(
158
+ "Set to true to run the command in the background. Returns immediately with a task ID that can be used to check status later."
159
+ ),
160
+ });
161
+
162
+ type ShellInput = z.infer<typeof shellSchema>;
163
+ type ShellOutput = string | ShellExpectedNonZeroResult | ShellErrorResult | ShellBackgroundResult;
164
+
165
+ /**
166
+ * Core implementation of shell command execution
167
+ * Shared between AI SDK and legacy Tool interfaces
168
+ *
169
+ * Handles four cases:
170
+ * 1. Success (exit code 0): Returns stdout + stderr as string
171
+ * 2. Expected non-zero exit (e.g., grep with no matches): Returns structured result, NOT an error
172
+ * 3. Genuine failure: Returns structured error result for LLM recovery
173
+ * 4. Background execution: Returns task info immediately, output written to file
174
+ */
175
+ async function executeShell(input: ShellInput, context: ToolExecutionContext): Promise<ShellOutput> {
176
+ const { command, description, cwd, timeout = 30, run_in_background } = input;
177
+
178
+ // Resolve cwd: if provided and relative, resolve against context.workingDirectory
179
+ // If not provided, use context.workingDirectory directly
180
+ let workingDir: string;
181
+ if (cwd) {
182
+ // If cwd is relative (like "."), resolve it against the project working directory
183
+ const { isAbsolute, resolve } = await import("node:path");
184
+ workingDir = isAbsolute(cwd) ? cwd : resolve(context.workingDirectory, cwd);
185
+ } else {
186
+ workingDir = context.workingDirectory;
187
+ }
188
+
189
+ // Add trace span with all context for debugging
190
+ const span = trace.getActiveSpan();
191
+ span?.setAttributes({
192
+ "shell.command": command.substring(0, 200),
193
+ "shell.description": description || "(not provided)",
194
+ "shell.cwd_param_raw": cwd || "(not provided)",
195
+ "shell.cwd_resolved": workingDir || "(empty)",
196
+ "shell.context.working_directory": context.workingDirectory || "(empty)",
197
+ "shell.context.project_base_path": context.projectBasePath || "(empty)",
198
+ "shell.context.current_branch": context.currentBranch || "(empty)",
199
+ "shell.agent": context.agent.name,
200
+ "shell.timeout": (timeout ?? 30) * 1000,
201
+ "shell.run_in_background": run_in_background ?? false,
202
+ });
203
+ span?.addEvent("shell.execute_start", {
204
+ command: command.substring(0, 200),
205
+ description: description || "(not provided)",
206
+ cwd: workingDir || "(empty)",
207
+ run_in_background: run_in_background ?? false,
208
+ });
209
+
210
+ // Validate working directory - fail fast if it's empty
211
+ if (!workingDir) {
212
+ const errorMsg = "Shell command cannot run: workingDirectory is empty. " +
213
+ `Context projectBasePath: "${context.projectBasePath}", ` +
214
+ `Context workingDirectory: "${context.workingDirectory}"`;
215
+ span?.addEvent("shell.error", { error: errorMsg });
216
+ throw new Error(errorMsg);
217
+ }
218
+
219
+ logger.info("Executing shell command", {
220
+ command,
221
+ description: description || undefined,
222
+ cwd: workingDir,
223
+ contextWorkingDir: context.workingDirectory,
224
+ contextProjectBasePath: context.projectBasePath,
225
+ agent: context.agent.name,
226
+ timeout,
227
+ runInBackground: run_in_background ?? false,
228
+ });
229
+
230
+ // Handle background execution
231
+ if (run_in_background) {
232
+ const taskId = generateTaskId();
233
+ const outputDir = join(tmpdir(), "tenex-shell-tasks");
234
+ await mkdir(outputDir, { recursive: true });
235
+ const outputFile = join(outputDir, `${taskId}.output`);
236
+
237
+ const child = spawn(command, [], {
238
+ cwd: workingDir,
239
+ shell: true,
240
+ detached: true,
241
+ stdio: ["ignore", "pipe", "pipe"],
242
+ env: {
243
+ ...process.env,
244
+ PATH: process.env.PATH,
245
+ HOME: process.env.HOME,
246
+ },
247
+ });
248
+
249
+ // Write output to file
250
+ const outputStream = createWriteStream(outputFile);
251
+ child.stdout?.pipe(outputStream);
252
+ child.stderr?.pipe(outputStream);
253
+
254
+ // Track the background task with project isolation
255
+ if (child.pid === undefined) {
256
+ throw new Error("Failed to start background task: process ID unavailable");
257
+ }
258
+
259
+ // Get project ID for isolation enforcement
260
+ const conversation = context.getConversation?.();
261
+ const projectId = conversation?.getProjectId();
262
+ if (!projectId) {
263
+ throw new Error("Cannot create background task: no project context available");
264
+ }
265
+
266
+ backgroundTasks.set(taskId, {
267
+ pid: child.pid,
268
+ command: command.substring(0, 200),
269
+ description: description || null,
270
+ outputFile,
271
+ startTime: new Date(),
272
+ projectId,
273
+ });
274
+
275
+ // Unref so parent can exit independently
276
+ child.unref();
277
+
278
+ // Clean up task tracking when process exits
279
+ child.on("exit", () => {
280
+ // Keep task info for a while so status can be checked
281
+ // It will be cleaned up eventually by a cleanup routine
282
+ });
283
+
284
+ span?.addEvent("shell.background_started", {
285
+ task_id: taskId,
286
+ output_file: outputFile,
287
+ pid: child.pid,
288
+ });
289
+
290
+ logger.info("Shell command started in background", {
291
+ taskId,
292
+ command: command.substring(0, 200),
293
+ description: description || undefined,
294
+ outputFile,
295
+ pid: child.pid,
296
+ });
297
+
298
+ const result: ShellBackgroundResult = {
299
+ type: "background-task",
300
+ taskId,
301
+ command: command.substring(0, 200),
302
+ description: description || null,
303
+ outputFile,
304
+ message: `Command started in background. Task ID: ${taskId}. Output is being written to: ${outputFile}`,
305
+ };
306
+
307
+ return result;
308
+ }
309
+
310
+ try {
311
+ const { stdout, stderr } = await execAsync(command, {
312
+ cwd: workingDir,
313
+ timeout: timeout != null ? timeout * 1000 : undefined,
314
+ env: {
315
+ ...process.env,
316
+ PATH: process.env.PATH,
317
+ HOME: process.env.HOME,
318
+ },
319
+ });
320
+
321
+ const output = stdout + (stderr ? `\nSTDERR:\n${stderr}` : "");
322
+
323
+ span?.addEvent("shell.execute_complete", {
324
+ has_stdout: !!stdout,
325
+ has_stderr: !!stderr,
326
+ output_length: output.length,
327
+ exit_code: 0,
328
+ });
329
+
330
+ logger.info("Shell command completed", {
331
+ command,
332
+ hasStdout: !!stdout,
333
+ hasStderr: !!stderr,
334
+ exitCode: 0,
335
+ });
336
+
337
+ return output;
338
+ } catch (error) {
339
+ // Handle exec errors - which include non-zero exit codes
340
+ const execError = error as ExecException & { stdout?: string; stderr?: string };
341
+ const exitCode = execError.code ?? null;
342
+ const stdout = execError.stdout || "";
343
+ const stderr = execError.stderr || "";
344
+ const signal = execError.signal || null;
345
+
346
+ // Check if this is an expected non-zero exit code
347
+ if (exitCode !== null) {
348
+ const { expected, explanation } = isExpectedNonZeroExit(command, exitCode);
349
+
350
+ if (expected) {
351
+ // This is NOT an error - it's expected behavior (e.g., grep found no matches)
352
+ const result: ShellExpectedNonZeroResult = {
353
+ type: "expected-non-zero-exit",
354
+ command: command.substring(0, 200),
355
+ exitCode,
356
+ stdout,
357
+ stderr,
358
+ explanation: explanation || `Command exited with code ${exitCode}`,
359
+ };
360
+
361
+ span?.addEvent("shell.execute_complete", {
362
+ has_stdout: !!stdout,
363
+ has_stderr: !!stderr,
364
+ exit_code: exitCode,
365
+ expected_non_zero: true,
366
+ explanation: explanation,
367
+ });
368
+
369
+ logger.info("Shell command completed with expected non-zero exit", {
370
+ command,
371
+ exitCode,
372
+ explanation,
373
+ hasStdout: !!stdout,
374
+ hasStderr: !!stderr,
375
+ });
376
+
377
+ // Return structured result - NOT throwing an error
378
+ return result;
379
+ }
380
+ }
381
+
382
+ // This is a genuine error - return structured error for LLM recovery
383
+ const errorResult: ShellErrorResult = {
384
+ type: "shell-error",
385
+ command: command.substring(0, 200),
386
+ exitCode,
387
+ error: execError.message,
388
+ stdout,
389
+ stderr,
390
+ signal,
391
+ };
392
+
393
+ span?.addEvent("shell.execute_error", {
394
+ exit_code: exitCode ?? "unknown",
395
+ signal: signal ?? "none",
396
+ error_message: execError.message.substring(0, 200),
397
+ has_stdout: !!stdout,
398
+ has_stderr: !!stderr,
399
+ });
400
+
401
+ logger.error("Shell command failed", {
402
+ command,
403
+ exitCode,
404
+ signal,
405
+ error: execError.message,
406
+ hasStdout: !!stdout,
407
+ hasStderr: !!stderr,
408
+ });
409
+
410
+ // Return structured error instead of throwing
411
+ // This allows the LLM to see the full context and make recovery decisions
412
+ return errorResult;
413
+ }
414
+ }
415
+
416
+ /**
417
+ * Create an AI SDK tool for executing shell commands
418
+ */
419
+ export function createShellTool(context: ToolExecutionContext): AISdkTool {
420
+ const aiTool = tool({
421
+ description: `Execute shell commands in the project directory.
422
+
423
+ IMPORTANT ESCAPING & STRING HANDLING:
424
+ - For complex/multi-line strings (git commits, PR bodies, JSON, etc.), ALWAYS use HEREDOC pattern:
425
+ command -m "$(cat <<'EOF'
426
+ Your multi-line content here
427
+ With "quotes" and $variables that don't need escaping!
428
+ EOF
429
+ )"
430
+ - Always quote file paths with spaces: cd "/path with spaces/file.txt"
431
+ - NEVER use nested quotes without HEREDOC - they will fail
432
+ - DO NOT use newlines to separate commands (newlines OK in quoted strings)
433
+
434
+ COMMAND CHAINING:
435
+ - For independent commands: Use multiple shell() calls in parallel
436
+ - For dependent sequential commands: Use && to chain (e.g., "cmd1 && cmd2 && cmd3")
437
+ - Use ; only when you don't care if earlier commands fail
438
+ - Prefer absolute paths over cd: "pytest /foo/bar/tests" NOT "cd /foo/bar && pytest tests"
439
+
440
+ WHEN NOT TO USE SHELL:
441
+ - File operations: Use fs_read/write_path (NOT cat/echo/sed/awk)
442
+ - Code modifications: Use edit tools directly (NOT sed/awk)
443
+ - File search: Use glob patterns (NOT find/ls)
444
+ - Content search: Use grep tools (NOT grep/rg commands)
445
+
446
+ OTHER RESTRICTIONS:
447
+ - NEVER use interactive flags like -i (git rebase -i, git add -i, etc.)
448
+ - Commands run with timeout in seconds (default: 30s, max: 600s / 10 minutes)
449
+
450
+ Use for: git operations, npm/build tools, docker, system commands where specialized tools don't exist.
451
+ - Time-based delays: Use shell(sleep N) to wait N seconds (e.g., shell(sleep 5) for 5 seconds).`,
452
+
453
+ inputSchema: shellSchema,
454
+
455
+ execute: async (input: ShellInput) => {
456
+ // executeShell now handles all error cases internally
457
+ // and returns structured results instead of throwing
458
+ return await executeShell(input, context);
459
+ },
460
+ });
461
+
462
+ Object.defineProperty(aiTool, "getHumanReadableContent", {
463
+ value: ({ command, description, run_in_background }: ShellInput) => {
464
+ const prefix = run_in_background ? "Running in background: " : "Executing: ";
465
+ if (description) {
466
+ return `${prefix}${description} (${command})`;
467
+ }
468
+ return `${prefix}${command}`;
469
+ },
470
+ enumerable: false,
471
+ configurable: true,
472
+ });
473
+
474
+ return aiTool as AISdkTool;
475
+ }
476
+
477
+ /**
478
+ * Get information about a background task by its ID
479
+ */
480
+ export function getBackgroundTaskInfo(taskId: string): BackgroundTaskInfo | undefined {
481
+ return backgroundTasks.get(taskId);
482
+ }
483
+
484
+ /**
485
+ * Get all background tasks
486
+ */
487
+ export function getAllBackgroundTasks(): Array<{ taskId: string } & BackgroundTaskInfo> {
488
+ return Array.from(backgroundTasks.entries()).map(([id, info]) => ({
489
+ taskId: id,
490
+ ...info,
491
+ }));
492
+ }
493
+
494
+ /**
495
+ * Kill a background task by its ID
496
+ * @returns Object with success status and message
497
+ */
498
+ export function killBackgroundTask(taskId: string): { success: boolean; message: string; pid?: number } {
499
+ const taskInfo = backgroundTasks.get(taskId);
500
+
501
+ if (!taskInfo) {
502
+ return {
503
+ success: false,
504
+ message: `No background task found with ID: ${taskId}`,
505
+ };
506
+ }
507
+
508
+ try {
509
+ // Send SIGTERM to gracefully terminate the process
510
+ process.kill(taskInfo.pid, "SIGTERM");
511
+
512
+ // Remove from tracking
513
+ backgroundTasks.delete(taskId);
514
+
515
+ logger.info("Background task killed", {
516
+ taskId,
517
+ pid: taskInfo.pid,
518
+ command: taskInfo.command,
519
+ });
520
+
521
+ return {
522
+ success: true,
523
+ message: `Successfully terminated background task ${taskId} (PID: ${taskInfo.pid})`,
524
+ pid: taskInfo.pid,
525
+ };
526
+ } catch (error) {
527
+ // Process might already be dead
528
+ if ((error as NodeJS.ErrnoException).code === "ESRCH") {
529
+ // Process doesn't exist anymore, clean up tracking
530
+ backgroundTasks.delete(taskId);
531
+ return {
532
+ success: true,
533
+ message: `Task ${taskId} was already terminated (PID: ${taskInfo.pid})`,
534
+ pid: taskInfo.pid,
535
+ };
536
+ }
537
+
538
+ logger.error("Failed to kill background task", {
539
+ taskId,
540
+ pid: taskInfo.pid,
541
+ error: error instanceof Error ? error.message : String(error),
542
+ });
543
+
544
+ return {
545
+ success: false,
546
+ message: `Failed to terminate task ${taskId}: ${error instanceof Error ? error.message : String(error)}`,
547
+ pid: taskInfo.pid,
548
+ };
549
+ }
550
+ }
551
+
552
+ // Export types for use in other modules
553
+ export type { ShellBackgroundResult, ShellErrorResult, ShellExpectedNonZeroResult };