@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.
- package/README.md +194 -0
- package/dist/backend-wrapper.cjs +3 -0
- package/dist/src/index.js +331928 -0
- package/package.json +103 -0
- package/src/agents/AgentRegistry.ts +418 -0
- package/src/agents/AgentStorage.ts +1133 -0
- package/src/agents/ConfigResolver.ts +229 -0
- package/src/agents/agent-installer.ts +236 -0
- package/src/agents/agent-loader.ts +241 -0
- package/src/agents/constants.ts +82 -0
- package/src/agents/errors.ts +48 -0
- package/src/agents/execution/AgentExecutor.ts +561 -0
- package/src/agents/execution/ExecutionContextFactory.ts +112 -0
- package/src/agents/execution/MessageCompiler.ts +597 -0
- package/src/agents/execution/MessageSyncer.ts +100 -0
- package/src/agents/execution/PostCompletionChecker.ts +278 -0
- package/src/agents/execution/ProgressMonitor.ts +50 -0
- package/src/agents/execution/RALResolver.ts +177 -0
- package/src/agents/execution/SessionManager.ts +181 -0
- package/src/agents/execution/StreamCallbacks.ts +312 -0
- package/src/agents/execution/StreamExecutionHandler.ts +579 -0
- package/src/agents/execution/StreamSetup.ts +313 -0
- package/src/agents/execution/ToolEventHandlers.ts +239 -0
- package/src/agents/execution/ToolExecutionTracker.ts +498 -0
- package/src/agents/execution/ToolResultUtils.ts +97 -0
- package/src/agents/execution/ToolSupervisionWrapper.ts +174 -0
- package/src/agents/execution/constants.ts +16 -0
- package/src/agents/execution/index.ts +3 -0
- package/src/agents/execution/types.ts +96 -0
- package/src/agents/execution/utils.ts +26 -0
- package/src/agents/index.ts +4 -0
- package/src/agents/script-installer.ts +266 -0
- package/src/agents/supervision/SupervisorLLMService.ts +253 -0
- package/src/agents/supervision/SupervisorOrchestrator.ts +471 -0
- package/src/agents/supervision/heuristics/ConsecutiveToolsWithoutTodoHeuristic.ts +73 -0
- package/src/agents/supervision/heuristics/DelegationClaimHeuristic.ts +80 -0
- package/src/agents/supervision/heuristics/HeuristicRegistry.ts +114 -0
- package/src/agents/supervision/heuristics/PendingTodosHeuristic.ts +93 -0
- package/src/agents/supervision/heuristics/SilentAgentHeuristic.ts +54 -0
- package/src/agents/supervision/heuristics/index.ts +5 -0
- package/src/agents/supervision/index.ts +28 -0
- package/src/agents/supervision/registerHeuristics.ts +110 -0
- package/src/agents/supervision/supervisionHealthCheck.ts +123 -0
- package/src/agents/supervision/types.ts +171 -0
- package/src/agents/tool-names.ts +46 -0
- package/src/agents/tool-normalization.ts +184 -0
- package/src/agents/types/index.ts +2 -0
- package/src/agents/types/runtime.ts +74 -0
- package/src/agents/types/storage.ts +145 -0
- package/src/commands/agent/import/index.ts +6 -0
- package/src/commands/agent/import/openclaw-distiller.ts +57 -0
- package/src/commands/agent/import/openclaw-reader.ts +141 -0
- package/src/commands/agent/import/openclaw.ts +154 -0
- package/src/commands/agent/index.ts +6 -0
- package/src/commands/agent.ts +215 -0
- package/src/commands/daemon.ts +198 -0
- package/src/commands/doctor.ts +134 -0
- package/src/commands/setup/embed.ts +228 -0
- package/src/commands/setup/global-system-prompt.ts +223 -0
- package/src/commands/setup/image.ts +179 -0
- package/src/commands/setup/index.ts +16 -0
- package/src/commands/setup/interactive.ts +95 -0
- package/src/commands/setup/llm.ts +38 -0
- package/src/commands/setup/onboarding.ts +294 -0
- package/src/commands/setup/providers.ts +27 -0
- package/src/constants.ts +34 -0
- package/src/conversations/ConversationDiskReader.ts +148 -0
- package/src/conversations/ConversationRegistry.ts +728 -0
- package/src/conversations/ConversationStore.ts +868 -0
- package/src/conversations/MessageBuilder.ts +866 -0
- package/src/conversations/executionTime.ts +62 -0
- package/src/conversations/formatters/DelegationXmlFormatter.ts +64 -0
- package/src/conversations/formatters/ThreadedConversationFormatter.ts +303 -0
- package/src/conversations/formatters/index.ts +9 -0
- package/src/conversations/formatters/utils/MessageFormatter.ts +46 -0
- package/src/conversations/formatters/utils/TimestampFormatter.ts +56 -0
- package/src/conversations/formatters/utils/TreeBuilder.ts +131 -0
- package/src/conversations/formatters/utils/TreeRenderer.ts +49 -0
- package/src/conversations/index.ts +2 -0
- package/src/conversations/persistence/ToolMessageStorage.ts +143 -0
- package/src/conversations/search/ConversationIndexManager.ts +393 -0
- package/src/conversations/search/QueryParser.ts +114 -0
- package/src/conversations/search/SearchEngine.ts +175 -0
- package/src/conversations/search/SnippetExtractor.ts +345 -0
- package/src/conversations/search/embeddings/ConversationEmbeddingService.ts +484 -0
- package/src/conversations/search/embeddings/ConversationIndexingJob.ts +320 -0
- package/src/conversations/search/embeddings/IndexingStateManager.ts +338 -0
- package/src/conversations/search/embeddings/index.ts +18 -0
- package/src/conversations/search/index.ts +49 -0
- package/src/conversations/search/types.ts +124 -0
- package/src/conversations/services/CategoryManager.ts +160 -0
- package/src/conversations/services/ConversationResolver.ts +296 -0
- package/src/conversations/services/ConversationSummarizer.ts +234 -0
- package/src/conversations/services/MetadataDebounceManager.ts +188 -0
- package/src/conversations/services/index.ts +2 -0
- package/src/conversations/types.ts +148 -0
- package/src/conversations/utils/content-utils.ts +69 -0
- package/src/conversations/utils/image-placeholder.ts +281 -0
- package/src/conversations/utils/image-url-utils.ts +171 -0
- package/src/conversations/utils/multimodal-content.ts +90 -0
- package/src/conversations/utils/tool-result-truncator.ts +159 -0
- package/src/daemon/Daemon.ts +1883 -0
- package/src/daemon/ProjectRuntime.ts +657 -0
- package/src/daemon/RestartState.ts +152 -0
- package/src/daemon/RuntimeLifecycle.ts +268 -0
- package/src/daemon/SubscriptionManager.ts +305 -0
- package/src/daemon/UnixSocketTransport.ts +318 -0
- package/src/daemon/filters/SubscriptionFilterBuilder.ts +119 -0
- package/src/daemon/index.ts +9 -0
- package/src/daemon/routing/DaemonRouter.ts +491 -0
- package/src/daemon/types.ts +150 -0
- package/src/daemon/utils/routing-log.ts +76 -0
- package/src/daemon/utils/telemetry.ts +173 -0
- package/src/event-handler/agentDeletion.ts +383 -0
- package/src/event-handler/index.ts +749 -0
- package/src/event-handler/newConversation.ts +165 -0
- package/src/event-handler/project.ts +166 -0
- package/src/event-handler/reply.ts +18 -0
- package/src/events/NDKAgentDefinition.ts +292 -0
- package/src/events/NDKAgentLesson.ts +106 -0
- package/src/events/NDKEventMetadata.ts +34 -0
- package/src/events/NDKMCPTool.ts +60 -0
- package/src/events/NDKProjectStatus.ts +384 -0
- package/src/events/index.ts +4 -0
- package/src/index.ts +126 -0
- package/src/lib/agent-home.ts +334 -0
- package/src/lib/error-formatter.ts +200 -0
- package/src/lib/fs/filesystem.ts +128 -0
- package/src/lib/fs/index.ts +1 -0
- package/src/lib/json-parser.ts +30 -0
- package/src/lib/string.ts +15 -0
- package/src/lib/time.ts +74 -0
- package/src/llm/ChunkHandler.ts +277 -0
- package/src/llm/FinishHandler.ts +250 -0
- package/src/llm/LLMConfigEditor.ts +154 -0
- package/src/llm/LLMServiceFactory.ts +230 -0
- package/src/llm/MessageProcessor.ts +90 -0
- package/src/llm/RecordingState.ts +37 -0
- package/src/llm/StreamPublisher.ts +40 -0
- package/src/llm/TracingUtils.ts +77 -0
- package/src/llm/chunk-validators.ts +57 -0
- package/src/llm/constants.ts +6 -0
- package/src/llm/index.ts +12 -0
- package/src/llm/meta/MetaModelResolver.ts +352 -0
- package/src/llm/meta/index.ts +11 -0
- package/src/llm/middleware/flight-recorder.ts +188 -0
- package/src/llm/providers/MockProvider.ts +332 -0
- package/src/llm/providers/agent/ClaudeCodeProvider.ts +343 -0
- package/src/llm/providers/agent/ClaudeCodeToolsAdapter.ts +203 -0
- package/src/llm/providers/agent/CodexAppServerProvider.ts +214 -0
- package/src/llm/providers/agent/CodexAppServerToolsAdapter.ts +91 -0
- package/src/llm/providers/agent/index.ts +10 -0
- package/src/llm/providers/base/AgentProvider.ts +107 -0
- package/src/llm/providers/base/BaseProvider.ts +114 -0
- package/src/llm/providers/base/StandardProvider.ts +38 -0
- package/src/llm/providers/base/index.ts +9 -0
- package/src/llm/providers/index.ts +106 -0
- package/src/llm/providers/key-manager.ts +238 -0
- package/src/llm/providers/ollama-models.ts +105 -0
- package/src/llm/providers/openrouter-models.ts +102 -0
- package/src/llm/providers/provider-ids.ts +18 -0
- package/src/llm/providers/registry/ProviderRegistry.ts +414 -0
- package/src/llm/providers/registry/index.ts +7 -0
- package/src/llm/providers/standard/AnthropicProvider.ts +71 -0
- package/src/llm/providers/standard/OllamaProvider.ts +59 -0
- package/src/llm/providers/standard/OpenAIProvider.ts +44 -0
- package/src/llm/providers/standard/OpenRouterProvider.ts +103 -0
- package/src/llm/providers/standard/index.ts +10 -0
- package/src/llm/providers/types.ts +194 -0
- package/src/llm/providers/usage-metadata.ts +78 -0
- package/src/llm/service.ts +713 -0
- package/src/llm/types.ts +167 -0
- package/src/llm/utils/ConfigurationManager.ts +650 -0
- package/src/llm/utils/ConfigurationTester.ts +229 -0
- package/src/llm/utils/ModelSelector.ts +212 -0
- package/src/llm/utils/ProviderConfigUI.ts +177 -0
- package/src/llm/utils/claudeCodePromptCompiler.ts +141 -0
- package/src/llm/utils/codex-models.ts +53 -0
- package/src/llm/utils/context-window-cache.ts +30 -0
- package/src/llm/utils/models-dev-cache.ts +267 -0
- package/src/llm/utils/provider-setup.ts +50 -0
- package/src/llm/utils/tool-errors.ts +78 -0
- package/src/llm/utils/usage.ts +74 -0
- package/src/logging/EventRoutingLogger.ts +205 -0
- package/src/nostr/AgentEventDecoder.ts +357 -0
- package/src/nostr/AgentEventEncoder.ts +677 -0
- package/src/nostr/AgentProfilePublisher.ts +657 -0
- package/src/nostr/AgentPublisher.ts +437 -0
- package/src/nostr/BlossomService.ts +226 -0
- package/src/nostr/InterventionPublisher.ts +132 -0
- package/src/nostr/TagExtractor.ts +228 -0
- package/src/nostr/collectEvents.ts +83 -0
- package/src/nostr/constants.ts +38 -0
- package/src/nostr/encryption.ts +26 -0
- package/src/nostr/index.ts +31 -0
- package/src/nostr/keys.ts +17 -0
- package/src/nostr/kinds.ts +37 -0
- package/src/nostr/ndkClient.ts +72 -0
- package/src/nostr/relays.ts +43 -0
- package/src/nostr/trace-context.ts +39 -0
- package/src/nostr/types.ts +227 -0
- package/src/nostr/utils.ts +84 -0
- package/src/prompts/core/FragmentRegistry.ts +30 -0
- package/src/prompts/core/PromptBuilder.ts +98 -0
- package/src/prompts/core/index.ts +3 -0
- package/src/prompts/core/types.ts +13 -0
- package/src/prompts/fragments/00-global-system-prompt.ts +44 -0
- package/src/prompts/fragments/01-agent-identity.ts +69 -0
- package/src/prompts/fragments/02-agent-home-directory.ts +114 -0
- package/src/prompts/fragments/03-system-reminders-explanation.ts +14 -0
- package/src/prompts/fragments/04-relay-configuration.ts +38 -0
- package/src/prompts/fragments/05-delegation-chain.ts +45 -0
- package/src/prompts/fragments/06-agent-todos.ts +74 -0
- package/src/prompts/fragments/06-todo-usage-guidance.ts +34 -0
- package/src/prompts/fragments/07-meta-project-context.ts +234 -0
- package/src/prompts/fragments/08-active-conversations.ts +382 -0
- package/src/prompts/fragments/09-recent-conversations.ts +153 -0
- package/src/prompts/fragments/10-referenced-article.ts +21 -0
- package/src/prompts/fragments/11-nudges.ts +134 -0
- package/src/prompts/fragments/12-skills.ts +127 -0
- package/src/prompts/fragments/13-available-nudges.ts +122 -0
- package/src/prompts/fragments/15-available-agents.ts +53 -0
- package/src/prompts/fragments/16-stay-in-your-lane.ts +41 -0
- package/src/prompts/fragments/17-todo-before-delegation.ts +39 -0
- package/src/prompts/fragments/20-voice-mode.ts +62 -0
- package/src/prompts/fragments/22-scheduled-tasks.ts +175 -0
- package/src/prompts/fragments/24-retrieved-lessons.ts +26 -0
- package/src/prompts/fragments/25-rag-instructions.ts +333 -0
- package/src/prompts/fragments/26-mcp-resources.ts +237 -0
- package/src/prompts/fragments/27-memorized-reports.ts +77 -0
- package/src/prompts/fragments/28-agent-directed-monitoring.ts +32 -0
- package/src/prompts/fragments/29-rag-collections.ts +50 -0
- package/src/prompts/fragments/30-worktree-context.ts +98 -0
- package/src/prompts/fragments/31-agents-md-guidance.ts +96 -0
- package/src/prompts/fragments/32-process-metrics.ts +72 -0
- package/src/prompts/fragments/debug-mode.ts +48 -0
- package/src/prompts/fragments/delegation-completion.ts +44 -0
- package/src/prompts/fragments/index.ts +91 -0
- package/src/prompts/index.ts +21 -0
- package/src/prompts/utils/systemPromptBuilder.ts +777 -0
- package/src/scripts/migrate-prefix-index.ts +157 -0
- package/src/services/AgentDefinitionMonitor.ts +701 -0
- package/src/services/ConfigService.ts +723 -0
- package/src/services/CooldownRegistry.ts +199 -0
- package/src/services/LLMOperationsRegistry.ts +424 -0
- package/src/services/OwnerAgentListService.ts +354 -0
- package/src/services/PubkeyService.ts +308 -0
- package/src/services/agents/AgentMetadataStore.ts +72 -0
- package/src/services/agents/AgentResolution.ts +59 -0
- package/src/services/agents/EscalationService.ts +281 -0
- package/src/services/agents/NDKAgentDiscovery.ts +95 -0
- package/src/services/agents/index.ts +7 -0
- package/src/services/agents-md/AgentsMdService.ts +184 -0
- package/src/services/agents-md/SystemReminderInjector.ts +238 -0
- package/src/services/agents-md/index.ts +11 -0
- package/src/services/apns/APNsClient.ts +203 -0
- package/src/services/apns/APNsService.ts +358 -0
- package/src/services/apns/index.ts +11 -0
- package/src/services/apns/types.ts +80 -0
- package/src/services/compression/CompressionService.ts +445 -0
- package/src/services/compression/compression-schema.ts +28 -0
- package/src/services/compression/compression-types.ts +74 -0
- package/src/services/compression/compression-utils.ts +587 -0
- package/src/services/config/types.ts +394 -0
- package/src/services/dispatch/AgentDispatchService.ts +937 -0
- package/src/services/dispatch/AgentRouter.ts +181 -0
- package/src/services/dispatch/DelegationCompletionHandler.ts +232 -0
- package/src/services/embedding/EmbeddingProvider.ts +188 -0
- package/src/services/embedding/index.ts +5 -0
- package/src/services/event-context/EventContextService.ts +108 -0
- package/src/services/event-context/index.ts +2 -0
- package/src/services/heuristics/ContextBuilder.ts +106 -0
- package/src/services/heuristics/HeuristicEngine.ts +200 -0
- package/src/services/heuristics/formatters.ts +58 -0
- package/src/services/heuristics/index.ts +12 -0
- package/src/services/heuristics/rules/index.ts +25 -0
- package/src/services/heuristics/rules/todoBeforeDelegation.ts +69 -0
- package/src/services/heuristics/rules/todoReminderOnToolUse.ts +63 -0
- package/src/services/heuristics/types.ts +144 -0
- package/src/services/image/ImageGenerationService.ts +389 -0
- package/src/services/image/index.ts +12 -0
- package/src/services/intervention/InterventionService.ts +1352 -0
- package/src/services/intervention/index.ts +7 -0
- package/src/services/mcp/MCPManager.ts +683 -0
- package/src/services/mcp/McpNotificationDelivery.ts +139 -0
- package/src/services/mcp/McpSubscriptionService.ts +653 -0
- package/src/services/mcp/mcpInstaller.ts +130 -0
- package/src/services/nip46/Nip46SigningLog.ts +81 -0
- package/src/services/nip46/Nip46SigningService.ts +467 -0
- package/src/services/nip46/index.ts +4 -0
- package/src/services/nudge/NudgeService.ts +224 -0
- package/src/services/nudge/NudgeWhitelistService.ts +382 -0
- package/src/services/nudge/index.ts +5 -0
- package/src/services/nudge/types.ts +83 -0
- package/src/services/projects/ProjectContext.ts +672 -0
- package/src/services/projects/ProjectContextStore.ts +102 -0
- package/src/services/projects/index.ts +6 -0
- package/src/services/prompt-compiler/index.ts +15 -0
- package/src/services/prompt-compiler/prompt-compiler-service.ts +1143 -0
- package/src/services/pubkey-gate/PubkeyGateService.ts +93 -0
- package/src/services/pubkey-gate/index.ts +1 -0
- package/src/services/rag/EmbeddingProviderFactory.ts +292 -0
- package/src/services/rag/LanceDBMaintenanceService.ts +211 -0
- package/src/services/rag/RAGDatabaseService.ts +173 -0
- package/src/services/rag/RAGOperations.ts +682 -0
- package/src/services/rag/RAGService.ts +240 -0
- package/src/services/rag/RagSubscriptionService.ts +618 -0
- package/src/services/rag/rag-utils.ts +174 -0
- package/src/services/ral/PendingDelegationsRegistry.ts +168 -0
- package/src/services/ral/RALRegistry.ts +2782 -0
- package/src/services/ral/index.ts +4 -0
- package/src/services/ral/types.ts +292 -0
- package/src/services/reports/LocalReportStore.ts +380 -0
- package/src/services/reports/ReportEmbeddingService.ts +430 -0
- package/src/services/reports/ReportService.ts +440 -0
- package/src/services/reports/articleUtils.ts +52 -0
- package/src/services/reports/index.ts +7 -0
- package/src/services/scheduling/SchedulerService.ts +1057 -0
- package/src/services/scheduling/errors.ts +14 -0
- package/src/services/scheduling/index.ts +7 -0
- package/src/services/scheduling/utils.ts +77 -0
- package/src/services/search/SearchProviderRegistry.ts +78 -0
- package/src/services/search/UnifiedSearchService.ts +218 -0
- package/src/services/search/index.ts +47 -0
- package/src/services/search/projectFilter.ts +22 -0
- package/src/services/search/providers/ConversationSearchProvider.ts +48 -0
- package/src/services/search/providers/LessonSearchProvider.ts +75 -0
- package/src/services/search/providers/ReportSearchProvider.ts +49 -0
- package/src/services/search/types.ts +144 -0
- package/src/services/skill/SkillService.ts +482 -0
- package/src/services/skill/index.ts +2 -0
- package/src/services/skill/types.ts +70 -0
- package/src/services/status/OperationsStatusService.ts +276 -0
- package/src/services/status/ProjectStatusService.ts +522 -0
- package/src/services/status/index.ts +11 -0
- package/src/services/storage/PrefixKVStore.ts +242 -0
- package/src/services/storage/index.ts +1 -0
- package/src/services/system-reminder/SystemReminderUtils.ts +96 -0
- package/src/services/system-reminder/index.ts +7 -0
- package/src/services/trust-pubkeys/TrustPubkeyService.ts +325 -0
- package/src/services/trust-pubkeys/index.ts +2 -0
- package/src/telemetry/ConversationSpanManager.ts +111 -0
- package/src/telemetry/EventLoopMonitor.ts +206 -0
- package/src/telemetry/LLMSpanRegistry.ts +20 -0
- package/src/telemetry/NostrSpanProcessor.ts +89 -0
- package/src/telemetry/ToolCallSpanProcessor.ts +66 -0
- package/src/telemetry/diagnostics.ts +27 -0
- package/src/telemetry/setup.ts +120 -0
- package/src/tools/implementations/agents_discover.ts +121 -0
- package/src/tools/implementations/agents_hire.ts +127 -0
- package/src/tools/implementations/agents_list.ts +96 -0
- package/src/tools/implementations/agents_publish.ts +611 -0
- package/src/tools/implementations/agents_read.ts +173 -0
- package/src/tools/implementations/agents_write.ts +200 -0
- package/src/tools/implementations/ask.ts +411 -0
- package/src/tools/implementations/change_model.ts +141 -0
- package/src/tools/implementations/conversation_get.ts +661 -0
- package/src/tools/implementations/conversation_list.ts +377 -0
- package/src/tools/implementations/conversation_search.ts +370 -0
- package/src/tools/implementations/delegate.ts +327 -0
- package/src/tools/implementations/delegate_crossproject.ts +209 -0
- package/src/tools/implementations/delegate_followup.ts +300 -0
- package/src/tools/implementations/fs_edit.ts +162 -0
- package/src/tools/implementations/fs_glob.ts +182 -0
- package/src/tools/implementations/fs_grep.ts +513 -0
- package/src/tools/implementations/fs_read.ts +332 -0
- package/src/tools/implementations/fs_write.ts +113 -0
- package/src/tools/implementations/generate_image.ts +259 -0
- package/src/tools/implementations/home_fs.ts +515 -0
- package/src/tools/implementations/kill.ts +651 -0
- package/src/tools/implementations/learn.ts +166 -0
- package/src/tools/implementations/lesson-formatter.ts +38 -0
- package/src/tools/implementations/lesson_delete.ts +164 -0
- package/src/tools/implementations/lesson_get.ts +105 -0
- package/src/tools/implementations/lessons_list.ts +153 -0
- package/src/tools/implementations/mcp_resource_read.ts +161 -0
- package/src/tools/implementations/mcp_subscribe.ts +158 -0
- package/src/tools/implementations/mcp_subscription_stop.ts +85 -0
- package/src/tools/implementations/nostr_fetch.ts +149 -0
- package/src/tools/implementations/nostr_publish_as_user.ts +353 -0
- package/src/tools/implementations/project_list.ts +146 -0
- package/src/tools/implementations/rag_add_documents.ts +573 -0
- package/src/tools/implementations/rag_create_collection.ts +65 -0
- package/src/tools/implementations/rag_delete_collection.ts +68 -0
- package/src/tools/implementations/rag_list_collections.ts +77 -0
- package/src/tools/implementations/rag_query.ts +107 -0
- package/src/tools/implementations/rag_subscription_create.ts +105 -0
- package/src/tools/implementations/rag_subscription_delete.ts +80 -0
- package/src/tools/implementations/rag_subscription_get.ts +123 -0
- package/src/tools/implementations/rag_subscription_list.ts +128 -0
- package/src/tools/implementations/report_delete.ts +79 -0
- package/src/tools/implementations/report_read.ts +160 -0
- package/src/tools/implementations/report_write.ts +278 -0
- package/src/tools/implementations/reports_list.ts +77 -0
- package/src/tools/implementations/schedule_task.ts +104 -0
- package/src/tools/implementations/schedule_task_cancel.ts +62 -0
- package/src/tools/implementations/schedule_task_once.ts +128 -0
- package/src/tools/implementations/schedule_tasks_list.ts +79 -0
- package/src/tools/implementations/search.ts +160 -0
- package/src/tools/implementations/shell.ts +553 -0
- package/src/tools/implementations/todo.ts +260 -0
- package/src/tools/implementations/upload_blob.ts +381 -0
- package/src/tools/implementations/web_fetch.ts +153 -0
- package/src/tools/implementations/web_search.ts +250 -0
- package/src/tools/registry.ts +670 -0
- package/src/tools/types.ts +177 -0
- package/src/tools/utils.ts +256 -0
- package/src/types/event-ids.ts +320 -0
- package/src/types/index.ts +46 -0
- package/src/utils/agentFetcher.ts +107 -0
- package/src/utils/cli-error.ts +29 -0
- package/src/utils/conversation-id.ts +27 -0
- package/src/utils/conversation-utils.ts +1 -0
- package/src/utils/delegation-chain.ts +357 -0
- package/src/utils/error-handler.ts +42 -0
- package/src/utils/git/gitignore.ts +69 -0
- package/src/utils/git/index.ts +2 -0
- package/src/utils/git/initializeGitRepo.ts +204 -0
- package/src/utils/git/worktree.ts +260 -0
- package/src/utils/lessonFormatter.ts +70 -0
- package/src/utils/lessonTrust.ts +24 -0
- package/src/utils/lockfile.ts +123 -0
- package/src/utils/logger.ts +149 -0
- package/src/utils/nostr-entity-parser.ts +365 -0
- package/src/utils/process.ts +49 -0
- package/src/wrapper.ts +262 -0
- package/tsconfig.json +41 -0
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { getDaemon } from "@/daemon";
|
|
2
|
+
import { getNDK, initNDK } from "@/nostr/ndkClient";
|
|
3
|
+
import { config } from "@/services/ConfigService";
|
|
4
|
+
import { llmOpsRegistry } from "@/services/LLMOperationsRegistry";
|
|
5
|
+
import { SchedulerService } from "@/services/scheduling";
|
|
6
|
+
import { eventLoopMonitor } from "@/telemetry/EventLoopMonitor";
|
|
7
|
+
import { logger } from "@/utils/logger";
|
|
8
|
+
import { runInteractiveSetup } from "./setup/interactive";
|
|
9
|
+
import chalk from "chalk";
|
|
10
|
+
import { Command } from "commander";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Daemon command - runs all projects in a single process
|
|
14
|
+
*/
|
|
15
|
+
export const daemonCommand = new Command("daemon")
|
|
16
|
+
.description("Start the TENEX daemon to manage all projects")
|
|
17
|
+
.option("-w, --whitelist <pubkeys>", "Comma-separated list of whitelisted pubkeys")
|
|
18
|
+
.option("-c, --config <path>", "Path to config file")
|
|
19
|
+
.option("-v, --verbose", "Enable verbose logging")
|
|
20
|
+
.option("-b, --boot <pattern>", "Auto-boot projects whose d-tag contains this pattern (can be used multiple times)", (value: string, prev: string[]) => {
|
|
21
|
+
return prev ? [...prev, value] : [value];
|
|
22
|
+
}, [])
|
|
23
|
+
.option("--supervised", "Run in supervised mode (enables graceful restart via SIGHUP)")
|
|
24
|
+
.action(async (options) => {
|
|
25
|
+
// Enable verbose logging if requested
|
|
26
|
+
if (options.verbose) {
|
|
27
|
+
process.env.LOG_LEVEL = "debug";
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Load configuration (MCP config will be loaded later per-project with metadataPath)
|
|
31
|
+
const { config: globalConfig, llms: globalLLMs } = await config.loadConfig();
|
|
32
|
+
|
|
33
|
+
// Initialize daemon logging
|
|
34
|
+
await logger.initDaemonLogging();
|
|
35
|
+
|
|
36
|
+
// Get whitelisted pubkeys
|
|
37
|
+
const whitelistedPubkeys = config.getWhitelistedPubkeys(
|
|
38
|
+
options.whitelist,
|
|
39
|
+
globalConfig
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
// Check for required configurations
|
|
43
|
+
const needsSetup =
|
|
44
|
+
whitelistedPubkeys.length === 0 ||
|
|
45
|
+
!globalLLMs.configurations ||
|
|
46
|
+
Object.keys(globalLLMs.configurations).length === 0;
|
|
47
|
+
|
|
48
|
+
if (needsSetup) {
|
|
49
|
+
if (whitelistedPubkeys.length === 0) {
|
|
50
|
+
logger.info("No whitelisted pubkeys found. Starting interactive setup...");
|
|
51
|
+
}
|
|
52
|
+
if (!globalLLMs.configurations || Object.keys(globalLLMs.configurations).length === 0) {
|
|
53
|
+
logger.info("No LLM configurations found. Starting interactive setup...");
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Run interactive setup
|
|
57
|
+
const setupConfig = await runInteractiveSetup();
|
|
58
|
+
|
|
59
|
+
// Save the setup configuration and reload
|
|
60
|
+
await config.saveGlobalConfig(setupConfig);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
console.log(chalk.cyan("╔════════════════════════════════════════╗"));
|
|
64
|
+
console.log(chalk.cyan("║ TENEX Daemon Starting ║"));
|
|
65
|
+
console.log(chalk.cyan("╚════════════════════════════════════════╝"));
|
|
66
|
+
console.log();
|
|
67
|
+
|
|
68
|
+
// Initialize NDK for Nostr communication
|
|
69
|
+
console.log(chalk.gray("🔌 Initializing Nostr connection..."));
|
|
70
|
+
await initNDK();
|
|
71
|
+
console.log(chalk.gray("✓ Nostr connected"));
|
|
72
|
+
|
|
73
|
+
// Get scheduler service instance (initialization deferred until callbacks are registered)
|
|
74
|
+
const schedulerService = SchedulerService.getInstance();
|
|
75
|
+
|
|
76
|
+
// DIAGNOSTIC: Start event loop monitoring for concurrent streaming bottleneck analysis
|
|
77
|
+
eventLoopMonitor.start(
|
|
78
|
+
() => llmOpsRegistry.getActiveOperationsCount(),
|
|
79
|
+
100, // Sample every 100ms
|
|
80
|
+
50 // Consider >50ms lag as blocked
|
|
81
|
+
);
|
|
82
|
+
console.log(chalk.gray("📊 Event loop monitoring enabled"));
|
|
83
|
+
|
|
84
|
+
// Get the daemon instance
|
|
85
|
+
console.log(chalk.gray("🚀 Starting daemon..."));
|
|
86
|
+
const daemon = getDaemon();
|
|
87
|
+
|
|
88
|
+
// Set supervised mode if enabled
|
|
89
|
+
if (options.supervised) {
|
|
90
|
+
daemon.setSupervisedMode(true);
|
|
91
|
+
console.log(chalk.yellow("🔄 Supervised mode enabled (SIGHUP triggers graceful restart)"));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Set boot patterns if provided
|
|
95
|
+
const bootPatterns: string[] = options.boot || [];
|
|
96
|
+
if (bootPatterns.length > 0) {
|
|
97
|
+
daemon.setAutoBootPatterns(bootPatterns);
|
|
98
|
+
console.log(chalk.yellow(`🚀 Auto-boot patterns: ${bootPatterns.join(", ")}`));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Register scheduler shutdown with daemon's shutdown handlers
|
|
102
|
+
daemon.addShutdownHandler(async () => {
|
|
103
|
+
schedulerService.shutdown();
|
|
104
|
+
// Stop event loop monitor and log final stats
|
|
105
|
+
const stats = eventLoopMonitor.getStats();
|
|
106
|
+
logger.info("[EventLoopMonitor] Final stats on shutdown", {
|
|
107
|
+
peakLagMs: stats.peakLagMs,
|
|
108
|
+
avgLagMs: Math.round(stats.avgLagMs * 100) / 100,
|
|
109
|
+
sampleCount: stats.sampleCount,
|
|
110
|
+
blockedCount: stats.blockedCount,
|
|
111
|
+
blockedPercentage: stats.sampleCount > 0
|
|
112
|
+
? Math.round((stats.blockedCount / stats.sampleCount) * 10000) / 100
|
|
113
|
+
: 0,
|
|
114
|
+
});
|
|
115
|
+
eventLoopMonitor.stop();
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
// Start the daemon
|
|
120
|
+
await daemon.start();
|
|
121
|
+
console.log(chalk.gray("✓ Daemon core started"));
|
|
122
|
+
|
|
123
|
+
// Load restart state if this is a restart (auto-boot previously booted projects)
|
|
124
|
+
if (options.supervised) {
|
|
125
|
+
await daemon.loadRestartState();
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Register project callbacks with scheduler service (dependency injection)
|
|
129
|
+
// This enables Layer 3 (SchedulerService) to use Layer 4 (Daemon) functionality
|
|
130
|
+
// without direct imports, maintaining architectural separation
|
|
131
|
+
schedulerService.setProjectCallbacks(
|
|
132
|
+
// Boot handler: called when a scheduled task needs to boot a project
|
|
133
|
+
async (projectId: string) => {
|
|
134
|
+
await daemon.startRuntime(projectId);
|
|
135
|
+
},
|
|
136
|
+
// State resolver: called to check if a project is already running
|
|
137
|
+
(projectId: string) => {
|
|
138
|
+
return daemon.getActiveRuntimes().has(projectId);
|
|
139
|
+
},
|
|
140
|
+
// Target resolver: called to resolve the target pubkey (may reroute to PM)
|
|
141
|
+
(projectId: string, originalTargetPubkey: string) => {
|
|
142
|
+
const runtime = daemon.getActiveRuntimes().get(projectId);
|
|
143
|
+
if (!runtime) {
|
|
144
|
+
// Project not running, use original target
|
|
145
|
+
return originalTargetPubkey;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const context = runtime.getContext();
|
|
149
|
+
if (!context) {
|
|
150
|
+
// No context available, use original target
|
|
151
|
+
return originalTargetPubkey;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Check if the target agent is in this project
|
|
155
|
+
const targetAgent = context.getAgentByPubkey(originalTargetPubkey);
|
|
156
|
+
if (targetAgent) {
|
|
157
|
+
// Target agent exists in project, use original target
|
|
158
|
+
return originalTargetPubkey;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Target agent is NOT in this project - route to PM instead
|
|
162
|
+
const pm = context.projectManager;
|
|
163
|
+
if (!pm) {
|
|
164
|
+
// No PM available, use original target
|
|
165
|
+
return originalTargetPubkey;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return pm.pubkey;
|
|
169
|
+
}
|
|
170
|
+
);
|
|
171
|
+
console.log(chalk.gray("✓ Scheduler callbacks registered"));
|
|
172
|
+
|
|
173
|
+
// Initialize scheduler AFTER callbacks are registered
|
|
174
|
+
// This ensures catch-up tasks can use ensureProjectRunning() for auto-boot
|
|
175
|
+
console.log(chalk.gray("⚙️ Initializing scheduler service..."));
|
|
176
|
+
await schedulerService.initialize(getNDK(), ".tenex");
|
|
177
|
+
console.log(chalk.gray("✓ Scheduler initialized"));
|
|
178
|
+
|
|
179
|
+
console.log(chalk.green("✅ Daemon started successfully"));
|
|
180
|
+
|
|
181
|
+
// Log initial status
|
|
182
|
+
const status = daemon.getStatus();
|
|
183
|
+
console.log(chalk.blue("📊 Initial Status:"));
|
|
184
|
+
console.log(chalk.gray(` Known Projects: ${status.knownProjects}`));
|
|
185
|
+
console.log(chalk.gray(` Active Projects: ${status.activeProjects}`));
|
|
186
|
+
console.log(chalk.gray(` Total Agents: ${status.totalAgents}`));
|
|
187
|
+
console.log();
|
|
188
|
+
|
|
189
|
+
// Keep the process alive
|
|
190
|
+
await new Promise(() => {
|
|
191
|
+
// This promise never resolves, keeping the daemon running
|
|
192
|
+
});
|
|
193
|
+
} catch (error) {
|
|
194
|
+
logger.error("Failed to start daemon", { error });
|
|
195
|
+
console.error(chalk.red("❌ Failed to start daemon:"), error);
|
|
196
|
+
process.exit(1);
|
|
197
|
+
}
|
|
198
|
+
});
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import { agentStorage, type StoredAgent } from "@/agents/AgentStorage";
|
|
4
|
+
import { NDKAgentDefinition } from "@/events/NDKAgentDefinition";
|
|
5
|
+
import { initNDK, getNDK } from "@/nostr/ndkClient";
|
|
6
|
+
import { NDKPrivateKeySigner } from "@nostr-dev-kit/ndk";
|
|
7
|
+
|
|
8
|
+
const refetchCommand = new Command("refetch")
|
|
9
|
+
.description("Refetch and update all agent definitions from Nostr")
|
|
10
|
+
.action(repairAgents);
|
|
11
|
+
|
|
12
|
+
const orphansCommand = new Command("orphans")
|
|
13
|
+
.description("List agents not assigned to any project")
|
|
14
|
+
.option("--purge", "Delete orphaned agents")
|
|
15
|
+
.action(async (options) => {
|
|
16
|
+
await findOrphanedAgents(!!options.purge);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const agentsCommand = new Command("agents")
|
|
20
|
+
.description("Agent diagnostics and repair")
|
|
21
|
+
.addCommand(refetchCommand)
|
|
22
|
+
.addCommand(orphansCommand);
|
|
23
|
+
|
|
24
|
+
export const doctorCommand = new Command("doctor")
|
|
25
|
+
.description("Diagnose and repair TENEX state")
|
|
26
|
+
.addCommand(agentsCommand);
|
|
27
|
+
|
|
28
|
+
function agentChanged(before: StoredAgent, after: StoredAgent): boolean {
|
|
29
|
+
if (before.name !== after.name) return true;
|
|
30
|
+
if (before.role !== after.role) return true;
|
|
31
|
+
if (before.description !== after.description) return true;
|
|
32
|
+
if (before.instructions !== after.instructions) return true;
|
|
33
|
+
if (before.useCriteria !== after.useCriteria) return true;
|
|
34
|
+
const oldTools = before.default?.tools?.slice().sort().join("\0") ?? "";
|
|
35
|
+
const newTools = after.default?.tools?.slice().sort().join("\0") ?? "";
|
|
36
|
+
return oldTools !== newTools;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function repairAgents(): Promise<void> {
|
|
40
|
+
await agentStorage.initialize();
|
|
41
|
+
await initNDK();
|
|
42
|
+
const ndk = getNDK();
|
|
43
|
+
|
|
44
|
+
const agents = await agentStorage.getAllAgents();
|
|
45
|
+
const nostrAgents = agents.filter((a) => a.eventId);
|
|
46
|
+
const skipped = agents.length - nostrAgents.length;
|
|
47
|
+
|
|
48
|
+
console.log(chalk.blue(`Checking ${nostrAgents.length} Nostr agent(s)...`));
|
|
49
|
+
|
|
50
|
+
let updated = 0;
|
|
51
|
+
let failed = 0;
|
|
52
|
+
|
|
53
|
+
for (const agent of nostrAgents) {
|
|
54
|
+
const pubkey = new NDKPrivateKeySigner(agent.nsec).pubkey;
|
|
55
|
+
const label = `${agent.slug} (${pubkey.substring(0, 8)}...)`;
|
|
56
|
+
|
|
57
|
+
const event = await ndk.fetchEvent(agent.eventId!, { groupable: false });
|
|
58
|
+
if (!event) {
|
|
59
|
+
console.log(chalk.yellow(` ⚠ ${label}: event not found on relays, skipping`));
|
|
60
|
+
failed++;
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const agentDef = NDKAgentDefinition.from(event);
|
|
65
|
+
const toolTags = event.tags
|
|
66
|
+
.filter((t) => t[0] === "tool" && t[1])
|
|
67
|
+
.map((t) => t[1] as string);
|
|
68
|
+
|
|
69
|
+
const newDefault = {
|
|
70
|
+
...agent.default,
|
|
71
|
+
tools: toolTags.length > 0 ? toolTags : undefined,
|
|
72
|
+
};
|
|
73
|
+
const updatedAgent = {
|
|
74
|
+
...agent,
|
|
75
|
+
name: agentDef.title || agent.name,
|
|
76
|
+
role: agentDef.role || agent.role,
|
|
77
|
+
description: agentDef.description ?? agent.description,
|
|
78
|
+
instructions: agentDef.instructions ?? agent.instructions,
|
|
79
|
+
useCriteria: agentDef.useCriteria ?? agent.useCriteria,
|
|
80
|
+
default: Object.values(newDefault).some((v) => v !== undefined) ? newDefault : undefined,
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const toolsDisplay = toolTags.length > 0 ? toolTags.join(", ") : "(none)";
|
|
84
|
+
const suffix = chalk.gray(` [tools: ${toolsDisplay}]`);
|
|
85
|
+
|
|
86
|
+
if (agentChanged(agent, updatedAgent)) {
|
|
87
|
+
await agentStorage.saveAgent(updatedAgent);
|
|
88
|
+
console.log(chalk.green(` ✓ ${label}: updated`) + suffix);
|
|
89
|
+
updated++;
|
|
90
|
+
} else {
|
|
91
|
+
console.log(chalk.gray(` ${label}: ok`) + suffix);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
console.log(
|
|
96
|
+
chalk.blue(
|
|
97
|
+
`\nDone: ${updated} updated, ${skipped} skipped (no eventId), ${failed} failed`
|
|
98
|
+
)
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async function findOrphanedAgents(purge: boolean): Promise<void> {
|
|
103
|
+
await agentStorage.initialize();
|
|
104
|
+
const agents = await agentStorage.getAllAgents();
|
|
105
|
+
|
|
106
|
+
const orphans: Array<{ agent: StoredAgent; pubkey: string }> = [];
|
|
107
|
+
for (const agent of agents) {
|
|
108
|
+
const pubkey = new NDKPrivateKeySigner(agent.nsec).pubkey;
|
|
109
|
+
const projects = await agentStorage.getAgentProjects(pubkey);
|
|
110
|
+
if (projects.length === 0) {
|
|
111
|
+
orphans.push({ agent, pubkey });
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (orphans.length === 0) {
|
|
116
|
+
console.log(chalk.green("No orphaned agents found."));
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
console.log(chalk.yellow(`Found ${orphans.length} orphaned agent(s):`));
|
|
121
|
+
for (const { agent, pubkey } of orphans) {
|
|
122
|
+
const source = agent.eventId ? `nostr:${agent.eventId.substring(0, 8)}...` : "local";
|
|
123
|
+
console.log(chalk.gray(` ${agent.slug} (${pubkey.substring(0, 8)}...) [${source}]`));
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (!purge) return;
|
|
127
|
+
|
|
128
|
+
console.log(chalk.blue(`\nPurging ${orphans.length} orphaned agent(s)...`));
|
|
129
|
+
for (const { agent, pubkey } of orphans) {
|
|
130
|
+
await agentStorage.deleteAgent(pubkey);
|
|
131
|
+
console.log(chalk.green(` ✓ deleted ${agent.slug}`));
|
|
132
|
+
}
|
|
133
|
+
console.log(chalk.blue(`Done: ${orphans.length} deleted`));
|
|
134
|
+
}
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import * as fileSystem from "@/lib/fs";
|
|
2
|
+
import { PROVIDER_IDS } from "@/llm/providers/provider-ids";
|
|
3
|
+
import {
|
|
4
|
+
type EmbeddingConfig,
|
|
5
|
+
EmbeddingProviderFactory,
|
|
6
|
+
} from "@/services/rag/EmbeddingProviderFactory";
|
|
7
|
+
import { config as configService } from "@/services/ConfigService";
|
|
8
|
+
import { logger } from "@/utils/logger";
|
|
9
|
+
import { Command } from "commander";
|
|
10
|
+
import inquirer from "inquirer";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Providers that support embeddings (OpenAI-compatible API)
|
|
14
|
+
*/
|
|
15
|
+
const EMBEDDING_CAPABLE_PROVIDERS = [
|
|
16
|
+
PROVIDER_IDS.OPENAI,
|
|
17
|
+
PROVIDER_IDS.OPENROUTER,
|
|
18
|
+
] as const;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Display names for providers
|
|
22
|
+
*/
|
|
23
|
+
const PROVIDER_DISPLAY_NAMES: Record<string, string> = {
|
|
24
|
+
[PROVIDER_IDS.OPENAI]: "OpenAI",
|
|
25
|
+
[PROVIDER_IDS.OPENROUTER]: "OpenRouter",
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Common embedding models by provider
|
|
30
|
+
*/
|
|
31
|
+
const EMBEDDING_MODELS: Record<string, Array<{ name: string; value: string }>> = {
|
|
32
|
+
[PROVIDER_IDS.OPENAI]: [
|
|
33
|
+
{ name: "text-embedding-3-small (fast, good quality)", value: "text-embedding-3-small" },
|
|
34
|
+
{ name: "text-embedding-3-large (slower, best quality)", value: "text-embedding-3-large" },
|
|
35
|
+
{ name: "text-embedding-ada-002 (legacy)", value: "text-embedding-ada-002" },
|
|
36
|
+
],
|
|
37
|
+
[PROVIDER_IDS.OPENROUTER]: [
|
|
38
|
+
{ name: "openai/text-embedding-3-small", value: "openai/text-embedding-3-small" },
|
|
39
|
+
{ name: "openai/text-embedding-3-large", value: "openai/text-embedding-3-large" },
|
|
40
|
+
{ name: "openai/text-embedding-ada-002", value: "openai/text-embedding-ada-002" },
|
|
41
|
+
],
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Command for configuring embedding provider
|
|
46
|
+
*/
|
|
47
|
+
export const embedCommand = new Command("embed")
|
|
48
|
+
.description(
|
|
49
|
+
"Configure embedding model for RAG (global by default, --project for current project)"
|
|
50
|
+
)
|
|
51
|
+
.option("--project", "Use project-specific configuration instead of global")
|
|
52
|
+
.action(async (options) => {
|
|
53
|
+
try {
|
|
54
|
+
const scope: "global" | "project" = options.project ? "project" : "global";
|
|
55
|
+
const projectPath = process.cwd();
|
|
56
|
+
const baseDir =
|
|
57
|
+
scope === "project"
|
|
58
|
+
? configService.getProjectPath(projectPath)
|
|
59
|
+
: configService.getGlobalPath();
|
|
60
|
+
|
|
61
|
+
if (scope === "project") {
|
|
62
|
+
// Check if we're in a TENEX project
|
|
63
|
+
if (!(await fileSystem.directoryExists(baseDir))) {
|
|
64
|
+
logger.error(
|
|
65
|
+
"No .tenex directory found. Make sure you're in a TENEX project directory."
|
|
66
|
+
);
|
|
67
|
+
process.exitCode = 1;
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
} else {
|
|
71
|
+
// Ensure global config directory exists
|
|
72
|
+
await fileSystem.ensureDirectory(baseDir);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Load existing configuration
|
|
76
|
+
const existing = await EmbeddingProviderFactory.loadConfiguration({
|
|
77
|
+
scope,
|
|
78
|
+
projectPath: scope === "project" ? projectPath : undefined,
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// Load configured providers from providers.json
|
|
82
|
+
const providersConfig = await configService.loadTenexProviders(configService.getGlobalPath());
|
|
83
|
+
if (Object.keys(providersConfig.providers).length === 0) {
|
|
84
|
+
logger.error(
|
|
85
|
+
"No providers configured. Run `tenex setup providers` before configuring embeddings."
|
|
86
|
+
);
|
|
87
|
+
process.exitCode = 1;
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const configuredProviders = Object.keys(providersConfig.providers);
|
|
91
|
+
|
|
92
|
+
// Build provider choices: local + any configured embedding-capable providers
|
|
93
|
+
const providerChoices: Array<{ name: string; value: string }> = [
|
|
94
|
+
{ name: "Local Transformers (runs on your machine)", value: "local" },
|
|
95
|
+
];
|
|
96
|
+
|
|
97
|
+
for (const providerId of EMBEDDING_CAPABLE_PROVIDERS) {
|
|
98
|
+
if (configuredProviders.includes(providerId)) {
|
|
99
|
+
const displayName = PROVIDER_DISPLAY_NAMES[providerId] || providerId;
|
|
100
|
+
providerChoices.push({
|
|
101
|
+
name: `${displayName} (configured)`,
|
|
102
|
+
value: providerId,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Prompt for provider selection
|
|
108
|
+
const { provider } = await inquirer.prompt([
|
|
109
|
+
{
|
|
110
|
+
type: "select",
|
|
111
|
+
name: "provider",
|
|
112
|
+
message: "Select embedding provider:",
|
|
113
|
+
choices: providerChoices,
|
|
114
|
+
default: existing?.provider || "local",
|
|
115
|
+
},
|
|
116
|
+
]);
|
|
117
|
+
|
|
118
|
+
let model: string;
|
|
119
|
+
|
|
120
|
+
if (provider !== "local") {
|
|
121
|
+
// OpenAI-compatible provider configuration
|
|
122
|
+
const displayName = PROVIDER_DISPLAY_NAMES[provider] || provider;
|
|
123
|
+
const modelChoices = EMBEDDING_MODELS[provider] || [
|
|
124
|
+
{ name: "Enter custom model ID", value: "custom" },
|
|
125
|
+
];
|
|
126
|
+
|
|
127
|
+
// Add custom model option if not already present
|
|
128
|
+
if (!modelChoices.some((c) => c.value === "custom")) {
|
|
129
|
+
modelChoices.push({ name: "Enter custom model ID", value: "custom" });
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const providerAnswers = await inquirer.prompt([
|
|
133
|
+
{
|
|
134
|
+
type: "select",
|
|
135
|
+
name: "model",
|
|
136
|
+
message: `Select ${displayName} embedding model:`,
|
|
137
|
+
choices: modelChoices,
|
|
138
|
+
default: existing?.provider === provider ? existing?.model : modelChoices[0]?.value,
|
|
139
|
+
},
|
|
140
|
+
]);
|
|
141
|
+
|
|
142
|
+
if (providerAnswers.model === "custom") {
|
|
143
|
+
const customAnswer = await inquirer.prompt([
|
|
144
|
+
{
|
|
145
|
+
type: "input",
|
|
146
|
+
name: "customModel",
|
|
147
|
+
message: "Enter model ID:",
|
|
148
|
+
validate: (input: string) =>
|
|
149
|
+
input.trim().length > 0 || "Model ID cannot be empty",
|
|
150
|
+
},
|
|
151
|
+
]);
|
|
152
|
+
model = customAnswer.customModel;
|
|
153
|
+
} else {
|
|
154
|
+
model = providerAnswers.model;
|
|
155
|
+
}
|
|
156
|
+
} else {
|
|
157
|
+
// Local transformer configuration
|
|
158
|
+
const localAnswers = await inquirer.prompt([
|
|
159
|
+
{
|
|
160
|
+
type: "select",
|
|
161
|
+
name: "model",
|
|
162
|
+
message: "Select local embedding model:",
|
|
163
|
+
choices: [
|
|
164
|
+
{
|
|
165
|
+
name: "all-MiniLM-L6-v2 (default, fast, good for general use)",
|
|
166
|
+
value: "Xenova/all-MiniLM-L6-v2",
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
name: "all-mpnet-base-v2 (larger, better quality)",
|
|
170
|
+
value: "Xenova/all-mpnet-base-v2",
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
name: "paraphrase-multilingual-MiniLM-L12-v2 (multilingual support)",
|
|
174
|
+
value: "Xenova/paraphrase-multilingual-MiniLM-L12-v2",
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
name: "Custom model (enter HuggingFace model ID)",
|
|
178
|
+
value: "custom",
|
|
179
|
+
},
|
|
180
|
+
],
|
|
181
|
+
default: existing?.model || "Xenova/all-MiniLM-L6-v2",
|
|
182
|
+
},
|
|
183
|
+
]);
|
|
184
|
+
|
|
185
|
+
if (localAnswers.model === "custom") {
|
|
186
|
+
const customAnswer = await inquirer.prompt([
|
|
187
|
+
{
|
|
188
|
+
type: "input",
|
|
189
|
+
name: "customModel",
|
|
190
|
+
message:
|
|
191
|
+
"Enter HuggingFace model ID (e.g., sentence-transformers/all-MiniLM-L6-v2):",
|
|
192
|
+
validate: (input: string) =>
|
|
193
|
+
input.trim().length > 0 || "Model ID cannot be empty",
|
|
194
|
+
},
|
|
195
|
+
]);
|
|
196
|
+
model = customAnswer.customModel;
|
|
197
|
+
} else {
|
|
198
|
+
model = localAnswers.model;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Save configuration (API key comes from providers.json, not stored here)
|
|
203
|
+
const embeddingConfig: EmbeddingConfig = {
|
|
204
|
+
provider,
|
|
205
|
+
model,
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
// Save model selection to embed.json
|
|
209
|
+
await EmbeddingProviderFactory.saveConfiguration(embeddingConfig, scope, {
|
|
210
|
+
projectPath: scope === "project" ? projectPath : undefined,
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
logger.info(
|
|
214
|
+
`✅ Embedding configuration saved to ${scope} config\n` +
|
|
215
|
+
` Provider: ${provider}\n` +
|
|
216
|
+
` Model: ${model}`
|
|
217
|
+
);
|
|
218
|
+
} catch (error: unknown) {
|
|
219
|
+
// Handle SIGINT (Ctrl+C) gracefully
|
|
220
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
221
|
+
if (errorMessage?.includes("SIGINT") || errorMessage?.includes("force closed")) {
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
logger.error(`Failed to configure embedding model: ${error}`);
|
|
226
|
+
process.exitCode = 1;
|
|
227
|
+
}
|
|
228
|
+
});
|