kfc-code-cli 0.0.1-alpha.8 → 0.0.1-alpha.9

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 (2) hide show
  1. package/dist/main.mjs +207 -42
  2. package/package.json +1 -1
package/dist/main.mjs CHANGED
@@ -95356,7 +95356,7 @@ var SkillActivationComponent = class extends Container {
95356
95356
  //#region src/tui/components/messages/thinking.ts
95357
95357
  const BULLET = "⏺ ";
95358
95358
  const INDENT = " ";
95359
- const PREVIEW_LINES$1 = 3;
95359
+ const PREVIEW_LINES = 3;
95360
95360
  const SPINNER_FRAMES = [
95361
95361
  "⠋",
95362
95362
  "⠙",
@@ -95407,7 +95407,7 @@ var ThinkingComponent = class {
95407
95407
  const textComponent = new Text(chalk.hex(this.color).italic(this.text), 0, 0);
95408
95408
  const contentLines = this.text.length > 0 ? textComponent.render(contentWidth) : [""];
95409
95409
  if (this.mode === "live") {
95410
- const visibleLines = contentLines.length > PREVIEW_LINES$1 ? contentLines.slice(contentLines.length - PREVIEW_LINES$1) : contentLines;
95410
+ const visibleLines = contentLines.length > PREVIEW_LINES ? contentLines.slice(contentLines.length - PREVIEW_LINES) : contentLines;
95411
95411
  return [
95412
95412
  "",
95413
95413
  chalk.hex(this.color)(`${SPINNER_FRAMES[this.spinnerFrame] ?? SPINNER_FRAMES[0]} `) + chalk.hex(this.color)("thinking..."),
@@ -95419,9 +95419,9 @@ var ThinkingComponent = class {
95419
95419
  const p = i === 0 && this.showMarker ? chalk.hex(this.color)(BULLET) : INDENT;
95420
95420
  rendered.push(p + contentLines[i]);
95421
95421
  }
95422
- if (this.expanded || contentLines.length <= PREVIEW_LINES$1) return rendered;
95423
- const truncated = rendered.slice(0, 1 + PREVIEW_LINES$1);
95424
- const remaining = contentLines.length - PREVIEW_LINES$1;
95422
+ if (this.expanded || contentLines.length <= PREVIEW_LINES) return rendered;
95423
+ const truncated = rendered.slice(0, 1 + PREVIEW_LINES);
95424
+ const remaining = contentLines.length - PREVIEW_LINES;
95425
95425
  truncated.push(INDENT + chalk.dim(`... (${String(remaining)} more lines, ctrl+o to expand)`));
95426
95426
  return truncated;
95427
95427
  }
@@ -95550,13 +95550,174 @@ var PlanBoxComponent = class {
95550
95550
  }
95551
95551
  };
95552
95552
  //#endregion
95553
+ //#region src/tui/components/messages/tool-renderers/types.ts
95554
+ function strArg(args, ...keys) {
95555
+ for (const key of keys) {
95556
+ const v = args[key];
95557
+ if (typeof v === "string" && v.length > 0) return v;
95558
+ }
95559
+ return "";
95560
+ }
95561
+ //#endregion
95562
+ //#region src/tui/components/messages/tool-renderers/chip.ts
95563
+ function countNonEmptyLines(text) {
95564
+ if (text.length === 0) return 0;
95565
+ let n = 0;
95566
+ for (const line of text.split("\n")) if (line.length > 0) n++;
95567
+ return n;
95568
+ }
95569
+ function pluralize(n, singular, plural) {
95570
+ return `${String(n)} ${n === 1 ? singular : plural ?? `${singular}s`}`;
95571
+ }
95572
+ function formatBytes(bytes) {
95573
+ if (bytes < 1024) return `${String(bytes)} B`;
95574
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
95575
+ return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
95576
+ }
95577
+ const editChip = (toolCall) => {
95578
+ const oldStr = strArg(toolCall.args, "old_string");
95579
+ const newStr = strArg(toolCall.args, "new_string");
95580
+ if (oldStr.length === 0 && newStr.length === 0) return "";
95581
+ const diff = computeDiffLines(oldStr, newStr);
95582
+ const added = diff.filter((l) => l.kind === "add").length;
95583
+ const removed = diff.filter((l) => l.kind === "delete").length;
95584
+ const parts = [];
95585
+ if (added > 0) parts.push(`+${String(added)}`);
95586
+ if (removed > 0) parts.push(`-${String(removed)}`);
95587
+ return parts.join(" ");
95588
+ };
95589
+ const writeChip = (toolCall) => {
95590
+ const content = strArg(toolCall.args, "content");
95591
+ const normalized = content.endsWith("\n") ? content.slice(0, -1) : content;
95592
+ return pluralize(normalized.length > 0 ? normalized.split("\n").length : 0, "line");
95593
+ };
95594
+ const readChip = (_toolCall, result) => pluralize(countNonEmptyLines(result.output), "line");
95595
+ const grepChip = (_toolCall, result) => {
95596
+ const matches = countNonEmptyLines(result.output);
95597
+ if (matches === 0) return "no matches";
95598
+ return pluralize(matches, "match", "matches");
95599
+ };
95600
+ const globChip = (_toolCall, result) => {
95601
+ const files = countNonEmptyLines(result.output);
95602
+ if (files === 0) return "no files";
95603
+ return pluralize(files, "file");
95604
+ };
95605
+ const fetchChip = (_toolCall, result) => formatBytes(Buffer.byteLength(result.output, "utf8"));
95606
+ const webSearchChip = (_toolCall, result) => {
95607
+ const lines = result.output.split("\n").filter((l) => l.trim().length > 0);
95608
+ let count = 0;
95609
+ for (const line of lines) if (/^\s*(\d+\.|[-*])\s+/.test(line)) count++;
95610
+ if (count === 0) return lines.length === 0 ? "no results" : "web result";
95611
+ return pluralize(count, "result");
95612
+ };
95613
+ const REGISTRY = {
95614
+ Edit: editChip,
95615
+ Write: writeChip,
95616
+ Read: readChip,
95617
+ Grep: grepChip,
95618
+ Glob: globChip,
95619
+ FetchURL: fetchChip,
95620
+ WebSearch: webSearchChip
95621
+ };
95622
+ function pickChip(toolName) {
95623
+ return REGISTRY[toolName];
95624
+ }
95625
+ //#endregion
95626
+ //#region src/tui/components/messages/tool-renderers/truncated.ts
95627
+ const renderTruncated = (_toolCall, result, ctx) => {
95628
+ if (!result.output) return [];
95629
+ const tint = result.is_error ? chalk.hex(ctx.colors.error) : chalk.dim;
95630
+ const lines = result.output.split("\n");
95631
+ if (ctx.expanded) return [new Text(tint(result.output), 2, 0)];
95632
+ const shown = lines.slice(0, 3);
95633
+ const remaining = lines.length - shown.length;
95634
+ const out = [new Text(tint(shown.join("\n")), 2, 0)];
95635
+ if (remaining > 0) out.push(new Text(chalk.dim(`... (${String(remaining)} more lines, ctrl+o to expand)`), 2, 0));
95636
+ return out;
95637
+ };
95638
+ //#endregion
95639
+ //#region src/tui/components/messages/tool-renderers/summary.ts
95640
+ const GLANCE_SAMPLES = 3;
95641
+ function withGlance(glance) {
95642
+ return (toolCall, result, ctx) => {
95643
+ if (result.is_error) return renderTruncated(toolCall, result, ctx);
95644
+ const out = [];
95645
+ if (glance !== null) {
95646
+ const line = glance(toolCall, result);
95647
+ if (line.length > 0) out.push(new Text(` ${chalk.dim(line)}`, 0, 0));
95648
+ }
95649
+ if (ctx.expanded && result.output.length > 0) out.push(new Text(chalk.dim(result.output), 4, 0));
95650
+ return out;
95651
+ };
95652
+ }
95653
+ function nonEmptyLines(text) {
95654
+ if (text.length === 0) return [];
95655
+ return text.split("\n").filter((line) => line.length > 0);
95656
+ }
95657
+ function pathFromGrepLine(line) {
95658
+ const idx = line.indexOf(":");
95659
+ if (idx <= 0) return line;
95660
+ const second = line.indexOf(":", idx + 1);
95661
+ if (second <= 0) return line;
95662
+ return line.slice(0, second);
95663
+ }
95664
+ const grepGlance = (_toolCall, result) => {
95665
+ const lines = nonEmptyLines(result.output);
95666
+ if (lines.length === 0) return "";
95667
+ const samples = lines.slice(0, GLANCE_SAMPLES).map(pathFromGrepLine);
95668
+ const remaining = lines.length - samples.length;
95669
+ const tail = remaining > 0 ? `, +${String(remaining)} more` : "";
95670
+ return `${samples.join(", ")}${tail}`;
95671
+ };
95672
+ const globGlance = (_toolCall, result) => {
95673
+ const lines = nonEmptyLines(result.output);
95674
+ if (lines.length === 0) return "";
95675
+ const samples = lines.slice(0, GLANCE_SAMPLES);
95676
+ const remaining = lines.length - samples.length;
95677
+ const tail = remaining > 0 ? `, +${String(remaining)} more` : "";
95678
+ return `${samples.join(", ")}${tail}`;
95679
+ };
95680
+ const readSummary = withGlance(null);
95681
+ const fetchSummary = withGlance(null);
95682
+ const webSearchSummary = withGlance(null);
95683
+ const thinkSummary = withGlance(null);
95684
+ const editSummary = withGlance(null);
95685
+ const writeSummary = withGlance(null);
95686
+ const grepSummary = withGlance(grepGlance);
95687
+ const globSummary = withGlance(globGlance);
95688
+ //#endregion
95689
+ //#region src/tui/components/messages/tool-renderers/registry.ts
95690
+ /**
95691
+ * Tool result renderer registry.
95692
+ *
95693
+ * Each tool name maps to a `ResultRenderer` that turns the tool's
95694
+ * `ToolResultBlockData` into renderable Components. Tools without an
95695
+ * explicit entry fall through to `renderTruncated` (the original
95696
+ * 3-line + ctrl+o behavior).
95697
+ *
95698
+ * Keep this dispatch flat — tool names live next to the renderer they
95699
+ * choose, so adding a new tool means appending one case.
95700
+ */
95701
+ function pickResultRenderer(toolName) {
95702
+ switch (toolName) {
95703
+ case "Read": return readSummary;
95704
+ case "Grep": return grepSummary;
95705
+ case "Glob": return globSummary;
95706
+ case "FetchURL": return fetchSummary;
95707
+ case "WebSearch": return webSearchSummary;
95708
+ case "Think": return thinkSummary;
95709
+ case "Edit": return editSummary;
95710
+ case "Write": return writeSummary;
95711
+ default: return renderTruncated;
95712
+ }
95713
+ }
95714
+ //#endregion
95553
95715
  //#region src/tui/components/messages/tool-call.ts
95554
95716
  /**
95555
95717
  * Renders a tool call entry in the transcript.
95556
95718
  * Supports expand/collapse via Ctrl+O.
95557
95719
  */
95558
95720
  const MAX_ARG_LENGTH = 60;
95559
- const PREVIEW_LINES = 3;
95560
95721
  const CALL_PREVIEW_LINES = 10;
95561
95722
  const BLINK_INTERVAL$1 = 500;
95562
95723
  const MAX_SUB_TOOL_CALLS_SHOWN = 4;
@@ -95706,14 +95867,10 @@ function parseArgsPreview(value) {
95706
95867
  }
95707
95868
  function extractKeyArgument(toolName, args) {
95708
95869
  const candidates = {
95709
- Shell: ["command"],
95710
95870
  Bash: ["command"],
95711
- ReadFile: ["path", "file_path"],
95712
95871
  Read: ["path", "file_path"],
95713
95872
  Write: ["path", "file_path"],
95714
- WriteFile: ["path", "file_path"],
95715
95873
  Edit: ["path", "file_path"],
95716
- EditFile: ["path", "file_path"],
95717
95874
  Grep: ["pattern"],
95718
95875
  Glob: ["pattern"],
95719
95876
  FetchURL: ["url"],
@@ -95890,7 +96047,15 @@ var ToolCallComponent = class extends Container {
95890
96047
  const keyArg = extractKeyArgument(toolCall.name, toolCall.args);
95891
96048
  const toolRef = chalk.hex(colors.primary).bold(toolCall.name);
95892
96049
  const argStr = keyArg ? chalk.dim(` (${keyArg})`) : "";
95893
- return `${bullet}${verb} ${toolRef}${argStr}`;
96050
+ const chipStr = isFinished && result ? this.buildHeaderChip(result) : "";
96051
+ return `${bullet}${verb} ${toolRef}${argStr}${chipStr}`;
96052
+ }
96053
+ buildHeaderChip(result) {
96054
+ const provider = pickChip(this.toolCall.name);
96055
+ if (provider === void 0) return "";
96056
+ const text = provider(this.toolCall, result);
96057
+ if (text.length === 0) return "";
96058
+ return (result.is_error ? chalk.hex(this.colors.error) : chalk.dim)(` · ${text}`);
95894
96059
  }
95895
96060
  rebuildContent() {
95896
96061
  while (this.children.length > this.callPreviewEndIndex) this.children.pop();
@@ -95945,7 +96110,7 @@ var ToolCallComponent = class extends Container {
95945
96110
  this.buildStreamingPreview(this.toolCall.streamingArguments);
95946
96111
  return;
95947
96112
  }
95948
- if (name === "Write" || name === "WriteFile") {
96113
+ if (name === "Write") {
95949
96114
  const content = str(this.toolCall.args["content"]);
95950
96115
  if (content.length === 0) return;
95951
96116
  const allLines = highlightLines(content, langFromPath(str(this.toolCall.args["file_path"] ?? this.toolCall.args["path"])));
@@ -95956,7 +96121,7 @@ var ToolCallComponent = class extends Container {
95956
96121
  this.addChild(new Text(lineNum + line, 2, 0));
95957
96122
  }
95958
96123
  if (remaining > 0) this.addChild(new Text(chalk.dim(`... (${String(remaining)} more lines, ${String(allLines.length)} total)`), 2, 0));
95959
- } else if (name === "Edit" || name === "EditFile") {
96124
+ } else if (name === "Edit") {
95960
96125
  const oldStr = str(this.toolCall.args["old_string"]);
95961
96126
  const newStr = str(this.toolCall.args["new_string"]);
95962
96127
  if (oldStr.length === 0 && newStr.length === 0) return;
@@ -95980,14 +96145,14 @@ var ToolCallComponent = class extends Container {
95980
96145
  */
95981
96146
  buildStreamingPreview(streamText) {
95982
96147
  const name = this.toolCall.name;
95983
- if (name === "Write" || name === "WriteFile") {
96148
+ if (name === "Write") {
95984
96149
  const content = extractPartialStringField(streamText, "content");
95985
96150
  if (content === void 0 || content.length === 0) return;
95986
96151
  const filePath = extractPartialStringField(streamText, "file_path") ?? extractPartialStringField(streamText, "path") ?? "";
95987
96152
  this.renderStreamingCode(content, filePath);
95988
96153
  return;
95989
96154
  }
95990
- if (name === "Edit" || name === "EditFile" || name === "MultiEdit") {
96155
+ if (name === "Edit") {
95991
96156
  const oldStr = extractPartialStringField(streamText, "old_string") ?? "";
95992
96157
  const newStr = extractPartialStringField(streamText, "new_string") ?? "";
95993
96158
  if (oldStr.length === 0 && newStr.length === 0) return;
@@ -95998,7 +96163,7 @@ var ToolCallComponent = class extends Container {
95998
96163
  if (remaining > 0) this.addChild(new Text(chalk.dim(`... (${String(remaining)} more lines)`), 2, 0));
95999
96164
  return;
96000
96165
  }
96001
- if (name === "Bash" || name === "Shell") {
96166
+ if (name === "Bash") {
96002
96167
  const cmd = extractPartialStringField(streamText, "command");
96003
96168
  if (cmd === void 0 || cmd.length === 0) return;
96004
96169
  const lines = cmd.split("\n").slice(0, CALL_PREVIEW_LINES);
@@ -96040,15 +96205,11 @@ var ToolCallComponent = class extends Container {
96040
96205
  }
96041
96206
  if (this.toolCall.name === "SetTodoList" && !result.is_error) return;
96042
96207
  if (this.toolCall.name === "AskUserQuestion" && !result.is_error && this.renderAskUserQuestionResult(result.output)) return;
96043
- const tint = result.is_error ? chalk.hex(this.colors.error) : chalk.dim;
96044
- const lines = result.output.split("\n");
96045
- if (this.expanded) this.addChild(new Text(tint(result.output), 2, 0));
96046
- else {
96047
- const shown = lines.slice(0, PREVIEW_LINES);
96048
- const remaining = lines.length - shown.length;
96049
- this.addChild(new Text(tint(shown.join("\n")), 2, 0));
96050
- if (remaining > 0) this.addChild(new Text(chalk.dim(`... (${String(remaining)} more lines, ctrl+o to expand)`), 2, 0));
96051
- }
96208
+ const components = pickResultRenderer(this.toolCall.name)(this.toolCall, result, {
96209
+ expanded: this.expanded,
96210
+ colors: this.colors
96211
+ });
96212
+ for (const component of components) this.addChild(component);
96052
96213
  }
96053
96214
  /**
96054
96215
  * Render AskUserQuestion's JSON payload as a friendly Q/A list.
@@ -97811,18 +97972,18 @@ var QuestionController = class extends ReverseRpcController {
97811
97972
  //#endregion
97812
97973
  //#region src/tui/theme/colors.ts
97813
97974
  const darkColors = {
97814
- primary: "#1783ff",
97815
- primaryDim: "#0f5ab0",
97975
+ primary: "#4FA8FF",
97976
+ primaryDim: "#2563EB",
97816
97977
  text: "#E0E0E0",
97817
97978
  textDim: "#888888",
97818
97979
  textMuted: "#555555",
97819
97980
  success: "#4EC87E",
97820
97981
  warning: "#E8A838",
97821
97982
  error: "#E85454",
97822
- info: "#1783ff",
97983
+ info: "#4FA8FF",
97823
97984
  border: "#444444",
97824
- prompt: "#1783ff",
97825
- spinner: "#1783ff",
97985
+ prompt: "#4FA8FF",
97986
+ spinner: "#4FA8FF",
97826
97987
  user: "#FFCB6B",
97827
97988
  assistant: "#E0E0E0",
97828
97989
  thinking: "#888888",
@@ -100569,30 +100730,30 @@ function renderDisplayBlock(block, expanded) {
100569
100730
  if (block.danger !== void 0) lines.push(chalk.red.bold(`⚠ potentially destructive: ${block.danger}`));
100570
100731
  (block.command.length > 0 ? block.command.split("\n") : [""]).forEach((cmdLine, idx) => {
100571
100732
  const prefix = idx === 0 ? chalk.cyan("$") : chalk.dim("·");
100572
- lines.push(`${prefix} ${chalk.gray(cmdLine)}`);
100733
+ lines.push(`${prefix} ${chalk.whiteBright(cmdLine)}`);
100573
100734
  });
100574
100735
  if (block.description !== void 0 && block.description.length > 0) lines.push(` ${chalk.dim(block.description)}`);
100575
100736
  return lines;
100576
100737
  }
100577
100738
  case "file_op": {
100578
- const lines = [`${chalk.cyan(block.operation.padEnd(5))} ${chalk.gray(block.path)}`];
100739
+ const lines = [`${chalk.cyan(block.operation.padEnd(5))} ${chalk.whiteBright(block.path)}`];
100579
100740
  if (block.detail !== void 0 && block.detail.length > 0) lines.push(chalk.dim(block.detail));
100580
100741
  return lines;
100581
100742
  }
100582
- case "url_fetch": return [`${chalk.cyan((block.method ?? "GET").toUpperCase().padEnd(5))} ${chalk.gray(block.url)}`];
100743
+ case "url_fetch": return [`${chalk.cyan((block.method ?? "GET").toUpperCase().padEnd(5))} ${chalk.whiteBright(block.url)}`];
100583
100744
  case "search": {
100584
- const lines = [`${chalk.cyan("search")} ${chalk.gray(block.query)}`];
100745
+ const lines = [`${chalk.cyan("search")} ${chalk.whiteBright(block.query)}`];
100585
100746
  if (block.scope !== void 0 && block.scope.length > 0) lines.push(chalk.dim(`scope: ${block.scope}`));
100586
100747
  return lines;
100587
100748
  }
100588
100749
  case "invocation": {
100589
- const lines = [`${chalk.cyan(block.kind.padEnd(5))} ${chalk.gray(block.name)}`];
100750
+ const lines = [`${chalk.cyan(block.kind.padEnd(5))} ${chalk.whiteBright(block.name)}`];
100590
100751
  if (block.description !== void 0 && block.description.length > 0) lines.push(chalk.dim(truncateOneLine(block.description, 200)));
100591
100752
  return lines;
100592
100753
  }
100593
- case "brief": return block.text ? block.text.split("\n").map((line) => line.length > 0 ? chalk.gray(line) : "") : [];
100594
- case "background_task": return [chalk.gray(`${block.status} ${block.kind} task ${block.task_id}: ${block.description}`)];
100595
- case "todo": return block.items.map((item) => chalk.gray(`- [${item.status}] ${item.title}`));
100754
+ case "brief": return block.text ? block.text.split("\n").map((line) => line.length > 0 ? chalk.whiteBright(line) : "") : [];
100755
+ case "background_task": return [chalk.whiteBright(`${block.status} ${block.kind} task ${block.task_id}: ${block.description}`)];
100756
+ case "todo": return block.items.map((item) => chalk.whiteBright(`- [${item.status}] ${item.title}`));
100596
100757
  default: return [];
100597
100758
  }
100598
100759
  }
@@ -100612,9 +100773,13 @@ function isDuplicateBriefBlock(block, description) {
100612
100773
  const borderColor = chalk.yellow;
100613
100774
  const selectColor = chalk.cyan;
100614
100775
  function headerFor(toolName) {
100615
- if (toolName === "ExitPlanMode") return "Approve this plan?";
100616
- if (toolName === "EnterPlanMode") return "Enter plan mode?";
100617
- return `${toolName} need approve?`;
100776
+ switch (toolName) {
100777
+ case "Bash": return "Run this command?";
100778
+ case "Write": return "Write this file?";
100779
+ case "Edit": return "Apply these edits?";
100780
+ case "TaskStop": return "Stop this task?";
100781
+ default: return `Approve ${toolName}?`;
100782
+ }
100618
100783
  }
100619
100784
  var ApprovalPanelComponent = class extends Container {
100620
100785
  focused = false;
@@ -100725,7 +100890,7 @@ var ApprovalPanelComponent = class extends Container {
100725
100890
  const labelWithNum = `${String(num)}. ${option.label}`;
100726
100891
  if (this.feedbackMode && option.requires_feedback === true && isSelected) lines.push(indent(this.renderInlineFeedbackLine(width - 2, labelWithNum)));
100727
100892
  else if (isSelected) lines.push(indent(`${selectColor.bold("▶")} ${selectColor.bold(labelWithNum)}`));
100728
- else lines.push(indent(chalk.gray(` ${labelWithNum}`)));
100893
+ else lines.push(indent(chalk.whiteBright(` ${labelWithNum}`)));
100729
100894
  }
100730
100895
  lines.push("");
100731
100896
  if (this.feedbackMode) lines.push(indent(chalk.dim("Type feedback · ↵ submit.")));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kfc-code-cli",
3
- "version": "0.0.1-alpha.8",
3
+ "version": "0.0.1-alpha.9",
4
4
  "description": "KFC crazy ",
5
5
  "license": "MIT",
6
6
  "bin": {