neuro-cli 4.2.0 → 4.3.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 +0 -0
  4. package/dist/agents/base.js +0 -0
  5. package/dist/agents/orchestrator.d.ts +0 -0
  6. package/dist/agents/orchestrator.js +0 -0
  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 +1 -1
  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 +0 -0
  66. package/dist/core/engine.js +0 -0
  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 +0 -0
  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 +4 -3
  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 +10 -63
  170. package/dist/ui/renderer.js +170 -155
  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
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
package/dist/tools/web.js CHANGED
File without changes
@@ -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
24
  agentActivity(agentName: string, status: 'starting' | 'working' | 'done' | 'error'): void;
60
- /**
61
- * Print error
62
- */
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,234 @@ ${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
- */
167
+ // ── Agent Activity (subtle indicator) ───────────────────
163
168
  agentActivity(agentName, status) {
164
- const icons = {
165
- starting: '🚀',
166
- working: '⚙️',
167
- done: '',
168
- error: '',
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
+ console.log(` ${indicators[status]} ${this.theme.muted(agentName)} ${this.theme.dim(statusText[status])}`);
177
182
  }
178
- /**
179
- * Print error
180
- */
183
+ // ── Status Messages (minimal) ───────────────────────────
181
184
  error(message) {
182
- console.error(`\n ${this.theme.error('✗ Error:')} ${this.theme.error(message)}\n`);
185
+ console.error(` ${this.theme.error('✗')} ${message}`);
183
186
  }
184
- /**
185
- * Print info
186
- */
187
187
  info(message) {
188
- console.log(` ${this.theme.primary('')} ${this.theme.primary(message)}`);
188
+ console.log(` ${this.theme.muted('')} ${this.theme.muted(message)}`);
189
189
  }
190
- /**
191
- * Print success
192
- */
193
190
  success(message) {
194
- console.log(` ${this.theme.success('✓')} ${this.theme.success(message)}`);
191
+ console.log(` ${this.theme.success('✓')} ${message}`);
195
192
  }
196
- /**
197
- * Print warning
198
- */
199
193
  warning(message) {
200
- console.log(` ${this.theme.warning('')} ${this.theme.warning(message)}`);
194
+ console.log(` ${this.theme.warning('!')} ${message}`);
201
195
  }
202
- /**
203
- * Print separator
204
- */
196
+ // ── Separator ───────────────────────────────────────────
205
197
  separator() {
206
198
  console.log(` ${this.theme.dim('─'.repeat(50))}`);
207
199
  }
208
- /**
209
- * Print code block
210
- */
200
+ // ── Code Block (clean frame) ────────────────────────────
211
201
  codeBlock(code, language) {
212
202
  const header = language ? ` ${language} ` : '';
213
- console.log(` ${this.theme.dim('┌' + '─'.repeat(48) + '┐')}`);
203
+ const width = 60;
204
+ console.log(` ${this.theme.dim('┌' + '─'.repeat(width - 2) + '┐')}`);
214
205
  if (header) {
215
- console.log(` ${this.theme.dim('│')} ${this.theme.keyword(header)}${' '.repeat(47 - header.length)}${this.theme.dim('│')}`);
206
+ console.log(` ${this.theme.dim('│')} ${this.theme.keyword(header)}${' '.repeat(width - 3 - header.length)}${this.theme.dim('│')}`);
216
207
  }
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('│')}`);
208
+ for (const line of code.split('\n').slice(0, 30)) {
209
+ const truncated = line.length > width - 4 ? line.slice(0, width - 5) + '…' : line;
210
+ console.log(` ${this.theme.dim('│')} ${this.theme.code(truncated)}${' '.repeat(Math.max(0, width - 3 - truncated.length))}${this.theme.dim('│')}`);
220
211
  }
221
- console.log(` ${this.theme.dim('└' + '─'.repeat(48) + '┘')}`);
212
+ console.log(` ${this.theme.dim('└' + '─'.repeat(width - 2) + '┘')}`);
222
213
  }
223
- /**
224
- * Print model selection menu
225
- */
214
+ // ── Model List ──────────────────────────────────────────
226
215
  modelList(selectedModel) {
227
- console.log(`\n ${this.theme.bold('Available Models:')}\n`);
216
+ console.log();
217
+ console.log(` ${this.theme.bold('Models')}`);
218
+ console.log(` ${this.theme.dim('─'.repeat(50))}`);
228
219
  const categories = {
229
- '🆓 Free (Best for Coding)': [
220
+ 'Free · Coding': [
230
221
  'qwen/qwen3-coder:free',
231
222
  'nvidia/nemotron-3-super-120b-a12b:free',
232
- 'nvidia/nemotron-3-ultra-550b-a55b:free',
233
223
  'cohere/north-mini-code:free',
234
224
  ],
235
- '🆓 Free (Large Context)': [
236
- 'nvidia/nemotron-3-super-120b-a12b:free',
225
+ 'Free · Large Context': [
237
226
  'nvidia/nemotron-3-ultra-550b-a55b:free',
238
- 'tencent/hy3:free',
239
227
  'meta-llama/llama-3.3-70b-instruct:free',
228
+ 'tencent/hy3:free',
240
229
  ],
241
- '🆓 Free (Vision + Tools)': [
230
+ 'Free · Vision': [
242
231
  'google/gemma-4-31b-it:free',
243
232
  'nvidia/nemotron-nano-12b-v2-vl:free',
244
- 'openai/gpt-oss-20b:free',
245
- 'poolside/laguna-m.1:free',
246
233
  ],
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'],
234
+ 'Premium · Flagship': ['anthropic/claude-opus-4', 'openai/o3', 'google/gemini-2.5-pro'],
235
+ 'Premium · Balanced': ['anthropic/claude-sonnet-4', 'openai/gpt-4o', 'deepseek/deepseek-r1'],
236
+ 'Premium · Fast': ['anthropic/claude-3.5-haiku', 'openai/gpt-4o-mini', 'google/gemini-2.5-flash'],
250
237
  };
251
238
  for (const [category, models] of Object.entries(categories)) {
252
- console.log(` ${this.theme.primary.bold(category)}`);
239
+ console.log(` ${this.theme.label(category)}`);
253
240
  for (const modelId of models) {
254
241
  const model = MODELS[modelId];
255
242
  if (!model)
256
243
  continue;
257
- const selected = modelId === selectedModel ? this.theme.accent(' ◀ current') : '';
244
+ const isCurrent = modelId === selectedModel;
245
+ const marker = isCurrent ? this.theme.accent('●') : this.theme.dim('○');
246
+ const name = isCurrent ? this.theme.bold(model.name) : this.theme.muted(model.name);
258
247
  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}`);
248
+ const price = isFree ? this.theme.success('free') : this.theme.muted(`$${model.inputPrice}/${model.outputPrice}`);
249
+ const ctx = this.theme.dim(`${(model.contextWindow / 1000).toFixed(0)}K`);
250
+ console.log(` ${marker} ${name.padEnd(36)} ${price.padEnd(14)} ${ctx}`);
262
251
  }
