kimiflare 0.34.1 → 0.36.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 +1671 -584
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
2
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
4
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
5
|
+
}) : x)(function(x) {
|
|
6
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
7
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
8
|
+
});
|
|
3
9
|
var __esm = (fn, res) => function __init() {
|
|
4
10
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
5
11
|
};
|
|
@@ -96,6 +102,31 @@ async function loadConfig() {
|
|
|
96
102
|
const envCodeMode = readBooleanEnv("KIMIFLARE_CODE_MODE");
|
|
97
103
|
const envCostAttribution = readBooleanEnv("KIMI_COST_ATTRIBUTION");
|
|
98
104
|
const envFilePicker = readBooleanEnv("KIMIFLARE_FILE_PICKER");
|
|
105
|
+
const envCloudMode = readBooleanEnv("KIMIFLARE_CLOUD");
|
|
106
|
+
if (envCloudMode) {
|
|
107
|
+
return {
|
|
108
|
+
accountId: "",
|
|
109
|
+
apiToken: "",
|
|
110
|
+
model: envModel,
|
|
111
|
+
cloudMode: true,
|
|
112
|
+
reasoningEffort: envEffort,
|
|
113
|
+
coauthor: envCoauthor?.enabled ?? true,
|
|
114
|
+
coauthorName: envCoauthor?.name,
|
|
115
|
+
coauthorEmail: envCoauthor?.email,
|
|
116
|
+
cacheStablePrompts,
|
|
117
|
+
compiledContext,
|
|
118
|
+
imageHistoryTurns: Number.isNaN(imageHistoryTurns) ? void 0 : imageHistoryTurns,
|
|
119
|
+
memoryEnabled: envMemoryEnabled,
|
|
120
|
+
memoryDbPath: envMemoryDbPath,
|
|
121
|
+
memoryMaxAgeDays: envMemoryMaxAgeDays,
|
|
122
|
+
memoryMaxEntries: envMemoryMaxEntries,
|
|
123
|
+
memoryEmbeddingModel: envMemoryEmbeddingModel,
|
|
124
|
+
plumbingModel: envPlumbingModel,
|
|
125
|
+
codeMode: envCodeMode,
|
|
126
|
+
costAttribution: envCostAttribution ?? false,
|
|
127
|
+
filePicker: envFilePicker ?? true
|
|
128
|
+
};
|
|
129
|
+
}
|
|
99
130
|
if (envAccount && envToken) {
|
|
100
131
|
return {
|
|
101
132
|
accountId: envAccount,
|
|
@@ -128,6 +159,31 @@ async function loadConfig() {
|
|
|
128
159
|
try {
|
|
129
160
|
const raw = await readFile(configPath(), "utf8");
|
|
130
161
|
const parsed = JSON.parse(raw);
|
|
162
|
+
if (parsed.cloudMode) {
|
|
163
|
+
return {
|
|
164
|
+
accountId: envAccount ?? parsed.accountId ?? "",
|
|
165
|
+
apiToken: envToken ?? parsed.apiToken ?? "",
|
|
166
|
+
model: envModel ?? parsed.model ?? DEFAULT_MODEL,
|
|
167
|
+
cloudMode: true,
|
|
168
|
+
reasoningEffort: envEffort ?? parsed.reasoningEffort,
|
|
169
|
+
coauthor: envCoauthor?.enabled ?? parsed.coauthor ?? true,
|
|
170
|
+
coauthorName: envCoauthor?.name ?? parsed.coauthorName,
|
|
171
|
+
coauthorEmail: envCoauthor?.email ?? parsed.coauthorEmail,
|
|
172
|
+
mcpServers: parsed.mcpServers,
|
|
173
|
+
cacheStablePrompts: parsed.cacheStablePrompts ?? cacheStablePrompts,
|
|
174
|
+
compiledContext: parsed.compiledContext ?? compiledContext,
|
|
175
|
+
imageHistoryTurns: Number.isNaN(imageHistoryTurns) ? parsed.imageHistoryTurns : imageHistoryTurns,
|
|
176
|
+
memoryEnabled: envMemoryEnabled ?? parsed.memoryEnabled,
|
|
177
|
+
memoryDbPath: envMemoryDbPath ?? parsed.memoryDbPath,
|
|
178
|
+
memoryMaxAgeDays: envMemoryMaxAgeDays ?? parsed.memoryMaxAgeDays,
|
|
179
|
+
memoryMaxEntries: envMemoryMaxEntries ?? parsed.memoryMaxEntries,
|
|
180
|
+
memoryEmbeddingModel: envMemoryEmbeddingModel ?? parsed.memoryEmbeddingModel,
|
|
181
|
+
plumbingModel: envPlumbingModel ?? parsed.plumbingModel,
|
|
182
|
+
codeMode: envCodeMode ?? parsed.codeMode,
|
|
183
|
+
costAttribution: envCostAttribution ?? parsed.costAttribution ?? false,
|
|
184
|
+
filePicker: envFilePicker ?? parsed.filePicker ?? true
|
|
185
|
+
};
|
|
186
|
+
}
|
|
131
187
|
if (parsed.accountId && parsed.apiToken) {
|
|
132
188
|
return {
|
|
133
189
|
accountId: envAccount ?? parsed.accountId,
|
|
@@ -155,7 +211,8 @@ async function loadConfig() {
|
|
|
155
211
|
memoryExtractionModel: envMemoryExtractionModel ?? parsed.memoryExtractionModel,
|
|
156
212
|
codeMode: envCodeMode ?? parsed.codeMode ?? true,
|
|
157
213
|
costAttribution: envCostAttribution ?? parsed.costAttribution ?? true,
|
|
158
|
-
filePicker: envFilePicker ?? parsed.filePicker ?? true
|
|
214
|
+
filePicker: envFilePicker ?? parsed.filePicker ?? true,
|
|
215
|
+
cloudMode: envCloudMode ?? parsed.cloudMode
|
|
159
216
|
};
|
|
160
217
|
}
|
|
161
218
|
} catch {
|
|
@@ -270,10 +327,8 @@ async function* readSSE(stream, signal) {
|
|
|
270
327
|
const decoder = new TextDecoder("utf-8");
|
|
271
328
|
let buffer = "";
|
|
272
329
|
const onAbort = () => {
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
} catch {
|
|
276
|
-
}
|
|
330
|
+
reader.cancel(new DOMException("aborted", "AbortError")).catch(() => {
|
|
331
|
+
});
|
|
277
332
|
};
|
|
278
333
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
279
334
|
try {
|
|
@@ -443,7 +498,7 @@ async function* runKimi(opts2) {
|
|
|
443
498
|
let res;
|
|
444
499
|
try {
|
|
445
500
|
const headers = {
|
|
446
|
-
Authorization: `Bearer ${opts2.apiToken}`,
|
|
501
|
+
Authorization: `Bearer ${opts2.cloudMode && opts2.cloudToken ? opts2.cloudToken : opts2.apiToken}`,
|
|
447
502
|
"Content-Type": "application/json",
|
|
448
503
|
"User-Agent": getUserAgent(),
|
|
449
504
|
...gatewayHeaders
|
|
@@ -500,6 +555,12 @@ function validateModelId(model) {
|
|
|
500
555
|
}
|
|
501
556
|
function buildKimiRequestTarget(opts2) {
|
|
502
557
|
validateModelId(opts2.model);
|
|
558
|
+
if (opts2.cloudMode) {
|
|
559
|
+
return {
|
|
560
|
+
url: "https://api.kimiflare.com/v1/chat",
|
|
561
|
+
headers: opts2.cloudToken ? { Authorization: `Bearer ${opts2.cloudToken}` } : {}
|
|
562
|
+
};
|
|
563
|
+
}
|
|
503
564
|
if (!opts2.gateway?.id) {
|
|
504
565
|
return {
|
|
505
566
|
url: `https://api.cloudflare.com/client/v4/accounts/${encodeURIComponent(opts2.accountId)}/ai/run/${opts2.model}`,
|
|
@@ -1326,6 +1387,8 @@ var init_api_generator = __esm({
|
|
|
1326
1387
|
});
|
|
1327
1388
|
|
|
1328
1389
|
// src/code-mode/sandbox.ts
|
|
1390
|
+
import { join as join6, dirname as dirname3 } from "path";
|
|
1391
|
+
import { pathToFileURL } from "url";
|
|
1329
1392
|
function stripTypescript(code) {
|
|
1330
1393
|
let js = code;
|
|
1331
1394
|
js = js.replace(/interface\s+\w+\s*\{[\s\S]*?\n\}/g, "");
|
|
@@ -1342,6 +1405,41 @@ function stripTypescript(code) {
|
|
|
1342
1405
|
js = js.replace(/\n{3,}/g, "\n\n");
|
|
1343
1406
|
return js.trim();
|
|
1344
1407
|
}
|
|
1408
|
+
async function loadTypescript(cwd) {
|
|
1409
|
+
try {
|
|
1410
|
+
const tsPath = await import.meta.resolve("typescript");
|
|
1411
|
+
return await import(tsPath);
|
|
1412
|
+
} catch {
|
|
1413
|
+
}
|
|
1414
|
+
let dir = cwd;
|
|
1415
|
+
while (dir !== dirname3(dir)) {
|
|
1416
|
+
try {
|
|
1417
|
+
const tsPath = join6(dir, "node_modules", "typescript", "lib", "typescript.js");
|
|
1418
|
+
return await import(pathToFileURL(tsPath).href);
|
|
1419
|
+
} catch {
|
|
1420
|
+
}
|
|
1421
|
+
dir = dirname3(dir);
|
|
1422
|
+
}
|
|
1423
|
+
return null;
|
|
1424
|
+
}
|
|
1425
|
+
async function transpileOrStrip(code, cwd) {
|
|
1426
|
+
const ts = await loadTypescript(cwd);
|
|
1427
|
+
if (ts) {
|
|
1428
|
+
const result = ts.transpileModule(code, {
|
|
1429
|
+
compilerOptions: {
|
|
1430
|
+
module: ts.ModuleKind.ES2022,
|
|
1431
|
+
target: ts.ScriptTarget.ES2022,
|
|
1432
|
+
esModuleInterop: true,
|
|
1433
|
+
isolatedModules: true
|
|
1434
|
+
}
|
|
1435
|
+
});
|
|
1436
|
+
return { js: result.outputText, warnings: [] };
|
|
1437
|
+
}
|
|
1438
|
+
return {
|
|
1439
|
+
js: stripTypescript(code),
|
|
1440
|
+
warnings: ["TypeScript not found in node_modules. Using fallback parser; install typescript for reliable transpilation."]
|
|
1441
|
+
};
|
|
1442
|
+
}
|
|
1345
1443
|
async function runWithIsolatedVm(opts2) {
|
|
1346
1444
|
const { Isolate } = await import("isolated-vm");
|
|
1347
1445
|
const isolate = new Isolate({ memoryLimit: opts2.memoryLimitMB ?? 128 });
|
|
@@ -1389,7 +1487,7 @@ async function runWithIsolatedVm(opts2) {
|
|
|
1389
1487
|
await context.eval(`var api = {
|
|
1390
1488
|
${apiMethods}
|
|
1391
1489
|
};`);
|
|
1392
|
-
const jsCode =
|
|
1490
|
+
const { js: jsCode, warnings } = await transpileOrStrip(opts2.code, opts2.ctx.cwd);
|
|
1393
1491
|
const wrapped = `(async function() {
|
|
1394
1492
|
${jsCode}
|
|
1395
1493
|
})();`;
|
|
@@ -1400,11 +1498,11 @@ ${jsCode}
|
|
|
1400
1498
|
await new Promise((r) => setTimeout(r, 10));
|
|
1401
1499
|
} catch (err) {
|
|
1402
1500
|
const message2 = err instanceof Error ? err.message : String(err);
|
|
1403
|
-
return { output: "", logs, error: message2, toolCalls };
|
|
1501
|
+
return { output: "", logs, error: message2, toolCalls, warnings };
|
|
1404
1502
|
} finally {
|
|
1405
1503
|
isolate.dispose();
|
|
1406
1504
|
}
|
|
1407
|
-
return { output: logs.join("\n"), logs, toolCalls };
|
|
1505
|
+
return { output: logs.join("\n"), logs, toolCalls, warnings };
|
|
1408
1506
|
}
|
|
1409
1507
|
async function runWithNodeVm(opts2) {
|
|
1410
1508
|
const { runInNewContext } = await import("vm");
|
|
@@ -1472,7 +1570,7 @@ async function runWithNodeVm(opts2) {
|
|
|
1472
1570
|
return result.content;
|
|
1473
1571
|
};
|
|
1474
1572
|
}
|
|
1475
|
-
const jsCode =
|
|
1573
|
+
const { js: jsCode, warnings } = await transpileOrStrip(opts2.code, opts2.ctx.cwd);
|
|
1476
1574
|
const wrapped = `"use strict";
|
|
1477
1575
|
(async function() {
|
|
1478
1576
|
${jsCode}
|
|
@@ -1483,9 +1581,9 @@ ${jsCode}
|
|
|
1483
1581
|
await new Promise((r) => setTimeout(r, 10));
|
|
1484
1582
|
} catch (err) {
|
|
1485
1583
|
const message2 = err instanceof Error ? err.message : String(err);
|
|
1486
|
-
return { output: "", logs, error: message2, toolCalls };
|
|
1584
|
+
return { output: "", logs, error: message2, toolCalls, warnings };
|
|
1487
1585
|
}
|
|
1488
|
-
return { output: logs.join("\n"), logs, toolCalls };
|
|
1586
|
+
return { output: logs.join("\n"), logs, toolCalls, warnings };
|
|
1489
1587
|
}
|
|
1490
1588
|
async function runInSandbox(opts2) {
|
|
1491
1589
|
try {
|
|
@@ -1580,7 +1678,18 @@ Use console.log() to return results. Only console.log output will be sent back t
|
|
|
1580
1678
|
});
|
|
1581
1679
|
}
|
|
1582
1680
|
if (iter >= max) {
|
|
1583
|
-
if (opts2.
|
|
1681
|
+
if (opts2.callbacks.onToolLimitReached) {
|
|
1682
|
+
const decision = await opts2.callbacks.onToolLimitReached();
|
|
1683
|
+
if (decision === "continue") {
|
|
1684
|
+
opts2.messages.push({
|
|
1685
|
+
role: "system",
|
|
1686
|
+
content: "You have reached the tool-call limit for this session. The counter has been reset so you can continue working. Please proceed with your task."
|
|
1687
|
+
});
|
|
1688
|
+
iter = 0;
|
|
1689
|
+
} else {
|
|
1690
|
+
return;
|
|
1691
|
+
}
|
|
1692
|
+
} else if (opts2.continueOnLimit) {
|
|
1584
1693
|
opts2.messages.push({
|
|
1585
1694
|
role: "system",
|
|
1586
1695
|
content: "You have reached the tool-call limit for this session. The counter has been reset so you can continue working. Please proceed with your task."
|
|
@@ -1646,7 +1755,9 @@ Use console.log() to return results. Only console.log output will be sent back t
|
|
|
1646
1755
|
maxCompletionTokens: opts2.maxCompletionTokens,
|
|
1647
1756
|
reasoningEffort: opts2.reasoningEffort,
|
|
1648
1757
|
sessionId: opts2.sessionId,
|
|
1649
|
-
gateway: opts2.gateway
|
|
1758
|
+
gateway: opts2.gateway,
|
|
1759
|
+
cloudMode: opts2.cloudMode,
|
|
1760
|
+
cloudToken: opts2.cloudToken
|
|
1650
1761
|
});
|
|
1651
1762
|
for await (const ev of events) {
|
|
1652
1763
|
switch (ev.type) {
|
|
@@ -1825,10 +1936,13 @@ Use console.log() to return results. Only console.log output will be sent back t
|
|
|
1825
1936
|
toolResults.push(toolResult);
|
|
1826
1937
|
opts2.callbacks.onToolResult?.(toolResult);
|
|
1827
1938
|
}
|
|
1828
|
-
const
|
|
1939
|
+
const warningPrefix = sandboxResult.warnings?.length ? `Warning: ${sandboxResult.warnings.join(" ")}
|
|
1940
|
+
|
|
1941
|
+
` : "";
|
|
1942
|
+
const resultContent = sandboxResult.error ? `${warningPrefix}Error: ${sandboxResult.error}
|
|
1829
1943
|
|
|
1830
1944
|
Output:
|
|
1831
|
-
${sandboxResult.output}` : sandboxResult.output
|
|
1945
|
+
${sandboxResult.output}` : `${warningPrefix}${sandboxResult.output}`;
|
|
1832
1946
|
const result = {
|
|
1833
1947
|
tool_call_id: tc.id,
|
|
1834
1948
|
name: "execute_code",
|
|
@@ -2180,11 +2294,11 @@ var init_mode = __esm({
|
|
|
2180
2294
|
|
|
2181
2295
|
// src/agent/system-prompt.ts
|
|
2182
2296
|
import { platform, release, homedir as homedir3 } from "os";
|
|
2183
|
-
import { basename, join as
|
|
2297
|
+
import { basename, join as join7 } from "path";
|
|
2184
2298
|
import { readFileSync as readFileSync2, statSync } from "fs";
|
|
2185
2299
|
function loadContextFile(cwd) {
|
|
2186
2300
|
for (const name of CONTEXT_FILENAMES) {
|
|
2187
|
-
const path =
|
|
2301
|
+
const path = join7(cwd, name);
|
|
2188
2302
|
try {
|
|
2189
2303
|
const s = statSync(path);
|
|
2190
2304
|
if (!s.isFile() || s.size > MAX_CONTEXT_BYTES) continue;
|
|
@@ -2339,7 +2453,7 @@ var init_read = __esm({
|
|
|
2339
2453
|
|
|
2340
2454
|
// src/tools/write.ts
|
|
2341
2455
|
import { mkdir as mkdir4, readFile as readFile4, writeFile as writeFile3 } from "fs/promises";
|
|
2342
|
-
import { dirname as
|
|
2456
|
+
import { dirname as dirname4 } from "path";
|
|
2343
2457
|
var writeTool;
|
|
2344
2458
|
var init_write = __esm({
|
|
2345
2459
|
"src/tools/write.ts"() {
|
|
@@ -2369,7 +2483,7 @@ var init_write = __esm({
|
|
|
2369
2483
|
before = await readFile4(abs, "utf8");
|
|
2370
2484
|
} catch {
|
|
2371
2485
|
}
|
|
2372
|
-
await mkdir4(
|
|
2486
|
+
await mkdir4(dirname4(abs), { recursive: true });
|
|
2373
2487
|
await writeFile3(abs, args.content, "utf8");
|
|
2374
2488
|
const verb = before ? "Overwrote" : "Created";
|
|
2375
2489
|
return `${verb} ${args.path} (${args.content.length} chars).`;
|
|
@@ -2436,7 +2550,7 @@ var init_edit = __esm({
|
|
|
2436
2550
|
// src/tools/bash.ts
|
|
2437
2551
|
import { spawn } from "child_process";
|
|
2438
2552
|
import { tmpdir } from "os";
|
|
2439
|
-
import { join as
|
|
2553
|
+
import { join as join8 } from "path";
|
|
2440
2554
|
function formatBashTitle(raw) {
|
|
2441
2555
|
let cmd = (raw ?? "").trim();
|
|
2442
2556
|
const m = cmd.match(/^cd\s+([^\s&;]+)\s*(?:&&|;)\s*(.*)$/);
|
|
@@ -2454,7 +2568,7 @@ function injectCoauthor(command, coauthor) {
|
|
|
2454
2568
|
const mentionsGit = /\bgit\b/.test(trimmed);
|
|
2455
2569
|
if (!createsCommit && !isRebaseContinue && !mentionsGit) return command;
|
|
2456
2570
|
if (movesHeadOnly) return command;
|
|
2457
|
-
const tmpFile =
|
|
2571
|
+
const tmpFile = join8(tmpdir(), `kf-coauthor-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`);
|
|
2458
2572
|
const amendBlock = `
|
|
2459
2573
|
if ! git log -1 --pretty=%B 2>/dev/null | grep -qF "${trailer}"; then
|
|
2460
2574
|
git log -1 --pretty=%B | git interpret-trailers --trailer "${trailer}" > "${tmpFile}" && git commit --amend -F "${tmpFile}" --no-edit && rm -f "${tmpFile}"
|
|
@@ -3618,16 +3732,16 @@ var init_executor = __esm({
|
|
|
3618
3732
|
// src/util/update-check.ts
|
|
3619
3733
|
import { readFile as readFile7, writeFile as writeFile5, mkdir as mkdir5 } from "fs/promises";
|
|
3620
3734
|
import { homedir as homedir5 } from "os";
|
|
3621
|
-
import { join as
|
|
3735
|
+
import { join as join9, dirname as dirname5 } from "path";
|
|
3622
3736
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
3623
3737
|
function cachePath() {
|
|
3624
|
-
const xdg = process.env.XDG_CONFIG_HOME ||
|
|
3625
|
-
return
|
|
3738
|
+
const xdg = process.env.XDG_CONFIG_HOME || join9(homedir5(), ".config");
|
|
3739
|
+
return join9(xdg, "kimiflare", "update-check.json");
|
|
3626
3740
|
}
|
|
3627
3741
|
async function findPackageJson(startDir) {
|
|
3628
3742
|
let dir = startDir;
|
|
3629
3743
|
while (true) {
|
|
3630
|
-
const candidate =
|
|
3744
|
+
const candidate = join9(dir, "package.json");
|
|
3631
3745
|
try {
|
|
3632
3746
|
const raw = await readFile7(candidate, "utf8");
|
|
3633
3747
|
const parsed = JSON.parse(raw);
|
|
@@ -3636,14 +3750,14 @@ async function findPackageJson(startDir) {
|
|
|
3636
3750
|
}
|
|
3637
3751
|
} catch {
|
|
3638
3752
|
}
|
|
3639
|
-
const parent =
|
|
3753
|
+
const parent = dirname5(dir);
|
|
3640
3754
|
if (parent === dir) break;
|
|
3641
3755
|
dir = parent;
|
|
3642
3756
|
}
|
|
3643
3757
|
return null;
|
|
3644
3758
|
}
|
|
3645
3759
|
async function readLocalVersion() {
|
|
3646
|
-
const here =
|
|
3760
|
+
const here = dirname5(fileURLToPath2(import.meta.url));
|
|
3647
3761
|
const found = await findPackageJson(here);
|
|
3648
3762
|
return found?.version ?? null;
|
|
3649
3763
|
}
|
|
@@ -3660,7 +3774,7 @@ async function readCache() {
|
|
|
3660
3774
|
}
|
|
3661
3775
|
async function writeCache(entry) {
|
|
3662
3776
|
const p = cachePath();
|
|
3663
|
-
await mkdir5(
|
|
3777
|
+
await mkdir5(dirname5(p), { recursive: true });
|
|
3664
3778
|
await writeFile5(p, JSON.stringify(entry), "utf8");
|
|
3665
3779
|
}
|
|
3666
3780
|
async function fetchLatestVersion() {
|
|
@@ -3720,20 +3834,20 @@ var init_update_check = __esm({
|
|
|
3720
3834
|
// src/remote/session-store.ts
|
|
3721
3835
|
import { readFile as readFile8, writeFile as writeFile6, mkdir as mkdir6, readdir as readdir2 } from "fs/promises";
|
|
3722
3836
|
import { homedir as homedir6 } from "os";
|
|
3723
|
-
import { join as
|
|
3837
|
+
import { join as join10 } from "path";
|
|
3724
3838
|
function remoteDir() {
|
|
3725
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
3726
|
-
return
|
|
3839
|
+
const xdg = process.env.XDG_DATA_HOME || join10(homedir6(), ".config");
|
|
3840
|
+
return join10(xdg, "kimiflare", "remote");
|
|
3727
3841
|
}
|
|
3728
3842
|
async function saveRemoteSession(session) {
|
|
3729
3843
|
const dir = remoteDir();
|
|
3730
3844
|
await mkdir6(dir, { recursive: true });
|
|
3731
|
-
const path =
|
|
3845
|
+
const path = join10(dir, `${session.sessionId}.json`);
|
|
3732
3846
|
await writeFile6(path, JSON.stringify(session, null, 2) + "\n", "utf8");
|
|
3733
3847
|
}
|
|
3734
3848
|
async function loadRemoteSession(sessionId) {
|
|
3735
3849
|
try {
|
|
3736
|
-
const path =
|
|
3850
|
+
const path = join10(remoteDir(), `${sessionId}.json`);
|
|
3737
3851
|
const raw = await readFile8(path, "utf8");
|
|
3738
3852
|
return JSON.parse(raw);
|
|
3739
3853
|
} catch {
|
|
@@ -3748,7 +3862,7 @@ async function listRemoteSessions() {
|
|
|
3748
3862
|
for (const file of files) {
|
|
3749
3863
|
if (!file.endsWith(".json")) continue;
|
|
3750
3864
|
try {
|
|
3751
|
-
const raw = await readFile8(
|
|
3865
|
+
const raw = await readFile8(join10(dir, file), "utf8");
|
|
3752
3866
|
sessions.push(JSON.parse(raw));
|
|
3753
3867
|
} catch {
|
|
3754
3868
|
}
|
|
@@ -3770,7 +3884,7 @@ var init_session_store = __esm({
|
|
|
3770
3884
|
|
|
3771
3885
|
// src/remote/deploy.ts
|
|
3772
3886
|
import { execSync } from "child_process";
|
|
3773
|
-
import { join as
|
|
3887
|
+
import { join as join11, dirname as dirname6 } from "path";
|
|
3774
3888
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
3775
3889
|
import { randomBytes } from "crypto";
|
|
3776
3890
|
function generateSecret() {
|
|
@@ -3805,7 +3919,7 @@ async function* deployForTui() {
|
|
|
3805
3919
|
yield { message: "Docker OK" };
|
|
3806
3920
|
yield { message: "Building remote agent bundle..." };
|
|
3807
3921
|
try {
|
|
3808
|
-
runCapture("npm run build:remote-agent",
|
|
3922
|
+
runCapture("npm run build:remote-agent", join11(REMOTE_DIR, ".."));
|
|
3809
3923
|
yield { message: "Agent bundle built" };
|
|
3810
3924
|
} catch (err) {
|
|
3811
3925
|
yield { message: `Build failed: ${err instanceof Error ? err.message : String(err)}`, error: true };
|
|
@@ -3934,9 +4048,9 @@ var init_deploy = __esm({
|
|
|
3934
4048
|
"src/remote/deploy.ts"() {
|
|
3935
4049
|
"use strict";
|
|
3936
4050
|
init_config();
|
|
3937
|
-
__dirname =
|
|
3938
|
-
REMOTE_DIR =
|
|
3939
|
-
WORKER_DIR =
|
|
4051
|
+
__dirname = dirname6(fileURLToPath3(import.meta.url));
|
|
4052
|
+
REMOTE_DIR = join11(__dirname, "..", "..", "..", "remote");
|
|
4053
|
+
WORKER_DIR = join11(REMOTE_DIR, "worker");
|
|
3940
4054
|
}
|
|
3941
4055
|
});
|
|
3942
4056
|
|
|
@@ -4360,11 +4474,11 @@ var init_heuristic = __esm({
|
|
|
4360
4474
|
|
|
4361
4475
|
// src/cost-attribution/classify-from-session.ts
|
|
4362
4476
|
import { readFile as readFile9 } from "fs/promises";
|
|
4363
|
-
import { join as
|
|
4477
|
+
import { join as join12 } from "path";
|
|
4364
4478
|
import { homedir as homedir7 } from "os";
|
|
4365
4479
|
function sessionsDir() {
|
|
4366
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
4367
|
-
return
|
|
4480
|
+
const xdg = process.env.XDG_DATA_HOME || join12(homedir7(), ".local", "share");
|
|
4481
|
+
return join12(xdg, "kimiflare", "sessions");
|
|
4368
4482
|
}
|
|
4369
4483
|
function parseToolCalls(calls) {
|
|
4370
4484
|
return calls.map((c) => {
|
|
@@ -4378,7 +4492,7 @@ function parseToolCalls(calls) {
|
|
|
4378
4492
|
}
|
|
4379
4493
|
async function classifyFromSessionFile(sessionId) {
|
|
4380
4494
|
try {
|
|
4381
|
-
const raw = await readFile9(
|
|
4495
|
+
const raw = await readFile9(join12(sessionsDir(), `${sessionId}.json`), "utf8");
|
|
4382
4496
|
const session = JSON.parse(raw);
|
|
4383
4497
|
const messages = session.messages ?? [];
|
|
4384
4498
|
const turns = [];
|
|
@@ -4412,14 +4526,14 @@ __export(cli_exports, {
|
|
|
4412
4526
|
runCostCommand: () => runCostCommand
|
|
4413
4527
|
});
|
|
4414
4528
|
import { readFile as readFile10 } from "fs/promises";
|
|
4415
|
-
import { join as
|
|
4529
|
+
import { join as join13 } from "path";
|
|
4416
4530
|
import { homedir as homedir8 } from "os";
|
|
4417
4531
|
function usageDir() {
|
|
4418
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
4419
|
-
return
|
|
4532
|
+
const xdg = process.env.XDG_DATA_HOME || join13(homedir8(), ".local", "share");
|
|
4533
|
+
return join13(xdg, "kimiflare");
|
|
4420
4534
|
}
|
|
4421
4535
|
function usagePath() {
|
|
4422
|
-
return
|
|
4536
|
+
return join13(usageDir(), "usage.json");
|
|
4423
4537
|
}
|
|
4424
4538
|
function today() {
|
|
4425
4539
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
@@ -4517,6 +4631,124 @@ var init_cli = __esm({
|
|
|
4517
4631
|
}
|
|
4518
4632
|
});
|
|
4519
4633
|
|
|
4634
|
+
// src/cloud/auth.ts
|
|
4635
|
+
var auth_exports = {};
|
|
4636
|
+
__export(auth_exports, {
|
|
4637
|
+
CLOUD_API_URL: () => CLOUD_API_URL,
|
|
4638
|
+
POLL_INTERVAL_MS: () => POLL_INTERVAL_MS,
|
|
4639
|
+
POLL_TIMEOUT_MS: () => POLL_TIMEOUT_MS,
|
|
4640
|
+
authenticateDevice: () => authenticateDevice,
|
|
4641
|
+
clearCloudCredentials: () => clearCloudCredentials,
|
|
4642
|
+
fetchCloudUsage: () => fetchCloudUsage,
|
|
4643
|
+
generateDeviceCodes: () => generateDeviceCodes,
|
|
4644
|
+
loadCloudCredentials: () => loadCloudCredentials,
|
|
4645
|
+
pollForToken: () => pollForToken,
|
|
4646
|
+
registerDevice: () => registerDevice,
|
|
4647
|
+
saveCloudCredentials: () => saveCloudCredentials
|
|
4648
|
+
});
|
|
4649
|
+
import { readFile as readFile11, writeFile as writeFile7 } from "fs/promises";
|
|
4650
|
+
import { homedir as homedir9 } from "os";
|
|
4651
|
+
import { join as join14 } from "path";
|
|
4652
|
+
function cloudCredPath() {
|
|
4653
|
+
const xdg = process.env.XDG_CONFIG_HOME || join14(homedir9(), ".config");
|
|
4654
|
+
return join14(xdg, "kimiflare", "cloud.json");
|
|
4655
|
+
}
|
|
4656
|
+
function generateCode() {
|
|
4657
|
+
const chars = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
|
|
4658
|
+
let out = "";
|
|
4659
|
+
for (let i = 0; i < 8; i++) {
|
|
4660
|
+
out += chars[Math.floor(Math.random() * chars.length)];
|
|
4661
|
+
}
|
|
4662
|
+
return out;
|
|
4663
|
+
}
|
|
4664
|
+
function generateDeviceCodes() {
|
|
4665
|
+
const deviceCode = `device-${generateCode()}-${Date.now()}`;
|
|
4666
|
+
const userCode = `${generateCode()}-${generateCode()}`;
|
|
4667
|
+
const authUrl = `${CLOUD_API_URL}/auth/github?code=${encodeURIComponent(userCode)}`;
|
|
4668
|
+
return { deviceCode, userCode, authUrl };
|
|
4669
|
+
}
|
|
4670
|
+
async function registerDevice(codes) {
|
|
4671
|
+
const registerRes = await fetch(`${CLOUD_API_URL}/auth/device`, {
|
|
4672
|
+
method: "POST",
|
|
4673
|
+
headers: { "Content-Type": "application/json" },
|
|
4674
|
+
body: JSON.stringify({ device_code: codes.deviceCode, user_code: codes.userCode })
|
|
4675
|
+
});
|
|
4676
|
+
if (!registerRes.ok) {
|
|
4677
|
+
const err = await registerRes.json().catch(() => ({}));
|
|
4678
|
+
throw new Error(`Failed to register device: ${err.error || registerRes.statusText}`);
|
|
4679
|
+
}
|
|
4680
|
+
}
|
|
4681
|
+
async function pollForToken(deviceCode) {
|
|
4682
|
+
const pollRes = await fetch(`${CLOUD_API_URL}/auth/poll`, {
|
|
4683
|
+
method: "POST",
|
|
4684
|
+
headers: { "Content-Type": "application/json" },
|
|
4685
|
+
body: JSON.stringify({ device_code: deviceCode })
|
|
4686
|
+
});
|
|
4687
|
+
if (!pollRes.ok) return null;
|
|
4688
|
+
const pollData = await pollRes.json();
|
|
4689
|
+
if (pollData.status === "approved" && pollData.access_token) {
|
|
4690
|
+
const creds = {
|
|
4691
|
+
accessToken: pollData.access_token,
|
|
4692
|
+
expiresAt: Math.floor(Date.now() / 1e3) + 7 * 24 * 60 * 60
|
|
4693
|
+
// 7 days
|
|
4694
|
+
};
|
|
4695
|
+
await saveCloudCredentials(creds);
|
|
4696
|
+
return creds;
|
|
4697
|
+
}
|
|
4698
|
+
return null;
|
|
4699
|
+
}
|
|
4700
|
+
async function fetchCloudUsage(token) {
|
|
4701
|
+
const res = await fetch(`${CLOUD_API_URL}/v1/usage`, {
|
|
4702
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
4703
|
+
});
|
|
4704
|
+
if (!res.ok) return null;
|
|
4705
|
+
return await res.json();
|
|
4706
|
+
}
|
|
4707
|
+
async function loadCloudCredentials() {
|
|
4708
|
+
try {
|
|
4709
|
+
const raw = await readFile11(cloudCredPath(), "utf8");
|
|
4710
|
+
const parsed = JSON.parse(raw);
|
|
4711
|
+
if (parsed.expiresAt && parsed.expiresAt > Date.now() / 1e3) {
|
|
4712
|
+
return parsed;
|
|
4713
|
+
}
|
|
4714
|
+
} catch {
|
|
4715
|
+
}
|
|
4716
|
+
return null;
|
|
4717
|
+
}
|
|
4718
|
+
async function saveCloudCredentials(creds) {
|
|
4719
|
+
const p = cloudCredPath();
|
|
4720
|
+
await writeFile7(p, JSON.stringify(creds, null, 2), "utf8");
|
|
4721
|
+
}
|
|
4722
|
+
async function clearCloudCredentials() {
|
|
4723
|
+
try {
|
|
4724
|
+
const { unlink: unlink4 } = await import("fs/promises");
|
|
4725
|
+
await unlink4(cloudCredPath());
|
|
4726
|
+
} catch {
|
|
4727
|
+
}
|
|
4728
|
+
}
|
|
4729
|
+
async function authenticateDevice(onStatus) {
|
|
4730
|
+
const codes = generateDeviceCodes();
|
|
4731
|
+
await registerDevice(codes);
|
|
4732
|
+
onStatus({ url: codes.authUrl, userCode: codes.userCode, polling: false });
|
|
4733
|
+
const startTime = Date.now();
|
|
4734
|
+
while (Date.now() - startTime < POLL_TIMEOUT_MS) {
|
|
4735
|
+
await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
|
|
4736
|
+
onStatus({ url: codes.authUrl, userCode: codes.userCode, polling: true });
|
|
4737
|
+
const creds = await pollForToken(codes.deviceCode);
|
|
4738
|
+
if (creds) return creds;
|
|
4739
|
+
}
|
|
4740
|
+
throw new Error("Authentication timed out. Please try again.");
|
|
4741
|
+
}
|
|
4742
|
+
var CLOUD_API_URL, POLL_INTERVAL_MS, POLL_TIMEOUT_MS;
|
|
4743
|
+
var init_auth = __esm({
|
|
4744
|
+
"src/cloud/auth.ts"() {
|
|
4745
|
+
"use strict";
|
|
4746
|
+
CLOUD_API_URL = "https://api.kimiflare.com";
|
|
4747
|
+
POLL_INTERVAL_MS = 5e3;
|
|
4748
|
+
POLL_TIMEOUT_MS = 15 * 60 * 1e3;
|
|
4749
|
+
}
|
|
4750
|
+
});
|
|
4751
|
+
|
|
4520
4752
|
// src/remote/tui-auth.ts
|
|
4521
4753
|
var tui_auth_exports = {};
|
|
4522
4754
|
__export(tui_auth_exports, {
|
|
@@ -5426,9 +5658,9 @@ var init_connection = __esm({
|
|
|
5426
5658
|
});
|
|
5427
5659
|
|
|
5428
5660
|
// src/lsp/protocol.ts
|
|
5429
|
-
import { pathToFileURL, fileURLToPath as fileURLToPath4 } from "url";
|
|
5661
|
+
import { pathToFileURL as pathToFileURL2, fileURLToPath as fileURLToPath4 } from "url";
|
|
5430
5662
|
function toUri(path) {
|
|
5431
|
-
return
|
|
5663
|
+
return pathToFileURL2(path).href;
|
|
5432
5664
|
}
|
|
5433
5665
|
function fromUri(uri) {
|
|
5434
5666
|
return fileURLToPath4(uri);
|
|
@@ -6568,7 +6800,7 @@ import { useEffect, useState } from "react";
|
|
|
6568
6800
|
import { Box as Box5, Text as Text5 } from "ink";
|
|
6569
6801
|
import Spinner3 from "ink-spinner";
|
|
6570
6802
|
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
6571
|
-
function StatusBar({ model, usage, sessionUsage, thinking, turnStartedAt, mode, effort, contextLimit, hasUpdate, latestVersion, gatewayMeta, codeMode }) {
|
|
6803
|
+
function StatusBar({ model, usage, sessionUsage, thinking, turnStartedAt, mode, effort, contextLimit, hasUpdate, latestVersion, gatewayMeta, codeMode, cloudMode, cloudBudget }) {
|
|
6572
6804
|
const theme = useTheme();
|
|
6573
6805
|
const [now2, setNow] = useState(Date.now());
|
|
6574
6806
|
const modeColor = mode === "plan" ? theme.modeBadge.plan : mode === "auto" ? theme.modeBadge.auto : theme.modeBadge.edit;
|
|
@@ -6580,6 +6812,7 @@ function StatusBar({ model, usage, sessionUsage, thinking, turnStartedAt, mode,
|
|
|
6580
6812
|
}, [thinking, turnStartedAt]);
|
|
6581
6813
|
const elapsed = turnStartedAt !== null ? formatElapsed(now2 - turnStartedAt) : null;
|
|
6582
6814
|
const leftParts = [`${shortModel(model)}`, effort];
|
|
6815
|
+
if (cloudMode) leftParts.push("CLOUD");
|
|
6583
6816
|
if (codeMode) leftParts.push("CODE");
|
|
6584
6817
|
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
|
|
6585
6818
|
/* @__PURE__ */ jsxs5(Box5, { children: [
|
|
@@ -6600,7 +6833,7 @@ function StatusBar({ model, usage, sessionUsage, thinking, turnStartedAt, mode,
|
|
|
6600
6833
|
] })
|
|
6601
6834
|
] }),
|
|
6602
6835
|
usage && /* @__PURE__ */ jsxs5(Box5, { children: [
|
|
6603
|
-
/* @__PURE__ */ jsx6(Text5, { color: theme.info.color, children: buildRightParts(usage, contextLimit, sessionUsage, gatewayMeta).join(" \xB7 ") }),
|
|
6836
|
+
/* @__PURE__ */ jsx6(Text5, { color: theme.info.color, children: buildRightParts(usage, contextLimit, sessionUsage, gatewayMeta, cloudMode, cloudBudget).join(" \xB7 ") }),
|
|
6604
6837
|
warn ? /* @__PURE__ */ jsxs5(Text5, { color: theme.warn, bold: true, children: [
|
|
6605
6838
|
" \xB7 ",
|
|
6606
6839
|
"/compact recommended"
|
|
@@ -6614,7 +6847,7 @@ function StatusBar({ model, usage, sessionUsage, thinking, turnStartedAt, mode,
|
|
|
6614
6847
|
] })
|
|
6615
6848
|
] });
|
|
6616
6849
|
}
|
|
6617
|
-
function buildRightParts(usage, contextLimit, sessionUsage, gatewayMeta) {
|
|
6850
|
+
function buildRightParts(usage, contextLimit, sessionUsage, gatewayMeta, cloudMode, cloudBudget) {
|
|
6618
6851
|
const pct = Math.round(usage.prompt_tokens / contextLimit * 100);
|
|
6619
6852
|
const parts = [];
|
|
6620
6853
|
if (sessionUsage) {
|
|
@@ -6622,19 +6855,35 @@ function buildRightParts(usage, contextLimit, sessionUsage, gatewayMeta) {
|
|
|
6622
6855
|
parts.push(`in ${sessionUsage.promptTokens}${cached ? ` (${cached} cached)` : ""}`);
|
|
6623
6856
|
parts.push(`out ${sessionUsage.completionTokens}`);
|
|
6624
6857
|
parts.push(`ctx ${pct}%`);
|
|
6625
|
-
|
|
6858
|
+
if (cloudMode) {
|
|
6859
|
+
parts.push(`\x1B[9m${sessionUsage.cost.toFixed(5)}\x1B[29m`);
|
|
6860
|
+
} else {
|
|
6861
|
+
parts.push(`${sessionUsage.cost.toFixed(5)}`);
|
|
6862
|
+
}
|
|
6626
6863
|
} else {
|
|
6627
6864
|
const cached = usage.prompt_tokens_details?.cached_tokens ?? 0;
|
|
6628
6865
|
const cost = calculateCost(usage.prompt_tokens, usage.completion_tokens, cached);
|
|
6629
6866
|
parts.push(`in ${usage.prompt_tokens}${cached ? ` (${cached} cached)` : ""}`);
|
|
6630
6867
|
parts.push(`out ${usage.completion_tokens}`);
|
|
6631
6868
|
parts.push(`ctx ${pct}%`);
|
|
6632
|
-
|
|
6869
|
+
if (cloudMode) {
|
|
6870
|
+
parts.push(`\x1B[9m${cost.total.toFixed(5)}\x1B[29m`);
|
|
6871
|
+
} else {
|
|
6872
|
+
parts.push(`${cost.total.toFixed(5)}`);
|
|
6873
|
+
}
|
|
6874
|
+
}
|
|
6875
|
+
if (cloudMode && cloudBudget) {
|
|
6876
|
+
parts.push(`${formatTokens(cloudBudget.remaining)}/${formatTokens(cloudBudget.limit)} tokens`);
|
|
6633
6877
|
}
|
|
6634
6878
|
const gatewayCache = formatGatewayCacheStatus(gatewayMeta);
|
|
6635
6879
|
if (gatewayCache) parts.push(gatewayCache);
|
|
6636
6880
|
return parts;
|
|
6637
6881
|
}
|
|
6882
|
+
function formatTokens(n) {
|
|
6883
|
+
if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
|
|
6884
|
+
if (n >= 1e3) return `${(n / 1e3).toFixed(1)}K`;
|
|
6885
|
+
return String(n);
|
|
6886
|
+
}
|
|
6638
6887
|
function formatGatewayCacheStatus(gatewayMeta) {
|
|
6639
6888
|
const status = gatewayMeta?.cacheStatus?.trim();
|
|
6640
6889
|
return status ? `AI Gateway \xB7 cache ${status.toLowerCase()}` : null;
|
|
@@ -6695,11 +6944,48 @@ var init_permission = __esm({
|
|
|
6695
6944
|
}
|
|
6696
6945
|
});
|
|
6697
6946
|
|
|
6698
|
-
// src/ui/
|
|
6699
|
-
import {
|
|
6700
|
-
import { Box as Box7, Text as Text7, useWindowSize } from "ink";
|
|
6947
|
+
// src/ui/limit-modal.tsx
|
|
6948
|
+
import { Box as Box7, Text as Text7 } from "ink";
|
|
6701
6949
|
import SelectInput2 from "ink-select-input";
|
|
6702
6950
|
import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
6951
|
+
function LimitModal({ limit, onDecide }) {
|
|
6952
|
+
const theme = useTheme();
|
|
6953
|
+
const items = [
|
|
6954
|
+
{ label: "Continue", value: "continue" },
|
|
6955
|
+
{ label: "Stop", value: "stop" }
|
|
6956
|
+
];
|
|
6957
|
+
return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", borderStyle: "round", borderColor: theme.error, paddingX: 1, children: [
|
|
6958
|
+
/* @__PURE__ */ jsxs7(Text7, { color: theme.error, bold: true, children: [
|
|
6959
|
+
"Tool-call limit reached (",
|
|
6960
|
+
limit,
|
|
6961
|
+
")"
|
|
6962
|
+
] }),
|
|
6963
|
+
/* @__PURE__ */ jsxs7(Text7, { dimColor: true, children: [
|
|
6964
|
+
"This session has made ",
|
|
6965
|
+
limit,
|
|
6966
|
+
" tool calls. What would you like to do?"
|
|
6967
|
+
] }),
|
|
6968
|
+
/* @__PURE__ */ jsx8(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx8(
|
|
6969
|
+
SelectInput2,
|
|
6970
|
+
{
|
|
6971
|
+
items,
|
|
6972
|
+
onSelect: (item) => onDecide(item.value)
|
|
6973
|
+
}
|
|
6974
|
+
) })
|
|
6975
|
+
] });
|
|
6976
|
+
}
|
|
6977
|
+
var init_limit_modal = __esm({
|
|
6978
|
+
"src/ui/limit-modal.tsx"() {
|
|
6979
|
+
"use strict";
|
|
6980
|
+
init_theme_context();
|
|
6981
|
+
}
|
|
6982
|
+
});
|
|
6983
|
+
|
|
6984
|
+
// src/ui/resume-picker.tsx
|
|
6985
|
+
import { useState as useState2 } from "react";
|
|
6986
|
+
import { Box as Box8, Text as Text8, useWindowSize } from "ink";
|
|
6987
|
+
import SelectInput3 from "ink-select-input";
|
|
6988
|
+
import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
6703
6989
|
function ResumePicker({ sessions, onPick }) {
|
|
6704
6990
|
const theme = useTheme();
|
|
6705
6991
|
const { rows } = useWindowSize();
|
|
@@ -6708,11 +6994,11 @@ function ResumePicker({ sessions, onPick }) {
|
|
|
6708
6994
|
const totalPages = Math.max(1, Math.ceil(sessions.length / pageSize));
|
|
6709
6995
|
const safePage = Math.min(page, totalPages - 1);
|
|
6710
6996
|
if (sessions.length === 0) {
|
|
6711
|
-
return /* @__PURE__ */
|
|
6712
|
-
/* @__PURE__ */
|
|
6713
|
-
/* @__PURE__ */
|
|
6714
|
-
/* @__PURE__ */
|
|
6715
|
-
|
|
6997
|
+
return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
6998
|
+
/* @__PURE__ */ jsx9(Text8, { color: theme.accent, bold: true, children: "Resume a session" }),
|
|
6999
|
+
/* @__PURE__ */ jsx9(Text8, { color: theme.info.color, children: "No saved sessions yet. Press Enter to dismiss." }),
|
|
7000
|
+
/* @__PURE__ */ jsx9(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx9(
|
|
7001
|
+
SelectInput3,
|
|
6716
7002
|
{
|
|
6717
7003
|
items: [{ label: "(back)", value: "__cancel__" }],
|
|
6718
7004
|
onSelect: () => onPick(null)
|
|
@@ -6734,9 +7020,9 @@ function ResumePicker({ sessions, onPick }) {
|
|
|
6734
7020
|
items.push({ label: "\u2192 next page", value: "__next__" });
|
|
6735
7021
|
}
|
|
6736
7022
|
items.push({ label: "(cancel)", value: "__cancel__" });
|
|
6737
|
-
return /* @__PURE__ */
|
|
6738
|
-
/* @__PURE__ */
|
|
6739
|
-
/* @__PURE__ */
|
|
7023
|
+
return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
7024
|
+
/* @__PURE__ */ jsx9(Text8, { color: theme.accent, bold: true, children: "Resume a session" }),
|
|
7025
|
+
/* @__PURE__ */ jsxs8(Text8, { color: theme.info.color, children: [
|
|
6740
7026
|
"Arrow keys to select, Enter to confirm. Page ",
|
|
6741
7027
|
safePage + 1,
|
|
6742
7028
|
" of ",
|
|
@@ -6745,8 +7031,8 @@ function ResumePicker({ sessions, onPick }) {
|
|
|
6745
7031
|
sessions.length,
|
|
6746
7032
|
" total)"
|
|
6747
7033
|
] }),
|
|
6748
|
-
/* @__PURE__ */
|
|
6749
|
-
|
|
7034
|
+
/* @__PURE__ */ jsx9(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx9(
|
|
7035
|
+
SelectInput3,
|
|
6750
7036
|
{
|
|
6751
7037
|
items,
|
|
6752
7038
|
onSelect: (item) => {
|
|
@@ -6786,9 +7072,9 @@ var init_resume_picker = __esm({
|
|
|
6786
7072
|
|
|
6787
7073
|
// src/ui/task-list.tsx
|
|
6788
7074
|
import { useEffect as useEffect2, useRef, useState as useState3 } from "react";
|
|
6789
|
-
import { Box as
|
|
7075
|
+
import { Box as Box9, Text as Text9 } from "ink";
|
|
6790
7076
|
import Spinner4 from "ink-spinner";
|
|
6791
|
-
import { jsx as
|
|
7077
|
+
import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
6792
7078
|
function TaskList({ tasks, startedAt, tokensDelta }) {
|
|
6793
7079
|
const theme = useTheme();
|
|
6794
7080
|
const [now2, setNow] = useState3(Date.now());
|
|
@@ -6812,21 +7098,21 @@ function TaskList({ tasks, startedAt, tokensDelta }) {
|
|
|
6812
7098
|
const allDone = done === total;
|
|
6813
7099
|
const header = active ? active.title : allDone ? `${total} tasks done` : `${done}/${total}`;
|
|
6814
7100
|
const elapsed = startedAt ? formatElapsed2(now2 - startedAt) : null;
|
|
6815
|
-
const headerStats = [elapsed, tokensDelta > 0 ? `\u2191 ${
|
|
7101
|
+
const headerStats = [elapsed, tokensDelta > 0 ? `\u2191 ${formatTokens2(tokensDelta)} tokens` : null].filter(Boolean).join(" \xB7 ");
|
|
6816
7102
|
const visibleTasks = tasks.slice(0, MAX_VISIBLE);
|
|
6817
7103
|
const hiddenPending = Math.max(0, tasks.length - visibleTasks.length);
|
|
6818
|
-
return /* @__PURE__ */
|
|
6819
|
-
/* @__PURE__ */
|
|
6820
|
-
/* @__PURE__ */
|
|
6821
|
-
headerStats && /* @__PURE__ */
|
|
7104
|
+
return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", marginBottom: 1, children: [
|
|
7105
|
+
/* @__PURE__ */ jsxs9(Box9, { children: [
|
|
7106
|
+
/* @__PURE__ */ jsx10(Text9, { color: allDone ? "green" : theme.accent, bold: true, children: header }),
|
|
7107
|
+
headerStats && /* @__PURE__ */ jsxs9(Text9, { color: theme.info.color, children: [
|
|
6822
7108
|
" ",
|
|
6823
7109
|
"(",
|
|
6824
7110
|
headerStats,
|
|
6825
7111
|
")"
|
|
6826
7112
|
] })
|
|
6827
7113
|
] }),
|
|
6828
|
-
visibleTasks.map((t) => /* @__PURE__ */
|
|
6829
|
-
hiddenPending > 0 && /* @__PURE__ */
|
|
7114
|
+
visibleTasks.map((t) => /* @__PURE__ */ jsx10(TaskRow, { task: t }, t.id)),
|
|
7115
|
+
hiddenPending > 0 && /* @__PURE__ */ jsxs9(Text9, { color: theme.info.color, children: [
|
|
6830
7116
|
" ",
|
|
6831
7117
|
"\u2026 +",
|
|
6832
7118
|
hiddenPending,
|
|
@@ -6837,21 +7123,21 @@ function TaskList({ tasks, startedAt, tokensDelta }) {
|
|
|
6837
7123
|
function TaskRow({ task }) {
|
|
6838
7124
|
const theme = useTheme();
|
|
6839
7125
|
if (task.status === "completed") {
|
|
6840
|
-
return /* @__PURE__ */
|
|
7126
|
+
return /* @__PURE__ */ jsxs9(Text9, { color: theme.info.color, children: [
|
|
6841
7127
|
" ",
|
|
6842
7128
|
"\u2713 ",
|
|
6843
|
-
/* @__PURE__ */
|
|
7129
|
+
/* @__PURE__ */ jsx10(Text9, { strikethrough: true, children: task.title })
|
|
6844
7130
|
] });
|
|
6845
7131
|
}
|
|
6846
7132
|
if (task.status === "in_progress") {
|
|
6847
|
-
return /* @__PURE__ */
|
|
7133
|
+
return /* @__PURE__ */ jsxs9(Text9, { color: theme.accent, bold: true, children: [
|
|
6848
7134
|
" ",
|
|
6849
|
-
/* @__PURE__ */
|
|
7135
|
+
/* @__PURE__ */ jsx10(Spinner4, { type: "dots" }),
|
|
6850
7136
|
" ",
|
|
6851
7137
|
task.title
|
|
6852
7138
|
] });
|
|
6853
7139
|
}
|
|
6854
|
-
return /* @__PURE__ */
|
|
7140
|
+
return /* @__PURE__ */ jsxs9(Text9, { color: theme.info.color, children: [
|
|
6855
7141
|
" ",
|
|
6856
7142
|
"\u2610 ",
|
|
6857
7143
|
task.title
|
|
@@ -6864,7 +7150,7 @@ function formatElapsed2(ms) {
|
|
|
6864
7150
|
if (m === 0) return `${s}s`;
|
|
6865
7151
|
return `${m}m ${s}s`;
|
|
6866
7152
|
}
|
|
6867
|
-
function
|
|
7153
|
+
function formatTokens2(n) {
|
|
6868
7154
|
if (n < 1e3) return String(n);
|
|
6869
7155
|
return `${(n / 1e3).toFixed(1)}k`;
|
|
6870
7156
|
}
|
|
@@ -7399,8 +7685,8 @@ var init_source = __esm({
|
|
|
7399
7685
|
|
|
7400
7686
|
// src/ui/text-input.tsx
|
|
7401
7687
|
import { useState as useState4, useEffect as useEffect3, useRef as useRef2 } from "react";
|
|
7402
|
-
import { Text as
|
|
7403
|
-
import { jsx as
|
|
7688
|
+
import { Text as Text10, useInput } from "ink";
|
|
7689
|
+
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
7404
7690
|
function shouldTreatAsPaste(input) {
|
|
7405
7691
|
if (input.length >= PASTE_CHAR_THRESHOLD) return true;
|
|
7406
7692
|
const newlines = (input.match(/\n/g) ?? []).length;
|
|
@@ -7610,7 +7896,7 @@ function CustomTextInput({
|
|
|
7610
7896
|
} else if (cursorOffset === displayValue.length) {
|
|
7611
7897
|
renderedValue += source_default.inverse(" ");
|
|
7612
7898
|
}
|
|
7613
|
-
return /* @__PURE__ */
|
|
7899
|
+
return /* @__PURE__ */ jsx11(Text10, { children: renderedValue });
|
|
7614
7900
|
}
|
|
7615
7901
|
function findPasteTokenEndingAt(value, pos, pastes) {
|
|
7616
7902
|
if (pos <= 0 || value[pos - 1] !== "]") return -1;
|
|
@@ -7632,17 +7918,138 @@ var init_text_input = __esm({
|
|
|
7632
7918
|
});
|
|
7633
7919
|
|
|
7634
7920
|
// src/ui/onboarding.tsx
|
|
7635
|
-
import { useState as useState5 } from "react";
|
|
7636
|
-
import { Box as
|
|
7637
|
-
import
|
|
7638
|
-
|
|
7921
|
+
import { useState as useState5, useEffect as useEffect4, useCallback } from "react";
|
|
7922
|
+
import { Box as Box10, Text as Text11, useInput as useInput2 } from "ink";
|
|
7923
|
+
import SelectInput4 from "ink-select-input";
|
|
7924
|
+
import Spinner5 from "ink-spinner";
|
|
7925
|
+
import { exec } from "child_process";
|
|
7926
|
+
import { promisify as promisify2 } from "util";
|
|
7927
|
+
import { Fragment, jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
7928
|
+
function openBrowser(url) {
|
|
7929
|
+
const platform3 = process.platform;
|
|
7930
|
+
const cmd = platform3 === "darwin" ? `open "${url}"` : platform3 === "win32" ? `start "" "${url}"` : `xdg-open "${url}"`;
|
|
7931
|
+
exec(cmd, (err) => {
|
|
7932
|
+
if (err) {
|
|
7933
|
+
}
|
|
7934
|
+
});
|
|
7935
|
+
}
|
|
7936
|
+
function formatRemaining(ms) {
|
|
7937
|
+
const totalSeconds = Math.ceil(ms / 1e3);
|
|
7938
|
+
const mins = Math.floor(totalSeconds / 60);
|
|
7939
|
+
const secs = totalSeconds % 60;
|
|
7940
|
+
return `${mins}:${secs.toString().padStart(2, "0")}`;
|
|
7941
|
+
}
|
|
7942
|
+
function Onboarding({ onDone, onCancel }) {
|
|
7639
7943
|
const theme = useTheme();
|
|
7640
|
-
const [step, setStep] = useState5("
|
|
7944
|
+
const [step, setStep] = useState5("mode");
|
|
7945
|
+
const [mode, setMode] = useState5("byok");
|
|
7641
7946
|
const [accountId, setAccountId] = useState5("");
|
|
7642
7947
|
const [apiToken, setApiToken] = useState5("");
|
|
7643
7948
|
const [model, setModel] = useState5(DEFAULT_MODEL);
|
|
7644
7949
|
const [savedPath, setSavedPath] = useState5(null);
|
|
7645
|
-
const
|
|
7950
|
+
const [cloudAuth, setCloudAuth] = useState5(null);
|
|
7951
|
+
const [pollTick, setPollTick] = useState5(0);
|
|
7952
|
+
useEffect4(() => {
|
|
7953
|
+
if (step !== "cloudAuth" || !cloudAuth) return;
|
|
7954
|
+
if (cloudAuth.phase !== "polling") return;
|
|
7955
|
+
let cancelled = false;
|
|
7956
|
+
const tick = setInterval(() => {
|
|
7957
|
+
setPollTick((t) => t + 1);
|
|
7958
|
+
}, 1e3);
|
|
7959
|
+
const poll = async () => {
|
|
7960
|
+
while (!cancelled) {
|
|
7961
|
+
const elapsed = Date.now() - cloudAuth.startTime;
|
|
7962
|
+
if (elapsed >= POLL_TIMEOUT_MS) {
|
|
7963
|
+
if (!cancelled) {
|
|
7964
|
+
setCloudAuth({ phase: "error", message: "Authentication timed out. Please try again." });
|
|
7965
|
+
}
|
|
7966
|
+
return;
|
|
7967
|
+
}
|
|
7968
|
+
try {
|
|
7969
|
+
const creds = await pollForToken(cloudAuth.codes.deviceCode);
|
|
7970
|
+
if (creds && !cancelled) {
|
|
7971
|
+
const usage = await fetchCloudUsage(creds.accessToken);
|
|
7972
|
+
if (usage && !cancelled) {
|
|
7973
|
+
setCloudAuth({
|
|
7974
|
+
phase: "success",
|
|
7975
|
+
creds,
|
|
7976
|
+
usage
|
|
7977
|
+
});
|
|
7978
|
+
} else if (!cancelled) {
|
|
7979
|
+
setCloudAuth({ phase: "error", message: "Authenticated but failed to fetch usage." });
|
|
7980
|
+
}
|
|
7981
|
+
return;
|
|
7982
|
+
}
|
|
7983
|
+
} catch {
|
|
7984
|
+
}
|
|
7985
|
+
await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
|
|
7986
|
+
}
|
|
7987
|
+
};
|
|
7988
|
+
poll();
|
|
7989
|
+
return () => {
|
|
7990
|
+
cancelled = true;
|
|
7991
|
+
clearInterval(tick);
|
|
7992
|
+
};
|
|
7993
|
+
}, [step, cloudAuth]);
|
|
7994
|
+
useInput2(
|
|
7995
|
+
useCallback(
|
|
7996
|
+
(_input, key) => {
|
|
7997
|
+
if (key.escape && onCancel) {
|
|
7998
|
+
onCancel();
|
|
7999
|
+
}
|
|
8000
|
+
},
|
|
8001
|
+
[onCancel]
|
|
8002
|
+
)
|
|
8003
|
+
);
|
|
8004
|
+
const startCloudAuth = useCallback(async () => {
|
|
8005
|
+
try {
|
|
8006
|
+
const codes = generateDeviceCodes();
|
|
8007
|
+
await registerDevice(codes);
|
|
8008
|
+
setCloudAuth({ phase: "ready", codes });
|
|
8009
|
+
setStep("cloudAuth");
|
|
8010
|
+
} catch (err) {
|
|
8011
|
+
setCloudAuth({
|
|
8012
|
+
phase: "error",
|
|
8013
|
+
message: err instanceof Error ? err.message : "Failed to start authentication"
|
|
8014
|
+
});
|
|
8015
|
+
setStep("cloudAuth");
|
|
8016
|
+
}
|
|
8017
|
+
}, []);
|
|
8018
|
+
const handleModeSelect = (item) => {
|
|
8019
|
+
if (item.value === "cloud") {
|
|
8020
|
+
setMode("cloud");
|
|
8021
|
+
void startCloudAuth();
|
|
8022
|
+
} else {
|
|
8023
|
+
setMode("byok");
|
|
8024
|
+
setStep("accountId");
|
|
8025
|
+
}
|
|
8026
|
+
};
|
|
8027
|
+
const handleOpenBrowser = () => {
|
|
8028
|
+
if (cloudAuth?.phase === "ready") {
|
|
8029
|
+
openBrowser(cloudAuth.codes.authUrl);
|
|
8030
|
+
setCloudAuth({ phase: "polling", codes: cloudAuth.codes, startTime: Date.now() });
|
|
8031
|
+
}
|
|
8032
|
+
};
|
|
8033
|
+
const handleCloudSuccess = async () => {
|
|
8034
|
+
if (cloudAuth?.phase !== "success") return;
|
|
8035
|
+
const cfg = { accountId: "", apiToken: "", model: DEFAULT_MODEL, cloudMode: true };
|
|
8036
|
+
try {
|
|
8037
|
+
const path = await saveConfig(cfg);
|
|
8038
|
+
setSavedPath(path);
|
|
8039
|
+
onDone(cfg);
|
|
8040
|
+
} catch (e) {
|
|
8041
|
+
setSavedPath(`error: ${e.message}`);
|
|
8042
|
+
}
|
|
8043
|
+
};
|
|
8044
|
+
const handleCloudRetry = () => {
|
|
8045
|
+
setCloudAuth(null);
|
|
8046
|
+
void startCloudAuth();
|
|
8047
|
+
};
|
|
8048
|
+
const handleCloudSwitchToByok = () => {
|
|
8049
|
+
setCloudAuth(null);
|
|
8050
|
+
setMode("byok");
|
|
8051
|
+
setStep("accountId");
|
|
8052
|
+
};
|
|
7646
8053
|
const handleAccountIdSubmit = (value) => {
|
|
7647
8054
|
const trimmed = value.trim();
|
|
7648
8055
|
if (!trimmed) return;
|
|
@@ -7670,26 +8077,133 @@ function Onboarding({ onDone }) {
|
|
|
7670
8077
|
setSavedPath(`error: ${e.message}`);
|
|
7671
8078
|
}
|
|
7672
8079
|
};
|
|
7673
|
-
|
|
7674
|
-
|
|
7675
|
-
|
|
7676
|
-
|
|
8080
|
+
const byokSteps = ["accountId", "apiToken", "model", "confirm"];
|
|
8081
|
+
const stepIndex = step === "mode" ? 1 : step === "cloudAuth" ? 2 : byokSteps.indexOf(step) + 2;
|
|
8082
|
+
const totalSteps = mode === "cloud" ? 2 : byokSteps.length + 1;
|
|
8083
|
+
return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", paddingY: 1, children: [
|
|
8084
|
+
/* @__PURE__ */ jsxs10(Box10, { marginBottom: 1, children: [
|
|
8085
|
+
/* @__PURE__ */ jsx12(Text11, { bold: true, color: theme.palette.primary, children: "kimiflare" }),
|
|
8086
|
+
/* @__PURE__ */ jsxs10(Text11, { color: theme.info.color, children: [
|
|
7677
8087
|
" ",
|
|
7678
8088
|
"Terminal coding agent"
|
|
7679
8089
|
] })
|
|
7680
8090
|
] }),
|
|
7681
|
-
/* @__PURE__ */
|
|
8091
|
+
/* @__PURE__ */ jsxs10(Text11, { color: theme.info.color, children: [
|
|
7682
8092
|
"Step ",
|
|
7683
8093
|
stepIndex,
|
|
7684
8094
|
" of ",
|
|
7685
|
-
|
|
8095
|
+
totalSteps
|
|
7686
8096
|
] }),
|
|
7687
|
-
/* @__PURE__ */
|
|
7688
|
-
step === "
|
|
7689
|
-
/* @__PURE__ */
|
|
7690
|
-
/* @__PURE__ */
|
|
7691
|
-
|
|
7692
|
-
|
|
8097
|
+
/* @__PURE__ */ jsxs10(Box10, { marginTop: 1, flexDirection: "column", children: [
|
|
8098
|
+
step === "mode" && /* @__PURE__ */ jsxs10(Fragment, { children: [
|
|
8099
|
+
/* @__PURE__ */ jsx12(Text11, { children: "How do you want to connect?" }),
|
|
8100
|
+
/* @__PURE__ */ jsx12(Box10, { marginTop: 1, children: /* @__PURE__ */ jsx12(
|
|
8101
|
+
SelectInput4,
|
|
8102
|
+
{
|
|
8103
|
+
items: [
|
|
8104
|
+
{ label: "Cloud (managed) \u2014 no API key needed", value: "cloud" },
|
|
8105
|
+
{ label: "BYOK \u2014 bring your own Cloudflare key", value: "byok" }
|
|
8106
|
+
],
|
|
8107
|
+
onSelect: handleModeSelect
|
|
8108
|
+
}
|
|
8109
|
+
) })
|
|
8110
|
+
] }),
|
|
8111
|
+
step === "cloudAuth" && cloudAuth?.phase === "ready" && /* @__PURE__ */ jsxs10(Fragment, { children: [
|
|
8112
|
+
/* @__PURE__ */ jsx12(Text11, { children: "Authenticating with Kimiflare Cloud..." }),
|
|
8113
|
+
/* @__PURE__ */ jsxs10(Box10, { marginTop: 1, flexDirection: "column", children: [
|
|
8114
|
+
/* @__PURE__ */ jsx12(Text11, { children: "1. Open this URL in your browser:" }),
|
|
8115
|
+
/* @__PURE__ */ jsx12(Text11, { color: theme.palette.primary, children: cloudAuth.codes.authUrl })
|
|
8116
|
+
] }),
|
|
8117
|
+
/* @__PURE__ */ jsxs10(Box10, { marginTop: 1, children: [
|
|
8118
|
+
/* @__PURE__ */ jsx12(Text11, { children: "2. " }),
|
|
8119
|
+
/* @__PURE__ */ jsx12(Text11, { bold: true, children: "[Press Enter to open browser]" })
|
|
8120
|
+
] }),
|
|
8121
|
+
/* @__PURE__ */ jsxs10(Box10, { marginTop: 1, children: [
|
|
8122
|
+
/* @__PURE__ */ jsx12(Text11, { color: theme.palette.primary, children: "\u203A " }),
|
|
8123
|
+
/* @__PURE__ */ jsx12(
|
|
8124
|
+
CustomTextInput,
|
|
8125
|
+
{
|
|
8126
|
+
value: "",
|
|
8127
|
+
onChange: () => {
|
|
8128
|
+
},
|
|
8129
|
+
onSubmit: handleOpenBrowser
|
|
8130
|
+
}
|
|
8131
|
+
)
|
|
8132
|
+
] })
|
|
8133
|
+
] }),
|
|
8134
|
+
step === "cloudAuth" && cloudAuth?.phase === "polling" && /* @__PURE__ */ jsxs10(Fragment, { children: [
|
|
8135
|
+
/* @__PURE__ */ jsxs10(Text11, { children: [
|
|
8136
|
+
/* @__PURE__ */ jsx12(Text11, { color: theme.spinner, children: /* @__PURE__ */ jsx12(Spinner5, { type: "dots" }) }),
|
|
8137
|
+
" ",
|
|
8138
|
+
"Waiting for authentication..."
|
|
8139
|
+
] }),
|
|
8140
|
+
/* @__PURE__ */ jsxs10(Text11, { color: theme.info.color, children: [
|
|
8141
|
+
"Expires in ",
|
|
8142
|
+
formatRemaining(POLL_TIMEOUT_MS - (Date.now() - cloudAuth.startTime))
|
|
8143
|
+
] }),
|
|
8144
|
+
/* @__PURE__ */ jsxs10(Text11, { color: theme.info.color, children: [
|
|
8145
|
+
"URL: ",
|
|
8146
|
+
cloudAuth.codes.authUrl
|
|
8147
|
+
] })
|
|
8148
|
+
] }),
|
|
8149
|
+
step === "cloudAuth" && cloudAuth?.phase === "success" && /* @__PURE__ */ jsxs10(Fragment, { children: [
|
|
8150
|
+
/* @__PURE__ */ jsx12(Text11, { color: theme.palette.success, children: "Authenticated!" }),
|
|
8151
|
+
/* @__PURE__ */ jsxs10(Box10, { marginTop: 1, flexDirection: "column", children: [
|
|
8152
|
+
/* @__PURE__ */ jsxs10(Text11, { children: [
|
|
8153
|
+
"Token budget:",
|
|
8154
|
+
" ",
|
|
8155
|
+
/* @__PURE__ */ jsxs10(Text11, { bold: true, children: [
|
|
8156
|
+
cloudAuth.usage.remaining.toLocaleString(),
|
|
8157
|
+
" /",
|
|
8158
|
+
" ",
|
|
8159
|
+
cloudAuth.usage.input_token_limit.toLocaleString()
|
|
8160
|
+
] }),
|
|
8161
|
+
" ",
|
|
8162
|
+
"remaining"
|
|
8163
|
+
] }),
|
|
8164
|
+
/* @__PURE__ */ jsxs10(Text11, { color: theme.info.color, children: [
|
|
8165
|
+
"Grant expires: ",
|
|
8166
|
+
cloudAuth.usage.expires_at
|
|
8167
|
+
] })
|
|
8168
|
+
] }),
|
|
8169
|
+
/* @__PURE__ */ jsx12(Box10, { marginTop: 1, children: /* @__PURE__ */ jsx12(Text11, { children: "[Press Enter to continue]" }) }),
|
|
8170
|
+
/* @__PURE__ */ jsxs10(Box10, { marginTop: 1, children: [
|
|
8171
|
+
/* @__PURE__ */ jsx12(Text11, { color: theme.palette.primary, children: "\u203A " }),
|
|
8172
|
+
/* @__PURE__ */ jsx12(
|
|
8173
|
+
CustomTextInput,
|
|
8174
|
+
{
|
|
8175
|
+
value: "",
|
|
8176
|
+
onChange: () => {
|
|
8177
|
+
},
|
|
8178
|
+
onSubmit: handleCloudSuccess
|
|
8179
|
+
}
|
|
8180
|
+
)
|
|
8181
|
+
] })
|
|
8182
|
+
] }),
|
|
8183
|
+
step === "cloudAuth" && cloudAuth?.phase === "error" && /* @__PURE__ */ jsxs10(Fragment, { children: [
|
|
8184
|
+
/* @__PURE__ */ jsx12(Text11, { color: theme.palette.error, children: "Authentication failed" }),
|
|
8185
|
+
/* @__PURE__ */ jsx12(Text11, { color: theme.info.color, children: cloudAuth.message }),
|
|
8186
|
+
/* @__PURE__ */ jsx12(Box10, { marginTop: 1, children: /* @__PURE__ */ jsx12(
|
|
8187
|
+
SelectInput4,
|
|
8188
|
+
{
|
|
8189
|
+
items: [
|
|
8190
|
+
{ label: "Retry", value: "retry" },
|
|
8191
|
+
{ label: "Switch to BYOK", value: "byok" },
|
|
8192
|
+
{ label: "Cancel", value: "cancel" }
|
|
8193
|
+
],
|
|
8194
|
+
onSelect: (item) => {
|
|
8195
|
+
if (item.value === "retry") handleCloudRetry();
|
|
8196
|
+
else if (item.value === "byok") handleCloudSwitchToByok();
|
|
8197
|
+
else if (onCancel) onCancel();
|
|
8198
|
+
}
|
|
8199
|
+
}
|
|
8200
|
+
) })
|
|
8201
|
+
] }),
|
|
8202
|
+
step === "accountId" && /* @__PURE__ */ jsxs10(Fragment, { children: [
|
|
8203
|
+
/* @__PURE__ */ jsx12(Text11, { children: "Enter your Cloudflare Account ID" }),
|
|
8204
|
+
/* @__PURE__ */ jsxs10(Box10, { marginTop: 1, children: [
|
|
8205
|
+
/* @__PURE__ */ jsx12(Text11, { color: theme.palette.primary, children: "\u203A " }),
|
|
8206
|
+
/* @__PURE__ */ jsx12(
|
|
7693
8207
|
CustomTextInput,
|
|
7694
8208
|
{
|
|
7695
8209
|
value: accountId,
|
|
@@ -7699,12 +8213,12 @@ function Onboarding({ onDone }) {
|
|
|
7699
8213
|
)
|
|
7700
8214
|
] })
|
|
7701
8215
|
] }),
|
|
7702
|
-
step === "apiToken" && /* @__PURE__ */
|
|
7703
|
-
/* @__PURE__ */
|
|
7704
|
-
/* @__PURE__ */
|
|
7705
|
-
/* @__PURE__ */
|
|
7706
|
-
/* @__PURE__ */
|
|
7707
|
-
/* @__PURE__ */
|
|
8216
|
+
step === "apiToken" && /* @__PURE__ */ jsxs10(Fragment, { children: [
|
|
8217
|
+
/* @__PURE__ */ jsx12(Text11, { children: "Enter your Cloudflare API Token" }),
|
|
8218
|
+
/* @__PURE__ */ jsx12(Text11, { color: theme.info.color, children: "Create one at https://dash.cloudflare.com/profile/api-tokens" }),
|
|
8219
|
+
/* @__PURE__ */ jsxs10(Box10, { marginTop: 1, children: [
|
|
8220
|
+
/* @__PURE__ */ jsx12(Text11, { color: theme.palette.primary, children: "\u203A " }),
|
|
8221
|
+
/* @__PURE__ */ jsx12(
|
|
7708
8222
|
CustomTextInput,
|
|
7709
8223
|
{
|
|
7710
8224
|
value: apiToken,
|
|
@@ -7715,15 +8229,15 @@ function Onboarding({ onDone }) {
|
|
|
7715
8229
|
)
|
|
7716
8230
|
] })
|
|
7717
8231
|
] }),
|
|
7718
|
-
step === "model" && /* @__PURE__ */
|
|
7719
|
-
/* @__PURE__ */
|
|
7720
|
-
/* @__PURE__ */
|
|
8232
|
+
step === "model" && /* @__PURE__ */ jsxs10(Fragment, { children: [
|
|
8233
|
+
/* @__PURE__ */ jsx12(Text11, { children: "Model ID (press Enter for default)" }),
|
|
8234
|
+
/* @__PURE__ */ jsxs10(Text11, { color: theme.info.color, children: [
|
|
7721
8235
|
"default: ",
|
|
7722
8236
|
DEFAULT_MODEL
|
|
7723
8237
|
] }),
|
|
7724
|
-
/* @__PURE__ */
|
|
7725
|
-
/* @__PURE__ */
|
|
7726
|
-
/* @__PURE__ */
|
|
8238
|
+
/* @__PURE__ */ jsxs10(Box10, { marginTop: 1, children: [
|
|
8239
|
+
/* @__PURE__ */ jsx12(Text11, { color: theme.palette.primary, children: "\u203A " }),
|
|
8240
|
+
/* @__PURE__ */ jsx12(
|
|
7727
8241
|
CustomTextInput,
|
|
7728
8242
|
{
|
|
7729
8243
|
value: model,
|
|
@@ -7733,10 +8247,10 @@ function Onboarding({ onDone }) {
|
|
|
7733
8247
|
)
|
|
7734
8248
|
] })
|
|
7735
8249
|
] }),
|
|
7736
|
-
step === "confirm" && /* @__PURE__ */
|
|
7737
|
-
/* @__PURE__ */
|
|
7738
|
-
/* @__PURE__ */
|
|
7739
|
-
|
|
8250
|
+
step === "confirm" && /* @__PURE__ */ jsxs10(Fragment, { children: [
|
|
8251
|
+
/* @__PURE__ */ jsx12(Text11, { children: "Ready to save configuration" }),
|
|
8252
|
+
/* @__PURE__ */ jsxs10(
|
|
8253
|
+
Box10,
|
|
7740
8254
|
{
|
|
7741
8255
|
flexDirection: "column",
|
|
7742
8256
|
marginTop: 1,
|
|
@@ -7745,25 +8259,25 @@ function Onboarding({ onDone }) {
|
|
|
7745
8259
|
borderColor: theme.info.color,
|
|
7746
8260
|
paddingX: 1,
|
|
7747
8261
|
children: [
|
|
7748
|
-
/* @__PURE__ */
|
|
8262
|
+
/* @__PURE__ */ jsxs10(Text11, { color: theme.info.color, children: [
|
|
7749
8263
|
"Account ID: ",
|
|
7750
8264
|
accountId
|
|
7751
8265
|
] }),
|
|
7752
|
-
/* @__PURE__ */
|
|
8266
|
+
/* @__PURE__ */ jsxs10(Text11, { color: theme.info.color, children: [
|
|
7753
8267
|
"API Token: ",
|
|
7754
8268
|
"\u2022".repeat(apiToken.length)
|
|
7755
8269
|
] }),
|
|
7756
|
-
/* @__PURE__ */
|
|
8270
|
+
/* @__PURE__ */ jsxs10(Text11, { color: theme.info.color, children: [
|
|
7757
8271
|
"Model: ",
|
|
7758
8272
|
model
|
|
7759
8273
|
] })
|
|
7760
8274
|
]
|
|
7761
8275
|
}
|
|
7762
8276
|
),
|
|
7763
|
-
/* @__PURE__ */
|
|
7764
|
-
/* @__PURE__ */
|
|
7765
|
-
/* @__PURE__ */
|
|
7766
|
-
/* @__PURE__ */
|
|
8277
|
+
/* @__PURE__ */ jsx12(Text11, { children: "Press Enter to confirm, or Ctrl+C to cancel" }),
|
|
8278
|
+
/* @__PURE__ */ jsxs10(Box10, { marginTop: 1, children: [
|
|
8279
|
+
/* @__PURE__ */ jsx12(Text11, { color: theme.palette.primary, children: "\u203A " }),
|
|
8280
|
+
/* @__PURE__ */ jsx12(
|
|
7767
8281
|
CustomTextInput,
|
|
7768
8282
|
{
|
|
7769
8283
|
value: "",
|
|
@@ -7774,53 +8288,54 @@ function Onboarding({ onDone }) {
|
|
|
7774
8288
|
)
|
|
7775
8289
|
] })
|
|
7776
8290
|
] }),
|
|
7777
|
-
savedPath && /* @__PURE__ */
|
|
8291
|
+
savedPath && /* @__PURE__ */ jsxs10(Text11, { color: theme.palette.success, children: [
|
|
7778
8292
|
"Config saved to ",
|
|
7779
8293
|
savedPath
|
|
7780
8294
|
] })
|
|
7781
8295
|
] })
|
|
7782
8296
|
] });
|
|
7783
8297
|
}
|
|
7784
|
-
var
|
|
8298
|
+
var execAsync;
|
|
7785
8299
|
var init_onboarding = __esm({
|
|
7786
8300
|
"src/ui/onboarding.tsx"() {
|
|
7787
8301
|
"use strict";
|
|
7788
8302
|
init_text_input();
|
|
7789
8303
|
init_config();
|
|
7790
8304
|
init_theme_context();
|
|
7791
|
-
|
|
8305
|
+
init_auth();
|
|
8306
|
+
execAsync = promisify2(exec);
|
|
7792
8307
|
}
|
|
7793
8308
|
});
|
|
7794
8309
|
|
|
7795
8310
|
// src/ui/welcome.tsx
|
|
7796
|
-
import { Box as
|
|
7797
|
-
import { jsx as
|
|
8311
|
+
import { Box as Box11, Text as Text12 } from "ink";
|
|
8312
|
+
import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
7798
8313
|
function Welcome({ accountId }) {
|
|
7799
8314
|
const theme = useTheme();
|
|
7800
|
-
return /* @__PURE__ */
|
|
7801
|
-
/* @__PURE__ */
|
|
7802
|
-
/* @__PURE__ */
|
|
7803
|
-
/* @__PURE__ */
|
|
8315
|
+
return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", marginBottom: 1, children: [
|
|
8316
|
+
/* @__PURE__ */ jsxs11(Box11, { marginBottom: 1, children: [
|
|
8317
|
+
/* @__PURE__ */ jsx13(Text12, { bold: true, color: theme.accent, children: "kimiflare" }),
|
|
8318
|
+
/* @__PURE__ */ jsxs11(Text12, { color: theme.info.color, children: [
|
|
7804
8319
|
" ",
|
|
7805
8320
|
"Ready when you are."
|
|
7806
8321
|
] })
|
|
7807
8322
|
] }),
|
|
7808
|
-
accountId && /* @__PURE__ */
|
|
8323
|
+
accountId && /* @__PURE__ */ jsx13(Box11, { marginBottom: 1, children: /* @__PURE__ */ jsxs11(Text12, { color: theme.info.color, children: [
|
|
7809
8324
|
" ",
|
|
7810
8325
|
"Check your Cloudflare billing: https://dash.cloudflare.com/",
|
|
7811
8326
|
accountId,
|
|
7812
8327
|
"/billing/billable-usage"
|
|
7813
8328
|
] }) }),
|
|
7814
|
-
/* @__PURE__ */
|
|
7815
|
-
/* @__PURE__ */
|
|
8329
|
+
/* @__PURE__ */ jsx13(Box11, { flexDirection: "column", children: SUGGESTIONS.map((s, i) => /* @__PURE__ */ jsxs11(Box11, { children: [
|
|
8330
|
+
/* @__PURE__ */ jsxs11(Text12, { color: theme.info.color, children: [
|
|
7816
8331
|
" ",
|
|
7817
8332
|
"\u203A",
|
|
7818
8333
|
" "
|
|
7819
8334
|
] }),
|
|
7820
|
-
/* @__PURE__ */
|
|
8335
|
+
/* @__PURE__ */ jsx13(Text12, { color: theme.user, children: s })
|
|
7821
8336
|
] }, i)) }),
|
|
7822
|
-
/* @__PURE__ */
|
|
7823
|
-
/* @__PURE__ */
|
|
8337
|
+
/* @__PURE__ */ jsx13(Box11, { marginTop: 1, children: /* @__PURE__ */ jsx13(Text12, { color: theme.info.color, children: "Type a message or /help for commands \xB7 ctrl-c to exit \xB7 shift+tab to cycle modes" }) }),
|
|
8338
|
+
/* @__PURE__ */ jsx13(Box11, { children: /* @__PURE__ */ jsx13(Text12, { color: theme.info.color, children: "Tip: type /hello to send feedback to the creator" }) })
|
|
7824
8339
|
] });
|
|
7825
8340
|
}
|
|
7826
8341
|
var SUGGESTIONS;
|
|
@@ -7838,14 +8353,14 @@ var init_welcome = __esm({
|
|
|
7838
8353
|
|
|
7839
8354
|
// src/ui/help-menu.tsx
|
|
7840
8355
|
import { useState as useState6 } from "react";
|
|
7841
|
-
import { Box as
|
|
7842
|
-
import
|
|
7843
|
-
import { jsx as
|
|
7844
|
-
function HelpMenu({ customCommands, costAttributionEnabled, onDone, onCommand }) {
|
|
8356
|
+
import { Box as Box12, Text as Text13, useInput as useInput3 } from "ink";
|
|
8357
|
+
import SelectInput5 from "ink-select-input";
|
|
8358
|
+
import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
8359
|
+
function HelpMenu({ customCommands, costAttributionEnabled, cloudMode, onDone, onCommand }) {
|
|
7845
8360
|
const theme = useTheme();
|
|
7846
8361
|
const [page, setPage] = useState6("main");
|
|
7847
8362
|
const customs = customCommands ?? [];
|
|
7848
|
-
|
|
8363
|
+
useInput3((_input, key) => {
|
|
7849
8364
|
if (key.escape) {
|
|
7850
8365
|
if (page !== "main") {
|
|
7851
8366
|
setPage("main");
|
|
@@ -7858,8 +8373,9 @@ function HelpMenu({ customCommands, costAttributionEnabled, onDone, onCommand })
|
|
|
7858
8373
|
onCommand(command);
|
|
7859
8374
|
onDone();
|
|
7860
8375
|
};
|
|
8376
|
+
const categories = cloudMode ? CATEGORIES.filter((c) => c.key !== "gateway") : CATEGORIES;
|
|
7861
8377
|
if (page === "main") {
|
|
7862
|
-
const items2 =
|
|
8378
|
+
const items2 = categories.map((cat) => ({
|
|
7863
8379
|
label: cat.label,
|
|
7864
8380
|
value: cat.key,
|
|
7865
8381
|
key: cat.key
|
|
@@ -7868,11 +8384,11 @@ function HelpMenu({ customCommands, costAttributionEnabled, onDone, onCommand })
|
|
|
7868
8384
|
items2.push({ label: "Run custom commands", value: "custom", key: "custom" });
|
|
7869
8385
|
}
|
|
7870
8386
|
items2.push({ label: "(close)", value: "__close__", key: "__close__" });
|
|
7871
|
-
return /* @__PURE__ */
|
|
7872
|
-
/* @__PURE__ */
|
|
7873
|
-
/* @__PURE__ */
|
|
7874
|
-
/* @__PURE__ */
|
|
7875
|
-
|
|
8387
|
+
return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
8388
|
+
/* @__PURE__ */ jsx14(Text13, { color: theme.accent, bold: true, children: "Help" }),
|
|
8389
|
+
/* @__PURE__ */ jsx14(Text13, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select, Esc to close." }),
|
|
8390
|
+
/* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(
|
|
8391
|
+
SelectInput5,
|
|
7876
8392
|
{
|
|
7877
8393
|
items: items2,
|
|
7878
8394
|
onSelect: (item) => {
|
|
@@ -7884,8 +8400,8 @@ function HelpMenu({ customCommands, costAttributionEnabled, onDone, onCommand })
|
|
|
7884
8400
|
}
|
|
7885
8401
|
}
|
|
7886
8402
|
) }),
|
|
7887
|
-
/* @__PURE__ */
|
|
7888
|
-
/* @__PURE__ */
|
|
8403
|
+
/* @__PURE__ */ jsx14(Box12, { marginTop: 1, flexDirection: "column", children: SINGLE_COMMANDS.map((cmd) => /* @__PURE__ */ jsx14(Text13, { color: theme.info.color, dimColor: false, children: ` ${cmd.command.padEnd(20)} ${cmd.description}` }, cmd.command)) }),
|
|
8404
|
+
/* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(Text13, { color: theme.info.color, dimColor: false, children: "keys: ctrl-c interrupt/exit \xB7 ctrl-r toggle reasoning \xB7 ctrl-o verbose \xB7 shift+tab cycle mode \xB7 \u2191/\u2193 history" }) })
|
|
7889
8405
|
] });
|
|
7890
8406
|
}
|
|
7891
8407
|
if (page === "custom") {
|
|
@@ -7895,11 +8411,11 @@ function HelpMenu({ customCommands, costAttributionEnabled, onDone, onCommand })
|
|
|
7895
8411
|
key: c.name
|
|
7896
8412
|
}));
|
|
7897
8413
|
items2.push({ label: "\u2190 Back", value: "__back__", key: "__back__" });
|
|
7898
|
-
return /* @__PURE__ */
|
|
7899
|
-
/* @__PURE__ */
|
|
7900
|
-
/* @__PURE__ */
|
|
7901
|
-
/* @__PURE__ */
|
|
7902
|
-
|
|
8414
|
+
return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
8415
|
+
/* @__PURE__ */ jsx14(Text13, { color: theme.accent, bold: true, children: "Custom commands" }),
|
|
8416
|
+
/* @__PURE__ */ jsx14(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." }),
|
|
8417
|
+
/* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(
|
|
8418
|
+
SelectInput5,
|
|
7903
8419
|
{
|
|
7904
8420
|
items: items2,
|
|
7905
8421
|
onSelect: (item) => {
|
|
@@ -7913,7 +8429,7 @@ function HelpMenu({ customCommands, costAttributionEnabled, onDone, onCommand })
|
|
|
7913
8429
|
) })
|
|
7914
8430
|
] });
|
|
7915
8431
|
}
|
|
7916
|
-
const category =
|
|
8432
|
+
const category = categories.find((c) => c.key === page);
|
|
7917
8433
|
const selectable = category.commands.filter((cmd) => cmd.selectable !== false);
|
|
7918
8434
|
const staticCmds = category.commands.filter((cmd) => cmd.selectable === false);
|
|
7919
8435
|
const items = selectable.map((cmd) => ({
|
|
@@ -7922,11 +8438,11 @@ function HelpMenu({ customCommands, costAttributionEnabled, onDone, onCommand })
|
|
|
7922
8438
|
key: cmd.command
|
|
7923
8439
|
}));
|
|
7924
8440
|
items.push({ label: "\u2190 Back", value: "__back__", key: "__back__" });
|
|
7925
|
-
return /* @__PURE__ */
|
|
7926
|
-
/* @__PURE__ */
|
|
7927
|
-
/* @__PURE__ */
|
|
7928
|
-
/* @__PURE__ */
|
|
7929
|
-
|
|
8441
|
+
return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
8442
|
+
/* @__PURE__ */ jsx14(Text13, { color: theme.accent, bold: true, children: category.label }),
|
|
8443
|
+
/* @__PURE__ */ jsx14(Text13, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to execute, Esc to go back." }),
|
|
8444
|
+
/* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(
|
|
8445
|
+
SelectInput5,
|
|
7930
8446
|
{
|
|
7931
8447
|
items,
|
|
7932
8448
|
onSelect: (item) => {
|
|
@@ -7938,7 +8454,7 @@ function HelpMenu({ customCommands, costAttributionEnabled, onDone, onCommand })
|
|
|
7938
8454
|
}
|
|
7939
8455
|
}
|
|
7940
8456
|
) }),
|
|
7941
|
-
staticCmds.length > 0 && /* @__PURE__ */
|
|
8457
|
+
staticCmds.length > 0 && /* @__PURE__ */ jsx14(Box12, { marginTop: 1, flexDirection: "column", children: staticCmds.map((cmd) => /* @__PURE__ */ jsx14(Text13, { color: theme.info.color, children: ` ${cmd.command.padEnd(28)} ${cmd.description}` }, cmd.command)) })
|
|
7942
8458
|
] });
|
|
7943
8459
|
}
|
|
7944
8460
|
var CATEGORIES, SINGLE_COMMANDS;
|
|
@@ -8170,17 +8686,17 @@ var init_tui_deploy = __esm({
|
|
|
8170
8686
|
});
|
|
8171
8687
|
|
|
8172
8688
|
// src/ui/remote-dashboard.tsx
|
|
8173
|
-
import { useEffect as
|
|
8174
|
-
import { Box as
|
|
8175
|
-
import
|
|
8176
|
-
import { jsx as
|
|
8689
|
+
import { useEffect as useEffect5, useState as useState7 } from "react";
|
|
8690
|
+
import { Box as Box13, Text as Text14, useInput as useInput4 } from "ink";
|
|
8691
|
+
import SelectInput6 from "ink-select-input";
|
|
8692
|
+
import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
8177
8693
|
function RemoteDashboard({ onSelect, onCancel }) {
|
|
8178
8694
|
const theme = useTheme();
|
|
8179
8695
|
const [sessions, setSessions] = useState7([]);
|
|
8180
8696
|
const [loading, setLoading] = useState7(true);
|
|
8181
8697
|
const [error, setError] = useState7(null);
|
|
8182
8698
|
const [refreshing, setRefreshing] = useState7(false);
|
|
8183
|
-
|
|
8699
|
+
useEffect5(() => {
|
|
8184
8700
|
loadSessions();
|
|
8185
8701
|
}, []);
|
|
8186
8702
|
async function loadSessions() {
|
|
@@ -8216,7 +8732,7 @@ function RemoteDashboard({ onSelect, onCancel }) {
|
|
|
8216
8732
|
setRefreshing(false);
|
|
8217
8733
|
}
|
|
8218
8734
|
}
|
|
8219
|
-
|
|
8735
|
+
useInput4((input, key) => {
|
|
8220
8736
|
if (input === "r" || input === "R") {
|
|
8221
8737
|
void loadSessions();
|
|
8222
8738
|
}
|
|
@@ -8229,31 +8745,31 @@ function RemoteDashboard({ onSelect, onCancel }) {
|
|
|
8229
8745
|
value: s.sessionId
|
|
8230
8746
|
}));
|
|
8231
8747
|
if (loading) {
|
|
8232
|
-
return /* @__PURE__ */
|
|
8748
|
+
return /* @__PURE__ */ jsx15(Box13, { flexDirection: "column", padding: 1, children: /* @__PURE__ */ jsx15(Text14, { color: theme.accent, children: "Loading remote sessions..." }) });
|
|
8233
8749
|
}
|
|
8234
8750
|
if (error) {
|
|
8235
|
-
return /* @__PURE__ */
|
|
8236
|
-
/* @__PURE__ */
|
|
8751
|
+
return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", padding: 1, children: [
|
|
8752
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.error, children: [
|
|
8237
8753
|
"Error: ",
|
|
8238
8754
|
error
|
|
8239
8755
|
] }),
|
|
8240
|
-
/* @__PURE__ */
|
|
8756
|
+
/* @__PURE__ */ jsx15(Text14, { dimColor: true, children: "Press R to retry, Esc to close" })
|
|
8241
8757
|
] });
|
|
8242
8758
|
}
|
|
8243
8759
|
if (sessions.length === 0) {
|
|
8244
|
-
return /* @__PURE__ */
|
|
8245
|
-
/* @__PURE__ */
|
|
8246
|
-
/* @__PURE__ */
|
|
8247
|
-
/* @__PURE__ */
|
|
8760
|
+
return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", padding: 1, children: [
|
|
8761
|
+
/* @__PURE__ */ jsx15(Text14, { color: theme.accent, children: "No remote sessions yet." }),
|
|
8762
|
+
/* @__PURE__ */ jsx15(Text14, { dimColor: true, children: "Type /remote <prompt> to start one." }),
|
|
8763
|
+
/* @__PURE__ */ jsx15(Text14, { dimColor: true, children: "Press Esc to close" })
|
|
8248
8764
|
] });
|
|
8249
8765
|
}
|
|
8250
|
-
return /* @__PURE__ */
|
|
8251
|
-
/* @__PURE__ */
|
|
8766
|
+
return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", padding: 1, children: [
|
|
8767
|
+
/* @__PURE__ */ jsxs13(Text14, { bold: true, color: theme.accent, children: [
|
|
8252
8768
|
"Recent remote tasks ",
|
|
8253
8769
|
refreshing ? "(refreshing...)" : ""
|
|
8254
8770
|
] }),
|
|
8255
|
-
/* @__PURE__ */
|
|
8256
|
-
|
|
8771
|
+
/* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
|
|
8772
|
+
SelectInput6,
|
|
8257
8773
|
{
|
|
8258
8774
|
items,
|
|
8259
8775
|
onSelect: (item) => {
|
|
@@ -8262,7 +8778,7 @@ function RemoteDashboard({ onSelect, onCancel }) {
|
|
|
8262
8778
|
}
|
|
8263
8779
|
}
|
|
8264
8780
|
) }),
|
|
8265
|
-
/* @__PURE__ */
|
|
8781
|
+
/* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(Text14, { dimColor: true, children: "\u2191\u2193 navigate \u2022 Enter select \u2022 R refresh \u2022 Esc close" }) })
|
|
8266
8782
|
] });
|
|
8267
8783
|
}
|
|
8268
8784
|
function formatSessionLine(s) {
|
|
@@ -8270,7 +8786,7 @@ function formatSessionLine(s) {
|
|
|
8270
8786
|
const ago = formatAgo(new Date(s.updatedAt));
|
|
8271
8787
|
const prompt = s.prompt.slice(0, 30) + (s.prompt.length > 30 ? "\u2026" : "");
|
|
8272
8788
|
const outcome = s.prUrl ? `PR ${s.prUrl.split("/").pop()}` : s.status;
|
|
8273
|
-
const cost = s.tokensUsed && s.tokensBudget ? ` (${
|
|
8789
|
+
const cost = s.tokensUsed && s.tokensBudget ? ` (${formatTokens3(s.tokensUsed)}/${formatTokens3(s.tokensBudget)})` : s.tokensUsed ? ` (${formatTokens3(s.tokensUsed)})` : "";
|
|
8274
8790
|
return `${icon} ${prompt} \u2192 ${outcome} ${ago}${cost}`;
|
|
8275
8791
|
}
|
|
8276
8792
|
function formatAgo(date) {
|
|
@@ -8283,7 +8799,7 @@ function formatAgo(date) {
|
|
|
8283
8799
|
if (minutes > 0) return `${minutes}m ago`;
|
|
8284
8800
|
return "just now";
|
|
8285
8801
|
}
|
|
8286
|
-
function
|
|
8802
|
+
function formatTokens3(n) {
|
|
8287
8803
|
if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
|
|
8288
8804
|
if (n >= 1e3) return `${(n / 1e3).toFixed(1)}K`;
|
|
8289
8805
|
return String(n);
|
|
@@ -8295,7 +8811,7 @@ function RemoteSessionDetail({
|
|
|
8295
8811
|
}) {
|
|
8296
8812
|
const theme = useTheme();
|
|
8297
8813
|
const [cancelling, setCancelling] = useState7(false);
|
|
8298
|
-
|
|
8814
|
+
useInput4((input, key) => {
|
|
8299
8815
|
if (key.escape) {
|
|
8300
8816
|
onBack();
|
|
8301
8817
|
}
|
|
@@ -8315,50 +8831,50 @@ function RemoteSessionDetail({
|
|
|
8315
8831
|
}
|
|
8316
8832
|
}
|
|
8317
8833
|
const isRunning = session.status === "running" || session.status === "pending";
|
|
8318
|
-
return /* @__PURE__ */
|
|
8319
|
-
/* @__PURE__ */
|
|
8320
|
-
/* @__PURE__ */
|
|
8321
|
-
/* @__PURE__ */
|
|
8834
|
+
return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", padding: 1, children: [
|
|
8835
|
+
/* @__PURE__ */ jsx15(Text14, { bold: true, color: theme.accent, children: "Remote Session" }),
|
|
8836
|
+
/* @__PURE__ */ jsxs13(Box13, { marginTop: 1, flexDirection: "column", children: [
|
|
8837
|
+
/* @__PURE__ */ jsxs13(Text14, { children: [
|
|
8322
8838
|
"ID: ",
|
|
8323
8839
|
session.sessionId
|
|
8324
8840
|
] }),
|
|
8325
|
-
/* @__PURE__ */
|
|
8841
|
+
/* @__PURE__ */ jsxs13(Text14, { children: [
|
|
8326
8842
|
"Repo: ",
|
|
8327
8843
|
session.repo
|
|
8328
8844
|
] }),
|
|
8329
|
-
/* @__PURE__ */
|
|
8845
|
+
/* @__PURE__ */ jsxs13(Text14, { children: [
|
|
8330
8846
|
"Status: ",
|
|
8331
8847
|
session.status
|
|
8332
8848
|
] }),
|
|
8333
|
-
/* @__PURE__ */
|
|
8849
|
+
/* @__PURE__ */ jsxs13(Text14, { children: [
|
|
8334
8850
|
"Prompt: ",
|
|
8335
8851
|
session.prompt
|
|
8336
8852
|
] }),
|
|
8337
|
-
session.prUrl && /* @__PURE__ */
|
|
8853
|
+
session.prUrl && /* @__PURE__ */ jsxs13(Text14, { children: [
|
|
8338
8854
|
"PR: ",
|
|
8339
8855
|
session.prUrl
|
|
8340
8856
|
] }),
|
|
8341
|
-
session.errorMessage && /* @__PURE__ */
|
|
8857
|
+
session.errorMessage && /* @__PURE__ */ jsxs13(Text14, { color: theme.error, children: [
|
|
8342
8858
|
"Error: ",
|
|
8343
8859
|
session.errorMessage
|
|
8344
8860
|
] }),
|
|
8345
|
-
session.tokensUsed !== void 0 && /* @__PURE__ */
|
|
8861
|
+
session.tokensUsed !== void 0 && /* @__PURE__ */ jsxs13(Text14, { children: [
|
|
8346
8862
|
"Tokens: ",
|
|
8347
|
-
|
|
8348
|
-
session.tokensBudget ? ` / ${
|
|
8863
|
+
formatTokens3(session.tokensUsed),
|
|
8864
|
+
session.tokensBudget ? ` / ${formatTokens3(session.tokensBudget)}` : ""
|
|
8349
8865
|
] }),
|
|
8350
|
-
/* @__PURE__ */
|
|
8866
|
+
/* @__PURE__ */ jsxs13(Text14, { children: [
|
|
8351
8867
|
"Created: ",
|
|
8352
8868
|
new Date(session.createdAt).toLocaleString()
|
|
8353
8869
|
] }),
|
|
8354
|
-
session.finishedAt && /* @__PURE__ */
|
|
8870
|
+
session.finishedAt && /* @__PURE__ */ jsxs13(Text14, { children: [
|
|
8355
8871
|
"Finished: ",
|
|
8356
8872
|
new Date(session.finishedAt).toLocaleString()
|
|
8357
8873
|
] })
|
|
8358
8874
|
] }),
|
|
8359
|
-
/* @__PURE__ */
|
|
8360
|
-
isRunning && onCancel && /* @__PURE__ */
|
|
8361
|
-
/* @__PURE__ */
|
|
8875
|
+
/* @__PURE__ */ jsxs13(Box13, { marginTop: 1, flexDirection: "row", gap: 2, children: [
|
|
8876
|
+
isRunning && onCancel && /* @__PURE__ */ jsx15(Text14, { color: theme.error, children: cancelling ? "Cancelling..." : "[C] Cancel session" }),
|
|
8877
|
+
/* @__PURE__ */ jsx15(Text14, { dimColor: true, children: "Esc back" })
|
|
8362
8878
|
] })
|
|
8363
8879
|
] });
|
|
8364
8880
|
}
|
|
@@ -8424,12 +8940,12 @@ __export(sessions_exports, {
|
|
|
8424
8940
|
pruneSessions: () => pruneSessions,
|
|
8425
8941
|
saveSession: () => saveSession
|
|
8426
8942
|
});
|
|
8427
|
-
import { readFile as
|
|
8428
|
-
import { homedir as
|
|
8429
|
-
import { join as
|
|
8943
|
+
import { readFile as readFile12, writeFile as writeFile8, mkdir as mkdir7, readdir as readdir3, stat as stat4 } from "fs/promises";
|
|
8944
|
+
import { homedir as homedir10 } from "os";
|
|
8945
|
+
import { join as join15 } from "path";
|
|
8430
8946
|
function sessionsDir2() {
|
|
8431
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
8432
|
-
return
|
|
8947
|
+
const xdg = process.env.XDG_DATA_HOME || join15(homedir10(), ".local", "share");
|
|
8948
|
+
return join15(xdg, "kimiflare", "sessions");
|
|
8433
8949
|
}
|
|
8434
8950
|
function sanitize(text) {
|
|
8435
8951
|
return text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40);
|
|
@@ -8442,8 +8958,8 @@ function makeSessionId(firstPrompt) {
|
|
|
8442
8958
|
async function saveSession(file) {
|
|
8443
8959
|
const dir = sessionsDir2();
|
|
8444
8960
|
await mkdir7(dir, { recursive: true });
|
|
8445
|
-
const path =
|
|
8446
|
-
await
|
|
8961
|
+
const path = join15(dir, `${file.id}.json`);
|
|
8962
|
+
await writeFile8(path, JSON.stringify(file, null, 2), "utf8");
|
|
8447
8963
|
return path;
|
|
8448
8964
|
}
|
|
8449
8965
|
async function pruneSessions() {
|
|
@@ -8462,9 +8978,9 @@ async function listSessions(limit = 30, cwd) {
|
|
|
8462
8978
|
const summaries = [];
|
|
8463
8979
|
for (const name of entries) {
|
|
8464
8980
|
if (!name.endsWith(".json")) continue;
|
|
8465
|
-
const path =
|
|
8981
|
+
const path = join15(dir, name);
|
|
8466
8982
|
try {
|
|
8467
|
-
const [s, raw] = await Promise.all([stat4(path),
|
|
8983
|
+
const [s, raw] = await Promise.all([stat4(path), readFile12(path, "utf8")]);
|
|
8468
8984
|
const parsed = JSON.parse(raw);
|
|
8469
8985
|
if (cwd && parsed.cwd !== cwd) continue;
|
|
8470
8986
|
const firstUser = parsed.messages.find((m) => m.role === "user");
|
|
@@ -8484,7 +9000,7 @@ async function listSessions(limit = 30, cwd) {
|
|
|
8484
9000
|
return summaries.slice(0, limit);
|
|
8485
9001
|
}
|
|
8486
9002
|
async function loadSession(filePath) {
|
|
8487
|
-
const raw = await
|
|
9003
|
+
const raw = await readFile12(filePath, "utf8");
|
|
8488
9004
|
return JSON.parse(raw);
|
|
8489
9005
|
}
|
|
8490
9006
|
var init_sessions = __esm({
|
|
@@ -8495,10 +9011,10 @@ var init_sessions = __esm({
|
|
|
8495
9011
|
});
|
|
8496
9012
|
|
|
8497
9013
|
// src/util/image.ts
|
|
8498
|
-
import { readFile as
|
|
9014
|
+
import { readFile as readFile13 } from "fs/promises";
|
|
8499
9015
|
import { basename as basename3 } from "path";
|
|
8500
9016
|
async function encodeImageFile(filePath) {
|
|
8501
|
-
const buf = await
|
|
9017
|
+
const buf = await readFile13(filePath);
|
|
8502
9018
|
if (buf.byteLength > MAX_IMAGE_BYTES) {
|
|
8503
9019
|
throw new Error(
|
|
8504
9020
|
`image too large (${(buf.byteLength / 1024 / 1024).toFixed(1)} MB); max is ${MAX_IMAGE_BYTES / 1024 / 1024} MB`
|
|
@@ -8534,15 +9050,15 @@ var init_image = __esm({
|
|
|
8534
9050
|
});
|
|
8535
9051
|
|
|
8536
9052
|
// src/usage-tracker.ts
|
|
8537
|
-
import { readFile as
|
|
8538
|
-
import { homedir as
|
|
8539
|
-
import { join as
|
|
9053
|
+
import { readFile as readFile14, writeFile as writeFile9, mkdir as mkdir8 } from "fs/promises";
|
|
9054
|
+
import { homedir as homedir11 } from "os";
|
|
9055
|
+
import { join as join16 } from "path";
|
|
8540
9056
|
function usageDir2() {
|
|
8541
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
8542
|
-
return
|
|
9057
|
+
const xdg = process.env.XDG_DATA_HOME || join16(homedir11(), ".local", "share");
|
|
9058
|
+
return join16(xdg, "kimiflare");
|
|
8543
9059
|
}
|
|
8544
9060
|
function usagePath2() {
|
|
8545
|
-
return
|
|
9061
|
+
return join16(usageDir2(), "usage.json");
|
|
8546
9062
|
}
|
|
8547
9063
|
function today2() {
|
|
8548
9064
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
@@ -8553,7 +9069,7 @@ function cutoffDate(daysBack) {
|
|
|
8553
9069
|
}
|
|
8554
9070
|
async function loadLog2() {
|
|
8555
9071
|
try {
|
|
8556
|
-
const raw = await
|
|
9072
|
+
const raw = await readFile14(usagePath2(), "utf8");
|
|
8557
9073
|
const parsed = JSON.parse(raw);
|
|
8558
9074
|
if (parsed.version === LOG_VERSION2) return parsed;
|
|
8559
9075
|
} catch {
|
|
@@ -8562,7 +9078,7 @@ async function loadLog2() {
|
|
|
8562
9078
|
}
|
|
8563
9079
|
async function saveLog(log) {
|
|
8564
9080
|
await mkdir8(usageDir2(), { recursive: true });
|
|
8565
|
-
await
|
|
9081
|
+
await writeFile9(usagePath2(), JSON.stringify(log, null, 2), "utf8");
|
|
8566
9082
|
}
|
|
8567
9083
|
function getOrCreateDay(log, date) {
|
|
8568
9084
|
let day = log.days.find((d) => d.date === date);
|
|
@@ -8768,7 +9284,7 @@ __export(db_exports, {
|
|
|
8768
9284
|
updateMemoryEmbedding: () => updateMemoryEmbedding
|
|
8769
9285
|
});
|
|
8770
9286
|
import Database from "better-sqlite3";
|
|
8771
|
-
import { dirname as
|
|
9287
|
+
import { dirname as dirname7 } from "path";
|
|
8772
9288
|
import { mkdirSync, statSync as statSync2 } from "fs";
|
|
8773
9289
|
function initSchema(db) {
|
|
8774
9290
|
db.exec(`
|
|
@@ -8853,7 +9369,7 @@ function openMemoryDb(dbPath) {
|
|
|
8853
9369
|
if (dbInstance) {
|
|
8854
9370
|
dbInstance.close();
|
|
8855
9371
|
}
|
|
8856
|
-
mkdirSync(
|
|
9372
|
+
mkdirSync(dirname7(dbPath), { recursive: true });
|
|
8857
9373
|
dbInstance = new Database(dbPath);
|
|
8858
9374
|
dbInstance.pragma("journal_mode = WAL");
|
|
8859
9375
|
dbInstance.pragma("foreign_keys = ON");
|
|
@@ -9263,8 +9779,8 @@ function computeExactScore(memory, queryText, cwd) {
|
|
|
9263
9779
|
let score = 0;
|
|
9264
9780
|
const lowerQuery = queryText.toLowerCase();
|
|
9265
9781
|
for (const file of memory.relatedFiles) {
|
|
9266
|
-
const
|
|
9267
|
-
if (lowerQuery.includes(
|
|
9782
|
+
const basename5 = file.split("/").pop() ?? file;
|
|
9783
|
+
if (lowerQuery.includes(basename5.toLowerCase()) || basename5.toLowerCase().includes(lowerQuery)) {
|
|
9268
9784
|
score += 0.3;
|
|
9269
9785
|
}
|
|
9270
9786
|
if (cwd && file.startsWith(cwd)) {
|
|
@@ -9792,16 +10308,16 @@ Context: This memory was explicitly provided by the user during a conversation.`
|
|
|
9792
10308
|
});
|
|
9793
10309
|
|
|
9794
10310
|
// src/util/state.ts
|
|
9795
|
-
import { readFile as
|
|
9796
|
-
import { homedir as
|
|
9797
|
-
import { join as
|
|
10311
|
+
import { readFile as readFile15, writeFile as writeFile10, mkdir as mkdir9 } from "fs/promises";
|
|
10312
|
+
import { homedir as homedir12 } from "os";
|
|
10313
|
+
import { join as join18 } from "path";
|
|
9798
10314
|
function statePath() {
|
|
9799
|
-
const xdg = process.env.XDG_CONFIG_HOME ||
|
|
9800
|
-
return
|
|
10315
|
+
const xdg = process.env.XDG_CONFIG_HOME || join18(homedir12(), ".config");
|
|
10316
|
+
return join18(xdg, "kimiflare", "state.json");
|
|
9801
10317
|
}
|
|
9802
10318
|
async function readState() {
|
|
9803
10319
|
try {
|
|
9804
|
-
const raw = await
|
|
10320
|
+
const raw = await readFile15(statePath(), "utf8");
|
|
9805
10321
|
return JSON.parse(raw);
|
|
9806
10322
|
} catch {
|
|
9807
10323
|
return {};
|
|
@@ -9809,8 +10325,8 @@ async function readState() {
|
|
|
9809
10325
|
}
|
|
9810
10326
|
async function writeState(state) {
|
|
9811
10327
|
const path = statePath();
|
|
9812
|
-
await mkdir9(
|
|
9813
|
-
await
|
|
10328
|
+
await mkdir9(join18(path, ".."), { recursive: true });
|
|
10329
|
+
await writeFile10(path, JSON.stringify(state, null, 2) + "\n", "utf8");
|
|
9814
10330
|
}
|
|
9815
10331
|
async function markCreatorMessageSeen(version) {
|
|
9816
10332
|
const state = await readState();
|
|
@@ -9883,15 +10399,15 @@ var init_frontmatter = __esm({
|
|
|
9883
10399
|
|
|
9884
10400
|
// src/commands/loader.ts
|
|
9885
10401
|
import { open, realpath } from "fs/promises";
|
|
9886
|
-
import { homedir as
|
|
9887
|
-
import { join as
|
|
10402
|
+
import { homedir as homedir13 } from "os";
|
|
10403
|
+
import { join as join19, relative as relative4, sep as sep2 } from "path";
|
|
9888
10404
|
import fg3 from "fast-glob";
|
|
9889
10405
|
function projectCommandsDir(cwd = process.cwd()) {
|
|
9890
|
-
return
|
|
10406
|
+
return join19(cwd, ".kimiflare", "commands");
|
|
9891
10407
|
}
|
|
9892
10408
|
function globalCommandsDir() {
|
|
9893
|
-
const xdg = process.env.XDG_CONFIG_HOME ||
|
|
9894
|
-
return
|
|
10409
|
+
const xdg = process.env.XDG_CONFIG_HOME || join19(homedir13(), ".config");
|
|
10410
|
+
return join19(xdg, "kimiflare", "commands");
|
|
9895
10411
|
}
|
|
9896
10412
|
async function loadCustomCommands(cwd = process.cwd()) {
|
|
9897
10413
|
const warnings = [];
|
|
@@ -10042,10 +10558,10 @@ var init_loader = __esm({
|
|
|
10042
10558
|
});
|
|
10043
10559
|
|
|
10044
10560
|
// src/commands/renderer.ts
|
|
10045
|
-
import { exec } from "child_process";
|
|
10561
|
+
import { exec as exec2 } from "child_process";
|
|
10046
10562
|
import { open as open2, realpath as realpath2 } from "fs/promises";
|
|
10047
10563
|
import { isAbsolute as isAbsolute2, relative as relative5, resolve as resolvePathJoin, basename as pathBasename } from "path";
|
|
10048
|
-
import { promisify as
|
|
10564
|
+
import { promisify as promisify3 } from "util";
|
|
10049
10565
|
function tokenizeArgs(s) {
|
|
10050
10566
|
return [...s.matchAll(ARG_TOKEN_RE)].map((match) => {
|
|
10051
10567
|
const token = match[0];
|
|
@@ -10112,7 +10628,7 @@ async function replaceShell(prompt, warnings, cmd, shellTimeoutMs) {
|
|
|
10112
10628
|
matches.map(async (match) => {
|
|
10113
10629
|
const command = match[1] ?? "";
|
|
10114
10630
|
try {
|
|
10115
|
-
const { stdout } = await
|
|
10631
|
+
const { stdout } = await execAsync2(command, {
|
|
10116
10632
|
timeout: shellTimeoutMs,
|
|
10117
10633
|
maxBuffer: 1024 * 1024
|
|
10118
10634
|
});
|
|
@@ -10193,12 +10709,12 @@ async function replaceFiles(prompt, warnings, cmd, cwd, maxFileBytes) {
|
|
|
10193
10709
|
function message(error) {
|
|
10194
10710
|
return error instanceof Error ? error.message : String(error);
|
|
10195
10711
|
}
|
|
10196
|
-
var
|
|
10712
|
+
var execAsync2, ARG_TOKEN_RE, POSITIONAL_RE, HAS_POSITIONAL, SHELL_RE, FILE_RE, DEFAULT_MAX_FILE_BYTES, DEFAULT_SHELL_TIMEOUT_MS, SECRET_PATTERNS2;
|
|
10197
10713
|
var init_renderer2 = __esm({
|
|
10198
10714
|
"src/commands/renderer.ts"() {
|
|
10199
10715
|
"use strict";
|
|
10200
10716
|
init_paths();
|
|
10201
|
-
|
|
10717
|
+
execAsync2 = promisify3(exec2);
|
|
10202
10718
|
ARG_TOKEN_RE = /(?:"[^"]*"|'[^']*'|[^\s"']+)/g;
|
|
10203
10719
|
POSITIONAL_RE = /\$(\d+)/g;
|
|
10204
10720
|
HAS_POSITIONAL = /\$\d+/;
|
|
@@ -10267,8 +10783,8 @@ var init_builtins = __esm({
|
|
|
10267
10783
|
});
|
|
10268
10784
|
|
|
10269
10785
|
// src/commands/save.ts
|
|
10270
|
-
import { mkdir as mkdir10, writeFile as
|
|
10271
|
-
import { dirname as
|
|
10786
|
+
import { mkdir as mkdir10, writeFile as writeFile11, unlink as unlink2 } from "fs/promises";
|
|
10787
|
+
import { dirname as dirname8 } from "path";
|
|
10272
10788
|
async function saveCustomCommand(opts2) {
|
|
10273
10789
|
const dir = opts2.source === "project" ? projectCommandsDir(opts2.cwd) : globalCommandsDir();
|
|
10274
10790
|
const filepath = `${dir}/${opts2.name}.md`;
|
|
@@ -10279,8 +10795,8 @@ async function saveCustomCommand(opts2) {
|
|
|
10279
10795
|
if (opts2.effort) data.effort = opts2.effort;
|
|
10280
10796
|
const frontmatter = serializeFrontmatter(data);
|
|
10281
10797
|
const content = frontmatter + opts2.template;
|
|
10282
|
-
await mkdir10(
|
|
10283
|
-
await
|
|
10798
|
+
await mkdir10(dirname8(filepath), { recursive: true });
|
|
10799
|
+
await writeFile11(filepath, content, "utf8");
|
|
10284
10800
|
return { filepath };
|
|
10285
10801
|
}
|
|
10286
10802
|
async function deleteCustomCommand(cmd) {
|
|
@@ -10296,9 +10812,9 @@ var init_save = __esm({
|
|
|
10296
10812
|
|
|
10297
10813
|
// src/ui/command-wizard.tsx
|
|
10298
10814
|
import { useState as useState8 } from "react";
|
|
10299
|
-
import { Box as
|
|
10300
|
-
import
|
|
10301
|
-
import { Fragment as Fragment2, jsx as
|
|
10815
|
+
import { Box as Box14, Text as Text15, useInput as useInput5, useWindowSize as useWindowSize2 } from "ink";
|
|
10816
|
+
import SelectInput7 from "ink-select-input";
|
|
10817
|
+
import { Fragment as Fragment2, jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
10302
10818
|
function CommandWizard({ mode, initial, existingNames, builtinNames, onDone, onSave }) {
|
|
10303
10819
|
const theme = useTheme();
|
|
10304
10820
|
const [step, setStep] = useState8("name");
|
|
@@ -10322,7 +10838,7 @@ function CommandWizard({ mode, initial, existingNames, builtinNames, onDone, onS
|
|
|
10322
10838
|
if (existingNames.includes(trimmed) && !isEditingSelf(trimmed)) return `/${trimmed} already exists`;
|
|
10323
10839
|
return null;
|
|
10324
10840
|
};
|
|
10325
|
-
|
|
10841
|
+
useInput5((_input, key) => {
|
|
10326
10842
|
if (key.escape) {
|
|
10327
10843
|
onDone();
|
|
10328
10844
|
}
|
|
@@ -10422,8 +10938,8 @@ ${template}`;
|
|
|
10422
10938
|
const renderStep = () => {
|
|
10423
10939
|
switch (step) {
|
|
10424
10940
|
case "name":
|
|
10425
|
-
return /* @__PURE__ */
|
|
10426
|
-
/* @__PURE__ */
|
|
10941
|
+
return /* @__PURE__ */ jsxs14(Fragment2, { children: [
|
|
10942
|
+
/* @__PURE__ */ jsxs14(Text15, { color: theme.accent, bold: true, children: [
|
|
10427
10943
|
mode === "create" ? "Create" : "Edit",
|
|
10428
10944
|
" custom command \u2014 Name (",
|
|
10429
10945
|
stepIndex,
|
|
@@ -10431,8 +10947,8 @@ ${template}`;
|
|
|
10431
10947
|
totalSteps,
|
|
10432
10948
|
")"
|
|
10433
10949
|
] }),
|
|
10434
|
-
error && /* @__PURE__ */
|
|
10435
|
-
/* @__PURE__ */
|
|
10950
|
+
error && /* @__PURE__ */ jsx16(Text15, { color: theme.error, children: error }),
|
|
10951
|
+
/* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(
|
|
10436
10952
|
CustomTextInput,
|
|
10437
10953
|
{
|
|
10438
10954
|
value: name,
|
|
@@ -10441,11 +10957,11 @@ ${template}`;
|
|
|
10441
10957
|
focus: true
|
|
10442
10958
|
}
|
|
10443
10959
|
) }),
|
|
10444
|
-
/* @__PURE__ */
|
|
10960
|
+
/* @__PURE__ */ jsx16(Text15, { color: theme.info.color, children: "letters, numbers, _ - / only; must start with a letter" })
|
|
10445
10961
|
] });
|
|
10446
10962
|
case "description":
|
|
10447
|
-
return /* @__PURE__ */
|
|
10448
|
-
/* @__PURE__ */
|
|
10963
|
+
return /* @__PURE__ */ jsxs14(Fragment2, { children: [
|
|
10964
|
+
/* @__PURE__ */ jsxs14(Text15, { color: theme.accent, bold: true, children: [
|
|
10449
10965
|
mode === "create" ? "Create" : "Edit",
|
|
10450
10966
|
" custom command \u2014 Description (",
|
|
10451
10967
|
stepIndex,
|
|
@@ -10453,7 +10969,7 @@ ${template}`;
|
|
|
10453
10969
|
totalSteps,
|
|
10454
10970
|
")"
|
|
10455
10971
|
] }),
|
|
10456
|
-
/* @__PURE__ */
|
|
10972
|
+
/* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(
|
|
10457
10973
|
CustomTextInput,
|
|
10458
10974
|
{
|
|
10459
10975
|
value: description,
|
|
@@ -10462,49 +10978,49 @@ ${template}`;
|
|
|
10462
10978
|
focus: true
|
|
10463
10979
|
}
|
|
10464
10980
|
) }),
|
|
10465
|
-
/* @__PURE__ */
|
|
10981
|
+
/* @__PURE__ */ jsx16(Text15, { color: theme.info.color, children: "Press Enter to skip" })
|
|
10466
10982
|
] });
|
|
10467
10983
|
case "template": {
|
|
10468
|
-
const guide = /* @__PURE__ */
|
|
10469
|
-
/* @__PURE__ */
|
|
10470
|
-
/* @__PURE__ */
|
|
10471
|
-
/* @__PURE__ */
|
|
10984
|
+
const guide = /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", paddingLeft: 1, children: [
|
|
10985
|
+
/* @__PURE__ */ jsx16(Text15, { color: theme.accent, bold: true, children: "What is this?" }),
|
|
10986
|
+
/* @__PURE__ */ jsx16(Text15, { color: theme.info.color, children: "A prompt template \u2014 instructions to the AI." }),
|
|
10987
|
+
/* @__PURE__ */ jsxs14(Text15, { color: theme.info.color, children: [
|
|
10472
10988
|
"When you type /",
|
|
10473
10989
|
name || "yourcommand",
|
|
10474
10990
|
" later, this gets sent to the model."
|
|
10475
10991
|
] }),
|
|
10476
|
-
/* @__PURE__ */
|
|
10477
|
-
/* @__PURE__ */
|
|
10478
|
-
/* @__PURE__ */
|
|
10992
|
+
/* @__PURE__ */ jsxs14(Box14, { marginTop: 1, flexDirection: "column", children: [
|
|
10993
|
+
/* @__PURE__ */ jsx16(Text15, { color: theme.accent, bold: true, children: "Variables" }),
|
|
10994
|
+
/* @__PURE__ */ jsxs14(Text15, { color: theme.info.color, children: [
|
|
10479
10995
|
" ",
|
|
10480
10996
|
"$1, $2 ... \u2192 arguments you type"
|
|
10481
10997
|
] }),
|
|
10482
|
-
/* @__PURE__ */
|
|
10998
|
+
/* @__PURE__ */ jsxs14(Text15, { color: theme.info.color, children: [
|
|
10483
10999
|
" ",
|
|
10484
11000
|
"$ARGUMENTS \u2192 everything after the command"
|
|
10485
11001
|
] })
|
|
10486
11002
|
] }),
|
|
10487
|
-
/* @__PURE__ */
|
|
10488
|
-
/* @__PURE__ */
|
|
10489
|
-
/* @__PURE__ */
|
|
11003
|
+
/* @__PURE__ */ jsxs14(Box14, { marginTop: 1, flexDirection: "column", children: [
|
|
11004
|
+
/* @__PURE__ */ jsx16(Text15, { color: theme.accent, bold: true, children: "Dynamic inlines" }),
|
|
11005
|
+
/* @__PURE__ */ jsxs14(Text15, { color: theme.info.color, children: [
|
|
10490
11006
|
" ",
|
|
10491
11007
|
"!`git diff` \u2192 shell output inlined"
|
|
10492
11008
|
] }),
|
|
10493
|
-
/* @__PURE__ */
|
|
11009
|
+
/* @__PURE__ */ jsxs14(Text15, { color: theme.info.color, children: [
|
|
10494
11010
|
" ",
|
|
10495
11011
|
"@README.md \u2192 file contents inlined"
|
|
10496
11012
|
] })
|
|
10497
11013
|
] }),
|
|
10498
|
-
/* @__PURE__ */
|
|
10499
|
-
/* @__PURE__ */
|
|
10500
|
-
/* @__PURE__ */
|
|
10501
|
-
/* @__PURE__ */
|
|
10502
|
-
/* @__PURE__ */
|
|
11014
|
+
/* @__PURE__ */ jsxs14(Box14, { marginTop: 1, flexDirection: "column", children: [
|
|
11015
|
+
/* @__PURE__ */ jsx16(Text15, { color: theme.accent, bold: true, children: "Example" }),
|
|
11016
|
+
/* @__PURE__ */ jsx16(Text15, { color: theme.info.color, children: "Review this PR diff:" }),
|
|
11017
|
+
/* @__PURE__ */ jsx16(Text15, { color: theme.info.color, children: "!`git diff main...HEAD`" }),
|
|
11018
|
+
/* @__PURE__ */ jsx16(Text15, { color: theme.info.color, children: "Focus on: $1" })
|
|
10503
11019
|
] })
|
|
10504
11020
|
] });
|
|
10505
|
-
const inputArea = /* @__PURE__ */
|
|
10506
|
-
error && /* @__PURE__ */
|
|
10507
|
-
/* @__PURE__ */
|
|
11021
|
+
const inputArea = /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", flexGrow: 1, children: [
|
|
11022
|
+
error && /* @__PURE__ */ jsx16(Text15, { color: theme.error, children: error }),
|
|
11023
|
+
/* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(
|
|
10508
11024
|
CustomTextInput,
|
|
10509
11025
|
{
|
|
10510
11026
|
value: template,
|
|
@@ -10514,13 +11030,13 @@ ${template}`;
|
|
|
10514
11030
|
enablePaste: true
|
|
10515
11031
|
}
|
|
10516
11032
|
) }),
|
|
10517
|
-
columns < 100 && /* @__PURE__ */
|
|
10518
|
-
/* @__PURE__ */
|
|
10519
|
-
/* @__PURE__ */
|
|
11033
|
+
columns < 100 && /* @__PURE__ */ jsxs14(Fragment2, { children: [
|
|
11034
|
+
/* @__PURE__ */ jsx16(Text15, { color: theme.info.color, children: "Paste multi-line templates with Ctrl+V." }),
|
|
11035
|
+
/* @__PURE__ */ jsx16(Text15, { color: theme.info.color, children: "Variables: $1 $2 ... $ARGUMENTS Shell: !`cmd` File: @path" })
|
|
10520
11036
|
] })
|
|
10521
11037
|
] });
|
|
10522
|
-
return /* @__PURE__ */
|
|
10523
|
-
/* @__PURE__ */
|
|
11038
|
+
return /* @__PURE__ */ jsxs14(Fragment2, { children: [
|
|
11039
|
+
/* @__PURE__ */ jsxs14(Text15, { color: theme.accent, bold: true, children: [
|
|
10524
11040
|
mode === "create" ? "Create" : "Edit",
|
|
10525
11041
|
" custom command \u2014 Template (",
|
|
10526
11042
|
stepIndex,
|
|
@@ -10528,10 +11044,10 @@ ${template}`;
|
|
|
10528
11044
|
totalSteps,
|
|
10529
11045
|
")"
|
|
10530
11046
|
] }),
|
|
10531
|
-
columns >= 100 ? /* @__PURE__ */
|
|
10532
|
-
/* @__PURE__ */
|
|
10533
|
-
/* @__PURE__ */
|
|
10534
|
-
] }) : /* @__PURE__ */
|
|
11047
|
+
columns >= 100 ? /* @__PURE__ */ jsxs14(Box14, { flexDirection: "row", marginTop: 1, children: [
|
|
11048
|
+
/* @__PURE__ */ jsx16(Box14, { flexDirection: "column", width: "50%", children: inputArea }),
|
|
11049
|
+
/* @__PURE__ */ jsx16(Box14, { flexDirection: "column", width: "50%", children: guide })
|
|
11050
|
+
] }) : /* @__PURE__ */ jsx16(Box14, { flexDirection: "column", marginTop: 1, children: inputArea })
|
|
10535
11051
|
] });
|
|
10536
11052
|
}
|
|
10537
11053
|
case "advanced": {
|
|
@@ -10540,8 +11056,8 @@ ${template}`;
|
|
|
10540
11056
|
{ label: "Skip", value: "skip", key: "skip" },
|
|
10541
11057
|
{ label: "\u2190 Cancel", value: "cancel", key: "cancel" }
|
|
10542
11058
|
];
|
|
10543
|
-
return /* @__PURE__ */
|
|
10544
|
-
/* @__PURE__ */
|
|
11059
|
+
return /* @__PURE__ */ jsxs14(Fragment2, { children: [
|
|
11060
|
+
/* @__PURE__ */ jsxs14(Text15, { color: theme.accent, bold: true, children: [
|
|
10545
11061
|
mode === "create" ? "Create" : "Edit",
|
|
10546
11062
|
" custom command \u2014 Options (",
|
|
10547
11063
|
stepIndex,
|
|
@@ -10549,8 +11065,8 @@ ${template}`;
|
|
|
10549
11065
|
totalSteps,
|
|
10550
11066
|
")"
|
|
10551
11067
|
] }),
|
|
10552
|
-
/* @__PURE__ */
|
|
10553
|
-
|
|
11068
|
+
/* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(
|
|
11069
|
+
SelectInput7,
|
|
10554
11070
|
{
|
|
10555
11071
|
items,
|
|
10556
11072
|
onSelect: (item) => {
|
|
@@ -10569,17 +11085,17 @@ ${template}`;
|
|
|
10569
11085
|
{ label: cmdMode === "auto" ? "auto \xB7 current" : "auto", value: "auto", key: "auto" },
|
|
10570
11086
|
{ label: "\u2190 Back", value: "__back__", key: "__back__" }
|
|
10571
11087
|
];
|
|
10572
|
-
return /* @__PURE__ */
|
|
10573
|
-
/* @__PURE__ */
|
|
11088
|
+
return /* @__PURE__ */ jsxs14(Fragment2, { children: [
|
|
11089
|
+
/* @__PURE__ */ jsxs14(Text15, { color: theme.accent, bold: true, children: [
|
|
10574
11090
|
"Mode override (",
|
|
10575
11091
|
stepIndex,
|
|
10576
11092
|
"/",
|
|
10577
11093
|
totalSteps,
|
|
10578
11094
|
")"
|
|
10579
11095
|
] }),
|
|
10580
|
-
/* @__PURE__ */
|
|
10581
|
-
/* @__PURE__ */
|
|
10582
|
-
|
|
11096
|
+
/* @__PURE__ */ jsx16(Text15, { color: theme.info.color, children: "Saved to file but not yet enforced at runtime" }),
|
|
11097
|
+
/* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(
|
|
11098
|
+
SelectInput7,
|
|
10583
11099
|
{
|
|
10584
11100
|
items,
|
|
10585
11101
|
onSelect: (item) => {
|
|
@@ -10598,16 +11114,16 @@ ${template}`;
|
|
|
10598
11114
|
{ label: cmdEffort === "high" ? "high \xB7 current" : "high", value: "high", key: "high" },
|
|
10599
11115
|
{ label: "\u2190 Back", value: "__back__", key: "__back__" }
|
|
10600
11116
|
];
|
|
10601
|
-
return /* @__PURE__ */
|
|
10602
|
-
/* @__PURE__ */
|
|
11117
|
+
return /* @__PURE__ */ jsxs14(Fragment2, { children: [
|
|
11118
|
+
/* @__PURE__ */ jsxs14(Text15, { color: theme.accent, bold: true, children: [
|
|
10603
11119
|
"Reasoning effort (",
|
|
10604
11120
|
stepIndex,
|
|
10605
11121
|
"/",
|
|
10606
11122
|
totalSteps,
|
|
10607
11123
|
")"
|
|
10608
11124
|
] }),
|
|
10609
|
-
/* @__PURE__ */
|
|
10610
|
-
|
|
11125
|
+
/* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(
|
|
11126
|
+
SelectInput7,
|
|
10611
11127
|
{
|
|
10612
11128
|
items,
|
|
10613
11129
|
onSelect: (item) => {
|
|
@@ -10619,15 +11135,15 @@ ${template}`;
|
|
|
10619
11135
|
] });
|
|
10620
11136
|
}
|
|
10621
11137
|
case "model":
|
|
10622
|
-
return /* @__PURE__ */
|
|
10623
|
-
/* @__PURE__ */
|
|
11138
|
+
return /* @__PURE__ */ jsxs14(Fragment2, { children: [
|
|
11139
|
+
/* @__PURE__ */ jsxs14(Text15, { color: theme.accent, bold: true, children: [
|
|
10624
11140
|
"Model override (",
|
|
10625
11141
|
stepIndex,
|
|
10626
11142
|
"/",
|
|
10627
11143
|
totalSteps,
|
|
10628
11144
|
")"
|
|
10629
11145
|
] }),
|
|
10630
|
-
/* @__PURE__ */
|
|
11146
|
+
/* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(
|
|
10631
11147
|
CustomTextInput,
|
|
10632
11148
|
{
|
|
10633
11149
|
value: cmdModel ?? "",
|
|
@@ -10636,7 +11152,7 @@ ${template}`;
|
|
|
10636
11152
|
focus: true
|
|
10637
11153
|
}
|
|
10638
11154
|
) }),
|
|
10639
|
-
/* @__PURE__ */
|
|
11155
|
+
/* @__PURE__ */ jsx16(Text15, { color: theme.info.color, children: "Press Enter to skip" })
|
|
10640
11156
|
] });
|
|
10641
11157
|
case "location": {
|
|
10642
11158
|
const items = [
|
|
@@ -10644,16 +11160,16 @@ ${template}`;
|
|
|
10644
11160
|
{ label: source === "global" ? "Global \xB7 current" : "Global", value: "global", key: "global" },
|
|
10645
11161
|
{ label: "\u2190 Back", value: "__back__", key: "__back__" }
|
|
10646
11162
|
];
|
|
10647
|
-
return /* @__PURE__ */
|
|
10648
|
-
/* @__PURE__ */
|
|
11163
|
+
return /* @__PURE__ */ jsxs14(Fragment2, { children: [
|
|
11164
|
+
/* @__PURE__ */ jsxs14(Text15, { color: theme.accent, bold: true, children: [
|
|
10649
11165
|
"Save location (",
|
|
10650
11166
|
stepIndex,
|
|
10651
11167
|
"/",
|
|
10652
11168
|
totalSteps,
|
|
10653
11169
|
")"
|
|
10654
11170
|
] }),
|
|
10655
|
-
/* @__PURE__ */
|
|
10656
|
-
|
|
11171
|
+
/* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(
|
|
11172
|
+
SelectInput7,
|
|
10657
11173
|
{
|
|
10658
11174
|
items,
|
|
10659
11175
|
onSelect: (item) => {
|
|
@@ -10662,7 +11178,7 @@ ${template}`;
|
|
|
10662
11178
|
}
|
|
10663
11179
|
}
|
|
10664
11180
|
) }),
|
|
10665
|
-
/* @__PURE__ */
|
|
11181
|
+
/* @__PURE__ */ jsx16(Text15, { color: theme.info.color, children: "Project: .kimiflare/commands/ Global: ~/.config/kimiflare/commands/" })
|
|
10666
11182
|
] });
|
|
10667
11183
|
}
|
|
10668
11184
|
case "confirm": {
|
|
@@ -10670,8 +11186,8 @@ ${template}`;
|
|
|
10670
11186
|
{ label: "Save", value: "save", key: "save" },
|
|
10671
11187
|
{ label: "Cancel", value: "cancel", key: "cancel" }
|
|
10672
11188
|
];
|
|
10673
|
-
return /* @__PURE__ */
|
|
10674
|
-
/* @__PURE__ */
|
|
11189
|
+
return /* @__PURE__ */ jsxs14(Fragment2, { children: [
|
|
11190
|
+
/* @__PURE__ */ jsxs14(Text15, { color: theme.accent, bold: true, children: [
|
|
10675
11191
|
mode === "create" ? "Create" : "Edit",
|
|
10676
11192
|
" custom command \u2014 Confirm (",
|
|
10677
11193
|
stepIndex,
|
|
@@ -10679,14 +11195,14 @@ ${template}`;
|
|
|
10679
11195
|
totalSteps,
|
|
10680
11196
|
")"
|
|
10681
11197
|
] }),
|
|
10682
|
-
/* @__PURE__ */
|
|
11198
|
+
/* @__PURE__ */ jsxs14(Text15, { color: theme.info.color, children: [
|
|
10683
11199
|
source === "project" ? ".kimiflare/commands/" : "~/.config/kimiflare/commands/",
|
|
10684
11200
|
name,
|
|
10685
11201
|
".md"
|
|
10686
11202
|
] }),
|
|
10687
|
-
/* @__PURE__ */
|
|
10688
|
-
/* @__PURE__ */
|
|
10689
|
-
|
|
11203
|
+
/* @__PURE__ */ jsx16(Box14, { marginTop: 1, flexDirection: "column", children: previewContent().split("\n").map((line, i) => /* @__PURE__ */ jsx16(Text15, { color: theme.info.color, children: line || " " }, i)) }),
|
|
11204
|
+
/* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(
|
|
11205
|
+
SelectInput7,
|
|
10690
11206
|
{
|
|
10691
11207
|
items,
|
|
10692
11208
|
onSelect: (item) => handleConfirm(item.value)
|
|
@@ -10696,7 +11212,7 @@ ${template}`;
|
|
|
10696
11212
|
}
|
|
10697
11213
|
}
|
|
10698
11214
|
};
|
|
10699
|
-
return /* @__PURE__ */
|
|
11215
|
+
return /* @__PURE__ */ jsx16(Box14, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: renderStep() });
|
|
10700
11216
|
}
|
|
10701
11217
|
var NAME_RE;
|
|
10702
11218
|
var init_command_wizard = __esm({
|
|
@@ -10708,10 +11224,442 @@ var init_command_wizard = __esm({
|
|
|
10708
11224
|
}
|
|
10709
11225
|
});
|
|
10710
11226
|
|
|
11227
|
+
// src/init/context-generator.ts
|
|
11228
|
+
import { existsSync as existsSync2, statSync as statSync3 } from "fs";
|
|
11229
|
+
import { join as join20 } from "path";
|
|
11230
|
+
function detectFlavor(cwd) {
|
|
11231
|
+
for (const [flavor, signatures] of Object.entries(FLAVOR_SIGNATURES)) {
|
|
11232
|
+
if (flavor === "generic") continue;
|
|
11233
|
+
for (const sig of signatures) {
|
|
11234
|
+
const path = join20(cwd, sig);
|
|
11235
|
+
if (sig.includes("*")) {
|
|
11236
|
+
try {
|
|
11237
|
+
const parts = sig.split("*");
|
|
11238
|
+
const prefix = parts[0] ?? "";
|
|
11239
|
+
const suffix = parts[1] ?? "";
|
|
11240
|
+
const entries = __require("fs").readdirSync(cwd);
|
|
11241
|
+
if (entries.some((e) => e.startsWith(prefix) && e.endsWith(suffix))) {
|
|
11242
|
+
return flavor;
|
|
11243
|
+
}
|
|
11244
|
+
} catch {
|
|
11245
|
+
}
|
|
11246
|
+
} else if (existsSync2(path)) {
|
|
11247
|
+
return flavor;
|
|
11248
|
+
}
|
|
11249
|
+
}
|
|
11250
|
+
}
|
|
11251
|
+
return "generic";
|
|
11252
|
+
}
|
|
11253
|
+
function findFile(cwd, candidates) {
|
|
11254
|
+
for (const c of candidates) {
|
|
11255
|
+
if (existsSync2(join20(cwd, c))) return c;
|
|
11256
|
+
}
|
|
11257
|
+
return null;
|
|
11258
|
+
}
|
|
11259
|
+
function findSourceRoots(cwd) {
|
|
11260
|
+
const roots = [];
|
|
11261
|
+
for (const r of SOURCE_ROOT_CANDIDATES) {
|
|
11262
|
+
const p = join20(cwd, r);
|
|
11263
|
+
try {
|
|
11264
|
+
const s = statSync3(p);
|
|
11265
|
+
if (s.isDirectory()) roots.push(r);
|
|
11266
|
+
} catch {
|
|
11267
|
+
}
|
|
11268
|
+
}
|
|
11269
|
+
return roots;
|
|
11270
|
+
}
|
|
11271
|
+
function findCiConfig(cwd) {
|
|
11272
|
+
for (const c of CI_PATHS) {
|
|
11273
|
+
if (existsSync2(join20(cwd, c))) {
|
|
11274
|
+
try {
|
|
11275
|
+
const s = statSync3(join20(cwd, c));
|
|
11276
|
+
return s.isDirectory() ? c : c;
|
|
11277
|
+
} catch {
|
|
11278
|
+
}
|
|
11279
|
+
}
|
|
11280
|
+
}
|
|
11281
|
+
return null;
|
|
11282
|
+
}
|
|
11283
|
+
function languageForFlavor(f) {
|
|
11284
|
+
const map = {
|
|
11285
|
+
node: "JavaScript / TypeScript",
|
|
11286
|
+
python: "Python",
|
|
11287
|
+
go: "Go",
|
|
11288
|
+
rust: "Rust",
|
|
11289
|
+
ruby: "Ruby",
|
|
11290
|
+
java: "Java / Kotlin",
|
|
11291
|
+
dotnet: "C# / F#",
|
|
11292
|
+
php: "PHP",
|
|
11293
|
+
elixir: "Elixir",
|
|
11294
|
+
haskell: "Haskell",
|
|
11295
|
+
c: "C",
|
|
11296
|
+
cpp: "C++",
|
|
11297
|
+
zig: "Zig",
|
|
11298
|
+
generic: "Unknown"
|
|
11299
|
+
};
|
|
11300
|
+
return map[f];
|
|
11301
|
+
}
|
|
11302
|
+
function analyzeProject(cwd) {
|
|
11303
|
+
const flavor = detectFlavor(cwd);
|
|
11304
|
+
const packageFiles = {
|
|
11305
|
+
node: ["package.json"],
|
|
11306
|
+
python: ["pyproject.toml", "setup.py", "setup.cfg"],
|
|
11307
|
+
go: ["go.mod"],
|
|
11308
|
+
rust: ["Cargo.toml"],
|
|
11309
|
+
ruby: ["Gemfile"],
|
|
11310
|
+
java: ["pom.xml", "build.gradle", "build.gradle.kts"],
|
|
11311
|
+
dotnet: ["*.csproj"],
|
|
11312
|
+
php: ["composer.json"],
|
|
11313
|
+
elixir: ["mix.exs"],
|
|
11314
|
+
haskell: ["package.yaml", "*.cabal"],
|
|
11315
|
+
c: ["Makefile", "CMakeLists.txt"],
|
|
11316
|
+
cpp: ["Makefile", "CMakeLists.txt"],
|
|
11317
|
+
zig: ["build.zig"],
|
|
11318
|
+
generic: []
|
|
11319
|
+
};
|
|
11320
|
+
const lockFiles = {
|
|
11321
|
+
node: ["package-lock.json", "yarn.lock", "pnpm-lock.yaml", "bun.lockb"],
|
|
11322
|
+
python: ["poetry.lock", "uv.lock", "Pipfile.lock"],
|
|
11323
|
+
go: ["go.sum"],
|
|
11324
|
+
rust: ["Cargo.lock"],
|
|
11325
|
+
ruby: ["Gemfile.lock"],
|
|
11326
|
+
java: [],
|
|
11327
|
+
dotnet: [],
|
|
11328
|
+
php: ["composer.lock"],
|
|
11329
|
+
elixir: ["mix.lock"],
|
|
11330
|
+
haskell: [],
|
|
11331
|
+
c: [],
|
|
11332
|
+
cpp: [],
|
|
11333
|
+
zig: [],
|
|
11334
|
+
generic: []
|
|
11335
|
+
};
|
|
11336
|
+
const buildFiles = {
|
|
11337
|
+
node: ["tsup.config.ts", "vite.config.ts", "webpack.config.js", "rollup.config.js", "esbuild.js", "next.config.js", "nuxt.config.ts", "astro.config.mjs", "svelte.config.js"],
|
|
11338
|
+
python: ["setup.py", "setup.cfg", "pyproject.toml"],
|
|
11339
|
+
go: ["Makefile"],
|
|
11340
|
+
rust: ["Cargo.toml"],
|
|
11341
|
+
ruby: ["Rakefile"],
|
|
11342
|
+
java: ["pom.xml", "build.gradle"],
|
|
11343
|
+
dotnet: ["*.sln"],
|
|
11344
|
+
php: [],
|
|
11345
|
+
elixir: ["mix.exs"],
|
|
11346
|
+
haskell: ["package.yaml", "*.cabal"],
|
|
11347
|
+
c: ["Makefile", "CMakeLists.txt"],
|
|
11348
|
+
cpp: ["Makefile", "CMakeLists.txt"],
|
|
11349
|
+
zig: ["build.zig"],
|
|
11350
|
+
generic: []
|
|
11351
|
+
};
|
|
11352
|
+
const testConfigs = {
|
|
11353
|
+
node: ["vitest.config.ts", "jest.config.js", "playwright.config.ts", "cypress.config.ts", "ava.config.js"],
|
|
11354
|
+
python: ["pytest.ini", "tox.ini", "setup.cfg"],
|
|
11355
|
+
go: [],
|
|
11356
|
+
rust: [],
|
|
11357
|
+
ruby: ["Rakefile", "spec_helper.rb"],
|
|
11358
|
+
java: [],
|
|
11359
|
+
dotnet: [],
|
|
11360
|
+
php: ["phpunit.xml"],
|
|
11361
|
+
elixir: ["test/test_helper.exs"],
|
|
11362
|
+
haskell: [],
|
|
11363
|
+
c: ["Makefile"],
|
|
11364
|
+
cpp: ["Makefile"],
|
|
11365
|
+
zig: [],
|
|
11366
|
+
generic: []
|
|
11367
|
+
};
|
|
11368
|
+
const lintConfigs = {
|
|
11369
|
+
node: [".eslintrc", ".eslintrc.js", ".eslintrc.json", ".prettierrc", "biome.json", "deno.json"],
|
|
11370
|
+
python: [".flake8", "pyproject.toml", "setup.cfg", ".pylintrc", "ruff.toml"],
|
|
11371
|
+
go: [],
|
|
11372
|
+
rust: ["rustfmt.toml", "clippy.toml"],
|
|
11373
|
+
ruby: [".rubocop.yml"],
|
|
11374
|
+
java: [],
|
|
11375
|
+
dotnet: [],
|
|
11376
|
+
php: [],
|
|
11377
|
+
elixir: [".formatter.exs"],
|
|
11378
|
+
haskell: [],
|
|
11379
|
+
c: [".clang-format", ".clang-tidy"],
|
|
11380
|
+
cpp: [".clang-format", ".clang-tidy"],
|
|
11381
|
+
zig: [],
|
|
11382
|
+
generic: []
|
|
11383
|
+
};
|
|
11384
|
+
const typeConfigs = {
|
|
11385
|
+
node: ["tsconfig.json", "jsconfig.json"],
|
|
11386
|
+
python: ["pyproject.toml", "setup.cfg", "mypy.ini"],
|
|
11387
|
+
go: [],
|
|
11388
|
+
rust: [],
|
|
11389
|
+
ruby: [],
|
|
11390
|
+
java: [],
|
|
11391
|
+
dotnet: [],
|
|
11392
|
+
php: [],
|
|
11393
|
+
elixir: [],
|
|
11394
|
+
haskell: [],
|
|
11395
|
+
c: [],
|
|
11396
|
+
cpp: [],
|
|
11397
|
+
zig: [],
|
|
11398
|
+
generic: []
|
|
11399
|
+
};
|
|
11400
|
+
return {
|
|
11401
|
+
flavor,
|
|
11402
|
+
primaryLanguage: languageForFlavor(flavor),
|
|
11403
|
+
packageFile: findFile(cwd, packageFiles[flavor]),
|
|
11404
|
+
lockFile: findFile(cwd, lockFiles[flavor]),
|
|
11405
|
+
buildFile: findFile(cwd, buildFiles[flavor]),
|
|
11406
|
+
testConfig: findFile(cwd, testConfigs[flavor]),
|
|
11407
|
+
lintConfig: findFile(cwd, lintConfigs[flavor]),
|
|
11408
|
+
typeConfig: findFile(cwd, typeConfigs[flavor]),
|
|
11409
|
+
ciConfig: findCiConfig(cwd),
|
|
11410
|
+
readme: findFile(cwd, ["README.md", "README.rst", "README.txt", "Readme.md"]),
|
|
11411
|
+
sourceRoots: findSourceRoots(cwd),
|
|
11412
|
+
hasGit: existsSync2(join20(cwd, ".git"))
|
|
11413
|
+
};
|
|
11414
|
+
}
|
|
11415
|
+
function bashDiscoveryCommands(profile) {
|
|
11416
|
+
const cmds = [];
|
|
11417
|
+
if (profile.hasGit) {
|
|
11418
|
+
cmds.push(
|
|
11419
|
+
"git log --oneline -20",
|
|
11420
|
+
"git branch -a | head -20"
|
|
11421
|
+
);
|
|
11422
|
+
}
|
|
11423
|
+
switch (profile.flavor) {
|
|
11424
|
+
case "node":
|
|
11425
|
+
cmds.push(
|
|
11426
|
+
`cat package.json | jq -r '.scripts | to_entries[] | "\\(.key): \\(.value)"' 2>/dev/null || node -e "const p=require('./package.json'); Object.entries(p.scripts||{}).forEach(([k,v])=>console.log(k+': '+v))"`,
|
|
11427
|
+
"ls -la node_modules/.bin 2>/dev/null | head -30 || true"
|
|
11428
|
+
);
|
|
11429
|
+
break;
|
|
11430
|
+
case "python":
|
|
11431
|
+
cmds.push(
|
|
11432
|
+
`python -c "import tomllib; f=open('pyproject.toml','rb'); d=tomllib.load(f); [print(f'{k}: {v}') for k,v in d.get('project',{}).get('scripts',{}).items()]" 2>/dev/null || true`,
|
|
11433
|
+
"make -p 2>/dev/null | grep -E '^[a-zA-Z_-]+:.*$' | head -20 || true"
|
|
11434
|
+
);
|
|
11435
|
+
break;
|
|
11436
|
+
case "go":
|
|
11437
|
+
cmds.push("go help 2>/dev/null | head -10 || true");
|
|
11438
|
+
break;
|
|
11439
|
+
case "rust":
|
|
11440
|
+
cmds.push("cargo --list 2>/dev/null | head -20 || true");
|
|
11441
|
+
break;
|
|
11442
|
+
case "ruby":
|
|
11443
|
+
cmds.push("bundle exec rake -T 2>/dev/null | head -20 || true");
|
|
11444
|
+
break;
|
|
11445
|
+
case "java":
|
|
11446
|
+
cmds.push("./mvnw help:describe -Dplugin=help 2>/dev/null | head -10 || true");
|
|
11447
|
+
break;
|
|
11448
|
+
}
|
|
11449
|
+
cmds.push("ls -la");
|
|
11450
|
+
return cmds;
|
|
11451
|
+
}
|
|
11452
|
+
function discoveryChecklist(profile) {
|
|
11453
|
+
const lines = [];
|
|
11454
|
+
lines.push("## PHASE 1: Project Identity & Configuration");
|
|
11455
|
+
lines.push("");
|
|
11456
|
+
if (profile.readme) {
|
|
11457
|
+
lines.push(`- [ ] Read \`${profile.readme}\` \u2014 extract project name, description, purpose.`);
|
|
11458
|
+
}
|
|
11459
|
+
if (profile.packageFile) {
|
|
11460
|
+
lines.push(`- [ ] Read \`${profile.packageFile}\` \u2014 extract dependencies, scripts, metadata.`);
|
|
11461
|
+
}
|
|
11462
|
+
if (profile.buildFile) {
|
|
11463
|
+
lines.push(`- [ ] Read \`${profile.buildFile}\` \u2014 understand build system and entry points.`);
|
|
11464
|
+
}
|
|
11465
|
+
if (profile.typeConfig) {
|
|
11466
|
+
lines.push(`- [ ] Read \`${profile.typeConfig}\` \u2014 note strictness, target, module system.`);
|
|
11467
|
+
}
|
|
11468
|
+
if (profile.testConfig) {
|
|
11469
|
+
lines.push(`- [ ] Read \`${profile.testConfig}\` \u2014 understand test runner and conventions.`);
|
|
11470
|
+
}
|
|
11471
|
+
if (profile.lintConfig) {
|
|
11472
|
+
lines.push(`- [ ] Read \`${profile.lintConfig}\` \u2014 note style rules and formatter.`);
|
|
11473
|
+
}
|
|
11474
|
+
if (profile.ciConfig) {
|
|
11475
|
+
lines.push(`- [ ] Inspect CI config in \`${profile.ciConfig}\` \u2014 note checks, matrix, deployment.`);
|
|
11476
|
+
}
|
|
11477
|
+
lines.push("");
|
|
11478
|
+
lines.push("## PHASE 2: Source Structure Discovery");
|
|
11479
|
+
lines.push("");
|
|
11480
|
+
for (const root of profile.sourceRoots) {
|
|
11481
|
+
lines.push(`- [ ] Use \`glob\` to list files in \`${root}/**/*\` (limit to ~50 files).`);
|
|
11482
|
+
lines.push(`- [ ] Read 3-5 representative files from \`${root}\` to understand code patterns.`);
|
|
11483
|
+
}
|
|
11484
|
+
if (profile.sourceRoots.length === 0) {
|
|
11485
|
+
lines.push("- [ ] Use `glob` to find source files (`**/*.{js,ts,py,go,rs,rb,java,cs,php,ex,hs,c,cpp,zig}`) \u2014 list top 50.");
|
|
11486
|
+
lines.push("- [ ] Read 3-5 representative source files to understand code patterns.");
|
|
11487
|
+
}
|
|
11488
|
+
lines.push("- [ ] Use `glob` to find test files and note their location/naming pattern.");
|
|
11489
|
+
lines.push("- [ ] Use `glob` to find config files at root level.");
|
|
11490
|
+
lines.push("");
|
|
11491
|
+
lines.push("## PHASE 3: Convention Extraction");
|
|
11492
|
+
lines.push("");
|
|
11493
|
+
lines.push("- [ ] Use `grep` to find import patterns (e.g., `import .* from` or `require(`).");
|
|
11494
|
+
lines.push("- [ ] Use `grep` to find export patterns (e.g., `export ` or `module.exports`).");
|
|
11495
|
+
lines.push("- [ ] Check for any `.editorconfig`, `.gitignore`, or `CONTRIBUTING.md`.");
|
|
11496
|
+
if (profile.hasGit) {
|
|
11497
|
+
lines.push("- [ ] Run `git log --oneline -20` to understand commit style and recent activity.");
|
|
11498
|
+
lines.push("- [ ] Run `git branch -a | head -20` to understand branching strategy.");
|
|
11499
|
+
}
|
|
11500
|
+
lines.push("");
|
|
11501
|
+
lines.push("## PHASE 4: Build & Development Workflow");
|
|
11502
|
+
lines.push("");
|
|
11503
|
+
const bashCmds = bashDiscoveryCommands(profile);
|
|
11504
|
+
for (const cmd of bashCmds) {
|
|
11505
|
+
lines.push(`- [ ] Run \`bash\` with: \`${cmd}\``);
|
|
11506
|
+
}
|
|
11507
|
+
lines.push("");
|
|
11508
|
+
lines.push("## PHASE 5: Architecture & Patterns (Deep Dive)");
|
|
11509
|
+
lines.push("");
|
|
11510
|
+
lines.push("- [ ] Identify the main entry point(s) of the application.");
|
|
11511
|
+
lines.push("- [ ] Identify the testing framework and how tests are organized.");
|
|
11512
|
+
lines.push("- [ ] Look for any architectural patterns: MVC, hexagonal, actor model, etc.");
|
|
11513
|
+
lines.push("- [ ] Note any code-generation, build-time transforms, or code-mod tools.");
|
|
11514
|
+
lines.push("- [ ] Check for Docker, docker-compose, or deployment configs.");
|
|
11515
|
+
lines.push("- [ ] Note any monorepo patterns (workspaces, turborepo, nx, etc.).");
|
|
11516
|
+
return lines.join("\n");
|
|
11517
|
+
}
|
|
11518
|
+
function sectionTemplate() {
|
|
11519
|
+
return `
|
|
11520
|
+
Generate the context document with these sections. Be concise but comprehensive.
|
|
11521
|
+
Aim for 100\u2013200 lines total. Use markdown tables where they save space.
|
|
11522
|
+
|
|
11523
|
+
### Required Sections
|
|
11524
|
+
|
|
11525
|
+
1. **Project** \u2014 One-line description + primary language/runtime + key frameworks.
|
|
11526
|
+
|
|
11527
|
+
2. **Build / test / run** \u2014 Exact shell commands. Include:
|
|
11528
|
+
- Development server / watch mode
|
|
11529
|
+
- Production build
|
|
11530
|
+
- Test commands (unit, integration, e2e if separate)
|
|
11531
|
+
- Lint / format commands
|
|
11532
|
+
- Type-checking commands
|
|
11533
|
+
- Any setup / install commands
|
|
11534
|
+
Note which commands are slow or require special setup.
|
|
11535
|
+
|
|
11536
|
+
3. **Layout** \u2014 Table of key directories AND a one-sentence rationale for each.
|
|
11537
|
+
Explain *why* things live where they do, not just *what* is there.
|
|
11538
|
+
|
|
11539
|
+
4. **Conventions** \u2014 Cover:
|
|
11540
|
+
- Naming conventions (files, variables, types, tests)
|
|
11541
|
+
- Import style and path resolution quirks
|
|
11542
|
+
- File organization patterns
|
|
11543
|
+
- Commit message style (if discernible from git history)
|
|
11544
|
+
- Branching strategy
|
|
11545
|
+
- TypeScript / type system strictness rules
|
|
11546
|
+
- Testing conventions (naming, location, mocks)
|
|
11547
|
+
- Anything surprising or non-obvious
|
|
11548
|
+
|
|
11549
|
+
5. **Dependencies** \u2014 Rules for adding dependencies:
|
|
11550
|
+
- Package manager commands
|
|
11551
|
+
- Dev vs runtime dependency conventions
|
|
11552
|
+
- Native deps that must stay external (if bundling)
|
|
11553
|
+
- Version pinning policy
|
|
11554
|
+
|
|
11555
|
+
6. **Do / Don't** \u2014 Numbered list of hard rules:
|
|
11556
|
+
- Security rules (never commit secrets, etc.)
|
|
11557
|
+
- Performance rules (don't bundle X, etc.)
|
|
11558
|
+
- Style rules that aren't caught by linters
|
|
11559
|
+
- Common mistakes to avoid
|
|
11560
|
+
- Anything that would make a maintainer sad
|
|
11561
|
+
|
|
11562
|
+
7. **Debugging & Troubleshooting** \u2014 Common issues:
|
|
11563
|
+
- How to run in debug mode
|
|
11564
|
+
- Common build failures and fixes
|
|
11565
|
+
- How to reset / clean the project
|
|
11566
|
+
- Where logs live
|
|
11567
|
+
|
|
11568
|
+
8. **Architecture Notes** (if applicable) \u2014 Brief notes on:
|
|
11569
|
+
- Key abstractions and their responsibilities
|
|
11570
|
+
- Data flow
|
|
11571
|
+
- External integrations
|
|
11572
|
+
- State management approach
|
|
11573
|
+
`.trim();
|
|
11574
|
+
}
|
|
11575
|
+
function buildInitPrompt(cwd) {
|
|
11576
|
+
const existingName = ["KIMI.md", "KIMIFLARE.md", "AGENT.md"].find(
|
|
11577
|
+
(n) => existsSync2(join20(cwd, n))
|
|
11578
|
+
);
|
|
11579
|
+
const isRefresh = existingName !== void 0;
|
|
11580
|
+
const targetFilename = existingName ?? "KIMI.md";
|
|
11581
|
+
const profile = analyzeProject(cwd);
|
|
11582
|
+
const checklist = discoveryChecklist(profile);
|
|
11583
|
+
const sections = sectionTemplate();
|
|
11584
|
+
const promptParts = [
|
|
11585
|
+
isRefresh ? `Regenerate \`${targetFilename}\` at the repository root to refresh project context. The file already exists \u2014 read it first and preserve anything still accurate, updating only what has changed or is missing.` : `Generate a \`${targetFilename}\` at the repository root so future agents have comprehensive project context.`,
|
|
11586
|
+
"",
|
|
11587
|
+
"This is a **structured investigation**. Follow the checklist below systematically. Use the `glob`, `read`, `grep`, and `bash` tools to gather information. Do not skip steps.",
|
|
11588
|
+
"",
|
|
11589
|
+
`**Detected project profile:** ${profile.primaryLanguage} (${profile.flavor})`,
|
|
11590
|
+
profile.packageFile ? `- Package file: ${profile.packageFile}` : null,
|
|
11591
|
+
profile.buildFile ? `- Build file: ${profile.buildFile}` : null,
|
|
11592
|
+
profile.testConfig ? `- Test config: ${profile.testConfig}` : null,
|
|
11593
|
+
profile.typeConfig ? `- Type config: ${profile.typeConfig}` : null,
|
|
11594
|
+
profile.lintConfig ? `- Lint config: ${profile.lintConfig}` : null,
|
|
11595
|
+
profile.ciConfig ? `- CI config: ${profile.ciConfig}` : null,
|
|
11596
|
+
profile.sourceRoots.length > 0 ? `- Source roots: ${profile.sourceRoots.join(", ")}` : null,
|
|
11597
|
+
profile.hasGit ? `- Git repository: yes` : null,
|
|
11598
|
+
"",
|
|
11599
|
+
"---",
|
|
11600
|
+
"",
|
|
11601
|
+
checklist,
|
|
11602
|
+
"",
|
|
11603
|
+
"---",
|
|
11604
|
+
"",
|
|
11605
|
+
sections,
|
|
11606
|
+
"",
|
|
11607
|
+
isRefresh ? `After writing the file, re-read \`${targetFilename}\` and verify it is complete and accurate.` : "After writing the file, re-read it and verify all sections are present and accurate.",
|
|
11608
|
+
"",
|
|
11609
|
+
"Do not call `tasks_set` for this. Just follow the checklist, gather information, then write the file."
|
|
11610
|
+
];
|
|
11611
|
+
const prompt = promptParts.filter((p) => p !== null).join("\n");
|
|
11612
|
+
return { prompt, targetFilename, isRefresh };
|
|
11613
|
+
}
|
|
11614
|
+
var FLAVOR_SIGNATURES, SOURCE_ROOT_CANDIDATES, CI_PATHS;
|
|
11615
|
+
var init_context_generator = __esm({
|
|
11616
|
+
"src/init/context-generator.ts"() {
|
|
11617
|
+
"use strict";
|
|
11618
|
+
FLAVOR_SIGNATURES = {
|
|
11619
|
+
node: ["package.json", "package-lock.json", "yarn.lock", "pnpm-lock.yaml", "bun.lockb", "node_modules"],
|
|
11620
|
+
python: ["pyproject.toml", "setup.py", "setup.cfg", "requirements.txt", "Pipfile", "poetry.lock", "uv.lock", "tox.ini"],
|
|
11621
|
+
go: ["go.mod", "go.sum"],
|
|
11622
|
+
rust: ["Cargo.toml", "Cargo.lock"],
|
|
11623
|
+
ruby: ["Gemfile", "Gemfile.lock", "*.gemspec"],
|
|
11624
|
+
java: ["pom.xml", "build.gradle", "build.gradle.kts"],
|
|
11625
|
+
dotnet: ["*.csproj", "*.fsproj", "*.sln"],
|
|
11626
|
+
php: ["composer.json", "composer.lock"],
|
|
11627
|
+
elixir: ["mix.exs", "mix.lock"],
|
|
11628
|
+
haskell: ["package.yaml", "*.cabal", "stack.yaml"],
|
|
11629
|
+
c: ["Makefile", "CMakeLists.txt", "configure.ac"],
|
|
11630
|
+
cpp: ["Makefile", "CMakeLists.txt", "configure.ac"],
|
|
11631
|
+
zig: ["build.zig", "build.zig.zon"],
|
|
11632
|
+
generic: []
|
|
11633
|
+
};
|
|
11634
|
+
SOURCE_ROOT_CANDIDATES = [
|
|
11635
|
+
"src",
|
|
11636
|
+
"lib",
|
|
11637
|
+
"app",
|
|
11638
|
+
"source",
|
|
11639
|
+
"Sources",
|
|
11640
|
+
"pkg",
|
|
11641
|
+
"internal",
|
|
11642
|
+
"cmd",
|
|
11643
|
+
"bin",
|
|
11644
|
+
"packages",
|
|
11645
|
+
"projects"
|
|
11646
|
+
];
|
|
11647
|
+
CI_PATHS = [
|
|
11648
|
+
".github/workflows",
|
|
11649
|
+
".gitlab-ci.yml",
|
|
11650
|
+
".circleci",
|
|
11651
|
+
"azure-pipelines.yml",
|
|
11652
|
+
"Jenkinsfile",
|
|
11653
|
+
".buildkite",
|
|
11654
|
+
"cloudbuild.yaml"
|
|
11655
|
+
];
|
|
11656
|
+
}
|
|
11657
|
+
});
|
|
11658
|
+
|
|
10711
11659
|
// src/ui/command-picker.tsx
|
|
10712
|
-
import { Box as
|
|
10713
|
-
import
|
|
10714
|
-
import { jsx as
|
|
11660
|
+
import { Box as Box15, Text as Text16 } from "ink";
|
|
11661
|
+
import SelectInput8 from "ink-select-input";
|
|
11662
|
+
import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
10715
11663
|
function CommandPicker({ commands, title, onPick }) {
|
|
10716
11664
|
const theme = useTheme();
|
|
10717
11665
|
const items = commands.map((cmd) => ({
|
|
@@ -10720,11 +11668,11 @@ function CommandPicker({ commands, title, onPick }) {
|
|
|
10720
11668
|
key: cmd.name
|
|
10721
11669
|
}));
|
|
10722
11670
|
items.push({ label: "\u2190 Cancel", value: null, key: "__cancel__" });
|
|
10723
|
-
return /* @__PURE__ */
|
|
10724
|
-
/* @__PURE__ */
|
|
10725
|
-
/* @__PURE__ */
|
|
10726
|
-
/* @__PURE__ */
|
|
10727
|
-
|
|
11671
|
+
return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
11672
|
+
/* @__PURE__ */ jsx17(Text16, { color: theme.accent, bold: true, children: title }),
|
|
11673
|
+
/* @__PURE__ */ jsx17(Text16, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select." }),
|
|
11674
|
+
/* @__PURE__ */ jsx17(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx17(
|
|
11675
|
+
SelectInput8,
|
|
10728
11676
|
{
|
|
10729
11677
|
items,
|
|
10730
11678
|
onSelect: (item) => {
|
|
@@ -10746,64 +11694,64 @@ var init_command_picker = __esm({
|
|
|
10746
11694
|
});
|
|
10747
11695
|
|
|
10748
11696
|
// src/ui/command-list.tsx
|
|
10749
|
-
import { Box as
|
|
10750
|
-
import { jsx as
|
|
11697
|
+
import { Box as Box16, Text as Text17, useInput as useInput6 } from "ink";
|
|
11698
|
+
import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
10751
11699
|
function CommandList({ commands, onDone }) {
|
|
10752
11700
|
const theme = useTheme();
|
|
10753
|
-
|
|
11701
|
+
useInput6((_input, key) => {
|
|
10754
11702
|
if (key.escape) {
|
|
10755
11703
|
onDone();
|
|
10756
11704
|
}
|
|
10757
11705
|
});
|
|
10758
|
-
return /* @__PURE__ */
|
|
10759
|
-
/* @__PURE__ */
|
|
10760
|
-
/* @__PURE__ */
|
|
10761
|
-
/* @__PURE__ */
|
|
10762
|
-
commands.length === 0 && /* @__PURE__ */
|
|
10763
|
-
commands.map((cmd) => /* @__PURE__ */
|
|
10764
|
-
/* @__PURE__ */
|
|
11706
|
+
return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
11707
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Custom commands" }),
|
|
11708
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Esc to close." }),
|
|
11709
|
+
/* @__PURE__ */ jsxs16(Box16, { marginTop: 1, flexDirection: "column", children: [
|
|
11710
|
+
commands.length === 0 && /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, children: "No custom commands found." }),
|
|
11711
|
+
commands.map((cmd) => /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", marginBottom: 1, children: [
|
|
11712
|
+
/* @__PURE__ */ jsxs16(Text17, { color: theme.accent, bold: true, children: [
|
|
10765
11713
|
"/",
|
|
10766
11714
|
cmd.name
|
|
10767
11715
|
] }),
|
|
10768
|
-
/* @__PURE__ */
|
|
11716
|
+
/* @__PURE__ */ jsxs16(Text17, { color: theme.info.color, children: [
|
|
10769
11717
|
" ",
|
|
10770
11718
|
"source: ",
|
|
10771
11719
|
cmd.source
|
|
10772
11720
|
] }),
|
|
10773
|
-
/* @__PURE__ */
|
|
11721
|
+
/* @__PURE__ */ jsxs16(Text17, { color: theme.info.color, children: [
|
|
10774
11722
|
" ",
|
|
10775
11723
|
"path: ",
|
|
10776
11724
|
cmd.filepath
|
|
10777
11725
|
] }),
|
|
10778
|
-
cmd.description && /* @__PURE__ */
|
|
11726
|
+
cmd.description && /* @__PURE__ */ jsxs16(Text17, { color: theme.info.color, children: [
|
|
10779
11727
|
" ",
|
|
10780
11728
|
"desc: ",
|
|
10781
11729
|
cmd.description
|
|
10782
11730
|
] }),
|
|
10783
|
-
cmd.mode && /* @__PURE__ */
|
|
11731
|
+
cmd.mode && /* @__PURE__ */ jsxs16(Text17, { color: theme.info.color, children: [
|
|
10784
11732
|
" ",
|
|
10785
11733
|
"mode: ",
|
|
10786
11734
|
cmd.mode
|
|
10787
11735
|
] }),
|
|
10788
|
-
cmd.effort && /* @__PURE__ */
|
|
11736
|
+
cmd.effort && /* @__PURE__ */ jsxs16(Text17, { color: theme.info.color, children: [
|
|
10789
11737
|
" ",
|
|
10790
11738
|
"effort: ",
|
|
10791
11739
|
cmd.effort
|
|
10792
11740
|
] }),
|
|
10793
|
-
cmd.model && /* @__PURE__ */
|
|
11741
|
+
cmd.model && /* @__PURE__ */ jsxs16(Text17, { color: theme.info.color, children: [
|
|
10794
11742
|
" ",
|
|
10795
11743
|
"model: ",
|
|
10796
11744
|
cmd.model
|
|
10797
11745
|
] }),
|
|
10798
|
-
/* @__PURE__ */
|
|
11746
|
+
/* @__PURE__ */ jsxs16(Text17, { color: theme.info.color, children: [
|
|
10799
11747
|
" ",
|
|
10800
11748
|
"template:"
|
|
10801
11749
|
] }),
|
|
10802
|
-
cmd.template.split("\n").slice(0, 5).map((line, i) => /* @__PURE__ */
|
|
11750
|
+
cmd.template.split("\n").slice(0, 5).map((line, i) => /* @__PURE__ */ jsxs16(Text17, { color: theme.info.color, children: [
|
|
10803
11751
|
" ",
|
|
10804
11752
|
line || " "
|
|
10805
11753
|
] }, i)),
|
|
10806
|
-
cmd.template.split("\n").length > 5 && /* @__PURE__ */
|
|
11754
|
+
cmd.template.split("\n").length > 5 && /* @__PURE__ */ jsxs16(Text17, { color: theme.info.color, children: [
|
|
10807
11755
|
" ",
|
|
10808
11756
|
"..."
|
|
10809
11757
|
] })
|
|
@@ -10820,10 +11768,10 @@ var init_command_list = __esm({
|
|
|
10820
11768
|
|
|
10821
11769
|
// src/ui/lsp-wizard.tsx
|
|
10822
11770
|
import { useState as useState9 } from "react";
|
|
10823
|
-
import { Box as
|
|
10824
|
-
import
|
|
11771
|
+
import { Box as Box17, Text as Text18 } from "ink";
|
|
11772
|
+
import SelectInput9 from "ink-select-input";
|
|
10825
11773
|
import { spawn as spawn3 } from "child_process";
|
|
10826
|
-
import { jsx as
|
|
11774
|
+
import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
10827
11775
|
function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
10828
11776
|
const theme = useTheme();
|
|
10829
11777
|
const [page, setPage] = useState9("main");
|
|
@@ -10934,11 +11882,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
10934
11882
|
{ label: "(close)", value: "__close__", key: "__close__" }
|
|
10935
11883
|
];
|
|
10936
11884
|
if (page === "main") {
|
|
10937
|
-
return /* @__PURE__ */
|
|
10938
|
-
/* @__PURE__ */
|
|
10939
|
-
/* @__PURE__ */
|
|
10940
|
-
/* @__PURE__ */
|
|
10941
|
-
|
|
11885
|
+
return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
11886
|
+
/* @__PURE__ */ jsx19(Text18, { color: theme.accent, bold: true, children: "LSP Servers" }),
|
|
11887
|
+
/* @__PURE__ */ jsx19(Text18, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select." }),
|
|
11888
|
+
/* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
|
|
11889
|
+
SelectInput9,
|
|
10942
11890
|
{
|
|
10943
11891
|
items: mainItems,
|
|
10944
11892
|
onSelect: (item) => {
|
|
@@ -10965,11 +11913,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
10965
11913
|
}),
|
|
10966
11914
|
{ label: "\u2190 Back", value: "__back__", key: "__back__" }
|
|
10967
11915
|
];
|
|
10968
|
-
return /* @__PURE__ */
|
|
10969
|
-
/* @__PURE__ */
|
|
10970
|
-
/* @__PURE__ */
|
|
10971
|
-
/* @__PURE__ */
|
|
10972
|
-
|
|
11916
|
+
return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
11917
|
+
/* @__PURE__ */ jsx19(Text18, { color: theme.accent, bold: true, children: "Add LSP Server" }),
|
|
11918
|
+
/* @__PURE__ */ jsx19(Text18, { color: theme.info.color, dimColor: false, children: "Select a language server to configure." }),
|
|
11919
|
+
/* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
|
|
11920
|
+
SelectInput9,
|
|
10973
11921
|
{
|
|
10974
11922
|
items,
|
|
10975
11923
|
onSelect: (item) => {
|
|
@@ -10996,19 +11944,19 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
10996
11944
|
{ label: isSuccess ? "Save to config \u2713" : "Save anyway", value: "save", key: "save" },
|
|
10997
11945
|
{ label: "\u2190 Back", value: "__back__", key: "__back__" }
|
|
10998
11946
|
];
|
|
10999
|
-
return /* @__PURE__ */
|
|
11000
|
-
/* @__PURE__ */
|
|
11947
|
+
return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
11948
|
+
/* @__PURE__ */ jsxs17(Text18, { color: theme.accent, bold: true, children: [
|
|
11001
11949
|
"Install ",
|
|
11002
11950
|
selectedPreset.name
|
|
11003
11951
|
] }),
|
|
11004
|
-
/* @__PURE__ */
|
|
11005
|
-
/* @__PURE__ */
|
|
11006
|
-
/* @__PURE__ */
|
|
11007
|
-
/* @__PURE__ */
|
|
11952
|
+
/* @__PURE__ */ jsx19(Text18, { color: theme.info.color, dimColor: false, children: selectedPreset.installHint }),
|
|
11953
|
+
/* @__PURE__ */ jsxs17(Box17, { marginTop: 1, flexDirection: "column", children: [
|
|
11954
|
+
/* @__PURE__ */ jsx19(Text18, { color: theme.info.color, dimColor: false, children: "Command:" }),
|
|
11955
|
+
/* @__PURE__ */ jsx19(Text18, { color: theme.accent, children: selectedPreset.installCommand || "(none required)" })
|
|
11008
11956
|
] }),
|
|
11009
|
-
installState.output && /* @__PURE__ */
|
|
11010
|
-
/* @__PURE__ */
|
|
11011
|
-
|
|
11957
|
+
installState.output && /* @__PURE__ */ jsx19(Box17, { marginTop: 1, flexDirection: "column", children: /* @__PURE__ */ jsx19(Text18, { color: isSuccess ? theme.accent : theme.error, children: installState.output.slice(-500) }) }),
|
|
11958
|
+
/* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
|
|
11959
|
+
SelectInput9,
|
|
11012
11960
|
{
|
|
11013
11961
|
items,
|
|
11014
11962
|
onSelect: (item) => {
|
|
@@ -11025,16 +11973,16 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
11025
11973
|
}
|
|
11026
11974
|
}
|
|
11027
11975
|
) }),
|
|
11028
|
-
isSuccess && /* @__PURE__ */
|
|
11976
|
+
isSuccess && /* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(Text18, { color: theme.accent, children: "Server saved. Run /lsp reload to start it." }) })
|
|
11029
11977
|
] });
|
|
11030
11978
|
}
|
|
11031
11979
|
if (page === "custom-name") {
|
|
11032
|
-
return /* @__PURE__ */
|
|
11033
|
-
/* @__PURE__ */
|
|
11034
|
-
/* @__PURE__ */
|
|
11035
|
-
/* @__PURE__ */
|
|
11036
|
-
/* @__PURE__ */
|
|
11037
|
-
/* @__PURE__ */
|
|
11980
|
+
return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
11981
|
+
/* @__PURE__ */ jsx19(Text18, { color: theme.accent, bold: true, children: "Custom LSP Server \u2014 Name" }),
|
|
11982
|
+
/* @__PURE__ */ jsx19(Text18, { color: theme.info.color, dimColor: false, children: "Enter a name for this server (e.g., my-server)." }),
|
|
11983
|
+
/* @__PURE__ */ jsxs17(Box17, { marginTop: 1, children: [
|
|
11984
|
+
/* @__PURE__ */ jsx19(Text18, { color: theme.accent, children: "\u203A " }),
|
|
11985
|
+
/* @__PURE__ */ jsx19(
|
|
11038
11986
|
CustomTextInput,
|
|
11039
11987
|
{
|
|
11040
11988
|
value: customName,
|
|
@@ -11048,8 +11996,8 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
11048
11996
|
}
|
|
11049
11997
|
)
|
|
11050
11998
|
] }),
|
|
11051
|
-
/* @__PURE__ */
|
|
11052
|
-
|
|
11999
|
+
/* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
|
|
12000
|
+
SelectInput9,
|
|
11053
12001
|
{
|
|
11054
12002
|
items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
|
|
11055
12003
|
onSelect: () => setPage("add")
|
|
@@ -11058,12 +12006,12 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
11058
12006
|
] });
|
|
11059
12007
|
}
|
|
11060
12008
|
if (page === "custom-command") {
|
|
11061
|
-
return /* @__PURE__ */
|
|
11062
|
-
/* @__PURE__ */
|
|
11063
|
-
/* @__PURE__ */
|
|
11064
|
-
/* @__PURE__ */
|
|
11065
|
-
/* @__PURE__ */
|
|
11066
|
-
/* @__PURE__ */
|
|
12009
|
+
return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
12010
|
+
/* @__PURE__ */ jsx19(Text18, { color: theme.accent, bold: true, children: "Custom LSP Server \u2014 Command" }),
|
|
12011
|
+
/* @__PURE__ */ jsx19(Text18, { color: theme.info.color, dimColor: false, children: "Enter the command to start the server (space-separated)." }),
|
|
12012
|
+
/* @__PURE__ */ jsxs17(Box17, { marginTop: 1, children: [
|
|
12013
|
+
/* @__PURE__ */ jsx19(Text18, { color: theme.accent, children: "\u203A " }),
|
|
12014
|
+
/* @__PURE__ */ jsx19(
|
|
11067
12015
|
CustomTextInput,
|
|
11068
12016
|
{
|
|
11069
12017
|
value: customCommand,
|
|
@@ -11077,8 +12025,8 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
11077
12025
|
}
|
|
11078
12026
|
)
|
|
11079
12027
|
] }),
|
|
11080
|
-
/* @__PURE__ */
|
|
11081
|
-
|
|
12028
|
+
/* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
|
|
12029
|
+
SelectInput9,
|
|
11082
12030
|
{
|
|
11083
12031
|
items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
|
|
11084
12032
|
onSelect: () => setPage("custom-name")
|
|
@@ -11101,11 +12049,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
11101
12049
|
},
|
|
11102
12050
|
{ label: "\u2190 Back", value: "__back__", key: "__back__" }
|
|
11103
12051
|
];
|
|
11104
|
-
return /* @__PURE__ */
|
|
11105
|
-
/* @__PURE__ */
|
|
11106
|
-
/* @__PURE__ */
|
|
11107
|
-
/* @__PURE__ */
|
|
11108
|
-
|
|
12052
|
+
return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
12053
|
+
/* @__PURE__ */ jsx19(Text18, { color: theme.accent, bold: true, children: "Save LSP Config" }),
|
|
12054
|
+
/* @__PURE__ */ jsx19(Text18, { color: theme.info.color, dimColor: false, children: "Where should this server configuration be saved?" }),
|
|
12055
|
+
/* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
|
|
12056
|
+
SelectInput9,
|
|
11109
12057
|
{
|
|
11110
12058
|
items,
|
|
11111
12059
|
onSelect: (item) => {
|
|
@@ -11123,11 +12071,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
11123
12071
|
if (page === "edit") {
|
|
11124
12072
|
const keys = Object.keys(servers);
|
|
11125
12073
|
if (keys.length === 0) {
|
|
11126
|
-
return /* @__PURE__ */
|
|
11127
|
-
/* @__PURE__ */
|
|
11128
|
-
/* @__PURE__ */
|
|
11129
|
-
/* @__PURE__ */
|
|
11130
|
-
|
|
12074
|
+
return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
12075
|
+
/* @__PURE__ */ jsx19(Text18, { color: theme.accent, bold: true, children: "Edit LSP Server" }),
|
|
12076
|
+
/* @__PURE__ */ jsx19(Text18, { color: theme.info.color, children: "No servers configured." }),
|
|
12077
|
+
/* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
|
|
12078
|
+
SelectInput9,
|
|
11131
12079
|
{
|
|
11132
12080
|
items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
|
|
11133
12081
|
onSelect: () => setPage("main")
|
|
@@ -11147,11 +12095,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
11147
12095
|
}),
|
|
11148
12096
|
{ label: "\u2190 Back", value: "__back__", key: "__back__" }
|
|
11149
12097
|
];
|
|
11150
|
-
return /* @__PURE__ */
|
|
11151
|
-
/* @__PURE__ */
|
|
11152
|
-
/* @__PURE__ */
|
|
11153
|
-
/* @__PURE__ */
|
|
11154
|
-
|
|
12098
|
+
return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
12099
|
+
/* @__PURE__ */ jsx19(Text18, { color: theme.accent, bold: true, children: "Edit LSP Server" }),
|
|
12100
|
+
/* @__PURE__ */ jsx19(Text18, { color: theme.info.color, dimColor: false, children: "Select a server to toggle enabled/disabled." }),
|
|
12101
|
+
/* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
|
|
12102
|
+
SelectInput9,
|
|
11155
12103
|
{
|
|
11156
12104
|
items,
|
|
11157
12105
|
onSelect: (item) => {
|
|
@@ -11168,11 +12116,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
11168
12116
|
if (page === "delete") {
|
|
11169
12117
|
const keys = Object.keys(servers);
|
|
11170
12118
|
if (keys.length === 0) {
|
|
11171
|
-
return /* @__PURE__ */
|
|
11172
|
-
/* @__PURE__ */
|
|
11173
|
-
/* @__PURE__ */
|
|
11174
|
-
/* @__PURE__ */
|
|
11175
|
-
|
|
12119
|
+
return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
12120
|
+
/* @__PURE__ */ jsx19(Text18, { color: theme.accent, bold: true, children: "Delete LSP Server" }),
|
|
12121
|
+
/* @__PURE__ */ jsx19(Text18, { color: theme.info.color, children: "No servers configured." }),
|
|
12122
|
+
/* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
|
|
12123
|
+
SelectInput9,
|
|
11176
12124
|
{
|
|
11177
12125
|
items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
|
|
11178
12126
|
onSelect: () => setPage("main")
|
|
@@ -11188,11 +12136,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
11188
12136
|
})),
|
|
11189
12137
|
{ label: "\u2190 Back", value: "__back__", key: "__back__" }
|
|
11190
12138
|
];
|
|
11191
|
-
return /* @__PURE__ */
|
|
11192
|
-
/* @__PURE__ */
|
|
11193
|
-
/* @__PURE__ */
|
|
11194
|
-
/* @__PURE__ */
|
|
11195
|
-
|
|
12139
|
+
return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
12140
|
+
/* @__PURE__ */ jsx19(Text18, { color: theme.accent, bold: true, children: "Delete LSP Server" }),
|
|
12141
|
+
/* @__PURE__ */ jsx19(Text18, { color: theme.info.color, dimColor: false, children: "Select a server to remove from config." }),
|
|
12142
|
+
/* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
|
|
12143
|
+
SelectInput9,
|
|
11196
12144
|
{
|
|
11197
12145
|
items,
|
|
11198
12146
|
onSelect: (item) => {
|
|
@@ -11208,15 +12156,15 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
11208
12156
|
}
|
|
11209
12157
|
if (page === "list") {
|
|
11210
12158
|
const keys = Object.keys(servers);
|
|
11211
|
-
return /* @__PURE__ */
|
|
11212
|
-
/* @__PURE__ */
|
|
11213
|
-
keys.length === 0 ? /* @__PURE__ */
|
|
12159
|
+
return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
12160
|
+
/* @__PURE__ */ jsx19(Text18, { color: theme.accent, bold: true, children: "Configured LSP Servers" }),
|
|
12161
|
+
keys.length === 0 ? /* @__PURE__ */ jsx19(Text18, { color: theme.info.color, children: "No servers configured." }) : /* @__PURE__ */ jsx19(Box17, { marginTop: 1, flexDirection: "column", children: keys.map((k) => {
|
|
11214
12162
|
const s = servers[k];
|
|
11215
12163
|
const status = s.enabled !== false ? "enabled" : "disabled";
|
|
11216
|
-
return /* @__PURE__ */
|
|
12164
|
+
return /* @__PURE__ */ jsx19(Text18, { color: theme.info.color, children: ` ${k.padEnd(16)} ${status} ${s.command.join(" ")}` }, k);
|
|
11217
12165
|
}) }),
|
|
11218
|
-
/* @__PURE__ */
|
|
11219
|
-
|
|
12166
|
+
/* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
|
|
12167
|
+
SelectInput9,
|
|
11220
12168
|
{
|
|
11221
12169
|
items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
|
|
11222
12170
|
onSelect: () => setPage("main")
|
|
@@ -11342,9 +12290,9 @@ var init_lsp_wizard = __esm({
|
|
|
11342
12290
|
});
|
|
11343
12291
|
|
|
11344
12292
|
// src/ui/theme-picker.tsx
|
|
11345
|
-
import { Box as
|
|
11346
|
-
import
|
|
11347
|
-
import { jsx as
|
|
12293
|
+
import { Box as Box18, Text as Text19 } from "ink";
|
|
12294
|
+
import SelectInput10 from "ink-select-input";
|
|
12295
|
+
import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
11348
12296
|
function PaletteSwatches({ palette }) {
|
|
11349
12297
|
const colors = [
|
|
11350
12298
|
palette.primary,
|
|
@@ -11352,7 +12300,7 @@ function PaletteSwatches({ palette }) {
|
|
|
11352
12300
|
palette.success,
|
|
11353
12301
|
palette.error
|
|
11354
12302
|
];
|
|
11355
|
-
return /* @__PURE__ */
|
|
12303
|
+
return /* @__PURE__ */ jsx20(Box18, { children: colors.map((c, i) => /* @__PURE__ */ jsx20(Text19, { color: c, children: "\u2588" }, i)) });
|
|
11356
12304
|
}
|
|
11357
12305
|
function ThemePicker({ themes, onPick, onPreview }) {
|
|
11358
12306
|
const current = useTheme();
|
|
@@ -11360,10 +12308,10 @@ function ThemePicker({ themes, onPick, onPreview }) {
|
|
|
11360
12308
|
...themes.map((t) => ({ label: t.label, value: t.name })),
|
|
11361
12309
|
{ label: "< Back", value: "__back__" }
|
|
11362
12310
|
];
|
|
11363
|
-
return /* @__PURE__ */
|
|
11364
|
-
/* @__PURE__ */
|
|
11365
|
-
/* @__PURE__ */
|
|
11366
|
-
|
|
12311
|
+
return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", borderStyle: "round", borderColor: current.accent, paddingX: 1, children: [
|
|
12312
|
+
/* @__PURE__ */ jsx20(Text19, { color: current.accent, bold: true, children: "Pick a theme" }),
|
|
12313
|
+
/* @__PURE__ */ jsx20(Box18, { marginTop: 1, children: /* @__PURE__ */ jsx20(
|
|
12314
|
+
SelectInput10,
|
|
11367
12315
|
{
|
|
11368
12316
|
items,
|
|
11369
12317
|
onHighlight: (item) => {
|
|
@@ -11382,9 +12330,9 @@ function ThemePicker({ themes, onPick, onPreview }) {
|
|
|
11382
12330
|
itemComponent: ({ label, isSelected }) => {
|
|
11383
12331
|
const t = themes.find((x) => x.label === label);
|
|
11384
12332
|
const color = t?.accent ?? current.accent;
|
|
11385
|
-
return /* @__PURE__ */
|
|
11386
|
-
/* @__PURE__ */
|
|
11387
|
-
t && /* @__PURE__ */
|
|
12333
|
+
return /* @__PURE__ */ jsxs18(Box18, { children: [
|
|
12334
|
+
/* @__PURE__ */ jsx20(Text19, { color, bold: isSelected, dimColor: !isSelected, children: label }),
|
|
12335
|
+
t && /* @__PURE__ */ jsx20(Box18, { marginLeft: 1, children: /* @__PURE__ */ jsx20(PaletteSwatches, { palette: t.palette }) })
|
|
11388
12336
|
] });
|
|
11389
12337
|
}
|
|
11390
12338
|
}
|
|
@@ -11528,8 +12476,8 @@ var init_lsp_nudge = __esm({
|
|
|
11528
12476
|
});
|
|
11529
12477
|
|
|
11530
12478
|
// src/ui/file-picker.tsx
|
|
11531
|
-
import { Box as
|
|
11532
|
-
import { jsx as
|
|
12479
|
+
import { Box as Box19, Text as Text20 } from "ink";
|
|
12480
|
+
import { jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
11533
12481
|
function FilePicker({ items, selectedIndex, query }) {
|
|
11534
12482
|
const theme = useTheme();
|
|
11535
12483
|
let startIndex = 0;
|
|
@@ -11539,12 +12487,12 @@ function FilePicker({ items, selectedIndex, query }) {
|
|
|
11539
12487
|
const visible = items.slice(startIndex, startIndex + VISIBLE_LIMIT);
|
|
11540
12488
|
const hasMoreAbove = startIndex > 0;
|
|
11541
12489
|
const hasMoreBelow = items.length > startIndex + VISIBLE_LIMIT;
|
|
11542
|
-
return /* @__PURE__ */
|
|
11543
|
-
/* @__PURE__ */
|
|
11544
|
-
/* @__PURE__ */
|
|
11545
|
-
/* @__PURE__ */
|
|
11546
|
-
visible.length === 0 && /* @__PURE__ */
|
|
11547
|
-
hasMoreAbove && /* @__PURE__ */
|
|
12490
|
+
return /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
12491
|
+
/* @__PURE__ */ jsx21(Text20, { color: theme.accent, bold: true, children: query ? `Files matching "${query}"` : "Mention a file" }),
|
|
12492
|
+
/* @__PURE__ */ jsx21(Text20, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select, Esc to cancel." }),
|
|
12493
|
+
/* @__PURE__ */ jsxs19(Box19, { marginTop: 1, flexDirection: "column", children: [
|
|
12494
|
+
visible.length === 0 && /* @__PURE__ */ jsx21(Text20, { color: theme.info.color, children: "No matches" }),
|
|
12495
|
+
hasMoreAbove && /* @__PURE__ */ jsxs19(Text20, { color: theme.info.color, children: [
|
|
11548
12496
|
"\u2026 ",
|
|
11549
12497
|
startIndex,
|
|
11550
12498
|
" more above"
|
|
@@ -11553,12 +12501,12 @@ function FilePicker({ items, selectedIndex, query }) {
|
|
|
11553
12501
|
const actualIndex = startIndex + i;
|
|
11554
12502
|
const isSelected = actualIndex === selectedIndex;
|
|
11555
12503
|
const label = item.isDirectory ? `${item.name}/` : item.name;
|
|
11556
|
-
return /* @__PURE__ */
|
|
12504
|
+
return /* @__PURE__ */ jsxs19(Text20, { color: isSelected ? theme.accent : void 0, bold: isSelected, children: [
|
|
11557
12505
|
isSelected ? "\u203A " : " ",
|
|
11558
12506
|
label
|
|
11559
12507
|
] }, item.name);
|
|
11560
12508
|
}),
|
|
11561
|
-
hasMoreBelow && /* @__PURE__ */
|
|
12509
|
+
hasMoreBelow && /* @__PURE__ */ jsxs19(Text20, { color: theme.info.color, children: [
|
|
11562
12510
|
"\u2026 ",
|
|
11563
12511
|
items.length - (startIndex + VISIBLE_LIMIT),
|
|
11564
12512
|
" more below"
|
|
@@ -11576,8 +12524,8 @@ var init_file_picker = __esm({
|
|
|
11576
12524
|
});
|
|
11577
12525
|
|
|
11578
12526
|
// src/ui/slash-picker.tsx
|
|
11579
|
-
import { Box as
|
|
11580
|
-
import { jsx as
|
|
12527
|
+
import { Box as Box20, Text as Text21 } from "ink";
|
|
12528
|
+
import { jsx as jsx22, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
11581
12529
|
function sourceBadge(source) {
|
|
11582
12530
|
if (source === "builtin") return "";
|
|
11583
12531
|
if (source === "project") return "project";
|
|
@@ -11597,12 +12545,12 @@ function SlashPicker({ items, selectedIndex, query }) {
|
|
|
11597
12545
|
const hasMoreBelow = items.length > startIndex + VISIBLE_LIMIT2;
|
|
11598
12546
|
const longestLabel = visible.reduce((m, it) => Math.max(m, commandLabel(it).length), 0);
|
|
11599
12547
|
const nameColWidth = Math.max(NAME_COL_MIN_WIDTH, longestLabel + NAME_DESC_GAP);
|
|
11600
|
-
return /* @__PURE__ */
|
|
11601
|
-
/* @__PURE__ */
|
|
11602
|
-
/* @__PURE__ */
|
|
11603
|
-
/* @__PURE__ */
|
|
11604
|
-
visible.length === 0 && /* @__PURE__ */
|
|
11605
|
-
hasMoreAbove && /* @__PURE__ */
|
|
12548
|
+
return /* @__PURE__ */ jsxs20(Box20, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
12549
|
+
/* @__PURE__ */ jsx22(Text21, { color: theme.accent, bold: true, children: query ? `Commands matching "/${query}"` : "Slash commands" }),
|
|
12550
|
+
/* @__PURE__ */ jsx22(Text21, { color: theme.info.color, children: "Arrow keys to navigate, Enter to select, Esc to cancel." }),
|
|
12551
|
+
/* @__PURE__ */ jsxs20(Box20, { marginTop: 1, flexDirection: "column", children: [
|
|
12552
|
+
visible.length === 0 && /* @__PURE__ */ jsx22(Text21, { color: theme.info.color, children: "No matches" }),
|
|
12553
|
+
hasMoreAbove && /* @__PURE__ */ jsxs20(Text21, { color: theme.info.color, children: [
|
|
11606
12554
|
"\u2026 ",
|
|
11607
12555
|
startIndex,
|
|
11608
12556
|
" more above"
|
|
@@ -11612,16 +12560,16 @@ function SlashPicker({ items, selectedIndex, query }) {
|
|
|
11612
12560
|
const isSelected = actualIndex === selectedIndex;
|
|
11613
12561
|
const nameCol = commandLabel(item).padEnd(nameColWidth);
|
|
11614
12562
|
const badge = sourceBadge(item.source);
|
|
11615
|
-
return /* @__PURE__ */
|
|
12563
|
+
return /* @__PURE__ */ jsxs20(Text21, { color: isSelected ? theme.accent : void 0, bold: isSelected, children: [
|
|
11616
12564
|
isSelected ? "\u203A " : " ",
|
|
11617
12565
|
nameCol,
|
|
11618
|
-
/* @__PURE__ */
|
|
12566
|
+
/* @__PURE__ */ jsxs20(Text21, { color: theme.info.color, children: [
|
|
11619
12567
|
item.description,
|
|
11620
12568
|
badge && ` [${badge}]`
|
|
11621
12569
|
] })
|
|
11622
12570
|
] }, item.name);
|
|
11623
12571
|
}),
|
|
11624
|
-
hasMoreBelow && /* @__PURE__ */
|
|
12572
|
+
hasMoreBelow && /* @__PURE__ */ jsxs20(Text21, { color: theme.info.color, children: [
|
|
11625
12573
|
"\u2026 ",
|
|
11626
12574
|
items.length - (startIndex + VISIBLE_LIMIT2),
|
|
11627
12575
|
" more below"
|
|
@@ -11701,15 +12649,15 @@ var tui_report_exports = {};
|
|
|
11701
12649
|
__export(tui_report_exports, {
|
|
11702
12650
|
getCategoryReportText: () => getCategoryReportText
|
|
11703
12651
|
});
|
|
11704
|
-
import { readFile as
|
|
11705
|
-
import { join as
|
|
11706
|
-
import { homedir as
|
|
12652
|
+
import { readFile as readFile16 } from "fs/promises";
|
|
12653
|
+
import { join as join21 } from "path";
|
|
12654
|
+
import { homedir as homedir14 } from "os";
|
|
11707
12655
|
function usageDir3() {
|
|
11708
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
11709
|
-
return
|
|
12656
|
+
const xdg = process.env.XDG_DATA_HOME || join21(homedir14(), ".local", "share");
|
|
12657
|
+
return join21(xdg, "kimiflare");
|
|
11710
12658
|
}
|
|
11711
12659
|
function usagePath3() {
|
|
11712
|
-
return
|
|
12660
|
+
return join21(usageDir3(), "usage.json");
|
|
11713
12661
|
}
|
|
11714
12662
|
function today3() {
|
|
11715
12663
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
@@ -11721,7 +12669,7 @@ function daysAgo2(n) {
|
|
|
11721
12669
|
}
|
|
11722
12670
|
async function loadLog3() {
|
|
11723
12671
|
try {
|
|
11724
|
-
const raw = await
|
|
12672
|
+
const raw = await readFile16(usagePath3(), "utf8");
|
|
11725
12673
|
return JSON.parse(raw);
|
|
11726
12674
|
} catch {
|
|
11727
12675
|
return { version: 1, days: [], sessions: [] };
|
|
@@ -11787,18 +12735,18 @@ __export(app_exports, {
|
|
|
11787
12735
|
shouldOpenMentionPicker: () => shouldOpenMentionPicker,
|
|
11788
12736
|
shouldOpenSlashPicker: () => shouldOpenSlashPicker
|
|
11789
12737
|
});
|
|
11790
|
-
import React14, { useState as useState10, useRef as useRef3, useEffect as
|
|
11791
|
-
import { Box as
|
|
11792
|
-
import
|
|
11793
|
-
import { existsSync as
|
|
11794
|
-
import { join as
|
|
12738
|
+
import React14, { useState as useState10, useRef as useRef3, useEffect as useEffect6, useCallback as useCallback2 } from "react";
|
|
12739
|
+
import { Box as Box21, Text as Text22, useApp, useInput as useInput7, render } from "ink";
|
|
12740
|
+
import SelectInput11 from "ink-select-input";
|
|
12741
|
+
import { existsSync as existsSync3, statSync as statSync4 } from "fs";
|
|
12742
|
+
import { join as join22 } from "path";
|
|
11795
12743
|
import { unlink as unlink3 } from "fs/promises";
|
|
11796
12744
|
import { execSync as execSync2 } from "child_process";
|
|
11797
12745
|
import { spawn as spawn4 } from "child_process";
|
|
11798
12746
|
import { platform as platform2 } from "os";
|
|
11799
12747
|
import fg4 from "fast-glob";
|
|
11800
12748
|
import { readFileSync as readFileSync3 } from "fs";
|
|
11801
|
-
import { jsx as
|
|
12749
|
+
import { jsx as jsx23, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
11802
12750
|
function buildFilePickerIgnoreList(cwd) {
|
|
11803
12751
|
const hardcoded = [
|
|
11804
12752
|
// Dependencies
|
|
@@ -11869,8 +12817,8 @@ function buildFilePickerIgnoreList(cwd) {
|
|
|
11869
12817
|
];
|
|
11870
12818
|
const gitignorePatterns = [];
|
|
11871
12819
|
try {
|
|
11872
|
-
const gitignorePath =
|
|
11873
|
-
const stats =
|
|
12820
|
+
const gitignorePath = join22(cwd, ".gitignore");
|
|
12821
|
+
const stats = statSync4(gitignorePath);
|
|
11874
12822
|
if (stats.size > MAX_GITIGNORE_SIZE) {
|
|
11875
12823
|
return hardcoded;
|
|
11876
12824
|
}
|
|
@@ -11938,7 +12886,7 @@ function gatewayUsageLookupFromConfig(cfg, meta) {
|
|
|
11938
12886
|
meta
|
|
11939
12887
|
};
|
|
11940
12888
|
}
|
|
11941
|
-
function
|
|
12889
|
+
function openBrowser2(url) {
|
|
11942
12890
|
const cmd = platform2() === "darwin" ? "open" : platform2() === "win32" ? "start" : "xdg-open";
|
|
11943
12891
|
const child = spawn4(cmd, [url], { detached: true, stdio: "ignore" });
|
|
11944
12892
|
child.unref();
|
|
@@ -11958,7 +12906,7 @@ function detectGitHubRepo(cachedRepo) {
|
|
|
11958
12906
|
}
|
|
11959
12907
|
return null;
|
|
11960
12908
|
}
|
|
11961
|
-
function
|
|
12909
|
+
function formatTokens4(n) {
|
|
11962
12910
|
if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
|
|
11963
12911
|
if (n >= 1e3) return `${(n / 1e3).toFixed(1)}K`;
|
|
11964
12912
|
return String(n);
|
|
@@ -12003,7 +12951,7 @@ function findImagePaths(text) {
|
|
|
12003
12951
|
let match;
|
|
12004
12952
|
while ((match = quotedRegex.exec(text)) !== null) {
|
|
12005
12953
|
const path = match[1] ?? match[2];
|
|
12006
|
-
if (path && isImagePath(path) &&
|
|
12954
|
+
if (path && isImagePath(path) && existsSync3(path)) {
|
|
12007
12955
|
paths.push(path);
|
|
12008
12956
|
}
|
|
12009
12957
|
}
|
|
@@ -12012,7 +12960,7 @@ function findImagePaths(text) {
|
|
|
12012
12960
|
const processed = remaining.replace(/\\ /g, ESCAPED_SPACE);
|
|
12013
12961
|
for (const token of processed.split(/\s+/)) {
|
|
12014
12962
|
const clean = token.replace(new RegExp(ESCAPED_SPACE, "g"), " ").replace(/^["']|["',;:!?]$/g, "").replace(/[.,;:!?]$/, "");
|
|
12015
|
-
if (clean && isImagePath(clean) &&
|
|
12963
|
+
if (clean && isImagePath(clean) && existsSync3(clean) && !paths.includes(clean)) {
|
|
12016
12964
|
paths.push(clean);
|
|
12017
12965
|
}
|
|
12018
12966
|
}
|
|
@@ -12022,14 +12970,15 @@ function App({
|
|
|
12022
12970
|
initialCfg,
|
|
12023
12971
|
initialUpdateResult,
|
|
12024
12972
|
initialLspScope,
|
|
12025
|
-
initialLspProjectPath
|
|
12973
|
+
initialLspProjectPath,
|
|
12974
|
+
initialCloudToken
|
|
12026
12975
|
}) {
|
|
12027
12976
|
const { exit } = useApp();
|
|
12028
12977
|
const [cfg, setCfg] = useState10(initialCfg);
|
|
12029
12978
|
const [lspScope, setLspScope] = useState10(initialLspScope);
|
|
12030
12979
|
const [lspProjectPath, setLspProjectPath] = useState10(initialLspProjectPath);
|
|
12031
12980
|
const [events, setRawEvents] = useState10([]);
|
|
12032
|
-
const setEvents =
|
|
12981
|
+
const setEvents = useCallback2(
|
|
12033
12982
|
(updater) => {
|
|
12034
12983
|
setRawEvents((prev) => {
|
|
12035
12984
|
const next = typeof updater === "function" ? updater(prev) : updater;
|
|
@@ -12043,8 +12992,10 @@ function App({
|
|
|
12043
12992
|
const [usage, setUsage] = useState10(null);
|
|
12044
12993
|
const [sessionUsage, setSessionUsage] = useState10(null);
|
|
12045
12994
|
const [gatewayMeta, setGatewayMeta] = useState10(null);
|
|
12995
|
+
const [cloudBudget, setCloudBudget] = useState10(null);
|
|
12046
12996
|
const [showReasoning, setShowReasoning] = useState10(false);
|
|
12047
12997
|
const [perm, setPerm] = useState10(null);
|
|
12998
|
+
const [limitModal, setLimitModal] = useState10(null);
|
|
12048
12999
|
const [queue, setQueue] = useState10([]);
|
|
12049
13000
|
const [history, setHistory] = useState10([]);
|
|
12050
13001
|
const [historyIndex, setHistoryIndex] = useState10(-1);
|
|
@@ -12074,6 +13025,21 @@ function App({
|
|
|
12074
13025
|
const [theme, setTheme] = useState10(resolveTheme(initialCfg?.theme));
|
|
12075
13026
|
const [showThemePicker, setShowThemePicker] = useState10(false);
|
|
12076
13027
|
const [originalTheme, setOriginalTheme] = useState10(null);
|
|
13028
|
+
useEffect6(() => {
|
|
13029
|
+
if (!cfg?.cloudMode || !initialCloudToken) return;
|
|
13030
|
+
let cancelled = false;
|
|
13031
|
+
const fetchBudget = async () => {
|
|
13032
|
+
const { fetchCloudUsage: fetchCloudUsage2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
|
|
13033
|
+
const usage2 = await fetchCloudUsage2(initialCloudToken);
|
|
13034
|
+
if (usage2 && !cancelled) {
|
|
13035
|
+
setCloudBudget({ remaining: usage2.remaining, limit: usage2.input_token_limit });
|
|
13036
|
+
}
|
|
13037
|
+
};
|
|
13038
|
+
fetchBudget();
|
|
13039
|
+
return () => {
|
|
13040
|
+
cancelled = true;
|
|
13041
|
+
};
|
|
13042
|
+
}, [cfg?.cloudMode, initialCloudToken]);
|
|
12077
13043
|
const [cursorOffset, setCursorOffset] = useState10(0);
|
|
12078
13044
|
const [activePicker, setActivePicker] = useState10(null);
|
|
12079
13045
|
const [filePickerItems, setFilePickerItems] = useState10([]);
|
|
@@ -12087,6 +13053,7 @@ function App({
|
|
|
12087
13053
|
const activeAsstIdRef = useRef3(null);
|
|
12088
13054
|
const activeControllerRef = useRef3(null);
|
|
12089
13055
|
const permResolveRef = useRef3(null);
|
|
13056
|
+
const limitResolveRef = useRef3(null);
|
|
12090
13057
|
const pendingToolCallsRef = useRef3(/* @__PURE__ */ new Map());
|
|
12091
13058
|
const sessionIdRef = useRef3(null);
|
|
12092
13059
|
const modeRef = useRef3(mode);
|
|
@@ -12108,12 +13075,16 @@ function App({
|
|
|
12108
13075
|
const lspManagerRef = useRef3(new LspManager());
|
|
12109
13076
|
const lspToolsRef = useRef3([]);
|
|
12110
13077
|
const lspInitRef = useRef3(false);
|
|
13078
|
+
const busyRef = useRef3(busy);
|
|
12111
13079
|
const memoryManagerRef = useRef3(null);
|
|
12112
13080
|
const sessionStartRecallRef = useRef3(null);
|
|
12113
13081
|
const pendingTextRef = useRef3(/* @__PURE__ */ new Map());
|
|
12114
13082
|
const flushTimeoutRef = useRef3(null);
|
|
12115
13083
|
const customCommandsRef = useRef3([]);
|
|
12116
13084
|
const pickerCancelRef = useRef3(null);
|
|
13085
|
+
useEffect6(() => {
|
|
13086
|
+
busyRef.current = busy;
|
|
13087
|
+
}, [busy]);
|
|
12117
13088
|
const pickerAnchor = activePicker?.anchor ?? null;
|
|
12118
13089
|
const pickerKind = activePicker?.kind ?? null;
|
|
12119
13090
|
const pickerQuery = React14.useMemo(() => {
|
|
@@ -12136,7 +13107,7 @@ function App({
|
|
|
12136
13107
|
if (pickerKind !== "slash" || pickerQuery === null) return [];
|
|
12137
13108
|
return fuzzyFilter(allSlashCommands, pickerQuery, (c) => c.name).slice(0, 50);
|
|
12138
13109
|
}, [pickerKind, allSlashCommands, pickerQuery]);
|
|
12139
|
-
|
|
13110
|
+
useEffect6(() => {
|
|
12140
13111
|
if (activePicker !== null) {
|
|
12141
13112
|
const trigger = activePicker.kind === "file" ? "@" : "/";
|
|
12142
13113
|
if (cursorOffset < activePicker.anchor) {
|
|
@@ -12193,28 +13164,28 @@ function App({
|
|
|
12193
13164
|
return;
|
|
12194
13165
|
}
|
|
12195
13166
|
}, [input, cursorOffset, activePicker, filePickerEnabled]);
|
|
12196
|
-
|
|
13167
|
+
useEffect6(() => {
|
|
12197
13168
|
if (activePicker?.kind !== "file") return;
|
|
12198
13169
|
const max = Math.max(0, filteredFileItems.length - 1);
|
|
12199
13170
|
if (activePicker.selected > max) {
|
|
12200
13171
|
setActivePicker({ ...activePicker, selected: max });
|
|
12201
13172
|
}
|
|
12202
13173
|
}, [filteredFileItems.length, activePicker]);
|
|
12203
|
-
|
|
13174
|
+
useEffect6(() => {
|
|
12204
13175
|
if (activePicker?.kind !== "slash") return;
|
|
12205
13176
|
const max = Math.max(0, filteredSlashItems.length - 1);
|
|
12206
13177
|
if (activePicker.selected > max) {
|
|
12207
13178
|
setActivePicker({ ...activePicker, selected: max });
|
|
12208
13179
|
}
|
|
12209
13180
|
}, [filteredSlashItems.length, activePicker]);
|
|
12210
|
-
const handlePickerUp =
|
|
13181
|
+
const handlePickerUp = useCallback2(() => {
|
|
12211
13182
|
setActivePicker((p) => {
|
|
12212
13183
|
if (!p) return null;
|
|
12213
13184
|
const next = Math.max(0, p.selected - 1);
|
|
12214
13185
|
return next === p.selected ? p : { ...p, selected: next };
|
|
12215
13186
|
});
|
|
12216
13187
|
}, []);
|
|
12217
|
-
const handlePickerDown =
|
|
13188
|
+
const handlePickerDown = useCallback2(() => {
|
|
12218
13189
|
setActivePicker((p) => {
|
|
12219
13190
|
if (!p) return null;
|
|
12220
13191
|
const max = p.kind === "file" ? Math.max(0, filteredFileItems.length - 1) : Math.max(0, filteredSlashItems.length - 1);
|
|
@@ -12222,7 +13193,7 @@ function App({
|
|
|
12222
13193
|
return next === p.selected ? p : { ...p, selected: next };
|
|
12223
13194
|
});
|
|
12224
13195
|
}, [filteredFileItems.length, filteredSlashItems.length]);
|
|
12225
|
-
const handlePickerSelect =
|
|
13196
|
+
const handlePickerSelect = useCallback2(() => {
|
|
12226
13197
|
if (!activePicker) return;
|
|
12227
13198
|
if (activePicker.kind === "file") {
|
|
12228
13199
|
const item2 = filteredFileItems[activePicker.selected];
|
|
@@ -12240,12 +13211,12 @@ function App({
|
|
|
12240
13211
|
setActivePicker(null);
|
|
12241
13212
|
submitRef.current(value);
|
|
12242
13213
|
}, [activePicker, filteredFileItems, filteredSlashItems, input, cursorOffset]);
|
|
12243
|
-
const handlePickerCancel =
|
|
13214
|
+
const handlePickerCancel = useCallback2(() => {
|
|
12244
13215
|
pickerCancelRef.current = cursorOffset;
|
|
12245
13216
|
setActivePicker(null);
|
|
12246
13217
|
}, [cursorOffset]);
|
|
12247
|
-
|
|
12248
|
-
const modalActive = showHelpMenu || commandWizard !== null || commandPicker !== null || commandToDelete !== null || showCommandList || showLspWizard || resumeSessions !== null || perm !== null;
|
|
13218
|
+
useEffect6(() => {
|
|
13219
|
+
const modalActive = showHelpMenu || commandWizard !== null || commandPicker !== null || commandToDelete !== null || showCommandList || showLspWizard || resumeSessions !== null || perm !== null || limitModal !== null;
|
|
12249
13220
|
if (modalActive && activePicker !== null) {
|
|
12250
13221
|
setActivePicker(null);
|
|
12251
13222
|
}
|
|
@@ -12258,9 +13229,10 @@ function App({
|
|
|
12258
13229
|
showLspWizard,
|
|
12259
13230
|
resumeSessions,
|
|
12260
13231
|
perm,
|
|
13232
|
+
limitModal,
|
|
12261
13233
|
activePicker
|
|
12262
13234
|
]);
|
|
12263
|
-
|
|
13235
|
+
useEffect6(() => {
|
|
12264
13236
|
if (!cfg) return;
|
|
12265
13237
|
void Promise.resolve().then(() => (init_sessions(), sessions_exports)).then(
|
|
12266
13238
|
({ pruneSessions: pruneSessions2 }) => pruneSessions2().then((removed) => {
|
|
@@ -12286,7 +13258,7 @@ function App({
|
|
|
12286
13258
|
}
|
|
12287
13259
|
});
|
|
12288
13260
|
if (cfg.memoryEnabled) {
|
|
12289
|
-
const dbPath = cfg.memoryDbPath ??
|
|
13261
|
+
const dbPath = cfg.memoryDbPath ?? join22(process.cwd(), ".kimiflare", "memory.db");
|
|
12290
13262
|
const manager = new MemoryManager({
|
|
12291
13263
|
dbPath,
|
|
12292
13264
|
accountId: cfg.accountId,
|
|
@@ -12354,7 +13326,7 @@ function App({
|
|
|
12354
13326
|
}
|
|
12355
13327
|
});
|
|
12356
13328
|
}, [cfg, setEvents]);
|
|
12357
|
-
|
|
13329
|
+
useEffect6(() => {
|
|
12358
13330
|
const id = setInterval(() => {
|
|
12359
13331
|
try {
|
|
12360
13332
|
performance.clearMarks();
|
|
@@ -12364,7 +13336,7 @@ function App({
|
|
|
12364
13336
|
}, 3e5);
|
|
12365
13337
|
return () => clearInterval(id);
|
|
12366
13338
|
}, []);
|
|
12367
|
-
const reloadCustomCommands =
|
|
13339
|
+
const reloadCustomCommands = useCallback2(async () => {
|
|
12368
13340
|
const { commands, warnings } = await loadCustomCommands(process.cwd());
|
|
12369
13341
|
customCommandsRef.current = commands;
|
|
12370
13342
|
setCustomCommandsVersion((v) => v + 1);
|
|
@@ -12379,7 +13351,7 @@ function App({
|
|
|
12379
13351
|
]);
|
|
12380
13352
|
}
|
|
12381
13353
|
}, [setEvents]);
|
|
12382
|
-
|
|
13354
|
+
useEffect6(() => {
|
|
12383
13355
|
if (!cfg || updateCheckedRef.current) return;
|
|
12384
13356
|
updateCheckedRef.current = true;
|
|
12385
13357
|
if (initialUpdateResult) {
|
|
@@ -12430,7 +13402,7 @@ function App({
|
|
|
12430
13402
|
}
|
|
12431
13403
|
});
|
|
12432
13404
|
}, [cfg, initialUpdateResult]);
|
|
12433
|
-
|
|
13405
|
+
useEffect6(() => {
|
|
12434
13406
|
modeRef.current = mode;
|
|
12435
13407
|
if (cacheStableRef.current) {
|
|
12436
13408
|
messagesRef.current[1] = {
|
|
@@ -12457,10 +13429,10 @@ function App({
|
|
|
12457
13429
|
executorRef.current.clearSessionPermissions();
|
|
12458
13430
|
}
|
|
12459
13431
|
}, [mode, cfg?.model]);
|
|
12460
|
-
|
|
13432
|
+
useEffect6(() => {
|
|
12461
13433
|
effortRef.current = effort;
|
|
12462
13434
|
}, [effort]);
|
|
12463
|
-
|
|
13435
|
+
useEffect6(() => {
|
|
12464
13436
|
if (!cfg) return;
|
|
12465
13437
|
const id = setInterval(() => {
|
|
12466
13438
|
void checkForUpdate().then((result) => {
|
|
@@ -12491,7 +13463,7 @@ function App({
|
|
|
12491
13463
|
}, 30 * 60 * 1e3);
|
|
12492
13464
|
return () => clearInterval(id);
|
|
12493
13465
|
}, [cfg]);
|
|
12494
|
-
const initMcp =
|
|
13466
|
+
const initMcp = useCallback2(async () => {
|
|
12495
13467
|
if (!cfg?.mcpServers || mcpInitRef.current) return;
|
|
12496
13468
|
mcpInitRef.current = true;
|
|
12497
13469
|
const manager = mcpManagerRef.current;
|
|
@@ -12552,7 +13524,7 @@ function App({
|
|
|
12552
13524
|
]);
|
|
12553
13525
|
}
|
|
12554
13526
|
}, [cfg]);
|
|
12555
|
-
const initLsp =
|
|
13527
|
+
const initLsp = useCallback2(async () => {
|
|
12556
13528
|
if (!cfg?.lspEnabled || !cfg?.lspServers || lspInitRef.current) {
|
|
12557
13529
|
if (lspInitRef.current) return;
|
|
12558
13530
|
if (!cfg?.lspEnabled) {
|
|
@@ -12615,7 +13587,7 @@ function App({
|
|
|
12615
13587
|
]);
|
|
12616
13588
|
}
|
|
12617
13589
|
}, [cfg]);
|
|
12618
|
-
|
|
13590
|
+
useEffect6(() => {
|
|
12619
13591
|
if (cfg && !mcpInitRef.current) {
|
|
12620
13592
|
void initMcp();
|
|
12621
13593
|
}
|
|
@@ -12623,7 +13595,7 @@ function App({
|
|
|
12623
13595
|
void initLsp();
|
|
12624
13596
|
}
|
|
12625
13597
|
}, [cfg, initMcp, initLsp]);
|
|
12626
|
-
const ensureSessionId =
|
|
13598
|
+
const ensureSessionId = useCallback2(() => {
|
|
12627
13599
|
if (sessionIdRef.current) return sessionIdRef.current;
|
|
12628
13600
|
const firstUser = messagesRef.current.find((m) => m.role === "user");
|
|
12629
13601
|
let firstText = "session";
|
|
@@ -12636,7 +13608,7 @@ function App({
|
|
|
12636
13608
|
sessionIdRef.current = makeSessionId(firstText);
|
|
12637
13609
|
return sessionIdRef.current;
|
|
12638
13610
|
}, []);
|
|
12639
|
-
const saveSessionSafe =
|
|
13611
|
+
const saveSessionSafe = useCallback2(async () => {
|
|
12640
13612
|
if (!cfg) return;
|
|
12641
13613
|
ensureSessionId();
|
|
12642
13614
|
try {
|
|
@@ -12653,7 +13625,7 @@ function App({
|
|
|
12653
13625
|
} catch {
|
|
12654
13626
|
}
|
|
12655
13627
|
}, [cfg, ensureSessionId]);
|
|
12656
|
-
const onIterationEnd =
|
|
13628
|
+
const onIterationEnd = useCallback2(
|
|
12657
13629
|
async (messages, signal) => {
|
|
12658
13630
|
if (signal.aborted) return messages;
|
|
12659
13631
|
if (!shouldCompact({ messages })) return messages;
|
|
@@ -12731,31 +13703,42 @@ function App({
|
|
|
12731
13703
|
},
|
|
12732
13704
|
[cfg]
|
|
12733
13705
|
);
|
|
12734
|
-
|
|
13706
|
+
useInput7((inputChar, key) => {
|
|
12735
13707
|
if (key.ctrl && inputChar === "c") {
|
|
12736
13708
|
const hadPerm = permResolveRef.current !== null;
|
|
13709
|
+
const hadLimit = limitResolveRef.current !== null;
|
|
12737
13710
|
if (hadPerm) {
|
|
12738
13711
|
permResolveRef.current("deny");
|
|
12739
13712
|
permResolveRef.current = null;
|
|
12740
13713
|
setPerm(null);
|
|
12741
13714
|
}
|
|
12742
|
-
if (
|
|
13715
|
+
if (hadLimit) {
|
|
13716
|
+
limitResolveRef.current("stop");
|
|
13717
|
+
limitResolveRef.current = null;
|
|
13718
|
+
setLimitModal(null);
|
|
13719
|
+
}
|
|
13720
|
+
if (busyRef.current && activeControllerRef.current) {
|
|
12743
13721
|
activeControllerRef.current.abort();
|
|
12744
13722
|
setQueue([]);
|
|
12745
13723
|
setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "(interrupted)" }]);
|
|
12746
|
-
} else if (!hadPerm) {
|
|
13724
|
+
} else if (!hadPerm && !hadLimit) {
|
|
12747
13725
|
void lspManagerRef.current.stopAll().finally(() => exit());
|
|
12748
13726
|
}
|
|
12749
13727
|
return;
|
|
12750
13728
|
}
|
|
12751
13729
|
if (key.escape) {
|
|
12752
|
-
const modalOpen = perm !== null || showHelpMenu || showLspWizard || showCommandList || commandWizard !== null || commandToDelete !== null || resumeSessions !== null;
|
|
12753
|
-
if (!modalOpen &&
|
|
13730
|
+
const modalOpen = perm !== null || limitModal !== null || showHelpMenu || showLspWizard || showCommandList || commandWizard !== null || commandToDelete !== null || resumeSessions !== null;
|
|
13731
|
+
if (!modalOpen && busyRef.current && activeControllerRef.current) {
|
|
12754
13732
|
if (permResolveRef.current) {
|
|
12755
13733
|
permResolveRef.current("deny");
|
|
12756
13734
|
permResolveRef.current = null;
|
|
12757
13735
|
setPerm(null);
|
|
12758
13736
|
}
|
|
13737
|
+
if (limitResolveRef.current) {
|
|
13738
|
+
limitResolveRef.current("stop");
|
|
13739
|
+
limitResolveRef.current = null;
|
|
13740
|
+
setLimitModal(null);
|
|
13741
|
+
}
|
|
12759
13742
|
activeControllerRef.current.abort();
|
|
12760
13743
|
setQueue([]);
|
|
12761
13744
|
setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "(interrupted)" }]);
|
|
@@ -12775,7 +13758,7 @@ function App({
|
|
|
12775
13758
|
return;
|
|
12776
13759
|
}
|
|
12777
13760
|
});
|
|
12778
|
-
const flushAssistantUpdates =
|
|
13761
|
+
const flushAssistantUpdates = useCallback2(() => {
|
|
12779
13762
|
flushTimeoutRef.current = null;
|
|
12780
13763
|
const pending = pendingTextRef.current;
|
|
12781
13764
|
if (pending.size === 0) return;
|
|
@@ -12793,7 +13776,7 @@ function App({
|
|
|
12793
13776
|
})
|
|
12794
13777
|
);
|
|
12795
13778
|
}, []);
|
|
12796
|
-
const updateAssistant =
|
|
13779
|
+
const updateAssistant = useCallback2(
|
|
12797
13780
|
(id, patch) => {
|
|
12798
13781
|
const result = patch({ text: "", reasoning: "" });
|
|
12799
13782
|
const assistantResult = result;
|
|
@@ -12822,7 +13805,7 @@ function App({
|
|
|
12822
13805
|
},
|
|
12823
13806
|
[flushAssistantUpdates]
|
|
12824
13807
|
);
|
|
12825
|
-
const updateTool =
|
|
13808
|
+
const updateTool = useCallback2(
|
|
12826
13809
|
(id, patch) => {
|
|
12827
13810
|
setEvents(
|
|
12828
13811
|
(evts) => evts.map(
|
|
@@ -12832,11 +13815,11 @@ function App({
|
|
|
12832
13815
|
},
|
|
12833
13816
|
[]
|
|
12834
13817
|
);
|
|
12835
|
-
const updateGatewayMeta =
|
|
13818
|
+
const updateGatewayMeta = useCallback2((meta) => {
|
|
12836
13819
|
gatewayMetaRef.current = meta;
|
|
12837
13820
|
setGatewayMeta(meta);
|
|
12838
13821
|
}, []);
|
|
12839
|
-
const runCompact =
|
|
13822
|
+
const runCompact = useCallback2(async () => {
|
|
12840
13823
|
if (!cfg) return;
|
|
12841
13824
|
if (busy) {
|
|
12842
13825
|
setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "can't compact while model is running" }]);
|
|
@@ -12921,40 +13904,23 @@ function App({
|
|
|
12921
13904
|
setTurnStartedAt(null);
|
|
12922
13905
|
activeControllerRef.current = null;
|
|
12923
13906
|
permResolveRef.current = null;
|
|
13907
|
+
limitResolveRef.current = null;
|
|
12924
13908
|
pendingToolCallsRef.current.clear();
|
|
12925
13909
|
}
|
|
12926
13910
|
}, [cfg, busy, saveSessionSafe]);
|
|
12927
|
-
const openResumePicker =
|
|
13911
|
+
const openResumePicker = useCallback2(async () => {
|
|
12928
13912
|
const sessions = await listSessions(200, process.cwd());
|
|
12929
13913
|
setResumeSessions(sessions);
|
|
12930
13914
|
}, []);
|
|
12931
|
-
const runInit =
|
|
13915
|
+
const runInit = useCallback2(async () => {
|
|
12932
13916
|
if (!cfg) return;
|
|
12933
13917
|
if (busy) {
|
|
12934
13918
|
setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "can't /init while model is running" }]);
|
|
12935
13919
|
return;
|
|
12936
13920
|
}
|
|
12937
13921
|
const cwd = process.cwd();
|
|
12938
|
-
const
|
|
12939
|
-
|
|
12940
|
-
const promptParts = [
|
|
12941
|
-
isRefresh ? `Regenerate ${existingName} at the repository root to refresh project context. If the file already exists, read it first and preserve anything still accurate, updating only what has changed.` : "Generate a KIMI.md at the repository root so future agents have project context.",
|
|
12942
|
-
"",
|
|
12943
|
-
"First, use the `glob`, `read`, and `grep` tools to understand the project: read `package.json`, the top-level `README.md` if present, the tsconfig / build config, and skim the top-level source directory structure.",
|
|
12944
|
-
isRefresh ? `Also read the existing ${existingName} so you know what to keep vs. update.` : null,
|
|
12945
|
-
"",
|
|
12946
|
-
"Then call the `write` tool to create `KIMI.md` at the repo root with these sections, terse (aim \u2264 100 lines total):",
|
|
12947
|
-
"",
|
|
12948
|
-
"- **Project** \u2014 one-line description + primary language/runtime.",
|
|
12949
|
-
"- **Build / test / run** \u2014 exact shell commands an agent should use.",
|
|
12950
|
-
"- **Layout** \u2014 key directories and what lives in each.",
|
|
12951
|
-
"- **Conventions** \u2014 naming, import style, file structure, commit style, anything surprising.",
|
|
12952
|
-
"- **Do / Don't** \u2014 quirks or rules future agents should know.",
|
|
12953
|
-
"",
|
|
12954
|
-
"Do not call `tasks_set` for this. Just read what you need, then write the file."
|
|
12955
|
-
];
|
|
12956
|
-
const prompt = promptParts.filter((p) => p !== null).join("\n");
|
|
12957
|
-
setEvents((e) => [...e, { kind: "user", key: mkKey(), text: isRefresh ? `/init (refreshing ${existingName})` : "/init" }]);
|
|
13922
|
+
const { prompt, targetFilename, isRefresh } = buildInitPrompt(cwd);
|
|
13923
|
+
setEvents((e) => [...e, { kind: "user", key: mkKey(), text: isRefresh ? `/init (refreshing ${targetFilename})` : "/init" }]);
|
|
12958
13924
|
messagesRef.current.push({ role: "user", content: sanitizeString(prompt) });
|
|
12959
13925
|
setBusy(true);
|
|
12960
13926
|
setTurnStartedAt(Date.now());
|
|
@@ -12986,13 +13952,15 @@ function App({
|
|
|
12986
13952
|
sessionId: ensureSessionId(),
|
|
12987
13953
|
memoryManager: memoryManagerRef.current,
|
|
12988
13954
|
codeMode: effectiveCodeMode,
|
|
13955
|
+
cloudMode: cfg.cloudMode,
|
|
13956
|
+
cloudToken: initialCloudToken,
|
|
12989
13957
|
onIterationEnd,
|
|
12990
13958
|
onFileChange: (path, content) => {
|
|
12991
13959
|
if (content) {
|
|
12992
13960
|
lspManagerRef.current.notifyChange(path, content);
|
|
12993
13961
|
} else {
|
|
12994
13962
|
void import("fs/promises").then(
|
|
12995
|
-
({ readFile:
|
|
13963
|
+
({ readFile: readFile17 }) => readFile17(path, "utf8").then((c) => lspManagerRef.current.notifyChange(path, c)).catch(() => {
|
|
12996
13964
|
})
|
|
12997
13965
|
);
|
|
12998
13966
|
}
|
|
@@ -13086,7 +14054,7 @@ function App({
|
|
|
13086
14054
|
})
|
|
13087
14055
|
}
|
|
13088
14056
|
});
|
|
13089
|
-
if (
|
|
14057
|
+
if (existsSync3(join22(cwd, "KIMI.md"))) {
|
|
13090
14058
|
if (cacheStableRef.current) {
|
|
13091
14059
|
messagesRef.current[1] = {
|
|
13092
14060
|
role: "system",
|
|
@@ -13141,10 +14109,11 @@ function App({
|
|
|
13141
14109
|
activeAsstIdRef.current = null;
|
|
13142
14110
|
activeControllerRef.current = null;
|
|
13143
14111
|
permResolveRef.current = null;
|
|
14112
|
+
limitResolveRef.current = null;
|
|
13144
14113
|
pendingToolCallsRef.current.clear();
|
|
13145
14114
|
}
|
|
13146
14115
|
}, [cfg, busy, updateAssistant, updateTool, updateGatewayMeta]);
|
|
13147
|
-
const handleThemePick =
|
|
14116
|
+
const handleThemePick = useCallback2(
|
|
13148
14117
|
(picked) => {
|
|
13149
14118
|
setShowThemePicker(false);
|
|
13150
14119
|
setOriginalTheme(null);
|
|
@@ -13163,7 +14132,7 @@ function App({
|
|
|
13163
14132
|
},
|
|
13164
14133
|
[cfg, originalTheme]
|
|
13165
14134
|
);
|
|
13166
|
-
const handleResumePick =
|
|
14135
|
+
const handleResumePick = useCallback2(
|
|
13167
14136
|
async (picked) => {
|
|
13168
14137
|
setResumeSessions(null);
|
|
13169
14138
|
if (!picked) return;
|
|
@@ -13221,7 +14190,7 @@ function App({
|
|
|
13221
14190
|
},
|
|
13222
14191
|
[]
|
|
13223
14192
|
);
|
|
13224
|
-
const handleSlash =
|
|
14193
|
+
const handleSlash = useCallback2(
|
|
13225
14194
|
(cmd) => {
|
|
13226
14195
|
const raw = cmd.trim();
|
|
13227
14196
|
const [head, ...rest] = raw.split(/\s+/);
|
|
@@ -13315,6 +14284,10 @@ function App({
|
|
|
13315
14284
|
setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "no config loaded" }]);
|
|
13316
14285
|
return true;
|
|
13317
14286
|
}
|
|
14287
|
+
if (cfg.cloudMode) {
|
|
14288
|
+
setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "AI Gateway is managed by Kimiflare Cloud" }]);
|
|
14289
|
+
return true;
|
|
14290
|
+
}
|
|
13318
14291
|
const sub = rest[0]?.toLowerCase() ?? "";
|
|
13319
14292
|
const subArg = rest.slice(1).join(" ").trim();
|
|
13320
14293
|
if (!sub || sub === "status") {
|
|
@@ -13703,7 +14676,7 @@ ${lines.join("\n")}` }]);
|
|
|
13703
14676
|
if (c === "/hello") {
|
|
13704
14677
|
const session = crypto.randomUUID();
|
|
13705
14678
|
const url = `${FEEDBACK_WORKER_URL}/?s=${session}&v=${getAppVersion()}`;
|
|
13706
|
-
|
|
14679
|
+
openBrowser2(url);
|
|
13707
14680
|
setEvents((e) => [
|
|
13708
14681
|
...e,
|
|
13709
14682
|
{ kind: "info", key: mkKey(), text: "Opened voice note page in your browser. Record your message there and hit Send when you're done." }
|
|
@@ -13828,7 +14801,7 @@ ${lines.join("\n")}` }]);
|
|
|
13828
14801
|
setEvents((e) => [
|
|
13829
14802
|
...e,
|
|
13830
14803
|
{ kind: "info", key: mkKey(), text: `Starting remote session for ${repo.owner}/${repo.name}...` },
|
|
13831
|
-
{ kind: "info", key: mkKey(), text: `Budget: ${
|
|
14804
|
+
{ kind: "info", key: mkKey(), text: `Budget: ${formatTokens4(budget)} tokens. TTL: ${ttl} min.` }
|
|
13832
14805
|
]);
|
|
13833
14806
|
try {
|
|
13834
14807
|
const data = await startRemoteSession({
|
|
@@ -13916,7 +14889,7 @@ ${lines.join("\n")}` }]);
|
|
|
13916
14889
|
},
|
|
13917
14890
|
[cfg, exit, usage, effort, theme, mode, openResumePicker, runCompact, runInit, initMcp, setCfg, setShowRemoteDashboard, setSelectedRemoteSession]
|
|
13918
14891
|
);
|
|
13919
|
-
const handleHelpCommand =
|
|
14892
|
+
const handleHelpCommand = useCallback2(
|
|
13920
14893
|
(command) => {
|
|
13921
14894
|
setShowHelpMenu(false);
|
|
13922
14895
|
const executed = handleSlash(command);
|
|
@@ -13926,7 +14899,7 @@ ${lines.join("\n")}` }]);
|
|
|
13926
14899
|
},
|
|
13927
14900
|
[handleSlash]
|
|
13928
14901
|
);
|
|
13929
|
-
const handleCommandSave =
|
|
14902
|
+
const handleCommandSave = useCallback2(
|
|
13930
14903
|
async (opts2) => {
|
|
13931
14904
|
setCommandWizard(null);
|
|
13932
14905
|
try {
|
|
@@ -13948,7 +14921,7 @@ ${lines.join("\n")}` }]);
|
|
|
13948
14921
|
},
|
|
13949
14922
|
[commandWizard, reloadCustomCommands, setEvents]
|
|
13950
14923
|
);
|
|
13951
|
-
const handleCommandDelete =
|
|
14924
|
+
const handleCommandDelete = useCallback2(
|
|
13952
14925
|
async (cmd) => {
|
|
13953
14926
|
setCommandToDelete(null);
|
|
13954
14927
|
try {
|
|
@@ -13967,7 +14940,7 @@ ${lines.join("\n")}` }]);
|
|
|
13967
14940
|
},
|
|
13968
14941
|
[reloadCustomCommands, setEvents]
|
|
13969
14942
|
);
|
|
13970
|
-
const processMessage =
|
|
14943
|
+
const processMessage = useCallback2(
|
|
13971
14944
|
async (text, displayText) => {
|
|
13972
14945
|
if (!cfg) return;
|
|
13973
14946
|
let trimmed = text.trim();
|
|
@@ -14166,6 +15139,10 @@ ${lines.join("\n")}` }]);
|
|
|
14166
15139
|
}
|
|
14167
15140
|
permResolveRef.current = resolve2;
|
|
14168
15141
|
setPerm({ tool: req.tool, args: req.args, resolve: resolve2 });
|
|
15142
|
+
}),
|
|
15143
|
+
onToolLimitReached: () => new Promise((resolve2) => {
|
|
15144
|
+
limitResolveRef.current = resolve2;
|
|
15145
|
+
setLimitModal({ limit: 50, resolve: resolve2 });
|
|
14169
15146
|
})
|
|
14170
15147
|
};
|
|
14171
15148
|
try {
|
|
@@ -14185,6 +15162,8 @@ ${lines.join("\n")}` }]);
|
|
|
14185
15162
|
memoryManager: memoryManagerRef.current,
|
|
14186
15163
|
keepLastImageTurns: cfg.imageHistoryTurns ?? 2,
|
|
14187
15164
|
codeMode: effectiveCodeMode,
|
|
15165
|
+
cloudMode: cfg.cloudMode,
|
|
15166
|
+
cloudToken: initialCloudToken,
|
|
14188
15167
|
onIterationEnd,
|
|
14189
15168
|
intentClassification: classification,
|
|
14190
15169
|
onFileChange: (path, content2) => {
|
|
@@ -14192,7 +15171,7 @@ ${lines.join("\n")}` }]);
|
|
|
14192
15171
|
lspManagerRef.current.notifyChange(path, content2);
|
|
14193
15172
|
} else {
|
|
14194
15173
|
void import("fs/promises").then(
|
|
14195
|
-
({ readFile:
|
|
15174
|
+
({ readFile: readFile17 }) => readFile17(path, "utf8").then((c) => lspManagerRef.current.notifyChange(path, c)).catch(() => {
|
|
14196
15175
|
})
|
|
14197
15176
|
);
|
|
14198
15177
|
}
|
|
@@ -14253,6 +15232,8 @@ ${lines.join("\n")}` }]);
|
|
|
14253
15232
|
text: `auto-compact failed: ${compactErr.message ?? String(compactErr)}`
|
|
14254
15233
|
}
|
|
14255
15234
|
]);
|
|
15235
|
+
} else {
|
|
15236
|
+
throw compactErr;
|
|
14256
15237
|
}
|
|
14257
15238
|
}
|
|
14258
15239
|
}
|
|
@@ -14322,19 +15303,20 @@ ${lines.join("\n")}` }]);
|
|
|
14322
15303
|
activeAsstIdRef.current = null;
|
|
14323
15304
|
activeControllerRef.current = null;
|
|
14324
15305
|
permResolveRef.current = null;
|
|
15306
|
+
limitResolveRef.current = null;
|
|
14325
15307
|
pendingToolCallsRef.current.clear();
|
|
14326
15308
|
}
|
|
14327
15309
|
},
|
|
14328
15310
|
[cfg, handleSlash, updateAssistant, updateTool, saveSessionSafe, updateGatewayMeta]
|
|
14329
15311
|
);
|
|
14330
|
-
|
|
15312
|
+
useEffect6(() => {
|
|
14331
15313
|
if (!busy && queue.length > 0) {
|
|
14332
15314
|
const next = queue[0];
|
|
14333
15315
|
setQueue((q) => q.slice(1));
|
|
14334
15316
|
processMessage(next.full, next.display);
|
|
14335
15317
|
}
|
|
14336
15318
|
}, [busy, queue, processMessage]);
|
|
14337
|
-
const submit =
|
|
15319
|
+
const submit = useCallback2(
|
|
14338
15320
|
(full, display) => {
|
|
14339
15321
|
const trimmedFull = full.trim();
|
|
14340
15322
|
if (!trimmedFull) return;
|
|
@@ -14355,7 +15337,7 @@ ${lines.join("\n")}` }]);
|
|
|
14355
15337
|
[busy, processMessage]
|
|
14356
15338
|
);
|
|
14357
15339
|
submitRef.current = submit;
|
|
14358
|
-
|
|
15340
|
+
useEffect6(() => {
|
|
14359
15341
|
if (compactSuggestedRef.current) return;
|
|
14360
15342
|
if (usage && usage.prompt_tokens / CONTEXT_LIMIT >= AUTO_COMPACT_SUGGEST_PCT) {
|
|
14361
15343
|
compactSuggestedRef.current = true;
|
|
@@ -14370,24 +15352,41 @@ ${lines.join("\n")}` }]);
|
|
|
14370
15352
|
}
|
|
14371
15353
|
}, [usage]);
|
|
14372
15354
|
if (!cfg) {
|
|
14373
|
-
return /* @__PURE__ */
|
|
15355
|
+
return /* @__PURE__ */ jsx23(ThemeProvider, { theme, children: /* @__PURE__ */ jsx23(
|
|
14374
15356
|
Onboarding,
|
|
14375
15357
|
{
|
|
14376
|
-
|
|
15358
|
+
onCancel: () => exit(),
|
|
15359
|
+
onDone: async (newCfg) => {
|
|
14377
15360
|
setCfg(newCfg);
|
|
14378
|
-
|
|
14379
|
-
|
|
14380
|
-
|
|
14381
|
-
|
|
15361
|
+
if (newCfg.cloudMode) {
|
|
15362
|
+
const { loadCloudCredentials: loadCloudCredentials2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
|
|
15363
|
+
const creds = await loadCloudCredentials2();
|
|
15364
|
+
if (creds) {
|
|
15365
|
+
setEvents((e) => [
|
|
15366
|
+
...e,
|
|
15367
|
+
{ kind: "info", key: mkKey(), text: "configuration saved \u2014 welcome to kimiflare! (cloud mode)" }
|
|
15368
|
+
]);
|
|
15369
|
+
} else {
|
|
15370
|
+
setEvents((e) => [
|
|
15371
|
+
...e,
|
|
15372
|
+
{ kind: "info", key: mkKey(), text: "cloud mode configured \u2014 run `kimiflare auth cloud` to sign in" }
|
|
15373
|
+
]);
|
|
15374
|
+
}
|
|
15375
|
+
} else {
|
|
15376
|
+
setEvents((e) => [
|
|
15377
|
+
...e,
|
|
15378
|
+
{ kind: "info", key: mkKey(), text: "configuration saved \u2014 welcome to kimiflare!" }
|
|
15379
|
+
]);
|
|
15380
|
+
}
|
|
14382
15381
|
}
|
|
14383
15382
|
}
|
|
14384
15383
|
) });
|
|
14385
15384
|
}
|
|
14386
15385
|
if (resumeSessions !== null) {
|
|
14387
|
-
return /* @__PURE__ */
|
|
15386
|
+
return /* @__PURE__ */ jsx23(ThemeProvider, { theme, children: /* @__PURE__ */ jsx23(Box21, { flexDirection: "column", children: /* @__PURE__ */ jsx23(ResumePicker, { sessions: resumeSessions, onPick: handleResumePick }) }) });
|
|
14388
15387
|
}
|
|
14389
15388
|
if (showRemoteDashboard) {
|
|
14390
|
-
return /* @__PURE__ */
|
|
15389
|
+
return /* @__PURE__ */ jsx23(ThemeProvider, { theme, children: /* @__PURE__ */ jsx23(Box21, { flexDirection: "column", children: selectedRemoteSession ? /* @__PURE__ */ jsx23(
|
|
14391
15390
|
RemoteSessionDetail,
|
|
14392
15391
|
{
|
|
14393
15392
|
session: selectedRemoteSession,
|
|
@@ -14410,7 +15409,7 @@ ${lines.join("\n")}` }]);
|
|
|
14410
15409
|
setShowRemoteDashboard(false);
|
|
14411
15410
|
}
|
|
14412
15411
|
}
|
|
14413
|
-
) : /* @__PURE__ */
|
|
15412
|
+
) : /* @__PURE__ */ jsx23(
|
|
14414
15413
|
RemoteDashboard,
|
|
14415
15414
|
{
|
|
14416
15415
|
onSelect: (session) => setSelectedRemoteSession(session),
|
|
@@ -14419,23 +15418,24 @@ ${lines.join("\n")}` }]);
|
|
|
14419
15418
|
) }) });
|
|
14420
15419
|
}
|
|
14421
15420
|
if (showHelpMenu) {
|
|
14422
|
-
return /* @__PURE__ */
|
|
15421
|
+
return /* @__PURE__ */ jsx23(ThemeProvider, { theme, children: /* @__PURE__ */ jsx23(Box21, { flexDirection: "column", children: /* @__PURE__ */ jsx23(
|
|
14423
15422
|
HelpMenu,
|
|
14424
15423
|
{
|
|
14425
15424
|
customCommands: customCommandsRef.current.filter((c) => !BUILTIN_COMMAND_NAMES.has(c.name.toLowerCase())).map((c) => ({ name: c.name, description: c.description })),
|
|
14426
15425
|
costAttributionEnabled: cfg?.costAttribution,
|
|
15426
|
+
cloudMode: cfg?.cloudMode,
|
|
14427
15427
|
onDone: () => setShowHelpMenu(false),
|
|
14428
15428
|
onCommand: handleHelpCommand
|
|
14429
15429
|
}
|
|
14430
15430
|
) }) });
|
|
14431
15431
|
}
|
|
14432
15432
|
if (showLspWizard) {
|
|
14433
|
-
return /* @__PURE__ */
|
|
15433
|
+
return /* @__PURE__ */ jsx23(ThemeProvider, { theme, children: /* @__PURE__ */ jsx23(Box21, { flexDirection: "column", children: /* @__PURE__ */ jsx23(
|
|
14434
15434
|
LspWizard,
|
|
14435
15435
|
{
|
|
14436
15436
|
servers: cfg?.lspServers ?? {},
|
|
14437
15437
|
currentScope: lspScope,
|
|
14438
|
-
hasProjectDir:
|
|
15438
|
+
hasProjectDir: existsSync3(join22(process.cwd(), ".kimiflare")),
|
|
14439
15439
|
onDone: () => setShowLspWizard(false),
|
|
14440
15440
|
onSave: (servers, enabled, scope) => {
|
|
14441
15441
|
setCfg((c) => c ? { ...c, lspEnabled: enabled, lspServers: servers } : c);
|
|
@@ -14467,7 +15467,7 @@ ${lines.join("\n")}` }]);
|
|
|
14467
15467
|
) }) });
|
|
14468
15468
|
}
|
|
14469
15469
|
if (commandWizard) {
|
|
14470
|
-
return /* @__PURE__ */
|
|
15470
|
+
return /* @__PURE__ */ jsx23(ThemeProvider, { theme, children: /* @__PURE__ */ jsx23(Box21, { flexDirection: "column", children: /* @__PURE__ */ jsx23(
|
|
14471
15471
|
CommandWizard,
|
|
14472
15472
|
{
|
|
14473
15473
|
mode: commandWizard.mode,
|
|
@@ -14480,7 +15480,7 @@ ${lines.join("\n")}` }]);
|
|
|
14480
15480
|
) }) });
|
|
14481
15481
|
}
|
|
14482
15482
|
if (commandPicker) {
|
|
14483
|
-
return /* @__PURE__ */
|
|
15483
|
+
return /* @__PURE__ */ jsx23(ThemeProvider, { theme, children: /* @__PURE__ */ jsx23(Box21, { flexDirection: "column", children: /* @__PURE__ */ jsx23(
|
|
14484
15484
|
CommandPicker,
|
|
14485
15485
|
{
|
|
14486
15486
|
commands: customCommandsRef.current,
|
|
@@ -14498,15 +15498,15 @@ ${lines.join("\n")}` }]);
|
|
|
14498
15498
|
) }) });
|
|
14499
15499
|
}
|
|
14500
15500
|
if (commandToDelete) {
|
|
14501
|
-
return /* @__PURE__ */
|
|
14502
|
-
/* @__PURE__ */
|
|
15501
|
+
return /* @__PURE__ */ jsx23(ThemeProvider, { theme, children: /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
15502
|
+
/* @__PURE__ */ jsxs21(Text22, { color: theme.accent, bold: true, children: [
|
|
14503
15503
|
"Delete /",
|
|
14504
15504
|
commandToDelete.name,
|
|
14505
15505
|
"?"
|
|
14506
15506
|
] }),
|
|
14507
|
-
/* @__PURE__ */
|
|
14508
|
-
/* @__PURE__ */
|
|
14509
|
-
|
|
15507
|
+
/* @__PURE__ */ jsx23(Text22, { color: theme.info.color, children: commandToDelete.filepath }),
|
|
15508
|
+
/* @__PURE__ */ jsx23(Box21, { marginTop: 1, children: /* @__PURE__ */ jsx23(
|
|
15509
|
+
SelectInput11,
|
|
14510
15510
|
{
|
|
14511
15511
|
items: [
|
|
14512
15512
|
{ label: "Yes, delete", value: "yes", key: "yes" },
|
|
@@ -14524,7 +15524,7 @@ ${lines.join("\n")}` }]);
|
|
|
14524
15524
|
] }) });
|
|
14525
15525
|
}
|
|
14526
15526
|
if (showCommandList) {
|
|
14527
|
-
return /* @__PURE__ */
|
|
15527
|
+
return /* @__PURE__ */ jsx23(ThemeProvider, { theme, children: /* @__PURE__ */ jsx23(Box21, { flexDirection: "column", children: /* @__PURE__ */ jsx23(
|
|
14528
15528
|
CommandList,
|
|
14529
15529
|
{
|
|
14530
15530
|
commands: customCommandsRef.current,
|
|
@@ -14533,12 +15533,12 @@ ${lines.join("\n")}` }]);
|
|
|
14533
15533
|
) }) });
|
|
14534
15534
|
}
|
|
14535
15535
|
if (showThemePicker) {
|
|
14536
|
-
return /* @__PURE__ */
|
|
15536
|
+
return /* @__PURE__ */ jsx23(ThemeProvider, { theme, children: /* @__PURE__ */ jsx23(Box21, { flexDirection: "column", children: /* @__PURE__ */ jsx23(ThemePicker, { themes: themeList(), onPick: handleThemePick, onPreview: (t) => setTheme(t) }) }) });
|
|
14537
15537
|
}
|
|
14538
15538
|
const hasConversation = events.some((e) => e.kind === "user" || e.kind === "assistant");
|
|
14539
|
-
return /* @__PURE__ */
|
|
14540
|
-
!hasConversation && events.length === 0 ? /* @__PURE__ */
|
|
14541
|
-
perm ? /* @__PURE__ */
|
|
15539
|
+
return /* @__PURE__ */ jsx23(ThemeProvider, { theme, children: /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", children: [
|
|
15540
|
+
!hasConversation && events.length === 0 ? /* @__PURE__ */ jsx23(Welcome, { accountId: cfg.accountId }) : /* @__PURE__ */ jsx23(ChatView, { events, showReasoning, verbose }),
|
|
15541
|
+
perm ? /* @__PURE__ */ jsx23(
|
|
14542
15542
|
PermissionModal,
|
|
14543
15543
|
{
|
|
14544
15544
|
tool: perm.tool,
|
|
@@ -14549,8 +15549,18 @@ ${lines.join("\n")}` }]);
|
|
|
14549
15549
|
setPerm(null);
|
|
14550
15550
|
}
|
|
14551
15551
|
}
|
|
14552
|
-
) : /* @__PURE__ */
|
|
14553
|
-
|
|
15552
|
+
) : limitModal ? /* @__PURE__ */ jsx23(
|
|
15553
|
+
LimitModal,
|
|
15554
|
+
{
|
|
15555
|
+
limit: limitModal.limit,
|
|
15556
|
+
onDecide: (d) => {
|
|
15557
|
+
limitModal.resolve(d);
|
|
15558
|
+
limitResolveRef.current = null;
|
|
15559
|
+
setLimitModal(null);
|
|
15560
|
+
}
|
|
15561
|
+
}
|
|
15562
|
+
) : /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", marginTop: 1, children: [
|
|
15563
|
+
tasks.length > 0 && /* @__PURE__ */ jsx23(
|
|
14554
15564
|
TaskList,
|
|
14555
15565
|
{
|
|
14556
15566
|
tasks,
|
|
@@ -14558,11 +15568,11 @@ ${lines.join("\n")}` }]);
|
|
|
14558
15568
|
tokensDelta: Math.max(0, (usage?.prompt_tokens ?? 0) - tasksStartTokens)
|
|
14559
15569
|
}
|
|
14560
15570
|
),
|
|
14561
|
-
queue.length > 0 && /* @__PURE__ */
|
|
15571
|
+
queue.length > 0 && /* @__PURE__ */ jsx23(Box21, { flexDirection: "column", marginBottom: 1, children: queue.map((q, i) => /* @__PURE__ */ jsxs21(Text22, { color: theme.info.color, children: [
|
|
14562
15572
|
"\u23F3 ",
|
|
14563
15573
|
q.display
|
|
14564
15574
|
] }, `queue_${i}`)) }),
|
|
14565
|
-
/* @__PURE__ */
|
|
15575
|
+
/* @__PURE__ */ jsx23(
|
|
14566
15576
|
StatusBar,
|
|
14567
15577
|
{
|
|
14568
15578
|
model: cfg.model,
|
|
@@ -14576,10 +15586,12 @@ ${lines.join("\n")}` }]);
|
|
|
14576
15586
|
hasUpdate,
|
|
14577
15587
|
latestVersion,
|
|
14578
15588
|
gatewayMeta,
|
|
14579
|
-
codeMode
|
|
15589
|
+
codeMode,
|
|
15590
|
+
cloudMode: cfg.cloudMode,
|
|
15591
|
+
cloudBudget
|
|
14580
15592
|
}
|
|
14581
15593
|
),
|
|
14582
|
-
activePicker?.kind === "file" && /* @__PURE__ */
|
|
15594
|
+
activePicker?.kind === "file" && /* @__PURE__ */ jsx23(
|
|
14583
15595
|
FilePicker,
|
|
14584
15596
|
{
|
|
14585
15597
|
items: filteredFileItems,
|
|
@@ -14587,7 +15599,7 @@ ${lines.join("\n")}` }]);
|
|
|
14587
15599
|
query: pickerQuery ?? ""
|
|
14588
15600
|
}
|
|
14589
15601
|
),
|
|
14590
|
-
activePicker?.kind === "slash" && /* @__PURE__ */
|
|
15602
|
+
activePicker?.kind === "slash" && /* @__PURE__ */ jsx23(
|
|
14591
15603
|
SlashPicker,
|
|
14592
15604
|
{
|
|
14593
15605
|
items: filteredSlashItems,
|
|
@@ -14595,9 +15607,9 @@ ${lines.join("\n")}` }]);
|
|
|
14595
15607
|
query: pickerQuery ?? ""
|
|
14596
15608
|
}
|
|
14597
15609
|
),
|
|
14598
|
-
/* @__PURE__ */
|
|
14599
|
-
/* @__PURE__ */
|
|
14600
|
-
/* @__PURE__ */
|
|
15610
|
+
/* @__PURE__ */ jsxs21(Box21, { marginTop: 1, children: [
|
|
15611
|
+
/* @__PURE__ */ jsx23(Text22, { color: "#d699b6", children: "\u203A " }),
|
|
15612
|
+
/* @__PURE__ */ jsx23(
|
|
14601
15613
|
CustomTextInput,
|
|
14602
15614
|
{
|
|
14603
15615
|
value: input,
|
|
@@ -14652,15 +15664,16 @@ ${lines.join("\n")}` }]);
|
|
|
14652
15664
|
] })
|
|
14653
15665
|
] }) });
|
|
14654
15666
|
}
|
|
14655
|
-
async function renderApp(cfg, updateResult, lspScope = "global", lspProjectPath = null) {
|
|
15667
|
+
async function renderApp(cfg, updateResult, lspScope = "global", lspProjectPath = null, cloudToken) {
|
|
14656
15668
|
const instance = render(
|
|
14657
|
-
/* @__PURE__ */
|
|
15669
|
+
/* @__PURE__ */ jsx23(
|
|
14658
15670
|
App,
|
|
14659
15671
|
{
|
|
14660
15672
|
initialCfg: cfg,
|
|
14661
15673
|
initialUpdateResult: updateResult,
|
|
14662
15674
|
initialLspScope: lspScope,
|
|
14663
|
-
initialLspProjectPath: lspProjectPath
|
|
15675
|
+
initialLspProjectPath: lspProjectPath,
|
|
15676
|
+
initialCloudToken: cloudToken
|
|
14664
15677
|
}
|
|
14665
15678
|
),
|
|
14666
15679
|
{
|
|
@@ -14687,6 +15700,7 @@ var init_app = __esm({
|
|
|
14687
15700
|
init_chat();
|
|
14688
15701
|
init_status();
|
|
14689
15702
|
init_permission();
|
|
15703
|
+
init_limit_modal();
|
|
14690
15704
|
init_resume_picker();
|
|
14691
15705
|
init_task_list();
|
|
14692
15706
|
init_text_input();
|
|
@@ -14714,6 +15728,7 @@ var init_app = __esm({
|
|
|
14714
15728
|
init_builtins();
|
|
14715
15729
|
init_save();
|
|
14716
15730
|
init_command_wizard();
|
|
15731
|
+
init_context_generator();
|
|
14717
15732
|
init_command_picker();
|
|
14718
15733
|
init_command_list();
|
|
14719
15734
|
init_lsp_wizard();
|
|
@@ -14851,7 +15866,7 @@ function createRemoteCommand() {
|
|
|
14851
15866
|
|
|
14852
15867
|
// src/index.tsx
|
|
14853
15868
|
var program = new Command2();
|
|
14854
|
-
program.name("kimiflare").description("Terminal coding agent powered by Kimi-K2.6 on Cloudflare Workers AI.").version(getAppVersion()).option("-p, --print <prompt>", "one-shot mode: send prompt, stream reply to stdout, exit").option("-m, --model <id>", "model id (defaults to @cf/moonshotai/kimi-k2.6)").option("--dangerously-allow-all", "auto-approve every permission prompt (print mode only)").option("--reasoning", "include reasoning in stdout (print mode only)").option("--continue-on-limit", "reset tool-call counter and continue when the 50-call limit is hit (print mode only)").option("--max-input-tokens <n>", "cumulative prompt token budget; exits 42 when exhausted (print mode only)", (v) => parseInt(v, 10));
|
|
15869
|
+
program.name("kimiflare").description("Terminal coding agent powered by Kimi-K2.6 on Cloudflare Workers AI.").version(getAppVersion()).option("-p, --print <prompt>", "one-shot mode: send prompt, stream reply to stdout, exit").option("-m, --model <id>", "model id (defaults to @cf/moonshotai/kimi-k2.6)").option("--cloud", "use Kimiflare Cloud (api.kimiflare.com) instead of direct Workers AI").option("--dangerously-allow-all", "auto-approve every permission prompt (print mode only)").option("--reasoning", "include reasoning in stdout (print mode only)").option("--continue-on-limit", "reset tool-call counter and continue when the 50-call limit is hit (print mode only)").option("--max-input-tokens <n>", "cumulative prompt token budget; exits 42 when exhausted (print mode only)", (v) => parseInt(v, 10));
|
|
14855
15870
|
program.command("cost").description("Show cost attribution by task type (requires costAttribution enabled)").option("-w, --week", "last 7 days (default)").option("-m, --month", "last 30 days").option("-d, --day", "today only").option("-s, --session <id>", "single session detail").option("-c, --category <name>", "filter by category").option("--json", "machine-readable output").option("--reclassify", "re-run classification on all sessions").option("--local-only", "skip Cloudflare reconciliation").action(async (cmdOpts) => {
|
|
14856
15871
|
const cfg = await loadConfig();
|
|
14857
15872
|
const enabled = cfg?.costAttribution ?? false;
|
|
@@ -14864,6 +15879,25 @@ program.command("cost").description("Show cost attribution by task type (require
|
|
|
14864
15879
|
const { runCostCommand: runCostCommand2 } = await Promise.resolve().then(() => (init_cli(), cli_exports));
|
|
14865
15880
|
await runCostCommand2({ ...cmdOpts, config: cfg });
|
|
14866
15881
|
});
|
|
15882
|
+
program.command("usage").description("Show Kimiflare Cloud token usage (requires cloud authentication)").action(async () => {
|
|
15883
|
+
const { loadCloudCredentials: loadCloudCredentials2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
|
|
15884
|
+
const creds = await loadCloudCredentials2();
|
|
15885
|
+
if (!creds) {
|
|
15886
|
+
console.error("Not authenticated with Kimiflare Cloud. Run: kimiflare auth cloud");
|
|
15887
|
+
process.exit(1);
|
|
15888
|
+
}
|
|
15889
|
+
const res = await fetch("https://api.kimiflare.com/v1/usage", {
|
|
15890
|
+
headers: { Authorization: `Bearer ${creds.accessToken}` }
|
|
15891
|
+
});
|
|
15892
|
+
if (!res.ok) {
|
|
15893
|
+
console.error(`Failed to fetch usage: ${res.status} ${res.statusText}`);
|
|
15894
|
+
process.exit(1);
|
|
15895
|
+
}
|
|
15896
|
+
const usage = await res.json();
|
|
15897
|
+
console.log(`Token budget: ${usage.remaining.toLocaleString()} / ${usage.input_token_limit.toLocaleString()} remaining`);
|
|
15898
|
+
console.log(`Used: ${usage.input_tokens_used.toLocaleString()}`);
|
|
15899
|
+
console.log(`Grant expires: ${usage.expires_at}`);
|
|
15900
|
+
});
|
|
14867
15901
|
program.addCommand(createRemoteCommand());
|
|
14868
15902
|
program.command("auth").description("Authenticate with external services").addCommand(
|
|
14869
15903
|
new Command2("github").description("Authenticate with GitHub via OAuth device flow").action(async () => {
|
|
@@ -14880,6 +15914,37 @@ Open: ${step.url}`);
|
|
|
14880
15914
|
if (step.error) process.exit(1);
|
|
14881
15915
|
}
|
|
14882
15916
|
})
|
|
15917
|
+
).addCommand(
|
|
15918
|
+
new Command2("cloud").description("Authenticate with Kimiflare Cloud").action(async () => {
|
|
15919
|
+
const { authenticateDevice: authenticateDevice2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
|
|
15920
|
+
try {
|
|
15921
|
+
const creds = await authenticateDevice2(({ url, userCode, polling }) => {
|
|
15922
|
+
if (!polling) {
|
|
15923
|
+
console.log(`
|
|
15924
|
+
Kimiflare Cloud Authentication`);
|
|
15925
|
+
console.log(`
|
|
15926
|
+
1. Open this URL in your browser:`);
|
|
15927
|
+
console.log(` ${url}`);
|
|
15928
|
+
console.log(`
|
|
15929
|
+
2. Sign in with GitHub
|
|
15930
|
+
`);
|
|
15931
|
+
}
|
|
15932
|
+
});
|
|
15933
|
+
console.log(`Authenticated! Token expires at ${new Date(creds.expiresAt * 1e3).toISOString()}`);
|
|
15934
|
+
const usageRes = await fetch("https://api.kimiflare.com/v1/usage", {
|
|
15935
|
+
headers: { Authorization: `Bearer ${creds.accessToken}` }
|
|
15936
|
+
});
|
|
15937
|
+
if (usageRes.ok) {
|
|
15938
|
+
const usage = await usageRes.json();
|
|
15939
|
+
console.log(`
|
|
15940
|
+
Token budget: ${usage.remaining.toLocaleString()} / ${usage.input_token_limit.toLocaleString()} remaining`);
|
|
15941
|
+
console.log(`Grant expires: ${usage.expires_at}`);
|
|
15942
|
+
}
|
|
15943
|
+
} catch (err) {
|
|
15944
|
+
console.error("Authentication failed:", err instanceof Error ? err.message : String(err));
|
|
15945
|
+
process.exit(1);
|
|
15946
|
+
}
|
|
15947
|
+
})
|
|
14883
15948
|
);
|
|
14884
15949
|
program.action(async () => {
|
|
14885
15950
|
await main();
|
|
@@ -14902,10 +15967,25 @@ async function main() {
|
|
|
14902
15967
|
lspScope = resolved.scope;
|
|
14903
15968
|
lspProjectPath = resolved.projectPath;
|
|
14904
15969
|
}
|
|
15970
|
+
const cloudMode = opts.cloud ?? cfg?.cloudMode ?? false;
|
|
15971
|
+
let cloudToken;
|
|
15972
|
+
if (cloudMode) {
|
|
15973
|
+
const { loadCloudCredentials: loadCloudCredentials2, authenticateDevice: authenticateDevice2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
|
|
15974
|
+
let cloudCreds = await loadCloudCredentials2();
|
|
15975
|
+
if (!cloudCreds) {
|
|
15976
|
+
console.error("kimiflare: cloud mode requires authentication.\nRun: kimiflare auth cloud\n");
|
|
15977
|
+
process.exit(2);
|
|
15978
|
+
}
|
|
15979
|
+
cloudToken = cloudCreds.accessToken;
|
|
15980
|
+
cfg = {
|
|
15981
|
+
...cfg ?? { accountId: "", apiToken: "", model: DEFAULT_MODEL },
|
|
15982
|
+
cloudMode: true
|
|
15983
|
+
};
|
|
15984
|
+
}
|
|
14905
15985
|
if (opts.print !== void 0) {
|
|
14906
15986
|
if (!cfg) {
|
|
14907
15987
|
console.error(
|
|
14908
|
-
'kimiflare: missing credentials.\nSet CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_API_TOKEN, or write them to\n ~/.config/kimiflare/config.json (chmod 600)\n { "accountId": "...", "apiToken": "...", "model": "@cf/moonshotai/kimi-k2.6" }'
|
|
15988
|
+
'kimiflare: missing credentials.\nSet CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_API_TOKEN, or write them to\n ~/.config/kimiflare/config.json (chmod 600)\n { "accountId": "...", "apiToken": "...", "model": "@cf/moonshotai/kimi-k2.6" }\nOr use cloud mode: kimiflare --cloud -p "..."'
|
|
14909
15989
|
);
|
|
14910
15990
|
process.exit(2);
|
|
14911
15991
|
}
|
|
@@ -14917,6 +15997,7 @@ async function main() {
|
|
|
14917
15997
|
allowAll: !!opts.dangerouslyAllowAll,
|
|
14918
15998
|
showReasoning: !!opts.reasoning,
|
|
14919
15999
|
codeMode: cfg.codeMode,
|
|
16000
|
+
cloudToken,
|
|
14920
16001
|
continueOnLimit: !!opts.continueOnLimit,
|
|
14921
16002
|
maxInputTokens: opts.maxInputTokens,
|
|
14922
16003
|
updateResult
|
|
@@ -14932,9 +16013,9 @@ async function main() {
|
|
|
14932
16013
|
const { renderApp: renderApp2 } = await Promise.resolve().then(() => (init_app(), app_exports));
|
|
14933
16014
|
if (cfg) {
|
|
14934
16015
|
const model = opts.model ?? cfg.model ?? DEFAULT_MODEL;
|
|
14935
|
-
await renderApp2({ ...cfg, model }, updateResult, lspScope, lspProjectPath);
|
|
16016
|
+
await renderApp2({ ...cfg, model }, updateResult, lspScope, lspProjectPath, cloudToken);
|
|
14936
16017
|
} else {
|
|
14937
|
-
await renderApp2(null, updateResult, lspScope, lspProjectPath);
|
|
16018
|
+
await renderApp2(null, updateResult, lspScope, lspProjectPath, cloudToken);
|
|
14938
16019
|
}
|
|
14939
16020
|
}
|
|
14940
16021
|
function gatewayFromPrintOpts(opts2) {
|
|
@@ -14948,6 +16029,10 @@ function gatewayFromPrintOpts(opts2) {
|
|
|
14948
16029
|
};
|
|
14949
16030
|
}
|
|
14950
16031
|
async function runPrintMode(opts2) {
|
|
16032
|
+
if (opts2.cloudMode) {
|
|
16033
|
+
process.stderr.write(`[cloud mode: api.kimiflare.com]
|
|
16034
|
+
`);
|
|
16035
|
+
}
|
|
14951
16036
|
if (opts2.updateResult.hasUpdate) {
|
|
14952
16037
|
process.stderr.write(
|
|
14953
16038
|
`\x1B[33mkimiflare update available: ${opts2.updateResult.localVersion} \u2192 ${opts2.updateResult.latestVersion}\x1B[0m
|
|
@@ -14980,6 +16065,8 @@ async function runPrintMode(opts2) {
|
|
|
14980
16065
|
codeMode: opts2.codeMode,
|
|
14981
16066
|
continueOnLimit: opts2.continueOnLimit,
|
|
14982
16067
|
maxInputTokens: opts2.maxInputTokens,
|
|
16068
|
+
cloudMode: opts2.cloudMode,
|
|
16069
|
+
cloudToken: opts2.cloudToken,
|
|
14983
16070
|
coauthor: opts2.coauthor !== false ? { name: opts2.coauthorName || "kimiflare", email: opts2.coauthorEmail || "kimiflare@proton.me" } : void 0,
|
|
14984
16071
|
callbacks: {
|
|
14985
16072
|
onReasoningDelta: opts2.showReasoning ? (delta) => {
|