@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,223 @@
1
+ import * as fileSystem from "@/lib/fs";
2
+ import { config as configService } from "@/services/ConfigService";
3
+ import { logger } from "@/utils/logger";
4
+ import { Command } from "commander";
5
+ import { spawn } from "node:child_process";
6
+ import * as fs from "node:fs/promises";
7
+ import * as os from "node:os";
8
+ import * as path from "node:path";
9
+
10
+ /**
11
+ * Get the user's preferred editor
12
+ * Checks $VISUAL, $EDITOR, then falls back to common defaults
13
+ */
14
+ function getEditor(): string {
15
+ // Check standard environment variables
16
+ if (process.env.VISUAL) {
17
+ return process.env.VISUAL;
18
+ }
19
+ if (process.env.EDITOR) {
20
+ return process.env.EDITOR;
21
+ }
22
+
23
+ // Platform-specific defaults
24
+ if (process.platform === "win32") {
25
+ return "notepad";
26
+ }
27
+
28
+ // Unix-like systems - try common editors
29
+ return "nano"; // Most user-friendly default
30
+ }
31
+
32
+ /**
33
+ * Open a file in the user's preferred editor and wait for them to close it
34
+ */
35
+ async function openInEditor(filePath: string): Promise<void> {
36
+ const editor = getEditor();
37
+
38
+ return new Promise((resolve, reject) => {
39
+ // Use shell to properly handle $EDITOR values with quoted paths or complex arguments
40
+ // e.g., EDITOR="code --wait" or EDITOR='"/path/with spaces/code" --wait'
41
+ const fullCommand = `${editor} "${filePath}"`;
42
+
43
+ logger.debug(`Opening editor with command: ${fullCommand}`);
44
+
45
+ const child = spawn(fullCommand, [], {
46
+ stdio: "inherit",
47
+ shell: true,
48
+ });
49
+
50
+ child.on("error", (error) => {
51
+ reject(new Error(`Failed to open editor '${editor}': ${error.message}`));
52
+ });
53
+
54
+ child.on("close", (code) => {
55
+ if (code === 0 || code === null) {
56
+ resolve();
57
+ } else {
58
+ reject(new Error(`Editor exited with code ${code}`));
59
+ }
60
+ });
61
+ });
62
+ }
63
+
64
+ /**
65
+ * Command for configuring global system prompt
66
+ *
67
+ * Opens the user's preferred editor to edit a system prompt fragment that
68
+ * will be added to ALL projects' system prompts.
69
+ */
70
+ export const globalSystemPromptCommand = new Command("global-system-prompt")
71
+ .description("Configure a global system prompt that is added to all projects")
72
+ .option("--disable", "Disable the global system prompt without deleting it")
73
+ .option("--enable", "Enable the global system prompt")
74
+ .option("--show", "Show the current global system prompt")
75
+ .action(async (options) => {
76
+ try {
77
+ const globalPath = configService.getGlobalPath();
78
+
79
+ // Ensure global config directory exists
80
+ await fileSystem.ensureDirectory(globalPath);
81
+
82
+ // Load existing configuration
83
+ const existingConfig = await configService.loadTenexConfig(globalPath);
84
+
85
+ // Handle --show flag
86
+ if (options.show) {
87
+ const content = existingConfig.globalSystemPrompt?.content;
88
+ const enabled = existingConfig.globalSystemPrompt?.enabled !== false;
89
+
90
+ if (!content || content.trim().length === 0) {
91
+ logger.info("No global system prompt configured.");
92
+ } else {
93
+ logger.info(`Global System Prompt (${enabled ? "enabled" : "disabled"}):`);
94
+ logger.info("─".repeat(50));
95
+ console.log(content);
96
+ logger.info("─".repeat(50));
97
+ }
98
+ return;
99
+ }
100
+
101
+ // Handle --disable flag
102
+ if (options.disable) {
103
+ const newConfig = {
104
+ ...existingConfig,
105
+ globalSystemPrompt: {
106
+ ...existingConfig.globalSystemPrompt,
107
+ enabled: false,
108
+ },
109
+ };
110
+ await configService.saveGlobalConfig(newConfig);
111
+ logger.info("Global system prompt disabled.");
112
+ return;
113
+ }
114
+
115
+ // Handle --enable flag
116
+ if (options.enable) {
117
+ const newConfig = {
118
+ ...existingConfig,
119
+ globalSystemPrompt: {
120
+ ...existingConfig.globalSystemPrompt,
121
+ enabled: true,
122
+ },
123
+ };
124
+ await configService.saveGlobalConfig(newConfig);
125
+ logger.info("Global system prompt enabled.");
126
+ return;
127
+ }
128
+
129
+ // Default action: open editor
130
+ // Create a temporary file with existing content
131
+ const tempDir = os.tmpdir();
132
+ const tempFile = path.join(tempDir, `tenex-global-prompt-${Date.now()}.md`);
133
+
134
+ // Delimiter that separates template instructions from user content
135
+ const CONTENT_DELIMITER = "---- YOUR PROMPT BELOW THIS LINE ----";
136
+
137
+ // Get existing content or provide a template
138
+ const existingContent = existingConfig.globalSystemPrompt?.content || "";
139
+ const templateHeader = `# Global System Prompt Configuration
140
+ #
141
+ # This content will be added to ALL agents' system prompts across ALL projects.
142
+ #
143
+ # Examples of what you might put here:
144
+ # - Personal preferences (e.g., "Always use TypeScript strict mode")
145
+ # - Coding standards (e.g., "Follow clean code principles")
146
+ # - Communication preferences (e.g., "Be concise in responses")
147
+ #
148
+ # IMPORTANT: Write your prompt BELOW the delimiter line.
149
+ # Everything above the delimiter will be discarded.
150
+ # Everything below (including markdown # headings) will be preserved.
151
+ #
152
+ # Save and close this file when done.
153
+
154
+ ${CONTENT_DELIMITER}
155
+ `;
156
+ const templateContent = templateHeader + existingContent;
157
+
158
+ await fs.writeFile(tempFile, templateContent, "utf-8");
159
+
160
+ logger.info(
161
+ "Opening editor to configure global system prompt...\n" +
162
+ `(Using editor: ${getEditor()})\n`
163
+ );
164
+
165
+ // Open editor and wait for it to close - use try/finally for cleanup
166
+ let editedContent: string;
167
+ try {
168
+ await openInEditor(tempFile);
169
+ editedContent = await fs.readFile(tempFile, "utf-8");
170
+ } finally {
171
+ // Always clean up temp file, even on error or interrupt
172
+ try {
173
+ await fs.unlink(tempFile);
174
+ } catch {
175
+ // Ignore cleanup errors
176
+ }
177
+ }
178
+
179
+ // Extract content after the delimiter, preserving all content including # headings
180
+ const delimiterIndex = editedContent.indexOf(CONTENT_DELIMITER);
181
+ let cleanedContent: string;
182
+ if (delimiterIndex !== -1) {
183
+ // Take everything after the delimiter line
184
+ const afterDelimiter = editedContent.substring(
185
+ delimiterIndex + CONTENT_DELIMITER.length
186
+ );
187
+ cleanedContent = afterDelimiter.trim();
188
+ } else {
189
+ // No delimiter found - use entire content (user may have deleted template)
190
+ cleanedContent = editedContent.trim();
191
+ }
192
+
193
+ // Save the configuration
194
+ const newConfig = {
195
+ ...existingConfig,
196
+ globalSystemPrompt: {
197
+ enabled: true,
198
+ content: cleanedContent,
199
+ },
200
+ };
201
+
202
+ await configService.saveGlobalConfig(newConfig);
203
+
204
+ if (cleanedContent.length === 0) {
205
+ logger.info("Global system prompt cleared (no content).");
206
+ } else {
207
+ logger.info(
208
+ "Global system prompt saved successfully!\n" +
209
+ `Content length: ${cleanedContent.length} characters\n\n` +
210
+ "This prompt will be added to all agents' system prompts."
211
+ );
212
+ }
213
+ } catch (error: unknown) {
214
+ // Handle SIGINT (Ctrl+C) gracefully
215
+ const errorMessage = error instanceof Error ? error.message : String(error);
216
+ if (errorMessage?.includes("SIGINT") || errorMessage?.includes("force closed")) {
217
+ return;
218
+ }
219
+
220
+ logger.error(`Failed to configure global system prompt: ${error}`);
221
+ process.exitCode = 1;
222
+ }
223
+ });
@@ -0,0 +1,179 @@
1
+ import * as fileSystem from "@/lib/fs";
2
+ import {
3
+ ImageGenerationService,
4
+ OPENROUTER_IMAGE_MODELS,
5
+ ASPECT_RATIOS,
6
+ IMAGE_SIZES,
7
+ type ImageConfig,
8
+ } from "@/services/image/ImageGenerationService";
9
+ import { config as configService } from "@/services/ConfigService";
10
+ import { logger } from "@/utils/logger";
11
+ import { Command } from "commander";
12
+ import inquirer from "inquirer";
13
+
14
+ /**
15
+ * Command for configuring image generation with OpenRouter
16
+ */
17
+ export const imageCommand = new Command("image")
18
+ .description(
19
+ "Configure image generation model (global by default, --project for current project)"
20
+ )
21
+ .option("--project", "Use project-specific configuration instead of global")
22
+ .action(async (options) => {
23
+ try {
24
+ const scope: "global" | "project" = options.project ? "project" : "global";
25
+ const projectPath = process.cwd();
26
+ const baseDir =
27
+ scope === "project"
28
+ ? configService.getProjectPath(projectPath)
29
+ : configService.getGlobalPath();
30
+
31
+ if (scope === "project") {
32
+ // Check if we're in a TENEX project
33
+ if (!(await fileSystem.directoryExists(baseDir))) {
34
+ logger.error(
35
+ "No .tenex directory found. Make sure you're in a TENEX project directory."
36
+ );
37
+ process.exitCode = 1;
38
+ return;
39
+ }
40
+ } else {
41
+ // Ensure global config directory exists
42
+ await fileSystem.ensureDirectory(baseDir);
43
+ }
44
+
45
+ // Load existing configuration
46
+ const existing = await ImageGenerationService.loadConfiguration({
47
+ scope,
48
+ projectPath: scope === "project" ? projectPath : undefined,
49
+ });
50
+
51
+ // Check if OpenRouter is configured
52
+ const providersConfig = await configService.loadTenexProviders(configService.getGlobalPath());
53
+ if (!providersConfig.providers.openrouter?.apiKey) {
54
+ logger.error(
55
+ "OpenRouter is not configured. Run `tenex setup providers` and add your OpenRouter API key first."
56
+ );
57
+ logger.info(
58
+ "\nImage generation requires OpenRouter. Get an API key at: https://openrouter.ai/keys"
59
+ );
60
+ process.exitCode = 1;
61
+ return;
62
+ }
63
+
64
+ logger.info("✓ OpenRouter API key found\n");
65
+
66
+ // Build model choices
67
+ const modelChoices = OPENROUTER_IMAGE_MODELS.map((m) => ({
68
+ name: `${m.name} - ${m.description}`,
69
+ value: m.value,
70
+ }));
71
+
72
+ // Add custom model option
73
+ modelChoices.push({
74
+ name: "Custom model (enter OpenRouter model ID)",
75
+ value: "custom",
76
+ });
77
+
78
+ // Prompt for model selection
79
+ const { model: selectedModel } = await inquirer.prompt([
80
+ {
81
+ type: "select",
82
+ name: "model",
83
+ message: "Select default image generation model:",
84
+ choices: modelChoices,
85
+ default: existing?.model || OPENROUTER_IMAGE_MODELS[0]?.value,
86
+ },
87
+ ]);
88
+
89
+ let model = selectedModel;
90
+ if (selectedModel === "custom") {
91
+ const customAnswer = await inquirer.prompt([
92
+ {
93
+ type: "input",
94
+ name: "customModel",
95
+ message: "Enter OpenRouter model ID (e.g., black-forest-labs/flux.2-pro):",
96
+ validate: (input: string) =>
97
+ input.trim().length > 0 || "Model ID cannot be empty",
98
+ },
99
+ ]);
100
+ model = customAnswer.customModel;
101
+ }
102
+
103
+ // Prompt for default aspect ratio
104
+ const aspectRatioChoices = ASPECT_RATIOS.map((ratio) => {
105
+ let description = "";
106
+ if (ratio === "1:1") description = " (square)";
107
+ else if (ratio === "16:9") description = " (widescreen landscape)";
108
+ else if (ratio === "9:16") description = " (portrait/mobile)";
109
+ else if (ratio === "4:3") description = " (classic)";
110
+ else if (ratio === "3:4") description = " (portrait classic)";
111
+ else if (ratio === "3:2") description = " (photo landscape)";
112
+ else if (ratio === "2:3") description = " (photo portrait)";
113
+ return { name: `${ratio}${description}`, value: ratio };
114
+ });
115
+
116
+ const { aspectRatio } = await inquirer.prompt([
117
+ {
118
+ type: "select",
119
+ name: "aspectRatio",
120
+ message: "Select default aspect ratio:",
121
+ choices: aspectRatioChoices,
122
+ default: existing?.defaultAspectRatio || "1:1",
123
+ },
124
+ ]);
125
+
126
+ // Prompt for default image size
127
+ const imageSizeChoices = IMAGE_SIZES.map((size) => {
128
+ let description = "";
129
+ if (size === "1K") description = " (fastest, lowest cost)";
130
+ else if (size === "2K") description = " (balanced)";
131
+ else if (size === "4K") description = " (highest quality, most expensive)";
132
+ return { name: `${size}${description}`, value: size };
133
+ });
134
+
135
+ const { imageSize } = await inquirer.prompt([
136
+ {
137
+ type: "select",
138
+ name: "imageSize",
139
+ message: "Select default image size:",
140
+ choices: imageSizeChoices,
141
+ default: existing?.defaultImageSize || "2K",
142
+ },
143
+ ]);
144
+
145
+ // Save configuration
146
+ const imageConfig: ImageConfig = {
147
+ provider: "openrouter",
148
+ model,
149
+ defaultAspectRatio: aspectRatio,
150
+ defaultImageSize: imageSize,
151
+ };
152
+
153
+ await ImageGenerationService.saveConfiguration(imageConfig, scope, {
154
+ projectPath: scope === "project" ? projectPath : undefined,
155
+ });
156
+
157
+ // Get model display name
158
+ const modelInfo = OPENROUTER_IMAGE_MODELS.find((m) => m.value === model);
159
+ const modelDisplayName = modelInfo ? modelInfo.name : model;
160
+
161
+ logger.info(
162
+ `\n✅ Image generation configured for ${scope}\n` +
163
+ ` Provider: OpenRouter\n` +
164
+ ` Model: ${modelDisplayName} (${model})\n` +
165
+ ` Default aspect ratio: ${aspectRatio}\n` +
166
+ ` Default image size: ${imageSize}\n` +
167
+ "\nAgents can now use the generate_image tool to create images."
168
+ );
169
+ } catch (error: unknown) {
170
+ // Handle SIGINT (Ctrl+C) gracefully
171
+ const errorMessage = error instanceof Error ? error.message : String(error);
172
+ if (errorMessage?.includes("SIGINT") || errorMessage?.includes("force closed")) {
173
+ return;
174
+ }
175
+
176
+ logger.error(`Failed to configure image generation: ${error}`);
177
+ process.exitCode = 1;
178
+ }
179
+ });
@@ -0,0 +1,16 @@
1
+ import { embedCommand } from "@/commands/setup/embed";
2
+ import { globalSystemPromptCommand } from "@/commands/setup/global-system-prompt";
3
+ import { imageCommand } from "@/commands/setup/image";
4
+ import { llmCommand } from "@/commands/setup/llm";
5
+ import { onboardingCommand } from "@/commands/setup/onboarding";
6
+ import { providersCommand } from "@/commands/setup/providers";
7
+ import { Command } from "commander";
8
+
9
+ export const setupCommand = new Command("setup")
10
+ .description("Setup and configuration commands")
11
+ .addCommand(onboardingCommand, { isDefault: true })
12
+ .addCommand(providersCommand)
13
+ .addCommand(llmCommand)
14
+ .addCommand(embedCommand)
15
+ .addCommand(imageCommand)
16
+ .addCommand(globalSystemPromptCommand);
@@ -0,0 +1,95 @@
1
+ import { LLMConfigEditor } from "@/llm/LLMConfigEditor";
2
+ import { config } from "@/services/ConfigService";
3
+ import type { TenexConfig } from "@/services/config/types";
4
+ import { logger } from "@/utils/logger";
5
+ import chalk from "chalk";
6
+ import inquirer from "inquirer";
7
+
8
+ export async function runInteractiveSetup(): Promise<TenexConfig> {
9
+ logger.info(chalk.cyan("\n🚀 Welcome to TENEX Daemon Setup\n"));
10
+ logger.info("Let's configure your daemon to get started.\n");
11
+
12
+ // Load current configuration to check what's missing
13
+ const { config: currentConfig, llms: currentLLMs } = await config.loadConfig();
14
+ const needsPubkeys =
15
+ !currentConfig.whitelistedPubkeys || currentConfig.whitelistedPubkeys.length === 0;
16
+ const needsLLMs =
17
+ !currentLLMs.configurations || Object.keys(currentLLMs.configurations).length === 0;
18
+
19
+ let pubkeys = currentConfig.whitelistedPubkeys || [];
20
+
21
+ // Step 1: Get whitelisted pubkeys if needed
22
+ if (needsPubkeys) {
23
+ pubkeys = await promptForPubkeys();
24
+ }
25
+
26
+ const tenexConfig: TenexConfig = {
27
+ ...currentConfig,
28
+ whitelistedPubkeys: pubkeys,
29
+ };
30
+
31
+ // Step 2: Save basic configuration (preserving existing settings)
32
+ await config.saveGlobalConfig(tenexConfig);
33
+
34
+ // Step 3: Set up LLM configurations if needed
35
+ if (needsLLMs) {
36
+ logger.info(chalk.yellow("\nStep 2: LLM Configuration"));
37
+ logger.info("You need at least one LLM configuration to run projects.\n");
38
+
39
+ const llmEditor = new LLMConfigEditor();
40
+ await llmEditor.runOnboardingFlow();
41
+ }
42
+
43
+ logger.info(chalk.green("\n✅ Setup complete!"));
44
+ logger.info(chalk.green(`Configuration saved to: ${config.getGlobalPath()}/`));
45
+ logger.info(
46
+ chalk.gray("\nYou can now run 'tenex daemon' to start the daemon with your configuration.")
47
+ );
48
+
49
+ return tenexConfig;
50
+ }
51
+
52
+ async function promptForPubkeys(): Promise<string[]> {
53
+ logger.info(chalk.yellow("Step 1: Whitelist Configuration"));
54
+ logger.info("Enter the Nostr pubkeys (hex format) that are allowed to control this daemon.");
55
+ logger.info("You can add multiple pubkeys, one at a time.\n");
56
+
57
+ const pubkeys: string[] = [];
58
+ let addMore = true;
59
+
60
+ while (addMore) {
61
+ const { pubkey } = await inquirer.prompt([
62
+ {
63
+ type: "input",
64
+ name: "pubkey",
65
+ message: "Enter a pubkey (hex format):",
66
+ validate: (input) => {
67
+ if (!input.trim()) {
68
+ return "Pubkey cannot be empty";
69
+ }
70
+ if (!/^[a-f0-9]{64}$/i.test(input.trim())) {
71
+ return "Invalid pubkey format. Must be 64 hex characters";
72
+ }
73
+ return true;
74
+ },
75
+ },
76
+ ]);
77
+
78
+ pubkeys.push(pubkey.trim().toLowerCase());
79
+
80
+ if (pubkeys.length > 0) {
81
+ const { continueAdding } = await inquirer.prompt([
82
+ {
83
+ type: "confirm",
84
+ name: "continueAdding",
85
+ message: "Add another pubkey?",
86
+ default: false,
87
+ },
88
+ ]);
89
+ addMore = continueAdding;
90
+ }
91
+ }
92
+
93
+ logger.info(chalk.green(`\n✓ Added ${pubkeys.length} whitelisted pubkey(s)\n`));
94
+ return pubkeys;
95
+ }
@@ -0,0 +1,38 @@
1
+ import * as fileSystem from "@/lib/fs";
2
+ import { LLMConfigEditor } from "@/llm/LLMConfigEditor";
3
+ import { config } from "@/services/ConfigService";
4
+ import { logger } from "@/utils/logger";
5
+ import { Command } from "commander";
6
+
7
+ export const llmCommand = new Command("llm")
8
+ .description("Manage LLM configurations (global only)")
9
+ .action(async () => {
10
+ try {
11
+ // LLM configuration is global only
12
+ const globalConfigDir = config.getGlobalPath();
13
+
14
+ // Ensure global config directory exists
15
+ await fileSystem.ensureDirectory(globalConfigDir);
16
+
17
+ const providersConfig = await config.loadTenexProviders(globalConfigDir);
18
+ if (Object.keys(providersConfig.providers).length === 0) {
19
+ logger.error(
20
+ "No providers configured. Run `tenex setup providers` before configuring LLMs."
21
+ );
22
+ process.exitCode = 1;
23
+ return;
24
+ }
25
+
26
+ const llmManager = new LLMConfigEditor();
27
+ await llmManager.showMainMenu();
28
+ } catch (error: unknown) {
29
+ // Handle SIGINT (Ctrl+C) gracefully - just exit without error
30
+ const errorMessage = error instanceof Error ? error.message : String(error);
31
+ if (errorMessage?.includes("SIGINT") || errorMessage?.includes("force closed")) {
32
+ return;
33
+ }
34
+ // Only show error for actual problems
35
+ logger.error(`Failed to start LLM configuration: ${error}`);
36
+ process.exitCode = 1;
37
+ }
38
+ });