@nexus-ai-nexoralabs/cli 0.1.3 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/.env.example +16 -16
  2. package/LICENSE +21 -21
  3. package/README.md +135 -106
  4. package/dist/api/index.d.ts +4 -0
  5. package/dist/api/index.d.ts.map +1 -1
  6. package/dist/api/index.js +9 -3
  7. package/dist/api/index.js.map +1 -1
  8. package/dist/chat/chatService.d.ts.map +1 -1
  9. package/dist/chat/chatService.js +22 -3
  10. package/dist/chat/chatService.js.map +1 -1
  11. package/dist/chat/conversationService.d.ts +7 -1
  12. package/dist/chat/conversationService.d.ts.map +1 -1
  13. package/dist/chat/conversationService.js +48 -15
  14. package/dist/chat/conversationService.js.map +1 -1
  15. package/dist/cli/agentRunner.d.ts.map +1 -1
  16. package/dist/cli/agentRunner.js +88 -8
  17. package/dist/cli/agentRunner.js.map +1 -1
  18. package/dist/cli/chatRunner.d.ts +65 -0
  19. package/dist/cli/chatRunner.d.ts.map +1 -0
  20. package/dist/cli/chatRunner.js +289 -0
  21. package/dist/cli/chatRunner.js.map +1 -0
  22. package/dist/cli/index.d.ts +2 -0
  23. package/dist/cli/index.d.ts.map +1 -1
  24. package/dist/cli/index.js +2 -0
  25. package/dist/cli/index.js.map +1 -1
  26. package/dist/cli/inputEngine.d.ts +10 -0
  27. package/dist/cli/inputEngine.d.ts.map +1 -1
  28. package/dist/cli/inputEngine.js +28 -1
  29. package/dist/cli/inputEngine.js.map +1 -1
  30. package/dist/cli/main.d.ts +4 -0
  31. package/dist/cli/main.d.ts.map +1 -1
  32. package/dist/cli/main.js +89 -25
  33. package/dist/cli/main.js.map +1 -1
  34. package/dist/cli/uiFormatters.d.ts +11 -1
  35. package/dist/cli/uiFormatters.d.ts.map +1 -1
  36. package/dist/cli/uiFormatters.js +253 -15
  37. package/dist/cli/uiFormatters.js.map +1 -1
  38. package/dist/intelligence/modelGateway.d.ts +1 -0
  39. package/dist/intelligence/modelGateway.d.ts.map +1 -1
  40. package/dist/intelligence/modelGateway.js +63 -6
  41. package/dist/intelligence/modelGateway.js.map +1 -1
  42. package/dist/intelligence/modelRegistry.d.ts +2 -2
  43. package/dist/intelligence/modelRegistry.d.ts.map +1 -1
  44. package/dist/intelligence/modelRegistry.js +72 -31
  45. package/dist/intelligence/modelRegistry.js.map +1 -1
  46. package/dist/intelligence/modelRouter.d.ts.map +1 -1
  47. package/dist/intelligence/modelRouter.js +62 -16
  48. package/dist/intelligence/modelRouter.js.map +1 -1
  49. package/dist/intelligence/providers/embeddedInferenceProvider.d.ts.map +1 -1
  50. package/dist/intelligence/providers/embeddedInferenceProvider.js +2224 -6
  51. package/dist/intelligence/providers/embeddedInferenceProvider.js.map +1 -1
  52. package/dist/intelligence/runtime/runtimeManager.d.ts +5 -0
  53. package/dist/intelligence/runtime/runtimeManager.d.ts.map +1 -1
  54. package/dist/intelligence/runtime/runtimeManager.js +64 -4
  55. package/dist/intelligence/runtime/runtimeManager.js.map +1 -1
  56. package/dist/orchestration/agentExecutionService.d.ts.map +1 -1
  57. package/dist/orchestration/agentExecutionService.js +22 -0
  58. package/dist/orchestration/agentExecutionService.js.map +1 -1
  59. package/dist/orchestration/agentTaskService.d.ts +24 -10
  60. package/dist/orchestration/agentTaskService.d.ts.map +1 -1
  61. package/dist/orchestration/agentTaskService.js +76 -13
  62. package/dist/orchestration/agentTaskService.js.map +1 -1
  63. package/dist/orchestration/codingAgentService.d.ts.map +1 -1
  64. package/dist/orchestration/codingAgentService.js +2 -0
  65. package/dist/orchestration/codingAgentService.js.map +1 -1
  66. package/dist/orchestration/goalCompletionVerifier.d.ts +9 -0
  67. package/dist/orchestration/goalCompletionVerifier.d.ts.map +1 -1
  68. package/dist/orchestration/goalCompletionVerifier.js +131 -9
  69. package/dist/orchestration/goalCompletionVerifier.js.map +1 -1
  70. package/dist/orchestration/index.d.ts +16 -2
  71. package/dist/orchestration/index.d.ts.map +1 -1
  72. package/dist/orchestration/index.js +20 -4
  73. package/dist/orchestration/index.js.map +1 -1
  74. package/dist/orchestration/placeholderDetector.d.ts +74 -0
  75. package/dist/orchestration/placeholderDetector.d.ts.map +1 -0
  76. package/dist/orchestration/placeholderDetector.js +741 -0
  77. package/dist/orchestration/placeholderDetector.js.map +1 -0
  78. package/dist/orchestration/planner.d.ts.map +1 -1
  79. package/dist/orchestration/planner.js +94 -55
  80. package/dist/orchestration/planner.js.map +1 -1
  81. package/dist/orchestration/projectOrchestrator.d.ts +63 -0
  82. package/dist/orchestration/projectOrchestrator.d.ts.map +1 -0
  83. package/dist/orchestration/projectOrchestrator.js +555 -0
  84. package/dist/orchestration/projectOrchestrator.js.map +1 -0
  85. package/dist/orchestration/taskDecompositionService.d.ts +36 -0
  86. package/dist/orchestration/taskDecompositionService.d.ts.map +1 -0
  87. package/dist/orchestration/taskDecompositionService.js +367 -0
  88. package/dist/orchestration/taskDecompositionService.js.map +1 -0
  89. package/dist/orchestration/taskDecompositionTypes.d.ts +62 -0
  90. package/dist/orchestration/taskDecompositionTypes.d.ts.map +1 -0
  91. package/dist/orchestration/taskDecompositionTypes.js +5 -0
  92. package/dist/orchestration/taskDecompositionTypes.js.map +1 -0
  93. package/dist/preview/previewServer.d.ts.map +1 -1
  94. package/dist/preview/previewServer.js +28 -7
  95. package/dist/preview/previewServer.js.map +1 -1
  96. package/dist/preview/previewService.d.ts +32 -3
  97. package/dist/preview/previewService.d.ts.map +1 -1
  98. package/dist/preview/previewService.js +370 -108
  99. package/dist/preview/previewService.js.map +1 -1
  100. package/dist/preview/previewTypes.d.ts +1 -1
  101. package/dist/preview/previewTypes.d.ts.map +1 -1
  102. package/dist/storage/index.d.ts +2 -0
  103. package/dist/storage/index.d.ts.map +1 -1
  104. package/dist/storage/index.js +3 -0
  105. package/dist/storage/index.js.map +1 -1
  106. package/dist/storage/migration.d.ts.map +1 -1
  107. package/dist/storage/migration.js +79 -0
  108. package/dist/storage/migration.js.map +1 -1
  109. package/dist/storage/repositories/agentTaskRepository.d.ts +13 -0
  110. package/dist/storage/repositories/agentTaskRepository.d.ts.map +1 -1
  111. package/dist/storage/repositories/agentTaskRepository.js +87 -25
  112. package/dist/storage/repositories/agentTaskRepository.js.map +1 -1
  113. package/dist/storage/repositories/conversationRepository.d.ts +5 -1
  114. package/dist/storage/repositories/conversationRepository.d.ts.map +1 -1
  115. package/dist/storage/repositories/conversationRepository.js +69 -0
  116. package/dist/storage/repositories/conversationRepository.js.map +1 -1
  117. package/dist/storage/repositories/messageRepository.d.ts +3 -0
  118. package/dist/storage/repositories/messageRepository.d.ts.map +1 -1
  119. package/dist/storage/repositories/messageRepository.js +29 -0
  120. package/dist/storage/repositories/messageRepository.js.map +1 -1
  121. package/dist/storage/repositories/taskArtifactRepository.d.ts +19 -0
  122. package/dist/storage/repositories/taskArtifactRepository.d.ts.map +1 -0
  123. package/dist/storage/repositories/taskArtifactRepository.js +82 -0
  124. package/dist/storage/repositories/taskArtifactRepository.js.map +1 -0
  125. package/dist/storage/repositories/types.d.ts +32 -0
  126. package/dist/storage/repositories/types.d.ts.map +1 -1
  127. package/dist/tools/adapters/filesystemAdapter.d.ts.map +1 -1
  128. package/dist/tools/adapters/filesystemAdapter.js +8 -1
  129. package/dist/tools/adapters/filesystemAdapter.js.map +1 -1
  130. package/dist/ui/public/app.js +777 -777
  131. package/dist/ui/public/index.html +117 -117
  132. package/dist/ui/public/styles.css +413 -413
  133. package/package.json +64 -63
