osai-agent 4.2.42 → 4.2.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/agent/loop/tool-executor.js +1 -1
- package/src/commands/provider.js +4 -4
- package/src/commands/stop-subagent.js +2 -2
- package/src/tools/local.js +2 -2
- package/src/ui/components/DiffView.js +3 -3
- package/src/ui/components/Header.js +7 -7
- package/src/ui/components/HistoryPicker.js +2 -2
- package/src/ui/components/MessageHistory.js +25 -25
- package/src/ui/components/ModePicker.js +2 -2
- package/src/ui/components/ProviderMenu.js +2 -1
- package/src/ui/components/SavePicker.js +2 -2
- package/src/ui/components/SelectMenu.js +3 -3
- package/src/ui/components/SlashMenu.js +2 -2
- package/src/ui/components/SubagentPanel.js +6 -6
- package/src/ui/components/ToolExecution.js +2 -2
- package/src/ui/diff.js +21 -20
- package/src/utils/unicode.js +4 -1
package/package.json
CHANGED
|
@@ -386,7 +386,7 @@ export default {
|
|
|
386
386
|
const header = `Todos for ${scopeLine}`;
|
|
387
387
|
return {
|
|
388
388
|
success: true,
|
|
389
|
-
output: `${header}\n${'
|
|
389
|
+
output: `${header}\n${'-'.repeat(header.length)}\n${items.length === 0 ? 'No todos.' : items.map(t => `[${t.status === 'done' ? 'x' : ' '}] #${t.id} [${t.priority}] ${t.text}`).join('\n')}`,
|
|
390
390
|
todos: items,
|
|
391
391
|
stats: todoStore.getStats(toolCall.mode || this.mode),
|
|
392
392
|
};
|
package/src/commands/provider.js
CHANGED
|
@@ -3,7 +3,7 @@ import Conf from 'conf';
|
|
|
3
3
|
import inquirer from 'inquirer';
|
|
4
4
|
import ora from 'ora';
|
|
5
5
|
import { printError, printSuccess, printInfo, printNotLoggedIn } from '../ui/terminal.js';
|
|
6
|
-
import { isUnicode, DASH, WARN } from '../utils/unicode.js';
|
|
6
|
+
import { isUnicode, DASH, WARN, ARROW_LEFT } from '../utils/unicode.js';
|
|
7
7
|
import { toHttpUrl } from '../services/server-url.js';
|
|
8
8
|
import { encrypt, decrypt, deriveKey } from '../services/crypto.js';
|
|
9
9
|
import pkg from 'node-machine-id';
|
|
@@ -113,7 +113,7 @@ export const listProviders = async () => {
|
|
|
113
113
|
console.log(chalk.hex('#565f89')(' ' + DASH.repeat(48)));
|
|
114
114
|
|
|
115
115
|
for (const p of catalog) {
|
|
116
|
-
const activeMark = p.active ? chalk.green(' ' +
|
|
116
|
+
const activeMark = p.active ? chalk.green(' ' + ARROW_LEFT) : '';
|
|
117
117
|
const freeMark = p.free_tier ? chalk.green('Yes') : chalk.red('No ');
|
|
118
118
|
const name = p.id === active?.id ? chalk.white.bold(p.name) : chalk.white(p.name);
|
|
119
119
|
const sdk = p.sdk_type === 'anthropic' ? 'native ' : 'OpenAI ';
|
|
@@ -395,7 +395,7 @@ export const showProvider = async () => {
|
|
|
395
395
|
const all = getAllLocalProviders();
|
|
396
396
|
console.log();
|
|
397
397
|
console.log(chalk.hex('#7aa2f7').bold(' Local Provider Configuration'));
|
|
398
|
-
console.log(chalk.hex('#565f89')('
|
|
398
|
+
console.log(chalk.hex('#565f89')(' ' + DASH.repeat(40)));
|
|
399
399
|
if (all.length === 0) {
|
|
400
400
|
console.log(` ${chalk.gray('No providers configured.')}`);
|
|
401
401
|
console.log(` ${chalk.gray(' Use: osai-agent provider set <type> --key <key> --local')}`);
|
|
@@ -424,7 +424,7 @@ export const showProvider = async () => {
|
|
|
424
424
|
|
|
425
425
|
console.log();
|
|
426
426
|
console.log(chalk.hex('#7aa2f7').bold(' Provider Configuration'));
|
|
427
|
-
console.log(chalk.hex('#565f89')('
|
|
427
|
+
console.log(chalk.hex('#565f89')(' ' + DASH.repeat(32)));
|
|
428
428
|
|
|
429
429
|
if (data.type === 'osai') {
|
|
430
430
|
console.log(` ${chalk.white('Current provider :')} ${chalk.green('OS AI Agent')}`);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import Conf from 'conf';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
import boxen from 'boxen';
|
|
4
|
-
import { DOT, EMPTY } from '../utils/unicode.js';
|
|
4
|
+
import { DOT, EMPTY, TICK } from '../utils/unicode.js';
|
|
5
5
|
import { showConfig } from './config.js';
|
|
6
6
|
import { clearScreen, printError, printPanel } from '../ui/terminal.js';
|
|
7
7
|
import { logger } from '../utils/logger.js';
|
|
@@ -50,7 +50,7 @@ export const stopSubagent = async ({ server }) => {
|
|
|
50
50
|
}
|
|
51
51
|
const result = await response.json();
|
|
52
52
|
spinner.succeeded(result.message || 'Subagent stop requested');
|
|
53
|
-
console.log(chalk.green(
|
|
53
|
+
console.log(chalk.green(`${TICK} Subagent stop command sent successfully`));
|
|
54
54
|
} catch (error) {
|
|
55
55
|
spinner.fail(`Failed to stop subagent: ${error.message}`);
|
|
56
56
|
console.error(chalk.red(`Error: ${error.message}`));
|
package/src/tools/local.js
CHANGED
|
@@ -8,7 +8,7 @@ import os from 'os';
|
|
|
8
8
|
import { DEFAULTS, TOOLS } from '../utils/constants.js';
|
|
9
9
|
import { logger } from '../utils/logger.js';
|
|
10
10
|
import { searchDDG, searchSerpAPI, searchTavily, searchDDGHttp, formatSearchOutput } from './search-providers.js';
|
|
11
|
-
import { TREE_BRANCH, TREE_LAST, TREE_VLINE, TREE_SPACE } from '../utils/unicode.js';
|
|
11
|
+
import { TREE_BRANCH, TREE_LAST, TREE_VLINE, TREE_SPACE, TICK } from '../utils/unicode.js';
|
|
12
12
|
import { extractExports, extractLocalImports } from '../parser/dependencies.js';
|
|
13
13
|
|
|
14
14
|
const execAsync = promisify(exec);
|
|
@@ -1274,7 +1274,7 @@ export const diagPostEdit = async (targetPath, lang = 'auto') => {
|
|
|
1274
1274
|
const output = [stdout, stderr].filter(Boolean).join('\n').trim();
|
|
1275
1275
|
|
|
1276
1276
|
if (!output || output.includes('Found 0 errors')) {
|
|
1277
|
-
return { success: true, output: `[DIAG:${detected.toUpperCase()}]
|
|
1277
|
+
return { success: true, output: `[DIAG:${detected.toUpperCase()}] ${TICK} No errors detected.` };
|
|
1278
1278
|
}
|
|
1279
1279
|
|
|
1280
1280
|
const lines = output.split('\n').slice(0, 30);
|
|
@@ -3,7 +3,7 @@ import { Box, Text } from 'ink';
|
|
|
3
3
|
import { h } from '../h.js';
|
|
4
4
|
import { buildDiff, collapseContext, langFromPath } from '../diff.js';
|
|
5
5
|
import { highlightCode } from '../../parser/markdown.js';
|
|
6
|
-
import { isUnicode, CROSS } from '../../utils/unicode.js';
|
|
6
|
+
import { isUnicode, CROSS, ELLIPSIS } from '../../utils/unicode.js';
|
|
7
7
|
|
|
8
8
|
const C = {
|
|
9
9
|
removedBg: '#2d1010',
|
|
@@ -141,7 +141,7 @@ export function NewFileDiff({ filePath, content }) {
|
|
|
141
141
|
),
|
|
142
142
|
h(Box, { flexDirection: 'column', paddingLeft: 2, borderStyle: 'round', borderColor: C.border },
|
|
143
143
|
...Array.from({ length: shown }, (_, i) => {
|
|
144
|
-
const raw = lines[i].length > innerW ? lines[i].slice(0, innerW - 1) +
|
|
144
|
+
const raw = lines[i].length > innerW ? lines[i].slice(0, innerW - 1) + ELLIPSIS : lines[i];
|
|
145
145
|
return h(Box, { key: i, paddingLeft: 1 },
|
|
146
146
|
h(Text, { color: C.lineNumFg }, `${String(i + 1).padStart(lnW)} `),
|
|
147
147
|
h(Box, { backgroundColor: C.addedBg },
|
|
@@ -173,7 +173,7 @@ export function AppendFileDiff({ filePath, content }) {
|
|
|
173
173
|
),
|
|
174
174
|
h(Box, { flexDirection: 'column', paddingLeft: 2, borderStyle: 'round', borderColor: C.border },
|
|
175
175
|
...shown.map((line, i) => {
|
|
176
|
-
const raw = line.length > innerW ? line.slice(0, innerW - 1) +
|
|
176
|
+
const raw = line.length > innerW ? line.slice(0, innerW - 1) + ELLIPSIS : line;
|
|
177
177
|
return h(Box, { key: i, paddingLeft: 1 },
|
|
178
178
|
h(Text, { color: C.lineNumFg }, `${String(i + 1).padStart(lnW)} `),
|
|
179
179
|
h(Box, { backgroundColor: C.addedBg },
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Box, Text } from 'ink';
|
|
2
2
|
import { h } from '../h.js';
|
|
3
|
-
import { isUnicode, DOT, EMPTY, HEADER_LOGO_L, HEADER_LOGO_M, HEADER_LOGO_R, BAR } from '../../utils/unicode.js';
|
|
3
|
+
import { isUnicode, DOT, EMPTY, HEADER_LOGO_L, HEADER_LOGO_M, HEADER_LOGO_R, BAR, BOX_TL, BOX_TR, BOX_BL, BOX_BR, BOX_H, ELLIPSIS } from '../../utils/unicode.js';
|
|
4
4
|
import { ENABLE_UI_ANIMATIONS, useAnimationFrame } from '../animation.js';
|
|
5
5
|
|
|
6
6
|
const chunkLength = (chunks) => chunks.reduce((sum, chunk) => sum + String(chunk.text || '').length, 0);
|
|
@@ -9,7 +9,7 @@ const makeItem = (chunks) => ({ chunks, width: chunkLength(chunks) });
|
|
|
9
9
|
|
|
10
10
|
function truncateChunks(chunks, maxWidth) {
|
|
11
11
|
if (chunkLength(chunks) <= maxWidth) return chunks;
|
|
12
|
-
if (maxWidth <= 1) return [{ text:
|
|
12
|
+
if (maxWidth <= 1) return [{ text: ELLIPSIS, color: chunks[0]?.color || 'white' }];
|
|
13
13
|
|
|
14
14
|
const out = [];
|
|
15
15
|
let remaining = maxWidth;
|
|
@@ -21,7 +21,7 @@ function truncateChunks(chunks, maxWidth) {
|
|
|
21
21
|
remaining -= text.length;
|
|
22
22
|
continue;
|
|
23
23
|
}
|
|
24
|
-
out.push({ ...chunk, text: text.slice(0, Math.max(0, remaining - 1)) +
|
|
24
|
+
out.push({ ...chunk, text: text.slice(0, Math.max(0, remaining - 1)) + ELLIPSIS });
|
|
25
25
|
remaining = 0;
|
|
26
26
|
}
|
|
27
27
|
return out;
|
|
@@ -128,7 +128,7 @@ export function Header({ mode, device, isConnected, isLocal, provider, execution
|
|
|
128
128
|
const padding = ' '.repeat(Math.max(0, contentWidth - lineWidth));
|
|
129
129
|
|
|
130
130
|
return h(Box, { key: `header_line_${lineIndex}`, flexDirection: 'row', width: '100%' },
|
|
131
|
-
h(Text, { color: 'white' },
|
|
131
|
+
h(Text, { color: 'white' }, BAR),
|
|
132
132
|
lineIndex > 0 ? h(Text, { color: '#3b4261' }, ' ') : null,
|
|
133
133
|
line.map((item, itemIndex) =>
|
|
134
134
|
h(Text, { key: `header_item_${lineIndex}_${itemIndex}` },
|
|
@@ -142,7 +142,7 @@ export function Header({ mode, device, isConnected, isLocal, provider, execution
|
|
|
142
142
|
)
|
|
143
143
|
),
|
|
144
144
|
h(Text, {}, padding),
|
|
145
|
-
h(Text, { color: 'white' },
|
|
145
|
+
h(Text, { color: 'white' }, BAR)
|
|
146
146
|
);
|
|
147
147
|
};
|
|
148
148
|
|
|
@@ -151,8 +151,8 @@ export function Header({ mode, device, isConnected, isLocal, provider, execution
|
|
|
151
151
|
width: '100%',
|
|
152
152
|
flexDirection: 'column',
|
|
153
153
|
},
|
|
154
|
-
h(Text, { color: 'white' },
|
|
154
|
+
h(Text, { color: 'white' }, `${BOX_TL}${BOX_H.repeat(contentWidth)}${BOX_TR}`),
|
|
155
155
|
lines.map(renderLine),
|
|
156
|
-
h(Text, { color: 'white' },
|
|
156
|
+
h(Text, { color: 'white' }, `${BOX_BL}${BOX_H.repeat(contentWidth)}${BOX_BR}`)
|
|
157
157
|
);
|
|
158
158
|
}
|
|
@@ -3,7 +3,7 @@ import { Box, Text, useInput, useWindowSize } from 'ink';
|
|
|
3
3
|
import { h } from '../h.js';
|
|
4
4
|
import { InputShell } from './InputShell.js';
|
|
5
5
|
import { isOnlySgrMouseInput } from '../mouse-scroll.js';
|
|
6
|
-
import { ARROW, CLOUD } from '../../utils/unicode.js';
|
|
6
|
+
import { ARROW, CLOUD, DASH } from '../../utils/unicode.js';
|
|
7
7
|
|
|
8
8
|
export function HistoryPicker({ sessions, visible, onSelect, onCancel }) {
|
|
9
9
|
const [cursor, setCursor] = useState(0);
|
|
@@ -80,7 +80,7 @@ export function HistoryPicker({ sessions, visible, onSelect, onCancel }) {
|
|
|
80
80
|
}
|
|
81
81
|
const visibleItems = filtered.slice(startIdx, startIdx + maxVis);
|
|
82
82
|
|
|
83
|
-
const separator =
|
|
83
|
+
const separator = DASH.repeat(52);
|
|
84
84
|
|
|
85
85
|
return h(
|
|
86
86
|
Box,
|
|
@@ -6,7 +6,7 @@ import { highlightCode } from '../../parser/markdown.js';
|
|
|
6
6
|
import { EditFileDiff, NewFileDiff, AppendFileDiff, DeleteFileDiff } from './DiffView.js';
|
|
7
7
|
import { ENABLE_UI_ANIMATIONS, useAnimationFrame } from '../animation.js';
|
|
8
8
|
import { SubagentPanel } from './SubagentPanel.js';
|
|
9
|
-
import { isUnicode, TICK, DOT, EMPTY, ARROW, SPINNER_BRAILLE } from '../../utils/unicode.js';
|
|
9
|
+
import { isUnicode, TICK, CROSS, DOT, EMPTY, ARROW, SPINNER_BRAILLE, BULLET, ELLIPSIS, BAR, DASH, BQ_LINE, LOADING } from '../../utils/unicode.js';
|
|
10
10
|
const stripAnsi = (s) => (s || '').replace(/\x1b\[[0-9;]*m/g, '').replace(/\x1b\]8;;[^\x1b]*\x1b\\/g, '');
|
|
11
11
|
const visibleLen = (s) => stripAnsi(s).length;
|
|
12
12
|
|
|
@@ -342,8 +342,8 @@ const ToolSpinner = React.memo(({ name, toolCall, done, animate = true }) => {
|
|
|
342
342
|
if (writeLabel) {
|
|
343
343
|
const dots = !done && animate && ENABLE_UI_ANIMATIONS ? WRITING_DOTS[frame % WRITING_DOTS.length] : '';
|
|
344
344
|
return h(Box, { paddingLeft: 2, paddingY: 0 },
|
|
345
|
-
h(Text, { color: done ? '#9ece6a' : '#7aa2f7' }, done ? '
|
|
346
|
-
h(Text, { color: '#ffffff' }, '
|
|
345
|
+
h(Text, { color: done ? '#9ece6a' : '#7aa2f7' }, done ? ' ' + TICK + ' ' : (animate && ENABLE_UI_ANIMATIONS ? ` ${SPINNER_FRAMES[frame % SPINNER_FRAMES.length]} ` : ' ' + ELLIPSIS + ' ')),
|
|
346
|
+
h(Text, { color: '#ffffff' }, BULLET + ' '),
|
|
347
347
|
h(Text, { color, bold: true }, writeLabel),
|
|
348
348
|
h(Text, { color: '#565f89' }, done ? '' : dots)
|
|
349
349
|
);
|
|
@@ -352,16 +352,16 @@ const ToolSpinner = React.memo(({ name, toolCall, done, animate = true }) => {
|
|
|
352
352
|
if (readLabel) {
|
|
353
353
|
const dots = !done && animate && ENABLE_UI_ANIMATIONS ? READING_DOTS[frame % READING_DOTS.length] : '';
|
|
354
354
|
return h(Box, { paddingLeft: 2, paddingY: 0 },
|
|
355
|
-
h(Text, { color: done ? '#9ece6a' : '#7aa2f7' }, done ? '
|
|
356
|
-
h(Text, { color: '#ffffff' }, '
|
|
355
|
+
h(Text, { color: done ? '#9ece6a' : '#7aa2f7' }, done ? ' ' + TICK + ' ' : (animate && ENABLE_UI_ANIMATIONS ? ` ${SPINNER_FRAMES[frame % SPINNER_FRAMES.length]} ` : ' ' + ELLIPSIS + ' ')),
|
|
356
|
+
h(Text, { color: '#ffffff' }, BULLET + ' '),
|
|
357
357
|
h(Text, { color, bold: true }, readLabel),
|
|
358
358
|
h(Text, { color: '#ffffff' }, done ? '' : dots)
|
|
359
359
|
);
|
|
360
360
|
}
|
|
361
361
|
|
|
362
362
|
return h(Box, { paddingLeft: 2, paddingY: 0 },
|
|
363
|
-
h(Text, { color: done ? '#9ece6a' : '#7aa2f7' }, done ? '
|
|
364
|
-
h(Text, { color: '#ffffff' }, '
|
|
363
|
+
h(Text, { color: done ? '#9ece6a' : '#7aa2f7' }, done ? ' ' + TICK + ' ' : (animate && ENABLE_UI_ANIMATIONS ? ` ${SPINNER_FRAMES[frame % SPINNER_FRAMES.length]} ` : ' ' + ELLIPSIS + ' ')),
|
|
364
|
+
h(Text, { color: '#ffffff' }, BULLET + ' '),
|
|
365
365
|
h(Text, { color, bold: true }, name),
|
|
366
366
|
target.text ? h(Text, { color: '#565f89' }, ': ') : null,
|
|
367
367
|
target.text
|
|
@@ -378,8 +378,8 @@ const ContextSummarySpinner = React.memo(({ summaryEvent, done, animate = true }
|
|
|
378
378
|
const keepRecent = Number(summaryEvent?.keepRecent || 0);
|
|
379
379
|
|
|
380
380
|
return h(Box, { paddingLeft: 2, paddingY: 0 },
|
|
381
|
-
h(Text, { color: done ? '#9ece6a' : '#7aa2f7', bold: true }, done ? '
|
|
382
|
-
h(Text, { color: '#ffffff' }, '
|
|
381
|
+
h(Text, { color: done ? '#9ece6a' : '#7aa2f7', bold: true }, done ? ' ' + TICK + ' ' : (animate && ENABLE_UI_ANIMATIONS ? ` ${SPINNER_FRAMES[frame % SPINNER_FRAMES.length]} ` : ' ' + ELLIPSIS + ' ')),
|
|
382
|
+
h(Text, { color: '#ffffff' }, BULLET + ' '),
|
|
383
383
|
h(Text, { color: '#7dcfff', bold: true }, 'CONTEXT_SUMMARY'),
|
|
384
384
|
h(Text, { color: '#565f89' }, done
|
|
385
385
|
? `: summarized ${summarizeCount} messages, kept ${keepRecent} recent`
|
|
@@ -392,8 +392,8 @@ const ContextSummaryResult = React.memo(({ doneEvent }) => {
|
|
|
392
392
|
const summarized = Number(doneEvent?.summarizedMessages || 0);
|
|
393
393
|
const remaining = Number(doneEvent?.remainingMessages || 0);
|
|
394
394
|
return h(Box, { paddingLeft: 2, paddingY: 0 },
|
|
395
|
-
h(Text, { color: '#9ece6a', bold: true }, '
|
|
396
|
-
h(Text, { color: '#ffffff' }, '
|
|
395
|
+
h(Text, { color: '#9ece6a', bold: true }, ' ' + TICK + ' '),
|
|
396
|
+
h(Text, { color: '#ffffff' }, BULLET + ' '),
|
|
397
397
|
h(Text, { color: '#7dcfff', bold: true }, 'CONTEXT_SUMMARY'),
|
|
398
398
|
h(Text, { color: '#565f89' }, `: completed (${summarized} summarized, ${remaining} messages now in context)`)
|
|
399
399
|
);
|
|
@@ -422,7 +422,7 @@ const SearchResults = React.memo(({ results }) => {
|
|
|
422
422
|
|
|
423
423
|
const ToolResultEvent = React.memo(({ name, success, output, toolCall, results, outputIndex, expandedOutputIndexes }) => {
|
|
424
424
|
const color = getToolColor(name);
|
|
425
|
-
const label = success ?
|
|
425
|
+
const label = success ? TICK : CROSS;
|
|
426
426
|
const labelColor = success ? '#9ece6a' : '#f7768e';
|
|
427
427
|
const target = formatTarget(toolCall);
|
|
428
428
|
const writeLabel = WRITE_TOOLS.has(name) ? getWriteActionLabel(name, toolCall, success) : null;
|
|
@@ -469,7 +469,7 @@ const ToolResultEvent = React.memo(({ name, success, output, toolCall, results,
|
|
|
469
469
|
return h(Box, { flexDirection: 'column', paddingLeft: 2, paddingY: 0 },
|
|
470
470
|
h(Box,
|
|
471
471
|
h(Text, { color: labelColor, bold: true }, ` ${label} `),
|
|
472
|
-
h(Text, { color: '#ffffff' }, '
|
|
472
|
+
h(Text, { color: '#ffffff' }, BULLET + ' '),
|
|
473
473
|
writeLabel
|
|
474
474
|
? h(Text, { color }, writeLabel)
|
|
475
475
|
: readLabel
|
|
@@ -697,7 +697,7 @@ function renderContent(text) {
|
|
|
697
697
|
type: 'list',
|
|
698
698
|
ordered: false,
|
|
699
699
|
level: Math.floor((bulletMatch[1] || '').length / 2),
|
|
700
|
-
marker:
|
|
700
|
+
marker: BULLET,
|
|
701
701
|
content: bulletMatch[2] || ''
|
|
702
702
|
});
|
|
703
703
|
continue;
|
|
@@ -763,7 +763,7 @@ const TableBlock = React.memo(({ rows }) => {
|
|
|
763
763
|
const displayLen = visibleLen(value);
|
|
764
764
|
if (displayLen <= width) return value + ' '.repeat(Math.max(0, width - displayLen));
|
|
765
765
|
const plain = stripAnsi(value);
|
|
766
|
-
const cut = plain.slice(0, Math.max(1, width - 1)) +
|
|
766
|
+
const cut = plain.slice(0, Math.max(1, width - 1)) + ELLIPSIS;
|
|
767
767
|
return cut + ' '.repeat(Math.max(0, width - cut.length));
|
|
768
768
|
};
|
|
769
769
|
|
|
@@ -772,17 +772,17 @@ const TableBlock = React.memo(({ rows }) => {
|
|
|
772
772
|
if (row.raw.startsWith('__HIDDEN_')) {
|
|
773
773
|
const hidden = Number(row.raw.match(/__HIDDEN_(\d+)__/)?.[1] || 0);
|
|
774
774
|
return h(Text, { key: `tbl_hidden_${idx}`, color: '#565f89', italic: true },
|
|
775
|
-
`
|
|
775
|
+
` ${ELLIPSIS} ${hidden} ligne(s) cachée(s) pour fluidité du terminal ${ELLIPSIS}`);
|
|
776
776
|
}
|
|
777
777
|
if (isTableSeparator(row.raw)) {
|
|
778
|
-
const sep = widths.map(w =>
|
|
778
|
+
const sep = widths.map(w => DASH.repeat(w)).join(DASH + '+' + DASH);
|
|
779
779
|
return h(Text, { key: `tbl_sep_${idx}`, color: '#2a2e3f' }, ` ${sep}`);
|
|
780
780
|
}
|
|
781
781
|
const content = row.cells.map((cell, i) => {
|
|
782
782
|
const rendered = renderCellInline(cell || '');
|
|
783
783
|
const styled = idx === 0 ? chalk.bold.hex('#7dcfff')(rendered) : chalk.hex('#c0caf5')(rendered);
|
|
784
784
|
return pad(styled, widths[i]);
|
|
785
|
-
}).join('
|
|
785
|
+
}).join(' ' + BAR + ' ');
|
|
786
786
|
return h(Text, { key: `tbl_row_${idx}`, ansi: true }, ` ${content}`);
|
|
787
787
|
})
|
|
788
788
|
);
|
|
@@ -795,8 +795,8 @@ const AnimatedToolIndicator = React.memo(({ tool, content, color, events, animat
|
|
|
795
795
|
const frame = useAnimationFrame(isAnimating);
|
|
796
796
|
|
|
797
797
|
return h(Box, { paddingLeft: 2 },
|
|
798
|
-
h(Text, { color: isAnimating ? '#7aa2f7' : '#9ece6a', bold: true }, isAnimating ? (ENABLE_UI_ANIMATIONS ? ` ${SPINNER_FRAMES[frame % SPINNER_FRAMES.length]} ` : '
|
|
799
|
-
h(Text, { color: '#ffffff' }, '
|
|
798
|
+
h(Text, { color: isAnimating ? '#7aa2f7' : '#9ece6a', bold: true }, isAnimating ? (ENABLE_UI_ANIMATIONS ? ` ${SPINNER_FRAMES[frame % SPINNER_FRAMES.length]} ` : ' ' + ELLIPSIS + ' ') : ' ' + TICK + ' '),
|
|
799
|
+
h(Text, { color: '#ffffff' }, BULLET + ' '),
|
|
800
800
|
h(Text, { color, bold: true }, tool),
|
|
801
801
|
content ? h(Text, { color: '#565f89' }, `: ${content}`) : null
|
|
802
802
|
);
|
|
@@ -841,10 +841,10 @@ const TextContent = React.memo(({ content, events, animate = true }) => {
|
|
|
841
841
|
h(Text, { color: '#9aa5ce', bold: true }, `#### ${part.content}`)
|
|
842
842
|
);
|
|
843
843
|
case 'hr':
|
|
844
|
-
return h(Box, { key: i, paddingLeft: 2 }, h(Text, { color: '#2a2e3f' },
|
|
844
|
+
return h(Box, { key: i, paddingLeft: 2 }, h(Text, { color: '#2a2e3f' }, DASH.repeat(40)));
|
|
845
845
|
case 'quote':
|
|
846
846
|
return h(Box, { key: i, paddingLeft: 2 },
|
|
847
|
-
h(Text, { color: '#565f89' }, '
|
|
847
|
+
h(Text, { color: '#565f89' }, BQ_LINE + ' '),
|
|
848
848
|
h(InlineText, { text: part.content })
|
|
849
849
|
);
|
|
850
850
|
case 'list':
|
|
@@ -880,7 +880,7 @@ function hasMatchingContextSummaryEnd(events, startIndex, summaryEvent) {
|
|
|
880
880
|
|
|
881
881
|
function EventSeparator() {
|
|
882
882
|
return h(Box, { flexDirection: 'column', paddingY: 0 },
|
|
883
|
-
h(Text, { color: '#2a2e3f' }, ' o
|
|
883
|
+
h(Text, { color: '#2a2e3f' }, ' o' + DASH.repeat(41) + 'o')
|
|
884
884
|
);
|
|
885
885
|
}
|
|
886
886
|
|
|
@@ -982,14 +982,14 @@ function renderEvent(ev, i, events, expandedOutputIndexes, thoughtStreaming, exp
|
|
|
982
982
|
...items.map((t, j) => {
|
|
983
983
|
const isDone = t.status === 'done' || t.status === 'completed';
|
|
984
984
|
const isProgress = t.status === 'in_progress';
|
|
985
|
-
const icon = isDone ? TICK : isProgress ?
|
|
985
|
+
const icon = isDone ? TICK : isProgress ? LOADING : EMPTY;
|
|
986
986
|
const color = isDone ? '#73daca' : isProgress ? '#e0af68' : '#565f89';
|
|
987
987
|
return h(Box, { key: j, paddingLeft: 2 },
|
|
988
988
|
h(Text, { color }, `${icon} `),
|
|
989
989
|
h(Text, { color: '#c0caf5' }, t.text || t.description || ''),
|
|
990
990
|
);
|
|
991
991
|
}),
|
|
992
|
-
more > 0 ? h(Text, { key: 'more', color: '#565f89', dimColor: true }, `
|
|
992
|
+
more > 0 ? h(Text, { key: 'more', color: '#565f89', dimColor: true }, ` ${ELLIPSIS} and ${more} more`) : null,
|
|
993
993
|
);
|
|
994
994
|
}
|
|
995
995
|
case 'subagent': {
|
|
@@ -3,7 +3,7 @@ import { Box, Text, useInput, useWindowSize } from 'ink';
|
|
|
3
3
|
import { h } from '../h.js';
|
|
4
4
|
import { InputShell } from './InputShell.js';
|
|
5
5
|
import { isOnlySgrMouseInput } from '../mouse-scroll.js';
|
|
6
|
-
import { MODE_ICONS, ARROW, DOT, DASH } from '../../utils/unicode.js';
|
|
6
|
+
import { MODE_ICONS, ARROW, ARROW_LEFT, DOT, DASH } from '../../utils/unicode.js';
|
|
7
7
|
|
|
8
8
|
const ALL_MODES = [
|
|
9
9
|
{ name: 'GENERAL', desc: 'System administration mode', value: 'GENERAL' },
|
|
@@ -115,7 +115,7 @@ export function ModePicker({ visible, onSelect, onCancel, currentMode, currentEx
|
|
|
115
115
|
const isCurrent = m.value === currentMode || m.value === currentExecutionMode;
|
|
116
116
|
const icon = MODE_ICONS[m.value] || DOT;
|
|
117
117
|
const prefix = isHighlighted ? h(Text, { color: '#9ece6a' }, ' ' + ARROW + ' ') : h(Text, { color: '#3b3f52' }, ' ');
|
|
118
|
-
const currentMark = isCurrent ?
|
|
118
|
+
const currentMark = isCurrent ? ` ${ARROW_LEFT} current` : '';
|
|
119
119
|
|
|
120
120
|
return h(
|
|
121
121
|
Box,
|
|
@@ -3,6 +3,7 @@ import { Box, Text, useInput, useWindowSize } from 'ink';
|
|
|
3
3
|
import { h } from '../h.js';
|
|
4
4
|
import { InputShell } from './InputShell.js';
|
|
5
5
|
import { isOnlySgrMouseInput } from '../mouse-scroll.js';
|
|
6
|
+
import { DASH } from '../../utils/unicode.js';
|
|
6
7
|
|
|
7
8
|
const MAIN_ACTIONS = [
|
|
8
9
|
{ name: 'Select Provider', desc: 'Choose from the provider catalog', action: 'catalog' },
|
|
@@ -729,7 +730,7 @@ export function ProviderMenu({ visible, onSelect, onCancel, serverUrl, token, cu
|
|
|
729
730
|
|
|
730
731
|
if (!visible) return null;
|
|
731
732
|
|
|
732
|
-
const separator =
|
|
733
|
+
const separator = DASH.repeat(52);
|
|
733
734
|
const { rows } = useWindowSize();
|
|
734
735
|
|
|
735
736
|
// SETTING UP VIEW
|
|
@@ -2,7 +2,7 @@ import React, { useState, useEffect, useMemo } from 'react';
|
|
|
2
2
|
import { Box, Text, useInput } from 'ink';
|
|
3
3
|
import { h } from '../h.js';
|
|
4
4
|
import { isOnlySgrMouseInput } from '../mouse-scroll.js';
|
|
5
|
-
import { isUnicode, ARROW, CROSS, DASH } from '../../utils/unicode.js';
|
|
5
|
+
import { isUnicode, ARROW, CROSS, CLOUD, DASH } from '../../utils/unicode.js';
|
|
6
6
|
|
|
7
7
|
const OPTIONS = [
|
|
8
8
|
{ name: 'Local', desc: 'Save to local storage', value: 'local' },
|
|
@@ -82,7 +82,7 @@ export function SavePicker({ visible, onSelect, onCancel, hasCloud }) {
|
|
|
82
82
|
...filtered.map((o, i) => {
|
|
83
83
|
const isHL = i === cursor;
|
|
84
84
|
const prefix = isHL ? h(Text, { color: '#9ece6a' }, ' ' + ARROW + ' ') : h(Text, { color: '#3b3f52' }, ' ');
|
|
85
|
-
const icon = o.value === 'local' ? ' ' : o.value === 'cloud' ?
|
|
85
|
+
const icon = o.value === 'local' ? ' ' : o.value === 'cloud' ? `${CLOUD} ` : CROSS + ' ';
|
|
86
86
|
|
|
87
87
|
return h(Box, { key: i },
|
|
88
88
|
prefix,
|
|
@@ -3,7 +3,7 @@ import { Box, Text, useInput, useWindowSize } from 'ink';
|
|
|
3
3
|
import { h } from '../h.js';
|
|
4
4
|
import { InputShell } from './InputShell.js';
|
|
5
5
|
import { isOnlySgrMouseInput } from '../mouse-scroll.js';
|
|
6
|
-
import { ARROW } from '../../utils/unicode.js';
|
|
6
|
+
import { ARROW, ARROW_LEFT, DASH } from '../../utils/unicode.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Reusable interactive menu with:
|
|
@@ -119,7 +119,7 @@ export function SelectMenu({
|
|
|
119
119
|
}
|
|
120
120
|
const visibleItems = filtered.slice(startIdx, startIdx + maxVisibleItems);
|
|
121
121
|
|
|
122
|
-
const separator =
|
|
122
|
+
const separator = DASH.repeat(50);
|
|
123
123
|
|
|
124
124
|
return h(
|
|
125
125
|
Box,
|
|
@@ -147,7 +147,7 @@ export function SelectMenu({
|
|
|
147
147
|
const icon = isHighlighted ? h(Text, { color: '#9ece6a' }, ` ${ARROW} `) : h(Text, { color: '#3b3f52' }, ' ');
|
|
148
148
|
const label = item.label || item.cmd || item.name || '';
|
|
149
149
|
const desc = item.desc ? ` ${item.desc}` : '';
|
|
150
|
-
const mark = item.active ?
|
|
150
|
+
const mark = item.active ? ` ${ARROW_LEFT}` : '';
|
|
151
151
|
|
|
152
152
|
return h(
|
|
153
153
|
Box,
|
|
@@ -3,7 +3,7 @@ import { Box, Text, useInput, useWindowSize } from 'ink';
|
|
|
3
3
|
import { h } from '../h.js';
|
|
4
4
|
import { InputShell } from './InputShell.js';
|
|
5
5
|
import { isOnlySgrMouseInput } from '../mouse-scroll.js';
|
|
6
|
-
import { ARROW } from '../../utils/unicode.js';
|
|
6
|
+
import { ARROW, DASH } from '../../utils/unicode.js';
|
|
7
7
|
|
|
8
8
|
const COMMANDS = [
|
|
9
9
|
{ cmd: '/clear', desc: 'Clear displayed history', action: 'clear' },
|
|
@@ -98,7 +98,7 @@ export function SlashMenu({ visible, onSelect, onCancel }) {
|
|
|
98
98
|
}
|
|
99
99
|
const visibleItems = filtered.slice(startIdx, startIdx + maxVisible);
|
|
100
100
|
|
|
101
|
-
const separator =
|
|
101
|
+
const separator = DASH.repeat(52);
|
|
102
102
|
|
|
103
103
|
return h(
|
|
104
104
|
Box,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Box, Text } from 'ink';
|
|
2
2
|
import { h } from '../h.js';
|
|
3
3
|
import { ENABLE_UI_ANIMATIONS, useAnimationFrame } from '../animation.js';
|
|
4
|
-
import { TICK, CROSS, SPINNER_CIRCLE, DOT } from '../../utils/unicode.js';
|
|
4
|
+
import { TICK, CROSS, SPINNER_CIRCLE, DOT, DASH, TREE_MID, ELLIPSIS } from '../../utils/unicode.js';
|
|
5
5
|
|
|
6
6
|
const SPINNER = SPINNER_CIRCLE;
|
|
7
7
|
|
|
@@ -15,7 +15,7 @@ function formatDuration(ms) {
|
|
|
15
15
|
function truncate(value, max = 50) {
|
|
16
16
|
const s = String(value || '');
|
|
17
17
|
if (s.length <= max) return s;
|
|
18
|
-
return s.slice(0, max - 1) +
|
|
18
|
+
return s.slice(0, max - 1) + ELLIPSIS;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
function statusLabel(state) {
|
|
@@ -90,7 +90,7 @@ export function SubagentPanel({ state, events, isExpanded }) {
|
|
|
90
90
|
),
|
|
91
91
|
isRunning && state.lastTool
|
|
92
92
|
? h(Box, { paddingLeft: 2 },
|
|
93
|
-
h(Text, { color: '#565f89' },
|
|
93
|
+
h(Text, { color: '#565f89' }, `${DASH} `),
|
|
94
94
|
h(Text, { color: getToolColor(state.lastTool), bold: true }, state.lastTool),
|
|
95
95
|
state.lastTarget ? h(Text, { color: '#565f89' }, `: ${truncate(state.lastTarget, 80)}`) : null,
|
|
96
96
|
)
|
|
@@ -98,13 +98,13 @@ export function SubagentPanel({ state, events, isExpanded }) {
|
|
|
98
98
|
isExpanded
|
|
99
99
|
? h(Box, { flexDirection: 'column', paddingLeft: 2 },
|
|
100
100
|
hiddenEvents > 0
|
|
101
|
-
? h(Text, { color: '#565f89', dimColor: true }, `
|
|
101
|
+
? h(Text, { color: '#565f89', dimColor: true }, ` ${ELLIPSIS} ${hiddenEvents} earlier subagent events hidden`)
|
|
102
102
|
: null,
|
|
103
103
|
visibleEvents.length > 0
|
|
104
104
|
? visibleEvents.map((ev, i) => {
|
|
105
105
|
if (ev.type === 'tool_start') {
|
|
106
106
|
return h(Box, { key: i },
|
|
107
|
-
h(Text, { color: '#7aa2f7' },
|
|
107
|
+
h(Text, { color: '#7aa2f7' }, ` ${TREE_MID}${DASH} `),
|
|
108
108
|
h(Text, { color: getToolColor(ev.name), bold: true }, ev.name),
|
|
109
109
|
formatTarget(ev) ? h(Text, { color: '#565f89' }, `: ${truncate(formatTarget(ev), 80)}`) : null,
|
|
110
110
|
h(Text, { color: '#565f89' }, ' ' + DOT),
|
|
@@ -112,7 +112,7 @@ export function SubagentPanel({ state, events, isExpanded }) {
|
|
|
112
112
|
}
|
|
113
113
|
if (ev.type === 'tool_end') {
|
|
114
114
|
return h(Box, { key: i },
|
|
115
|
-
h(Text, { color: ev.success ? '#9ece6a' : '#f7768e' },
|
|
115
|
+
h(Text, { color: ev.success ? '#9ece6a' : '#f7768e' }, ` ${TREE_MID}${DASH} `),
|
|
116
116
|
h(Text, { color: getToolColor(ev.name), bold: true }, ev.name),
|
|
117
117
|
formatTarget(ev) ? h(Text, { color: '#565f89' }, `: ${truncate(formatTarget(ev), 80)}`) : null,
|
|
118
118
|
h(Text, { color: '#565f89' }, ev.success ? ' ' + TICK : ' ' + CROSS),
|
|
@@ -3,7 +3,7 @@ import { Box, Text } from 'ink';
|
|
|
3
3
|
import { h } from '../h.js';
|
|
4
4
|
import { highlightCode } from '../../parser/markdown.js';
|
|
5
5
|
import { ENABLE_UI_ANIMATIONS, useAnimationFrame } from '../animation.js';
|
|
6
|
-
import { SPINNER_BRAILLE, TICK, CROSS } from '../../utils/unicode.js';
|
|
6
|
+
import { SPINNER_BRAILLE, TICK, CROSS, ELLIPSIS } from '../../utils/unicode.js';
|
|
7
7
|
|
|
8
8
|
const SPINNER_FRAMES = SPINNER_BRAILLE;
|
|
9
9
|
|
|
@@ -171,7 +171,7 @@ export function ToolItem({ tool }) {
|
|
|
171
171
|
const prefix = tool.name === 'TASK' ? 'Subagent' : isSubagent ? 'Subagent tool' : null;
|
|
172
172
|
|
|
173
173
|
return h(Box, { paddingLeft: 2, paddingY: 0 },
|
|
174
|
-
h(Text, { color: '#7aa2f7' }, ENABLE_UI_ANIMATIONS ? ` ${SPINNER_FRAMES[frame % SPINNER_FRAMES.length]} ` : '
|
|
174
|
+
h(Text, { color: '#7aa2f7' }, ENABLE_UI_ANIMATIONS ? ` ${SPINNER_FRAMES[frame % SPINNER_FRAMES.length]} ` : ' ' + ELLIPSIS + ' '),
|
|
175
175
|
prefix ? h(Text, { color: '#7dcfff' }, `${prefix} `) : null,
|
|
176
176
|
h(Text, { color, bold: true }, tool.name),
|
|
177
177
|
target.text ? h(Text, { color: '#565f89' }, ': ') : null,
|
package/src/ui/diff.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { highlightCode } from '../parser/markdown.js';
|
|
3
|
+
import { BOX_TL, BOX_TR, BOX_BL, BOX_BR, BOX_V, BOX_H, ELLIPSIS, CROSS } from '../utils/unicode.js';
|
|
3
4
|
|
|
4
5
|
export const langFromPath = (fp) => {
|
|
5
6
|
if (!fp) return '';
|
|
@@ -115,22 +116,22 @@ export const printNewFile = (filePath, content) => {
|
|
|
115
116
|
console.log();
|
|
116
117
|
const header = ` + ${filePath} (new file, ${lines.length} lines) `;
|
|
117
118
|
const headerPad = Math.max(0, w - 2 - header.length);
|
|
118
|
-
console.log(bc(
|
|
119
|
+
console.log(bc(BOX_TL) + chalk.bgHex(c.headerBg).hex(c.headerFg)(header) + chalk.hex(c.headerBg)(BOX_H.repeat(headerPad)) + bc(BOX_TR));
|
|
119
120
|
|
|
120
121
|
const shown = Math.min(lines.length, 50);
|
|
121
122
|
for (let i = 0; i < shown; i++) {
|
|
122
123
|
const lineNum = chalk.hex(c.lineNumFg)(String(i + 1).padStart(lnW));
|
|
123
|
-
const raw = lines[i].length > innerW ? lines[i].slice(0, innerW - 1) +
|
|
124
|
+
const raw = lines[i].length > innerW ? lines[i].slice(0, innerW - 1) + ELLIPSIS : lines[i];
|
|
124
125
|
const colored = highlightCode(raw, lang);
|
|
125
126
|
const prefix = chalk.bgHex(c.addedBg).hex(c.addedFg)('+');
|
|
126
127
|
const padLen = Math.max(0, innerW - stripAnsi(colored).length);
|
|
127
|
-
console.log(bc(
|
|
128
|
+
console.log(bc(BOX_V) + ' ' + lineNum + ' ' + prefix + ' ' + colored + ' '.repeat(padLen) + bc(BOX_V));
|
|
128
129
|
}
|
|
129
130
|
if (lines.length > 50) {
|
|
130
131
|
const msg = ` ··· ${lines.length - 50} more lines`;
|
|
131
|
-
console.log(bc(
|
|
132
|
+
console.log(bc(BOX_V) + chalk.hex(c.dim)(msg) + ' '.repeat(Math.max(0, w - 2 - msg.length)) + bc(BOX_V));
|
|
132
133
|
}
|
|
133
|
-
console.log(bc(
|
|
134
|
+
console.log(bc(BOX_BL + BOX_H.repeat(w - 2) + BOX_BR));
|
|
134
135
|
console.log();
|
|
135
136
|
};
|
|
136
137
|
|
|
@@ -150,13 +151,13 @@ export const printEditDiff = (filePath, find, replace) => {
|
|
|
150
151
|
console.log();
|
|
151
152
|
const header = ` ✎ ${filePath} `;
|
|
152
153
|
const headerPad = Math.max(0, w - 2 - header.length);
|
|
153
|
-
console.log(bc(
|
|
154
|
+
console.log(bc(BOX_TL) + chalk.bgHex(c.headerBg).hex(c.headerFg)(header) + chalk.hex(c.headerBg)(BOX_H.repeat(headerPad)) + bc(BOX_TR));
|
|
154
155
|
|
|
155
156
|
for (const hunk of collapsed) {
|
|
156
157
|
if (hunk.type === 'skip') {
|
|
157
158
|
const msg = ` ··· ${hunk.count} unchanged line${hunk.count > 1 ? 's' : ''}`;
|
|
158
159
|
const pad = Math.max(0, w - 2 - msg.length);
|
|
159
|
-
console.log(bc(
|
|
160
|
+
console.log(bc(BOX_V) + chalk.hex(c.dim)(msg) + ' '.repeat(pad) + bc(BOX_V));
|
|
160
161
|
continue;
|
|
161
162
|
}
|
|
162
163
|
|
|
@@ -171,7 +172,7 @@ export const printEditDiff = (filePath, find, replace) => {
|
|
|
171
172
|
const nums = idx === 0 ? lineNums : lineNumsCont;
|
|
172
173
|
const styled = chalk.hex(c.ctxFg)(' ' + chunk);
|
|
173
174
|
const pad = Math.max(0, innerW + 1 - visLen(styled));
|
|
174
|
-
console.log(bc(
|
|
175
|
+
console.log(bc(BOX_V) + ' ' + nums + ' ' + styled + ' '.repeat(pad) + bc(BOX_V));
|
|
175
176
|
});
|
|
176
177
|
} else if (hunk.type === 'del') {
|
|
177
178
|
const chunks = wrapPlain(hunk.line, innerW);
|
|
@@ -180,7 +181,7 @@ export const printEditDiff = (filePath, find, replace) => {
|
|
|
180
181
|
const sign = idx === 0 ? '-' : ' ';
|
|
181
182
|
const colored = chalk.bgHex(c.removedBg).hex(c.removedFg)(sign) + highlightCode(chunk, lang);
|
|
182
183
|
const pad = Math.max(0, innerW + 1 - stripAnsi(colored).length);
|
|
183
|
-
console.log(bc(
|
|
184
|
+
console.log(bc(BOX_V) + ' ' + nums + ' ' + colored + ' '.repeat(pad) + bc(BOX_V));
|
|
184
185
|
});
|
|
185
186
|
} else if (hunk.type === 'add') {
|
|
186
187
|
const chunks = wrapPlain(hunk.line, innerW);
|
|
@@ -189,7 +190,7 @@ export const printEditDiff = (filePath, find, replace) => {
|
|
|
189
190
|
const sign = idx === 0 ? '+' : ' ';
|
|
190
191
|
const colored = chalk.bgHex(c.addedBg).hex(c.addedFg)(sign) + highlightCode(chunk, lang);
|
|
191
192
|
const pad = Math.max(0, innerW + 1 - stripAnsi(colored).length);
|
|
192
|
-
console.log(bc(
|
|
193
|
+
console.log(bc(BOX_V) + ' ' + nums + ' ' + colored + ' '.repeat(pad) + bc(BOX_V));
|
|
193
194
|
});
|
|
194
195
|
}
|
|
195
196
|
}
|
|
@@ -198,8 +199,8 @@ export const printEditDiff = (filePath, find, replace) => {
|
|
|
198
199
|
const adds = hunks.filter(h => h.type === 'add').length;
|
|
199
200
|
const summary = ` ${chalk.hex(c.addedFg)('+' + adds)} ${chalk.hex(c.removedFg)('-' + dels)} `;
|
|
200
201
|
const summaryPad = Math.max(0, w - 2 - stripAnsi(summary).length);
|
|
201
|
-
console.log(bc(
|
|
202
|
-
console.log(bc(
|
|
202
|
+
console.log(bc(BOX_V) + summary + ' '.repeat(summaryPad) + bc(BOX_V));
|
|
203
|
+
console.log(bc(BOX_BL + BOX_H.repeat(w - 2) + BOX_BR));
|
|
203
204
|
console.log();
|
|
204
205
|
};
|
|
205
206
|
|
|
@@ -215,22 +216,22 @@ export const printAppendDiff = (filePath, content) => {
|
|
|
215
216
|
console.log();
|
|
216
217
|
const header = ` + ${filePath} (appending ${lines.length} line${lines.length > 1 ? 's' : ''}) `;
|
|
217
218
|
const headerPad = Math.max(0, w - 2 - header.length);
|
|
218
|
-
console.log(bc(
|
|
219
|
+
console.log(bc(BOX_TL) + chalk.bgHex(c.headerBg).hex(c.addedFg)(header) + chalk.hex(c.headerBg)(BOX_H.repeat(headerPad)) + bc(BOX_TR));
|
|
219
220
|
|
|
220
221
|
const skip = lines.length > 30;
|
|
221
222
|
const shown = skip ? lines.slice(0, 15) : lines;
|
|
222
223
|
shown.forEach((line, i) => {
|
|
223
224
|
const lineNum = chalk.hex(c.lineNumFg)(String(i + 1).padStart(lnW));
|
|
224
|
-
const raw = line.length > innerW ? line.slice(0, innerW - 1) +
|
|
225
|
+
const raw = line.length > innerW ? line.slice(0, innerW - 1) + ELLIPSIS : line;
|
|
225
226
|
const colored = highlightCode(raw, lang);
|
|
226
227
|
const pad = Math.max(0, innerW - stripAnsi(colored).length);
|
|
227
|
-
console.log(bc(
|
|
228
|
+
console.log(bc(BOX_V) + ' ' + lineNum + ' ' + chalk.bgHex(c.addedBg).hex(c.addedFg)('+') + ' ' + colored + ' '.repeat(pad) + bc(BOX_V));
|
|
228
229
|
});
|
|
229
230
|
if (skip) {
|
|
230
231
|
const msg = ` ··· ${lines.length - 15} more lines`;
|
|
231
|
-
console.log(bc(
|
|
232
|
+
console.log(bc(BOX_V) + chalk.hex(c.dim)(msg) + ' '.repeat(Math.max(0, w - 2 - msg.length)) + bc(BOX_V));
|
|
232
233
|
}
|
|
233
|
-
console.log(bc(
|
|
234
|
+
console.log(bc(BOX_BL + BOX_H.repeat(w - 2) + BOX_BR));
|
|
234
235
|
console.log();
|
|
235
236
|
};
|
|
236
237
|
|
|
@@ -240,10 +241,10 @@ export const printAppendDiff = (filePath, content) => {
|
|
|
240
241
|
export const printDeleteFile = (filePath) => {
|
|
241
242
|
const w = getWidth();
|
|
242
243
|
const bc = chalk.hex(c.border);
|
|
243
|
-
const msg = `
|
|
244
|
+
const msg = ` ${CROSS} ${filePath} (deleted) `;
|
|
244
245
|
const pad = Math.max(0, w - 2 - msg.length);
|
|
245
246
|
console.log();
|
|
246
|
-
console.log(bc(
|
|
247
|
-
console.log(bc(
|
|
247
|
+
console.log(bc(BOX_TL) + chalk.bgHex(c.removedBg).hex(c.removedFg)(msg) + chalk.hex(c.removedBg)(BOX_H.repeat(pad)) + bc(BOX_TR));
|
|
248
|
+
console.log(bc(BOX_BL + BOX_H.repeat(w - 2) + BOX_BR));
|
|
248
249
|
console.log();
|
|
249
250
|
};
|
package/src/utils/unicode.js
CHANGED
|
@@ -8,7 +8,7 @@ export const ARROW = isUnicode ? '▸' : '>';
|
|
|
8
8
|
export const DASH = isUnicode ? '─' : '-';
|
|
9
9
|
export const BAR = isUnicode ? '│' : '|';
|
|
10
10
|
export const BULLET = isUnicode ? '•' : '*';
|
|
11
|
-
export const ELLIPSIS = '…';
|
|
11
|
+
export const ELLIPSIS = isUnicode ? '…' : '...';
|
|
12
12
|
export const SPINNER_BRAILLE = isUnicode
|
|
13
13
|
? ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']
|
|
14
14
|
: ['|', '/', '-', '\\'];
|
|
@@ -44,9 +44,12 @@ export const WARN = isUnicode ? '⚠' : '!';
|
|
|
44
44
|
export const CLOUD = isUnicode ? '☁' : '~';
|
|
45
45
|
export const TRIANGLE = isUnicode ? '▲' : '^';
|
|
46
46
|
export const TREE_BRANCH = isUnicode ? '├── ' : '|-- ';
|
|
47
|
+
export const TREE_MID = isUnicode ? '├' : '|';
|
|
47
48
|
export const TREE_LAST = isUnicode ? '└── ' : '`-- ';
|
|
48
49
|
export const TREE_VLINE = isUnicode ? '│ ' : '| ';
|
|
49
50
|
export const TREE_SPACE = ' ';
|
|
51
|
+
export const ARROW_LEFT = isUnicode ? '◀' : '<';
|
|
52
|
+
export const LOADING = isUnicode ? '⟳' : '[.]';
|
|
50
53
|
export const LOADING_DOTS = isUnicode
|
|
51
54
|
? ['', '∘', '∘∘', '∘∘∘']
|
|
52
55
|
: ['', '.', '..', '...'];
|