neuro-cli 4.2.0 → 5.0.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.
Files changed (175) hide show
  1. package/dist/advisor/advisor.d.ts +0 -0
  2. package/dist/advisor/advisor.js +0 -0
  3. package/dist/agents/base.d.ts +21 -2
  4. package/dist/agents/base.js +174 -31
  5. package/dist/agents/orchestrator.d.ts +3 -1
  6. package/dist/agents/orchestrator.js +32 -16
  7. package/dist/agents/team.d.ts +0 -0
  8. package/dist/agents/team.js +0 -0
  9. package/dist/api/models.d.ts +0 -0
  10. package/dist/api/models.js +0 -0
  11. package/dist/api/ollama.d.ts +0 -0
  12. package/dist/api/ollama.js +0 -0
  13. package/dist/api/openrouter.d.ts +0 -0
  14. package/dist/api/openrouter.js +0 -0
  15. package/dist/commands/commands.d.ts +0 -0
  16. package/dist/commands/commands.js +0 -0
  17. package/dist/config/config.d.ts +0 -0
  18. package/dist/config/config.js +18 -18
  19. package/dist/context/compaction.d.ts +0 -0
  20. package/dist/context/compaction.js +0 -0
  21. package/dist/context/custom-agents.d.ts +0 -0
  22. package/dist/context/custom-agents.js +0 -0
  23. package/dist/context/custom-tools.d.ts +0 -0
  24. package/dist/context/custom-tools.js +0 -0
  25. package/dist/context/git-checkpoint.d.ts +0 -0
  26. package/dist/context/git-checkpoint.js +0 -0
  27. package/dist/context/neuro-md.d.ts +0 -0
  28. package/dist/context/neuro-md.js +0 -0
  29. package/dist/context/neuroignore.d.ts +0 -0
  30. package/dist/context/neuroignore.js +0 -0
  31. package/dist/context/repo-map.d.ts +0 -0
  32. package/dist/context/repo-map.js +0 -0
  33. package/dist/context/skill-standard.d.ts +0 -0
  34. package/dist/context/skill-standard.js +0 -0
  35. package/dist/context/skill-system.d.ts +0 -0
  36. package/dist/context/skill-system.js +0 -0
  37. package/dist/context/tree-sitter.d.ts +0 -0
  38. package/dist/context/tree-sitter.js +0 -0
  39. package/dist/core/acp.d.ts +0 -0
  40. package/dist/core/acp.js +0 -0
  41. package/dist/core/api-server.d.ts +0 -0
  42. package/dist/core/api-server.js +0 -0
  43. package/dist/core/approval.d.ts +4 -0
  44. package/dist/core/approval.js +46 -27
  45. package/dist/core/auto-compact.d.ts +0 -0
  46. package/dist/core/auto-compact.js +0 -0
  47. package/dist/core/auto-mode.d.ts +0 -0
  48. package/dist/core/auto-mode.js +0 -0
  49. package/dist/core/background-session.d.ts +0 -0
  50. package/dist/core/background-session.js +0 -0
  51. package/dist/core/cicd.d.ts +0 -0
  52. package/dist/core/cicd.js +0 -0
  53. package/dist/core/cloud-sync.d.ts +0 -0
  54. package/dist/core/cloud-sync.js +0 -0
  55. package/dist/core/code-review.d.ts +0 -0
  56. package/dist/core/code-review.js +0 -0
  57. package/dist/core/completion.d.ts +0 -0
  58. package/dist/core/completion.js +0 -0
  59. package/dist/core/context.d.ts +0 -0
  60. package/dist/core/context.js +0 -0
  61. package/dist/core/diff-preview.d.ts +0 -0
  62. package/dist/core/diff-preview.js +8 -16
  63. package/dist/core/doom-loop.d.ts +0 -0
  64. package/dist/core/doom-loop.js +0 -0
  65. package/dist/core/engine.d.ts +6 -3
  66. package/dist/core/engine.js +58 -56
  67. package/dist/core/extended-thinking.d.ts +0 -0
  68. package/dist/core/extended-thinking.js +0 -0
  69. package/dist/core/fallback.d.ts +0 -0
  70. package/dist/core/fallback.js +0 -0
  71. package/dist/core/git-worktree.d.ts +0 -0
  72. package/dist/core/git-worktree.js +0 -0
  73. package/dist/core/headless.d.ts +0 -0
  74. package/dist/core/headless.js +0 -0
  75. package/dist/core/i18n.d.ts +0 -0
  76. package/dist/core/i18n.js +0 -0
  77. package/dist/core/linting.d.ts +0 -0
  78. package/dist/core/linting.js +0 -0
  79. package/dist/core/model-router.d.ts +0 -0
  80. package/dist/core/model-router.js +3 -3
  81. package/dist/core/multi-model.d.ts +0 -0
  82. package/dist/core/multi-model.js +0 -0
  83. package/dist/core/multi-session.d.ts +0 -0
  84. package/dist/core/multi-session.js +0 -0
  85. package/dist/core/multimodal.d.ts +0 -0
  86. package/dist/core/multimodal.js +0 -0
  87. package/dist/core/observability.d.ts +0 -0
  88. package/dist/core/observability.js +0 -0
  89. package/dist/core/os-sandbox.d.ts +0 -0
  90. package/dist/core/os-sandbox.js +0 -0
  91. package/dist/core/outcome-grading.d.ts +0 -0
  92. package/dist/core/outcome-grading.js +0 -0
  93. package/dist/core/output-styles.d.ts +0 -0
  94. package/dist/core/output-styles.js +0 -0
  95. package/dist/core/parallel-agents.d.ts +0 -0
  96. package/dist/core/parallel-agents.js +0 -0
  97. package/dist/core/plugin-bundle.d.ts +0 -0
  98. package/dist/core/plugin-bundle.js +0 -0
  99. package/dist/core/plugin-sdk.d.ts +0 -0
  100. package/dist/core/plugin-sdk.js +0 -0
  101. package/dist/core/prompt-cache.d.ts +0 -0
  102. package/dist/core/prompt-cache.js +0 -0
  103. package/dist/core/sandbox.d.ts +0 -0
  104. package/dist/core/sandbox.js +0 -0
  105. package/dist/core/scheduled-tasks.d.ts +0 -0
  106. package/dist/core/scheduled-tasks.js +0 -0
  107. package/dist/core/security-scanner.d.ts +0 -0
  108. package/dist/core/security-scanner.js +0 -0
  109. package/dist/core/session.d.ts +0 -0
  110. package/dist/core/session.js +0 -0
  111. package/dist/core/shell-completion.d.ts +0 -0
  112. package/dist/core/shell-completion.js +0 -0
  113. package/dist/core/smart-monitor.d.ts +0 -0
  114. package/dist/core/smart-monitor.js +0 -0
  115. package/dist/core/spec-driven.d.ts +0 -0
  116. package/dist/core/spec-driven.js +0 -0
  117. package/dist/core/spending-warnings.d.ts +0 -0
  118. package/dist/core/spending-warnings.js +0 -0
  119. package/dist/core/sub-agent.d.ts +0 -0
  120. package/dist/core/sub-agent.js +0 -0
  121. package/dist/core/telemetry.d.ts +0 -0
  122. package/dist/core/telemetry.js +0 -0
  123. package/dist/core/terminal-ux.d.ts +0 -0
  124. package/dist/core/terminal-ux.js +0 -0
  125. package/dist/core/testing.d.ts +0 -0
  126. package/dist/core/testing.js +0 -0
  127. package/dist/core/types.d.ts +1 -1
  128. package/dist/core/types.js +0 -0
  129. package/dist/core/undo-redo.d.ts +0 -0
  130. package/dist/core/undo-redo.js +0 -0
  131. package/dist/core/updater.d.ts +0 -0
  132. package/dist/core/updater.js +0 -0
  133. package/dist/core/vim-mode.d.ts +0 -0
  134. package/dist/core/vim-mode.js +0 -0
  135. package/dist/core/voice.d.ts +0 -0
  136. package/dist/core/voice.js +0 -0
  137. package/dist/core/web-dashboard.d.ts +0 -0
  138. package/dist/core/web-dashboard.js +0 -0
  139. package/dist/hooks/hooks.d.ts +0 -0
  140. package/dist/hooks/hooks.js +0 -0
  141. package/dist/hooks/llm-evaluator.d.ts +0 -0
  142. package/dist/hooks/llm-evaluator.js +0 -0
  143. package/dist/index.d.ts +0 -0
  144. package/dist/index.js +5 -4
  145. package/dist/lsp/lsp-manager.d.ts +0 -0
  146. package/dist/lsp/lsp-manager.js +0 -0
  147. package/dist/mcp/client.d.ts +0 -0
  148. package/dist/mcp/client.js +0 -0
  149. package/dist/mcp/mcp-apps.d.ts +0 -0
  150. package/dist/mcp/mcp-apps.js +0 -0
  151. package/dist/tools/bash.d.ts +0 -0
  152. package/dist/tools/bash.js +0 -0
  153. package/dist/tools/browser.d.ts +0 -0
  154. package/dist/tools/browser.js +0 -0
  155. package/dist/tools/extended.d.ts +0 -0
  156. package/dist/tools/extended.js +0 -0
  157. package/dist/tools/file.d.ts +0 -0
  158. package/dist/tools/file.js +0 -0
  159. package/dist/tools/github.d.ts +0 -0
  160. package/dist/tools/github.js +0 -0
  161. package/dist/tools/index.d.ts +0 -0
  162. package/dist/tools/index.js +0 -0
  163. package/dist/tools/memory.d.ts +0 -0
  164. package/dist/tools/memory.js +0 -0
  165. package/dist/tools/registry.d.ts +0 -0
  166. package/dist/tools/registry.js +0 -0
  167. package/dist/tools/web.d.ts +0 -0
  168. package/dist/tools/web.js +0 -0
  169. package/dist/ui/renderer.d.ts +11 -64
  170. package/dist/ui/renderer.js +172 -156
  171. package/dist/ui/theme.d.ts +5 -0
  172. package/dist/ui/theme.js +99 -45
  173. package/dist/utils/crosspath.d.ts +0 -0
  174. package/dist/utils/crosspath.js +0 -0
  175. package/package.json +1 -1
