erosolar-cli 1.7.14 → 1.7.15

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 (61) hide show
  1. package/dist/core/responseVerifier.d.ts +79 -0
  2. package/dist/core/responseVerifier.d.ts.map +1 -0
  3. package/dist/core/responseVerifier.js +443 -0
  4. package/dist/core/responseVerifier.js.map +1 -0
  5. package/dist/shell/interactiveShell.d.ts +5 -0
  6. package/dist/shell/interactiveShell.d.ts.map +1 -1
  7. package/dist/shell/interactiveShell.js +38 -0
  8. package/dist/shell/interactiveShell.js.map +1 -1
  9. package/dist/ui/ShellUIAdapter.d.ts +3 -0
  10. package/dist/ui/ShellUIAdapter.d.ts.map +1 -1
  11. package/dist/ui/ShellUIAdapter.js +4 -10
  12. package/dist/ui/ShellUIAdapter.js.map +1 -1
  13. package/dist/ui/persistentPrompt.d.ts +4 -0
  14. package/dist/ui/persistentPrompt.d.ts.map +1 -1
  15. package/dist/ui/persistentPrompt.js +10 -11
  16. package/dist/ui/persistentPrompt.js.map +1 -1
  17. package/package.json +1 -1
  18. package/dist/bin/core/agent.js +0 -362
  19. package/dist/bin/core/agentProfileManifest.js +0 -187
  20. package/dist/bin/core/agentProfiles.js +0 -34
  21. package/dist/bin/core/agentRulebook.js +0 -135
  22. package/dist/bin/core/agentSchemaLoader.js +0 -233
  23. package/dist/bin/core/contextManager.js +0 -412
  24. package/dist/bin/core/contextWindow.js +0 -122
  25. package/dist/bin/core/customCommands.js +0 -80
  26. package/dist/bin/core/errors/apiKeyErrors.js +0 -114
  27. package/dist/bin/core/errors/errorTypes.js +0 -340
  28. package/dist/bin/core/errors/safetyValidator.js +0 -304
  29. package/dist/bin/core/errors.js +0 -32
  30. package/dist/bin/core/modelDiscovery.js +0 -755
  31. package/dist/bin/core/preferences.js +0 -224
  32. package/dist/bin/core/schemaValidator.js +0 -92
  33. package/dist/bin/core/secretStore.js +0 -199
  34. package/dist/bin/core/sessionStore.js +0 -187
  35. package/dist/bin/core/toolRuntime.js +0 -290
  36. package/dist/bin/core/types.js +0 -1
  37. package/dist/bin/shell/bracketedPasteManager.js +0 -350
  38. package/dist/bin/shell/fileChangeTracker.js +0 -65
  39. package/dist/bin/shell/interactiveShell.js +0 -2908
  40. package/dist/bin/shell/liveStatus.js +0 -78
  41. package/dist/bin/shell/shellApp.js +0 -290
  42. package/dist/bin/shell/systemPrompt.js +0 -60
  43. package/dist/bin/shell/updateManager.js +0 -108
  44. package/dist/bin/ui/ShellUIAdapter.js +0 -459
  45. package/dist/bin/ui/UnifiedUIController.js +0 -183
  46. package/dist/bin/ui/animation/AnimationScheduler.js +0 -430
  47. package/dist/bin/ui/codeHighlighter.js +0 -854
  48. package/dist/bin/ui/designSystem.js +0 -121
  49. package/dist/bin/ui/display.js +0 -1222
  50. package/dist/bin/ui/interrupts/InterruptManager.js +0 -437
  51. package/dist/bin/ui/layout.js +0 -139
  52. package/dist/bin/ui/orchestration/StatusOrchestrator.js +0 -403
  53. package/dist/bin/ui/outputMode.js +0 -38
  54. package/dist/bin/ui/persistentPrompt.js +0 -183
  55. package/dist/bin/ui/richText.js +0 -338
  56. package/dist/bin/ui/shortcutsHelp.js +0 -87
  57. package/dist/bin/ui/telemetry/UITelemetry.js +0 -443
  58. package/dist/bin/ui/textHighlighter.js +0 -210
  59. package/dist/bin/ui/theme.js +0 -116
  60. package/dist/bin/ui/toolDisplay.js +0 -423
  61. package/dist/bin/ui/toolDisplayAdapter.js +0 -357
