kimiflare 0.24.0 → 0.25.0
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/index.js +856 -116
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -18,8 +18,7 @@ function configPath() {
|
|
|
18
18
|
}
|
|
19
19
|
function readReasoningEffortEnv() {
|
|
20
20
|
const raw = process.env.KIMI_REASONING_EFFORT?.toLowerCase();
|
|
21
|
-
|
|
22
|
-
return void 0;
|
|
21
|
+
return EFFORTS.includes(raw ?? "") ? raw : void 0;
|
|
23
22
|
}
|
|
24
23
|
function readCoauthorEnv() {
|
|
25
24
|
const enabled = process.env.KIMIFLARE_COAUTHOR;
|
|
@@ -152,10 +151,11 @@ async function saveConfig(cfg) {
|
|
|
152
151
|
await chmod(p, 384);
|
|
153
152
|
return p;
|
|
154
153
|
}
|
|
155
|
-
var DEFAULT_MODEL, DEFAULT_REASONING_EFFORT;
|
|
154
|
+
var EFFORTS, DEFAULT_MODEL, DEFAULT_REASONING_EFFORT;
|
|
156
155
|
var init_config = __esm({
|
|
157
156
|
"src/config.ts"() {
|
|
158
157
|
"use strict";
|
|
158
|
+
EFFORTS = ["low", "medium", "high"];
|
|
159
159
|
DEFAULT_MODEL = "@cf/moonshotai/kimi-k2.6";
|
|
160
160
|
DEFAULT_REASONING_EFFORT = "medium";
|
|
161
161
|
}
|
|
@@ -173,10 +173,10 @@ async function* readSSE(stream, signal) {
|
|
|
173
173
|
if (done) break;
|
|
174
174
|
buffer += decoder.decode(value, { stream: true });
|
|
175
175
|
buffer = buffer.replace(/\r\n/g, "\n");
|
|
176
|
-
let
|
|
177
|
-
while ((
|
|
178
|
-
const event = buffer.slice(0,
|
|
179
|
-
buffer = buffer.slice(
|
|
176
|
+
let sep3;
|
|
177
|
+
while ((sep3 = buffer.indexOf("\n\n")) !== -1) {
|
|
178
|
+
const event = buffer.slice(0, sep3);
|
|
179
|
+
buffer = buffer.slice(sep3 + 2);
|
|
180
180
|
const data = extractData(event);
|
|
181
181
|
if (data !== null) yield data;
|
|
182
182
|
}
|
|
@@ -209,8 +209,8 @@ var init_errors = __esm({
|
|
|
209
209
|
"src/util/errors.ts"() {
|
|
210
210
|
"use strict";
|
|
211
211
|
KimiApiError = class extends Error {
|
|
212
|
-
constructor(
|
|
213
|
-
super(
|
|
212
|
+
constructor(message2, code, httpStatus) {
|
|
213
|
+
super(message2);
|
|
214
214
|
this.code = code;
|
|
215
215
|
this.httpStatus = httpStatus;
|
|
216
216
|
this.name = "KimiApiError";
|
|
@@ -1027,8 +1027,8 @@ ${jsCode}
|
|
|
1027
1027
|
await script.run(context, { timeout, release: true });
|
|
1028
1028
|
await new Promise((r) => setTimeout(r, 10));
|
|
1029
1029
|
} catch (err) {
|
|
1030
|
-
const
|
|
1031
|
-
return { output: "", logs, error:
|
|
1030
|
+
const message2 = err instanceof Error ? err.message : String(err);
|
|
1031
|
+
return { output: "", logs, error: message2, toolCalls };
|
|
1032
1032
|
} finally {
|
|
1033
1033
|
isolate.dispose();
|
|
1034
1034
|
}
|
|
@@ -1110,8 +1110,8 @@ ${jsCode}
|
|
|
1110
1110
|
await runInNewContext(wrapped, sandbox, { timeout, displayErrors: true });
|
|
1111
1111
|
await new Promise((r) => setTimeout(r, 10));
|
|
1112
1112
|
} catch (err) {
|
|
1113
|
-
const
|
|
1114
|
-
return { output: "", logs, error:
|
|
1113
|
+
const message2 = err instanceof Error ? err.message : String(err);
|
|
1114
|
+
return { output: "", logs, error: message2, toolCalls };
|
|
1115
1115
|
}
|
|
1116
1116
|
return { output: logs.join("\n"), logs, toolCalls };
|
|
1117
1117
|
}
|
|
@@ -1119,8 +1119,8 @@ async function runInSandbox(opts2) {
|
|
|
1119
1119
|
try {
|
|
1120
1120
|
return await runWithIsolatedVm(opts2);
|
|
1121
1121
|
} catch (err) {
|
|
1122
|
-
const
|
|
1123
|
-
if (
|
|
1122
|
+
const message2 = err instanceof Error ? err.message : String(err);
|
|
1123
|
+
if (message2.includes("isolated-vm") || message2.includes("Cannot find module") || message2.includes("bindings")) {
|
|
1124
1124
|
return runWithNodeVm(opts2);
|
|
1125
1125
|
}
|
|
1126
1126
|
return runWithNodeVm(opts2);
|
|
@@ -1711,6 +1711,9 @@ function resolvePath(cwd, input) {
|
|
|
1711
1711
|
}
|
|
1712
1712
|
return isAbsolute(input) ? input : resolve(cwd, input);
|
|
1713
1713
|
}
|
|
1714
|
+
function isPathOutside(relPath) {
|
|
1715
|
+
return relPath === ".." || relPath.startsWith(`..${sep}`) || isAbsolute(relPath);
|
|
1716
|
+
}
|
|
1714
1717
|
function collapsePath(input, cwd, maxLen = 40) {
|
|
1715
1718
|
if (!input) return input;
|
|
1716
1719
|
let abs;
|
|
@@ -2839,6 +2842,16 @@ var init_expand_artifact = __esm({
|
|
|
2839
2842
|
});
|
|
2840
2843
|
|
|
2841
2844
|
// src/tools/executor.ts
|
|
2845
|
+
function isDiffCommand(cmd) {
|
|
2846
|
+
const trimmed = cmd.trim();
|
|
2847
|
+
if (/^git\s+show(?:\s|$)/.test(trimmed)) return true;
|
|
2848
|
+
if (/^git\s+diff(?:\s|$)/.test(trimmed)) return true;
|
|
2849
|
+
if (/^git\s+format-patch(?:\s|$)/.test(trimmed)) return true;
|
|
2850
|
+
const hasPatchFlag = /(?:^|\s)(?:-p|--patch)(?:\s|$)/.test(trimmed);
|
|
2851
|
+
if (/^git\s+log(?:\s|$)/.test(trimmed) && hasPatchFlag) return true;
|
|
2852
|
+
if (/^git\s+stash\s+show(?:\s|$)/.test(trimmed) && hasPatchFlag) return true;
|
|
2853
|
+
return false;
|
|
2854
|
+
}
|
|
2842
2855
|
function normalizeToolOutput(result) {
|
|
2843
2856
|
if (typeof result === "string") {
|
|
2844
2857
|
const bytes = Buffer.byteLength(result, "utf8");
|
|
@@ -2941,6 +2954,20 @@ var init_executor = __esm({
|
|
|
2941
2954
|
try {
|
|
2942
2955
|
const result = await tool.run(args, ctx);
|
|
2943
2956
|
const normalized = normalizeToolOutput(result);
|
|
2957
|
+
const cmd = call.name === "bash" && typeof args.command === "string" ? args.command : "";
|
|
2958
|
+
if (isDiffCommand(cmd)) {
|
|
2959
|
+
const artifactId = this.artifactStore.store(normalized.content);
|
|
2960
|
+
const bytes = Buffer.byteLength(normalized.content, "utf8");
|
|
2961
|
+
return {
|
|
2962
|
+
tool_call_id: call.id,
|
|
2963
|
+
name: call.name,
|
|
2964
|
+
content: normalized.content,
|
|
2965
|
+
ok: true,
|
|
2966
|
+
rawBytes: bytes,
|
|
2967
|
+
reducedBytes: bytes,
|
|
2968
|
+
artifactId
|
|
2969
|
+
};
|
|
2970
|
+
}
|
|
2944
2971
|
const reduced = reduceToolOutput(
|
|
2945
2972
|
call.name,
|
|
2946
2973
|
normalized.content,
|
|
@@ -3087,13 +3114,17 @@ import { fileURLToPath as fileURLToPath2 } from "url";
|
|
|
3087
3114
|
import { dirname as dirname3, join as join7 } from "path";
|
|
3088
3115
|
function getAppVersion() {
|
|
3089
3116
|
if (cachedVersion !== null) return cachedVersion;
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3117
|
+
const here = dirname3(fileURLToPath2(import.meta.url));
|
|
3118
|
+
const candidates = [join7(here, "..", "..", "package.json"), join7(here, "..", "package.json")];
|
|
3119
|
+
for (const path of candidates) {
|
|
3120
|
+
try {
|
|
3121
|
+
const pkg = JSON.parse(readFileSync2(path, "utf8"));
|
|
3122
|
+
cachedVersion = pkg.version ?? "0.0.0";
|
|
3123
|
+
return cachedVersion;
|
|
3124
|
+
} catch {
|
|
3125
|
+
}
|
|
3096
3126
|
}
|
|
3127
|
+
cachedVersion = "0.0.0";
|
|
3097
3128
|
return cachedVersion;
|
|
3098
3129
|
}
|
|
3099
3130
|
var cachedVersion;
|
|
@@ -3577,11 +3608,12 @@ function recallArtifacts(messages, store, state) {
|
|
|
3577
3608
|
}
|
|
3578
3609
|
for (const failure of state.recent_failures) {
|
|
3579
3610
|
const keyword = failure.split(":")[0];
|
|
3580
|
-
if (keyword
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3611
|
+
if (!keyword) continue;
|
|
3612
|
+
const lowerKeyword = keyword.toLowerCase();
|
|
3613
|
+
if (!text.toLowerCase().includes(lowerKeyword)) continue;
|
|
3614
|
+
for (const [id, meta] of Object.entries(state.artifact_index)) {
|
|
3615
|
+
if (meta.source === "bash" && !ids.includes(id) && meta.summary.toLowerCase().includes(lowerKeyword)) {
|
|
3616
|
+
ids.push(id);
|
|
3585
3617
|
}
|
|
3586
3618
|
}
|
|
3587
3619
|
}
|
|
@@ -4153,14 +4185,14 @@ function buildRightParts(usage, contextLimit, sessionUsage, gatewayMeta) {
|
|
|
4153
4185
|
parts.push(`in ${sessionUsage.promptTokens}${cached ? ` (${cached} cached)` : ""}`);
|
|
4154
4186
|
parts.push(`out ${sessionUsage.completionTokens}`);
|
|
4155
4187
|
parts.push(`ctx ${pct}%`);
|
|
4156
|
-
parts.push(
|
|
4188
|
+
parts.push(`$${sessionUsage.cost.toFixed(5)}`);
|
|
4157
4189
|
} else {
|
|
4158
4190
|
const cached = usage.prompt_tokens_details?.cached_tokens ?? 0;
|
|
4159
4191
|
const cost = calculateCost(usage.prompt_tokens, usage.completion_tokens, cached);
|
|
4160
4192
|
parts.push(`in ${usage.prompt_tokens}${cached ? ` (${cached} cached)` : ""}`);
|
|
4161
4193
|
parts.push(`out ${usage.completion_tokens}`);
|
|
4162
4194
|
parts.push(`ctx ${pct}%`);
|
|
4163
|
-
parts.push(
|
|
4195
|
+
parts.push(`$${cost.total.toFixed(5)}`);
|
|
4164
4196
|
}
|
|
4165
4197
|
const gatewayCache = formatGatewayCacheStatus(gatewayMeta);
|
|
4166
4198
|
if (gatewayCache) parts.push(gatewayCache);
|
|
@@ -4910,18 +4942,18 @@ var init_source = __esm({
|
|
|
4910
4942
|
}
|
|
4911
4943
|
}
|
|
4912
4944
|
});
|
|
4913
|
-
createStyler = (
|
|
4945
|
+
createStyler = (open3, close, parent) => {
|
|
4914
4946
|
let openAll;
|
|
4915
4947
|
let closeAll;
|
|
4916
4948
|
if (parent === void 0) {
|
|
4917
|
-
openAll =
|
|
4949
|
+
openAll = open3;
|
|
4918
4950
|
closeAll = close;
|
|
4919
4951
|
} else {
|
|
4920
|
-
openAll = parent.openAll +
|
|
4952
|
+
openAll = parent.openAll + open3;
|
|
4921
4953
|
closeAll = close + parent.closeAll;
|
|
4922
4954
|
}
|
|
4923
4955
|
return {
|
|
4924
|
-
open,
|
|
4956
|
+
open: open3,
|
|
4925
4957
|
close,
|
|
4926
4958
|
openAll,
|
|
4927
4959
|
closeAll,
|
|
@@ -5367,6 +5399,235 @@ var init_welcome = __esm({
|
|
|
5367
5399
|
}
|
|
5368
5400
|
});
|
|
5369
5401
|
|
|
5402
|
+
// src/ui/help-menu.tsx
|
|
5403
|
+
import { useState as useState6 } from "react";
|
|
5404
|
+
import { Box as Box12, Text as Text13, useInput as useInput2 } from "ink";
|
|
5405
|
+
import SelectInput4 from "ink-select-input";
|
|
5406
|
+
import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
5407
|
+
function HelpMenu({ theme, themes, currentThemeName, customCommands, onDone, onCommand }) {
|
|
5408
|
+
const [page, setPage] = useState6("main");
|
|
5409
|
+
const customs = customCommands ?? [];
|
|
5410
|
+
useInput2((_input, key) => {
|
|
5411
|
+
if (key.escape) {
|
|
5412
|
+
if (page !== "main") {
|
|
5413
|
+
setPage("main");
|
|
5414
|
+
} else {
|
|
5415
|
+
onDone();
|
|
5416
|
+
}
|
|
5417
|
+
}
|
|
5418
|
+
});
|
|
5419
|
+
const handleSelect = (command) => {
|
|
5420
|
+
onCommand(command);
|
|
5421
|
+
onDone();
|
|
5422
|
+
};
|
|
5423
|
+
if (page === "main") {
|
|
5424
|
+
const items2 = CATEGORIES.map((cat) => ({
|
|
5425
|
+
label: cat.label,
|
|
5426
|
+
value: cat.key,
|
|
5427
|
+
key: cat.key
|
|
5428
|
+
}));
|
|
5429
|
+
if (customs.length > 0) {
|
|
5430
|
+
items2.push({ label: "Custom commands", value: "custom", key: "custom" });
|
|
5431
|
+
}
|
|
5432
|
+
items2.push({ label: "(close)", value: "__close__", key: "__close__" });
|
|
5433
|
+
return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
5434
|
+
/* @__PURE__ */ jsx13(Text13, { color: theme.accent, bold: true, children: "Help" }),
|
|
5435
|
+
/* @__PURE__ */ jsx13(Text13, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select, Esc to close." }),
|
|
5436
|
+
/* @__PURE__ */ jsx13(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx13(
|
|
5437
|
+
SelectInput4,
|
|
5438
|
+
{
|
|
5439
|
+
items: items2,
|
|
5440
|
+
onSelect: (item) => {
|
|
5441
|
+
if (item.value === "__close__") {
|
|
5442
|
+
onDone();
|
|
5443
|
+
} else {
|
|
5444
|
+
setPage(item.value);
|
|
5445
|
+
}
|
|
5446
|
+
}
|
|
5447
|
+
}
|
|
5448
|
+
) }),
|
|
5449
|
+
/* @__PURE__ */ jsx13(Box12, { marginTop: 1, flexDirection: "column", children: SINGLE_COMMANDS.map((cmd) => /* @__PURE__ */ jsx13(Text13, { color: theme.info.color, dimColor: false, children: ` ${cmd.command.padEnd(20)} ${cmd.description}` }, cmd.command)) }),
|
|
5450
|
+
/* @__PURE__ */ jsx13(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx13(Text13, { color: theme.info.color, dimColor: false, children: "keys: ctrl-c interrupt/exit \xB7 ctrl-r toggle reasoning \xB7 ctrl-o verbose \xB7 ctrl+t theme \xB7 shift+tab cycle mode \xB7 \u2191/\u2193 history" }) })
|
|
5451
|
+
] });
|
|
5452
|
+
}
|
|
5453
|
+
if (page === "theme") {
|
|
5454
|
+
const items2 = themes.map((t) => ({
|
|
5455
|
+
label: t.name === currentThemeName ? `${t.label} \xB7 current` : t.label,
|
|
5456
|
+
value: t.name,
|
|
5457
|
+
key: t.name
|
|
5458
|
+
}));
|
|
5459
|
+
items2.push({ label: "\u2190 Back", value: "__back__", key: "__back__" });
|
|
5460
|
+
return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
5461
|
+
/* @__PURE__ */ jsx13(Text13, { color: theme.accent, bold: true, children: "Theme" }),
|
|
5462
|
+
/* @__PURE__ */ jsx13(Text13, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to apply, Esc to go back." }),
|
|
5463
|
+
/* @__PURE__ */ jsx13(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx13(
|
|
5464
|
+
SelectInput4,
|
|
5465
|
+
{
|
|
5466
|
+
items: items2,
|
|
5467
|
+
onSelect: (item) => {
|
|
5468
|
+
if (item.value === "__back__") {
|
|
5469
|
+
setPage("main");
|
|
5470
|
+
} else {
|
|
5471
|
+
handleSelect(`/theme ${item.value}`);
|
|
5472
|
+
}
|
|
5473
|
+
}
|
|
5474
|
+
}
|
|
5475
|
+
) })
|
|
5476
|
+
] });
|
|
5477
|
+
}
|
|
5478
|
+
if (page === "custom") {
|
|
5479
|
+
const items2 = customs.map((c) => ({
|
|
5480
|
+
label: `${`/${c.name}`.padEnd(28)} ${c.description ?? ""}`.trimEnd(),
|
|
5481
|
+
value: `/${c.name}`,
|
|
5482
|
+
key: c.name
|
|
5483
|
+
}));
|
|
5484
|
+
items2.push({ label: "\u2190 Back", value: "__back__", key: "__back__" });
|
|
5485
|
+
return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
5486
|
+
/* @__PURE__ */ jsx13(Text13, { color: theme.accent, bold: true, children: "Custom commands" }),
|
|
5487
|
+
/* @__PURE__ */ jsx13(Text13, { color: theme.info.color, dimColor: false, children: customs.length === 0 ? "no custom commands found in .kimiflare/commands/" : "Arrow keys to navigate, Enter to run, Esc to go back." }),
|
|
5488
|
+
/* @__PURE__ */ jsx13(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx13(
|
|
5489
|
+
SelectInput4,
|
|
5490
|
+
{
|
|
5491
|
+
items: items2,
|
|
5492
|
+
onSelect: (item) => {
|
|
5493
|
+
if (item.value === "__back__") {
|
|
5494
|
+
setPage("main");
|
|
5495
|
+
} else {
|
|
5496
|
+
handleSelect(item.value);
|
|
5497
|
+
}
|
|
5498
|
+
}
|
|
5499
|
+
}
|
|
5500
|
+
) })
|
|
5501
|
+
] });
|
|
5502
|
+
}
|
|
5503
|
+
const category = CATEGORIES.find((c) => c.key === page);
|
|
5504
|
+
const selectable = category.commands.filter((cmd) => cmd.selectable !== false);
|
|
5505
|
+
const staticCmds = category.commands.filter((cmd) => cmd.selectable === false);
|
|
5506
|
+
const items = selectable.map((cmd) => ({
|
|
5507
|
+
label: `${cmd.command.padEnd(28)} ${cmd.description}`,
|
|
5508
|
+
value: cmd.command,
|
|
5509
|
+
key: cmd.command
|
|
5510
|
+
}));
|
|
5511
|
+
items.push({ label: "\u2190 Back", value: "__back__", key: "__back__" });
|
|
5512
|
+
return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
5513
|
+
/* @__PURE__ */ jsx13(Text13, { color: theme.accent, bold: true, children: category.label }),
|
|
5514
|
+
/* @__PURE__ */ jsx13(Text13, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to execute, Esc to go back." }),
|
|
5515
|
+
/* @__PURE__ */ jsx13(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx13(
|
|
5516
|
+
SelectInput4,
|
|
5517
|
+
{
|
|
5518
|
+
items,
|
|
5519
|
+
onSelect: (item) => {
|
|
5520
|
+
if (item.value === "__back__") {
|
|
5521
|
+
setPage("main");
|
|
5522
|
+
} else {
|
|
5523
|
+
handleSelect(item.value);
|
|
5524
|
+
}
|
|
5525
|
+
}
|
|
5526
|
+
}
|
|
5527
|
+
) }),
|
|
5528
|
+
staticCmds.length > 0 && /* @__PURE__ */ jsx13(Box12, { marginTop: 1, flexDirection: "column", children: staticCmds.map((cmd) => /* @__PURE__ */ jsx13(Text13, { color: theme.info.color, dimColor: true, children: ` ${cmd.command.padEnd(28)} ${cmd.description}` }, cmd.command)) })
|
|
5529
|
+
] });
|
|
5530
|
+
}
|
|
5531
|
+
var CATEGORIES, SINGLE_COMMANDS;
|
|
5532
|
+
var init_help_menu = __esm({
|
|
5533
|
+
"src/ui/help-menu.tsx"() {
|
|
5534
|
+
"use strict";
|
|
5535
|
+
CATEGORIES = [
|
|
5536
|
+
{
|
|
5537
|
+
key: "mode",
|
|
5538
|
+
label: "Mode",
|
|
5539
|
+
commands: [
|
|
5540
|
+
{ command: "/mode edit", description: "switch to edit mode" },
|
|
5541
|
+
{ command: "/mode plan", description: "switch to plan mode" },
|
|
5542
|
+
{ command: "/mode auto", description: "switch to auto mode" }
|
|
5543
|
+
]
|
|
5544
|
+
},
|
|
5545
|
+
{
|
|
5546
|
+
key: "thinking",
|
|
5547
|
+
label: "Thinking",
|
|
5548
|
+
commands: [
|
|
5549
|
+
{ command: "/thinking low", description: "fast, lower quality" },
|
|
5550
|
+
{ command: "/thinking medium", description: "balanced" },
|
|
5551
|
+
{ command: "/thinking high", description: "slow, higher quality" }
|
|
5552
|
+
]
|
|
5553
|
+
},
|
|
5554
|
+
{
|
|
5555
|
+
key: "theme",
|
|
5556
|
+
label: "Theme",
|
|
5557
|
+
commands: []
|
|
5558
|
+
},
|
|
5559
|
+
{
|
|
5560
|
+
key: "session",
|
|
5561
|
+
label: "Session",
|
|
5562
|
+
commands: [
|
|
5563
|
+
{ command: "/resume", description: "pick a past conversation" },
|
|
5564
|
+
{ command: "/compact", description: "summarize old turns to free context" },
|
|
5565
|
+
{ command: "/clear", description: "clear current conversation" }
|
|
5566
|
+
]
|
|
5567
|
+
},
|
|
5568
|
+
{
|
|
5569
|
+
key: "memory",
|
|
5570
|
+
label: "Memory",
|
|
5571
|
+
commands: [
|
|
5572
|
+
{ command: "/memory", description: "show memory stats" },
|
|
5573
|
+
{ command: "/memory on", description: "enable memory" },
|
|
5574
|
+
{ command: "/memory off", description: "disable memory" },
|
|
5575
|
+
{ command: "/memory clear", description: "wipe memories for this repo" },
|
|
5576
|
+
{ command: "/memory search <query>", description: "search stored memories", selectable: false }
|
|
5577
|
+
]
|
|
5578
|
+
},
|
|
5579
|
+
{
|
|
5580
|
+
key: "mcp",
|
|
5581
|
+
label: "MCP",
|
|
5582
|
+
commands: [
|
|
5583
|
+
{ command: "/mcp list", description: "list connected MCP servers and tools" },
|
|
5584
|
+
{ command: "/mcp reload", description: "reconnect all configured MCP servers" }
|
|
5585
|
+
]
|
|
5586
|
+
},
|
|
5587
|
+
{
|
|
5588
|
+
key: "gateway",
|
|
5589
|
+
label: "Gateway",
|
|
5590
|
+
commands: [
|
|
5591
|
+
{ command: "/gateway", description: "show gateway status" },
|
|
5592
|
+
{ command: "/gateway off", description: "disable AI Gateway (direct Workers AI)" },
|
|
5593
|
+
{ command: "/gateway skip-cache true", description: "enable skip-cache" },
|
|
5594
|
+
{ command: "/gateway skip-cache false", description: "disable skip-cache" },
|
|
5595
|
+
{ command: "/gateway collect-logs true", description: "enable log collection" },
|
|
5596
|
+
{ command: "/gateway collect-logs false", description: "disable log collection" },
|
|
5597
|
+
{ command: "/gateway metadata clear", description: "remove all metadata" },
|
|
5598
|
+
{ command: "/gateway <id>", description: "enable AI Gateway", selectable: false },
|
|
5599
|
+
{ command: "/gateway cache-ttl <seconds>", description: "set cache TTL", selectable: false },
|
|
5600
|
+
{ command: "/gateway metadata <key>=<value>", description: "add metadata", selectable: false }
|
|
5601
|
+
]
|
|
5602
|
+
},
|
|
5603
|
+
{
|
|
5604
|
+
key: "info",
|
|
5605
|
+
label: "Info",
|
|
5606
|
+
commands: [
|
|
5607
|
+
{ command: "/cost", description: "show cost report" },
|
|
5608
|
+
{ command: "/model", description: "show current model" },
|
|
5609
|
+
{ command: "/update", description: "check for updates" },
|
|
5610
|
+
{ command: "/hello", description: "send a voice note to the creator" },
|
|
5611
|
+
{ command: "/community", description: "join our Discord server" }
|
|
5612
|
+
]
|
|
5613
|
+
},
|
|
5614
|
+
{
|
|
5615
|
+
key: "config",
|
|
5616
|
+
label: "Config",
|
|
5617
|
+
commands: [
|
|
5618
|
+
{ command: "/init", description: "scan this repo and write a KIMI.md" },
|
|
5619
|
+
{ command: "/logout", description: "clear credentials" }
|
|
5620
|
+
]
|
|
5621
|
+
}
|
|
5622
|
+
];
|
|
5623
|
+
SINGLE_COMMANDS = [
|
|
5624
|
+
{ command: "/reasoning", description: "toggle show/hide model reasoning" },
|
|
5625
|
+
{ command: "/help", description: "show this menu" },
|
|
5626
|
+
{ command: "/exit", description: "exit kimiflare" }
|
|
5627
|
+
];
|
|
5628
|
+
}
|
|
5629
|
+
});
|
|
5630
|
+
|
|
5370
5631
|
// src/ui/theme.ts
|
|
5371
5632
|
function resolveTheme(name) {
|
|
5372
5633
|
if (!name) return THEMES[DEFAULT_THEME_NAME];
|
|
@@ -6932,19 +7193,358 @@ var init_state = __esm({
|
|
|
6932
7193
|
}
|
|
6933
7194
|
});
|
|
6934
7195
|
|
|
7196
|
+
// src/commands/frontmatter.ts
|
|
7197
|
+
function parseFrontmatter(input) {
|
|
7198
|
+
const errors = [];
|
|
7199
|
+
if (!FENCE.test(input)) {
|
|
7200
|
+
return { data: {}, body: input, errors };
|
|
7201
|
+
}
|
|
7202
|
+
const afterOpen = input.replace(FENCE, "");
|
|
7203
|
+
const closeIdx = afterOpen.search(/\r?\n---\s*(\r?\n|$)/);
|
|
7204
|
+
if (closeIdx === -1) {
|
|
7205
|
+
errors.push("frontmatter not closed with ---");
|
|
7206
|
+
return { data: {}, body: input, errors };
|
|
7207
|
+
}
|
|
7208
|
+
const yaml = afterOpen.slice(0, closeIdx);
|
|
7209
|
+
const closeMatch = afterOpen.slice(closeIdx).match(/\r?\n---\s*(\r?\n|$)/);
|
|
7210
|
+
const body = closeMatch ? afterOpen.slice(closeIdx + closeMatch[0].length) : "";
|
|
7211
|
+
const data = {};
|
|
7212
|
+
const lines = yaml.split(/\r?\n/);
|
|
7213
|
+
for (const line of lines) {
|
|
7214
|
+
if (line.trim() === "" || line.trim().startsWith("#")) continue;
|
|
7215
|
+
const m = line.match(KV);
|
|
7216
|
+
if (!m) {
|
|
7217
|
+
errors.push(`unparseable line: ${line.trim()}`);
|
|
7218
|
+
continue;
|
|
7219
|
+
}
|
|
7220
|
+
const key = m[1];
|
|
7221
|
+
let value = m[2] ?? "";
|
|
7222
|
+
if (value.startsWith('"') && value.endsWith('"') && value.length >= 2 || value.startsWith("'") && value.endsWith("'") && value.length >= 2) {
|
|
7223
|
+
value = value.slice(1, -1);
|
|
7224
|
+
}
|
|
7225
|
+
data[key] = value;
|
|
7226
|
+
}
|
|
7227
|
+
return { data, body, errors };
|
|
7228
|
+
}
|
|
7229
|
+
var FENCE, KV;
|
|
7230
|
+
var init_frontmatter = __esm({
|
|
7231
|
+
"src/commands/frontmatter.ts"() {
|
|
7232
|
+
"use strict";
|
|
7233
|
+
FENCE = /^---\s*\r?\n/;
|
|
7234
|
+
KV = /^([A-Za-z][\w-]*)\s*:\s*(.*?)\s*$/;
|
|
7235
|
+
}
|
|
7236
|
+
});
|
|
7237
|
+
|
|
7238
|
+
// src/commands/loader.ts
|
|
7239
|
+
import { open, realpath } from "fs/promises";
|
|
7240
|
+
import { homedir as homedir9 } from "os";
|
|
7241
|
+
import { join as join12, relative as relative2, sep as sep2 } from "path";
|
|
7242
|
+
import fg3 from "fast-glob";
|
|
7243
|
+
function projectCommandsDir(cwd = process.cwd()) {
|
|
7244
|
+
return join12(cwd, ".kimiflare", "commands");
|
|
7245
|
+
}
|
|
7246
|
+
function globalCommandsDir() {
|
|
7247
|
+
const xdg = process.env.XDG_CONFIG_HOME || join12(homedir9(), ".config");
|
|
7248
|
+
return join12(xdg, "kimiflare", "commands");
|
|
7249
|
+
}
|
|
7250
|
+
async function loadCustomCommands(cwd = process.cwd()) {
|
|
7251
|
+
const warnings = [];
|
|
7252
|
+
const byName = /* @__PURE__ */ new Map();
|
|
7253
|
+
const sources = [
|
|
7254
|
+
{ dir: globalCommandsDir(), source: "global" },
|
|
7255
|
+
{ dir: projectCommandsDir(cwd), source: "project" }
|
|
7256
|
+
];
|
|
7257
|
+
const perSource = await Promise.all(
|
|
7258
|
+
sources.map(async ({ dir, source }) => {
|
|
7259
|
+
const safeDir = await resolveSafeDir(dir, source, cwd, warnings);
|
|
7260
|
+
if (safeDir === null) return [];
|
|
7261
|
+
const files = await fg3("**/*.md", {
|
|
7262
|
+
cwd: safeDir,
|
|
7263
|
+
absolute: true,
|
|
7264
|
+
onlyFiles: true,
|
|
7265
|
+
followSymbolicLinks: false,
|
|
7266
|
+
suppressErrors: true
|
|
7267
|
+
});
|
|
7268
|
+
return Promise.all(files.map((file) => loadOne(file, safeDir, source, warnings)));
|
|
7269
|
+
})
|
|
7270
|
+
);
|
|
7271
|
+
for (const loaded of perSource) {
|
|
7272
|
+
for (const cmd of loaded) {
|
|
7273
|
+
if (cmd) byName.set(cmd.name, cmd);
|
|
7274
|
+
}
|
|
7275
|
+
}
|
|
7276
|
+
return {
|
|
7277
|
+
commands: [...byName.values()].sort((a, b) => a.name.localeCompare(b.name)),
|
|
7278
|
+
warnings
|
|
7279
|
+
};
|
|
7280
|
+
}
|
|
7281
|
+
async function resolveSafeDir(dir, source, cwd, warnings) {
|
|
7282
|
+
let realDir;
|
|
7283
|
+
try {
|
|
7284
|
+
realDir = await realpath(dir);
|
|
7285
|
+
} catch (err) {
|
|
7286
|
+
const code = err.code;
|
|
7287
|
+
if (code !== "ENOENT" && code !== "ENOTDIR") {
|
|
7288
|
+
warnings.push(`commands dir ${dir} unreadable: ${err.message}`);
|
|
7289
|
+
}
|
|
7290
|
+
return null;
|
|
7291
|
+
}
|
|
7292
|
+
if (source === "project") {
|
|
7293
|
+
let realCwd;
|
|
7294
|
+
try {
|
|
7295
|
+
realCwd = await realpath(cwd);
|
|
7296
|
+
} catch {
|
|
7297
|
+
return null;
|
|
7298
|
+
}
|
|
7299
|
+
const rel = relative2(realCwd, realDir);
|
|
7300
|
+
if (rel !== "" && isPathOutside(rel)) {
|
|
7301
|
+
warnings.push(`commands dir ${dir} escapes workspace via symlink \u2014 skipped`);
|
|
7302
|
+
return null;
|
|
7303
|
+
}
|
|
7304
|
+
}
|
|
7305
|
+
return realDir;
|
|
7306
|
+
}
|
|
7307
|
+
async function loadOne(file, rootDir, source, warnings) {
|
|
7308
|
+
let content;
|
|
7309
|
+
try {
|
|
7310
|
+
const handle = await open(file, "r");
|
|
7311
|
+
try {
|
|
7312
|
+
const stats = await handle.stat();
|
|
7313
|
+
if (stats.size > MAX_COMMAND_FILE_BYTES) {
|
|
7314
|
+
warnings.push(`command file ${file} exceeds ${MAX_COMMAND_FILE_BYTES} bytes \u2014 skipped`);
|
|
7315
|
+
return null;
|
|
7316
|
+
}
|
|
7317
|
+
content = await handle.readFile("utf8");
|
|
7318
|
+
} finally {
|
|
7319
|
+
await handle.close();
|
|
7320
|
+
}
|
|
7321
|
+
} catch (e) {
|
|
7322
|
+
warnings.push(`failed to read command file ${file}: ${e.message}`);
|
|
7323
|
+
return null;
|
|
7324
|
+
}
|
|
7325
|
+
const name = filenameToCommandName(file, rootDir);
|
|
7326
|
+
if (!name) {
|
|
7327
|
+
warnings.push(`invalid command name from ${file}`);
|
|
7328
|
+
return null;
|
|
7329
|
+
}
|
|
7330
|
+
const { data, body, errors } = parseFrontmatter(content);
|
|
7331
|
+
if (errors.length > 0) {
|
|
7332
|
+
warnings.push(`frontmatter errors in ${file}: ${errors.join("; ")} \u2014 skipped`);
|
|
7333
|
+
return null;
|
|
7334
|
+
}
|
|
7335
|
+
const cmd = {
|
|
7336
|
+
name,
|
|
7337
|
+
template: body,
|
|
7338
|
+
source,
|
|
7339
|
+
filepath: file
|
|
7340
|
+
};
|
|
7341
|
+
if (data.description) cmd.description = data.description;
|
|
7342
|
+
const modeRaw = data.mode ?? data.agent;
|
|
7343
|
+
if (modeRaw !== void 0) {
|
|
7344
|
+
const normalized = modeRaw === "build" ? "edit" : modeRaw;
|
|
7345
|
+
if (MODES.includes(normalized)) {
|
|
7346
|
+
cmd.mode = normalized;
|
|
7347
|
+
} else {
|
|
7348
|
+
warnings.push(`unknown mode "${modeRaw}" in ${file} \u2014 ignored`);
|
|
7349
|
+
}
|
|
7350
|
+
}
|
|
7351
|
+
if (data.model !== void 0 && data.model !== "") {
|
|
7352
|
+
cmd.model = data.model;
|
|
7353
|
+
}
|
|
7354
|
+
if (data.effort !== void 0) {
|
|
7355
|
+
if (EFFORTS.includes(data.effort)) {
|
|
7356
|
+
cmd.effort = data.effort;
|
|
7357
|
+
} else {
|
|
7358
|
+
warnings.push(`unknown effort "${data.effort}" in ${file} \u2014 ignored`);
|
|
7359
|
+
}
|
|
7360
|
+
}
|
|
7361
|
+
return cmd;
|
|
7362
|
+
}
|
|
7363
|
+
function filenameToCommandName(file, rootDir) {
|
|
7364
|
+
const rel = relative2(rootDir, file);
|
|
7365
|
+
if (!rel || isPathOutside(rel)) return null;
|
|
7366
|
+
const noExt = rel.replace(/\.md$/i, "");
|
|
7367
|
+
const parts = noExt.split(sep2).filter((p) => p.length > 0);
|
|
7368
|
+
if (parts.length === 0) return null;
|
|
7369
|
+
if (parts.some((p) => !/^[\w.-]+$/.test(p))) return null;
|
|
7370
|
+
return parts.join("/");
|
|
7371
|
+
}
|
|
7372
|
+
var MAX_COMMAND_FILE_BYTES;
|
|
7373
|
+
var init_loader = __esm({
|
|
7374
|
+
"src/commands/loader.ts"() {
|
|
7375
|
+
"use strict";
|
|
7376
|
+
init_mode();
|
|
7377
|
+
init_config();
|
|
7378
|
+
init_paths();
|
|
7379
|
+
init_frontmatter();
|
|
7380
|
+
MAX_COMMAND_FILE_BYTES = 256 * 1024;
|
|
7381
|
+
}
|
|
7382
|
+
});
|
|
7383
|
+
|
|
7384
|
+
// src/commands/renderer.ts
|
|
7385
|
+
import { exec } from "child_process";
|
|
7386
|
+
import { open as open2, realpath as realpath2 } from "fs/promises";
|
|
7387
|
+
import { isAbsolute as isAbsolute2, relative as relative3, resolve as resolvePathJoin } from "path";
|
|
7388
|
+
import { promisify as promisify2 } from "util";
|
|
7389
|
+
function tokenizeArgs(s) {
|
|
7390
|
+
return [...s.matchAll(ARG_TOKEN_RE)].map((match) => {
|
|
7391
|
+
const token = match[0];
|
|
7392
|
+
if (token.length >= 2 && (token.startsWith('"') && token.endsWith('"') || token.startsWith("'") && token.endsWith("'"))) {
|
|
7393
|
+
return token.slice(1, -1);
|
|
7394
|
+
}
|
|
7395
|
+
return token;
|
|
7396
|
+
});
|
|
7397
|
+
}
|
|
7398
|
+
async function renderCommand(cmd, rawInput, opts2 = {}) {
|
|
7399
|
+
const warnings = [];
|
|
7400
|
+
const cwd = opts2.cwd ?? process.cwd();
|
|
7401
|
+
const maxFileBytes = opts2.maxFileBytes ?? DEFAULT_MAX_FILE_BYTES;
|
|
7402
|
+
const argsString = stripCommandName(rawInput);
|
|
7403
|
+
const args = tokenizeArgs(argsString);
|
|
7404
|
+
const originalTemplate = cmd.template;
|
|
7405
|
+
const hadArguments = originalTemplate.includes("$ARGUMENTS");
|
|
7406
|
+
const hadPositionals = HAS_POSITIONAL.test(originalTemplate);
|
|
7407
|
+
let prompt = replacePositionals(originalTemplate, args);
|
|
7408
|
+
prompt = prompt.replaceAll("$ARGUMENTS", argsString);
|
|
7409
|
+
if (!hadArguments && !hadPositionals && argsString !== "") {
|
|
7410
|
+
prompt += `
|
|
7411
|
+
|
|
7412
|
+
${argsString}`;
|
|
7413
|
+
}
|
|
7414
|
+
prompt = await replaceShell(prompt, warnings, opts2.shellTimeoutMs ?? DEFAULT_SHELL_TIMEOUT_MS);
|
|
7415
|
+
prompt = await replaceFiles(prompt, warnings, cwd, maxFileBytes);
|
|
7416
|
+
if (prompt.trim() === "") {
|
|
7417
|
+
warnings.push("rendered prompt is empty");
|
|
7418
|
+
}
|
|
7419
|
+
return { prompt, warnings };
|
|
7420
|
+
}
|
|
7421
|
+
function stripCommandName(rawInput) {
|
|
7422
|
+
if (!rawInput.startsWith("/")) {
|
|
7423
|
+
return rawInput;
|
|
7424
|
+
}
|
|
7425
|
+
return rawInput.replace(/^\/\S+\s*/, "");
|
|
7426
|
+
}
|
|
7427
|
+
function replacePositionals(template, args) {
|
|
7428
|
+
const indexes = [...template.matchAll(POSITIONAL_RE)].map(
|
|
7429
|
+
(match) => Number(match[1])
|
|
7430
|
+
);
|
|
7431
|
+
const highest = indexes.length === 0 ? -1 : Math.max(...indexes);
|
|
7432
|
+
return template.replace(POSITIONAL_RE, (_match, n) => {
|
|
7433
|
+
const index = Number(n);
|
|
7434
|
+
if (index <= 0) {
|
|
7435
|
+
return "";
|
|
7436
|
+
}
|
|
7437
|
+
if (index === highest) {
|
|
7438
|
+
return args.slice(index - 1).join(" ");
|
|
7439
|
+
}
|
|
7440
|
+
return args[index - 1] ?? "";
|
|
7441
|
+
});
|
|
7442
|
+
}
|
|
7443
|
+
async function replaceShell(prompt, warnings, shellTimeoutMs) {
|
|
7444
|
+
const matches = [...prompt.matchAll(SHELL_RE)];
|
|
7445
|
+
const replacements = await Promise.all(
|
|
7446
|
+
matches.map(async (match) => {
|
|
7447
|
+
const command = match[1] ?? "";
|
|
7448
|
+
try {
|
|
7449
|
+
const { stdout } = await execAsync(command, {
|
|
7450
|
+
timeout: shellTimeoutMs,
|
|
7451
|
+
maxBuffer: 1024 * 1024
|
|
7452
|
+
});
|
|
7453
|
+
return String(stdout).trimEnd();
|
|
7454
|
+
} catch (error) {
|
|
7455
|
+
warnings.push(`shell command failed: \`${command}\` \u2014 ${message(error)}`);
|
|
7456
|
+
return "";
|
|
7457
|
+
}
|
|
7458
|
+
})
|
|
7459
|
+
);
|
|
7460
|
+
let index = 0;
|
|
7461
|
+
return prompt.replace(SHELL_RE, () => replacements[index++] ?? "");
|
|
7462
|
+
}
|
|
7463
|
+
async function replaceFiles(prompt, warnings, cwd, maxFileBytes) {
|
|
7464
|
+
const matches = [...prompt.matchAll(FILE_RE)];
|
|
7465
|
+
if (matches.length === 0) return prompt;
|
|
7466
|
+
const realCwd = await realpath2(cwd).catch(() => cwd);
|
|
7467
|
+
const replacements = await Promise.all(
|
|
7468
|
+
matches.map(async (match) => {
|
|
7469
|
+
const rawPath = match[1] ?? "";
|
|
7470
|
+
if (isAbsolute2(rawPath) || rawPath.startsWith("~")) {
|
|
7471
|
+
warnings.push(`file inclusion skipped: @${rawPath} \u2014 outside workspace`);
|
|
7472
|
+
return "";
|
|
7473
|
+
}
|
|
7474
|
+
const resolved = resolvePathJoin(cwd, rawPath);
|
|
7475
|
+
if (isPathOutside(relative3(cwd, resolved))) {
|
|
7476
|
+
warnings.push(`file inclusion skipped: @${rawPath} \u2014 outside workspace`);
|
|
7477
|
+
return "";
|
|
7478
|
+
}
|
|
7479
|
+
let real;
|
|
7480
|
+
try {
|
|
7481
|
+
real = await realpath2(resolved);
|
|
7482
|
+
} catch (error) {
|
|
7483
|
+
warnings.push(`file inclusion failed: @${rawPath} \u2014 ${message(error)}`);
|
|
7484
|
+
return "";
|
|
7485
|
+
}
|
|
7486
|
+
if (isPathOutside(relative3(realCwd, real))) {
|
|
7487
|
+
warnings.push(`file inclusion skipped: @${rawPath} \u2014 symlink escapes workspace`);
|
|
7488
|
+
return "";
|
|
7489
|
+
}
|
|
7490
|
+
try {
|
|
7491
|
+
const handle = await open2(real, "r");
|
|
7492
|
+
try {
|
|
7493
|
+
const stats = await handle.stat();
|
|
7494
|
+
if (stats.size > maxFileBytes) {
|
|
7495
|
+
warnings.push(
|
|
7496
|
+
`file inclusion skipped: @${rawPath} \u2014 exceeds ${maxFileBytes} bytes`
|
|
7497
|
+
);
|
|
7498
|
+
return "";
|
|
7499
|
+
}
|
|
7500
|
+
return await handle.readFile("utf8");
|
|
7501
|
+
} finally {
|
|
7502
|
+
await handle.close();
|
|
7503
|
+
}
|
|
7504
|
+
} catch (error) {
|
|
7505
|
+
warnings.push(`file inclusion failed: @${rawPath} \u2014 ${message(error)}`);
|
|
7506
|
+
return "";
|
|
7507
|
+
}
|
|
7508
|
+
})
|
|
7509
|
+
);
|
|
7510
|
+
let index = 0;
|
|
7511
|
+
return prompt.replace(FILE_RE, (_match, _path, trailing = "") => {
|
|
7512
|
+
const replacement = replacements[index++] ?? "";
|
|
7513
|
+
return replacement + trailing;
|
|
7514
|
+
});
|
|
7515
|
+
}
|
|
7516
|
+
function message(error) {
|
|
7517
|
+
return error instanceof Error ? error.message : String(error);
|
|
7518
|
+
}
|
|
7519
|
+
var execAsync, ARG_TOKEN_RE, POSITIONAL_RE, HAS_POSITIONAL, SHELL_RE, FILE_RE, DEFAULT_MAX_FILE_BYTES, DEFAULT_SHELL_TIMEOUT_MS;
|
|
7520
|
+
var init_renderer = __esm({
|
|
7521
|
+
"src/commands/renderer.ts"() {
|
|
7522
|
+
"use strict";
|
|
7523
|
+
init_paths();
|
|
7524
|
+
execAsync = promisify2(exec);
|
|
7525
|
+
ARG_TOKEN_RE = /(?:"[^"]*"|'[^']*'|[^\s"']+)/g;
|
|
7526
|
+
POSITIONAL_RE = /\$(\d+)/g;
|
|
7527
|
+
HAS_POSITIONAL = /\$\d+/;
|
|
7528
|
+
SHELL_RE = /!`([^`]+)`/g;
|
|
7529
|
+
FILE_RE = /(?<![\w`])@(\.?[^\s`,]+?)([.,;:!?)\]}]*)(?=[\s`,]|$)/g;
|
|
7530
|
+
DEFAULT_MAX_FILE_BYTES = 100 * 1024;
|
|
7531
|
+
DEFAULT_SHELL_TIMEOUT_MS = 5e3;
|
|
7532
|
+
}
|
|
7533
|
+
});
|
|
7534
|
+
|
|
6935
7535
|
// src/app.tsx
|
|
6936
7536
|
var app_exports = {};
|
|
6937
7537
|
__export(app_exports, {
|
|
6938
7538
|
renderApp: () => renderApp
|
|
6939
7539
|
});
|
|
6940
|
-
import { useState as
|
|
6941
|
-
import { Box as
|
|
7540
|
+
import { useState as useState7, useRef as useRef3, useEffect as useEffect4, useCallback } from "react";
|
|
7541
|
+
import { Box as Box13, Text as Text14, useApp, useInput as useInput3, render } from "ink";
|
|
6942
7542
|
import { existsSync } from "fs";
|
|
6943
|
-
import { join as
|
|
7543
|
+
import { join as join13 } from "path";
|
|
6944
7544
|
import { unlink as unlink2 } from "fs/promises";
|
|
6945
7545
|
import { spawn as spawn2 } from "child_process";
|
|
6946
7546
|
import { platform as platform2 } from "os";
|
|
6947
|
-
import { jsx as
|
|
7547
|
+
import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
6948
7548
|
function gatewayFromConfig(cfg) {
|
|
6949
7549
|
if (!cfg.aiGatewayId) return void 0;
|
|
6950
7550
|
return {
|
|
@@ -7015,8 +7615,8 @@ function findImagePaths(text) {
|
|
|
7015
7615
|
}
|
|
7016
7616
|
function App({ initialCfg, initialUpdateResult }) {
|
|
7017
7617
|
const { exit } = useApp();
|
|
7018
|
-
const [cfg, setCfg] =
|
|
7019
|
-
const [events, setRawEvents] =
|
|
7618
|
+
const [cfg, setCfg] = useState7(initialCfg);
|
|
7619
|
+
const [events, setRawEvents] = useState7([]);
|
|
7020
7620
|
const setEvents = useCallback(
|
|
7021
7621
|
(updater) => {
|
|
7022
7622
|
setRawEvents((prev) => {
|
|
@@ -7026,33 +7626,34 @@ function App({ initialCfg, initialUpdateResult }) {
|
|
|
7026
7626
|
},
|
|
7027
7627
|
[]
|
|
7028
7628
|
);
|
|
7029
|
-
const [input, setInput] =
|
|
7030
|
-
const [busy, setBusy] =
|
|
7031
|
-
const [usage, setUsage] =
|
|
7032
|
-
const [sessionUsage, setSessionUsage] =
|
|
7033
|
-
const [gatewayMeta, setGatewayMeta] =
|
|
7034
|
-
const [showReasoning, setShowReasoning] =
|
|
7035
|
-
const [perm, setPerm] =
|
|
7036
|
-
const [queue, setQueue] =
|
|
7037
|
-
const [history, setHistory] =
|
|
7038
|
-
const [historyIndex, setHistoryIndex] =
|
|
7039
|
-
const [draftInput, setDraftInput] =
|
|
7040
|
-
const [mode, setMode] =
|
|
7041
|
-
const [codeMode, setCodeMode] =
|
|
7042
|
-
const [effort, setEffort] =
|
|
7629
|
+
const [input, setInput] = useState7("");
|
|
7630
|
+
const [busy, setBusy] = useState7(false);
|
|
7631
|
+
const [usage, setUsage] = useState7(null);
|
|
7632
|
+
const [sessionUsage, setSessionUsage] = useState7(null);
|
|
7633
|
+
const [gatewayMeta, setGatewayMeta] = useState7(null);
|
|
7634
|
+
const [showReasoning, setShowReasoning] = useState7(false);
|
|
7635
|
+
const [perm, setPerm] = useState7(null);
|
|
7636
|
+
const [queue, setQueue] = useState7([]);
|
|
7637
|
+
const [history, setHistory] = useState7([]);
|
|
7638
|
+
const [historyIndex, setHistoryIndex] = useState7(-1);
|
|
7639
|
+
const [draftInput, setDraftInput] = useState7("");
|
|
7640
|
+
const [mode, setMode] = useState7("edit");
|
|
7641
|
+
const [codeMode, setCodeMode] = useState7(initialCfg?.codeMode ?? false);
|
|
7642
|
+
const [effort, setEffort] = useState7(
|
|
7043
7643
|
initialCfg?.reasoningEffort ?? DEFAULT_REASONING_EFFORT
|
|
7044
7644
|
);
|
|
7045
|
-
const [theme, setTheme] =
|
|
7046
|
-
const [resumeSessions, setResumeSessions] =
|
|
7047
|
-
const [showThemePicker, setShowThemePicker] =
|
|
7048
|
-
const [
|
|
7049
|
-
const [
|
|
7050
|
-
const [
|
|
7051
|
-
const [
|
|
7052
|
-
const [
|
|
7053
|
-
const [
|
|
7054
|
-
const [
|
|
7055
|
-
const [
|
|
7645
|
+
const [theme, setTheme] = useState7(resolveTheme(initialCfg?.theme));
|
|
7646
|
+
const [resumeSessions, setResumeSessions] = useState7(null);
|
|
7647
|
+
const [showThemePicker, setShowThemePicker] = useState7(false);
|
|
7648
|
+
const [showHelpMenu, setShowHelpMenu] = useState7(false);
|
|
7649
|
+
const [originalTheme, setOriginalTheme] = useState7(null);
|
|
7650
|
+
const [tasks, setTasks] = useState7([]);
|
|
7651
|
+
const [tasksStartedAt, setTasksStartedAt] = useState7(null);
|
|
7652
|
+
const [tasksStartTokens, setTasksStartTokens] = useState7(0);
|
|
7653
|
+
const [turnStartedAt, setTurnStartedAt] = useState7(null);
|
|
7654
|
+
const [verbose, setVerbose] = useState7(false);
|
|
7655
|
+
const [hasUpdate, setHasUpdate] = useState7(initialUpdateResult?.hasUpdate ?? false);
|
|
7656
|
+
const [latestVersion, setLatestVersion] = useState7(initialUpdateResult?.latestVersion ?? null);
|
|
7056
7657
|
const cacheStableRef = useRef3(initialCfg?.cacheStablePrompts !== false);
|
|
7057
7658
|
const messagesRef = useRef3(
|
|
7058
7659
|
makePrefixMessages(cacheStableRef.current, cfg?.model ?? DEFAULT_MODEL, "edit", ALL_TOOLS)
|
|
@@ -7078,6 +7679,7 @@ function App({ initialCfg, initialUpdateResult }) {
|
|
|
7078
7679
|
const memoryManagerRef = useRef3(null);
|
|
7079
7680
|
const pendingTextRef = useRef3(/* @__PURE__ */ new Map());
|
|
7080
7681
|
const flushTimeoutRef = useRef3(null);
|
|
7682
|
+
const customCommandsRef = useRef3([]);
|
|
7081
7683
|
useEffect4(() => {
|
|
7082
7684
|
if (!cfg) return;
|
|
7083
7685
|
void Promise.resolve().then(() => (init_sessions(), sessions_exports)).then(
|
|
@@ -7104,7 +7706,7 @@ function App({ initialCfg, initialUpdateResult }) {
|
|
|
7104
7706
|
}
|
|
7105
7707
|
});
|
|
7106
7708
|
if (cfg.memoryEnabled) {
|
|
7107
|
-
const dbPath = cfg.memoryDbPath ??
|
|
7709
|
+
const dbPath = cfg.memoryDbPath ?? join13(process.cwd(), ".kimiflare", "memory.db");
|
|
7108
7710
|
const manager = new MemoryManager({
|
|
7109
7711
|
dbPath,
|
|
7110
7712
|
accountId: cfg.accountId,
|
|
@@ -7138,7 +7740,20 @@ function App({ initialCfg, initialUpdateResult }) {
|
|
|
7138
7740
|
memoryManagerRef.current?.close();
|
|
7139
7741
|
memoryManagerRef.current = null;
|
|
7140
7742
|
}
|
|
7141
|
-
|
|
7743
|
+
void loadCustomCommands(process.cwd()).then(({ commands, warnings }) => {
|
|
7744
|
+
customCommandsRef.current = commands;
|
|
7745
|
+
for (const w of warnings) {
|
|
7746
|
+
setEvents((e) => [...e, { kind: "info", key: mkKey(), text: `commands: ${w}` }]);
|
|
7747
|
+
}
|
|
7748
|
+
const shadowed = commands.filter((c) => BUILTIN_COMMAND_NAMES.has(c.name.toLowerCase()));
|
|
7749
|
+
for (const c of shadowed) {
|
|
7750
|
+
setEvents((e) => [
|
|
7751
|
+
...e,
|
|
7752
|
+
{ kind: "info", key: mkKey(), text: `commands: /${c.name} (${c.filepath}) shadowed by built-in \u2014 will not run` }
|
|
7753
|
+
]);
|
|
7754
|
+
}
|
|
7755
|
+
});
|
|
7756
|
+
}, [cfg, setEvents]);
|
|
7142
7757
|
useEffect4(() => {
|
|
7143
7758
|
if (!cfg || updateCheckedRef.current) return;
|
|
7144
7759
|
updateCheckedRef.current = true;
|
|
@@ -7346,7 +7961,7 @@ function App({ initialCfg, initialUpdateResult }) {
|
|
|
7346
7961
|
} catch {
|
|
7347
7962
|
}
|
|
7348
7963
|
}, [cfg, ensureSessionId]);
|
|
7349
|
-
|
|
7964
|
+
useInput3((inputChar, key) => {
|
|
7350
7965
|
if (key.ctrl && inputChar === "c") {
|
|
7351
7966
|
if (busy && activeControllerRef.current) {
|
|
7352
7967
|
activeControllerRef.current.abort();
|
|
@@ -7537,13 +8152,13 @@ function App({ initialCfg, initialUpdateResult }) {
|
|
|
7537
8152
|
}
|
|
7538
8153
|
const cwd = process.cwd();
|
|
7539
8154
|
for (const name of ["KIMI.md", "KIMIFLARE.md", "AGENT.md"]) {
|
|
7540
|
-
if (existsSync(
|
|
8155
|
+
if (existsSync(join13(cwd, name))) {
|
|
7541
8156
|
setEvents((e) => [
|
|
7542
8157
|
...e,
|
|
7543
8158
|
{
|
|
7544
8159
|
kind: "info",
|
|
7545
8160
|
key: mkKey(),
|
|
7546
|
-
text: `${name} already exists at ${
|
|
8161
|
+
text: `${name} already exists at ${join13(cwd, name)} \u2014 delete it first if you want to regenerate`
|
|
7547
8162
|
}
|
|
7548
8163
|
]);
|
|
7549
8164
|
return;
|
|
@@ -7671,7 +8286,7 @@ function App({ initialCfg, initialUpdateResult }) {
|
|
|
7671
8286
|
})
|
|
7672
8287
|
}
|
|
7673
8288
|
});
|
|
7674
|
-
if (existsSync(
|
|
8289
|
+
if (existsSync(join13(cwd, "KIMI.md"))) {
|
|
7675
8290
|
if (cacheStableRef.current) {
|
|
7676
8291
|
messagesRef.current[1] = {
|
|
7677
8292
|
role: "system",
|
|
@@ -8035,8 +8650,25 @@ use: /thinking low | medium | high`
|
|
|
8035
8650
|
return true;
|
|
8036
8651
|
}
|
|
8037
8652
|
if (c === "/memory") {
|
|
8038
|
-
if (!cfg
|
|
8039
|
-
|
|
8653
|
+
if (!cfg) return true;
|
|
8654
|
+
if (arg === "on") {
|
|
8655
|
+
const next = { ...cfg, memoryEnabled: true };
|
|
8656
|
+
setCfg(next);
|
|
8657
|
+
void saveConfig(next).catch(() => {
|
|
8658
|
+
});
|
|
8659
|
+
setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "memory enabled" }]);
|
|
8660
|
+
return true;
|
|
8661
|
+
}
|
|
8662
|
+
if (arg === "off") {
|
|
8663
|
+
const next = { ...cfg, memoryEnabled: false };
|
|
8664
|
+
setCfg(next);
|
|
8665
|
+
void saveConfig(next).catch(() => {
|
|
8666
|
+
});
|
|
8667
|
+
setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "memory disabled" }]);
|
|
8668
|
+
return true;
|
|
8669
|
+
}
|
|
8670
|
+
if (!cfg.memoryEnabled) {
|
|
8671
|
+
setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "memory is disabled. Use /memory on to enable it, or set KIMIFLARE_MEMORY_ENABLED=1" }]);
|
|
8040
8672
|
return true;
|
|
8041
8673
|
}
|
|
8042
8674
|
if (arg === "clear") {
|
|
@@ -8186,27 +8818,57 @@ ${lines.join("\n")}` }]);
|
|
|
8186
8818
|
return true;
|
|
8187
8819
|
}
|
|
8188
8820
|
if (c === "/help") {
|
|
8189
|
-
|
|
8190
|
-
...e,
|
|
8191
|
-
{
|
|
8192
|
-
kind: "info",
|
|
8193
|
-
key: mkKey(),
|
|
8194
|
-
text: "commands:\n /mode edit|plan|auto switch mode (or shift+tab to cycle)\n /plan /auto /edit shortcuts for /mode\n /thinking low|med|high set reasoning effort (quality vs speed)\n /theme interactive theme picker (or ctrl+t)\n /theme NAME set theme by name\n /resume pick a past conversation\n /compact summarize old turns to free context\n /init scan this repo and write a KIMI.md for future agents\n /memory show memory stats\n /memory search <query> search stored memories\n /memory clear wipe memories for this repo\n /mcp list list connected MCP servers and tools\n /mcp reload reconnect all configured MCP servers\n /reasoning toggle show/hide model reasoning\n /clear clear current conversation\n /hello send a voice note to the creator\n /community join our Discord server\n /gateway show gateway status\n /gateway ID enable AI Gateway\n /gateway off disable AI Gateway (direct Workers AI)\n /gateway cache-ttl N set gateway cache TTL in seconds\n /gateway skip-cache T|F set gateway skip-cache flag\n /gateway collect-logs T|F include payload in gateway logs\n /gateway metadata K=V add metadata key-value pair\n /gateway metadata clear remove all metadata\n /cost /model /update /logout /help /exit\nkeys: ctrl-c interrupt/exit \xB7 ctrl-r toggle reasoning \xB7 ctrl-o verbose \xB7 ctrl+t theme \xB7 shift+tab cycle mode \xB7 \u2191/\u2193 history"
|
|
8195
|
-
}
|
|
8196
|
-
]);
|
|
8821
|
+
setShowHelpMenu(true);
|
|
8197
8822
|
return true;
|
|
8198
8823
|
}
|
|
8199
8824
|
return false;
|
|
8200
8825
|
},
|
|
8201
8826
|
[cfg, exit, usage, effort, theme, mode, openResumePicker, runCompact, runInit, initMcp, setCfg]
|
|
8202
8827
|
);
|
|
8828
|
+
const handleHelpCommand = useCallback(
|
|
8829
|
+
(command) => {
|
|
8830
|
+
setShowHelpMenu(false);
|
|
8831
|
+
const executed = handleSlash(command);
|
|
8832
|
+
if (!executed) {
|
|
8833
|
+
setEvents((e) => [...e, { kind: "error", key: mkKey(), text: `unknown command: ${command}` }]);
|
|
8834
|
+
}
|
|
8835
|
+
},
|
|
8836
|
+
[handleSlash]
|
|
8837
|
+
);
|
|
8203
8838
|
const processMessage = useCallback(
|
|
8204
8839
|
async (text, displayText) => {
|
|
8205
8840
|
if (!cfg) return;
|
|
8206
|
-
|
|
8841
|
+
let trimmed = text.trim();
|
|
8207
8842
|
if (!trimmed) return;
|
|
8208
|
-
|
|
8209
|
-
|
|
8843
|
+
let overrideModel;
|
|
8844
|
+
let overrideEffort;
|
|
8845
|
+
let display = displayText?.trim() || trimmed;
|
|
8846
|
+
if (trimmed.startsWith("/")) {
|
|
8847
|
+
if (handleSlash(trimmed)) return;
|
|
8848
|
+
const head = trimmed.split(/\s+/)[0].slice(1);
|
|
8849
|
+
const custom = customCommandsRef.current.find((c) => c.name === head);
|
|
8850
|
+
if (custom) {
|
|
8851
|
+
const info = (text2) => setEvents((e) => [...e, { kind: "info", key: mkKey(), text: text2 }]);
|
|
8852
|
+
const { prompt: rendered, warnings } = await renderCommand(custom, trimmed, {
|
|
8853
|
+
cwd: process.cwd()
|
|
8854
|
+
});
|
|
8855
|
+
for (const w of warnings) info(`${custom.name}: ${w}`);
|
|
8856
|
+
if (!rendered.trim()) return;
|
|
8857
|
+
const parts = [];
|
|
8858
|
+
if (custom.model) {
|
|
8859
|
+
overrideModel = custom.model;
|
|
8860
|
+
parts.push(`model=${custom.model}`);
|
|
8861
|
+
}
|
|
8862
|
+
if (custom.effort) {
|
|
8863
|
+
overrideEffort = custom.effort;
|
|
8864
|
+
parts.push(`effort=${custom.effort}`);
|
|
8865
|
+
}
|
|
8866
|
+
if (parts.length > 0) info(`command '${custom.name}' \u2192 ${parts.join(", ")} (this turn)`);
|
|
8867
|
+
if (custom.mode) info(`note: mode override (${custom.mode}) is not yet wired; current mode applies`);
|
|
8868
|
+
display = trimmed;
|
|
8869
|
+
trimmed = rendered;
|
|
8870
|
+
}
|
|
8871
|
+
}
|
|
8210
8872
|
const imagePaths = findImagePaths(trimmed).slice(0, MAX_IMAGES_PER_MESSAGE);
|
|
8211
8873
|
let images = [];
|
|
8212
8874
|
let content = sanitizeString(trimmed);
|
|
@@ -8258,14 +8920,14 @@ ${lines.join("\n")}` }]);
|
|
|
8258
8920
|
await runAgentTurn({
|
|
8259
8921
|
accountId: cfg.accountId,
|
|
8260
8922
|
apiToken: cfg.apiToken,
|
|
8261
|
-
model: cfg.model,
|
|
8923
|
+
model: overrideModel ?? cfg.model,
|
|
8262
8924
|
gateway: gatewayFromConfig(cfg),
|
|
8263
8925
|
messages: messagesRef.current,
|
|
8264
8926
|
tools: [...ALL_TOOLS, ...mcpToolsRef.current],
|
|
8265
8927
|
executor: executorRef.current,
|
|
8266
8928
|
cwd: process.cwd(),
|
|
8267
8929
|
signal: controller.signal,
|
|
8268
|
-
reasoningEffort: effortRef.current,
|
|
8930
|
+
reasoningEffort: overrideEffort ?? effortRef.current,
|
|
8269
8931
|
coauthor: cfg.coauthor !== false ? { name: cfg.coauthorName || "kimiflare", email: cfg.coauthorEmail || "kimiflare@proton.me" } : void 0,
|
|
8270
8932
|
sessionId: ensureSessionId(),
|
|
8271
8933
|
memoryManager: memoryManagerRef.current,
|
|
@@ -8370,24 +9032,60 @@ ${lines.join("\n")}` }]);
|
|
|
8370
9032
|
}
|
|
8371
9033
|
});
|
|
8372
9034
|
await saveSessionSafe();
|
|
8373
|
-
if (
|
|
8374
|
-
|
|
8375
|
-
|
|
8376
|
-
|
|
8377
|
-
|
|
8378
|
-
|
|
8379
|
-
|
|
8380
|
-
|
|
8381
|
-
|
|
8382
|
-
|
|
8383
|
-
|
|
8384
|
-
|
|
8385
|
-
|
|
8386
|
-
|
|
8387
|
-
|
|
9035
|
+
if (shouldCompact({ messages: messagesRef.current })) {
|
|
9036
|
+
if (compiledContextRef.current) {
|
|
9037
|
+
const result = compactMessages2({
|
|
9038
|
+
messages: messagesRef.current,
|
|
9039
|
+
state: sessionStateRef.current,
|
|
9040
|
+
store: artifactStoreRef.current
|
|
9041
|
+
});
|
|
9042
|
+
if (result.metrics.rawTurnsRemoved > 0) {
|
|
9043
|
+
messagesRef.current = result.newMessages;
|
|
9044
|
+
sessionStateRef.current = result.newState;
|
|
9045
|
+
setEvents((e) => [
|
|
9046
|
+
...e,
|
|
9047
|
+
{
|
|
9048
|
+
kind: "info",
|
|
9049
|
+
key: mkKey(),
|
|
9050
|
+
text: `auto-compacted: ${result.metrics.estimatedTokensBefore} \u2192 ${result.metrics.estimatedTokensAfter} tokens (${result.metrics.archivedArtifacts} artifacts)`
|
|
9051
|
+
}
|
|
9052
|
+
]);
|
|
9053
|
+
await saveSessionSafe();
|
|
9054
|
+
}
|
|
9055
|
+
} else {
|
|
9056
|
+
try {
|
|
9057
|
+
const result = await compactMessages({
|
|
9058
|
+
accountId: cfg.accountId,
|
|
9059
|
+
apiToken: cfg.apiToken,
|
|
9060
|
+
model: cfg.model,
|
|
9061
|
+
messages: messagesRef.current,
|
|
9062
|
+
signal: controller.signal,
|
|
9063
|
+
gateway: gatewayFromConfig(cfg)
|
|
9064
|
+
});
|
|
9065
|
+
if (result.replacedCount > 0) {
|
|
9066
|
+
messagesRef.current = result.newMessages;
|
|
9067
|
+
setEvents((e) => [
|
|
9068
|
+
...e,
|
|
9069
|
+
{
|
|
9070
|
+
kind: "info",
|
|
9071
|
+
key: mkKey(),
|
|
9072
|
+
text: `auto-compacted: ${result.replacedCount} messages summarized`
|
|
9073
|
+
}
|
|
9074
|
+
]);
|
|
9075
|
+
await saveSessionSafe();
|
|
8388
9076
|
}
|
|
8389
|
-
|
|
8390
|
-
|
|
9077
|
+
} catch (compactErr) {
|
|
9078
|
+
if (compactErr.name !== "AbortError") {
|
|
9079
|
+
setEvents((es) => [
|
|
9080
|
+
...es,
|
|
9081
|
+
{
|
|
9082
|
+
kind: "info",
|
|
9083
|
+
key: mkKey(),
|
|
9084
|
+
text: `auto-compact failed: ${compactErr.message ?? String(compactErr)}`
|
|
9085
|
+
}
|
|
9086
|
+
]);
|
|
9087
|
+
}
|
|
9088
|
+
}
|
|
8391
9089
|
}
|
|
8392
9090
|
}
|
|
8393
9091
|
} catch (e) {
|
|
@@ -8463,7 +9161,7 @@ ${lines.join("\n")}` }]);
|
|
|
8463
9161
|
}
|
|
8464
9162
|
}, [usage]);
|
|
8465
9163
|
if (!cfg) {
|
|
8466
|
-
return /* @__PURE__ */
|
|
9164
|
+
return /* @__PURE__ */ jsx14(
|
|
8467
9165
|
Onboarding,
|
|
8468
9166
|
{
|
|
8469
9167
|
onDone: (newCfg) => {
|
|
@@ -8477,15 +9175,28 @@ ${lines.join("\n")}` }]);
|
|
|
8477
9175
|
);
|
|
8478
9176
|
}
|
|
8479
9177
|
if (resumeSessions !== null) {
|
|
8480
|
-
return /* @__PURE__ */
|
|
9178
|
+
return /* @__PURE__ */ jsx14(Box13, { flexDirection: "column", children: /* @__PURE__ */ jsx14(ResumePicker, { sessions: resumeSessions, onPick: handleResumePick, theme }) });
|
|
8481
9179
|
}
|
|
8482
9180
|
if (showThemePicker) {
|
|
8483
|
-
return /* @__PURE__ */
|
|
9181
|
+
return /* @__PURE__ */ jsx14(Box13, { flexDirection: "column", children: /* @__PURE__ */ jsx14(ThemePicker, { themes: themeList(), current: theme, onPick: handleThemePick, onPreview: (t) => setTheme(t) }) });
|
|
9182
|
+
}
|
|
9183
|
+
if (showHelpMenu) {
|
|
9184
|
+
return /* @__PURE__ */ jsx14(Box13, { flexDirection: "column", children: /* @__PURE__ */ jsx14(
|
|
9185
|
+
HelpMenu,
|
|
9186
|
+
{
|
|
9187
|
+
theme,
|
|
9188
|
+
themes: themeList().map((t) => ({ name: t.name, label: t.label })),
|
|
9189
|
+
currentThemeName: theme.name,
|
|
9190
|
+
customCommands: customCommandsRef.current.filter((c) => !BUILTIN_COMMAND_NAMES.has(c.name.toLowerCase())).map((c) => ({ name: c.name, description: c.description })),
|
|
9191
|
+
onDone: () => setShowHelpMenu(false),
|
|
9192
|
+
onCommand: handleHelpCommand
|
|
9193
|
+
}
|
|
9194
|
+
) });
|
|
8484
9195
|
}
|
|
8485
9196
|
const hasConversation = events.some((e) => e.kind === "user" || e.kind === "assistant");
|
|
8486
|
-
return /* @__PURE__ */
|
|
8487
|
-
!hasConversation && events.length === 0 ? /* @__PURE__ */
|
|
8488
|
-
perm ? /* @__PURE__ */
|
|
9197
|
+
return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", children: [
|
|
9198
|
+
!hasConversation && events.length === 0 ? /* @__PURE__ */ jsx14(Welcome, { theme, accountId: cfg.accountId }) : /* @__PURE__ */ jsx14(ChatView, { events, showReasoning, theme, verbose }),
|
|
9199
|
+
perm ? /* @__PURE__ */ jsx14(
|
|
8489
9200
|
PermissionModal,
|
|
8490
9201
|
{
|
|
8491
9202
|
tool: perm.tool,
|
|
@@ -8496,8 +9207,8 @@ ${lines.join("\n")}` }]);
|
|
|
8496
9207
|
setPerm(null);
|
|
8497
9208
|
}
|
|
8498
9209
|
}
|
|
8499
|
-
) : /* @__PURE__ */
|
|
8500
|
-
tasks.length > 0 && /* @__PURE__ */
|
|
9210
|
+
) : /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", marginTop: 1, children: [
|
|
9211
|
+
tasks.length > 0 && /* @__PURE__ */ jsx14(
|
|
8501
9212
|
TaskList,
|
|
8502
9213
|
{
|
|
8503
9214
|
tasks,
|
|
@@ -8506,11 +9217,11 @@ ${lines.join("\n")}` }]);
|
|
|
8506
9217
|
tokensDelta: Math.max(0, (usage?.prompt_tokens ?? 0) - tasksStartTokens)
|
|
8507
9218
|
}
|
|
8508
9219
|
),
|
|
8509
|
-
queue.length > 0 && /* @__PURE__ */
|
|
9220
|
+
queue.length > 0 && /* @__PURE__ */ jsx14(Box13, { flexDirection: "column", marginBottom: 1, children: queue.map((q, i) => /* @__PURE__ */ jsxs13(Text14, { color: theme.queue.color, dimColor: theme.queue.dim, children: [
|
|
8510
9221
|
"\u23F3 ",
|
|
8511
9222
|
q.display
|
|
8512
9223
|
] }, `queue_${i}`)) }),
|
|
8513
|
-
/* @__PURE__ */
|
|
9224
|
+
/* @__PURE__ */ jsx14(
|
|
8514
9225
|
StatusBar,
|
|
8515
9226
|
{
|
|
8516
9227
|
model: cfg.model,
|
|
@@ -8528,9 +9239,9 @@ ${lines.join("\n")}` }]);
|
|
|
8528
9239
|
codeMode
|
|
8529
9240
|
}
|
|
8530
9241
|
),
|
|
8531
|
-
/* @__PURE__ */
|
|
8532
|
-
/* @__PURE__ */
|
|
8533
|
-
/* @__PURE__ */
|
|
9242
|
+
/* @__PURE__ */ jsxs13(Box13, { marginTop: 1, children: [
|
|
9243
|
+
/* @__PURE__ */ jsx14(Text14, { color: theme.accent, children: "\u203A " }),
|
|
9244
|
+
/* @__PURE__ */ jsx14(
|
|
8534
9245
|
CustomTextInput,
|
|
8535
9246
|
{
|
|
8536
9247
|
value: input,
|
|
@@ -8579,12 +9290,12 @@ ${lines.join("\n")}` }]);
|
|
|
8579
9290
|
] });
|
|
8580
9291
|
}
|
|
8581
9292
|
async function renderApp(cfg, updateResult) {
|
|
8582
|
-
const instance = render(/* @__PURE__ */
|
|
9293
|
+
const instance = render(/* @__PURE__ */ jsx14(App, { initialCfg: cfg, initialUpdateResult: updateResult }), {
|
|
8583
9294
|
incrementalRendering: true
|
|
8584
9295
|
});
|
|
8585
9296
|
await instance.waitUntilExit();
|
|
8586
9297
|
}
|
|
8587
|
-
var FEEDBACK_WORKER_URL, CONTEXT_LIMIT, AUTO_COMPACT_SUGGEST_PCT, MAX_EVENTS, nextAssistantId, nextKey, mkKey, MAX_IMAGES_PER_MESSAGE, EFFORT_DESCRIPTIONS;
|
|
9298
|
+
var FEEDBACK_WORKER_URL, CONTEXT_LIMIT, AUTO_COMPACT_SUGGEST_PCT, MAX_EVENTS, nextAssistantId, nextKey, mkKey, MAX_IMAGES_PER_MESSAGE, BUILTIN_COMMAND_NAMES, EFFORT_DESCRIPTIONS;
|
|
8588
9299
|
var init_app = __esm({
|
|
8589
9300
|
"src/app.tsx"() {
|
|
8590
9301
|
"use strict";
|
|
@@ -8607,6 +9318,7 @@ var init_app = __esm({
|
|
|
8607
9318
|
init_update_check();
|
|
8608
9319
|
init_onboarding();
|
|
8609
9320
|
init_welcome();
|
|
9321
|
+
init_help_menu();
|
|
8610
9322
|
init_config();
|
|
8611
9323
|
init_theme();
|
|
8612
9324
|
init_mode();
|
|
@@ -8617,6 +9329,8 @@ var init_app = __esm({
|
|
|
8617
9329
|
init_storage_limits();
|
|
8618
9330
|
init_state();
|
|
8619
9331
|
init_version();
|
|
9332
|
+
init_loader();
|
|
9333
|
+
init_renderer();
|
|
8620
9334
|
FEEDBACK_WORKER_URL = "https://kimiflare-feedback.sina-b35.workers.dev";
|
|
8621
9335
|
CONTEXT_LIMIT = 262e3;
|
|
8622
9336
|
AUTO_COMPACT_SUGGEST_PCT = 0.8;
|
|
@@ -8625,6 +9339,32 @@ var init_app = __esm({
|
|
|
8625
9339
|
nextKey = 1;
|
|
8626
9340
|
mkKey = () => `evt_${nextKey++}`;
|
|
8627
9341
|
MAX_IMAGES_PER_MESSAGE = 10;
|
|
9342
|
+
BUILTIN_COMMAND_NAMES = /* @__PURE__ */ new Set([
|
|
9343
|
+
"exit",
|
|
9344
|
+
"quit",
|
|
9345
|
+
"clear",
|
|
9346
|
+
"reasoning",
|
|
9347
|
+
"cost",
|
|
9348
|
+
"model",
|
|
9349
|
+
"thinking",
|
|
9350
|
+
"effort",
|
|
9351
|
+
"theme",
|
|
9352
|
+
"mode",
|
|
9353
|
+
"plan",
|
|
9354
|
+
"auto",
|
|
9355
|
+
"edit",
|
|
9356
|
+
"resume",
|
|
9357
|
+
"compact",
|
|
9358
|
+
"init",
|
|
9359
|
+
"update",
|
|
9360
|
+
"mcp",
|
|
9361
|
+
"logout",
|
|
9362
|
+
"help",
|
|
9363
|
+
"memory",
|
|
9364
|
+
"gateway",
|
|
9365
|
+
"hello",
|
|
9366
|
+
"community"
|
|
9367
|
+
]);
|
|
8628
9368
|
EFFORT_DESCRIPTIONS = {
|
|
8629
9369
|
low: "low \u2014 fastest; lightest reasoning. Best for simple Q&A, small edits, quick coordination.",
|
|
8630
9370
|
medium: "medium \u2014 balanced (default). Solid quality on most edits, fast on trivial prompts.",
|