@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,175 @@
1
+ /**
2
+ * SearchEngine - Pure search logic for conversation index.
3
+ *
4
+ * Handles:
5
+ * - Agent filtering (conversation must have at least one matching agent)
6
+ * - Date filtering (lastMessageAt >= since)
7
+ * - Case-insensitive text matching on message content
8
+ * - Snippet extraction for matches
9
+ * - Sorting by lastActivity descending
10
+ */
11
+
12
+ import type {
13
+ ConversationIndex,
14
+ ConversationIndexEntry,
15
+ MessageMatch,
16
+ SearchQuery,
17
+ SearchResult,
18
+ } from "./types";
19
+ import { extractSnippet } from "./SnippetExtractor";
20
+ import { getEffectiveSinceTimestamp } from "./QueryParser";
21
+
22
+ /**
23
+ * Check if a conversation matches the agent filter.
24
+ * Returns true if no filter is specified or if at least one agent EXACTLY matches.
25
+ * Uses case-insensitive exact matching for agent slugs/pubkeys.
26
+ */
27
+ function matchesAgentFilter(conversation: ConversationIndexEntry, agentFilter?: string[]): boolean {
28
+ if (!agentFilter || agentFilter.length === 0) {
29
+ return true;
30
+ }
31
+
32
+ // Convert agent filter to lowercase for case-insensitive exact matching
33
+ const filterLower = new Set(agentFilter.map((a) => a.toLowerCase().trim()));
34
+
35
+ // Check if any conversation agent exactly matches any filter agent
36
+ return conversation.agents.some((agent) => {
37
+ const agentLower = agent.toLowerCase().trim();
38
+ return filterLower.has(agentLower);
39
+ });
40
+ }
41
+
42
+ /**
43
+ * Check if a conversation matches the date filter.
44
+ * Returns true if no filter is specified or if lastMessageAt >= since.
45
+ */
46
+ function matchesDateFilter(conversation: ConversationIndexEntry, sinceTimestamp?: number): boolean {
47
+ if (sinceTimestamp === undefined) {
48
+ return true;
49
+ }
50
+
51
+ const lastMessageAt = conversation.lastMessageAt ?? 0;
52
+ return lastMessageAt >= sinceTimestamp;
53
+ }
54
+
55
+ /**
56
+ * Find matching messages in a conversation and extract snippets.
57
+ */
58
+ function findMatchingMessages(
59
+ conversation: ConversationIndexEntry,
60
+ searchText: string,
61
+ maxMatches: number = 3
62
+ ): MessageMatch[] {
63
+ const matches: MessageMatch[] = [];
64
+ const searchLower = searchText.toLowerCase();
65
+
66
+ for (const message of conversation.messages) {
67
+ if (matches.length >= maxMatches) break;
68
+
69
+ const contentLower = message.content.toLowerCase();
70
+ if (contentLower.includes(searchLower)) {
71
+ const snippetResult = extractSnippet(message.content, searchText);
72
+ if (snippetResult) {
73
+ matches.push({
74
+ messageId: message.messageId,
75
+ snippet: snippetResult.snippet,
76
+ });
77
+ }
78
+ }
79
+ }
80
+
81
+ return matches;
82
+ }
83
+
84
+ /**
85
+ * Search the conversation index.
86
+ *
87
+ * @param query - Parsed search query with text and filters
88
+ * @param index - The conversation index to search
89
+ * @param limit - Maximum number of results to return
90
+ * @returns Array of search results sorted by lastActivity descending
91
+ */
92
+ export function search(
93
+ query: SearchQuery,
94
+ index: ConversationIndex,
95
+ limit: number = 20
96
+ ): SearchResult[] {
97
+ const results: SearchResult[] = [];
98
+ const sinceTimestamp = getEffectiveSinceTimestamp(query.filters);
99
+
100
+ for (const conversation of index.conversations) {
101
+ // Apply filters
102
+ if (!matchesAgentFilter(conversation, query.filters.agents)) {
103
+ continue;
104
+ }
105
+
106
+ if (!matchesDateFilter(conversation, sinceTimestamp)) {
107
+ continue;
108
+ }
109
+
110
+ // Search for text matches
111
+ const matches = findMatchingMessages(conversation, query.text);
112
+
113
+ // Only include conversations with at least one match
114
+ if (matches.length === 0) {
115
+ continue;
116
+ }
117
+
118
+ results.push({
119
+ conversationId: conversation.conversationId,
120
+ title: conversation.title,
121
+ messageCount: conversation.messageCount,
122
+ createdAt: conversation.messages[0]?.timestamp,
123
+ lastActivity: conversation.lastMessageAt,
124
+ matches,
125
+ });
126
+ }
127
+
128
+ // Sort by lastActivity descending (most recent first)
129
+ results.sort((a, b) => {
130
+ const aTime = a.lastActivity ?? 0;
131
+ const bTime = b.lastActivity ?? 0;
132
+ return bTime - aTime;
133
+ });
134
+
135
+ // Apply limit
136
+ return results.slice(0, limit);
137
+ }
138
+
139
+ /**
140
+ * Search with title-only fallback for backward compatibility.
141
+ * This searches only by title, not message content.
142
+ */
143
+ export function searchByTitleOnly(
144
+ query: string,
145
+ index: ConversationIndex,
146
+ limit: number = 20
147
+ ): SearchResult[] {
148
+ const results: SearchResult[] = [];
149
+ const queryLower = query.toLowerCase();
150
+
151
+ for (const conversation of index.conversations) {
152
+ if (conversation.title && conversation.title.toLowerCase().includes(queryLower)) {
153
+ results.push({
154
+ conversationId: conversation.conversationId,
155
+ title: conversation.title,
156
+ messageCount: conversation.messageCount,
157
+ createdAt: conversation.messages[0]?.timestamp,
158
+ lastActivity: conversation.lastMessageAt,
159
+ matches: [{
160
+ messageId: "title",
161
+ snippet: conversation.title,
162
+ }],
163
+ });
164
+ }
165
+ }
166
+
167
+ // Sort by lastActivity descending
168
+ results.sort((a, b) => {
169
+ const aTime = a.lastActivity ?? 0;
170
+ const bTime = b.lastActivity ?? 0;
171
+ return bTime - aTime;
172
+ });
173
+
174
+ return results.slice(0, limit);
175
+ }
@@ -0,0 +1,345 @@
1
+ /**
2
+ * SnippetExtractor - Pure utility for extracting search result snippets.
3
+ *
4
+ * Extracts snippets with 50-75 character TOTAL length (including matched text),
5
+ * finding word boundaries for cleaner snippets.
6
+ */
7
+
8
+ /** Maximum total snippet length (50-75 char target range) */
9
+ const MAX_SNIPPET_LENGTH = 75;
10
+
11
+ /**
12
+ * Result of snippet extraction.
13
+ */
14
+ export interface SnippetResult {
15
+ /** The full snippet including context */
16
+ snippet: string;
17
+ /** The actual matched text */
18
+ matchedText: string;
19
+ /** Start index of match in original content */
20
+ matchStart: number;
21
+ /** End index of match in original content */
22
+ matchEnd: number;
23
+ }
24
+
25
+ /**
26
+ * Find the nearest word boundary before the given index.
27
+ * Returns the index of the character after the boundary (space, punctuation, etc.)
28
+ */
29
+ function findWordBoundaryBefore(text: string, index: number, minIndex: number): number {
30
+ if (index <= minIndex) return minIndex;
31
+
32
+ // Look for a space or punctuation within a reasonable range
33
+ let pos = index;
34
+ const lookbackLimit = Math.max(minIndex, index - 10); // Don't look too far back
35
+
36
+ while (pos > lookbackLimit) {
37
+ const char = text[pos - 1];
38
+ if (char === " " || char === "\n" || char === "\t") {
39
+ return pos; // Return position after the whitespace
40
+ }
41
+ if (char === "." || char === "," || char === ";" || char === ":" || char === "!" || char === "?") {
42
+ return pos; // Return position after punctuation
43
+ }
44
+ pos--;
45
+ }
46
+
47
+ // No clean boundary found, use the calculated index
48
+ return Math.max(minIndex, index);
49
+ }
50
+
51
+ /**
52
+ * Find the nearest word boundary after the given index.
53
+ * Returns the index of the boundary character.
54
+ */
55
+ function findWordBoundaryAfter(text: string, index: number, maxIndex: number): number {
56
+ if (index >= maxIndex) return maxIndex;
57
+
58
+ // Look for a space or punctuation within a reasonable range
59
+ let pos = index;
60
+ const lookaheadLimit = Math.min(maxIndex, index + 10); // Don't look too far ahead
61
+
62
+ while (pos < lookaheadLimit) {
63
+ const char = text[pos];
64
+ if (char === " " || char === "\n" || char === "\t") {
65
+ return pos; // Return position of the whitespace
66
+ }
67
+ if (char === "." || char === "," || char === ";" || char === ":" || char === "?") {
68
+ return pos + 1; // Include the punctuation
69
+ }
70
+ if (char === "!") {
71
+ return pos + 1; // Include the punctuation
72
+ }
73
+ pos++;
74
+ }
75
+
76
+ // No clean boundary found, use the calculated index
77
+ return Math.min(maxIndex, index);
78
+ }
79
+
80
+ /**
81
+ * Extract a snippet from content around a search match.
82
+ * Ensures TOTAL snippet length is between 50-75 characters.
83
+ *
84
+ * @param content - The full message content
85
+ * @param searchText - The text that was searched for
86
+ * @returns SnippetResult if match found, null otherwise
87
+ */
88
+ export function extractSnippet(content: string, searchText: string): SnippetResult | null {
89
+ if (!content || !searchText) return null;
90
+
91
+ // Case-insensitive search
92
+ const contentLower = content.toLowerCase();
93
+ const searchLower = searchText.toLowerCase();
94
+
95
+ const matchStart = contentLower.indexOf(searchLower);
96
+ if (matchStart === -1) return null;
97
+
98
+ const matchEnd = matchStart + searchText.length;
99
+ const matchedText = content.substring(matchStart, matchEnd);
100
+ const matchLength = matchedText.length;
101
+
102
+ // If the match is exactly MAX_SNIPPET_LENGTH, return it as-is (no truncation needed)
103
+ if (matchLength === MAX_SNIPPET_LENGTH) {
104
+ return {
105
+ snippet: matchedText,
106
+ matchedText,
107
+ matchStart,
108
+ matchEnd,
109
+ };
110
+ }
111
+
112
+ // If the match exceeds MAX_SNIPPET_LENGTH, truncate to 72 chars + "..." = 75 total
113
+ if (matchLength > MAX_SNIPPET_LENGTH) {
114
+ const truncateLength = MAX_SNIPPET_LENGTH - 3;
115
+ const truncated = matchedText.substring(0, truncateLength);
116
+ return {
117
+ snippet: truncated + "...",
118
+ matchedText: truncated,
119
+ matchStart,
120
+ matchEnd: matchStart + truncated.length,
121
+ };
122
+ }
123
+
124
+ // Calculate available space for context (total snippet should be 50-75 chars)
125
+ // Target: use up to MAX_SNIPPET_LENGTH total, at least MIN_SNIPPET_LENGTH if possible
126
+ const availableContext = MAX_SNIPPET_LENGTH - matchLength;
127
+ const contextPerSide = Math.floor(availableContext / 2);
128
+
129
+ // Calculate ideal context boundaries
130
+ let contextStart = Math.max(0, matchStart - contextPerSide);
131
+ let contextEnd = Math.min(content.length, matchEnd + contextPerSide);
132
+
133
+ // Adjust to word boundaries (but stay within our budget)
134
+ if (contextStart > 0) {
135
+ const adjustedStart = findWordBoundaryBefore(content, contextStart, Math.max(0, matchStart - contextPerSide - 5));
136
+ // Only use adjusted start if it doesn't blow our budget
137
+ if (matchEnd - adjustedStart + (contextEnd - matchEnd) <= MAX_SNIPPET_LENGTH) {
138
+ contextStart = adjustedStart;
139
+ }
140
+ }
141
+ if (contextEnd < content.length) {
142
+ const adjustedEnd = findWordBoundaryAfter(content, contextEnd, Math.min(content.length, matchEnd + contextPerSide + 5));
143
+ // Only use adjusted end if it doesn't blow our budget
144
+ if (adjustedEnd - contextStart <= MAX_SNIPPET_LENGTH) {
145
+ contextEnd = adjustedEnd;
146
+ }
147
+ }
148
+
149
+ // Final enforcement: hard cap at MAX_SNIPPET_LENGTH
150
+ if (contextEnd - contextStart > MAX_SNIPPET_LENGTH) {
151
+ // Trim from whichever side has more context, prioritizing keeping the match centered
152
+ const beforeMatch = matchStart - contextStart;
153
+ const afterMatch = contextEnd - matchEnd;
154
+
155
+ if (beforeMatch > afterMatch) {
156
+ // Trim from start
157
+ contextStart = contextEnd - MAX_SNIPPET_LENGTH;
158
+ } else {
159
+ // Trim from end
160
+ contextEnd = contextStart + MAX_SNIPPET_LENGTH;
161
+ }
162
+ }
163
+
164
+ // Ensure we don't cut into the match
165
+ if (contextStart > matchStart) contextStart = matchStart;
166
+ if (contextEnd < matchEnd) contextEnd = matchEnd;
167
+
168
+ // Build snippet
169
+ let snippet = content.substring(contextStart, contextEnd);
170
+
171
+ // Normalize whitespace
172
+ snippet = snippet.replace(/\s+/g, " ").trim();
173
+
174
+ // Add ellipsis if truncated (but count them in length)
175
+ const needsPrefixEllipsis = contextStart > 0;
176
+ const needsSuffixEllipsis = contextEnd < content.length;
177
+
178
+ // Adjust for ellipsis length (3 chars each)
179
+ const ellipsisLength = (needsPrefixEllipsis ? 3 : 0) + (needsSuffixEllipsis ? 3 : 0);
180
+ if (snippet.length + ellipsisLength > MAX_SNIPPET_LENGTH) {
181
+ // Trim snippet to make room for ellipsis
182
+ const targetLength = MAX_SNIPPET_LENGTH - ellipsisLength;
183
+ if (snippet.length > targetLength) {
184
+ // Trim evenly from both sides if possible
185
+ const excess = snippet.length - targetLength;
186
+ const trimStart = Math.floor(excess / 2);
187
+ const trimEnd = excess - trimStart;
188
+ snippet = snippet.substring(trimStart, snippet.length - trimEnd);
189
+ }
190
+ }
191
+
192
+ if (needsPrefixEllipsis) {
193
+ snippet = "..." + snippet;
194
+ }
195
+ if (needsSuffixEllipsis) {
196
+ snippet = snippet + "...";
197
+ }
198
+
199
+ return {
200
+ snippet,
201
+ matchedText,
202
+ matchStart,
203
+ matchEnd,
204
+ };
205
+ }
206
+
207
+ /**
208
+ * Extract a snippet from content at a specific match position.
209
+ * Used by extractAllSnippets to get snippets with proper context.
210
+ *
211
+ * @param content - The full message content
212
+ * @param matchStart - Start index of the match in the original content
213
+ * @param matchLength - Length of the matched text
214
+ * @returns SnippetResult
215
+ */
216
+ function extractSnippetAtPosition(content: string, matchStart: number, matchLength: number): SnippetResult {
217
+ const matchEnd = matchStart + matchLength;
218
+ const matchedText = content.substring(matchStart, matchEnd);
219
+
220
+ // If the match is exactly MAX_SNIPPET_LENGTH, return it as-is (no truncation needed)
221
+ if (matchLength === MAX_SNIPPET_LENGTH) {
222
+ return {
223
+ snippet: matchedText,
224
+ matchedText,
225
+ matchStart,
226
+ matchEnd,
227
+ };
228
+ }
229
+
230
+ // If the match exceeds MAX_SNIPPET_LENGTH, truncate to 72 chars + "..." = 75 total
231
+ if (matchLength > MAX_SNIPPET_LENGTH) {
232
+ const truncateLength = MAX_SNIPPET_LENGTH - 3;
233
+ const truncated = matchedText.substring(0, truncateLength);
234
+ return {
235
+ snippet: truncated + "...",
236
+ matchedText: truncated,
237
+ matchStart,
238
+ matchEnd: matchStart + truncated.length,
239
+ };
240
+ }
241
+
242
+ // Calculate available space for context
243
+ const availableContext = MAX_SNIPPET_LENGTH - matchLength;
244
+ const contextPerSide = Math.floor(availableContext / 2);
245
+
246
+ // Calculate ideal context boundaries
247
+ let contextStart = Math.max(0, matchStart - contextPerSide);
248
+ let contextEnd = Math.min(content.length, matchEnd + contextPerSide);
249
+
250
+ // Adjust to word boundaries (but stay within our budget)
251
+ if (contextStart > 0) {
252
+ const adjustedStart = findWordBoundaryBefore(content, contextStart, Math.max(0, matchStart - contextPerSide - 5));
253
+ if (matchEnd - adjustedStart + (contextEnd - matchEnd) <= MAX_SNIPPET_LENGTH) {
254
+ contextStart = adjustedStart;
255
+ }
256
+ }
257
+ if (contextEnd < content.length) {
258
+ const adjustedEnd = findWordBoundaryAfter(content, contextEnd, Math.min(content.length, matchEnd + contextPerSide + 5));
259
+ if (adjustedEnd - contextStart <= MAX_SNIPPET_LENGTH) {
260
+ contextEnd = adjustedEnd;
261
+ }
262
+ }
263
+
264
+ // Final enforcement: hard cap at MAX_SNIPPET_LENGTH
265
+ if (contextEnd - contextStart > MAX_SNIPPET_LENGTH) {
266
+ const beforeMatch = matchStart - contextStart;
267
+ const afterMatch = contextEnd - matchEnd;
268
+
269
+ if (beforeMatch > afterMatch) {
270
+ contextStart = contextEnd - MAX_SNIPPET_LENGTH;
271
+ } else {
272
+ contextEnd = contextStart + MAX_SNIPPET_LENGTH;
273
+ }
274
+ }
275
+
276
+ // Ensure we don't cut into the match
277
+ if (contextStart > matchStart) contextStart = matchStart;
278
+ if (contextEnd < matchEnd) contextEnd = matchEnd;
279
+
280
+ // Build snippet
281
+ let snippet = content.substring(contextStart, contextEnd);
282
+ snippet = snippet.replace(/\s+/g, " ").trim();
283
+
284
+ const needsPrefixEllipsis = contextStart > 0;
285
+ const needsSuffixEllipsis = contextEnd < content.length;
286
+
287
+ const ellipsisLength = (needsPrefixEllipsis ? 3 : 0) + (needsSuffixEllipsis ? 3 : 0);
288
+ if (snippet.length + ellipsisLength > MAX_SNIPPET_LENGTH) {
289
+ const targetLength = MAX_SNIPPET_LENGTH - ellipsisLength;
290
+ if (snippet.length > targetLength) {
291
+ const excess = snippet.length - targetLength;
292
+ const trimStart = Math.floor(excess / 2);
293
+ const trimEnd = excess - trimStart;
294
+ snippet = snippet.substring(trimStart, snippet.length - trimEnd);
295
+ }
296
+ }
297
+
298
+ if (needsPrefixEllipsis) {
299
+ snippet = "..." + snippet;
300
+ }
301
+ if (needsSuffixEllipsis) {
302
+ snippet = snippet + "...";
303
+ }
304
+
305
+ return {
306
+ snippet,
307
+ matchedText,
308
+ matchStart,
309
+ matchEnd,
310
+ };
311
+ }
312
+
313
+ /**
314
+ * Extract all snippets from content for a search term.
315
+ * Computes snippets against full content with proper offsets.
316
+ *
317
+ * @param content - The full message content
318
+ * @param searchText - The text to search for
319
+ * @param maxSnippets - Maximum number of snippets to return (default: 3)
320
+ */
321
+ export function extractAllSnippets(
322
+ content: string,
323
+ searchText: string,
324
+ maxSnippets: number = 3
325
+ ): SnippetResult[] {
326
+ if (!content || !searchText) return [];
327
+
328
+ const results: SnippetResult[] = [];
329
+ const contentLower = content.toLowerCase();
330
+ const searchLower = searchText.toLowerCase();
331
+
332
+ let startPos = 0;
333
+ while (results.length < maxSnippets) {
334
+ const matchStart = contentLower.indexOf(searchLower, startPos);
335
+ if (matchStart === -1) break;
336
+
337
+ // Extract snippet using the full content with the correct match position
338
+ const result = extractSnippetAtPosition(content, matchStart, searchText.length);
339
+ results.push(result);
340
+
341
+ startPos = matchStart + searchText.length;
342
+ }
343
+
344
+ return results;
345
+ }