package/dist/cli/main.js CHANGED
@@ -4,11 +4,16 @@
4
4
  * Bootstraps ApplicationApi, displays NEXUS Workstation Dashboard,
5
5
  * and manages an interactive shell via InputEngine (paste-debounced,
6
6
  * compose-mode-capable) with concurrency guards and safe SIGINT handling.
7
+ *
8
+ * Provides clean dual-runtime operation:
9
+ * - Agent Mode: Full task execution pipeline (Think -> Plan -> Approve -> Execute -> Verify)
10
+ * - Chat Mode: Pure conversational AI (direct ModelGateway / ChatService inference)
7
11
  */
8
12
  import { loadConfig } from '../config/index.js';
9
13
  import { ApplicationApi } from '../api/index.js';
10
14
  import { AgentRunner } from './agentRunner.js';
11
- import { InputEngine, SIGNAL_ENTER_COMPOSE, SIGNAL_SEND_COMPOSE } from './inputEngine.js';
15
+ import { ChatRunner } from './chatRunner.js';
16
+ import { InputEngine, SIGNAL_ENTER_COMPOSE, SIGNAL_SEND_COMPOSE, SIGNAL_ENTER_CHAT, SIGNAL_EXIT_CHAT, } from './inputEngine.js';
12
17
  import { renderDashboard, renderOllamaMissingBanner, colors } from './uiFormatters.js';
