kfc-code-cli 0.0.1-alpha.7 → 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.
- package/dist/main.mjs +469 -184
- package/package.json +1 -1
package/dist/main.mjs
CHANGED
|
@@ -95084,26 +95084,21 @@ function pinoToLogger(p) {
|
|
|
95084
95084
|
async function createKimiAgent() {
|
|
95085
95085
|
const workDir = process.cwd();
|
|
95086
95086
|
const version = getVersion();
|
|
95087
|
-
const { client, dispose
|
|
95087
|
+
const { client, dispose, maxContextSize, defaultModel, defaultThinking, defaultYolo, defaultPlanMode, availableModels, syncSessionRuntime } = await createDefaultSoulPlusWireClient({
|
|
95088
95088
|
workspaceDir: workDir,
|
|
95089
95089
|
userAgent: `KimiCLI/${version}`,
|
|
95090
95090
|
defaultHeaders: buildKimiDefaultHeaders(version),
|
|
95091
95091
|
logger: pinoToLogger(getLogger()).child({ component: "session" })
|
|
95092
95092
|
});
|
|
95093
95093
|
client.onRequest("hook.request", async () => ({ ok: true }));
|
|
95094
|
-
const dispose = async () => {
|
|
95095
|
-
await disposeClient();
|
|
95096
|
-
};
|
|
95097
95094
|
return {
|
|
95098
95095
|
client,
|
|
95099
|
-
model:
|
|
95096
|
+
model: defaultModel,
|
|
95100
95097
|
defaultThinking,
|
|
95101
95098
|
defaultModes: {
|
|
95102
95099
|
yolo: defaultYolo,
|
|
95103
95100
|
planMode: defaultPlanMode
|
|
95104
95101
|
},
|
|
95105
|
-
theme,
|
|
95106
|
-
defaultEditor,
|
|
95107
95102
|
availableModels,
|
|
95108
95103
|
maxContextSize,
|
|
95109
95104
|
syncSessionRuntime,
|
|
@@ -95254,6 +95249,40 @@ function shellQuote(path) {
|
|
|
95254
95249
|
return `'${path.replace(/'/g, "'\\''")}'`;
|
|
95255
95250
|
}
|
|
95256
95251
|
//#endregion
|
|
95252
|
+
//#region src/tui/components/media/image-thumbnail.ts
|
|
95253
|
+
/**
|
|
95254
|
+
* Transcript-side rendering of a pasted image.
|
|
95255
|
+
*
|
|
95256
|
+
* On terminals that speak the Kitty graphics protocol or iTerm2 inline
|
|
95257
|
+
* image protocol (detected by pi-tui's `getCapabilities()`), we show
|
|
95258
|
+
* the actual image. Everywhere else we fall back to a one-line text
|
|
95259
|
+
* marker matching the placeholder the user sees in the input box —
|
|
95260
|
+
* this keeps the transcript readable on Terminal.app / Linux default
|
|
95261
|
+
* terminals / `script` recordings without extra chrome.
|
|
95262
|
+
*
|
|
95263
|
+
* Height is capped at ~12 rows so a single screenshot can't monopolize
|
|
95264
|
+
* the viewport; pi-tui handles proportional scaling internally.
|
|
95265
|
+
*/
|
|
95266
|
+
const MAX_IMAGE_ROWS = 12;
|
|
95267
|
+
var ImageThumbnail = class extends Container {
|
|
95268
|
+
constructor(attachment, colors) {
|
|
95269
|
+
super();
|
|
95270
|
+
const caps = getCapabilities();
|
|
95271
|
+
if (!(caps.images === "kitty" || caps.images === "iterm2")) {
|
|
95272
|
+
this.addChild(new Text(chalk.dim.cyan(` ${attachment.placeholder}`), 0, 0));
|
|
95273
|
+
return;
|
|
95274
|
+
}
|
|
95275
|
+
const image = new Image(Buffer.from(attachment.bytes).toString("base64"), attachment.mime, { fallbackColor: (s) => chalk.hex(colors.textDim)(s) }, {
|
|
95276
|
+
maxHeightCells: MAX_IMAGE_ROWS,
|
|
95277
|
+
filename: attachment.placeholder
|
|
95278
|
+
}, {
|
|
95279
|
+
widthPx: attachment.width,
|
|
95280
|
+
heightPx: attachment.height
|
|
95281
|
+
});
|
|
95282
|
+
this.addChild(image);
|
|
95283
|
+
}
|
|
95284
|
+
};
|
|
95285
|
+
//#endregion
|
|
95257
95286
|
//#region src/tui/components/messages/assistant-message.ts
|
|
95258
95287
|
const BULLET$1 = "⏺ ";
|
|
95259
95288
|
const INDENT$1 = " ";
|
|
@@ -95293,44 +95322,41 @@ var AssistantMessageComponent = class {
|
|
|
95293
95322
|
}
|
|
95294
95323
|
};
|
|
95295
95324
|
//#endregion
|
|
95296
|
-
//#region src/tui/components/
|
|
95325
|
+
//#region src/tui/components/messages/skill-activation.ts
|
|
95297
95326
|
/**
|
|
95298
|
-
*
|
|
95327
|
+
* Skill activation card.
|
|
95299
95328
|
*
|
|
95300
|
-
*
|
|
95301
|
-
*
|
|
95302
|
-
* the actual image. Everywhere else we fall back to a one-line text
|
|
95303
|
-
* marker matching the placeholder the user sees in the input box —
|
|
95304
|
-
* this keeps the transcript readable on Terminal.app / Linux default
|
|
95305
|
-
* terminals / `script` recordings without extra chrome.
|
|
95329
|
+
* 用户跑 `/skill:foo bar` 时不再把 SKILL.md 正文铺在 user 气泡里 ——
|
|
95330
|
+
* 只显示一张紧凑卡片:
|
|
95306
95331
|
*
|
|
95307
|
-
*
|
|
95308
|
-
*
|
|
95332
|
+
* ▶ Activated skill: foo
|
|
95333
|
+
* bar
|
|
95334
|
+
*
|
|
95335
|
+
* 第二行(args)可省。skill 正文已经经由 `client.prompt` 进了 LLM
|
|
95336
|
+
* 的上下文,用户视角无需再看到。
|
|
95337
|
+
*
|
|
95338
|
+
* Resume 重放仍会通过磁盘上的 user_message WAL 把 skill 正文当 user
|
|
95339
|
+
* 消息渲染(核心层未引入 skill_activated WAL 类型)—— 视为已知限制。
|
|
95309
95340
|
*/
|
|
95310
|
-
const
|
|
95311
|
-
var
|
|
95312
|
-
constructor(
|
|
95341
|
+
const ARGS_PREVIEW_MAX = 200;
|
|
95342
|
+
var SkillActivationComponent = class extends Container {
|
|
95343
|
+
constructor(name, args, colors) {
|
|
95313
95344
|
super();
|
|
95314
|
-
|
|
95315
|
-
|
|
95316
|
-
|
|
95317
|
-
|
|
95345
|
+
this.addChild(new Spacer(1));
|
|
95346
|
+
const head = chalk.hex(colors.primary).bold("▶ Activated skill: ") + chalk.hex(colors.user).bold(name);
|
|
95347
|
+
this.addChild(new Text(head, 0, 0));
|
|
95348
|
+
const trimmed = args?.trim() ?? "";
|
|
95349
|
+
if (trimmed.length > 0) {
|
|
95350
|
+
const preview = trimmed.length > ARGS_PREVIEW_MAX ? trimmed.slice(0, ARGS_PREVIEW_MAX) + "…" : trimmed;
|
|
95351
|
+
this.addChild(new Text(" " + chalk.hex(colors.textDim)(preview), 0, 0));
|
|
95318
95352
|
}
|
|
95319
|
-
const image = new Image(Buffer.from(attachment.bytes).toString("base64"), attachment.mime, { fallbackColor: (s) => chalk.hex(colors.textDim)(s) }, {
|
|
95320
|
-
maxHeightCells: MAX_IMAGE_ROWS,
|
|
95321
|
-
filename: attachment.placeholder
|
|
95322
|
-
}, {
|
|
95323
|
-
widthPx: attachment.width,
|
|
95324
|
-
heightPx: attachment.height
|
|
95325
|
-
});
|
|
95326
|
-
this.addChild(image);
|
|
95327
95353
|
}
|
|
95328
95354
|
};
|
|
95329
95355
|
//#endregion
|
|
95330
95356
|
//#region src/tui/components/messages/thinking.ts
|
|
95331
95357
|
const BULLET = "⏺ ";
|
|
95332
95358
|
const INDENT = " ";
|
|
95333
|
-
const PREVIEW_LINES
|
|
95359
|
+
const PREVIEW_LINES = 3;
|
|
95334
95360
|
const SPINNER_FRAMES = [
|
|
95335
95361
|
"⠋",
|
|
95336
95362
|
"⠙",
|
|
@@ -95381,10 +95407,10 @@ var ThinkingComponent = class {
|
|
|
95381
95407
|
const textComponent = new Text(chalk.hex(this.color).italic(this.text), 0, 0);
|
|
95382
95408
|
const contentLines = this.text.length > 0 ? textComponent.render(contentWidth) : [""];
|
|
95383
95409
|
if (this.mode === "live") {
|
|
95384
|
-
const visibleLines = contentLines.length > PREVIEW_LINES
|
|
95410
|
+
const visibleLines = contentLines.length > PREVIEW_LINES ? contentLines.slice(contentLines.length - PREVIEW_LINES) : contentLines;
|
|
95385
95411
|
return [
|
|
95386
95412
|
"",
|
|
95387
|
-
|
|
95413
|
+
chalk.hex(this.color)(`${SPINNER_FRAMES[this.spinnerFrame] ?? SPINNER_FRAMES[0]} `) + chalk.hex(this.color)("thinking..."),
|
|
95388
95414
|
...visibleLines.map((line) => INDENT + line)
|
|
95389
95415
|
];
|
|
95390
95416
|
}
|
|
@@ -95393,9 +95419,9 @@ var ThinkingComponent = class {
|
|
|
95393
95419
|
const p = i === 0 && this.showMarker ? chalk.hex(this.color)(BULLET) : INDENT;
|
|
95394
95420
|
rendered.push(p + contentLines[i]);
|
|
95395
95421
|
}
|
|
95396
|
-
if (this.expanded || contentLines.length <= PREVIEW_LINES
|
|
95397
|
-
const truncated = rendered.slice(0, 1 + PREVIEW_LINES
|
|
95398
|
-
const remaining = contentLines.length - PREVIEW_LINES
|
|
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;
|
|
95399
95425
|
truncated.push(INDENT + chalk.dim(`... (${String(remaining)} more lines, ctrl+o to expand)`));
|
|
95400
95426
|
return truncated;
|
|
95401
95427
|
}
|
|
@@ -95524,13 +95550,174 @@ var PlanBoxComponent = class {
|
|
|
95524
95550
|
}
|
|
95525
95551
|
};
|
|
95526
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
|
|
95527
95715
|
//#region src/tui/components/messages/tool-call.ts
|
|
95528
95716
|
/**
|
|
95529
95717
|
* Renders a tool call entry in the transcript.
|
|
95530
95718
|
* Supports expand/collapse via Ctrl+O.
|
|
95531
95719
|
*/
|
|
95532
95720
|
const MAX_ARG_LENGTH = 60;
|
|
95533
|
-
const PREVIEW_LINES = 3;
|
|
95534
95721
|
const CALL_PREVIEW_LINES = 10;
|
|
95535
95722
|
const BLINK_INTERVAL$1 = 500;
|
|
95536
95723
|
const MAX_SUB_TOOL_CALLS_SHOWN = 4;
|
|
@@ -95586,7 +95773,7 @@ function extractApprovedPlan(output) {
|
|
|
95586
95773
|
}
|
|
95587
95774
|
const STREAMING_FIELD_RE$1 = /"(path|file_path|command|pattern|query|url|description|title|name)"\s*:\s*"((?:\\.|[^"\\])*)"/g;
|
|
95588
95775
|
function unescapeJsonString$1(s) {
|
|
95589
|
-
return s.
|
|
95776
|
+
return s.replaceAll(/\\(["\\/bfnrt])/g, (_, ch) => {
|
|
95590
95777
|
switch (ch) {
|
|
95591
95778
|
case "n": return "\n";
|
|
95592
95779
|
case "t": return " ";
|
|
@@ -95648,7 +95835,7 @@ function extractPartialStringField(text, key) {
|
|
|
95648
95835
|
const hex = text.slice(i + 2, i + 6);
|
|
95649
95836
|
const code = Number.parseInt(hex, 16);
|
|
95650
95837
|
if (Number.isNaN(code)) return out;
|
|
95651
|
-
out += String.
|
|
95838
|
+
out += String.fromCodePoint(code);
|
|
95652
95839
|
i += 6;
|
|
95653
95840
|
continue;
|
|
95654
95841
|
}
|
|
@@ -95680,14 +95867,10 @@ function parseArgsPreview(value) {
|
|
|
95680
95867
|
}
|
|
95681
95868
|
function extractKeyArgument(toolName, args) {
|
|
95682
95869
|
const candidates = {
|
|
95683
|
-
Shell: ["command"],
|
|
95684
95870
|
Bash: ["command"],
|
|
95685
|
-
ReadFile: ["path", "file_path"],
|
|
95686
95871
|
Read: ["path", "file_path"],
|
|
95687
95872
|
Write: ["path", "file_path"],
|
|
95688
|
-
WriteFile: ["path", "file_path"],
|
|
95689
95873
|
Edit: ["path", "file_path"],
|
|
95690
|
-
EditFile: ["path", "file_path"],
|
|
95691
95874
|
Grep: ["pattern"],
|
|
95692
95875
|
Glob: ["pattern"],
|
|
95693
95876
|
FetchURL: ["url"],
|
|
@@ -95864,7 +96047,15 @@ var ToolCallComponent = class extends Container {
|
|
|
95864
96047
|
const keyArg = extractKeyArgument(toolCall.name, toolCall.args);
|
|
95865
96048
|
const toolRef = chalk.hex(colors.primary).bold(toolCall.name);
|
|
95866
96049
|
const argStr = keyArg ? chalk.dim(` (${keyArg})`) : "";
|
|
95867
|
-
|
|
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}`);
|
|
95868
96059
|
}
|
|
95869
96060
|
rebuildContent() {
|
|
95870
96061
|
while (this.children.length > this.callPreviewEndIndex) this.children.pop();
|
|
@@ -95919,7 +96110,7 @@ var ToolCallComponent = class extends Container {
|
|
|
95919
96110
|
this.buildStreamingPreview(this.toolCall.streamingArguments);
|
|
95920
96111
|
return;
|
|
95921
96112
|
}
|
|
95922
|
-
if (name === "Write"
|
|
96113
|
+
if (name === "Write") {
|
|
95923
96114
|
const content = str(this.toolCall.args["content"]);
|
|
95924
96115
|
if (content.length === 0) return;
|
|
95925
96116
|
const allLines = highlightLines(content, langFromPath(str(this.toolCall.args["file_path"] ?? this.toolCall.args["path"])));
|
|
@@ -95930,7 +96121,7 @@ var ToolCallComponent = class extends Container {
|
|
|
95930
96121
|
this.addChild(new Text(lineNum + line, 2, 0));
|
|
95931
96122
|
}
|
|
95932
96123
|
if (remaining > 0) this.addChild(new Text(chalk.dim(`... (${String(remaining)} more lines, ${String(allLines.length)} total)`), 2, 0));
|
|
95933
|
-
} else if (name === "Edit"
|
|
96124
|
+
} else if (name === "Edit") {
|
|
95934
96125
|
const oldStr = str(this.toolCall.args["old_string"]);
|
|
95935
96126
|
const newStr = str(this.toolCall.args["new_string"]);
|
|
95936
96127
|
if (oldStr.length === 0 && newStr.length === 0) return;
|
|
@@ -95954,14 +96145,14 @@ var ToolCallComponent = class extends Container {
|
|
|
95954
96145
|
*/
|
|
95955
96146
|
buildStreamingPreview(streamText) {
|
|
95956
96147
|
const name = this.toolCall.name;
|
|
95957
|
-
if (name === "Write"
|
|
96148
|
+
if (name === "Write") {
|
|
95958
96149
|
const content = extractPartialStringField(streamText, "content");
|
|
95959
96150
|
if (content === void 0 || content.length === 0) return;
|
|
95960
96151
|
const filePath = extractPartialStringField(streamText, "file_path") ?? extractPartialStringField(streamText, "path") ?? "";
|
|
95961
96152
|
this.renderStreamingCode(content, filePath);
|
|
95962
96153
|
return;
|
|
95963
96154
|
}
|
|
95964
|
-
if (name === "Edit"
|
|
96155
|
+
if (name === "Edit") {
|
|
95965
96156
|
const oldStr = extractPartialStringField(streamText, "old_string") ?? "";
|
|
95966
96157
|
const newStr = extractPartialStringField(streamText, "new_string") ?? "";
|
|
95967
96158
|
if (oldStr.length === 0 && newStr.length === 0) return;
|
|
@@ -95972,7 +96163,7 @@ var ToolCallComponent = class extends Container {
|
|
|
95972
96163
|
if (remaining > 0) this.addChild(new Text(chalk.dim(`... (${String(remaining)} more lines)`), 2, 0));
|
|
95973
96164
|
return;
|
|
95974
96165
|
}
|
|
95975
|
-
if (name === "Bash"
|
|
96166
|
+
if (name === "Bash") {
|
|
95976
96167
|
const cmd = extractPartialStringField(streamText, "command");
|
|
95977
96168
|
if (cmd === void 0 || cmd.length === 0) return;
|
|
95978
96169
|
const lines = cmd.split("\n").slice(0, CALL_PREVIEW_LINES);
|
|
@@ -96014,15 +96205,11 @@ var ToolCallComponent = class extends Container {
|
|
|
96014
96205
|
}
|
|
96015
96206
|
if (this.toolCall.name === "SetTodoList" && !result.is_error) return;
|
|
96016
96207
|
if (this.toolCall.name === "AskUserQuestion" && !result.is_error && this.renderAskUserQuestionResult(result.output)) return;
|
|
96017
|
-
const
|
|
96018
|
-
|
|
96019
|
-
|
|
96020
|
-
|
|
96021
|
-
|
|
96022
|
-
const remaining = lines.length - shown.length;
|
|
96023
|
-
this.addChild(new Text(tint(shown.join("\n")), 2, 0));
|
|
96024
|
-
if (remaining > 0) this.addChild(new Text(chalk.dim(`... (${String(remaining)} more lines, ctrl+o to expand)`), 2, 0));
|
|
96025
|
-
}
|
|
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);
|
|
96026
96213
|
}
|
|
96027
96214
|
/**
|
|
96028
96215
|
* Render AskUserQuestion's JSON payload as a friendly Q/A list.
|
|
@@ -96101,10 +96288,11 @@ var WelcomeComponent = class {
|
|
|
96101
96288
|
"",
|
|
96102
96289
|
...infoLines
|
|
96103
96290
|
];
|
|
96104
|
-
const lines = [
|
|
96105
|
-
|
|
96106
|
-
|
|
96107
|
-
|
|
96291
|
+
const lines = [
|
|
96292
|
+
"",
|
|
96293
|
+
primary("╭" + "─".repeat(width - 2) + "╮"),
|
|
96294
|
+
primary("│") + " ".repeat(width - 2) + primary("│")
|
|
96295
|
+
];
|
|
96108
96296
|
for (const content of contentLines) {
|
|
96109
96297
|
const truncated = truncateToWidth(content, innerWidth, "…");
|
|
96110
96298
|
const vis = visibleWidth(truncated);
|
|
@@ -96250,6 +96438,7 @@ function createTranscriptComponent(state, entry) {
|
|
|
96250
96438
|
}
|
|
96251
96439
|
return msg;
|
|
96252
96440
|
}
|
|
96441
|
+
case "skill_activation": return new SkillActivationComponent(entry.skillName ?? entry.content, entry.skillArgs, state.colors);
|
|
96253
96442
|
case "assistant": return createAssistantEntry(state, entry.content);
|
|
96254
96443
|
case "thinking": return new ThinkingComponent(entry.content, state.colors, true);
|
|
96255
96444
|
case "tool_call":
|
|
@@ -96392,7 +96581,7 @@ function buildImagePart(att) {
|
|
|
96392
96581
|
}
|
|
96393
96582
|
//#endregion
|
|
96394
96583
|
//#region src/tui/theme/pi-tui-theme.ts
|
|
96395
|
-
const HEADING_HASH_PREFIX = /^((?:\
|
|
96584
|
+
const HEADING_HASH_PREFIX = /^((?:\x1B\[[0-9;]*m)*)#{1,6}[ \t]+/;
|
|
96396
96585
|
function createMarkdownTheme(colors) {
|
|
96397
96586
|
const stripHash = (text) => text.replace(HEADING_HASH_PREFIX, "$1");
|
|
96398
96587
|
return {
|
|
@@ -96638,7 +96827,7 @@ function fetchSnapshot(gitRoot) {
|
|
|
96638
96827
|
const seen = /* @__PURE__ */ new Set();
|
|
96639
96828
|
for (const path of tracked) seen.add(path);
|
|
96640
96829
|
for (const path of untracked) seen.add(path);
|
|
96641
|
-
const merged = [...seen].
|
|
96830
|
+
const merged = [...seen].toSorted();
|
|
96642
96831
|
const files = merged.length > MAX_ENTRIES ? merged.slice(0, MAX_ENTRIES) : merged;
|
|
96643
96832
|
return {
|
|
96644
96833
|
files,
|
|
@@ -96794,6 +96983,7 @@ function createAuthCommands(deps = {}) {
|
|
|
96794
96983
|
aliases: [],
|
|
96795
96984
|
description: "Clear OAuth credentials",
|
|
96796
96985
|
mode: "both",
|
|
96986
|
+
priority: 40,
|
|
96797
96987
|
async execute(_args, _ctx) {
|
|
96798
96988
|
if (deps.client === void 0) return ok$2("OAuth is unavailable: no wire client is attached.");
|
|
96799
96989
|
if (!(await deps.client.authStatus(providerName)).providers.some((provider) => provider.provider_name === providerName && provider.has_token)) return ok$2("Not logged in.");
|
|
@@ -96805,6 +96995,7 @@ function createAuthCommands(deps = {}) {
|
|
|
96805
96995
|
aliases: [],
|
|
96806
96996
|
description: "Start OAuth device code login flow",
|
|
96807
96997
|
mode: "both",
|
|
96998
|
+
priority: 40,
|
|
96808
96999
|
async execute(_args, ctx) {
|
|
96809
97000
|
if (deps.client === void 0) return ok$2("OAuth is unavailable: no wire client is attached.");
|
|
96810
97001
|
const disposeDeviceCodeHandler = deps.client.onRequest("auth.device_code", (req) => {
|
|
@@ -96853,6 +97044,7 @@ const shellCommands = [
|
|
|
96853
97044
|
aliases: ["quit", "q"],
|
|
96854
97045
|
description: "Exit the application",
|
|
96855
97046
|
mode: "both",
|
|
97047
|
+
priority: 20,
|
|
96856
97048
|
async execute() {
|
|
96857
97049
|
return { type: "exit" };
|
|
96858
97050
|
}
|
|
@@ -96862,6 +97054,7 @@ const shellCommands = [
|
|
|
96862
97054
|
aliases: ["h", "?"],
|
|
96863
97055
|
description: "Show available commands and shortcuts",
|
|
96864
97056
|
mode: "both",
|
|
97057
|
+
priority: 80,
|
|
96865
97058
|
async execute(_args, _ctx) {
|
|
96866
97059
|
return ok$1("__show_help__");
|
|
96867
97060
|
}
|
|
@@ -96871,6 +97064,7 @@ const shellCommands = [
|
|
|
96871
97064
|
aliases: [],
|
|
96872
97065
|
description: "Show version information",
|
|
96873
97066
|
mode: "both",
|
|
97067
|
+
priority: 20,
|
|
96874
97068
|
async execute(_args, ctx) {
|
|
96875
97069
|
return ok$1(`Kimi Code v${ctx.appState.version}`);
|
|
96876
97070
|
}
|
|
@@ -96880,6 +97074,7 @@ const shellCommands = [
|
|
|
96880
97074
|
aliases: [],
|
|
96881
97075
|
description: "Start a fresh session in the current workspace",
|
|
96882
97076
|
mode: "both",
|
|
97077
|
+
priority: 80,
|
|
96883
97078
|
async execute() {
|
|
96884
97079
|
return {
|
|
96885
97080
|
type: "reload",
|
|
@@ -96892,6 +97087,7 @@ const shellCommands = [
|
|
|
96892
97087
|
aliases: ["resume"],
|
|
96893
97088
|
description: "Browse and resume sessions",
|
|
96894
97089
|
mode: "both",
|
|
97090
|
+
priority: 80,
|
|
96895
97091
|
async execute(_args, _ctx) {
|
|
96896
97092
|
return ok$1("__show_sessions__");
|
|
96897
97093
|
}
|
|
@@ -96901,6 +97097,7 @@ const shellCommands = [
|
|
|
96901
97097
|
aliases: ["rename"],
|
|
96902
97098
|
description: "Set or show session title",
|
|
96903
97099
|
mode: "both",
|
|
97100
|
+
priority: 60,
|
|
96904
97101
|
async execute(args, ctx) {
|
|
96905
97102
|
const trimmed = args.trim();
|
|
96906
97103
|
if (trimmed.length === 0) {
|
|
@@ -96921,6 +97118,7 @@ const shellCommands = [
|
|
|
96921
97118
|
aliases: ["yes"],
|
|
96922
97119
|
description: "Toggle auto-approve mode",
|
|
96923
97120
|
mode: "both",
|
|
97121
|
+
priority: 100,
|
|
96924
97122
|
async execute(args, ctx) {
|
|
96925
97123
|
let enabled;
|
|
96926
97124
|
if (args === "on") enabled = true;
|
|
@@ -96937,6 +97135,7 @@ const shellCommands = [
|
|
|
96937
97135
|
aliases: [],
|
|
96938
97136
|
description: "Toggle plan mode",
|
|
96939
97137
|
mode: "both",
|
|
97138
|
+
priority: 100,
|
|
96940
97139
|
async execute(args, ctx) {
|
|
96941
97140
|
const subcmd = args.trim().toLowerCase();
|
|
96942
97141
|
if (subcmd === "view") {
|
|
@@ -96964,6 +97163,7 @@ const shellCommands = [
|
|
|
96964
97163
|
aliases: [],
|
|
96965
97164
|
description: "Switch LLM model",
|
|
96966
97165
|
mode: "both",
|
|
97166
|
+
priority: 100,
|
|
96967
97167
|
async execute(args, ctx) {
|
|
96968
97168
|
const trimmed = args.trim();
|
|
96969
97169
|
if (trimmed.length === 0) return ok$1("__show_model_picker__");
|
|
@@ -96976,6 +97176,7 @@ const shellCommands = [
|
|
|
96976
97176
|
aliases: ["status"],
|
|
96977
97177
|
description: "Show session tokens + context window + plan quotas",
|
|
96978
97178
|
mode: "both",
|
|
97179
|
+
priority: 60,
|
|
96979
97180
|
async execute() {
|
|
96980
97181
|
return ok$1("__show_usage__");
|
|
96981
97182
|
}
|
|
@@ -96995,6 +97196,7 @@ const soulCommands = [{
|
|
|
96995
97196
|
aliases: [],
|
|
96996
97197
|
description: "Compact the conversation context",
|
|
96997
97198
|
mode: "both",
|
|
97199
|
+
priority: 80,
|
|
96998
97200
|
async execute(args, ctx) {
|
|
96999
97201
|
const customInstruction = args.trim() || void 0;
|
|
97000
97202
|
await ctx.client.compact(ctx.appState.sessionId, customInstruction);
|
|
@@ -97077,11 +97279,17 @@ var SlashCommandRegistry = class {
|
|
|
97077
97279
|
}
|
|
97078
97280
|
return [...bestScores.values()].toSorted((a, b) => b.score - a.score || a.def.name.localeCompare(b.def.name)).map(({ def }) => def);
|
|
97079
97281
|
}
|
|
97080
|
-
/**
|
|
97282
|
+
/**
|
|
97283
|
+
* List all registered commands, optionally filtered by mode.
|
|
97284
|
+
* Built-in commands come first, sorted alphabetically; skill commands
|
|
97285
|
+
* follow in their original registration order.
|
|
97286
|
+
*/
|
|
97081
97287
|
listAll(mode) {
|
|
97082
97288
|
const all = [...this.commands.values()];
|
|
97083
|
-
|
|
97084
|
-
|
|
97289
|
+
const filtered = mode === void 0 ? all : all.filter((def) => def.mode === mode || def.mode === "both");
|
|
97290
|
+
const builtins = filtered.filter((def) => !def.name.startsWith(SKILL_COMMAND_PREFIX)).toSorted((a, b) => (b.priority ?? 0) - (a.priority ?? 0) || a.name.localeCompare(b.name));
|
|
97291
|
+
const skills = filtered.filter((def) => def.name.startsWith(SKILL_COMMAND_PREFIX));
|
|
97292
|
+
return [...builtins, ...skills];
|
|
97085
97293
|
}
|
|
97086
97294
|
/** Get the number of registered commands. */
|
|
97087
97295
|
get size() {
|
|
@@ -97652,9 +97860,7 @@ var TodoPanelComponent = class {
|
|
|
97652
97860
|
render(width) {
|
|
97653
97861
|
if (this.todos.length === 0) return [];
|
|
97654
97862
|
const c = this.colors;
|
|
97655
|
-
const lines = [];
|
|
97656
|
-
lines.push(chalk.hex(c.border)("─".repeat(width)));
|
|
97657
|
-
lines.push(chalk.hex(c.primary).bold(" Todo"));
|
|
97863
|
+
const lines = [chalk.hex(c.border)("─".repeat(width)), chalk.hex(c.primary).bold(" Todo")];
|
|
97658
97864
|
for (const todo of this.todos) lines.push(renderRow(todo, c));
|
|
97659
97865
|
return lines.map((line) => truncateToWidth(line, width));
|
|
97660
97866
|
}
|
|
@@ -97766,18 +97972,18 @@ var QuestionController = class extends ReverseRpcController {
|
|
|
97766
97972
|
//#endregion
|
|
97767
97973
|
//#region src/tui/theme/colors.ts
|
|
97768
97974
|
const darkColors = {
|
|
97769
|
-
primary: "#
|
|
97770
|
-
primaryDim: "#
|
|
97975
|
+
primary: "#4FA8FF",
|
|
97976
|
+
primaryDim: "#2563EB",
|
|
97771
97977
|
text: "#E0E0E0",
|
|
97772
97978
|
textDim: "#888888",
|
|
97773
97979
|
textMuted: "#555555",
|
|
97774
97980
|
success: "#4EC87E",
|
|
97775
97981
|
warning: "#E8A838",
|
|
97776
97982
|
error: "#E85454",
|
|
97777
|
-
info: "#
|
|
97983
|
+
info: "#4FA8FF",
|
|
97778
97984
|
border: "#444444",
|
|
97779
|
-
prompt: "#
|
|
97780
|
-
spinner: "#
|
|
97985
|
+
prompt: "#4FA8FF",
|
|
97986
|
+
spinner: "#4FA8FF",
|
|
97781
97987
|
user: "#FFCB6B",
|
|
97782
97988
|
assistant: "#E0E0E0",
|
|
97783
97989
|
thinking: "#888888",
|
|
@@ -98024,7 +98230,7 @@ function enqueueMessage(state, text) {
|
|
|
98024
98230
|
}
|
|
98025
98231
|
function recallLastQueued(state) {
|
|
98026
98232
|
if (state.queuedMessages.length === 0) return void 0;
|
|
98027
|
-
const last = state.queuedMessages
|
|
98233
|
+
const last = state.queuedMessages.at(-1);
|
|
98028
98234
|
state.queuedMessages = state.queuedMessages.slice(0, -1);
|
|
98029
98235
|
return last.text;
|
|
98030
98236
|
}
|
|
@@ -98090,6 +98296,66 @@ function sendMessageInternal(state, addEntry, input, options) {
|
|
|
98090
98296
|
});
|
|
98091
98297
|
});
|
|
98092
98298
|
}
|
|
98299
|
+
/**
|
|
98300
|
+
* Activate a skill: render a compact activation card (no skill body in
|
|
98301
|
+
* the transcript) and forward the prepared prompt — `skill.content +
|
|
98302
|
+
* "\n\nUser request:\n" + args` — to core via `client.prompt`. Keeps
|
|
98303
|
+
* the skill body out of the user-visible transcript while still feeding
|
|
98304
|
+
* it into the LLM exactly as the legacy path did.
|
|
98305
|
+
*/
|
|
98306
|
+
function sendSkillActivation(state, addEntry, skillName, skillArgs, fullPrompt) {
|
|
98307
|
+
addEntry({
|
|
98308
|
+
id: nextTranscriptId(),
|
|
98309
|
+
kind: "skill_activation",
|
|
98310
|
+
turnId: void 0,
|
|
98311
|
+
renderMode: "plain",
|
|
98312
|
+
content: `Activated skill: ${skillName}`,
|
|
98313
|
+
skillName,
|
|
98314
|
+
skillArgs
|
|
98315
|
+
});
|
|
98316
|
+
state.currentTurnId = void 0;
|
|
98317
|
+
state.assistantDraft = "";
|
|
98318
|
+
state.assistantStreamActive = false;
|
|
98319
|
+
state.thinkingDraft = "";
|
|
98320
|
+
disposeActiveThinkingComponent(state);
|
|
98321
|
+
state.activeToolCalls.clear();
|
|
98322
|
+
state.streamingToolCallArguments.clear();
|
|
98323
|
+
state.livePane = {
|
|
98324
|
+
...state.livePane,
|
|
98325
|
+
mode: "waiting",
|
|
98326
|
+
thinkingText: "",
|
|
98327
|
+
assistantText: "",
|
|
98328
|
+
pendingToolCall: null,
|
|
98329
|
+
pendingApproval: null,
|
|
98330
|
+
pendingQuestion: null
|
|
98331
|
+
};
|
|
98332
|
+
state.appState.isStreaming = true;
|
|
98333
|
+
state.appState.streamingPhase = "waiting";
|
|
98334
|
+
state.appState.streamingStartTime = Date.now();
|
|
98335
|
+
state.footer.setState(state.appState);
|
|
98336
|
+
state.ui.requestRender();
|
|
98337
|
+
state.client.prompt(state.appState.sessionId, { input: fullPrompt }).catch((error) => {
|
|
98338
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
98339
|
+
state.appState.isStreaming = false;
|
|
98340
|
+
state.appState.streamingPhase = "idle";
|
|
98341
|
+
state.livePane = {
|
|
98342
|
+
mode: "idle",
|
|
98343
|
+
thinkingText: "",
|
|
98344
|
+
assistantText: "",
|
|
98345
|
+
pendingToolCall: null,
|
|
98346
|
+
pendingApproval: null,
|
|
98347
|
+
pendingQuestion: null
|
|
98348
|
+
};
|
|
98349
|
+
state.footer.setState(state.appState);
|
|
98350
|
+
addEntry({
|
|
98351
|
+
id: nextTranscriptId(),
|
|
98352
|
+
kind: "status",
|
|
98353
|
+
renderMode: "plain",
|
|
98354
|
+
content: `Skill "${skillName}" failed: ${message}`,
|
|
98355
|
+
color: state.colors.error
|
|
98356
|
+
});
|
|
98357
|
+
});
|
|
98358
|
+
}
|
|
98093
98359
|
/** Send from user input: enqueue if busy, otherwise send immediately. */
|
|
98094
98360
|
function sendMessage(state, addEntry, input, options) {
|
|
98095
98361
|
if (state.appState.isStreaming || state.appState.isCompacting) {
|
|
@@ -98789,36 +99055,71 @@ function endCompaction(state, tokensBefore, tokensAfter) {
|
|
|
98789
99055
|
state.ui.requestRender();
|
|
98790
99056
|
}
|
|
98791
99057
|
//#endregion
|
|
99058
|
+
//#region src/tui/commands/skill-commands.ts
|
|
99059
|
+
const SKILL_ACTIVATION_SENTINEL_PREFIX = "__activate_skill__:";
|
|
99060
|
+
async function fetchSkills(client, sessionId) {
|
|
99061
|
+
const skills = (await client.listSkills(sessionId))?.skills ?? [];
|
|
99062
|
+
const out = [];
|
|
99063
|
+
for (const s of skills) {
|
|
99064
|
+
if (typeof s?.name !== "string" || s.name.length === 0) continue;
|
|
99065
|
+
if (typeof s.content !== "string") continue;
|
|
99066
|
+
out.push({
|
|
99067
|
+
name: s.name,
|
|
99068
|
+
content: s.content,
|
|
99069
|
+
...typeof s.description === "string" ? { description: s.description } : {}
|
|
99070
|
+
});
|
|
99071
|
+
}
|
|
99072
|
+
return out;
|
|
99073
|
+
}
|
|
99074
|
+
function buildSkillCommand(skill) {
|
|
99075
|
+
return {
|
|
99076
|
+
name: `${SKILL_COMMAND_PREFIX}${skill.name}`,
|
|
99077
|
+
aliases: [],
|
|
99078
|
+
description: skill.description ?? "",
|
|
99079
|
+
mode: "both",
|
|
99080
|
+
async execute(args) {
|
|
99081
|
+
const trimmed = args.trim();
|
|
99082
|
+
const prompt = trimmed.length > 0 ? `${skill.content}\n\nUser request:\n${trimmed}` : skill.content;
|
|
99083
|
+
const payload = {
|
|
99084
|
+
name: skill.name,
|
|
99085
|
+
args: trimmed,
|
|
99086
|
+
prompt
|
|
99087
|
+
};
|
|
99088
|
+
return {
|
|
99089
|
+
type: "ok",
|
|
99090
|
+
message: `${SKILL_ACTIVATION_SENTINEL_PREFIX}${JSON.stringify(payload)}`
|
|
99091
|
+
};
|
|
99092
|
+
}
|
|
99093
|
+
};
|
|
99094
|
+
}
|
|
99095
|
+
//#endregion
|
|
98792
99096
|
//#region src/tui/commands/skill-dispatch.ts
|
|
98793
99097
|
/**
|
|
98794
|
-
*
|
|
99098
|
+
* 探测 `/name args` 是否对应某个 skill。命中返回 activate(含拼好的
|
|
99099
|
+
* prompt);未命中或查询失败返回 unknown,message 由调用方推到 transcript。
|
|
98795
99100
|
*/
|
|
98796
99101
|
async function tryDispatchSkill(client, sessionId, name, args) {
|
|
98797
99102
|
let skills;
|
|
98798
99103
|
try {
|
|
98799
99104
|
skills = (await client.listSkills(sessionId))?.skills ?? [];
|
|
98800
|
-
} catch (
|
|
99105
|
+
} catch (error) {
|
|
98801
99106
|
return {
|
|
98802
|
-
|
|
98803
|
-
message: `Unknown command: /${name} (skill lookup failed: ${
|
|
99107
|
+
kind: "unknown",
|
|
99108
|
+
message: `Unknown command: /${name} (skill lookup failed: ${error instanceof Error ? error.message : String(error)})`
|
|
98804
99109
|
};
|
|
98805
99110
|
}
|
|
98806
|
-
|
|
98807
|
-
|
|
99111
|
+
const skill = skills.find((s) => s.name === name);
|
|
99112
|
+
if (skill === void 0 || typeof skill.content !== "string") return {
|
|
99113
|
+
kind: "unknown",
|
|
98808
99114
|
message: `Unknown command: /${name}`
|
|
98809
99115
|
};
|
|
98810
|
-
|
|
98811
|
-
|
|
98812
|
-
|
|
98813
|
-
|
|
98814
|
-
|
|
98815
|
-
}
|
|
98816
|
-
}
|
|
98817
|
-
return {
|
|
98818
|
-
matched: true,
|
|
98819
|
-
message: `Skill "${name}" failed: ${err instanceof Error ? err.message : String(err)}`
|
|
98820
|
-
};
|
|
98821
|
-
}
|
|
99116
|
+
const trimmed = args.trim();
|
|
99117
|
+
return {
|
|
99118
|
+
kind: "activate",
|
|
99119
|
+
name,
|
|
99120
|
+
args: trimmed,
|
|
99121
|
+
prompt: trimmed.length > 0 ? `${skill.content}\n\nUser request:\n${trimmed}` : skill.content
|
|
99122
|
+
};
|
|
98822
99123
|
}
|
|
98823
99124
|
//#endregion
|
|
98824
99125
|
//#region src/tui/commands/dispatch.ts
|
|
@@ -98827,7 +99128,12 @@ async function dispatchSlashCommand(input, state, buildCtx, addEntry) {
|
|
|
98827
99128
|
if (!parsed) return false;
|
|
98828
99129
|
const def = state.registry.find(parsed.name);
|
|
98829
99130
|
if (!def) {
|
|
99131
|
+
const ctx = buildCtx();
|
|
98830
99132
|
const result = await tryDispatchSkill(state.client, state.appState.sessionId, parsed.name, parsed.args);
|
|
99133
|
+
if (result.kind === "activate") {
|
|
99134
|
+
ctx.activateSkill(result.name, result.args, result.prompt);
|
|
99135
|
+
return true;
|
|
99136
|
+
}
|
|
98831
99137
|
addEntry({
|
|
98832
99138
|
id: `slash-${Date.now()}`,
|
|
98833
99139
|
kind: "status",
|
|
@@ -98895,6 +99201,24 @@ async function dispatchSlashCommand(input, state, buildCtx, addEntry) {
|
|
|
98895
99201
|
ctx.sendAsMessage(msg);
|
|
98896
99202
|
return true;
|
|
98897
99203
|
}
|
|
99204
|
+
if (result.message.startsWith("__activate_skill__:")) {
|
|
99205
|
+
const raw = result.message.slice(19);
|
|
99206
|
+
let payload;
|
|
99207
|
+
try {
|
|
99208
|
+
payload = JSON.parse(raw);
|
|
99209
|
+
} catch (error) {
|
|
99210
|
+
addEntry({
|
|
99211
|
+
id: `slash-err-${Date.now()}`,
|
|
99212
|
+
kind: "status",
|
|
99213
|
+
renderMode: "plain",
|
|
99214
|
+
content: `Skill activation failed: malformed payload (${error instanceof Error ? error.message : String(error)})`,
|
|
99215
|
+
color: state.colors.error
|
|
99216
|
+
});
|
|
99217
|
+
return true;
|
|
99218
|
+
}
|
|
99219
|
+
ctx.activateSkill(payload.name, payload.args, payload.prompt);
|
|
99220
|
+
return true;
|
|
99221
|
+
}
|
|
98898
99222
|
addEntry({
|
|
98899
99223
|
id: `slash-${Date.now()}`,
|
|
98900
99224
|
kind: "status",
|
|
@@ -98986,7 +99310,7 @@ function handleContentDelta(ectx, data) {
|
|
|
98986
99310
|
//#region src/tui/handlers/tool.ts
|
|
98987
99311
|
const STREAMING_FIELD_RE = /"(path|file_path|command|pattern|query|url|description|title|name)"\s*:\s*"((?:\\.|[^"\\])*)"/g;
|
|
98988
99312
|
function unescapeJsonString(s) {
|
|
98989
|
-
return s.
|
|
99313
|
+
return s.replaceAll(/\\(["\\/bfnrt])/g, (_, ch) => {
|
|
98990
99314
|
switch (ch) {
|
|
98991
99315
|
case "n": return "\n";
|
|
98992
99316
|
case "t": return " ";
|
|
@@ -99269,7 +99593,7 @@ var ChoicePickerComponent = class extends Container {
|
|
|
99269
99593
|
super();
|
|
99270
99594
|
this.opts = opts;
|
|
99271
99595
|
const currentIdx = opts.options.findIndex((o) => o.value === opts.currentValue);
|
|
99272
|
-
this.selectedIndex = currentIdx
|
|
99596
|
+
this.selectedIndex = Math.max(currentIdx, 0);
|
|
99273
99597
|
}
|
|
99274
99598
|
handleInput(data) {
|
|
99275
99599
|
if (matchesKey(data, Key.escape)) {
|
|
@@ -99292,12 +99616,13 @@ var ChoicePickerComponent = class extends Container {
|
|
|
99292
99616
|
}
|
|
99293
99617
|
render(width) {
|
|
99294
99618
|
const { colors } = this.opts;
|
|
99295
|
-
const lines = [];
|
|
99296
|
-
lines.push(chalk.hex(colors.primary)("─".repeat(width)));
|
|
99297
|
-
lines.push(chalk.hex(colors.primary).bold(` ${this.opts.title}`));
|
|
99298
99619
|
const hint = this.opts.hint ?? "↑↓ navigate · Enter select · Esc cancel";
|
|
99299
|
-
lines
|
|
99300
|
-
|
|
99620
|
+
const lines = [
|
|
99621
|
+
chalk.hex(colors.primary)("─".repeat(width)),
|
|
99622
|
+
chalk.hex(colors.primary).bold(` ${this.opts.title}`),
|
|
99623
|
+
chalk.hex(colors.textMuted)(` ${hint}`),
|
|
99624
|
+
""
|
|
99625
|
+
];
|
|
99301
99626
|
for (let i = 0; i < this.opts.options.length; i++) {
|
|
99302
99627
|
const opt = this.opts.options[i];
|
|
99303
99628
|
const isSelected = i === this.selectedIndex;
|
|
@@ -99455,31 +99780,28 @@ var HelpPanelComponent = class extends Container {
|
|
|
99455
99780
|
const muted = chalk.hex(c.textMuted);
|
|
99456
99781
|
const kbdColor = chalk.hex(c.warning);
|
|
99457
99782
|
const slashColor = chalk.hex(c.primary);
|
|
99458
|
-
const lines = [];
|
|
99459
|
-
lines.push(accent("─".repeat(width)));
|
|
99460
|
-
lines.push(accent.bold(" help ") + muted("· Esc / Enter / q to close · ↑↓ scroll"));
|
|
99461
|
-
lines.push("");
|
|
99462
|
-
lines.push(` ${dim("Sure, Kimi is ready to help! Just send a message to get started.")}`);
|
|
99463
|
-
lines.push("");
|
|
99464
|
-
lines.push(` ${chalk.bold("Keyboard shortcuts")}`);
|
|
99465
99783
|
const shortcuts = this.opts.shortcuts ?? DEFAULT_KEYBOARD_SHORTCUTS;
|
|
99466
99784
|
const kbdWidth = Math.max(8, ...shortcuts.map((s) => s.keys.length));
|
|
99467
|
-
|
|
99468
|
-
lines.push("");
|
|
99469
|
-
lines.push(` ${chalk.bold("Slash commands")}`);
|
|
99470
|
-
const sortedCmds = [...this.opts.commands].sort((a, b) => a.name.localeCompare(b.name));
|
|
99785
|
+
const sortedCmds = [...this.opts.commands].toSorted((a, b) => a.name.localeCompare(b.name));
|
|
99471
99786
|
const cmdLabels = sortedCmds.map((c) => {
|
|
99472
99787
|
const aliases = c.aliases.length > 0 ? ` (${c.aliases.map((a) => "/" + a).join(", ")})` : "";
|
|
99473
99788
|
return `/${c.name}${aliases}`;
|
|
99474
99789
|
});
|
|
99475
99790
|
const cmdWidth = Math.max(12, ...cmdLabels.map((l) => l.length));
|
|
99476
|
-
|
|
99477
|
-
|
|
99478
|
-
|
|
99479
|
-
|
|
99480
|
-
|
|
99481
|
-
|
|
99482
|
-
|
|
99791
|
+
const lines = [
|
|
99792
|
+
accent("─".repeat(width)),
|
|
99793
|
+
accent.bold(" help ") + muted("· Esc / Enter / q to close · ↑↓ scroll"),
|
|
99794
|
+
"",
|
|
99795
|
+
` ${dim("Sure, Kimi is ready to help! Just send a message to get started.")}`,
|
|
99796
|
+
"",
|
|
99797
|
+
` ${chalk.bold("Keyboard shortcuts")}`,
|
|
99798
|
+
...shortcuts.map((s) => ` ${kbdColor(s.keys.padEnd(kbdWidth))} ${dim(s.description)}`),
|
|
99799
|
+
"",
|
|
99800
|
+
` ${chalk.bold("Slash commands")}`,
|
|
99801
|
+
...sortedCmds.map((cmd, i) => ` ${slashColor(cmdLabels[i].padEnd(cmdWidth))} ${dim(cmd.description)}`),
|
|
99802
|
+
"",
|
|
99803
|
+
accent("─".repeat(width))
|
|
99804
|
+
];
|
|
99483
99805
|
const content = lines.slice(1, lines.length - 1);
|
|
99484
99806
|
const maxVisible = Math.max(5, this.opts.maxVisible ?? 24);
|
|
99485
99807
|
if (content.length > maxVisible) {
|
|
@@ -99490,7 +99812,7 @@ var HelpPanelComponent = class extends Container {
|
|
|
99490
99812
|
lines[0],
|
|
99491
99813
|
...slice,
|
|
99492
99814
|
scrollInfo,
|
|
99493
|
-
lines
|
|
99815
|
+
lines.at(-1)
|
|
99494
99816
|
].map((line) => truncateToWidth(line, width));
|
|
99495
99817
|
}
|
|
99496
99818
|
this.scrollTop = 0;
|
|
@@ -99664,8 +99986,7 @@ var SessionPickerComponent = class extends Container {
|
|
|
99664
99986
|
}
|
|
99665
99987
|
render(width) {
|
|
99666
99988
|
const colors = this.colors;
|
|
99667
|
-
const lines = [];
|
|
99668
|
-
lines.push(chalk.hex(colors.primary)("─".repeat(width)));
|
|
99989
|
+
const lines = [chalk.hex(colors.primary)("─".repeat(width))];
|
|
99669
99990
|
if (this.loading) {
|
|
99670
99991
|
lines.push(chalk.hex(colors.primary).bold("Sessions"));
|
|
99671
99992
|
lines.push(chalk.hex(colors.textMuted)("Loading sessions..."));
|
|
@@ -100409,30 +100730,30 @@ function renderDisplayBlock(block, expanded) {
|
|
|
100409
100730
|
if (block.danger !== void 0) lines.push(chalk.red.bold(`⚠ potentially destructive: ${block.danger}`));
|
|
100410
100731
|
(block.command.length > 0 ? block.command.split("\n") : [""]).forEach((cmdLine, idx) => {
|
|
100411
100732
|
const prefix = idx === 0 ? chalk.cyan("$") : chalk.dim("·");
|
|
100412
|
-
lines.push(`${prefix} ${chalk.
|
|
100733
|
+
lines.push(`${prefix} ${chalk.whiteBright(cmdLine)}`);
|
|
100413
100734
|
});
|
|
100414
100735
|
if (block.description !== void 0 && block.description.length > 0) lines.push(` ${chalk.dim(block.description)}`);
|
|
100415
100736
|
return lines;
|
|
100416
100737
|
}
|
|
100417
100738
|
case "file_op": {
|
|
100418
|
-
const lines = [`${chalk.cyan(block.operation.padEnd(5))} ${chalk.
|
|
100739
|
+
const lines = [`${chalk.cyan(block.operation.padEnd(5))} ${chalk.whiteBright(block.path)}`];
|
|
100419
100740
|
if (block.detail !== void 0 && block.detail.length > 0) lines.push(chalk.dim(block.detail));
|
|
100420
100741
|
return lines;
|
|
100421
100742
|
}
|
|
100422
|
-
case "url_fetch": return [`${chalk.cyan((block.method ?? "GET").toUpperCase().padEnd(5))} ${chalk.
|
|
100743
|
+
case "url_fetch": return [`${chalk.cyan((block.method ?? "GET").toUpperCase().padEnd(5))} ${chalk.whiteBright(block.url)}`];
|
|
100423
100744
|
case "search": {
|
|
100424
|
-
const lines = [`${chalk.cyan("search")} ${chalk.
|
|
100745
|
+
const lines = [`${chalk.cyan("search")} ${chalk.whiteBright(block.query)}`];
|
|
100425
100746
|
if (block.scope !== void 0 && block.scope.length > 0) lines.push(chalk.dim(`scope: ${block.scope}`));
|
|
100426
100747
|
return lines;
|
|
100427
100748
|
}
|
|
100428
100749
|
case "invocation": {
|
|
100429
|
-
const lines = [`${chalk.cyan(block.kind.padEnd(5))} ${chalk.
|
|
100750
|
+
const lines = [`${chalk.cyan(block.kind.padEnd(5))} ${chalk.whiteBright(block.name)}`];
|
|
100430
100751
|
if (block.description !== void 0 && block.description.length > 0) lines.push(chalk.dim(truncateOneLine(block.description, 200)));
|
|
100431
100752
|
return lines;
|
|
100432
100753
|
}
|
|
100433
|
-
case "brief": return block.text ? block.text.split("\n").map((line) => line.length > 0 ? chalk.
|
|
100434
|
-
case "background_task": return [chalk.
|
|
100435
|
-
case "todo": return block.items.map((item) => chalk.
|
|
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}`));
|
|
100436
100757
|
default: return [];
|
|
100437
100758
|
}
|
|
100438
100759
|
}
|
|
@@ -100452,9 +100773,13 @@ function isDuplicateBriefBlock(block, description) {
|
|
|
100452
100773
|
const borderColor = chalk.yellow;
|
|
100453
100774
|
const selectColor = chalk.cyan;
|
|
100454
100775
|
function headerFor(toolName) {
|
|
100455
|
-
|
|
100456
|
-
|
|
100457
|
-
|
|
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
|
+
}
|
|
100458
100783
|
}
|
|
100459
100784
|
var ApprovalPanelComponent = class extends Container {
|
|
100460
100785
|
focused = false;
|
|
@@ -100565,7 +100890,7 @@ var ApprovalPanelComponent = class extends Container {
|
|
|
100565
100890
|
const labelWithNum = `${String(num)}. ${option.label}`;
|
|
100566
100891
|
if (this.feedbackMode && option.requires_feedback === true && isSelected) lines.push(indent(this.renderInlineFeedbackLine(width - 2, labelWithNum)));
|
|
100567
100892
|
else if (isSelected) lines.push(indent(`${selectColor.bold("▶")} ${selectColor.bold(labelWithNum)}`));
|
|
100568
|
-
else lines.push(indent(chalk.
|
|
100893
|
+
else lines.push(indent(chalk.whiteBright(` ${labelWithNum}`)));
|
|
100569
100894
|
}
|
|
100570
100895
|
lines.push("");
|
|
100571
100896
|
if (this.feedbackMode) lines.push(indent(chalk.dim("Type feedback · ↵ submit.")));
|
|
@@ -101209,10 +101534,7 @@ function registerReverseRPCHandlers(state, client, callbacks) {
|
|
|
101209
101534
|
showPanel: (payload) => showQuestionDialog(state, payload),
|
|
101210
101535
|
hidePanel: () => hideQuestionDialog(state)
|
|
101211
101536
|
});
|
|
101212
|
-
|
|
101213
|
-
disposers.push(client.onRequest("approval.request", createApprovalRequestHandler(state)));
|
|
101214
|
-
disposers.push(client.onRequest("question.ask", createQuestionAskHandler(state)));
|
|
101215
|
-
return disposers;
|
|
101537
|
+
return [client.onRequest("approval.request", createApprovalRequestHandler(state)), client.onRequest("question.ask", createQuestionAskHandler(state))];
|
|
101216
101538
|
}
|
|
101217
101539
|
//#endregion
|
|
101218
101540
|
//#region src/utils/clipboard/clipboard-native.ts
|
|
@@ -101554,44 +101876,6 @@ function readUInt32BE(b, off) {
|
|
|
101554
101876
|
return b[off] * 16777216 + (b[off + 1] << 16) + (b[off + 2] << 8) + b[off + 3] >>> 0;
|
|
101555
101877
|
}
|
|
101556
101878
|
//#endregion
|
|
101557
|
-
//#region src/tui/commands/skill-commands.ts
|
|
101558
|
-
async function fetchSkills(client, sessionId) {
|
|
101559
|
-
const skills = (await client.listSkills(sessionId))?.skills ?? [];
|
|
101560
|
-
const out = [];
|
|
101561
|
-
for (const s of skills) {
|
|
101562
|
-
if (typeof s?.name !== "string" || s.name.length === 0) continue;
|
|
101563
|
-
if (typeof s.content !== "string") continue;
|
|
101564
|
-
out.push({
|
|
101565
|
-
name: s.name,
|
|
101566
|
-
content: s.content,
|
|
101567
|
-
...typeof s.description === "string" ? { description: s.description } : {}
|
|
101568
|
-
});
|
|
101569
|
-
}
|
|
101570
|
-
return out;
|
|
101571
|
-
}
|
|
101572
|
-
function buildSkillCommand(skill) {
|
|
101573
|
-
return {
|
|
101574
|
-
name: `${SKILL_COMMAND_PREFIX}${skill.name}`,
|
|
101575
|
-
aliases: [],
|
|
101576
|
-
description: skill.description ?? "",
|
|
101577
|
-
mode: "both",
|
|
101578
|
-
async execute(args, ctx) {
|
|
101579
|
-
const trimmed = args.trim();
|
|
101580
|
-
const prompt = trimmed.length > 0 ? `${skill.content}\n\nUser request:\n${trimmed}` : skill.content;
|
|
101581
|
-
try {
|
|
101582
|
-
await ctx.client.prompt(ctx.appState.sessionId, { input: prompt });
|
|
101583
|
-
} catch (err) {
|
|
101584
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
101585
|
-
return {
|
|
101586
|
-
type: "ok",
|
|
101587
|
-
message: `Skill "${skill.name}" failed: ${msg}`
|
|
101588
|
-
};
|
|
101589
|
-
}
|
|
101590
|
-
return { type: "ok" };
|
|
101591
|
-
}
|
|
101592
|
-
};
|
|
101593
|
-
}
|
|
101594
|
-
//#endregion
|
|
101595
101879
|
//#region src/tui/components/editor/file-mention-provider.ts
|
|
101596
101880
|
/**
|
|
101597
101881
|
* `@file` autocomplete provider for the input box.
|
|
@@ -101701,7 +101985,7 @@ function rankForEmptyQuery(files, snapshot) {
|
|
|
101701
101985
|
const result = [];
|
|
101702
101986
|
const cap = MAX_SUGGESTIONS_WHEN_EMPTY;
|
|
101703
101987
|
const inFiles = new Set(files);
|
|
101704
|
-
const byRecency = [...snapshot.recencyOrder.entries()].filter(([path]) => inFiles.has(path)).
|
|
101988
|
+
const byRecency = [...snapshot.recencyOrder.entries()].filter(([path]) => inFiles.has(path)).toSorted((a, b) => a[1] - b[1]);
|
|
101705
101989
|
for (const [path] of byRecency) {
|
|
101706
101990
|
if (result.length >= cap) break;
|
|
101707
101991
|
if (picked.has(path)) continue;
|
|
@@ -101709,7 +101993,7 @@ function rankForEmptyQuery(files, snapshot) {
|
|
|
101709
101993
|
result.push(path);
|
|
101710
101994
|
}
|
|
101711
101995
|
if (result.length < cap) {
|
|
101712
|
-
const byMtime = files.filter((p) => !picked.has(p) && snapshot.mtimeByPath.has(p)).
|
|
101996
|
+
const byMtime = files.filter((p) => !picked.has(p) && snapshot.mtimeByPath.has(p)).toSorted((a, b) => (snapshot.mtimeByPath.get(b) ?? 0) - (snapshot.mtimeByPath.get(a) ?? 0));
|
|
101713
101997
|
for (const path of byMtime) {
|
|
101714
101998
|
if (result.length >= cap) break;
|
|
101715
101999
|
picked.add(path);
|
|
@@ -101717,7 +102001,7 @@ function rankForEmptyQuery(files, snapshot) {
|
|
|
101717
102001
|
}
|
|
101718
102002
|
}
|
|
101719
102003
|
if (result.length < cap) {
|
|
101720
|
-
const rest = files.filter((p) => !picked.has(p)).
|
|
102004
|
+
const rest = files.filter((p) => !picked.has(p)).toSorted((a, b) => basename(a).localeCompare(basename(b)) || a.localeCompare(b));
|
|
101721
102005
|
for (const path of rest) {
|
|
101722
102006
|
if (result.length >= cap) break;
|
|
101723
102007
|
result.push(path);
|
|
@@ -102238,6 +102522,7 @@ var KimiTUI = class {
|
|
|
102238
102522
|
showUsage(this.state);
|
|
102239
102523
|
},
|
|
102240
102524
|
sendAsMessage: (text) => sendMessage(this.state, (e) => this.addEntry(e), text),
|
|
102525
|
+
activateSkill: (name, args, fullPrompt) => sendSkillActivation(this.state, (e) => this.addEntry(e), name, args, fullPrompt),
|
|
102241
102526
|
performReload: (action) => performReload(this.state, action, this.buildInputHooks())
|
|
102242
102527
|
};
|
|
102243
102528
|
}
|
|
@@ -102285,9 +102570,9 @@ async function runShell(opts, version) {
|
|
|
102285
102570
|
isReplaying: false,
|
|
102286
102571
|
streamingPhase: "idle",
|
|
102287
102572
|
streamingStartTime: 0,
|
|
102288
|
-
theme:
|
|
102573
|
+
theme: "dark",
|
|
102289
102574
|
version,
|
|
102290
|
-
editorCommand:
|
|
102575
|
+
editorCommand: null,
|
|
102291
102576
|
availableModels: ctx.availableModels,
|
|
102292
102577
|
sessionTitle: null
|
|
102293
102578
|
};
|
|
@@ -102421,7 +102706,7 @@ async function promptForInstallConfirmation(options) {
|
|
|
102421
102706
|
const output = options.output ?? process.stdout;
|
|
102422
102707
|
const choices = createInstallPromptChoices(options.target);
|
|
102423
102708
|
let selectedIndex = getDefaultInstallPromptSelection(choices);
|
|
102424
|
-
return
|
|
102709
|
+
return new Promise((resolve) => {
|
|
102425
102710
|
let lineCount = 0;
|
|
102426
102711
|
const hadRawMode = "isRaw" in input ? input.isRaw === true : false;
|
|
102427
102712
|
const canSetRawMode = typeof input.setRawMode === "function";
|