@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,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
|
+
});
|