@@ -4,94 +4,41 @@ export declare class TerminalUI {
4
4
  theme: Theme;
5
5
  private showTokens;
6
6
  private showCost;
7
+ private isStreaming;
8
+ version: string;
7
9
  constructor(themeName?: string, showTokens?: boolean, showCost?: boolean);
8
- /**
9
- * Print the banner / splash screen
10
- */
10
+ setVersion(v: string): void;
11
11
  banner(): void;
12
- /**
13
- * Print user message
14
- */
15
12
  userMessage(content: string): void;
16
- /**
17
- * Print assistant message with markdown-like formatting
18
- */
19
13
  assistantMessage(content: string): void;
20
- /**
21
- * Print streaming token
22
- */
23
14
  streamingToken(token: string): void;
24
- /**
25
- * Start streaming block
26
- */
27
15
  startStreaming(): void;
28
- /**
29
- * End streaming block
30
- */
31
16
  endStreaming(): void;
32
- /**
33
- * Print thinking indicator
34
- */
35
17
  thinking(message: string): void;
36
- /**
37
- * Print tool call
38
- */
39
18
  toolCall(name: string, args: Record<string, unknown>): void;
40
- /**
41
- * Print tool result
42
- */
19
+ private formatToolArgs;
43
20
  toolResult(name: string, result: string, isError: boolean): void;
44
- /**
45
- * Print approval request
46
- */
47
21
  approvalRequest(toolName: string, args: Record<string, unknown>, risk: 'low' | 'medium' | 'high'): boolean;
48
- /**
49
- * Print token usage
50
- */
51
22
  tokenUsage(usage: TokenUsage, modelId: string): void;
52
- /**
53
- * Print session stats
54
- */
55
23
  sessionStats(totalInput: number, totalOutput: number, totalCost: number): void;
56
- /**
57
- * Print agent activity
58
- */
59
- agentActivity(agentName: string, status: 'starting' | 'working' | 'done' | 'error'): void;
60
- /**
61
- * Print error
62
- */
24
+ agentActivity(agentName: string, status: 'starting' | 'working' | 'done' | 'error', detail?: string): void;
63
25
  error(message: string): void;
64
- /**
65
- * Print info
66
- */
67
26
  info(message: string): void;
68
- /**
69
- * Print success
70
- */
71
27
  success(message: string): void;
72
- /**
73
- * Print warning
74
- */
75
28
  warning(message: string): void;
76
- /**
77
- * Print separator
78
- */
79
29
  separator(): void;
80
- /**
81
- * Print code block
82
- */
83
30
  codeBlock(code: string, language?: string): void;
84
- /**
85
- * Print model selection menu
86
- */
87
31
  modelList(selectedModel: string): void;
88
- /**
89
- * Print agent list
90
- */
91
32
  agentList(agents: Array<{
92
33
  name: string;
93
34
  description: string;
94
35
  model: string;
95
36
  }>): void;
37
+ diffAdd(line: string): void;
38
+ diffRemove(line: string): void;
39
+ diffContext(line: string): void;
40
+ diffHeader(file: string): void;
41
+ private truncate;
42
+ private byteSize;
96
43
  }