13
18
  export function handleCliFlags(args = process.argv.slice(2)) {
14
19
  if (args.includes('--version') || args.includes('-v')) {
@@ -16,22 +21,24 @@ export function handleCliFlags(args = process.argv.slice(2)) {
16
21
  return true;
17
22
  }
18
23
  if (args.includes('--help') || args.includes('-h')) {
19
- console.log(`NEXUS AI — Local-First AI Workstation CLI
20
-
21
- Usage:
22
- nexus [options]
23
-
24
- Options:
25
- -v, --version Display NEXUS AI version
26
- -h, --help Display CLI help and usage
27
-
28
- Interactive Shell Commands:
29
- /help Show available in-app commands
30
- /model [id] Display or switch active AI model
31
- /models List all discovered models
32
- /tasks List recent task history
33
- /preview Launch project preview server
34
- /clear Clear terminal screen
24
+ console.log(`NEXUS AI — Local-First AI Workstation CLI
25
+
26
+ Usage:
27
+ nexus [options]
28
+
29
+ Options:
30
+ -v, --version Display NEXUS AI version
31
+ -h, --help Display CLI help and usage
32
+
33
+ Interactive Shell Commands:
34
+ /chat Start normal AI conversation (Chat Mode)
35
+ /chats View conversation history
36
+ /help Show available in-app commands
37
+ /model [id] Display or switch active AI model
38
+ /models List all discovered models
39
+ /tasks List recent task history
40
+ /preview Launch project preview server
41
+ /clear Clear terminal screen
35
42
  /exit Exit NEXUS AI Workstation`);
36
43
  return true;
37
44
  }
@@ -46,6 +53,7 @@ async function runCli() {
46
53
  // 1. Bootstrap all subsystems
47
54
  const healthReport = await api.bootstrap();
48
55
  const runner = new AgentRunner(api, config.logLevel);
56
+ const chatRunner = new ChatRunner(api, config.logLevel);
49
57
  // 2. Render initial Workstation Dashboard
50
58
  const renderStartDashboard = () => renderDashboard(healthReport, config.workspaceRoot);
51
59
  console.log(renderStartDashboard());
@@ -62,13 +70,21 @@ async function runCli() {
62
70
  }
63
71
  }
64
72
  let isBusy = false;
65
- // 3. Build InputEngine — paste-debounced, compose-mode-capable
66
- const engine = new InputEngine({
67
- isAwaitingApproval: () => !!(runner.currentTask && runner.currentTask.state === 'awaiting_approval'),
73
+ // 4. Build InputEngine — paste-debounced, compose-mode-capable, dual-mode (Agent / Chat)
74
+ let engine;
75
+ engine = new InputEngine({
76
+ isAwaitingApproval: () => engine?.getCliMode() === 'agent' &&
77
+ !!(runner.currentTask && runner.currentTask.state === 'awaiting_approval'),
68
78
  onInput: async (text) => {
69
- // Exit commands handled before isBusy to allow clean exit at any time
70
79
  const lower = text.toLowerCase();
80
+ // Global Exit commands handled before isBusy to allow clean exit at any time
71
81
  if (lower === '/exit' || lower === '/quit' || lower === '/q') {
82
+ if (engine.getCliMode() === 'chat') {
83
+ engine.setCliMode('agent');
84
+ process.stdout.write(`\n${colors.brightCyan}Returned to NEXUS Agent mode.${colors.reset}\n\n`);
85
+ engine.refreshPrompt();
86
+ return;
87
+ }
72
88
  console.log(`\n${runner.exitRunner()}\n`);
73
89
  api.close();
74
90
  engine.close();
@@ -76,27 +92,62 @@ async function runCli() {
76
92
  }
77
93
  if (lower === '/clear' || lower === '/cls') {
78
94
  process.stdout.write('\x1bc');
79
- console.log(renderStartDashboard());
95
+ if (engine.getCliMode() === 'agent') {
96
+ console.log(renderStartDashboard());
97
+ }
80
98
  engine.refreshPrompt();
81
99
  return;
82
100
  }
83
101
  if (isBusy) {
84
- process.stdout.write(`\n${colors.brightYellow}Task in progress. Please wait or press Ctrl+C to cancel.${colors.reset}\n\n`);
102
+ process.stdout.write(`\n${colors.brightYellow}Operation in progress. Please wait or press Ctrl+C to cancel.${colors.reset}\n\n`);
85
103
  engine.refreshPrompt();
86
104
  return;
87
105
  }
88
106
  isBusy = true;
89
107
  try {
108
+ // ---------------------------------------------------------------------
109
+ // CHAT MODE DISPATCH
110
+ // ---------------------------------------------------------------------
111
+ if (engine.getCliMode() === 'chat') {
112
+ if (lower === '/exit-chat' || lower === '/exitchat') {
113
+ engine.setCliMode('agent');
114
+ process.stdout.write(`\n${colors.brightCyan}Returned to NEXUS Agent mode.${colors.reset}\n\n`);
115
+ return;
116
+ }
117
+ const response = await chatRunner.runCommand(text, { streamToStdout: true });
118
+ if (response === SIGNAL_EXIT_CHAT) {
119
+ engine.setCliMode('agent');
120
+ process.stdout.write(`\n${colors.brightCyan}Returned to NEXUS Agent mode.${colors.reset}\n\n`);
121
+ return;
122
+ }
123
+ if (response) {
124
+ process.stdout.write(`\n${response}\n\n`);
125
+ }
126
+ return;
127
+ }
128
+ // ---------------------------------------------------------------------
129
+ // AGENT MODE DISPATCH
130
+ // ---------------------------------------------------------------------
90
131
  const response = await runner.runCommand(text);
91
132
  // Handle compose mode signals returned by AgentRunner
92
133
  if (response === SIGNAL_ENTER_COMPOSE) {
93
134
  engine.enterComposeMode();
94
- return; // prompt refresh handled inside enterComposeMode
135
+ return;
95
136
  }
96
137
  if (response === SIGNAL_SEND_COMPOSE) {
97
138
  await engine.submitComposeBuffer();
98
139
  return;
99
140
  }
141
+ // Handle Chat Mode transitions
142
+ if (response === SIGNAL_ENTER_CHAT || response.startsWith(`${SIGNAL_ENTER_CHAT}:`)) {
143
+ const targetConvId = response.startsWith(`${SIGNAL_ENTER_CHAT}:`)
144
+ ? response.slice(SIGNAL_ENTER_CHAT.length + 1).trim()
145
+ : undefined;
146
+ engine.setCliMode('chat');
147
+ const banner = await chatRunner.startOrResumeChat(targetConvId);
148
+ process.stdout.write(`\n${banner}\n\n`);
149
+ return;
150
+ }
100
151
  if (response) {
101
152
  process.stdout.write(`\n${response}\n\n`);
102
153
  }
@@ -110,8 +161,21 @@ async function runCli() {
110
161
  }
111
162
  },
112
163
  });
113
- // 4. Safe Ctrl+C handling: cancels active task if running, or exits cleanly if idle
164
+ // 5. Safe Ctrl+C handling: cancels active generation or task if running, or exits cleanly if idle
114
165
  engine.readline.on('SIGINT', async () => {
166
+ if (engine.getCliMode() === 'chat') {
167
+ if (chatRunner.cancelActiveGeneration()) {
168
+ process.stdout.write(`\n\n${colors.brightYellow}[SIGINT] Chat generation cancelled.${colors.reset}\n\n`);
169
+ isBusy = false;
170
+ engine.refreshPrompt();
171
+ return;
172
+ }
173
+ process.stdout.write(`\n\n${colors.dim}[SIGINT] Safely closing NEXUS AI Workstation...${colors.reset}\n`);
174
+ api.close();
175
+ engine.close();
176
+ process.exit(0);
177
+ return;
178
+ }
115
179
  if (runner.currentTask &&
116
180
  ['created', 'planning', 'executing', 'awaiting_approval'].includes(runner.currentTask.state)) {
117
181
  process.stdout.write(`\n\n${colors.brightYellow}[SIGINT] Cancelling active task '${runner.currentTask.id}'...${colors.reset}\n`);
@@ -1 +1 @@
1
- {"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"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"}
@@ -14,6 +14,7 @@ import type { SystemHealthReport } from '../api/index.js';
14
14
  import type { AgentTask } from '../storage/repositories/types.js';
15
15
  import type { AgentPlan } from '../orchestration/types.js';
16
16
  import type { ApprovalRequest } from '../tools/approvalTypes.js';
17
+ import type { DecompositionPlan, ProjectOrchestrationResult } from '../orchestration/taskDecompositionTypes.js';
17
18
  export declare const colors: {
18
19
  reset: string;
19
20
  bold: string;
@@ -57,21 +58,30 @@ export declare function sanitizeText(text: string): string;
57
58
  export declare function drawDivider(char?: string, width?: number): string;
58
59
  export declare function drawHeaderBanner(): string;
59
60
  export declare function renderDashboard(report: SystemHealthReport, workspaceRoot: string): string;
61
+ export declare function formatRelativeTime(isoString: string): string;
62
+ export declare function renderChatBanner(): string;
63
+ export declare function renderChatHistory(conversations: Array<import('../storage/repositories/types.js').ConversationSummary>): string;
64
+ export declare function renderChatSearchResults(query: string, results: Array<import('../storage/repositories/types.js').ConversationSummary>): string;
60
65
  export declare function renderHelpMenu(): string;
61
66
  export declare function renderTasksList(tasks: AgentTask[]): string;
62
67
  export declare function renderApprovalCard(approval: ApprovalRequest, taskTitle?: string): string;
63
68
  export declare function renderCompletionCard(task: AgentTask, plan?: AgentPlan | null, durationMs?: number): string;
64
69
  export declare function renderFailureCard(task: AgentTask, errorMessage?: string): string;
70
+ export declare function renderTaskDecompositionPlanCard(plan: DecompositionPlan, taskTitle: string): string;
71
+ export declare function renderDecompositionCompletionCard(task: AgentTask, result: ProjectOrchestrationResult, durationMs?: number): string;
72
+ export declare function renderDecompositionFailureCard(task: AgentTask, result: ProjectOrchestrationResult): string;
65
73
  export declare function renderPromptPreview(text: string): string;
66
74
  export declare function renderComposeHeader(): string;
67
75
  export declare function renderModelControlScreen(models: Array<{
68
76
  id: string;
69
77
  name: string;
78
+ provider?: string;
70
79
  capabilities: string[];
80
+ isAvailable?: boolean;
71
81
  }>, roleStatus: Record<string, {
72
82
  modelId: string;
73
83
  source: 'USER' | 'AUTO';
74
- }>, providerName?: string): string;
84
+ }>, providerName?: string, activeModelId?: string): string;
75
85
  export declare function renderModelStatusScreen(roleStatus: Record<string, {
76
86
  modelId: string;
77
87
  source: 'USER' | 'AUTO';
@@ -1 +1 @@
1
- {"version":3,"file":"uiFormatters.d.ts","sourceRoot":"","sources":["../../src/cli/uiFormatters.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"uiFormatters.d.ts","sourceRoot":"","sources":["../../src/cli/uiFormatters.ts"],"names":[],"mappings":"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"}
@@ -417,6 +417,89 @@ export function renderDashboard(report, workspaceRoot) {
417
417
  lines.push('');
418
418
  return lines.join('\n');
419
419
  }
420
+ export function formatRelativeTime(isoString) {
421
+ try {
422
+ const time = new Date(isoString).getTime();
423
+ if (isNaN(time))
424
+ return 'recently';
425
+ const now = Date.now();
426
+ const diffMs = Math.max(0, now - time);
427
+ const diffSec = Math.floor(diffMs / 1000);
428
+ const diffMin = Math.floor(diffSec / 60);
429
+ const diffHour = Math.floor(diffMin / 60);
430
+ const diffDay = Math.floor(diffHour / 24);
431
+ if (diffSec < 45)
432
+ return 'just now';
433
+ if (diffMin === 1)
434
+ return '1 minute ago';
435
+ if (diffMin < 60)
436
+ return `${diffMin} minutes ago`;
437
+ if (diffHour === 1)
438
+ return '1 hour ago';
439
+ if (diffHour < 24)
440
+ return `${diffHour} hours ago`;
441
+ if (diffDay === 1)
442
+ return 'yesterday';
443
+ if (diffDay < 7)
444
+ return `${diffDay} days ago`;
445
+ return new Date(isoString).toLocaleDateString('en-US', { month: 'short', day: 'numeric' });
446
+ }
447
+ catch {
448
+ return 'recently';
449
+ }
450
+ }
451
+ export function renderChatBanner() {
452
+ const lines = [];
453
+ lines.push(`${colors.bold}${colors.brightCyan}NEXUS CHAT${colors.reset}`);
454
+ lines.push(drawDivider('─', 40));
455
+ lines.push('');
456
+ lines.push('You are now chatting with NEXUS.');
457
+ lines.push(`Type ${colors.brightCyan}/exit-chat${colors.reset} to return to the main NEXUS prompt.`);
458
+ lines.push(`Type ${colors.brightCyan}/new-chat${colors.reset} to start a new conversation.`);
459
+ lines.push(`Type ${colors.brightCyan}/chats${colors.reset} to view conversation history.`);
460
+ return lines.join('\n');
461
+ }
462
+ export function renderChatHistory(conversations) {
463
+ const lines = [];
464
+ lines.push(`${colors.bold}${colors.brightCyan}NEXUS CHAT HISTORY${colors.reset}`);
465
+ lines.push(drawDivider('─', 40));
466
+ lines.push('');
467
+ if (conversations.length === 0) {
468
+ lines.push(`${colors.dim}No conversation history found. Type /chat to start chatting.${colors.reset}`);
469
+ lines.push('');
470
+ return lines.join('\n');
471
+ }
472
+ conversations.forEach((c, idx) => {
473
+ const relTime = formatRelativeTime(c.updatedAt);
474
+ lines.push(`${colors.bold}${colors.white}${idx + 1}. ${c.title}${colors.reset}`);
475
+ lines.push(` ${colors.dim}Updated:${colors.reset} ${relTime}`);
476
+ lines.push(` ${colors.dim}Messages:${colors.reset} ${c.messageCount}`);
477
+ lines.push(` ${colors.dim}ID:${colors.reset} ${colors.brightCyan}${c.id}${colors.reset}`);
478
+ lines.push('');
479
+ });
480
+ lines.push(`${colors.bold}Commands:${colors.reset}`);
481
+ lines.push(` ${colors.brightCyan}/chats open <id>${colors.reset} Open conversation`);
482
+ lines.push(` ${colors.brightCyan}/chats delete <id>${colors.reset} Delete conversation`);
483
+ lines.push(` ${colors.brightCyan}/chats search <q>${colors.reset} Search conversations`);
484
+ return lines.join('\n');
485
+ }
486
+ export function renderChatSearchResults(query, results) {
487
+ const lines = [];
488
+ lines.push(`${colors.bold}${colors.brightCyan}NEXUS CHAT SEARCH RESULTS: "${query}"${colors.reset}`);
489
+ lines.push(drawDivider('─', 48));
490
+ lines.push('');
491
+ if (results.length === 0) {
492
+ lines.push(`${colors.dim}No conversations found matching "${query}".${colors.reset}`);
493
+ lines.push('');
494
+ return lines.join('\n');
495
+ }
496
+ results.forEach((c, idx) => {
497
+ lines.push(`${colors.bold}${idx + 1}. ${c.title}${colors.reset} ${colors.dim}(${c.messageCount} msg${c.messageCount === 1 ? '' : 's'}) [ID: ${colors.brightCyan}${c.id}${colors.dim}]${colors.reset}`);
498
+ });
499
+ lines.push('');
500
+ lines.push(`${colors.dim}Use /chats open <id> to resume a conversation.${colors.reset}`);
501
+ return lines.join('\n');
502
+ }
420
503
  // ---------------------------------------------------------------------------
421
504
  // Help Command Renderer
422
505
  // ---------------------------------------------------------------------------
@@ -424,7 +507,20 @@ export function renderHelpMenu() {
424
507
  const lines = [
425
508
  `${colors.bold}${colors.brightCyan}NEXUS AI Agent Runner \u2014 Help & Command Reference${colors.reset}`,
426
509
  drawDivider('─', 64),
427
- `${colors.dim}TASK COMMANDS${colors.reset}`,
510
+ `${colors.dim}CHAT${colors.reset}`,
511
+ ` ${colors.brightCyan}/chat${colors.reset} Start normal AI conversation`,
512
+ ` ${colors.brightCyan}/chats${colors.reset} View conversation history`,
513
+ ` ${colors.brightCyan}/chats open <id>${colors.reset} Open previous conversation`,
514
+ ` ${colors.brightCyan}/chats search <q>${colors.reset} Search conversations`,
515
+ ` ${colors.brightCyan}/chats delete <id>${colors.reset} Delete conversation`,
516
+ '',
517
+ `${colors.dim}CHAT MODE${colors.reset}`,
518
+ ` ${colors.brightCyan}/exit-chat${colors.reset} Return to Agent Mode`,
519
+ ` ${colors.brightCyan}/new-chat${colors.reset} Start new conversation`,
520
+ ` ${colors.brightCyan}/chats${colors.reset} View conversations`,
521
+ ` ${colors.brightCyan}/model${colors.reset} Display or switch active model`,
522
+ '',
523
+ `${colors.dim}AGENT MODE${colors.reset}`,
428
524
  ` ${colors.brightCyan}<task description>${colors.reset} Submit a natural language goal`,
429
525
  ` ${colors.brightCyan}/task <goal>${colors.reset} Explicitly submit a task (alias: /t)`,
430
526
  ` ${colors.brightCyan}/code <goal>${colors.reset} Run automated coding task (P6-D)`,
@@ -440,7 +536,7 @@ export function renderHelpMenu() {
440
536
  ` ${colors.brightCyan}/preview stop${colors.reset} Stop active preview server`,
441
537
  ` ${colors.brightCyan}/preview status${colors.reset} Show active preview status`,
442
538
  ` ${colors.brightCyan}/tasks${colors.reset} List recent task history`,
443
- ` ${colors.brightCyan}/models${colors.reset} List installed Ollama models`,
539
+ ` ${colors.brightCyan}/models${colors.reset} List installed models`,
444
540
  ` ${colors.brightCyan}/model <role> <n>${colors.reset} Set role model override`,
445
541
  ` ${colors.brightCyan}/model reset${colors.reset} Reset all model overrides`,
446
542
  ` ${colors.brightCyan}/workspace${colors.reset} Workspace root & security info`,
@@ -451,8 +547,8 @@ export function renderHelpMenu() {
451
547
  ` ${colors.brightCyan}/clear${colors.reset} Clear terminal screen`,
452
548
  ` ${colors.brightCyan}/exit${colors.reset} Exit NEXUS CLI`,
453
549
  drawDivider('─', 64),
454
- `${colors.dim}TIP: Paste multi-line prompts directly \u2014 NEXUS batches them safely.${colors.reset}`,
455
- `${colors.dim} Use /prompt for deliberate multi-line task authoring.${colors.reset}`,
550
+ `${colors.dim}TIP: Type /chat to talk directly with the AI without creating tasks.${colors.reset}`,
551
+ `${colors.dim} Type task instructions at NEXUS> to have the Agent build & execute.${colors.reset}`,
456
552
  ];
457
553
  return lines.join('\n');
458
554
  }
@@ -467,10 +563,11 @@ export function renderTasksList(tasks) {
467
563
  `${colors.bold}${colors.brightCyan}RECENT TASKS${colors.reset}`,
468
564
  drawDivider('─', 74),
469
565
  ];
470
- tasks.slice(0, 15).forEach((t) => {
566
+ tasks.slice(0, 15).forEach((t, idx) => {
567
+ const num = `${idx + 1}.`.padEnd(4, ' ');
471
568
  const symbol = getSymbolForState(t.state);
472
569
  const idPad = t.id.padEnd(26, ' ');
473
- const titleTrunc = t.title.length > 30 ? `${t.title.slice(0, 27)}...` : t.title.padEnd(30, ' ');
570
+ const titleTrunc = t.title.length > 26 ? `${t.title.slice(0, 23)}...` : t.title.padEnd(26, ' ');
474
571
  const stateColor = t.state === 'completed'
475
572
  ? colors.brightGreen
476
573
  : t.state === 'failed'
@@ -478,10 +575,10 @@ export function renderTasksList(tasks) {
478
575
  : t.state === 'awaiting_approval'
479
576
  ? colors.brightYellow
480
577
  : colors.dim;
481
- lines.push(`${symbol} ${colors.brightCyan}${idPad}${colors.reset} ${titleTrunc} ${stateColor}${t.state.toUpperCase()}${colors.reset}`);
578
+ lines.push(`${colors.bold}${num}${colors.reset}${symbol} ${colors.brightCyan}${idPad}${colors.reset} ${titleTrunc} ${stateColor}${t.state.toUpperCase()}${colors.reset}`);
482
579
  });
483
580
  lines.push(drawDivider('─', 74));
484
- lines.push(`${colors.dim}Use /task <id> to inspect detailed plan and steps for a specific task.${colors.reset}`);
581
+ lines.push(`${colors.dim}Commands: /preview (latest) | /preview <number> (e.g. /preview 2) | /task <id>${colors.reset}`);
485
582
  return lines.join('\n');
486
583
  }
487
584
  // ---------------------------------------------------------------------------
@@ -569,6 +666,90 @@ export function renderFailureCard(task, errorMessage) {
569
666
  return lines.join('\n');
570
667
  }
571
668
  // ---------------------------------------------------------------------------
669
+ // Task Decomposition & Project Orchestration Renderers
670
+ // ---------------------------------------------------------------------------
671
+ export function renderTaskDecompositionPlanCard(plan, taskTitle) {
672
+ const lines = [];
673
+ lines.push('');
674
+ lines.push(drawDivider('─', 64));
675
+ lines.push(` ${colors.bold}${colors.brightCyan}NEXUS TASK PLAN${colors.reset}`);
676
+ lines.push(drawDivider('─', 64));
677
+ lines.push('');
678
+ lines.push(` ${colors.bold}Goal:${colors.reset} ${taskTitle}`);
679
+ lines.push(` ${colors.dim}${plan.units.length} implementation units detected (${plan.estimatedComplexity.toUpperCase()} complexity):${colors.reset}`);
680
+ lines.push('');
681
+ plan.units.forEach((unit, idx) => {
682
+ const num = `${idx + 1}.`.padEnd(4, ' ');
683
+ const title = unit.title;
684
+ const cat = `[${unit.category}]`.padEnd(14, ' ');
685
+ const deps = unit.dependencies.length > 0 ? `${colors.dim}(deps: ${unit.dependencies.join(', ')})${colors.reset}` : '';
686
+ lines.push(` ${colors.bold}${num}${colors.reset} ${colors.brightCyan}${cat}${colors.reset} ${title} ${deps}`);
687
+ });
688
+ lines.push('');
689
+ lines.push(` ${colors.dim}Executing queue sequentially with per-unit verification...${colors.reset}`);
690
+ lines.push(drawDivider('─', 64));
691
+ return lines.join('\n');
692
+ }
693
+ export function renderDecompositionCompletionCard(task, result, durationMs) {
694
+ const durationSec = durationMs ? (durationMs / 1000).toFixed(1) : 'N/A';
695
+ const lines = [];
696
+ lines.push(drawDivider('─', 64));
697
+ lines.push(` ${colors.bold}${colors.brightGreen}FINAL RESULT \u2014 PROJECT COMPLETED${colors.reset}`);
698
+ lines.push(drawDivider('─', 64));
699
+ lines.push('');
700
+ lines.push(` ${colors.bold}Goal:${colors.reset} ${task.title}`);
701
+ lines.push(` ${colors.bold}Status:${colors.reset} ${colors.brightGreen}\u2713 COMPLETED${colors.reset}`);
702
+ lines.push(` ${colors.bold}Task ID:${colors.reset} ${task.id}`);
703
+ lines.push(` ${colors.bold}Duration:${colors.reset} ${durationSec}s`);
704
+ lines.push(` ${colors.bold}Units:${colors.reset} ${result.completedUnits}/${result.totalUnits} completed cleanly`);
705
+ lines.push('');
706
+ lines.push(`${colors.bold}Execution Summary:${colors.reset}`);
707
+ result.childResults.forEach((child, idx) => {
708
+ const sym = child.success ? `${colors.brightGreen}\u2713${colors.reset}` : `${colors.brightRed}\u2716${colors.reset}`;
709
+ lines.push(` ${sym} Unit ${idx + 1}: ${child.title}`);
710
+ });
711
+ lines.push('');
712
+ lines.push(`${colors.bold}Verification:${colors.reset}`);
713
+ lines.push(` ${colors.brightGreen}\u2713 All child implementation units verified${colors.reset}`);
714
+ lines.push(` ${colors.brightGreen}\u2713 Final end-to-end integration verified${colors.reset}`);
715
+ lines.push(` ${colors.brightGreen}\u2713 Artifacts registered and ready for /preview${colors.reset}`);
716
+ lines.push(drawDivider('─', 64));
717
+ return lines.join('\n');
718
+ }
719
+ export function renderDecompositionFailureCard(task, result) {
720
+ const lines = [];
721
+ lines.push(drawDivider('─', 64));
722
+ lines.push(` ${colors.bold}${colors.brightRed}PROJECT EXECUTION FAILED${colors.reset}`);
723
+ lines.push(drawDivider('─', 64));
724
+ lines.push('');
725
+ lines.push(` ${colors.bold}Goal:${colors.reset} ${task.title}`);
726
+ lines.push(` ${colors.bold}Status:${colors.reset} ${colors.brightRed}\u2716 FAILED${colors.reset}`);
727
+ lines.push(` ${colors.bold}Task ID:${colors.reset} ${task.id}`);
728
+ lines.push(` ${colors.bold}Progress:${colors.reset} ${result.completedUnits}/${result.totalUnits} units succeeded`);
729
+ if (result.error) {
730
+ lines.push(` ${colors.bold}Error:${colors.reset} ${colors.brightRed}${result.error}${colors.reset}`);
731
+ }
732
+ lines.push('');
733
+ lines.push(`${colors.bold}Unit Breakdown:${colors.reset}`);
734
+ result.childResults.forEach((child, idx) => {
735
+ const sym = child.success
736
+ ? `${colors.brightGreen}\u2713${colors.reset}`
737
+ : child.status === 'blocked'
738
+ ? `${colors.gray}\u25cb${colors.reset}`
739
+ : `${colors.brightRed}\u2716${colors.reset}`;
740
+ const statusText = child.success
741
+ ? `${colors.brightGreen}COMPLETED${colors.reset}`
742
+ : child.status === 'blocked'
743
+ ? `${colors.gray}BLOCKED${colors.reset}`
744
+ : `${colors.brightRed}FAILED${colors.reset}`;
745
+ lines.push(` ${sym} Unit ${idx + 1}: ${child.title.padEnd(30, ' ')} [${statusText}]`);
746
+ });
747
+ lines.push('');
748
+ lines.push(` ${colors.dim}Preview is unavailable due to verification or execution failure.${colors.reset}`);
749
+ lines.push(drawDivider('─', 64));
750
+ return lines.join('\n');
751
+ }
752
+ // ---------------------------------------------------------------------------
572
753
  // P7-F.1: Prompt Preview Card
573
754
  // ---------------------------------------------------------------------------
574
755
  const MAX_PREVIEW_LINES = 5;
@@ -618,13 +799,17 @@ export function renderComposeHeader() {
618
799
  // ---------------------------------------------------------------------------
619
800
  // P7-G: Model Control & Status Screen Renderers
620
801
  // ---------------------------------------------------------------------------
621
- export function renderModelControlScreen(models, roleStatus, providerName = 'Embedded (Local)') {
802
+ export function renderModelControlScreen(models, roleStatus, providerName = 'Embedded (Local)', activeModelId) {
622
803
  const lines = [];
623
804
  lines.push(drawDivider('─', 60));
624
805
  lines.push(` ${colors.bold}${colors.brightCyan}NEXUS MODEL CONTROL${colors.reset}`);
625
806
  lines.push(drawDivider('─', 60));
626
807
  lines.push('');
627
- lines.push(` ${colors.dim}Provider:${colors.reset} ${colors.bold}${colors.brightGreen}${providerName}${colors.reset} • ${colors.dim}Status:${colors.reset} ${colors.bold}${colors.brightGreen}READY${colors.reset}`);
808
+ const activeModelDisplay = activeModelId || roleStatus['chat']?.modelId || roleStatus['coder']?.modelId || (models[0] ? models[0].id : 'None');
809
+ const activeModelObj = models.find((m) => m.id === activeModelDisplay);
810
+ const activeProviderDisplay = activeModelObj?.provider ? (activeModelObj.provider === 'embedded' ? 'Embedded' : 'Ollama') : providerName;
811
+ lines.push(` ${colors.bold}Current Active Model:${colors.reset} ${colors.brightCyan}${colors.bold}${activeModelDisplay}${colors.reset}`);
812
+ lines.push(` ${colors.dim}Provider:${colors.reset} ${colors.brightGreen}${activeProviderDisplay}${colors.reset} • ${colors.dim}Status:${colors.reset} ${colors.brightGreen}READY${colors.reset}`);
628
813
  lines.push('');
629
814
  lines.push(`${colors.bold}AVAILABLE MODELS${colors.reset}`);
630
815
  lines.push('');
@@ -633,8 +818,10 @@ export function renderModelControlScreen(models, roleStatus, providerName = 'Emb
633
818
  }
634
819
  else {
635
820
  models.forEach((m, idx) => {
636
- lines.push(` ${colors.brightCyan}[${idx + 1}]${colors.reset} ${colors.bold}${m.name}${colors.reset}`);
637
- lines.push(` ${colors.dim}${m.capabilities.join(' \u2022 ')}${colors.reset}`);
821
+ const pTag = m.provider === 'embedded' ? `${colors.brightGreen}[Embedded]${colors.reset}` : `${colors.brightCyan}[Ollama]${colors.reset}`;
822
+ const statusTag = m.isAvailable !== false ? `${colors.brightGreen}AVAILABLE${colors.reset}` : `${colors.brightRed}UNAVAILABLE${colors.reset}`;
823
+ lines.push(` ${colors.brightCyan}[${idx + 1}]${colors.reset} ${colors.bold}${m.name}${colors.reset} ${pTag}`);
824
+ lines.push(` ${colors.dim}Capabilities:${colors.reset} ${m.capabilities.join(', ')} • ${colors.dim}Status:${colors.reset} ${statusTag}`);
638
825
  lines.push('');
639
826
  });
640
827
  }
@@ -709,14 +896,47 @@ export function renderPreviewCard(result) {
709
896
  lines.push(drawDivider('─', 56));
710
897
  lines.push('');
711
898
  if (result.status === 'NO_COMPLETED_TASK') {
712
- lines.push(` ${colors.brightRed}\u2716 No completed task is available to preview.${colors.reset}`);
899
+ lines.push(` ${colors.brightYellow}ℹ No previewable task is available.${colors.reset}`);
900
+ lines.push('');
901
+ lines.push(` ${colors.dim}${result.message || 'Run a task to build a project first, or type /tasks to view history.'}${colors.reset}`);
902
+ lines.push(drawDivider('─', 56));
903
+ return lines.join('\n');
904
+ }
905
+ if (result.status === 'TASK_FAILED') {
906
+ lines.push(` ${colors.brightRed}\u2716 Preview Unavailable${colors.reset}`);
907
+ lines.push('');
908
+ if (result.task) {
909
+ lines.push(` ${colors.bold}Task:${colors.reset}`);
910
+ lines.push(` ${result.task.title}`);
911
+ lines.push('');
912
+ lines.push(` ${colors.bold}Status:${colors.reset}`);
913
+ lines.push(` ${colors.brightRed}FAILED${colors.reset}`);
914
+ lines.push('');
915
+ lines.push(` ${colors.bold}Reason:${colors.reset}`);
916
+ lines.push(` ${result.error || result.task.errorCategory || 'Execution Failed'}`);
917
+ lines.push('');
918
+ }
919
+ lines.push(` ${colors.dim}Run /tasks to view history or /preview <number> to preview an older completed task.${colors.reset}`);
920
+ lines.push(drawDivider('─', 56));
921
+ return lines.join('\n');
922
+ }
923
+ if (result.status === 'TASK_INCOMPLETE') {
924
+ lines.push(` ${colors.brightYellow}\u26a0 Preview Unavailable${colors.reset}`);
713
925
  lines.push('');
714
- lines.push(` ${colors.dim}Complete a task that creates a supported previewable project first.${colors.reset}`);
926
+ if (result.task) {
927
+ lines.push(` ${colors.bold}Task:${colors.reset}`);
928
+ lines.push(` ${result.task.title}`);
929
+ lines.push('');
930
+ lines.push(` ${colors.bold}Status:${colors.reset}`);
931
+ lines.push(` ${colors.brightYellow}${result.task.state.toUpperCase()}${colors.reset}`);
932
+ lines.push('');
933
+ }
934
+ lines.push(` ${colors.dim}${result.message || 'Only completed tasks can be previewed. Run /tasks to view history.'}${colors.reset}`);
715
935
  lines.push(drawDivider('─', 56));
716
936
  return lines.join('\n');
717
937
  }
718
938
  if (result.status === 'NOT_WEB_PROJECT') {
719
- lines.push(` ${colors.brightYellow}\u26a0 Latest task does not contain a previewable web project.${colors.reset}`);
939
+ lines.push(` ${colors.brightYellow}\u26a0 Selected task does not contain a previewable web project.${colors.reset}`);
720
940
  lines.push('');
721
941
  if (result.task) {
722
942
  lines.push(` ${colors.bold}Task:${colors.reset}`);
@@ -757,6 +977,24 @@ export function renderPreviewCard(result) {
757
977
  lines.push(drawDivider('─', 56));
758
978
  return lines.join('\n');
759
979
  }
980
+ if (result.status === 'PLACEHOLDER_ARTIFACT_BLOCKED') {
981
+ lines.push(` ${colors.brightRed}\u2716 Preview Blocked${colors.reset}`);
982
+ lines.push('');
983
+ if (result.task) {
984
+ lines.push(` ${colors.bold}Task:${colors.reset}`);
985
+ lines.push(` ${result.task.title}`);
986
+ lines.push('');
987
+ lines.push(` ${colors.bold}Status:${colors.reset}`);
988
+ lines.push(` ${colors.brightRed}PLACEHOLDER_ARTIFACT_REJECTED${colors.reset}`);
989
+ lines.push('');
990
+ }
991
+ lines.push(` ${colors.bold}Reason:${colors.reset}`);
992
+ lines.push(` ${result.message || 'Generated artifact does not contain a valid implementation of the requested task.'}`);
993
+ lines.push('');
994
+ lines.push(` ${colors.dim}The agent must generate a real project implementation before previewing.${colors.reset}`);
995
+ lines.push(drawDivider('─', 56));
996
+ return lines.join('\n');
997
+ }
760
998
  if (result.status === 'ERROR' || !result.success || !result.serverInfo) {
761
999
  lines.push(` ${colors.brightRed}\u2716 Preview Launch Failed${colors.reset}`);
762
1000
  lines.push(` ${result.error || result.message || 'Unknown preview error'}`);