263
252
  console.log();
264
253
  }
265
254
  }
266
- /**
267
- * Print agent list
268
- */
255
+ // ── Agent List ──────────────────────────────────────────
269
256
  agentList(agents) {
270
- console.log(`\n ${this.theme.bold('Available Agents:')}\n`);
257
+ console.log();
258
+ console.log(` ${this.theme.bold('Agents')}`);
259
+ console.log(` ${this.theme.dim('─'.repeat(50))}`);
271
260
  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}`)}`);
261
+ console.log(` ${this.theme.accent('●')} ${this.theme.bold(agent.name.padEnd(12))} ${this.theme.muted(agent.description)}`);
275
262
  }
276
263
  console.log();
277
264
  }
265
+ // ── Diff Display (Claude Code style: + and - lines) ─────
266
+ diffAdd(line) {
267
+ console.log(` ${this.theme.diffAdd('+')} ${this.theme.diffAdd(line)}`);
268
+ }
269
+ diffRemove(line) {
270
+ console.log(` ${this.theme.diffRemove('-')} ${this.theme.diffRemove(line)}`);
271
+ }
272
+ diffContext(line) {
273
+ console.log(` ${this.theme.diffContext(' ')} ${this.theme.diffContext(line)}`);
274
+ }
275
+ diffHeader(file) {
276
+ console.log();
277
+ console.log(` ${this.theme.dim('───')} ${this.theme.path(file)} ${this.theme.dim('───')}`);
278
+ }
279
+ // ── Helpers ─────────────────────────────────────────────
280
+ truncate(str, maxLen) {
281
+ if (str.length <= maxLen)
282
+ return str;
283
+ return str.slice(0, maxLen - 1) + '…';
284
+ }
285
+ byteSize(content) {
286
+ const bytes = Buffer.byteLength(content, 'utf-8');
287
+ if (bytes < 1024)
288
+ return `${bytes}B`;
289
+ if (bytes < 1024 * 1024)
290
+ return `${(bytes / 1024).toFixed(1)}KB`;
291
+ return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
292
+ }
278
293
  }
279
294
  //# 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[];