ikie-cli 0.1.13 → 0.1.14
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/dist/agent.js +4 -3
- package/dist/theme.d.ts +11 -3
- package/dist/theme.js +137 -33
- package/package.json +1 -1
package/dist/agent.js
CHANGED
|
@@ -530,12 +530,13 @@ export class Agent {
|
|
|
530
530
|
if (name === 'edit_file' && !result.startsWith('Error')) {
|
|
531
531
|
const oldStr = String(input.old_string ?? '');
|
|
532
532
|
const newStr = String(input.new_string ?? '');
|
|
533
|
-
|
|
533
|
+
const path = typeof input.path === 'string' ? input.path : undefined;
|
|
534
|
+
block = toolDiffBlock(oldStr, newStr, ms, { path, indent: this.indent });
|
|
534
535
|
}
|
|
535
536
|
else {
|
|
536
|
-
block = toolOutputBlock(result, ms);
|
|
537
|
+
block = toolOutputBlock(result, ms, this.indent);
|
|
537
538
|
}
|
|
538
|
-
process.stdout.write(`${
|
|
539
|
+
process.stdout.write(`${block}\n`);
|
|
539
540
|
return result;
|
|
540
541
|
}
|
|
541
542
|
catch (err) {
|
package/dist/theme.d.ts
CHANGED
|
@@ -62,9 +62,16 @@ export declare class InlineSpinner {
|
|
|
62
62
|
}
|
|
63
63
|
export declare function toolLine(name: string, args: string): string;
|
|
64
64
|
/** Multi-line output block shown after a tool runs. */
|
|
65
|
-
export declare function toolOutputBlock(result: string, ms: number): string;
|
|
66
|
-
|
|
67
|
-
|
|
65
|
+
export declare function toolOutputBlock(result: string, ms: number, indent?: string): string;
|
|
66
|
+
interface DiffOpts {
|
|
67
|
+
path?: string;
|
|
68
|
+
indent?: string;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Render an edit as a polished unified diff: line-number gutter, a few lines of
|
|
72
|
+
* surrounding context pulled from the file, and full-width muted red/green rows.
|
|
73
|
+
*/
|
|
74
|
+
export declare function toolDiffBlock(oldStr: string, newStr: string, ms: number, opts?: DiffOpts): string;
|
|
68
75
|
export declare function toolSuccessLine(ms: number, preview?: string): string;
|
|
69
76
|
export declare function toolErrorLine(msg: string): string;
|
|
70
77
|
export declare function successLine(msg: string): string;
|
|
@@ -72,3 +79,4 @@ export declare function errorLine(msg: string): string;
|
|
|
72
79
|
export declare function warnLine(msg: string): string;
|
|
73
80
|
export declare function infoLine(msg: string): string;
|
|
74
81
|
export declare function permissionPrompt(toolName: string, preview: string): string;
|
|
82
|
+
export {};
|
package/dist/theme.js
CHANGED
|
@@ -375,55 +375,159 @@ export function toolLine(name, args) {
|
|
|
375
375
|
return `${tint('●')} ${c.white.bold(verb + badge)}${c.dim('(')}${c.muted(args)}${c.dim(')')}`;
|
|
376
376
|
}
|
|
377
377
|
/** Multi-line output block shown after a tool runs. */
|
|
378
|
-
export function toolOutputBlock(result, ms) {
|
|
378
|
+
export function toolOutputBlock(result, ms, indent = ' ') {
|
|
379
379
|
const time = c.muted(formatDuration(ms));
|
|
380
380
|
const lines = result.split('\n').filter(l => l.trim() !== '');
|
|
381
381
|
if (!lines.length)
|
|
382
|
-
return
|
|
382
|
+
return `${indent}${c.muted('⎿')} ${time}`;
|
|
383
383
|
const MAX = 5;
|
|
384
384
|
const shown = lines.slice(0, MAX);
|
|
385
385
|
const hidden = lines.length - MAX;
|
|
386
|
+
const cont = indent + ' ';
|
|
386
387
|
const out = [];
|
|
387
|
-
out.push(
|
|
388
|
+
out.push(`${indent}${c.muted('⎿')} ${time} ${c.dim(clampLine(shown[0]))}`);
|
|
388
389
|
for (let i = 1; i < shown.length; i++) {
|
|
389
|
-
out.push(
|
|
390
|
+
out.push(`${cont}${c.dim(clampLine(shown[i]))}`);
|
|
390
391
|
}
|
|
391
392
|
if (hidden > 0) {
|
|
392
|
-
out.push(
|
|
393
|
+
out.push(`${cont}${c.muted(`… +${hidden} lines`)}`);
|
|
393
394
|
}
|
|
394
395
|
return out.join('\n');
|
|
395
396
|
}
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
397
|
+
// ── Diff rendering ────────────────────────────────────────────────────────────
|
|
398
|
+
// Diff palette (256-color, muted — chalk degrades gracefully on low-color TTYs).
|
|
399
|
+
const diffColors = {
|
|
400
|
+
delBg: chalk.bgAnsi256(52), // deep red
|
|
401
|
+
insBg: chalk.bgAnsi256(22), // deep green
|
|
402
|
+
delGutter: chalk.ansi256(210),
|
|
403
|
+
insGutter: chalk.ansi256(151),
|
|
404
|
+
onBg: chalk.ansi256(255),
|
|
405
|
+
ctxGutter: chalk.ansi256(240),
|
|
406
|
+
ctxCode: chalk.ansi256(248),
|
|
407
|
+
};
|
|
408
|
+
/** Classic LCS line diff — interleaves equal/removed/added like a real unified diff. */
|
|
409
|
+
function lineDiff(a, b) {
|
|
410
|
+
const n = a.length, m = b.length;
|
|
411
|
+
const dp = Array.from({ length: n + 1 }, () => new Array(m + 1).fill(0));
|
|
412
|
+
for (let i = n - 1; i >= 0; i--) {
|
|
413
|
+
for (let j = m - 1; j >= 0; j--) {
|
|
414
|
+
dp[i][j] = a[i] === b[j] ? dp[i + 1][j + 1] + 1 : Math.max(dp[i + 1][j], dp[i][j + 1]);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
409
417
|
const out = [];
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
+
let i = 0, j = 0;
|
|
419
|
+
while (i < n && j < m) {
|
|
420
|
+
if (a[i] === b[j]) {
|
|
421
|
+
out.push({ t: 'eq', s: a[i] });
|
|
422
|
+
i++;
|
|
423
|
+
j++;
|
|
424
|
+
}
|
|
425
|
+
else if (dp[i + 1][j] >= dp[i][j + 1]) {
|
|
426
|
+
out.push({ t: 'del', s: a[i] });
|
|
427
|
+
i++;
|
|
428
|
+
}
|
|
429
|
+
else {
|
|
430
|
+
out.push({ t: 'ins', s: b[j] });
|
|
431
|
+
j++;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
while (i < n)
|
|
435
|
+
out.push({ t: 'del', s: a[i++] });
|
|
436
|
+
while (j < m)
|
|
437
|
+
out.push({ t: 'ins', s: b[j++] });
|
|
438
|
+
return out;
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Render an edit as a polished unified diff: line-number gutter, a few lines of
|
|
442
|
+
* surrounding context pulled from the file, and full-width muted red/green rows.
|
|
443
|
+
*/
|
|
444
|
+
export function toolDiffBlock(oldStr, newStr, ms, opts = {}) {
|
|
445
|
+
const indent = opts.indent ?? ' ';
|
|
446
|
+
const cols = Math.max(40, (process.stdout.columns ?? 100));
|
|
447
|
+
const time = c.muted(formatDuration(ms));
|
|
448
|
+
const oldLines = oldStr.split('\n');
|
|
449
|
+
const newLines = newStr.split('\n');
|
|
450
|
+
const ops = lineDiff(oldLines, newLines);
|
|
451
|
+
const nDel = ops.filter(o => o.t === 'del').length;
|
|
452
|
+
const nIns = ops.filter(o => o.t === 'ins').length;
|
|
453
|
+
// Anchor line numbers + context lines by locating the new text in the file.
|
|
454
|
+
let anchor = 1;
|
|
455
|
+
let fileLines = null;
|
|
456
|
+
const CTX = 3;
|
|
457
|
+
if (opts.path) {
|
|
458
|
+
try {
|
|
459
|
+
const content = readFileSync(opts.path, 'utf-8');
|
|
460
|
+
const idx = content.indexOf(newStr);
|
|
461
|
+
if (idx >= 0) {
|
|
462
|
+
anchor = (content.slice(0, idx).match(/\n/g)?.length ?? 0) + 1;
|
|
463
|
+
fileLines = content.split('\n');
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
catch { /* no context — fall back to anchorless diff */ }
|
|
418
467
|
}
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
468
|
+
const summaryParts = [];
|
|
469
|
+
if (nIns)
|
|
470
|
+
summaryParts.push(`Added ${nIns} line${nIns === 1 ? '' : 's'}`);
|
|
471
|
+
if (nDel)
|
|
472
|
+
summaryParts.push(`removed ${nDel} line${nDel === 1 ? '' : 's'}`);
|
|
473
|
+
const summary = summaryParts.join(', ') || 'no changes';
|
|
474
|
+
// Width of the line-number gutter.
|
|
475
|
+
const maxNum = anchor + Math.max(oldLines.length, newLines.length) + CTX;
|
|
476
|
+
const gw = String(maxNum).length;
|
|
477
|
+
const rowsRaw = [];
|
|
478
|
+
// Leading context (lines just before the edit).
|
|
479
|
+
if (fileLines) {
|
|
480
|
+
for (let k = Math.max(1, anchor - CTX); k < anchor; k++) {
|
|
481
|
+
rowsRaw.push({ kind: 'eq', num: k, text: fileLines[k - 1] ?? '' });
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
// The diff body — track separate old/new line counters off the same anchor.
|
|
485
|
+
let oldNum = anchor, newNum = anchor;
|
|
486
|
+
for (const op of ops) {
|
|
487
|
+
if (op.t === 'eq') {
|
|
488
|
+
rowsRaw.push({ kind: 'eq', num: newNum, text: op.s });
|
|
489
|
+
oldNum++;
|
|
490
|
+
newNum++;
|
|
491
|
+
}
|
|
492
|
+
else if (op.t === 'del') {
|
|
493
|
+
rowsRaw.push({ kind: 'del', num: oldNum, text: op.s });
|
|
494
|
+
oldNum++;
|
|
495
|
+
}
|
|
496
|
+
else {
|
|
497
|
+
rowsRaw.push({ kind: 'ins', num: newNum, text: op.s });
|
|
498
|
+
newNum++;
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
// Trailing context (lines just after the edit).
|
|
502
|
+
if (fileLines) {
|
|
503
|
+
const afterStart = newNum;
|
|
504
|
+
for (let k = afterStart; k < afterStart + CTX && k <= fileLines.length; k++) {
|
|
505
|
+
rowsRaw.push({ kind: 'eq', num: k, text: fileLines[k - 1] ?? '' });
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
const out = [];
|
|
509
|
+
out.push(`${indent}${c.muted('⎿')} ${time} ${c.dim(summary)}`);
|
|
510
|
+
const MAX = 16;
|
|
511
|
+
const codeWidth = cols - indent.length - gw - 4; // gutter + " x " marker + space
|
|
512
|
+
const render = rowsRaw.slice(0, MAX);
|
|
513
|
+
for (const r of render) {
|
|
514
|
+
const numStr = String(r.num).padStart(gw);
|
|
515
|
+
const code = r.text.length > codeWidth ? r.text.slice(0, codeWidth - 1) + '…' : r.text;
|
|
516
|
+
if (r.kind === 'eq') {
|
|
517
|
+
out.push(`${indent}${diffColors.ctxGutter(numStr)} ${diffColors.ctxCode(code)}`);
|
|
518
|
+
}
|
|
519
|
+
else {
|
|
520
|
+
const marker = r.kind === 'del' ? '-' : '+';
|
|
521
|
+
const bg = r.kind === 'del' ? diffColors.delBg : diffColors.insBg;
|
|
522
|
+
const gutter = r.kind === 'del' ? diffColors.delGutter : diffColors.insGutter;
|
|
523
|
+
const plainLen = numStr.length + 3 + code.length; // num + " x " + code
|
|
524
|
+
const pad = Math.max(0, cols - indent.length - plainLen);
|
|
525
|
+
const inner = `${gutter(numStr)} ${gutter(marker)} ${diffColors.onBg(code)}${' '.repeat(pad)}`;
|
|
526
|
+
out.push(`${indent}${bg(inner)}`);
|
|
527
|
+
}
|
|
424
528
|
}
|
|
425
|
-
if (
|
|
426
|
-
out.push(
|
|
529
|
+
if (rowsRaw.length > MAX) {
|
|
530
|
+
out.push(`${indent}${c.muted(`… +${rowsRaw.length - MAX} lines`)}`);
|
|
427
531
|
}
|
|
428
532
|
return out.join('\n');
|
|
429
533
|
}
|