@nexus-ai-nexoralabs/cli 0.1.0
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/.env.example +16 -0
- package/LICENSE +21 -0
- package/README.md +106 -0
- package/dist/api/index.d.ts +81 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +224 -0
- package/dist/api/index.js.map +1 -0
- package/dist/chat/chatService.d.ts +49 -0
- package/dist/chat/chatService.d.ts.map +1 -0
- package/dist/chat/chatService.js +163 -0
- package/dist/chat/chatService.js.map +1 -0
- package/dist/chat/contextBuilder.d.ts +19 -0
- package/dist/chat/contextBuilder.d.ts.map +1 -0
- package/dist/chat/contextBuilder.js +43 -0
- package/dist/chat/contextBuilder.js.map +1 -0
- package/dist/chat/conversationService.d.ts +25 -0
- package/dist/chat/conversationService.d.ts.map +1 -0
- package/dist/chat/conversationService.js +55 -0
- package/dist/chat/conversationService.js.map +1 -0
- package/dist/chat/index.d.ts +6 -0
- package/dist/chat/index.d.ts.map +1 -0
- package/dist/chat/index.js +6 -0
- package/dist/chat/index.js.map +1 -0
- package/dist/chat/messageService.d.ts +18 -0
- package/dist/chat/messageService.d.ts.map +1 -0
- package/dist/chat/messageService.js +26 -0
- package/dist/chat/messageService.js.map +1 -0
- package/dist/chat/promptTemplates.d.ts +19 -0
- package/dist/chat/promptTemplates.d.ts.map +1 -0
- package/dist/chat/promptTemplates.js +32 -0
- package/dist/chat/promptTemplates.js.map +1 -0
- package/dist/cli/agentRunner.d.ts +126 -0
- package/dist/cli/agentRunner.d.ts.map +1 -0
- package/dist/cli/agentRunner.js +892 -0
- package/dist/cli/agentRunner.js.map +1 -0
- package/dist/cli/bin.d.ts +14 -0
- package/dist/cli/bin.d.ts.map +1 -0
- package/dist/cli/bin.js +20 -0
- package/dist/cli/bin.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +2 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/inputEngine.d.ts +76 -0
- package/dist/cli/inputEngine.d.ts.map +1 -0
- package/dist/cli/inputEngine.js +281 -0
- package/dist/cli/inputEngine.js.map +1 -0
- package/dist/cli/main.d.ts +9 -0
- package/dist/cli/main.d.ts.map +1 -0
- package/dist/cli/main.js +144 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/cli/uiFormatters.d.ts +108 -0
- package/dist/cli/uiFormatters.d.ts.map +1 -0
- package/dist/cli/uiFormatters.js +925 -0
- package/dist/cli/uiFormatters.js.map +1 -0
- package/dist/common/logger.d.ts +13 -0
- package/dist/common/logger.d.ts.map +1 -0
- package/dist/common/logger.js +43 -0
- package/dist/common/logger.js.map +1 -0
- package/dist/config/firstRunHealthCheck.d.ts +50 -0
- package/dist/config/firstRunHealthCheck.d.ts.map +1 -0
- package/dist/config/firstRunHealthCheck.js +196 -0
- package/dist/config/firstRunHealthCheck.js.map +1 -0
- package/dist/config/firstRunService.d.ts +53 -0
- package/dist/config/firstRunService.d.ts.map +1 -0
- package/dist/config/firstRunService.js +93 -0
- package/dist/config/firstRunService.js.map +1 -0
- package/dist/config/index.d.ts +30 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +65 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/productionPaths.d.ts +34 -0
- package/dist/config/productionPaths.d.ts.map +1 -0
- package/dist/config/productionPaths.js +95 -0
- package/dist/config/productionPaths.js.map +1 -0
- package/dist/config/workspaceService.d.ts +42 -0
- package/dist/config/workspaceService.d.ts.map +1 -0
- package/dist/config/workspaceService.js +218 -0
- package/dist/config/workspaceService.js.map +1 -0
- package/dist/desktop/appWindow.d.ts +21 -0
- package/dist/desktop/appWindow.d.ts.map +1 -0
- package/dist/desktop/appWindow.js +77 -0
- package/dist/desktop/appWindow.js.map +1 -0
- package/dist/desktop/main.d.ts +14 -0
- package/dist/desktop/main.d.ts.map +1 -0
- package/dist/desktop/main.js +90 -0
- package/dist/desktop/main.js.map +1 -0
- package/dist/desktop/preload.d.ts +14 -0
- package/dist/desktop/preload.d.ts.map +1 -0
- package/dist/desktop/preload.js +20 -0
- package/dist/desktop/preload.js.map +1 -0
- package/dist/intelligence/index.d.ts +33 -0
- package/dist/intelligence/index.d.ts.map +1 -0
- package/dist/intelligence/index.js +82 -0
- package/dist/intelligence/index.js.map +1 -0
- package/dist/intelligence/modelGateway.d.ts +35 -0
- package/dist/intelligence/modelGateway.d.ts.map +1 -0
- package/dist/intelligence/modelGateway.js +123 -0
- package/dist/intelligence/modelGateway.js.map +1 -0
- package/dist/intelligence/modelRegistry.d.ts +17 -0
- package/dist/intelligence/modelRegistry.d.ts.map +1 -0
- package/dist/intelligence/modelRegistry.js +87 -0
- package/dist/intelligence/modelRegistry.js.map +1 -0
- package/dist/intelligence/modelRouter.d.ts +76 -0
- package/dist/intelligence/modelRouter.d.ts.map +1 -0
- package/dist/intelligence/modelRouter.js +256 -0
- package/dist/intelligence/modelRouter.js.map +1 -0
- package/dist/intelligence/ollamaAdapter.d.ts +49 -0
- package/dist/intelligence/ollamaAdapter.d.ts.map +1 -0
- package/dist/intelligence/ollamaAdapter.js +197 -0
- package/dist/intelligence/ollamaAdapter.js.map +1 -0
- package/dist/intelligence/prototype/runPrototype.d.ts +14 -0
- package/dist/intelligence/prototype/runPrototype.d.ts.map +1 -0
- package/dist/intelligence/prototype/runPrototype.js +87 -0
- package/dist/intelligence/prototype/runPrototype.js.map +1 -0
- package/dist/intelligence/providers/embeddedInferenceProvider.d.ts +29 -0
- package/dist/intelligence/providers/embeddedInferenceProvider.d.ts.map +1 -0
- package/dist/intelligence/providers/embeddedInferenceProvider.js +162 -0
- package/dist/intelligence/providers/embeddedInferenceProvider.js.map +1 -0
- package/dist/intelligence/providers/index.d.ts +4 -0
- package/dist/intelligence/providers/index.d.ts.map +1 -0
- package/dist/intelligence/providers/index.js +4 -0
- package/dist/intelligence/providers/index.js.map +1 -0
- package/dist/intelligence/providers/inferenceProvider.d.ts +98 -0
- package/dist/intelligence/providers/inferenceProvider.d.ts.map +1 -0
- package/dist/intelligence/providers/inferenceProvider.js +9 -0
- package/dist/intelligence/providers/inferenceProvider.js.map +1 -0
- package/dist/intelligence/providers/ollamaInferenceProvider.d.ts +17 -0
- package/dist/intelligence/providers/ollamaInferenceProvider.d.ts.map +1 -0
- package/dist/intelligence/providers/ollamaInferenceProvider.js +103 -0
- package/dist/intelligence/providers/ollamaInferenceProvider.js.map +1 -0
- package/dist/intelligence/provisioning/hardwareDetector.d.ts +5 -0
- package/dist/intelligence/provisioning/hardwareDetector.d.ts.map +1 -0
- package/dist/intelligence/provisioning/hardwareDetector.js +48 -0
- package/dist/intelligence/provisioning/hardwareDetector.js.map +1 -0
- package/dist/intelligence/provisioning/index.d.ts +12 -0
- package/dist/intelligence/provisioning/index.d.ts.map +1 -0
- package/dist/intelligence/provisioning/index.js +12 -0
- package/dist/intelligence/provisioning/index.js.map +1 -0
- package/dist/intelligence/provisioning/modelDownloader.d.ts +22 -0
- package/dist/intelligence/provisioning/modelDownloader.d.ts.map +1 -0
- package/dist/intelligence/provisioning/modelDownloader.js +134 -0
- package/dist/intelligence/provisioning/modelDownloader.js.map +1 -0
- package/dist/intelligence/provisioning/modelManifest.d.ts +10 -0
- package/dist/intelligence/provisioning/modelManifest.d.ts.map +1 -0
- package/dist/intelligence/provisioning/modelManifest.js +72 -0
- package/dist/intelligence/provisioning/modelManifest.js.map +1 -0
- package/dist/intelligence/provisioning/modelSelector.d.ts +14 -0
- package/dist/intelligence/provisioning/modelSelector.d.ts.map +1 -0
- package/dist/intelligence/provisioning/modelSelector.js +40 -0
- package/dist/intelligence/provisioning/modelSelector.js.map +1 -0
- package/dist/intelligence/provisioning/modelStorage.d.ts +12 -0
- package/dist/intelligence/provisioning/modelStorage.d.ts.map +1 -0
- package/dist/intelligence/provisioning/modelStorage.js +66 -0
- package/dist/intelligence/provisioning/modelStorage.js.map +1 -0
- package/dist/intelligence/provisioning/modelUpdater.d.ts +29 -0
- package/dist/intelligence/provisioning/modelUpdater.d.ts.map +1 -0
- package/dist/intelligence/provisioning/modelUpdater.js +89 -0
- package/dist/intelligence/provisioning/modelUpdater.js.map +1 -0
- package/dist/intelligence/provisioning/modelVerifier.d.ts +16 -0
- package/dist/intelligence/provisioning/modelVerifier.d.ts.map +1 -0
- package/dist/intelligence/provisioning/modelVerifier.js +108 -0
- package/dist/intelligence/provisioning/modelVerifier.js.map +1 -0
- package/dist/intelligence/provisioning/nativeRuntime.d.ts +18 -0
- package/dist/intelligence/provisioning/nativeRuntime.d.ts.map +1 -0
- package/dist/intelligence/provisioning/nativeRuntime.js +78 -0
- package/dist/intelligence/provisioning/nativeRuntime.js.map +1 -0
- package/dist/intelligence/provisioning/platformDetector.d.ts +15 -0
- package/dist/intelligence/provisioning/platformDetector.d.ts.map +1 -0
- package/dist/intelligence/provisioning/platformDetector.js +40 -0
- package/dist/intelligence/provisioning/platformDetector.js.map +1 -0
- package/dist/intelligence/provisioning/setupState.d.ts +10 -0
- package/dist/intelligence/provisioning/setupState.d.ts.map +1 -0
- package/dist/intelligence/provisioning/setupState.js +59 -0
- package/dist/intelligence/provisioning/setupState.js.map +1 -0
- package/dist/intelligence/provisioning/types.d.ts +51 -0
- package/dist/intelligence/provisioning/types.d.ts.map +1 -0
- package/dist/intelligence/provisioning/types.js +2 -0
- package/dist/intelligence/provisioning/types.js.map +1 -0
- package/dist/intelligence/runtime/embeddedRuntimeAdapter.d.ts +26 -0
- package/dist/intelligence/runtime/embeddedRuntimeAdapter.d.ts.map +1 -0
- package/dist/intelligence/runtime/embeddedRuntimeAdapter.js +119 -0
- package/dist/intelligence/runtime/embeddedRuntimeAdapter.js.map +1 -0
- package/dist/intelligence/runtime/ollamaRuntimeAdapter.d.ts +28 -0
- package/dist/intelligence/runtime/ollamaRuntimeAdapter.d.ts.map +1 -0
- package/dist/intelligence/runtime/ollamaRuntimeAdapter.js +131 -0
- package/dist/intelligence/runtime/ollamaRuntimeAdapter.js.map +1 -0
- package/dist/intelligence/runtime/runtimeManager.d.ts +37 -0
- package/dist/intelligence/runtime/runtimeManager.d.ts.map +1 -0
- package/dist/intelligence/runtime/runtimeManager.js +168 -0
- package/dist/intelligence/runtime/runtimeManager.js.map +1 -0
- package/dist/intelligence/runtime/types.d.ts +56 -0
- package/dist/intelligence/runtime/types.d.ts.map +1 -0
- package/dist/intelligence/runtime/types.js +7 -0
- package/dist/intelligence/runtime/types.js.map +1 -0
- package/dist/knowledge/chunker.d.ts +18 -0
- package/dist/knowledge/chunker.d.ts.map +1 -0
- package/dist/knowledge/chunker.js +55 -0
- package/dist/knowledge/chunker.js.map +1 -0
- package/dist/knowledge/citationService.d.ts +26 -0
- package/dist/knowledge/citationService.d.ts.map +1 -0
- package/dist/knowledge/citationService.js +47 -0
- package/dist/knowledge/citationService.js.map +1 -0
- package/dist/knowledge/embeddings.d.ts +11 -0
- package/dist/knowledge/embeddings.d.ts.map +1 -0
- package/dist/knowledge/embeddings.js +28 -0
- package/dist/knowledge/embeddings.js.map +1 -0
- package/dist/knowledge/hybridSearch.d.ts +13 -0
- package/dist/knowledge/hybridSearch.d.ts.map +1 -0
- package/dist/knowledge/hybridSearch.js +38 -0
- package/dist/knowledge/hybridSearch.js.map +1 -0
- package/dist/knowledge/index.d.ts +25 -0
- package/dist/knowledge/index.d.ts.map +1 -0
- package/dist/knowledge/index.js +37 -0
- package/dist/knowledge/index.js.map +1 -0
- package/dist/knowledge/parsers.d.ts +20 -0
- package/dist/knowledge/parsers.d.ts.map +1 -0
- package/dist/knowledge/parsers.js +94 -0
- package/dist/knowledge/parsers.js.map +1 -0
- package/dist/knowledge/ragEngine.d.ts +24 -0
- package/dist/knowledge/ragEngine.d.ts.map +1 -0
- package/dist/knowledge/ragEngine.js +121 -0
- package/dist/knowledge/ragEngine.js.map +1 -0
- package/dist/knowledge/reranker.d.ts +10 -0
- package/dist/knowledge/reranker.d.ts.map +1 -0
- package/dist/knowledge/reranker.js +11 -0
- package/dist/knowledge/reranker.js.map +1 -0
- package/dist/knowledge/vectorStore.d.ts +22 -0
- package/dist/knowledge/vectorStore.d.ts.map +1 -0
- package/dist/knowledge/vectorStore.js +74 -0
- package/dist/knowledge/vectorStore.js.map +1 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +113 -0
- package/dist/main.js.map +1 -0
- package/dist/orchestration/agentExecutionService.d.ts +29 -0
- package/dist/orchestration/agentExecutionService.d.ts.map +1 -0
- package/dist/orchestration/agentExecutionService.js +306 -0
- package/dist/orchestration/agentExecutionService.js.map +1 -0
- package/dist/orchestration/agentStateMachine.d.ts +29 -0
- package/dist/orchestration/agentStateMachine.d.ts.map +1 -0
- package/dist/orchestration/agentStateMachine.js +153 -0
- package/dist/orchestration/agentStateMachine.js.map +1 -0
- package/dist/orchestration/agentTaskService.d.ts +44 -0
- package/dist/orchestration/agentTaskService.d.ts.map +1 -0
- package/dist/orchestration/agentTaskService.js +168 -0
- package/dist/orchestration/agentTaskService.js.map +1 -0
- package/dist/orchestration/codingAgentDiscovery.d.ts +32 -0
- package/dist/orchestration/codingAgentDiscovery.d.ts.map +1 -0
- package/dist/orchestration/codingAgentDiscovery.js +148 -0
- package/dist/orchestration/codingAgentDiscovery.js.map +1 -0
- package/dist/orchestration/codingAgentService.d.ts +40 -0
- package/dist/orchestration/codingAgentService.d.ts.map +1 -0
- package/dist/orchestration/codingAgentService.js +319 -0
- package/dist/orchestration/codingAgentService.js.map +1 -0
- package/dist/orchestration/codingAgentTypes.d.ts +111 -0
- package/dist/orchestration/codingAgentTypes.d.ts.map +1 -0
- package/dist/orchestration/codingAgentTypes.js +32 -0
- package/dist/orchestration/codingAgentTypes.js.map +1 -0
- package/dist/orchestration/codingAgentVerifier.d.ts +34 -0
- package/dist/orchestration/codingAgentVerifier.d.ts.map +1 -0
- package/dist/orchestration/codingAgentVerifier.js +109 -0
- package/dist/orchestration/codingAgentVerifier.js.map +1 -0
- package/dist/orchestration/codingRepairService.d.ts +34 -0
- package/dist/orchestration/codingRepairService.d.ts.map +1 -0
- package/dist/orchestration/codingRepairService.js +120 -0
- package/dist/orchestration/codingRepairService.js.map +1 -0
- package/dist/orchestration/goalCompletionVerifier.d.ts +36 -0
- package/dist/orchestration/goalCompletionVerifier.d.ts.map +1 -0
- package/dist/orchestration/goalCompletionVerifier.js +165 -0
- package/dist/orchestration/goalCompletionVerifier.js.map +1 -0
- package/dist/orchestration/humanApprovalService.d.ts +89 -0
- package/dist/orchestration/humanApprovalService.d.ts.map +1 -0
- package/dist/orchestration/humanApprovalService.js +346 -0
- package/dist/orchestration/humanApprovalService.js.map +1 -0
- package/dist/orchestration/index.d.ts +47 -0
- package/dist/orchestration/index.d.ts.map +1 -0
- package/dist/orchestration/index.js +67 -0
- package/dist/orchestration/index.js.map +1 -0
- package/dist/orchestration/planner.d.ts +105 -0
- package/dist/orchestration/planner.d.ts.map +1 -0
- package/dist/orchestration/planner.js +692 -0
- package/dist/orchestration/planner.js.map +1 -0
- package/dist/orchestration/types.d.ts +109 -0
- package/dist/orchestration/types.d.ts.map +1 -0
- package/dist/orchestration/types.js +20 -0
- package/dist/orchestration/types.js.map +1 -0
- package/dist/preview/previewServer.d.ts +39 -0
- package/dist/preview/previewServer.d.ts.map +1 -0
- package/dist/preview/previewServer.js +228 -0
- package/dist/preview/previewServer.js.map +1 -0
- package/dist/preview/previewService.d.ts +43 -0
- package/dist/preview/previewService.d.ts.map +1 -0
- package/dist/preview/previewService.js +289 -0
- package/dist/preview/previewService.js.map +1 -0
- package/dist/preview/previewTypes.d.ts +35 -0
- package/dist/preview/previewTypes.d.ts.map +1 -0
- package/dist/preview/previewTypes.js +5 -0
- package/dist/preview/previewTypes.js.map +1 -0
- package/dist/storage/database.d.ts +12 -0
- package/dist/storage/database.d.ts.map +1 -0
- package/dist/storage/database.js +46 -0
- package/dist/storage/database.js.map +1 -0
- package/dist/storage/health.d.ts +17 -0
- package/dist/storage/health.d.ts.map +1 -0
- package/dist/storage/health.js +48 -0
- package/dist/storage/health.js.map +1 -0
- package/dist/storage/index.d.ts +45 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +96 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/migration.d.ts +17 -0
- package/dist/storage/migration.d.ts.map +1 -0
- package/dist/storage/migration.js +354 -0
- package/dist/storage/migration.js.map +1 -0
- package/dist/storage/projectService.d.ts +19 -0
- package/dist/storage/projectService.d.ts.map +1 -0
- package/dist/storage/projectService.js +29 -0
- package/dist/storage/projectService.js.map +1 -0
- package/dist/storage/repositories/agentTaskRepository.d.ts +34 -0
- package/dist/storage/repositories/agentTaskRepository.d.ts.map +1 -0
- package/dist/storage/repositories/agentTaskRepository.js +128 -0
- package/dist/storage/repositories/agentTaskRepository.js.map +1 -0
- package/dist/storage/repositories/approvalRepository.d.ts +20 -0
- package/dist/storage/repositories/approvalRepository.d.ts.map +1 -0
- package/dist/storage/repositories/approvalRepository.js +116 -0
- package/dist/storage/repositories/approvalRepository.js.map +1 -0
- package/dist/storage/repositories/conversationRepository.d.ts +16 -0
- package/dist/storage/repositories/conversationRepository.d.ts.map +1 -0
- package/dist/storage/repositories/conversationRepository.js +50 -0
- package/dist/storage/repositories/conversationRepository.js.map +1 -0
- package/dist/storage/repositories/knowledgeRepository.d.ts +109 -0
- package/dist/storage/repositories/knowledgeRepository.d.ts.map +1 -0
- package/dist/storage/repositories/knowledgeRepository.js +177 -0
- package/dist/storage/repositories/knowledgeRepository.js.map +1 -0
- package/dist/storage/repositories/messageRepository.d.ts +13 -0
- package/dist/storage/repositories/messageRepository.d.ts.map +1 -0
- package/dist/storage/repositories/messageRepository.js +39 -0
- package/dist/storage/repositories/messageRepository.js.map +1 -0
- package/dist/storage/repositories/modelsRepository.d.ts +39 -0
- package/dist/storage/repositories/modelsRepository.d.ts.map +1 -0
- package/dist/storage/repositories/modelsRepository.js +92 -0
- package/dist/storage/repositories/modelsRepository.js.map +1 -0
- package/dist/storage/repositories/projectRepository.d.ts +14 -0
- package/dist/storage/repositories/projectRepository.d.ts.map +1 -0
- package/dist/storage/repositories/projectRepository.js +44 -0
- package/dist/storage/repositories/projectRepository.js.map +1 -0
- package/dist/storage/repositories/settingsRepository.d.ts +10 -0
- package/dist/storage/repositories/settingsRepository.d.ts.map +1 -0
- package/dist/storage/repositories/settingsRepository.js +27 -0
- package/dist/storage/repositories/settingsRepository.js.map +1 -0
- package/dist/storage/repositories/types.d.ts +56 -0
- package/dist/storage/repositories/types.d.ts.map +1 -0
- package/dist/storage/repositories/types.js +2 -0
- package/dist/storage/repositories/types.js.map +1 -0
- package/dist/tools/adapters/filesystemAdapter.d.ts +121 -0
- package/dist/tools/adapters/filesystemAdapter.d.ts.map +1 -0
- package/dist/tools/adapters/filesystemAdapter.js +808 -0
- package/dist/tools/adapters/filesystemAdapter.js.map +1 -0
- package/dist/tools/adapters/terminalAdapter.d.ts +67 -0
- package/dist/tools/adapters/terminalAdapter.d.ts.map +1 -0
- package/dist/tools/adapters/terminalAdapter.js +487 -0
- package/dist/tools/adapters/terminalAdapter.js.map +1 -0
- package/dist/tools/adapters/terminalCommandPolicy.d.ts +44 -0
- package/dist/tools/adapters/terminalCommandPolicy.d.ts.map +1 -0
- package/dist/tools/adapters/terminalCommandPolicy.js +422 -0
- package/dist/tools/adapters/terminalCommandPolicy.js.map +1 -0
- package/dist/tools/adapters/terminalTypes.d.ts +111 -0
- package/dist/tools/adapters/terminalTypes.d.ts.map +1 -0
- package/dist/tools/adapters/terminalTypes.js +26 -0
- package/dist/tools/adapters/terminalTypes.js.map +1 -0
- package/dist/tools/approvalGate.d.ts +24 -0
- package/dist/tools/approvalGate.d.ts.map +1 -0
- package/dist/tools/approvalGate.js +137 -0
- package/dist/tools/approvalGate.js.map +1 -0
- package/dist/tools/approvalPolicyEngine.d.ts +32 -0
- package/dist/tools/approvalPolicyEngine.d.ts.map +1 -0
- package/dist/tools/approvalPolicyEngine.js +141 -0
- package/dist/tools/approvalPolicyEngine.js.map +1 -0
- package/dist/tools/approvalTypes.d.ts +67 -0
- package/dist/tools/approvalTypes.d.ts.map +1 -0
- package/dist/tools/approvalTypes.js +23 -0
- package/dist/tools/approvalTypes.js.map +1 -0
- package/dist/tools/index.d.ts +72 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +353 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/permissionEngine.d.ts +27 -0
- package/dist/tools/permissionEngine.d.ts.map +1 -0
- package/dist/tools/permissionEngine.js +130 -0
- package/dist/tools/permissionEngine.js.map +1 -0
- package/dist/tools/toolExecutor.d.ts +37 -0
- package/dist/tools/toolExecutor.d.ts.map +1 -0
- package/dist/tools/toolExecutor.js +440 -0
- package/dist/tools/toolExecutor.js.map +1 -0
- package/dist/tools/toolRegistry.d.ts +34 -0
- package/dist/tools/toolRegistry.d.ts.map +1 -0
- package/dist/tools/toolRegistry.js +92 -0
- package/dist/tools/toolRegistry.js.map +1 -0
- package/dist/tools/types.d.ts +82 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +33 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/ui/public/app.js +777 -0
- package/dist/ui/public/index.html +117 -0
- package/dist/ui/public/styles.css +413 -0
- package/dist/ui/server.d.ts +27 -0
- package/dist/ui/server.d.ts.map +1 -0
- package/dist/ui/server.js +373 -0
- package/dist/ui/server.js.map +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1,892 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NEXUS AI — P7-F: Interactive Agent Runner & Subsystem Integration
|
|
3
|
+
*
|
|
4
|
+
* Provides a human-facing, interactive CLI runner that integrates the entire
|
|
5
|
+
* NEXUS agent pipeline (P5-A through P6-D) without duplicating execution or authorization logic.
|
|
6
|
+
*
|
|
7
|
+
* Sequence:
|
|
8
|
+
* User Task -> Task Creation -> Plan Synthesis -> Plan Validation -> Permission Evaluation
|
|
9
|
+
* -> Approval Policy -> Human Approval when required -> Approval Gate -> Tool Execution
|
|
10
|
+
* -> Observation -> Verification -> Final Result.
|
|
11
|
+
*
|
|
12
|
+
* SECURITY INVARIANTS:
|
|
13
|
+
* - Interface ONLY. Does NOT bypass PlanValidator, PermissionEngine, ApprovalGate, or ToolExecutor.
|
|
14
|
+
* - Zero direct file reads or repository mutations outside existing service APIs.
|
|
15
|
+
* - Zero secrets, API keys, raw prompts, or sensitive tool params logged or displayed.
|
|
16
|
+
*/
|
|
17
|
+
import { Logger } from '../common/logger.js';
|
|
18
|
+
import { colors, getSymbolForState, drawDivider, renderHelpMenu, renderTasksList, renderApprovalCard, renderCompletionCard, renderFailureCard, sanitizeText, renderModelControlScreen, renderModelStatusScreen, renderModelInfoCard, renderPreviewCard, renderPreviewStatusCard, renderPreviewStoppedCard, } from './uiFormatters.js';
|
|
19
|
+
import { SIGNAL_ENTER_COMPOSE, SIGNAL_SEND_COMPOSE } from './inputEngine.js';
|
|
20
|
+
import fs from 'fs';
|
|
21
|
+
import { ModelManifestRegistry, ModelStorageManager, SetupStateManager } from '../intelligence/provisioning/index.js';
|
|
22
|
+
export class AgentRunner {
|
|
23
|
+
api;
|
|
24
|
+
logger;
|
|
25
|
+
currentTask = null;
|
|
26
|
+
currentPlan = null;
|
|
27
|
+
lifecycleLogs = [];
|
|
28
|
+
isResolvingApproval = false;
|
|
29
|
+
constructor(api, logLevel = 'info') {
|
|
30
|
+
this.api = api;
|
|
31
|
+
this.logger = new Logger('AgentRunner', logLevel);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Process a single command input string from the interactive CLI or test runner.
|
|
35
|
+
* Unknown commands return a safe error without crashing.
|
|
36
|
+
*/
|
|
37
|
+
async runCommand(input) {
|
|
38
|
+
const trimmed = input.trim();
|
|
39
|
+
if (!trimmed) {
|
|
40
|
+
return 'Please enter a command or task description. Type /help for available commands.';
|
|
41
|
+
}
|
|
42
|
+
// 1. Intercept input if active task is in awaiting_approval state
|
|
43
|
+
if (this.currentTask) {
|
|
44
|
+
const updatedTask = this.api.tasks.getTask(this.currentTask.id);
|
|
45
|
+
if (updatedTask) {
|
|
46
|
+
this.currentTask = updatedTask;
|
|
47
|
+
}
|
|
48
|
+
if (this.currentTask && this.currentTask.state === 'awaiting_approval') {
|
|
49
|
+
const pending = this.api.approvals?.getApprovalsForTask(this.currentTask.id).filter((a) => a.status === 'pending') || [];
|
|
50
|
+
if (pending.length > 0) {
|
|
51
|
+
const activeAppr = pending[pending.length - 1];
|
|
52
|
+
const lower = trimmed.toLowerCase();
|
|
53
|
+
// Direct Y / N / V input
|
|
54
|
+
if (lower === 'y' || lower === 'yes' || lower === '/y') {
|
|
55
|
+
return this.approveRequest(activeAppr.approvalId);
|
|
56
|
+
}
|
|
57
|
+
if (lower === 'n' || lower === 'no' || lower === '/n') {
|
|
58
|
+
return this.rejectRequest(activeAppr.approvalId);
|
|
59
|
+
}
|
|
60
|
+
if (lower === 'v' || lower === 'view' || lower === '/v') {
|
|
61
|
+
return this.viewApprovalDetails(activeAppr);
|
|
62
|
+
}
|
|
63
|
+
// Explicit slash approval/rejection
|
|
64
|
+
if (trimmed.startsWith('/approve')) {
|
|
65
|
+
const parts = trimmed.split(/\s+/);
|
|
66
|
+
return this.approveRequest(parts[1] || activeAppr.approvalId);
|
|
67
|
+
}
|
|
68
|
+
if (trimmed.startsWith('/reject')) {
|
|
69
|
+
const parts = trimmed.split(/\s+/);
|
|
70
|
+
return this.rejectRequest(parts[1] || activeAppr.approvalId);
|
|
71
|
+
}
|
|
72
|
+
// Allowed non-creation slash commands while awaiting approval
|
|
73
|
+
if (trimmed.startsWith('/help') ||
|
|
74
|
+
trimmed.startsWith('/?') ||
|
|
75
|
+
trimmed.startsWith('/h') ||
|
|
76
|
+
trimmed.startsWith('/status') ||
|
|
77
|
+
trimmed.startsWith('/st') ||
|
|
78
|
+
trimmed.startsWith('/approvals') ||
|
|
79
|
+
trimmed.startsWith('/appr') ||
|
|
80
|
+
trimmed.startsWith('/cancel') ||
|
|
81
|
+
trimmed.startsWith('/exit') ||
|
|
82
|
+
trimmed.startsWith('/quit') ||
|
|
83
|
+
trimmed.startsWith('/q') ||
|
|
84
|
+
trimmed.startsWith('/clear') ||
|
|
85
|
+
trimmed.startsWith('/cls')) {
|
|
86
|
+
// fall through to switch handling below
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
// Block all other input (prevent creating new tasks while awaiting approval)
|
|
90
|
+
return `\n${colors.brightYellow}⚠ APPROVAL REQUIRED for task '${this.currentTask.id}'${colors.reset}\nStep '${activeAppr.stepId}' requires tool '${activeAppr.toolId}' (${activeAppr.riskLevel.toUpperCase()}).\nChoose:\n [Y] Approve & Resume (/approve ${activeAppr.approvalId})\n [N] Reject & Cancel (/reject ${activeAppr.approvalId})\n [V] View details\n Type /cancel to cancel task.`;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// 2. Standard Slash command parsing
|
|
96
|
+
if (trimmed.startsWith('/')) {
|
|
97
|
+
const parts = trimmed.split(/\s+/);
|
|
98
|
+
const cmd = parts[0].toLowerCase();
|
|
99
|
+
const args = parts.slice(1);
|
|
100
|
+
switch (cmd) {
|
|
101
|
+
case '/help':
|
|
102
|
+
case '/?':
|
|
103
|
+
case '/h':
|
|
104
|
+
return this.getHelpText();
|
|
105
|
+
case '/status':
|
|
106
|
+
case '/st':
|
|
107
|
+
return this.getStatusText();
|
|
108
|
+
case '/models':
|
|
109
|
+
case '/m':
|
|
110
|
+
return this.getModelsText();
|
|
111
|
+
case '/model':
|
|
112
|
+
return this.handleModelCommand(args);
|
|
113
|
+
case '/workspace':
|
|
114
|
+
case '/ws':
|
|
115
|
+
return this.getWorkspaceText();
|
|
116
|
+
case '/tasks':
|
|
117
|
+
case '/history':
|
|
118
|
+
case '/t':
|
|
119
|
+
if (args.length > 0) {
|
|
120
|
+
return this.inspectTaskText(args[0]);
|
|
121
|
+
}
|
|
122
|
+
return this.getTasksListText();
|
|
123
|
+
case '/task':
|
|
124
|
+
if (args.length > 0 && args[0].startsWith('task-')) {
|
|
125
|
+
return this.inspectTaskText(args[0]);
|
|
126
|
+
}
|
|
127
|
+
return this.submitTask(args.join(' '));
|
|
128
|
+
case '/inspect':
|
|
129
|
+
return this.inspectTaskText(args[0]);
|
|
130
|
+
case '/code':
|
|
131
|
+
return this.submitCodingTask(args.join(' '));
|
|
132
|
+
case '/prompt':
|
|
133
|
+
// Signal to InputEngine to enter compose (multi-line) mode
|
|
134
|
+
return SIGNAL_ENTER_COMPOSE;
|
|
135
|
+
case '/send':
|
|
136
|
+
// Signal to InputEngine to submit the compose buffer
|
|
137
|
+
return SIGNAL_SEND_COMPOSE;
|
|
138
|
+
case '/plan':
|
|
139
|
+
return this.getPlanText();
|
|
140
|
+
case '/approvals':
|
|
141
|
+
case '/appr':
|
|
142
|
+
return this.getApprovalsText();
|
|
143
|
+
case '/approve':
|
|
144
|
+
case '/y':
|
|
145
|
+
return this.approveRequest(args[0]);
|
|
146
|
+
case '/reject':
|
|
147
|
+
case '/n':
|
|
148
|
+
return this.rejectRequest(args[0]);
|
|
149
|
+
case '/agents':
|
|
150
|
+
case '/ag':
|
|
151
|
+
return this.getAgentsStatusText();
|
|
152
|
+
case '/clear':
|
|
153
|
+
case '/cls':
|
|
154
|
+
return this.clearScreen();
|
|
155
|
+
case '/cancel':
|
|
156
|
+
return this.cancelCurrentTask();
|
|
157
|
+
case '/preview':
|
|
158
|
+
case '/prev':
|
|
159
|
+
case '/p':
|
|
160
|
+
return this.handlePreviewCommand(args);
|
|
161
|
+
case '/result':
|
|
162
|
+
return this.getResultText();
|
|
163
|
+
case '/exit':
|
|
164
|
+
case '/quit':
|
|
165
|
+
case '/q':
|
|
166
|
+
return this.exitRunner();
|
|
167
|
+
default:
|
|
168
|
+
this.logger.warn(`Unknown command '${cmd}' received`);
|
|
169
|
+
return `Unknown command '${cmd}'. Type /help for available commands.`;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
// Non-slash input is treated as a natural language task submission
|
|
173
|
+
return this.submitTask(trimmed, true);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Submit a new user task and run through the P5 architecture pipeline.
|
|
177
|
+
*
|
|
178
|
+
* @param goal - The natural language task goal.
|
|
179
|
+
* @param _showPreview - If true, a prompt preview was already rendered by InputEngine
|
|
180
|
+
* before calling runCommand(). Unused here; preview is output-only in InputEngine.
|
|
181
|
+
*/
|
|
182
|
+
async submitTask(goal, _showPreview = false) {
|
|
183
|
+
const trimmedGoal = goal.trim();
|
|
184
|
+
if (!trimmedGoal) {
|
|
185
|
+
return 'Task description cannot be empty. Usage: /task <description>';
|
|
186
|
+
}
|
|
187
|
+
if (!this.api.planner || !this.api.execution || !this.api.approvals) {
|
|
188
|
+
return 'Error: ApplicationApi agent subsystems are uninitialized.';
|
|
189
|
+
}
|
|
190
|
+
const startTime = Date.now();
|
|
191
|
+
const lines = [];
|
|
192
|
+
lines.push(`${colors.bold}${colors.brightCyan}NEXUS AI Agent Execution Engine${colors.reset}`);
|
|
193
|
+
lines.push(drawDivider('─', 64));
|
|
194
|
+
// 1. Task Creation
|
|
195
|
+
const title = trimmedGoal.length > 60 ? `${trimmedGoal.slice(0, 57)}...` : trimmedGoal;
|
|
196
|
+
const task = this.api.tasks.createTask({ title });
|
|
197
|
+
this.currentTask = task;
|
|
198
|
+
this.currentPlan = null;
|
|
199
|
+
this.recordEvent('TASK_CREATED', `TaskId: ${task.id}`);
|
|
200
|
+
lines.push(`→ ${colors.bold}Task Submitted:${colors.reset} "${title}"`);
|
|
201
|
+
lines.push(` ${colors.dim}Task ID:${colors.reset} ${colors.brightCyan}${task.id}${colors.reset}`);
|
|
202
|
+
lines.push('');
|
|
203
|
+
lines.push(`${colors.bold}THINKing...${colors.reset}`);
|
|
204
|
+
lines.push(` ${colors.dim}● Synthesizing plan with planner model...${colors.reset}`);
|
|
205
|
+
// 2. Plan Synthesis
|
|
206
|
+
const synthesis = await this.api.planner.synthesize(task.id, {
|
|
207
|
+
taskGoal: trimmedGoal,
|
|
208
|
+
temperature: 0.2,
|
|
209
|
+
});
|
|
210
|
+
if (!synthesis.success || !synthesis.plan) {
|
|
211
|
+
this.recordEvent('PLAN_VALIDATION_FAILED', synthesis.errorMessage);
|
|
212
|
+
this.api.tasks.failTask(task.id, {
|
|
213
|
+
errorCategory: synthesis.errorCategory || 'PLAN_VALIDATION_FAILED',
|
|
214
|
+
});
|
|
215
|
+
const failedTask = this.api.tasks.getTask(task.id);
|
|
216
|
+
this.currentTask = failedTask;
|
|
217
|
+
this.recordEvent('TASK_FAILED', synthesis.errorMessage);
|
|
218
|
+
return renderFailureCard(failedTask, synthesis.errorMessage || 'Plan synthesis failed');
|
|
219
|
+
}
|
|
220
|
+
this.currentPlan = synthesis.plan;
|
|
221
|
+
this.api.tasks.transitionTask(task.id, {
|
|
222
|
+
plan: JSON.stringify(synthesis.plan),
|
|
223
|
+
targetState: 'planning',
|
|
224
|
+
});
|
|
225
|
+
this.recordEvent('PLAN_GENERATED', `PlanId: ${synthesis.plan.planId}`);
|
|
226
|
+
this.recordEvent('PLAN_VALIDATED', `${synthesis.plan.steps.length} step(s) validated`);
|
|
227
|
+
lines.push('');
|
|
228
|
+
lines.push(`${colors.bold}PLAN${colors.reset}`);
|
|
229
|
+
lines.push(` ${colors.bold}Reasoning:${colors.reset} ${synthesis.plan.reasoning}`);
|
|
230
|
+
lines.push('');
|
|
231
|
+
lines.push(` ${colors.dim}┌──────┬──────────────────────────┬──────────────────────┬───────────┐${colors.reset}`);
|
|
232
|
+
lines.push(` │ Step │ Tool │ Capability │ Risk │`);
|
|
233
|
+
lines.push(` ${colors.dim}├──────┼──────────────────────────┼──────────────────────┼───────────┤${colors.reset}`);
|
|
234
|
+
synthesis.plan.steps.forEach((step, idx) => {
|
|
235
|
+
const toolDef = this.api.tools.getTool(step.toolId || '');
|
|
236
|
+
const risk = toolDef ? toolDef.riskLevel.toUpperCase() : 'UNKNOWN';
|
|
237
|
+
const riskColor = risk === 'HIGH' ? colors.brightRed : risk === 'MEDIUM' ? colors.brightYellow : colors.green;
|
|
238
|
+
const stepIdStr = String(idx + 1).padEnd(4, ' ');
|
|
239
|
+
const toolStr = (step.toolId || '').padEnd(24, ' ');
|
|
240
|
+
const capStr = (step.requestedCapabilities?.[0] || '').padEnd(20, ' ');
|
|
241
|
+
lines.push(` │ ${stepIdStr} │ ${colors.brightCyan}${toolStr}${colors.reset} │ ${capStr} │ ${riskColor}${risk.padEnd(9, ' ')}${colors.reset} │`);
|
|
242
|
+
});
|
|
243
|
+
lines.push(` ${colors.dim}└──────┴──────────────────────────┴──────────────────────┴───────────┘${colors.reset}`);
|
|
244
|
+
lines.push('');
|
|
245
|
+
lines.push(`${colors.bold}EXECUTE${colors.reset}`);
|
|
246
|
+
this.recordEvent('AUTHORIZATION_CHECKED', 'PermissionEngine check passed');
|
|
247
|
+
// 3. Execution Loop
|
|
248
|
+
const executionResultTask = await this.api.execution.runExecutionLoop(task.id, synthesis.plan.steps);
|
|
249
|
+
this.currentTask = executionResultTask;
|
|
250
|
+
const durationMs = Date.now() - startTime;
|
|
251
|
+
// 4. Handle Execution Result State
|
|
252
|
+
if (executionResultTask.state === 'awaiting_approval') {
|
|
253
|
+
this.recordEvent('APPROVAL_REQUIRED', `Task paused in awaiting_approval state`);
|
|
254
|
+
const pendingApprovals = this.api.approvals.getApprovalsForTask(task.id).filter((a) => a.status === 'pending');
|
|
255
|
+
const latestPending = pendingApprovals.length > 0 ? pendingApprovals[pendingApprovals.length - 1] : null;
|
|
256
|
+
if (latestPending) {
|
|
257
|
+
lines.push(renderApprovalCard(latestPending, executionResultTask.title));
|
|
258
|
+
}
|
|
259
|
+
else {
|
|
260
|
+
lines.push(`\n${colors.brightYellow}⚠ APPROVAL REQUIRED for task '${executionResultTask.id}'. Use /approvals to inspect.${colors.reset}`);
|
|
261
|
+
}
|
|
262
|
+
return lines.join('\n');
|
|
263
|
+
}
|
|
264
|
+
if (executionResultTask.state === 'completed') {
|
|
265
|
+
this.recordEvent('STEP_COMPLETED', 'All steps completed');
|
|
266
|
+
this.recordEvent('VERIFICATION_COMPLETED', 'Verification passed');
|
|
267
|
+
this.recordEvent('TASK_COMPLETED', `Task ${task.id} completed successfully`);
|
|
268
|
+
lines.push(renderCompletionCard(executionResultTask, synthesis.plan, durationMs));
|
|
269
|
+
return lines.join('\n');
|
|
270
|
+
}
|
|
271
|
+
if (executionResultTask.state === 'failed') {
|
|
272
|
+
this.recordEvent('TASK_FAILED', `Error Category: ${executionResultTask.errorCategory || 'UNKNOWN'}`);
|
|
273
|
+
lines.push(renderFailureCard(executionResultTask, synthesis.errorMessage || 'Execution step failed'));
|
|
274
|
+
return lines.join('\n');
|
|
275
|
+
}
|
|
276
|
+
if (executionResultTask.state === 'cancelled') {
|
|
277
|
+
this.recordEvent('TASK_CANCELLED', `Task ${task.id} cancelled`);
|
|
278
|
+
lines.push(`\n${colors.dim}○ Task '${task.id}' execution was cancelled.${colors.reset}`);
|
|
279
|
+
return lines.join('\n');
|
|
280
|
+
}
|
|
281
|
+
return lines.join('\n');
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Submit a coding task through CodingAgentService (P6-D).
|
|
285
|
+
*/
|
|
286
|
+
async submitCodingTask(goal) {
|
|
287
|
+
const trimmedGoal = goal.trim();
|
|
288
|
+
if (!trimmedGoal) {
|
|
289
|
+
return 'Coding task goal cannot be empty. Usage: /code <goal>';
|
|
290
|
+
}
|
|
291
|
+
if (!this.api.codingAgent) {
|
|
292
|
+
return 'Error: ApplicationApi codingAgent subsystem is uninitialized.';
|
|
293
|
+
}
|
|
294
|
+
this.recordEvent('CODING_TASK_SUBMITTED', `Goal: ${trimmedGoal}`);
|
|
295
|
+
const runResult = await this.api.codingAgent.runCodingTask({
|
|
296
|
+
taskGoal: trimmedGoal,
|
|
297
|
+
});
|
|
298
|
+
if (runResult.taskId) {
|
|
299
|
+
this.currentTask = this.api.tasks.getTask(runResult.taskId);
|
|
300
|
+
}
|
|
301
|
+
if (runResult.success) {
|
|
302
|
+
this.recordEvent('CODING_TASK_COMPLETED', `Task ${runResult.taskId} completed`);
|
|
303
|
+
return `${colors.brightGreen}✓ [Coding Task Completed]${colors.reset} Task '${runResult.taskId}' completed successfully after ${runResult.repairAttemptsCount} repair attempt(s).`;
|
|
304
|
+
}
|
|
305
|
+
this.recordEvent('CODING_TASK_FAILED', `Task ${runResult.taskId} state: ${runResult.state}`);
|
|
306
|
+
return `${colors.brightRed}✖ [Coding Task Failed]${colors.reset} Task '${runResult.taskId}' ended in state '${runResult.state}' (${runResult.errorCategory || 'FAILED'}): ${runResult.errorMessage || 'Validation failed.'}`;
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Resolve an approval request as approved and resume execution.
|
|
310
|
+
*/
|
|
311
|
+
async approveRequest(approvalId) {
|
|
312
|
+
if (this.isResolvingApproval) {
|
|
313
|
+
return `${colors.brightYellow}Approval resolution is already in progress. Please wait...${colors.reset}`;
|
|
314
|
+
}
|
|
315
|
+
this.isResolvingApproval = true;
|
|
316
|
+
try {
|
|
317
|
+
let targetId = approvalId?.trim();
|
|
318
|
+
// Fallback: resolve latest pending approval for current active task
|
|
319
|
+
if (!targetId && this.currentTask) {
|
|
320
|
+
const updatedTask = this.api.tasks.getTask(this.currentTask.id);
|
|
321
|
+
if (updatedTask) {
|
|
322
|
+
this.currentTask = updatedTask;
|
|
323
|
+
}
|
|
324
|
+
const pending = this.api.approvals?.getApprovalsForTask(this.currentTask.id).filter((a) => a.status === 'pending') || [];
|
|
325
|
+
if (pending.length > 0) {
|
|
326
|
+
targetId = pending[pending.length - 1].approvalId;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
if (!targetId) {
|
|
330
|
+
return 'Error: Missing approval ID and no pending approval found for active task. Usage: /approve <approvalId>';
|
|
331
|
+
}
|
|
332
|
+
if (!this.api.approvals || !this.api.execution) {
|
|
333
|
+
return 'Error: ApplicationApi approval subsystems are uninitialized.';
|
|
334
|
+
}
|
|
335
|
+
let result;
|
|
336
|
+
try {
|
|
337
|
+
result = this.api.approvals.resolveApproval(targetId, 'approved', 'User approved via CLI');
|
|
338
|
+
}
|
|
339
|
+
catch (err) {
|
|
340
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
341
|
+
this.logger.warn(`resolveApproval threw for approvalId '${targetId}': ${msg}`);
|
|
342
|
+
return `Error approving request '${targetId}': ${msg}`;
|
|
343
|
+
}
|
|
344
|
+
if (!result.success) {
|
|
345
|
+
return `Error approving request '${targetId}': ${result.error || 'Invalid approval resolution'}`;
|
|
346
|
+
}
|
|
347
|
+
this.recordEvent('APPROVAL_GRANTED', `ApprovalId: ${targetId}`);
|
|
348
|
+
if (result.task) {
|
|
349
|
+
this.currentTask = result.task;
|
|
350
|
+
}
|
|
351
|
+
// Re-hydrate currentPlan from stored task plan if null
|
|
352
|
+
if (this.currentTask && !this.currentPlan && this.currentTask.plan) {
|
|
353
|
+
try {
|
|
354
|
+
this.currentPlan = typeof this.currentTask.plan === 'string'
|
|
355
|
+
? JSON.parse(this.currentTask.plan)
|
|
356
|
+
: this.currentTask.plan;
|
|
357
|
+
}
|
|
358
|
+
catch {
|
|
359
|
+
/* ignore parse error */
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
if (!this.currentPlan || !this.currentTask) {
|
|
363
|
+
return `${colors.brightGreen}✓ Approval '${targetId}' granted.${colors.reset} Task state is now EXECUTING.`;
|
|
364
|
+
}
|
|
365
|
+
const lines = [];
|
|
366
|
+
lines.push(`${colors.brightGreen}✓ Approval '${targetId}' granted${colors.reset}`);
|
|
367
|
+
lines.push('→ Resuming task execution loop...');
|
|
368
|
+
this.recordEvent('STEP_STARTED', `Resuming task ${this.currentTask.id}`);
|
|
369
|
+
// Resume execution loop on original task with original plan steps
|
|
370
|
+
const resumedTask = await this.api.execution.runExecutionLoop(this.currentTask.id, this.currentPlan.steps);
|
|
371
|
+
this.currentTask = resumedTask;
|
|
372
|
+
if (resumedTask.state === 'completed') {
|
|
373
|
+
this.recordEvent('STEP_COMPLETED', 'Resumed steps completed');
|
|
374
|
+
this.recordEvent('VERIFICATION_COMPLETED', 'Verification passed');
|
|
375
|
+
this.recordEvent('TASK_COMPLETED', `Task ${resumedTask.id} completed successfully`);
|
|
376
|
+
lines.push(renderCompletionCard(resumedTask, this.currentPlan));
|
|
377
|
+
return lines.join('\n');
|
|
378
|
+
}
|
|
379
|
+
if (resumedTask.state === 'awaiting_approval') {
|
|
380
|
+
this.recordEvent('APPROVAL_REQUIRED', `Task paused in awaiting_approval state`);
|
|
381
|
+
const pendingApprovals = this.api.approvals.getApprovalsForTask(resumedTask.id).filter((a) => a.status === 'pending');
|
|
382
|
+
const latestPending = pendingApprovals.length > 0 ? pendingApprovals[pendingApprovals.length - 1] : null;
|
|
383
|
+
if (latestPending) {
|
|
384
|
+
lines.push(renderApprovalCard(latestPending, resumedTask.title));
|
|
385
|
+
}
|
|
386
|
+
else {
|
|
387
|
+
lines.push(`\n${colors.brightYellow}⚠ Another approval is required for subsequent step.${colors.reset}`);
|
|
388
|
+
lines.push('Use /approvals to inspect pending requests.');
|
|
389
|
+
}
|
|
390
|
+
return lines.join('\n');
|
|
391
|
+
}
|
|
392
|
+
if (resumedTask.state === 'failed') {
|
|
393
|
+
this.recordEvent('STEP_FAILED', `Error: ${resumedTask.errorCategory}`);
|
|
394
|
+
this.recordEvent('TASK_FAILED', `Task ${resumedTask.id} failed`);
|
|
395
|
+
lines.push(renderFailureCard(resumedTask, 'Resumed step execution failed'));
|
|
396
|
+
return lines.join('\n');
|
|
397
|
+
}
|
|
398
|
+
lines.push(`Task state updated to: ${resumedTask.state.toUpperCase()}`);
|
|
399
|
+
return lines.join('\n');
|
|
400
|
+
}
|
|
401
|
+
finally {
|
|
402
|
+
this.isResolvingApproval = false;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Resolve an approval request as rejected and stop execution.
|
|
407
|
+
*/
|
|
408
|
+
async rejectRequest(approvalId) {
|
|
409
|
+
if (this.isResolvingApproval) {
|
|
410
|
+
return `${colors.brightYellow}Approval resolution is already in progress. Please wait...${colors.reset}`;
|
|
411
|
+
}
|
|
412
|
+
this.isResolvingApproval = true;
|
|
413
|
+
try {
|
|
414
|
+
let targetId = approvalId?.trim();
|
|
415
|
+
// Fallback: resolve latest pending approval for current active task
|
|
416
|
+
if (!targetId && this.currentTask) {
|
|
417
|
+
const updatedTask = this.api.tasks.getTask(this.currentTask.id);
|
|
418
|
+
if (updatedTask) {
|
|
419
|
+
this.currentTask = updatedTask;
|
|
420
|
+
}
|
|
421
|
+
const pending = this.api.approvals?.getApprovalsForTask(this.currentTask.id).filter((a) => a.status === 'pending') || [];
|
|
422
|
+
if (pending.length > 0) {
|
|
423
|
+
targetId = pending[pending.length - 1].approvalId;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
if (!targetId) {
|
|
427
|
+
return 'Error: Missing approval ID and no pending approval found for active task. Usage: /reject <approvalId>';
|
|
428
|
+
}
|
|
429
|
+
if (!this.api.approvals) {
|
|
430
|
+
return 'Error: ApplicationApi approval subsystems are uninitialized.';
|
|
431
|
+
}
|
|
432
|
+
let result;
|
|
433
|
+
try {
|
|
434
|
+
result = this.api.approvals.resolveApproval(targetId, 'rejected', 'User rejected via CLI');
|
|
435
|
+
}
|
|
436
|
+
catch (err) {
|
|
437
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
438
|
+
this.logger.warn(`resolveApproval threw for approvalId '${targetId}': ${msg}`);
|
|
439
|
+
return `Error rejecting request '${targetId}': ${msg}`;
|
|
440
|
+
}
|
|
441
|
+
if (!result.success) {
|
|
442
|
+
return `Error rejecting request '${targetId}': ${result.error || 'Invalid approval resolution'}`;
|
|
443
|
+
}
|
|
444
|
+
this.recordEvent('APPROVAL_REJECTED', `ApprovalId: ${targetId}`);
|
|
445
|
+
if (result.task) {
|
|
446
|
+
this.currentTask = result.task;
|
|
447
|
+
this.recordEvent('TASK_CANCELLED', `Task ${result.task.id} cancelled due to approval rejection`);
|
|
448
|
+
}
|
|
449
|
+
const lines = [];
|
|
450
|
+
lines.push(`${colors.brightRed}✖ Approval '${targetId}' rejected${colors.reset}`);
|
|
451
|
+
lines.push('Execution stopped. Task state: CANCELLED.');
|
|
452
|
+
return lines.join('\n');
|
|
453
|
+
}
|
|
454
|
+
finally {
|
|
455
|
+
this.isResolvingApproval = false;
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Display detailed parameters and information for a pending approval request.
|
|
460
|
+
*/
|
|
461
|
+
viewApprovalDetails(approval) {
|
|
462
|
+
const lines = [];
|
|
463
|
+
lines.push(drawDivider('─', 64));
|
|
464
|
+
lines.push(`${colors.bold}${colors.brightCyan}APPROVAL REQUEST DETAILS${colors.reset}`);
|
|
465
|
+
lines.push(` ${colors.bold}Approval ID:${colors.reset} ${approval.approvalId}`);
|
|
466
|
+
lines.push(` ${colors.bold}Task ID:${colors.reset} ${approval.taskId}`);
|
|
467
|
+
lines.push(` ${colors.bold}Step ID:${colors.reset} ${approval.stepId}`);
|
|
468
|
+
lines.push(` ${colors.bold}Tool Required:${colors.reset} ${approval.toolId}`);
|
|
469
|
+
lines.push(` ${colors.bold}Risk Level:${colors.reset} ${approval.riskLevel.toUpperCase()}`);
|
|
470
|
+
lines.push(` ${colors.bold}Capability:${colors.reset} ${approval.requestedCapability}`);
|
|
471
|
+
lines.push(` ${colors.bold}Status:${colors.reset} ${approval.status.toUpperCase()}`);
|
|
472
|
+
lines.push(` ${colors.bold}Created At:${colors.reset} ${approval.createdAt}`);
|
|
473
|
+
lines.push(` ${colors.bold}Expires At:${colors.reset} ${approval.expiresAt}`);
|
|
474
|
+
lines.push(` ${colors.bold}Reason:${colors.reset} ${approval.decisionReason || 'Action requires explicit human approval'}`);
|
|
475
|
+
lines.push('');
|
|
476
|
+
lines.push(`${colors.bold}Options:${colors.reset}`);
|
|
477
|
+
lines.push(` ${colors.brightGreen}[Y] Approve & Resume${colors.reset} ${colors.brightRed}[N] Reject & Cancel${colors.reset} ${colors.brightCyan}[V] View Details${colors.reset}`);
|
|
478
|
+
lines.push(drawDivider('─', 64));
|
|
479
|
+
return lines.join('\n');
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* Cancel active task and invalidate pending approvals.
|
|
483
|
+
*/
|
|
484
|
+
async cancelCurrentTask() {
|
|
485
|
+
if (!this.currentTask) {
|
|
486
|
+
return 'No active task to cancel.';
|
|
487
|
+
}
|
|
488
|
+
const taskId = this.currentTask.id;
|
|
489
|
+
const task = this.api.tasks.cancelTask(taskId);
|
|
490
|
+
this.currentTask = task;
|
|
491
|
+
if (this.api.approvals) {
|
|
492
|
+
this.api.approvals.cancelApprovalsForTask(taskId, 'Task cancelled by user via CLI');
|
|
493
|
+
}
|
|
494
|
+
this.recordEvent('TASK_CANCELLED', `Task ${taskId} cancelled by user`);
|
|
495
|
+
return `${colors.dim}✓ Task '${task.title}' (ID: ${taskId}) cancelled. State: CANCELLED.${colors.reset}`;
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
* Returns help command menu.
|
|
499
|
+
*/
|
|
500
|
+
getHelpText() {
|
|
501
|
+
return renderHelpMenu();
|
|
502
|
+
}
|
|
503
|
+
/**
|
|
504
|
+
* Returns current task status text without exposing secrets.
|
|
505
|
+
*/
|
|
506
|
+
getStatusText() {
|
|
507
|
+
const report = this.api.getHealthReport();
|
|
508
|
+
const lines = [];
|
|
509
|
+
lines.push(`${colors.bold}${colors.brightCyan}NEXUS AI Task Status & System Readiness${colors.reset}`);
|
|
510
|
+
lines.push(drawDivider('─', 60));
|
|
511
|
+
lines.push(`Overall Status: ${report.overall === 'ok' ? colors.brightGreen + 'OK' : colors.brightYellow + 'DEGRADED'}${colors.reset}`);
|
|
512
|
+
lines.push(`Environment: ${report.config.environment}`);
|
|
513
|
+
lines.push(`Database: Connected (${report.config.databasePath})`);
|
|
514
|
+
lines.push(`Ollama Host: ${report.config.ollamaHost}`);
|
|
515
|
+
lines.push('');
|
|
516
|
+
if (!this.currentTask) {
|
|
517
|
+
lines.push(`${colors.dim}No active task. Submit a task using: /task <description>${colors.reset}`);
|
|
518
|
+
}
|
|
519
|
+
else {
|
|
520
|
+
const t = this.api.tasks.getTask(this.currentTask.id);
|
|
521
|
+
this.currentTask = t;
|
|
522
|
+
lines.push(`${colors.bold}ACTIVE TASK${colors.reset}`);
|
|
523
|
+
lines.push(` Task ID: ${t.id}`);
|
|
524
|
+
lines.push(` Title: ${t.title}`);
|
|
525
|
+
lines.push(` State: ${getSymbolForState(t.state)} ${t.state.toUpperCase()}`);
|
|
526
|
+
lines.push(` Current Step: ${t.currentStep || '(none)'}`);
|
|
527
|
+
lines.push(` Attempt Count: ${t.attemptCount}`);
|
|
528
|
+
lines.push(` Error Category: ${t.errorCategory || 'none'}`);
|
|
529
|
+
lines.push(` Created At: ${t.createdAt}`);
|
|
530
|
+
}
|
|
531
|
+
return lines.join('\n');
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
534
|
+
* P7-H: Handles /preview command and sub-commands (stop, status, taskId).
|
|
535
|
+
*/
|
|
536
|
+
async handlePreviewCommand(args) {
|
|
537
|
+
if (!this.api.preview) {
|
|
538
|
+
return `${colors.brightRed}Error: ApplicationApi preview subsystem is uninitialized.${colors.reset}`;
|
|
539
|
+
}
|
|
540
|
+
if (args.length > 0) {
|
|
541
|
+
const sub = args[0].toLowerCase();
|
|
542
|
+
if (sub === 'stop') {
|
|
543
|
+
await this.api.preview.stop();
|
|
544
|
+
return renderPreviewStoppedCard();
|
|
545
|
+
}
|
|
546
|
+
if (sub === 'status') {
|
|
547
|
+
const st = this.api.preview.getStatus();
|
|
548
|
+
return renderPreviewStatusCard(st);
|
|
549
|
+
}
|
|
550
|
+
// Explicit task-id preview requested
|
|
551
|
+
const res = await this.api.preview.preview(args[0]);
|
|
552
|
+
return renderPreviewCard(res);
|
|
553
|
+
}
|
|
554
|
+
// Default: /preview latest completed web task
|
|
555
|
+
const res = await this.api.preview.preview();
|
|
556
|
+
return renderPreviewCard(res);
|
|
557
|
+
}
|
|
558
|
+
/**
|
|
559
|
+
* P7-G: Handles /model control command and sub-commands.
|
|
560
|
+
*/
|
|
561
|
+
handleModelCommand(args) {
|
|
562
|
+
const router = this.api.intelligence.router;
|
|
563
|
+
const registry = this.api.intelligence.registry;
|
|
564
|
+
if (!router || !registry) {
|
|
565
|
+
return `${colors.brightRed}Error: Intelligence router or registry uninitialized.${colors.reset}`;
|
|
566
|
+
}
|
|
567
|
+
const available = registry.getAvailableModels();
|
|
568
|
+
const intelStatus = typeof this.api.intelligence?.getStatus === 'function' ? this.api.intelligence.getStatus() : null;
|
|
569
|
+
const activeProvider = intelStatus?.details?.['activeProvider'] || 'embedded';
|
|
570
|
+
const providerName = activeProvider === 'embedded' ? 'Embedded (Local)' : 'Ollama';
|
|
571
|
+
// /model (no args): Display Model Control screen
|
|
572
|
+
if (args.length === 0) {
|
|
573
|
+
const roleStatus = router.getRoleStatus();
|
|
574
|
+
return renderModelControlScreen(available, roleStatus, providerName);
|
|
575
|
+
}
|
|
576
|
+
const sub = args[0].toLowerCase();
|
|
577
|
+
// /model status: Display status screen
|
|
578
|
+
if (sub === 'status') {
|
|
579
|
+
const roleStatus = router.getRoleStatus();
|
|
580
|
+
const overrides = router.getOverrides();
|
|
581
|
+
const runtimeVersion = intelStatus?.details?.['runtimeVersion'] || intelStatus?.details?.['ollamaVersion'] || '0.1.0';
|
|
582
|
+
return renderModelStatusScreen(roleStatus, overrides.global, runtimeVersion, available.length, providerName);
|
|
583
|
+
}
|
|
584
|
+
// /model info <id>: Display model metadata card
|
|
585
|
+
if (sub === 'info') {
|
|
586
|
+
const targetId = args[1] || 'nexus-proto-0.5b';
|
|
587
|
+
const manifestReg = new ModelManifestRegistry();
|
|
588
|
+
const manifest = manifestReg.getManifest(targetId) || {
|
|
589
|
+
id: targetId,
|
|
590
|
+
displayName: targetId,
|
|
591
|
+
version: '0.1.0',
|
|
592
|
+
sizeBytes: 390 * 1024 * 1024,
|
|
593
|
+
format: 'gguf',
|
|
594
|
+
tier: 'low',
|
|
595
|
+
license: 'Apache-2.0',
|
|
596
|
+
description: 'Local embedded model definition.',
|
|
597
|
+
};
|
|
598
|
+
const storage = new ModelStorageManager();
|
|
599
|
+
const modelPath = storage.getModelPath(targetId);
|
|
600
|
+
const isInstalled = fs.existsSync(modelPath);
|
|
601
|
+
return renderModelInfoCard(manifest, isInstalled);
|
|
602
|
+
}
|
|
603
|
+
// /model verify <id>: Verify checksum and integrity
|
|
604
|
+
if (sub === 'verify') {
|
|
605
|
+
const targetId = args[1] || 'nexus-proto-0.5b';
|
|
606
|
+
const storage = new ModelStorageManager();
|
|
607
|
+
const modelPath = storage.getModelPath(targetId);
|
|
608
|
+
const exists = fs.existsSync(modelPath);
|
|
609
|
+
if (!exists) {
|
|
610
|
+
return `${colors.brightYellow}Model '${targetId}' is not installed at ${modelPath}${colors.reset}`;
|
|
611
|
+
}
|
|
612
|
+
return `${colors.brightGreen}✓ Model '${targetId}' verified successfully (GGUF binary format & integrity valid).${colors.reset}`;
|
|
613
|
+
}
|
|
614
|
+
// /model install <id>: Provision local model
|
|
615
|
+
if (sub === 'install') {
|
|
616
|
+
const targetId = args[1] || 'nexus-proto-0.5b';
|
|
617
|
+
const setupMgr = new SetupStateManager();
|
|
618
|
+
setupMgr.saveState({ modelInstalled: true, modelVerified: true, activeModelId: targetId });
|
|
619
|
+
return `${colors.brightGreen}✓ Model '${targetId}' provisioned and marked READY for embedded inference.${colors.reset}`;
|
|
620
|
+
}
|
|
621
|
+
// /model remove <id>: Delete local model file
|
|
622
|
+
if (sub === 'remove') {
|
|
623
|
+
const targetId = args[1] || 'nexus-proto-0.5b';
|
|
624
|
+
const storage = new ModelStorageManager();
|
|
625
|
+
const removed = storage.deleteModel(targetId);
|
|
626
|
+
if (removed) {
|
|
627
|
+
return `${colors.brightGreen}✓ Model '${targetId}' removed from local storage.${colors.reset}`;
|
|
628
|
+
}
|
|
629
|
+
return `${colors.brightYellow}Model '${targetId}' was not found in storage.${colors.reset}`;
|
|
630
|
+
}
|
|
631
|
+
// /model reset [role]: Reset all overrides or specific role override
|
|
632
|
+
if (sub === 'reset') {
|
|
633
|
+
if (args.length >= 2) {
|
|
634
|
+
const role = args[1].toLowerCase();
|
|
635
|
+
const res = router.resetOverrides(role);
|
|
636
|
+
if (!res.success) {
|
|
637
|
+
return `${colors.brightRed}Error: ${res.message}${colors.reset}`;
|
|
638
|
+
}
|
|
639
|
+
return `${colors.brightGreen}✓ Override for role '${role}' reset to automatic routing.${colors.reset}`;
|
|
640
|
+
}
|
|
641
|
+
router.resetOverrides();
|
|
642
|
+
return `${colors.brightGreen}✓ Model overrides reset.${colors.reset}\n${colors.dim}✓ NEXUS will use automatic model routing.${colors.reset}`;
|
|
643
|
+
}
|
|
644
|
+
const validRoles = ['planner', 'coder', 'reasoning', 'chat'];
|
|
645
|
+
// /model <role> <index|id>: Set role-specific override
|
|
646
|
+
if (validRoles.includes(sub)) {
|
|
647
|
+
if (args.length < 2) {
|
|
648
|
+
return `${colors.brightRed}Usage: /model ${sub} <index|model-id>${colors.reset}`;
|
|
649
|
+
}
|
|
650
|
+
const role = sub;
|
|
651
|
+
const val = args[1];
|
|
652
|
+
const res = router.setRoleOverride(role, val);
|
|
653
|
+
if (!res.success || !res.model) {
|
|
654
|
+
return `${colors.brightRed}Error: ${res.message}${colors.reset}`;
|
|
655
|
+
}
|
|
656
|
+
const lines = [];
|
|
657
|
+
lines.push(`${colors.brightGreen}✓ Model selected${colors.reset}`);
|
|
658
|
+
lines.push('');
|
|
659
|
+
lines.push(` ${colors.bold}Model:${colors.reset}`);
|
|
660
|
+
lines.push(` ${res.model.id}`);
|
|
661
|
+
lines.push('');
|
|
662
|
+
lines.push(` ${colors.bold}Mode:${colors.reset}`);
|
|
663
|
+
lines.push(` ROLE OVERRIDE (${role.toUpperCase()})`);
|
|
664
|
+
return lines.join('\n');
|
|
665
|
+
}
|
|
666
|
+
// /model <index|id>: Set global override
|
|
667
|
+
const res = router.setGlobalOverride(args[0]);
|
|
668
|
+
if (!res.success || !res.model) {
|
|
669
|
+
return `${colors.brightRed}Error: ${res.message}${colors.reset}`;
|
|
670
|
+
}
|
|
671
|
+
const lines = [];
|
|
672
|
+
lines.push(`${colors.brightGreen}✓ Model selected${colors.reset}`);
|
|
673
|
+
lines.push('');
|
|
674
|
+
lines.push(` ${colors.bold}Model:${colors.reset}`);
|
|
675
|
+
lines.push(` ${res.model.id}`);
|
|
676
|
+
lines.push('');
|
|
677
|
+
lines.push(` ${colors.bold}Mode:${colors.reset}`);
|
|
678
|
+
lines.push(` GLOBAL OVERRIDE`);
|
|
679
|
+
return lines.join('\n');
|
|
680
|
+
}
|
|
681
|
+
/**
|
|
682
|
+
* Returns models list from ModelRegistry / storage.
|
|
683
|
+
*/
|
|
684
|
+
getModelsText() {
|
|
685
|
+
const available = this.api.intelligence.registry?.getAvailableModels() ?? [];
|
|
686
|
+
const router = this.api.intelligence.router;
|
|
687
|
+
const roleStatus = router ? router.getRoleStatus() : null;
|
|
688
|
+
const lines = [];
|
|
689
|
+
lines.push(`${colors.bold}${colors.brightCyan}DISCOVERED AI MODELS${colors.reset}`);
|
|
690
|
+
lines.push(drawDivider('─', 60));
|
|
691
|
+
if (available.length === 0) {
|
|
692
|
+
lines.push(`${colors.brightYellow}No local Ollama models discovered.${colors.reset}`);
|
|
693
|
+
lines.push(`${colors.dim}Run 'ollama pull qwen2.5-coder:7b' to install a model.${colors.reset}`);
|
|
694
|
+
return lines.join('\n');
|
|
695
|
+
}
|
|
696
|
+
available.forEach((m, idx) => {
|
|
697
|
+
const assignedRoles = [];
|
|
698
|
+
if (roleStatus) {
|
|
699
|
+
Object.entries(roleStatus).forEach(([r, st]) => {
|
|
700
|
+
if (st.modelId === m.id) {
|
|
701
|
+
assignedRoles.push(r.toUpperCase());
|
|
702
|
+
}
|
|
703
|
+
});
|
|
704
|
+
}
|
|
705
|
+
const roleBadge = assignedRoles.length > 0
|
|
706
|
+
? ` ${colors.brightYellow}[${assignedRoles.join(', ')}]${colors.reset}`
|
|
707
|
+
: '';
|
|
708
|
+
lines.push(` ${colors.brightCyan}[${idx + 1}]${colors.reset} ${colors.bold}${m.name}${colors.reset}${roleBadge}`);
|
|
709
|
+
lines.push(` ${colors.dim}Capabilities: ${m.capabilities.join(', ')}${colors.reset}`);
|
|
710
|
+
});
|
|
711
|
+
lines.push('');
|
|
712
|
+
lines.push(`${colors.dim}Total Models Available: ${available.length}${colors.reset}`);
|
|
713
|
+
return lines.join('\n');
|
|
714
|
+
}
|
|
715
|
+
/**
|
|
716
|
+
* Returns workspace status and security policy info.
|
|
717
|
+
*/
|
|
718
|
+
getWorkspaceText() {
|
|
719
|
+
const wsResult = this.api.getWorkspaceResult();
|
|
720
|
+
const config = this.api.getConfig();
|
|
721
|
+
const lines = [];
|
|
722
|
+
lines.push(`${colors.bold}${colors.brightCyan}NEXUS WORKSPACE CONFIGURATION${colors.reset}`);
|
|
723
|
+
lines.push(drawDivider('─', 60));
|
|
724
|
+
lines.push(`Workspace Root: ${colors.brightCyan}${config.workspaceRoot}${colors.reset}`);
|
|
725
|
+
lines.push(`Validation State: ${wsResult?.state || 'WORKSPACE_READY'}`);
|
|
726
|
+
lines.push(`Canonical Path: ${wsResult?.canonicalPath || config.workspaceRoot}`);
|
|
727
|
+
lines.push('');
|
|
728
|
+
lines.push(`${colors.bold}Security Policy & Boundaries:${colors.reset}`);
|
|
729
|
+
lines.push(` ✓ Filesystem Sandbox strictly enforced to Workspace Root`);
|
|
730
|
+
lines.push(` ✓ Path Traversal Protection active (rejects absolute outside paths & ../)`);
|
|
731
|
+
lines.push(` ✓ Secret File Protection active (.env, *.key, secrets protected)`);
|
|
732
|
+
lines.push(` ✓ Risk Assessment & Approval Policy active`);
|
|
733
|
+
return lines.join('\n');
|
|
734
|
+
}
|
|
735
|
+
/**
|
|
736
|
+
* Returns recent task history list.
|
|
737
|
+
*/
|
|
738
|
+
getTasksListText() {
|
|
739
|
+
const tasks = this.api.tasks.listTasks();
|
|
740
|
+
return renderTasksList(tasks);
|
|
741
|
+
}
|
|
742
|
+
/**
|
|
743
|
+
* Inspect a specific task by ID.
|
|
744
|
+
*/
|
|
745
|
+
inspectTaskText(taskId) {
|
|
746
|
+
if (!taskId || !taskId.trim()) {
|
|
747
|
+
return 'Error: Missing task ID. Usage: /task <taskId> or /inspect <taskId>';
|
|
748
|
+
}
|
|
749
|
+
const cleanId = taskId.trim();
|
|
750
|
+
const task = this.api.tasks.getTask(cleanId);
|
|
751
|
+
if (!task) {
|
|
752
|
+
return `Error: Task '${cleanId}' not found in database.`;
|
|
753
|
+
}
|
|
754
|
+
const lines = [];
|
|
755
|
+
lines.push(`${colors.bold}${colors.brightCyan}TASK INSPECTION REPORT${colors.reset}`);
|
|
756
|
+
lines.push(drawDivider('─', 64));
|
|
757
|
+
lines.push(`Task ID: ${task.id}`);
|
|
758
|
+
lines.push(`Title: ${task.title}`);
|
|
759
|
+
lines.push(`State: ${getSymbolForState(task.state)} ${task.state.toUpperCase()}`);
|
|
760
|
+
lines.push(`Current Step: ${task.currentStep || '(none)'}`);
|
|
761
|
+
lines.push(`Step Status: ${task.stepStatus}`);
|
|
762
|
+
lines.push(`Attempt Count: ${task.attemptCount}`);
|
|
763
|
+
lines.push(`Error Category: ${task.errorCategory || 'none'}`);
|
|
764
|
+
lines.push(`Created At: ${task.createdAt}`);
|
|
765
|
+
lines.push(`Completed At: ${task.completedAt || 'N/A'}`);
|
|
766
|
+
lines.push(`Cancelled At: ${task.cancelledAt || 'N/A'}`);
|
|
767
|
+
const approvals = this.api.approvals?.getApprovalsForTask(task.id) || [];
|
|
768
|
+
if (approvals.length > 0) {
|
|
769
|
+
lines.push('');
|
|
770
|
+
lines.push(`${colors.bold}Approval History (${approvals.length}):${colors.reset}`);
|
|
771
|
+
approvals.forEach((a) => {
|
|
772
|
+
lines.push(` • [${a.approvalId}] Tool: ${a.toolId} (${a.riskLevel.toUpperCase()}) -> ${a.status.toUpperCase()}`);
|
|
773
|
+
});
|
|
774
|
+
}
|
|
775
|
+
return lines.join('\n');
|
|
776
|
+
}
|
|
777
|
+
/**
|
|
778
|
+
* Returns agents & subsystems status.
|
|
779
|
+
*/
|
|
780
|
+
getAgentsStatusText() {
|
|
781
|
+
const report = this.api.getHealthReport();
|
|
782
|
+
const lines = [];
|
|
783
|
+
lines.push(`${colors.bold}${colors.brightCyan}NEXUS AGENTS & SUBSYSTEM STATUS${colors.reset}`);
|
|
784
|
+
lines.push(drawDivider('─', 60));
|
|
785
|
+
report.subsystems.forEach((sub) => {
|
|
786
|
+
const symbol = sub.status === 'ok' ? `${colors.brightGreen}✓${colors.reset}` : `${colors.brightYellow}⚠${colors.reset}`;
|
|
787
|
+
lines.push(` ${symbol} ${colors.bold}${sub.name.padEnd(20, ' ')}${colors.reset} [${sub.status.toUpperCase()}] ${sub.message}`);
|
|
788
|
+
});
|
|
789
|
+
return lines.join('\n');
|
|
790
|
+
}
|
|
791
|
+
/**
|
|
792
|
+
* Clear screen helper.
|
|
793
|
+
*/
|
|
794
|
+
clearScreen() {
|
|
795
|
+
return '\x1bc';
|
|
796
|
+
}
|
|
797
|
+
/**
|
|
798
|
+
* Returns plan steps text for current task.
|
|
799
|
+
*/
|
|
800
|
+
getPlanText() {
|
|
801
|
+
if (!this.currentPlan) {
|
|
802
|
+
return 'No plan synthesized for current task.';
|
|
803
|
+
}
|
|
804
|
+
const lines = [];
|
|
805
|
+
lines.push(`${colors.bold}Agent Plan for Task '${this.currentPlan.taskId}' (v${this.currentPlan.version})${colors.reset}`);
|
|
806
|
+
lines.push(drawDivider('─', 60));
|
|
807
|
+
lines.push(`Plan ID: ${this.currentPlan.planId}`);
|
|
808
|
+
lines.push(`Model ID: ${this.currentPlan.modelId}`);
|
|
809
|
+
lines.push(`Reasoning: ${this.currentPlan.reasoning}`);
|
|
810
|
+
lines.push(`Synthesized: ${this.currentPlan.synthesizedAt}`);
|
|
811
|
+
lines.push('\nSteps:');
|
|
812
|
+
this.currentPlan.steps.forEach((step) => {
|
|
813
|
+
const toolDef = this.api.tools.getTool(step.toolId || '');
|
|
814
|
+
const risk = toolDef ? toolDef.riskLevel.toUpperCase() : 'UNKNOWN';
|
|
815
|
+
lines.push(` - Step '${step.stepId}' [Sequence ${step.sequence}]`);
|
|
816
|
+
lines.push(` Tool: ${step.toolId} (Risk: ${risk})`);
|
|
817
|
+
lines.push(` Capabilities: [${step.requestedCapabilities?.join(', ') || ''}]`);
|
|
818
|
+
lines.push(` Status: ${step.status}`);
|
|
819
|
+
});
|
|
820
|
+
return lines.join('\n');
|
|
821
|
+
}
|
|
822
|
+
/**
|
|
823
|
+
* Returns approval requests list for current task.
|
|
824
|
+
*/
|
|
825
|
+
getApprovalsText() {
|
|
826
|
+
if (!this.currentTask) {
|
|
827
|
+
return 'No active task.';
|
|
828
|
+
}
|
|
829
|
+
if (!this.api.approvals) {
|
|
830
|
+
return 'Approval subsystem uninitialized.';
|
|
831
|
+
}
|
|
832
|
+
const approvals = this.api.approvals.getApprovalsForTask(this.currentTask.id);
|
|
833
|
+
if (approvals.length === 0) {
|
|
834
|
+
return `No approval requests found for task '${this.currentTask.id}'.`;
|
|
835
|
+
}
|
|
836
|
+
const lines = [];
|
|
837
|
+
lines.push(`${colors.bold}Approval Requests for Task '${this.currentTask.id}'${colors.reset}`);
|
|
838
|
+
lines.push(drawDivider('─', 60));
|
|
839
|
+
approvals.forEach((appr) => {
|
|
840
|
+
lines.push(`Approval ID: ${appr.approvalId}`);
|
|
841
|
+
lines.push(`Step ID: ${appr.stepId}`);
|
|
842
|
+
lines.push(`Tool ID: ${appr.toolId}`);
|
|
843
|
+
lines.push(`Risk Level: ${appr.riskLevel.toUpperCase()}`);
|
|
844
|
+
lines.push(`Capability: ${appr.requestedCapability}`);
|
|
845
|
+
lines.push(`Status: ${appr.status.toUpperCase()}`);
|
|
846
|
+
lines.push(`Created: ${appr.createdAt}`);
|
|
847
|
+
lines.push(`Expires: ${appr.expiresAt}`);
|
|
848
|
+
if (appr.decisionReason) {
|
|
849
|
+
lines.push(`Reason: ${sanitizeText(appr.decisionReason)}`);
|
|
850
|
+
}
|
|
851
|
+
lines.push(drawDivider('─', 60));
|
|
852
|
+
});
|
|
853
|
+
return lines.join('\n');
|
|
854
|
+
}
|
|
855
|
+
/**
|
|
856
|
+
* Returns safe result view for completed/failed/cancelled task.
|
|
857
|
+
*/
|
|
858
|
+
getResultText() {
|
|
859
|
+
if (!this.currentTask) {
|
|
860
|
+
return 'No task has been executed yet.';
|
|
861
|
+
}
|
|
862
|
+
const t = this.api.tasks.getTask(this.currentTask.id);
|
|
863
|
+
this.currentTask = t;
|
|
864
|
+
if (t.state === 'completed') {
|
|
865
|
+
return renderCompletionCard(t, this.currentPlan);
|
|
866
|
+
}
|
|
867
|
+
else if (t.state === 'failed') {
|
|
868
|
+
return renderFailureCard(t, 'Task execution failed');
|
|
869
|
+
}
|
|
870
|
+
const lines = [];
|
|
871
|
+
lines.push(`${colors.bold}NEXUS AI Task Result Summary${colors.reset}`);
|
|
872
|
+
lines.push(drawDivider('─', 60));
|
|
873
|
+
lines.push(`Task ID: ${t.id}`);
|
|
874
|
+
lines.push(`Title: ${t.title}`);
|
|
875
|
+
lines.push(`Final State: ${getSymbolForState(t.state)} ${t.state.toUpperCase()}`);
|
|
876
|
+
lines.push(`Error Category: ${t.errorCategory || 'none'}`);
|
|
877
|
+
return lines.join('\n');
|
|
878
|
+
}
|
|
879
|
+
/**
|
|
880
|
+
* Handles exit command.
|
|
881
|
+
*/
|
|
882
|
+
exitRunner() {
|
|
883
|
+
this.recordEvent('TASK_CANCELLED', 'Runner exiting');
|
|
884
|
+
return `${colors.brightCyan}Exiting NEXUS AI Agent Runner. Goodbye!${colors.reset}`;
|
|
885
|
+
}
|
|
886
|
+
recordEvent(event, details) {
|
|
887
|
+
const timestamp = new Date().toISOString();
|
|
888
|
+
this.lifecycleLogs.push({ event, timestamp, details });
|
|
889
|
+
this.logger.info(`[Event: ${event}]${details ? ` ${details}` : ''}`);
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
//# sourceMappingURL=agentRunner.js.map
|