97
44
  //# sourceMappingURL=renderer.d.ts.map
@@ -1,6 +1,7 @@
1
1
  // ============================================================
2
- // NeuroCLI - Terminal UI Renderer
3
- // Beautiful terminal output with streaming support
2
+ // NeuroCLI - Terminal UI Renderer v2
3
+ // Claude Code-inspired minimal, professional terminal output
4
+ // Clean lines, subtle colors, compact information display
4
5
  // ============================================================
5
6
  import { getTheme } from './theme.js';
6
7
  import { MODELS } from '../api/models.js';
@@ -8,54 +9,48 @@ export class TerminalUI {
8
9
  theme;
9
10
  showTokens;
10
11
  showCost;
11
- constructor(themeName = 'dracula', showTokens = true, showCost = true) {
12
+ isStreaming = false;
13
+ version = '4.3.0';
14
+ constructor(themeName = 'claude', showTokens = true, showCost = true) {
12
15
  this.theme = getTheme(themeName);
13
16
  this.showTokens = showTokens;
14
17
  this.showCost = showCost;
15
18
  }
16
- /**
17
- * Print the banner / splash screen
18
- */
19
+ setVersion(v) {
20
+ this.version = v;
21
+ }
22
+ // ── Banner ──────────────────────────────────────────────
19
23
  banner() {
20
- const banner = `
21
- ${this.theme.primary(' ╔══════════════════════════════════════════╗')}
22
- ${this.theme.primary(' ║')} ${this.theme.accent.bold('🧠 NeuroCLI')} ${this.theme.muted('v1.0.0')} ${this.theme.primary('║')}
23
- ${this.theme.primary('')} ${this.theme.secondary('Advanced AI Terminal Coding Assistant')} ${this.theme.primary('║')}
24
- ${this.theme.primary(' ╠══════════════════════════════════════════╣')}
25
- ${this.theme.primary(' ║')} ${this.theme.muted('OpenRouter')} ${this.theme.success('●')} ${this.theme.muted('Multi-Agent')} ${this.theme.success('●')} ${this.theme.muted('Streaming')} ${this.theme.success('●')} ${this.theme.primary('║')}
26
- ${this.theme.primary(' ╚══════════════════════════════════════════╝')}
27
- `;
28
- console.log(banner);
24
+ // Claude Code style: clean, minimal, no box art
25
+ // Version is injected from index.ts via setVersion()
26
+ console.log();
27
+ console.log(` ${this.theme.bold('NeuroCLI')} ${this.theme.muted(`v${this.version}`)}`);
28
+ console.log(` ${this.theme.dim(''.repeat(40))}`);
29
29
  }
30
- /**
31
- * Print user message
32
- */
30
+ // ── User Messages ───────────────────────────────────────
33
31
  userMessage(content) {
34
- console.log(`\n${this.theme.user('❯')} ${this.theme.user.bold('You')}`);
35
- console.log(` ${content}\n`);
32
+ console.log();
33
+ console.log(` ${this.theme.accent('>')} ${content}`);
34
+ console.log();
36
35
  }
37
- /**
38
- * Print assistant message with markdown-like formatting
39
- */
36
+ // ── Assistant Messages ──────────────────────────────────
40
37
  assistantMessage(content) {
41
- console.log(`${this.theme.accent('◈')} ${this.theme.bold('Neuro')}`);
42
- // Simple markdown rendering
43
38
  const lines = content.split('\n');
44
39
  for (const line of lines) {
45
40
  if (line.startsWith('```')) {
46
- continue; // Code block markers handled separately
41
+ continue;
47
42
  }
48
43
  else if (line.startsWith('# ')) {
49
- console.log(` ${this.theme.bold(line)}`);
44
+ console.log(` ${this.theme.bold(line.slice(2))}`);
50
45
  }
51
46
  else if (line.startsWith('## ')) {
52
- console.log(` ${this.theme.primary(line)}`);
47
+ console.log(` ${this.theme.bold(line.slice(3))}`);
53
48
  }
54
49
  else if (line.startsWith('### ')) {
55
- console.log(` ${this.theme.accent(line)}`);
50
+ console.log(` ${this.theme.primary(line.slice(4))}`);
56
51
  }
57
52
  else if (line.startsWith('- ') || line.startsWith('* ')) {
58
- console.log(` ${this.theme.muted('')} ${line.slice(2)}`);
53
+ console.log(` ${this.theme.muted('·')} ${line.slice(2)}`);
59
54
  }
60
55
  else if (line.startsWith('> ')) {
61
56
  console.log(` ${this.theme.thinking(line)}`);
@@ -66,214 +61,235 @@ ${this.theme.primary(' ╚═════════════════
66
61
  }
67
62
  console.log();
68
63
  }
69
- /**
70
- * Print streaming token
71
- */
64
+ // ── Streaming ───────────────────────────────────────────
72
65
  streamingToken(token) {
73
66
  process.stdout.write(token);
74
67
  }
75
- /**
76
- * Start streaming block
77
- */
78
68
  startStreaming() {
79
- process.stdout.write(`${this.theme.accent('◈')} ${this.theme.bold('Neuro')} `);
69
+ this.isStreaming = true;
80
70
  }
81
- /**
82
- * End streaming block
83
- */
84
71
  endStreaming() {
72
+ this.isStreaming = false;
85
73
  console.log('\n');
86
74
  }
87
- /**
88
- * Print thinking indicator
89
- */
75
+ // ── Thinking / Status ───────────────────────────────────
90
76
  thinking(message) {
91
- console.log(`${this.theme.thinking(' ○')} ${this.theme.thinking(message)}`);
77
+ // Claude Code: dim italic, compact
78
+ console.log(` ${this.theme.thinking(message)}`);
92
79
  }
93
- /**
94
- * Print tool call
95
- */
80
+ // ── Tool Calls (Claude Code style: compact one-liners) ──
96
81
  toolCall(name, args) {
97
- const argsStr = Object.entries(args)
98
- .map(([k, v]) => {
99
- const val = typeof v === 'string' && v.length > 60
100
- ? `"${v.slice(0, 60)}..."`
101
- : JSON.stringify(v);
102
- return `${this.theme.muted(k)}=${val}`;
103
- })
104
- .join(' ');
105
- console.log(` ${this.theme.tool('')} ${this.theme.tool.bold(name)} ${this.theme.muted(argsStr)}`);
82
+ // Build compact argument summary
83
+ const summary = this.formatToolArgs(name, args);
84
+ console.log(` ${this.theme.tool('')} ${this.theme.tool(name)}${summary}`);
85
+ }
86
+ formatToolArgs(name, args) {
87
+ switch (name) {
88
+ case 'read_file':
89
+ return ` ${this.theme.path(String(args.path || ''))}`;
90
+ case 'write_file':
91
+ return ` ${this.theme.path(String(args.path || ''))} ${this.theme.muted(`(${this.byteSize(String(args.content || ''))})`)}`;
92
+ case 'edit_file':
93
+ return ` ${this.theme.path(String(args.path || ''))}`;
94
+ case 'search_files':
95
+ return ` ${this.theme.muted(`"${args.query || ''}"`)} ${this.theme.path(String(args.path || '.'))}`;
96
+ case 'list_directory':
97
+ return ` ${this.theme.path(String(args.path || args.directory || '.'))}`;
98
+ case 'run_command':
99
+ return ` ${this.theme.muted(this.truncate(String(args.command || ''), 60))}`;
100
+ case 'apply_diff':
101
+ return ` ${this.theme.path(String(args.path || ''))}`;
102
+ case 'delete_file':
103
+ return ` ${this.theme.path(String(args.path || ''))}`;
104
+ case 'web_search':
105
+ return ` ${this.theme.muted(`"${args.query || ''}"`)}`;
106
+ case 'web_fetch':
107
+ return ` ${this.theme.muted(this.truncate(String(args.url || ''), 60))}`;
108
+ default: {
109
+ const entries = Object.entries(args);
110
+ if (entries.length === 0)
111
+ return '';
112
+ const first = entries[0];
113
+ const val = typeof first[1] === 'string' ? this.truncate(first[1], 50) : JSON.stringify(first[1]);
114
+ return ` ${this.theme.muted(`${first[0]}: ${val}`)}`;
115
+ }
116
+ }
106
117
  }
107
- /**
108
- * Print tool result
109
- */
118
+ // ── Tool Results (compact status line) ──────────────────
110
119
  toolResult(name, result, isError) {
111
120
  if (isError) {
112
- console.log(` ${this.theme.error('✗')} ${this.theme.error(name)}: ${this.theme.error(result.slice(0, 200))}`);
121
+ const preview = this.truncate(result.replace(/\n/g, ' '), 80);
122
+ console.log(` ${this.theme.error('✗')} ${this.theme.error(preview)}`);
113
123
  }
114
124
  else {
115
- const preview = result.length > 200 ? result.slice(0, 200) + '...' : result;
116
- console.log(` ${this.theme.success('')} ${this.theme.muted(name)}: ${this.theme.muted(preview)}`);
125
+ // Show brief success indicator with key info
126
+ const preview = this.truncate(result.replace(/\n/g, ' '), 80);
127
+ if (preview.length > 0 && !preview.startsWith('{') && !preview.startsWith('[')) {
128
+ console.log(` ${this.theme.dim(preview)}`);
129
+ }
117
130
  }
118
131
  }
119
- /**
120
- * Print approval request
121
- */
132
+ // ── Approval Prompts (minimal, clear) ───────────────────
122
133
  approvalRequest(toolName, args, risk) {
123
- const riskColors = {
124
- low: this.theme.success,
125
- medium: this.theme.warning,
126
- high: this.theme.error,
134
+ const riskLabel = {
135
+ low: this.theme.success('low'),
136
+ medium: this.theme.warning('med'),
137
+ high: this.theme.error('high'),
127
138
  };
128
- const riskIcons = { low: '🟢', medium: '🟡', high: '🔴' };
129
- console.log(`\n ${riskIcons[risk]} ${riskColors[risk].bold(`Approval needed [${risk} risk]`)}`);
130
- console.log(` Tool: ${this.theme.tool(toolName)}`);
131
- console.log(` Args: ${this.theme.muted(JSON.stringify(args, null, 2).slice(0, 300))}`);
139
+ const summary = this.formatToolArgs(toolName, args);
140
+ console.log();
141
+ console.log(` ${this.theme.muted('┌─')} ${this.theme.bold(toolName)} ${riskLabel[risk]} risk`);
142
+ console.log(` ${this.theme.muted('└─')}${summary}`);
132
143
  return true;
133
144
  }
134
- /**
135
- * Print token usage
136
- */
145
+ // ── Token Usage (compact footer) ────────────────────────
137
146
  tokenUsage(usage, modelId) {
138
147
  if (!this.showTokens && !this.showCost)
139
148
  return;
140
149
  const parts = [];
141
150
  if (this.showTokens) {
142
- parts.push(`in: ${usage.inputTokens.toLocaleString()}`);
143
- parts.push(`out: ${usage.outputTokens.toLocaleString()}`);
151
+ parts.push(`${usage.inputTokens.toLocaleString()}in`);
152
+ parts.push(`${usage.outputTokens.toLocaleString()}out`);
144
153
  }
145
154
  if (this.showCost) {
146
- parts.push(`cost: $${usage.cost.toFixed(4)}`);
155
+ parts.push(`$${usage.cost.toFixed(4)}`);
147
156
  }
148
157
  const model = MODELS[modelId];
149
158
  const modelName = model?.name || modelId;
150
- console.log(` ${this.theme.muted(`📊 ${modelName} | ${parts.join(' | ')}`)}`);
159
+ // Claude Code style: dim compact line
160
+ console.log(` ${this.theme.dim(`${modelName} · ${parts.join(' · ')}`)}`);
151
161
  }
152
- /**
153
- * Print session stats
154
- */
162
+ // ── Session Stats ───────────────────────────────────────
155
163
  sessionStats(totalInput, totalOutput, totalCost) {
156
- console.log(`\n ${this.theme.muted('━━━ Session Stats ━━━')}`);
157
- console.log(` ${this.theme.muted(`Total tokens: ${totalInput.toLocaleString()} in + ${totalOutput.toLocaleString()} out`)}`);
158
- console.log(` ${this.theme.muted(`Total cost: $${totalCost.toFixed(4)}`)}`);
164
+ console.log();
165
+ console.log(` ${this.theme.muted('Session:')}`, this.theme.dim(`${totalInput.toLocaleString()} in · ${totalOutput.toLocaleString()} out · $${totalCost.toFixed(4)}`));
159
166
  }
160
- /**
161
- * Print agent activity
162
- */
163
- agentActivity(agentName, status) {
164
- const icons = {
165
- starting: '🚀',
166
- working: '⚙️',
167
- done: '✅',
168
- error: '❌',
167
+ // ── Agent Activity (subtle indicator) ───────────────────
168
+ agentActivity(agentName, status, detail) {
169
+ const indicators = {
170
+ starting: this.theme.muted('○'),
171
+ working: this.theme.accent('◎'),
172
+ done: this.theme.success(''),
173
+ error: this.theme.error(''),
169
174
  };
170
- const colors = {
171
- starting: this.theme.primary,
172
- working: this.theme.warning,
173
- done: this.theme.success,
174
- error: this.theme.error,
175
+ const statusText = {
176
+ starting: 'starting',
177
+ working: 'working...',
178
+ done: 'done',
179
+ error: 'failed',
175
180
  };
176
- console.log(` ${icons[status]} ${colors[status](`${agentName}: ${status}`)}`);
181
+ const detailStr = detail ? ` ${this.theme.dim(detail)}` : '';
182
+ console.log(` ${indicators[status]} ${this.theme.muted(agentName)} ${this.theme.dim(statusText[status])}${detailStr}`);
177
183
  }
178
- /**
179
- * Print error
180
- */
184
+ // ── Status Messages (minimal) ───────────────────────────
181
185
  error(message) {
182
- console.error(`\n ${this.theme.error('✗ Error:')} ${this.theme.error(message)}\n`);
186
+ console.error(` ${this.theme.error('✗')} ${message}`);
183
187
  }
184
- /**
185
- * Print info
186
- */
187
188
  info(message) {
188
- console.log(` ${this.theme.primary('')} ${this.theme.primary(message)}`);
189
+ console.log(` ${this.theme.muted('')} ${this.theme.muted(message)}`);
189
190
  }
190
- /**
191
- * Print success
192
- */
193
191
  success(message) {
194
- console.log(` ${this.theme.success('✓')} ${this.theme.success(message)}`);
192
+ console.log(` ${this.theme.success('✓')} ${message}`);
195
193
  }
196
- /**
197
- * Print warning
198
- */
199
194
  warning(message) {
200
- console.log(` ${this.theme.warning('')} ${this.theme.warning(message)}`);
195
+ console.log(` ${this.theme.warning('!')} ${message}`);
201
196
  }
202
- /**
203
- * Print separator
204
- */
197
+ // ── Separator ───────────────────────────────────────────
205
198
  separator() {
206
199
  console.log(` ${this.theme.dim('─'.repeat(50))}`);
207
200
  }
208
- /**
209
- * Print code block
210
- */
201
+ // ── Code Block (clean frame) ────────────────────────────
211
202
  codeBlock(code, language) {
212
203
  const header = language ? ` ${language} ` : '';
213
- console.log(` ${this.theme.dim('┌' + '─'.repeat(48) + '┐')}`);
204
+ const width = 60;
205
+ console.log(` ${this.theme.dim('┌' + '─'.repeat(width - 2) + '┐')}`);
214
206
  if (header) {
215
- console.log(` ${this.theme.dim('│')} ${this.theme.keyword(header)}${' '.repeat(47 - header.length)}${this.theme.dim('│')}`);
207
+ console.log(` ${this.theme.dim('│')} ${this.theme.keyword(header)}${' '.repeat(width - 3 - header.length)}${this.theme.dim('│')}`);
216
208
  }
217
- for (const line of code.split('\n')) {
218
- const truncated = line.length > 46 ? line.slice(0, 46) + '…' : line;
219
- console.log(` ${this.theme.dim('│')} ${this.theme.code(truncated)}${' '.repeat(Math.max(0, 47 - truncated.length))}${this.theme.dim('│')}`);
209
+ for (const line of code.split('\n').slice(0, 30)) {
210
+ const truncated = line.length > width - 4 ? line.slice(0, width - 5) + '…' : line;
211
+ console.log(` ${this.theme.dim('│')} ${this.theme.code(truncated)}${' '.repeat(Math.max(0, width - 3 - truncated.length))}${this.theme.dim('│')}`);
220
212
  }
221
- console.log(` ${this.theme.dim('└' + '─'.repeat(48) + '┘')}`);
213
+ console.log(` ${this.theme.dim('└' + '─'.repeat(width - 2) + '┘')}`);
222
214
  }
223
- /**
224
- * Print model selection menu
225
- */
215
+ // ── Model List ──────────────────────────────────────────
226
216
  modelList(selectedModel) {
227
- console.log(`\n ${this.theme.bold('Available Models:')}\n`);
217
+ console.log();
218
+ console.log(` ${this.theme.bold('Models')}`);
219
+ console.log(` ${this.theme.dim('─'.repeat(50))}`);
228
220
  const categories = {
229
- '🆓 Free (Best for Coding)': [
221
+ 'Free · Coding': [
230
222
  'qwen/qwen3-coder:free',
231
223
  'nvidia/nemotron-3-super-120b-a12b:free',
232
- 'nvidia/nemotron-3-ultra-550b-a55b:free',
233
224
  'cohere/north-mini-code:free',
234
225
  ],
235
- '🆓 Free (Large Context)': [
236
- 'nvidia/nemotron-3-super-120b-a12b:free',
226
+ 'Free · Large Context': [
237
227
  'nvidia/nemotron-3-ultra-550b-a55b:free',
238
- 'tencent/hy3:free',
239
228
  'meta-llama/llama-3.3-70b-instruct:free',
229
+ 'tencent/hy3:free',
240
230
  ],
241
- '🆓 Free (Vision + Tools)': [
231
+ 'Free · Vision': [
242
232
  'google/gemma-4-31b-it:free',
243
233
  'nvidia/nemotron-nano-12b-v2-vl:free',
244
- 'openai/gpt-oss-20b:free',
245
- 'poolside/laguna-m.1:free',
246
234
  ],
247
- '💎 Premium Flagship': ['anthropic/claude-opus-4', 'openai/o3', 'google/gemini-2.5-pro'],
248
- '💎 Premium Balanced': ['anthropic/claude-sonnet-4', 'openai/gpt-4o', 'deepseek/deepseek-r1'],
249
- '💎 Premium Fast': ['anthropic/claude-3.5-haiku', 'openai/gpt-4o-mini', 'google/gemini-2.5-flash', 'deepseek/deepseek-chat'],
235
+ 'Premium · Flagship': ['anthropic/claude-opus-4', 'openai/o3', 'google/gemini-2.5-pro'],
236
+ 'Premium · Balanced': ['anthropic/claude-sonnet-4', 'openai/gpt-4o', 'deepseek/deepseek-r1'],
237
+ 'Premium · Fast': ['anthropic/claude-3.5-haiku', 'openai/gpt-4o-mini', 'google/gemini-2.5-flash'],
250
238
  };
251
239
  for (const [category, models] of Object.entries(categories)) {
252
- console.log(` ${this.theme.primary.bold(category)}`);
240
+ console.log(` ${this.theme.label(category)}`);
253
241
  for (const modelId of models) {
254
242
  const model = MODELS[modelId];
255
243
  if (!model)
256
244
  continue;
257
- const selected = modelId === selectedModel ? this.theme.accent(' ◀ current') : '';
245
+ const isCurrent = modelId === selectedModel;
246
+ const marker = isCurrent ? this.theme.accent('●') : this.theme.dim('○');
247
+ const name = isCurrent ? this.theme.bold(model.name) : this.theme.muted(model.name);
258
248
  const isFree = model.inputPrice === 0 && model.outputPrice === 0;
259
- const price = isFree ? 'FREE' : `$${model.inputPrice}/${model.outputPrice}`;
260
- const priceColored = isFree ? this.theme.success(price.padEnd(12)) : this.theme.muted(price.padEnd(12));
261
- console.log(` ${this.theme.muted('•')} ${this.theme.tool(model.name.padEnd(35))} ${priceColored} ${this.theme.muted(`${(model.contextWindow / 1000).toFixed(0)}K ctx`)}${model.supportsTools ? this.theme.muted(' 🔧') : ''}${selected}`);
249
+ const price = isFree ? this.theme.success('free') : this.theme.muted(`$${model.inputPrice}/${model.outputPrice}`);
250
+ const ctx = this.theme.dim(`${(model.contextWindow / 1000).toFixed(0)}K`);
251
+ console.log(` ${marker} ${name.padEnd(36)} ${price.padEnd(14)} ${ctx}`);
262
252
  }
263
253
  console.log();
264
254
  }
265
255
  }
266
- /**
267
- * Print agent list
268
- */
256
+ // ── Agent List ──────────────────────────────────────────
269
257
  agentList(agents) {
270
- console.log(`\n ${this.theme.bold('Available Agents:')}\n`);
258
+ console.log();
259
+ console.log(` ${this.theme.bold('Agents')}`);
260
+ console.log(` ${this.theme.dim('─'.repeat(50))}`);
271
261
  for (const agent of agents) {
272
- const model = MODELS[agent.model];
273
- console.log(` ${this.theme.tool('◆')} ${this.theme.bold(agent.name.padEnd(12))} ${this.theme.muted('- ' + agent.description)}`);
274
- console.log(` ${this.theme.muted(`Model: ${model?.name || agent.model}`)}`);
262
+ console.log(` ${this.theme.accent('●')} ${this.theme.bold(agent.name.padEnd(12))} ${this.theme.muted(agent.description)}`);
275
263
  }
276
264
  console.log();
277
265
  }
266
+ // ── Diff Display (Claude Code style: + and - lines) ─────
267
+ diffAdd(line) {
268
+ console.log(` ${this.theme.diffAdd('+')} ${this.theme.diffAdd(line)}`);
269
+ }
270
+ diffRemove(line) {
271
+ console.log(` ${this.theme.diffRemove('-')} ${this.theme.diffRemove(line)}`);
272
+ }
273
+ diffContext(line) {
274
+ console.log(` ${this.theme.diffContext(' ')} ${this.theme.diffContext(line)}`);
275
+ }
276
+ diffHeader(file) {
277
+ console.log();
278
+ console.log(` ${this.theme.dim('───')} ${this.theme.path(file)} ${this.theme.dim('───')}`);
279
+ }
280
+ // ── Helpers ─────────────────────────────────────────────
281
+ truncate(str, maxLen) {
282
+ if (str.length <= maxLen)
283
+ return str;
284
+ return str.slice(0, maxLen - 1) + '…';
285
+ }
286
+ byteSize(content) {
287
+ const bytes = Buffer.byteLength(content, 'utf-8');
288
+ if (bytes < 1024)
289
+ return `${bytes}B`;
290
+ if (bytes < 1024 * 1024)
291
+ return `${(bytes / 1024).toFixed(1)}KB`;
292
+ return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
293
+ }
278
294
  }
279
295
  //# sourceMappingURL=renderer.js.map
@@ -21,6 +21,11 @@ export interface Theme {
21
21
  keyword: typeof chalk;
22
22
  comment: typeof chalk;
23
23
  border: typeof chalk;
24
+ diffAdd: typeof chalk;
25
+ diffRemove: typeof chalk;
26
+ diffContext: typeof chalk;
27
+ label: typeof chalk;
28
+ path: typeof chalk;
24
29
  }
25
30
  export declare function getTheme(name: string): Theme;
26
31
  export declare function listThemes(): string[];