@@ -1,338 +0,0 @@
1
- import { icons, theme } from './theme.js';
2
- import { getContentWidth, measure, normalizePanelWidth, renderPanel, wrapParagraph, wrapPreformatted, } from './layout.js';
3
- import { highlightAndWrapCode } from './codeHighlighter.js';
4
- import { isPlainOutputMode } from './outputMode.js';
5
- export function formatRichContent(content, width) {
6
- const blocks = parseBlocks(content);
7
- const lines = [];
8
- for (const block of blocks) {
9
- let blockLines = [];
10
- switch (block.type) {
11
- case 'paragraph': {
12
- const formatted = formatInlineText(block.text);
13
- blockLines = wrapParagraph(formatted, width);
14
- break;
15
- }
16
- case 'list':
17
- blockLines = formatList(block.items, width);
18
- break;
19
- case 'code':
20
- blockLines = formatCodeBlock(block.content, width, block.language);
21
- break;
22
- case 'diff':
23
- blockLines = formatDiffBlock(block.content, width);
24
- break;
25
- case 'heading':
26
- blockLines = formatHeadingBlock(block, width);
27
- break;
28
- case 'quote':
29
- blockLines = formatQuoteBlock(block.lines, width);
30
- break;
31
- case 'divider':
32
- blockLines = [formatDivider(width)];
33
- break;
34
- default:
35
- blockLines = [];
36
- }
37
- if (!blockLines.length) {
38
- continue;
39
- }
40
- if (lines.length) {
41
- const lastLine = lines[lines.length - 1];
42
- if (lastLine?.trim()) {
43
- lines.push('');
44
- }
45
- }
46
- lines.push(...blockLines);
47
- }
48
- while (lines.length) {
49
- const lastLine = lines[lines.length - 1];
50
- if (lastLine?.trim()) {
51
- break;
52
- }
53
- lines.pop();
54
- }
55
- return lines;
56
- }
57
- export function renderMessagePanel(content, options) {
58
- const width = normalizePanelWidth(options.width ?? getContentWidth());
59
- const lines = formatRichContent(content, width);
60
- return renderPanel(lines, { ...options, width });
61
- }
62
- export function renderMessageBody(content, width) {
63
- const normalizedWidth = normalizePanelWidth(width ?? getContentWidth());
64
- const lines = formatRichContent(content, normalizedWidth);
65
- return lines.join('\n');
66
- }
67
- export function formatDiffBlock(diff, width) {
68
- const lines = diff.replace(/\t/g, ' ').split('\n');
69
- const result = [];
70
- for (const line of lines) {
71
- if (!line.trim()) {
72
- result.push('');
73
- continue;
74
- }
75
- const color = pickDiffColor(line);
76
- const chunks = wrapPreformatted(line, width);
77
- chunks.forEach((chunk) => result.push(color(chunk)));
78
- }
79
- return result;
80
- }
81
- function parseBlocks(content) {
82
- const blocks = [];
83
- const lines = content.split('\n');
84
- let fence = null;
85
- let paragraph = [];
86
- let blockquote = null;
87
- const flushParagraph = () => {
88
- if (!paragraph.length) {
89
- return;
90
- }
91
- const merged = paragraph.join('\n');
92
- const trimmedLines = merged
93
- .split('\n')
94
- .map((line) => line.trim())
95
- .filter(Boolean);
96
- if (!trimmedLines.length) {
97
- paragraph = [];
98
- return;
99
- }
100
- const isList = trimmedLines.every((line) => /^(\*|-|•|\d+\.)\s+/.test(line));
101
- if (isList) {
102
- blocks.push({
103
- type: 'list',
104
- items: trimmedLines.map((line) => line.replace(/^(\*|-|•|\d+\.)\s+/, '')),
105
- });
106
- }
107
- else {
108
- blocks.push({ type: 'paragraph', text: trimmedLines.join(' ') });
109
- }
110
- paragraph = [];
111
- };
112
- const flushBlockquote = () => {
113
- if (!blockquote?.length) {
114
- blockquote = null;
115
- return;
116
- }
117
- blocks.push({ type: 'quote', lines: blockquote });
118
- blockquote = null;
119
- };
120
- for (const line of lines) {
121
- if (line.trimStart().startsWith('```')) {
122
- const raw = line.trim();
123
- if (fence) {
124
- blocks.push(fence.language.includes('diff')
125
- ? { type: 'diff', content: fence.buffer.join('\n') }
126
- : { type: 'code', content: fence.buffer.join('\n'), language: fence.language });
127
- fence = null;
128
- continue;
129
- }
130
- flushParagraph();
131
- flushBlockquote();
132
- const language = raw.slice(3).trim().toLowerCase();
133
- fence = { language, buffer: [] };
134
- continue;
135
- }
136
- if (fence) {
137
- fence.buffer.push(line);
138
- continue;
139
- }
140
- const trimmed = line.trim();
141
- if (!trimmed) {
142
- flushParagraph();
143
- flushBlockquote();
144
- continue;
145
- }
146
- const quoteMatch = line.match(/^\s*>\s?(.*)$/);
147
- if (quoteMatch) {
148
- flushParagraph();
149
- blockquote = blockquote ?? [];
150
- blockquote.push(quoteMatch[1] ?? '');
151
- continue;
152
- }
153
- flushBlockquote();
154
- const headingMatch = trimmed.match(/^(#{1,6})\s+(.*)$/);
155
- if (headingMatch) {
156
- flushParagraph();
157
- const hashes = headingMatch[1] ?? '';
158
- const text = headingMatch[2] ?? '';
159
- blocks.push({ type: 'heading', level: hashes.length, text: text.trim() });
160
- continue;
161
- }
162
- if (/^(-{3,}|_{3,}|\*{3,})$/.test(trimmed)) {
163
- flushParagraph();
164
- blocks.push({ type: 'divider' });
165
- continue;
166
- }
167
- paragraph.push(line);
168
- }
169
- flushParagraph();
170
- flushBlockquote();
171
- return blocks;
172
- }
173
- function formatList(items, width) {
174
- const lines = [];
175
- const bullet = theme.secondary(`${icons.bullet} `);
176
- const bulletWidth = measure(`${icons.bullet} `);
177
- const contentWidth = Math.max(10, width - bulletWidth);
178
- for (const item of items) {
179
- const formatted = formatInlineText(item);
180
- const wrapped = wrapParagraph(formatted, contentWidth);
181
- wrapped.forEach((segment, index) => {
182
- if (index === 0) {
183
- lines.push(`${bullet}${segment}`);
184
- }
185
- else {
186
- lines.push(`${' '.repeat(bulletWidth)}${segment}`);
187
- }
188
- });
189
- }
190
- return lines;
191
- }
192
- function formatCodeBlock(code, width, language) {
193
- const gutterRaw = isPlainOutputMode() ? '' : '│ ';
194
- const gutter = theme.ui.muted(gutterRaw);
195
- const available = Math.max(16, width - measure(gutterRaw));
196
- const { lines, languageLabel } = highlightAndWrapCode(code, language, available);
197
- const headerLabel = (languageLabel ?? 'CODE').toUpperCase();
198
- const result = [];
199
- if (isPlainOutputMode()) {
200
- result.push(theme.ui.muted(`[${headerLabel}]`));
201
- for (const line of lines) {
202
- result.push(line);
203
- }
204
- }
205
- else {
206
- result.push(`${gutter}${theme.ui.muted(buildCodeDivider(headerLabel, available))}`);
207
- for (const line of lines) {
208
- result.push(`${gutter}${line}`);
209
- }
210
- }
211
- return result;
212
- }
213
- function formatHeadingBlock(block, width) {
214
- const wrapped = wrapParagraph(formatInlineText(block.text), width);
215
- if (!wrapped.length) {
216
- return [];
217
- }
218
- const accent = pickHeadingAccent(block.level);
219
- const content = wrapped.map((line) => accent(theme.bold(line)));
220
- if (block.level <= 2 && !isPlainOutputMode()) {
221
- content.push(accent('─'.repeat(width)));
222
- }
223
- return content;
224
- }
225
- function formatQuoteBlock(lines, width) {
226
- if (!lines.length) {
227
- return [];
228
- }
229
- const gutterText = isPlainOutputMode() ? '> ' : '│ ';
230
- const gutter = theme.ui.muted(gutterText);
231
- const available = Math.max(12, width - measure(gutterText));
232
- const result = [];
233
- for (const line of lines) {
234
- if (!line.trim()) {
235
- result.push(gutter);
236
- continue;
237
- }
238
- const wrapped = wrapParagraph(formatInlineText(line), available);
239
- wrapped.forEach((segment) => {
240
- result.push(`${gutter}${segment}`);
241
- });
242
- }
243
- return result;
244
- }
245
- function formatDivider(width) {
246
- if (isPlainOutputMode()) {
247
- return theme.ui.muted('---');
248
- }
249
- return theme.ui.muted('─'.repeat(width));
250
- }
251
- function buildCodeDivider(label, width) {
252
- const normalized = label.trim() || 'CODE';
253
- const targetWidth = Math.max(8, width);
254
- const title = ` ${normalized} `;
255
- if (title.length >= targetWidth) {
256
- return title.slice(0, targetWidth);
257
- }
258
- const remaining = targetWidth - title.length;
259
- const left = '─'.repeat(Math.floor(remaining / 2));
260
- const right = '─'.repeat(remaining - left.length);
261
- return `${left}${title}${right}`;
262
- }
263
- function pickDiffColor(line) {
264
- if (line.startsWith('+++') || line.startsWith('---')) {
265
- return theme.diff.header;
266
- }
267
- if (line.startsWith('@@')) {
268
- return theme.diff.hunk;
269
- }
270
- if (line.startsWith('+')) {
271
- return theme.diff.added;
272
- }
273
- if (line.startsWith('-')) {
274
- return theme.diff.removed;
275
- }
276
- if (line.startsWith('diff')) {
277
- return theme.diff.meta;
278
- }
279
- return theme.ui.text;
280
- }
281
- function formatInlineText(text) {
282
- if (!text) {
283
- return '';
284
- }
285
- const codeSpans = [];
286
- const linkSpans = [];
287
- const LINK_PLACEHOLDER = '\u0001';
288
- let result = text.replace(/`([^`]+)`/g, (_, inner) => {
289
- codeSpans.push(inner);
290
- return `\u0000${codeSpans.length - 1}\u0000`;
291
- });
292
- const formatBold = (_match, value) => theme.bold(value);
293
- result = result.replace(/\*\*(.+?)\*\*/g, formatBold);
294
- result = result.replace(/__(.+?)__/g, formatBold);
295
- const formatItalics = (_match, value) => theme.italic(value);
296
- result = result.replace(/(?<!\*)\*(?!\*)([^*]+?)(?<!\*)\*(?!\*)/g, formatItalics);
297
- result = result.replace(/(?<!_)_(?!_)([^_]+?)(?<!_)_(?!_)/g, formatItalics);
298
- result = result.replace(/~~(.+?)~~/g, (_match, value) => theme.dim(value));
299
- result = result.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_match, label, url) => {
300
- linkSpans.push(formatMarkdownLink(label, url));
301
- return `${LINK_PLACEHOLDER}${linkSpans.length - 1}${LINK_PLACEHOLDER}`;
302
- });
303
- result = result.replace(/(\bhttps?:\/\/[^\s)]+)([)\]}>,.;:!?"]*)/g, (_match, url, trailing = '') => {
304
- linkSpans.push(`${formatBareLink(url)}${trailing}`);
305
- return `${LINK_PLACEHOLDER}${linkSpans.length - 1}${LINK_PLACEHOLDER}`;
306
- });
307
- result = result.replace(new RegExp(`${LINK_PLACEHOLDER}(\\d+)${LINK_PLACEHOLDER}`, 'g'), (_match, index) => linkSpans[Number.parseInt(index, 10)] ?? '');
308
- result = result.replace(/\u0000(\d+)\u0000/g, (_match, index) => formatInlineCode(codeSpans[Number.parseInt(index, 10)] ?? ''));
309
- return result;
310
- }
311
- function formatInlineCode(value) {
312
- const normalized = value.length ? value.trim() : value;
313
- const display = normalized.length ? normalized : value;
314
- const snippet = display.replace(/\s+/g, ' ');
315
- return theme.ui.background(theme.ui.text(` ${snippet} `));
316
- }
317
- function formatMarkdownLink(label, url) {
318
- const cleanUrl = url.trim();
319
- const cleanLabel = label.trim() || cleanUrl;
320
- const labelColor = theme.link?.label ?? theme.secondary;
321
- const urlColor = theme.link?.url ?? theme.info;
322
- const styledLabel = labelColor(cleanLabel);
323
- const styledUrl = urlColor(`(${cleanUrl})`);
324
- return `${styledLabel} ${styledUrl}`;
325
- }
326
- function formatBareLink(url) {
327
- const colorize = theme.link?.url ?? theme.info;
328
- return colorize(url.trim());
329
- }
330
- function pickHeadingAccent(level) {
331
- if (level <= 1) {
332
- return theme.primary;
333
- }
334
- if (level === 2) {
335
- return theme.secondary;
336
- }
337
- return theme.assistant;
338
- }
@@ -1,87 +0,0 @@
1
- /**
2
- * Keyboard Shortcuts Help Display (Claude Code style)
3
- */
4
- import { theme } from './theme.js';
5
- import { getTerminalColumns } from './layout.js';
6
- const EROSOLAR_SHORTCUTS = [
7
- {
8
- title: 'Navigation',
9
- shortcuts: [
10
- { keys: 'ctrl+c', description: 'Cancel current operation' },
11
- { keys: 'ctrl+d', description: 'Exit (when input is empty)' },
12
- { keys: 'up/down', description: 'Navigate command history' },
13
- ],
14
- },
15
- {
16
- title: 'Editing',
17
- shortcuts: [
18
- { keys: 'ctrl+a', description: 'Move to start of line' },
19
- { keys: 'ctrl+e', description: 'Move to end of line' },
20
- { keys: 'ctrl+k', description: 'Delete to end of line' },
21
- { keys: 'ctrl+u', description: 'Delete to start of line' },
22
- { keys: 'ctrl+w', description: 'Delete previous word' },
23
- ],
24
- },
25
- {
26
- title: 'Composable Messages',
27
- shortcuts: [
28
- { keys: 'ctrl+g', description: 'Edit pasted content blocks' },
29
- { keys: 'shift+tab', description: 'Cycle paste preview options' },
30
- { keys: 'enter', description: 'Send message with blocks' },
31
- ],
32
- },
33
- {
34
- title: 'Special',
35
- shortcuts: [
36
- { keys: '/', description: 'Trigger slash commands' },
37
- { keys: '?', description: 'Show this help' },
38
- { keys: 'ctrl+o', description: 'Expand collapsed output' },
39
- ],
40
- },
41
- ];
42
- /**
43
- * Format keyboard shortcuts help in Claude Code style
44
- */
45
- export function formatShortcutsHelp() {
46
- const width = Math.min(getTerminalColumns(), 80);
47
- const lines = [];
48
- // Title
49
- lines.push('');
50
- lines.push(theme.gradient.primary('Keyboard Shortcuts'));
51
- lines.push(theme.ui.muted('─'.repeat(width - 1)));
52
- lines.push('');
53
- // Groups
54
- for (const group of EROSOLAR_SHORTCUTS) {
55
- lines.push(theme.bold(` ${group.title}`));
56
- lines.push('');
57
- for (const shortcut of group.shortcuts) {
58
- const keys = theme.info(shortcut.keys.padEnd(20));
59
- const desc = theme.ui.muted(shortcut.description);
60
- lines.push(` ${keys} ${desc}`);
61
- }
62
- lines.push('');
63
- }
64
- // Footer
65
- lines.push(theme.ui.muted('─'.repeat(width - 1)));
66
- lines.push(theme.ui.muted(' Press any key to continue...'));
67
- lines.push('');
68
- return lines.join('\n');
69
- }
70
- /**
71
- * Format inline shortcut hint (Claude Code style)
72
- */
73
- export function formatShortcutHint(keys, description) {
74
- return `${theme.info(keys)} ${theme.ui.muted(description)}`;
75
- }
76
- /**
77
- * Quick shortcuts reference (one-line)
78
- */
79
- export function formatQuickShortcuts() {
80
- const hints = [
81
- '? for help',
82
- '/ for commands',
83
- 'ctrl+c to cancel',
84
- 'ctrl+d to exit',
85
- ];
86
- return hints.map(h => theme.ui.muted(h)).join(' · ');
87
- }