kimiflare 0.32.0 → 0.34.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 +1792 -519
- package/dist/index.js.map +1 -1
- package/package.json +4 -1
package/dist/index.js
CHANGED
|
@@ -9,6 +9,15 @@ var __export = (target, all) => {
|
|
|
9
9
|
};
|
|
10
10
|
|
|
11
11
|
// src/config.ts
|
|
12
|
+
var config_exports = {};
|
|
13
|
+
__export(config_exports, {
|
|
14
|
+
DEFAULT_MODEL: () => DEFAULT_MODEL,
|
|
15
|
+
DEFAULT_REASONING_EFFORT: () => DEFAULT_REASONING_EFFORT,
|
|
16
|
+
EFFORTS: () => EFFORTS,
|
|
17
|
+
configPath: () => configPath,
|
|
18
|
+
loadConfig: () => loadConfig,
|
|
19
|
+
saveConfig: () => saveConfig
|
|
20
|
+
});
|
|
12
21
|
import { readFile, mkdir, writeFile, chmod } from "fs/promises";
|
|
13
22
|
import { homedir } from "os";
|
|
14
23
|
import { join } from "path";
|
|
@@ -933,7 +942,10 @@ async function logTurnDebug(ctx) {
|
|
|
933
942
|
toolSavingsPct: toolTotalRaw > 0 ? Math.round((toolTotalRaw - toolTotalReduced) / toolTotalRaw * 100) : 0,
|
|
934
943
|
cacheDiagnostics,
|
|
935
944
|
compaction: ctx.compaction,
|
|
936
|
-
shadowStrip: ctx.shadowStrip
|
|
945
|
+
shadowStrip: ctx.shadowStrip,
|
|
946
|
+
durationMs: ctx.durationMs,
|
|
947
|
+
intentClassification: ctx.intentClassification,
|
|
948
|
+
codeMode: ctx.codeMode
|
|
937
949
|
});
|
|
938
950
|
}
|
|
939
951
|
var LOG_VERSION;
|
|
@@ -945,6 +957,87 @@ var init_cost_debug = __esm({
|
|
|
945
957
|
}
|
|
946
958
|
});
|
|
947
959
|
|
|
960
|
+
// src/memory/extractors.ts
|
|
961
|
+
function safeJsonParse(text) {
|
|
962
|
+
try {
|
|
963
|
+
return JSON.parse(text);
|
|
964
|
+
} catch {
|
|
965
|
+
return null;
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
var EXTRACTORS;
|
|
969
|
+
var init_extractors = __esm({
|
|
970
|
+
"src/memory/extractors.ts"() {
|
|
971
|
+
"use strict";
|
|
972
|
+
EXTRACTORS = [
|
|
973
|
+
{
|
|
974
|
+
id: "package_json",
|
|
975
|
+
match: (tool, file) => tool === "read" && /package\.json$/.test(file || ""),
|
|
976
|
+
extract: (content, file) => {
|
|
977
|
+
const pkg = safeJsonParse(content);
|
|
978
|
+
if (!pkg) return null;
|
|
979
|
+
const deps = Object.keys(pkg.dependencies || {}).slice(0, 10);
|
|
980
|
+
const devDeps = Object.keys(pkg.devDependencies || {}).slice(0, 5);
|
|
981
|
+
const scripts = Object.keys(pkg.scripts || {}).slice(0, 5);
|
|
982
|
+
return {
|
|
983
|
+
content: `Project dependencies: ${deps.join(", ") || "none"}. Dev dependencies: ${devDeps.join(", ") || "none"}. Scripts: ${scripts.join(", ") || "none"}. Type: ${pkg.type || "commonjs"}.`,
|
|
984
|
+
category: "fact",
|
|
985
|
+
importance: 4,
|
|
986
|
+
topicKey: "project_dependencies",
|
|
987
|
+
relatedFiles: file ? [file] : void 0
|
|
988
|
+
};
|
|
989
|
+
}
|
|
990
|
+
},
|
|
991
|
+
{
|
|
992
|
+
id: "tsconfig",
|
|
993
|
+
match: (tool, file) => tool === "read" && /tsconfig.*\.json$/.test(file || ""),
|
|
994
|
+
extract: (content, file) => {
|
|
995
|
+
const ts = safeJsonParse(content);
|
|
996
|
+
if (!ts) return null;
|
|
997
|
+
const opts2 = ts.compilerOptions || {};
|
|
998
|
+
return {
|
|
999
|
+
content: `TypeScript config: target=${opts2.target || "default"}, module=${opts2.module || "default"}, strict=${opts2.strict || false}, jsx=${opts2.jsx || "none"}.`,
|
|
1000
|
+
category: "fact",
|
|
1001
|
+
importance: 4,
|
|
1002
|
+
topicKey: "project_tsconfig",
|
|
1003
|
+
relatedFiles: file ? [file] : void 0
|
|
1004
|
+
};
|
|
1005
|
+
}
|
|
1006
|
+
},
|
|
1007
|
+
{
|
|
1008
|
+
id: "entry_point",
|
|
1009
|
+
match: (tool, file) => tool === "read" && /src\/(index|main)\.(ts|tsx|js|jsx)$/.test(file || ""),
|
|
1010
|
+
extract: (content, file) => {
|
|
1011
|
+
const exports = content.match(/export\s+(?:default\s+)?(?:function|class|const|interface|type)\s+(\w+)/g);
|
|
1012
|
+
const exportNames = exports ? exports.map((e) => e.split(/\s+/).pop()).filter((n) => !!n).slice(0, 5) : [];
|
|
1013
|
+
return {
|
|
1014
|
+
content: `Entry point ${file} exports: ${exportNames.join(", ") || "default export or side effects"}.`,
|
|
1015
|
+
category: "fact",
|
|
1016
|
+
importance: 3,
|
|
1017
|
+
topicKey: "project_entry_point",
|
|
1018
|
+
relatedFiles: file ? [file] : void 0
|
|
1019
|
+
};
|
|
1020
|
+
}
|
|
1021
|
+
},
|
|
1022
|
+
{
|
|
1023
|
+
id: "edit_event",
|
|
1024
|
+
match: (tool, file) => (tool === "edit" || tool === "write") && !!file,
|
|
1025
|
+
extract: (_content, file) => {
|
|
1026
|
+
if (!file) return null;
|
|
1027
|
+
const safeKey = file.replace(/[^a-zA-Z0-9]/g, "_");
|
|
1028
|
+
return {
|
|
1029
|
+
content: `File modified: ${file}.`,
|
|
1030
|
+
category: "event",
|
|
1031
|
+
importance: 2,
|
|
1032
|
+
topicKey: `event_edit_${safeKey}`,
|
|
1033
|
+
relatedFiles: [file]
|
|
1034
|
+
};
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
];
|
|
1038
|
+
}
|
|
1039
|
+
});
|
|
1040
|
+
|
|
948
1041
|
// src/agent/strip-reasoning.ts
|
|
949
1042
|
function stripHistoricalReasoning(messages, opts2 = {}) {
|
|
950
1043
|
const keepLast = opts2.keepLast ?? DEFAULT_KEEP_LAST;
|
|
@@ -1275,6 +1368,7 @@ var init_code_mode = __esm({
|
|
|
1275
1368
|
|
|
1276
1369
|
// src/agent/loop.ts
|
|
1277
1370
|
async function runAgentTurn(opts2) {
|
|
1371
|
+
const turnStart = performance.now();
|
|
1278
1372
|
const max = opts2.maxToolIterations ?? 50;
|
|
1279
1373
|
const codeMode = opts2.codeMode ?? false;
|
|
1280
1374
|
let toolDefs;
|
|
@@ -1328,7 +1422,28 @@ Use console.log() to return results. Only console.log output will be sent back t
|
|
|
1328
1422
|
const webFetchHistory = [];
|
|
1329
1423
|
const MAX_WEB_FETCH_PER_TURN = 5;
|
|
1330
1424
|
const WEB_FETCH_DOMAIN_THRESHOLD = 2;
|
|
1331
|
-
|
|
1425
|
+
let cumulativePromptTokens = 0;
|
|
1426
|
+
let iter = 0;
|
|
1427
|
+
let budgetExhausted = false;
|
|
1428
|
+
while (true) {
|
|
1429
|
+
if (budgetExhausted) {
|
|
1430
|
+
opts2.messages.push({
|
|
1431
|
+
role: "system",
|
|
1432
|
+
content: "You have reached the cumulative input token budget for this session. Please synthesize your findings and provide a final summary of what was accomplished."
|
|
1433
|
+
});
|
|
1434
|
+
}
|
|
1435
|
+
if (iter >= max) {
|
|
1436
|
+
if (opts2.continueOnLimit) {
|
|
1437
|
+
opts2.messages.push({
|
|
1438
|
+
role: "system",
|
|
1439
|
+
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."
|
|
1440
|
+
});
|
|
1441
|
+
iter = 0;
|
|
1442
|
+
} else {
|
|
1443
|
+
throw new Error(`kimiflare: tool iteration limit reached (${max})`);
|
|
1444
|
+
}
|
|
1445
|
+
}
|
|
1446
|
+
iter++;
|
|
1332
1447
|
turn++;
|
|
1333
1448
|
const previousMessages = opts2.messages.slice();
|
|
1334
1449
|
const toolCalls = [];
|
|
@@ -1426,7 +1541,13 @@ Use console.log() to return results. Only console.log output will be sent back t
|
|
|
1426
1541
|
}
|
|
1427
1542
|
}
|
|
1428
1543
|
if (opts2.signal.aborted) throw new DOMException("aborted", "AbortError");
|
|
1429
|
-
if (lastUsage)
|
|
1544
|
+
if (lastUsage) {
|
|
1545
|
+
opts2.callbacks.onUsageFinal?.(lastUsage, gatewayMeta);
|
|
1546
|
+
cumulativePromptTokens += lastUsage.prompt_tokens;
|
|
1547
|
+
if (!budgetExhausted && opts2.maxInputTokens !== void 0 && opts2.maxInputTokens > 0 && cumulativePromptTokens >= opts2.maxInputTokens && toolCalls.length > 0) {
|
|
1548
|
+
budgetExhausted = true;
|
|
1549
|
+
}
|
|
1550
|
+
}
|
|
1430
1551
|
const assistantMsg = {
|
|
1431
1552
|
role: "assistant",
|
|
1432
1553
|
content: content ? sanitizeString(content) : null,
|
|
@@ -1455,6 +1576,9 @@ Use console.log() to return results. Only console.log output will be sent back t
|
|
|
1455
1576
|
shadowStrip: shadowStripMetrics
|
|
1456
1577
|
});
|
|
1457
1578
|
}
|
|
1579
|
+
if (budgetExhausted) {
|
|
1580
|
+
throw new BudgetExhaustedError();
|
|
1581
|
+
}
|
|
1458
1582
|
return;
|
|
1459
1583
|
}
|
|
1460
1584
|
for (const tc of toolCalls) {
|
|
@@ -1589,10 +1713,38 @@ ${sandboxResult.output}` : sandboxResult.output;
|
|
|
1589
1713
|
name: result.name
|
|
1590
1714
|
});
|
|
1591
1715
|
opts2.callbacks.onToolResult?.(result);
|
|
1716
|
+
if (opts2.memoryManager) {
|
|
1717
|
+
let filePath;
|
|
1718
|
+
try {
|
|
1719
|
+
const args = JSON.parse(tc.function.arguments || "{}");
|
|
1720
|
+
filePath = args.path;
|
|
1721
|
+
} catch {
|
|
1722
|
+
}
|
|
1723
|
+
for (const extractor of EXTRACTORS) {
|
|
1724
|
+
if (extractor.match(tc.function.name, filePath)) {
|
|
1725
|
+
const memory = extractor.extract(result.content, filePath);
|
|
1726
|
+
if (memory) {
|
|
1727
|
+
void opts2.memoryManager.remember(
|
|
1728
|
+
memory.content,
|
|
1729
|
+
memory.category,
|
|
1730
|
+
memory.importance,
|
|
1731
|
+
opts2.cwd,
|
|
1732
|
+
opts2.sessionId ?? "unknown",
|
|
1733
|
+
opts2.signal
|
|
1734
|
+
).catch(() => {
|
|
1735
|
+
});
|
|
1736
|
+
}
|
|
1737
|
+
}
|
|
1738
|
+
}
|
|
1739
|
+
}
|
|
1592
1740
|
recentToolCalls.push(loopSignature);
|
|
1593
1741
|
if (recentToolCalls.length > LOOP_WINDOW) recentToolCalls.shift();
|
|
1594
1742
|
}
|
|
1595
1743
|
}
|
|
1744
|
+
if (opts2.onIterationEnd) {
|
|
1745
|
+
opts2.messages = await opts2.onIterationEnd(opts2.messages, opts2.signal);
|
|
1746
|
+
if (opts2.signal.aborted) throw new DOMException("aborted", "AbortError");
|
|
1747
|
+
}
|
|
1596
1748
|
if (opts2.sessionId && lastUsage) {
|
|
1597
1749
|
void logTurnDebug({
|
|
1598
1750
|
sessionId: opts2.sessionId,
|
|
@@ -1601,11 +1753,16 @@ ${sandboxResult.output}` : sandboxResult.output;
|
|
|
1601
1753
|
previousMessages,
|
|
1602
1754
|
toolResults,
|
|
1603
1755
|
usage: lastUsage,
|
|
1604
|
-
shadowStrip: shadowStripMetrics
|
|
1756
|
+
shadowStrip: shadowStripMetrics,
|
|
1757
|
+
durationMs: Math.round(performance.now() - turnStart),
|
|
1758
|
+
intentClassification: opts2.intentClassification,
|
|
1759
|
+
codeMode: opts2.codeMode
|
|
1605
1760
|
});
|
|
1606
1761
|
}
|
|
1762
|
+
if (budgetExhausted) {
|
|
1763
|
+
throw new BudgetExhaustedError();
|
|
1764
|
+
}
|
|
1607
1765
|
}
|
|
1608
|
-
throw new Error(`kimiflare: tool iteration limit reached (${opts2.maxToolIterations ?? 50})`);
|
|
1609
1766
|
}
|
|
1610
1767
|
function validateToolArguments(raw) {
|
|
1611
1768
|
if (!raw || !raw.trim()) return "{}";
|
|
@@ -1616,7 +1773,7 @@ function validateToolArguments(raw) {
|
|
|
1616
1773
|
return "{}";
|
|
1617
1774
|
}
|
|
1618
1775
|
}
|
|
1619
|
-
var codeModeApiCache;
|
|
1776
|
+
var BudgetExhaustedError, codeModeApiCache;
|
|
1620
1777
|
var init_loop = __esm({
|
|
1621
1778
|
"src/agent/loop.ts"() {
|
|
1622
1779
|
"use strict";
|
|
@@ -1624,8 +1781,15 @@ var init_loop = __esm({
|
|
|
1624
1781
|
init_registry();
|
|
1625
1782
|
init_messages();
|
|
1626
1783
|
init_cost_debug();
|
|
1784
|
+
init_extractors();
|
|
1627
1785
|
init_strip_reasoning();
|
|
1628
1786
|
init_code_mode();
|
|
1787
|
+
BudgetExhaustedError = class extends Error {
|
|
1788
|
+
constructor(message2 = "Cumulative input token budget exhausted") {
|
|
1789
|
+
super(message2);
|
|
1790
|
+
this.name = "BudgetExhaustedError";
|
|
1791
|
+
}
|
|
1792
|
+
};
|
|
1629
1793
|
codeModeApiCache = /* @__PURE__ */ new Map();
|
|
1630
1794
|
}
|
|
1631
1795
|
});
|
|
@@ -3387,6 +3551,229 @@ var init_update_check = __esm({
|
|
|
3387
3551
|
}
|
|
3388
3552
|
});
|
|
3389
3553
|
|
|
3554
|
+
// src/remote/session-store.ts
|
|
3555
|
+
import { readFile as readFile8, writeFile as writeFile6, mkdir as mkdir6, readdir as readdir2 } from "fs/promises";
|
|
3556
|
+
import { homedir as homedir6 } from "os";
|
|
3557
|
+
import { join as join9 } from "path";
|
|
3558
|
+
function remoteDir() {
|
|
3559
|
+
const xdg = process.env.XDG_DATA_HOME || join9(homedir6(), ".config");
|
|
3560
|
+
return join9(xdg, "kimiflare", "remote");
|
|
3561
|
+
}
|
|
3562
|
+
async function saveRemoteSession(session) {
|
|
3563
|
+
const dir = remoteDir();
|
|
3564
|
+
await mkdir6(dir, { recursive: true });
|
|
3565
|
+
const path = join9(dir, `${session.sessionId}.json`);
|
|
3566
|
+
await writeFile6(path, JSON.stringify(session, null, 2) + "\n", "utf8");
|
|
3567
|
+
}
|
|
3568
|
+
async function loadRemoteSession(sessionId) {
|
|
3569
|
+
try {
|
|
3570
|
+
const path = join9(remoteDir(), `${sessionId}.json`);
|
|
3571
|
+
const raw = await readFile8(path, "utf8");
|
|
3572
|
+
return JSON.parse(raw);
|
|
3573
|
+
} catch {
|
|
3574
|
+
return null;
|
|
3575
|
+
}
|
|
3576
|
+
}
|
|
3577
|
+
async function listRemoteSessions() {
|
|
3578
|
+
const dir = remoteDir();
|
|
3579
|
+
try {
|
|
3580
|
+
const files = await readdir2(dir);
|
|
3581
|
+
const sessions = [];
|
|
3582
|
+
for (const file of files) {
|
|
3583
|
+
if (!file.endsWith(".json")) continue;
|
|
3584
|
+
try {
|
|
3585
|
+
const raw = await readFile8(join9(dir, file), "utf8");
|
|
3586
|
+
sessions.push(JSON.parse(raw));
|
|
3587
|
+
} catch {
|
|
3588
|
+
}
|
|
3589
|
+
}
|
|
3590
|
+
return sessions.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
|
|
3591
|
+
} catch {
|
|
3592
|
+
return [];
|
|
3593
|
+
}
|
|
3594
|
+
}
|
|
3595
|
+
async function getMostRecentRemoteSession() {
|
|
3596
|
+
const sessions = await listRemoteSessions();
|
|
3597
|
+
return sessions[0] ?? null;
|
|
3598
|
+
}
|
|
3599
|
+
var init_session_store = __esm({
|
|
3600
|
+
"src/remote/session-store.ts"() {
|
|
3601
|
+
"use strict";
|
|
3602
|
+
}
|
|
3603
|
+
});
|
|
3604
|
+
|
|
3605
|
+
// src/remote/deploy.ts
|
|
3606
|
+
import { execSync } from "child_process";
|
|
3607
|
+
import { join as join10, dirname as dirname5 } from "path";
|
|
3608
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
3609
|
+
import { randomBytes } from "crypto";
|
|
3610
|
+
function generateSecret() {
|
|
3611
|
+
return randomBytes(32).toString("hex");
|
|
3612
|
+
}
|
|
3613
|
+
function runCapture(cmd, cwd) {
|
|
3614
|
+
return execSync(cmd, { cwd, encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
3615
|
+
}
|
|
3616
|
+
async function* deployForTui() {
|
|
3617
|
+
yield { message: "Checking prerequisites..." };
|
|
3618
|
+
try {
|
|
3619
|
+
runCapture("wrangler --version");
|
|
3620
|
+
} catch {
|
|
3621
|
+
yield { message: "wrangler not found. Install: npm install -g wrangler", error: true };
|
|
3622
|
+
yield { message: "Then run: wrangler login", error: true };
|
|
3623
|
+
throw new Error("wrangler not installed");
|
|
3624
|
+
}
|
|
3625
|
+
yield { message: "wrangler OK" };
|
|
3626
|
+
try {
|
|
3627
|
+
runCapture("wrangler whoami");
|
|
3628
|
+
} catch {
|
|
3629
|
+
yield { message: "wrangler not authenticated. Run: wrangler login", error: true };
|
|
3630
|
+
throw new Error("wrangler not authenticated");
|
|
3631
|
+
}
|
|
3632
|
+
yield { message: "wrangler authenticated" };
|
|
3633
|
+
try {
|
|
3634
|
+
runCapture("docker --version");
|
|
3635
|
+
} catch {
|
|
3636
|
+
yield { message: "Docker not found. Install: https://docs.docker.com/get-docker/", error: true };
|
|
3637
|
+
throw new Error("docker not installed");
|
|
3638
|
+
}
|
|
3639
|
+
yield { message: "Docker OK" };
|
|
3640
|
+
yield { message: "Building remote agent bundle..." };
|
|
3641
|
+
try {
|
|
3642
|
+
runCapture("npm run build:remote-agent", join10(REMOTE_DIR, ".."));
|
|
3643
|
+
yield { message: "Agent bundle built" };
|
|
3644
|
+
} catch (err) {
|
|
3645
|
+
yield { message: `Build failed: ${err instanceof Error ? err.message : String(err)}`, error: true };
|
|
3646
|
+
throw err;
|
|
3647
|
+
}
|
|
3648
|
+
yield { message: "Deploying Worker to Cloudflare..." };
|
|
3649
|
+
try {
|
|
3650
|
+
runCapture("wrangler deploy", WORKER_DIR);
|
|
3651
|
+
yield { message: "Worker deployed" };
|
|
3652
|
+
} catch (err) {
|
|
3653
|
+
yield { message: `Deploy failed: ${err instanceof Error ? err.message : String(err)}`, error: true };
|
|
3654
|
+
throw err;
|
|
3655
|
+
}
|
|
3656
|
+
let workerUrl;
|
|
3657
|
+
try {
|
|
3658
|
+
const info = runCapture("wrangler info", WORKER_DIR);
|
|
3659
|
+
const match = info.match(/https:\/\/[^\s]+\.workers\.dev/);
|
|
3660
|
+
if (match) workerUrl = match[0];
|
|
3661
|
+
} catch {
|
|
3662
|
+
}
|
|
3663
|
+
if (!workerUrl) {
|
|
3664
|
+
yield { message: "Could not auto-detect Worker URL", error: true };
|
|
3665
|
+
throw new Error("Worker URL not found");
|
|
3666
|
+
}
|
|
3667
|
+
yield { message: `Worker URL: ${workerUrl}` };
|
|
3668
|
+
const authSecret = generateSecret();
|
|
3669
|
+
const cfg = await loadConfig();
|
|
3670
|
+
const cfToken = process.env.CF_API_TOKEN ?? cfg?.apiToken;
|
|
3671
|
+
if (!cfToken) {
|
|
3672
|
+
yield { message: "CF_API_TOKEN not found. Set CF_API_TOKEN env var or apiToken in config", error: true };
|
|
3673
|
+
throw new Error("CF_API_TOKEN missing");
|
|
3674
|
+
}
|
|
3675
|
+
yield { message: "Setting Worker secrets..." };
|
|
3676
|
+
try {
|
|
3677
|
+
execSync(`wrangler secret put REMOTE_AUTH_SECRET`, {
|
|
3678
|
+
cwd: WORKER_DIR,
|
|
3679
|
+
input: authSecret,
|
|
3680
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
3681
|
+
});
|
|
3682
|
+
execSync(`wrangler secret put CF_API_TOKEN`, {
|
|
3683
|
+
cwd: WORKER_DIR,
|
|
3684
|
+
input: cfToken,
|
|
3685
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
3686
|
+
});
|
|
3687
|
+
yield { message: "Secrets set" };
|
|
3688
|
+
} catch (err) {
|
|
3689
|
+
yield { message: `Secret setup failed: ${err instanceof Error ? err.message : String(err)}`, error: true };
|
|
3690
|
+
throw err;
|
|
3691
|
+
}
|
|
3692
|
+
const imageTag = "ghcr.io/sinameraji/kimiflare-remote-agent:latest";
|
|
3693
|
+
yield { message: "Building container image..." };
|
|
3694
|
+
try {
|
|
3695
|
+
runCapture(`docker build -t ${imageTag} .`, REMOTE_DIR);
|
|
3696
|
+
yield { message: "Image built" };
|
|
3697
|
+
} catch (err) {
|
|
3698
|
+
yield { message: `Image build failed: ${err instanceof Error ? err.message : String(err)}`, error: true };
|
|
3699
|
+
throw err;
|
|
3700
|
+
}
|
|
3701
|
+
yield { message: `Pushing ${imageTag}...` };
|
|
3702
|
+
try {
|
|
3703
|
+
runCapture(`docker push ${imageTag}`, REMOTE_DIR);
|
|
3704
|
+
yield { message: "Image pushed" };
|
|
3705
|
+
} catch (err) {
|
|
3706
|
+
yield { message: `Push failed: ${err instanceof Error ? err.message : String(err)}`, error: true };
|
|
3707
|
+
yield { message: "Make sure you're logged into ghcr.io: docker login ghcr.io -u USERNAME -p GITHUB_TOKEN", error: true };
|
|
3708
|
+
throw err;
|
|
3709
|
+
}
|
|
3710
|
+
const nextCfg = {
|
|
3711
|
+
...cfg ?? { accountId: "", apiToken: "", model: "@cf/moonshotai/kimi-k2.6" },
|
|
3712
|
+
remoteWorkerUrl: workerUrl,
|
|
3713
|
+
remoteAuthSecret: authSecret
|
|
3714
|
+
};
|
|
3715
|
+
await saveConfig(nextCfg);
|
|
3716
|
+
yield { message: "Config saved" };
|
|
3717
|
+
yield { message: "Remote infrastructure ready!", done: true };
|
|
3718
|
+
return { workerUrl, authSecret };
|
|
3719
|
+
}
|
|
3720
|
+
async function runDeploy() {
|
|
3721
|
+
console.log("kimiflare remote deploy\n");
|
|
3722
|
+
try {
|
|
3723
|
+
for await (const step of deployForTui()) {
|
|
3724
|
+
console.log(step.message);
|
|
3725
|
+
if (step.done) break;
|
|
3726
|
+
if (step.error) process.exit(1);
|
|
3727
|
+
}
|
|
3728
|
+
console.log("\nDeploy complete!");
|
|
3729
|
+
} catch (err) {
|
|
3730
|
+
console.error(`Deploy failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
3731
|
+
process.exit(1);
|
|
3732
|
+
}
|
|
3733
|
+
}
|
|
3734
|
+
async function checkDeployStatus() {
|
|
3735
|
+
let wrangler = false;
|
|
3736
|
+
let wranglerAuth = false;
|
|
3737
|
+
let docker = false;
|
|
3738
|
+
let workerUrl;
|
|
3739
|
+
try {
|
|
3740
|
+
execSync("wrangler --version", { stdio: "pipe" });
|
|
3741
|
+
wrangler = true;
|
|
3742
|
+
} catch {
|
|
3743
|
+
}
|
|
3744
|
+
if (wrangler) {
|
|
3745
|
+
try {
|
|
3746
|
+
execSync("wrangler whoami", { stdio: "pipe" });
|
|
3747
|
+
wranglerAuth = true;
|
|
3748
|
+
} catch {
|
|
3749
|
+
}
|
|
3750
|
+
}
|
|
3751
|
+
try {
|
|
3752
|
+
execSync("docker --version", { stdio: "pipe" });
|
|
3753
|
+
docker = true;
|
|
3754
|
+
} catch {
|
|
3755
|
+
}
|
|
3756
|
+
const cfg = await loadConfig();
|
|
3757
|
+
if (cfg?.remoteWorkerUrl) {
|
|
3758
|
+
try {
|
|
3759
|
+
const res = await fetch(`${cfg.remoteWorkerUrl}/health`, { signal: AbortSignal.timeout(5e3) });
|
|
3760
|
+
if (res.ok) workerUrl = cfg.remoteWorkerUrl;
|
|
3761
|
+
} catch {
|
|
3762
|
+
}
|
|
3763
|
+
}
|
|
3764
|
+
return { wrangler, wranglerAuth, docker, workerUrl };
|
|
3765
|
+
}
|
|
3766
|
+
var __dirname, REMOTE_DIR, WORKER_DIR;
|
|
3767
|
+
var init_deploy = __esm({
|
|
3768
|
+
"src/remote/deploy.ts"() {
|
|
3769
|
+
"use strict";
|
|
3770
|
+
init_config();
|
|
3771
|
+
__dirname = dirname5(fileURLToPath3(import.meta.url));
|
|
3772
|
+
REMOTE_DIR = join10(__dirname, "..", "..", "..", "remote");
|
|
3773
|
+
WORKER_DIR = join10(REMOTE_DIR, "worker");
|
|
3774
|
+
}
|
|
3775
|
+
});
|
|
3776
|
+
|
|
3390
3777
|
// src/cost-attribution/types.ts
|
|
3391
3778
|
var ALL_CATEGORIES;
|
|
3392
3779
|
var init_types = __esm({
|
|
@@ -3806,12 +4193,12 @@ var init_heuristic = __esm({
|
|
|
3806
4193
|
});
|
|
3807
4194
|
|
|
3808
4195
|
// src/cost-attribution/classify-from-session.ts
|
|
3809
|
-
import { readFile as
|
|
3810
|
-
import { join as
|
|
3811
|
-
import { homedir as
|
|
4196
|
+
import { readFile as readFile9 } from "fs/promises";
|
|
4197
|
+
import { join as join11 } from "path";
|
|
4198
|
+
import { homedir as homedir7 } from "os";
|
|
3812
4199
|
function sessionsDir() {
|
|
3813
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
3814
|
-
return
|
|
4200
|
+
const xdg = process.env.XDG_DATA_HOME || join11(homedir7(), ".local", "share");
|
|
4201
|
+
return join11(xdg, "kimiflare", "sessions");
|
|
3815
4202
|
}
|
|
3816
4203
|
function parseToolCalls(calls) {
|
|
3817
4204
|
return calls.map((c) => {
|
|
@@ -3825,7 +4212,7 @@ function parseToolCalls(calls) {
|
|
|
3825
4212
|
}
|
|
3826
4213
|
async function classifyFromSessionFile(sessionId) {
|
|
3827
4214
|
try {
|
|
3828
|
-
const raw = await
|
|
4215
|
+
const raw = await readFile9(join11(sessionsDir(), `${sessionId}.json`), "utf8");
|
|
3829
4216
|
const session = JSON.parse(raw);
|
|
3830
4217
|
const messages = session.messages ?? [];
|
|
3831
4218
|
const turns = [];
|
|
@@ -3858,15 +4245,15 @@ var cli_exports = {};
|
|
|
3858
4245
|
__export(cli_exports, {
|
|
3859
4246
|
runCostCommand: () => runCostCommand
|
|
3860
4247
|
});
|
|
3861
|
-
import { readFile as
|
|
3862
|
-
import { join as
|
|
3863
|
-
import { homedir as
|
|
4248
|
+
import { readFile as readFile10 } from "fs/promises";
|
|
4249
|
+
import { join as join12 } from "path";
|
|
4250
|
+
import { homedir as homedir8 } from "os";
|
|
3864
4251
|
function usageDir() {
|
|
3865
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
3866
|
-
return
|
|
4252
|
+
const xdg = process.env.XDG_DATA_HOME || join12(homedir8(), ".local", "share");
|
|
4253
|
+
return join12(xdg, "kimiflare");
|
|
3867
4254
|
}
|
|
3868
4255
|
function usagePath() {
|
|
3869
|
-
return
|
|
4256
|
+
return join12(usageDir(), "usage.json");
|
|
3870
4257
|
}
|
|
3871
4258
|
function today() {
|
|
3872
4259
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
@@ -3878,7 +4265,7 @@ function daysAgo(n) {
|
|
|
3878
4265
|
}
|
|
3879
4266
|
async function loadLog() {
|
|
3880
4267
|
try {
|
|
3881
|
-
const raw = await
|
|
4268
|
+
const raw = await readFile10(usagePath(), "utf8");
|
|
3882
4269
|
return JSON.parse(raw);
|
|
3883
4270
|
} catch {
|
|
3884
4271
|
return { version: 1, days: [], sessions: [] };
|
|
@@ -3964,6 +4351,94 @@ var init_cli = __esm({
|
|
|
3964
4351
|
}
|
|
3965
4352
|
});
|
|
3966
4353
|
|
|
4354
|
+
// src/remote/tui-auth.ts
|
|
4355
|
+
var tui_auth_exports = {};
|
|
4356
|
+
__export(tui_auth_exports, {
|
|
4357
|
+
authGitHubForTui: () => authGitHubForTui
|
|
4358
|
+
});
|
|
4359
|
+
function sleep2(ms) {
|
|
4360
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
4361
|
+
}
|
|
4362
|
+
async function* authGitHubForTui() {
|
|
4363
|
+
yield { message: "Starting GitHub OAuth device flow..." };
|
|
4364
|
+
const deviceRes = await fetch(GITHUB_DEVICE_AUTH_URL, {
|
|
4365
|
+
method: "POST",
|
|
4366
|
+
headers: {
|
|
4367
|
+
Accept: "application/json",
|
|
4368
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
4369
|
+
},
|
|
4370
|
+
body: new URLSearchParams({ client_id: CLIENT_ID, scope: "repo" })
|
|
4371
|
+
});
|
|
4372
|
+
if (!deviceRes.ok) {
|
|
4373
|
+
yield { message: `Failed to request device code: ${deviceRes.status}`, error: true };
|
|
4374
|
+
throw new Error("Device code request failed");
|
|
4375
|
+
}
|
|
4376
|
+
const deviceData = await deviceRes.json();
|
|
4377
|
+
yield {
|
|
4378
|
+
message: `Open ${deviceData.verification_uri} and enter code: ${deviceData.user_code}`,
|
|
4379
|
+
url: deviceData.verification_uri,
|
|
4380
|
+
code: deviceData.user_code
|
|
4381
|
+
};
|
|
4382
|
+
const startTime = Date.now();
|
|
4383
|
+
const expiresIn = deviceData.expires_in * 1e3;
|
|
4384
|
+
const interval = deviceData.interval * 1e3;
|
|
4385
|
+
while (Date.now() - startTime < expiresIn) {
|
|
4386
|
+
await sleep2(interval);
|
|
4387
|
+
const tokenRes = await fetch(GITHUB_ACCESS_TOKEN_URL, {
|
|
4388
|
+
method: "POST",
|
|
4389
|
+
headers: {
|
|
4390
|
+
Accept: "application/json",
|
|
4391
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
4392
|
+
},
|
|
4393
|
+
body: new URLSearchParams({
|
|
4394
|
+
client_id: CLIENT_ID,
|
|
4395
|
+
device_code: deviceData.device_code,
|
|
4396
|
+
grant_type: "urn:ietf:params:oauth:grant-type:device_code"
|
|
4397
|
+
})
|
|
4398
|
+
});
|
|
4399
|
+
if (!tokenRes.ok) continue;
|
|
4400
|
+
const tokenData = await tokenRes.json();
|
|
4401
|
+
if (tokenData.error === "authorization_pending") {
|
|
4402
|
+
continue;
|
|
4403
|
+
}
|
|
4404
|
+
if (tokenData.error === "slow_down") {
|
|
4405
|
+
await sleep2(interval * 2);
|
|
4406
|
+
continue;
|
|
4407
|
+
}
|
|
4408
|
+
if (tokenData.error) {
|
|
4409
|
+
yield { message: `OAuth error: ${tokenData.error}`, error: true };
|
|
4410
|
+
throw new Error(tokenData.error);
|
|
4411
|
+
}
|
|
4412
|
+
if (tokenData.access_token) {
|
|
4413
|
+
const cfg = await loadConfig() ?? {
|
|
4414
|
+
accountId: "",
|
|
4415
|
+
apiToken: "",
|
|
4416
|
+
model: "@cf/moonshotai/kimi-k2.6"
|
|
4417
|
+
};
|
|
4418
|
+
await saveConfig({
|
|
4419
|
+
...cfg,
|
|
4420
|
+
githubOAuthToken: tokenData.access_token,
|
|
4421
|
+
githubRefreshToken: tokenData.refresh_token,
|
|
4422
|
+
githubTokenExpiry: tokenData.expires_in ? Date.now() + tokenData.expires_in * 1e3 : void 0
|
|
4423
|
+
});
|
|
4424
|
+
yield { message: "GitHub authentication successful!", done: true };
|
|
4425
|
+
return;
|
|
4426
|
+
}
|
|
4427
|
+
}
|
|
4428
|
+
yield { message: "Device flow expired. Please try again.", error: true };
|
|
4429
|
+
throw new Error("Device flow expired");
|
|
4430
|
+
}
|
|
4431
|
+
var GITHUB_DEVICE_AUTH_URL, GITHUB_ACCESS_TOKEN_URL, CLIENT_ID;
|
|
4432
|
+
var init_tui_auth = __esm({
|
|
4433
|
+
"src/remote/tui-auth.ts"() {
|
|
4434
|
+
"use strict";
|
|
4435
|
+
init_config();
|
|
4436
|
+
GITHUB_DEVICE_AUTH_URL = "https://github.com/login/device/code";
|
|
4437
|
+
GITHUB_ACCESS_TOKEN_URL = "https://github.com/login/oauth/access_token";
|
|
4438
|
+
CLIENT_ID = process.env.KIMIFLARE_GITHUB_CLIENT_ID ?? "Ov23liM7lJX1xE2V1sVK";
|
|
4439
|
+
}
|
|
4440
|
+
});
|
|
4441
|
+
|
|
3967
4442
|
// src/agent/compact.ts
|
|
3968
4443
|
function indexOfNthUserFromEnd(messages, n) {
|
|
3969
4444
|
let seen = 0;
|
|
@@ -4785,12 +5260,12 @@ var init_connection = __esm({
|
|
|
4785
5260
|
});
|
|
4786
5261
|
|
|
4787
5262
|
// src/lsp/protocol.ts
|
|
4788
|
-
import { pathToFileURL, fileURLToPath as
|
|
5263
|
+
import { pathToFileURL, fileURLToPath as fileURLToPath4 } from "url";
|
|
4789
5264
|
function toUri(path) {
|
|
4790
5265
|
return pathToFileURL(path).href;
|
|
4791
5266
|
}
|
|
4792
5267
|
function fromUri(uri) {
|
|
4793
|
-
return
|
|
5268
|
+
return fileURLToPath4(uri);
|
|
4794
5269
|
}
|
|
4795
5270
|
function symbolKindName(kind) {
|
|
4796
5271
|
const names = {
|
|
@@ -7413,7 +7888,7 @@ var init_help_menu = __esm({
|
|
|
7413
7888
|
commands: [
|
|
7414
7889
|
{ command: "/init", description: "scan this repo and write a KIMI.md" },
|
|
7415
7890
|
{ command: "/logout", description: "clear credentials" },
|
|
7416
|
-
{ command: "filePicker", description: "
|
|
7891
|
+
{ command: "filePicker", description: "enabled by default; disable with KIMIFLARE_FILE_PICKER=0 or filePicker: false in config", selectable: false }
|
|
7417
7892
|
]
|
|
7418
7893
|
}
|
|
7419
7894
|
];
|
|
@@ -7425,96 +7900,446 @@ var init_help_menu = __esm({
|
|
|
7425
7900
|
}
|
|
7426
7901
|
});
|
|
7427
7902
|
|
|
7428
|
-
// src/
|
|
7429
|
-
var
|
|
7430
|
-
__export(
|
|
7431
|
-
|
|
7432
|
-
|
|
7433
|
-
|
|
7434
|
-
|
|
7435
|
-
saveSession: () => saveSession
|
|
7903
|
+
// src/remote/worker-client.ts
|
|
7904
|
+
var worker_client_exports = {};
|
|
7905
|
+
__export(worker_client_exports, {
|
|
7906
|
+
cancelRemoteSession: () => cancelRemoteSession,
|
|
7907
|
+
getRemoteStatus: () => getRemoteStatus,
|
|
7908
|
+
startRemoteSession: () => startRemoteSession,
|
|
7909
|
+
streamRemoteProgress: () => streamRemoteProgress
|
|
7436
7910
|
});
|
|
7437
|
-
|
|
7438
|
-
|
|
7439
|
-
|
|
7440
|
-
|
|
7441
|
-
|
|
7442
|
-
|
|
7443
|
-
|
|
7444
|
-
|
|
7445
|
-
|
|
7446
|
-
}
|
|
7447
|
-
|
|
7448
|
-
|
|
7449
|
-
|
|
7450
|
-
|
|
7451
|
-
}
|
|
7452
|
-
|
|
7453
|
-
|
|
7454
|
-
|
|
7455
|
-
|
|
7456
|
-
|
|
7457
|
-
|
|
7458
|
-
|
|
7459
|
-
|
|
7460
|
-
|
|
7461
|
-
|
|
7462
|
-
|
|
7911
|
+
async function startRemoteSession(opts2) {
|
|
7912
|
+
const workerUrl = opts2.cfg.remoteWorkerUrl;
|
|
7913
|
+
if (!workerUrl) {
|
|
7914
|
+
throw new Error("Remote worker URL not configured. Set remoteWorkerUrl in config.");
|
|
7915
|
+
}
|
|
7916
|
+
const githubToken = opts2.cfg.githubOAuthToken;
|
|
7917
|
+
if (!githubToken) {
|
|
7918
|
+
throw new Error("GitHub token not found. Run `kimiflare auth github` first.");
|
|
7919
|
+
}
|
|
7920
|
+
const res = await fetch(`${workerUrl}/remote/start`, {
|
|
7921
|
+
method: "POST",
|
|
7922
|
+
headers: {
|
|
7923
|
+
"Content-Type": "application/json",
|
|
7924
|
+
Authorization: `Bearer ${opts2.cfg.remoteAuthSecret ?? ""}`
|
|
7925
|
+
},
|
|
7926
|
+
body: JSON.stringify({
|
|
7927
|
+
prompt: opts2.prompt,
|
|
7928
|
+
repo: opts2.repo,
|
|
7929
|
+
githubToken,
|
|
7930
|
+
accountId: opts2.cfg.accountId,
|
|
7931
|
+
apiToken: opts2.cfg.apiToken,
|
|
7932
|
+
model: opts2.cfg.model,
|
|
7933
|
+
reasoningEffort: opts2.cfg.reasoningEffort,
|
|
7934
|
+
ttlMinutes: opts2.ttlMinutes ?? opts2.cfg.remoteTtlMinutes,
|
|
7935
|
+
tokensBudget: opts2.tokensBudget ?? opts2.cfg.remoteMaxInputTokens
|
|
7936
|
+
})
|
|
7937
|
+
});
|
|
7938
|
+
if (!res.ok) {
|
|
7939
|
+
const text = await res.text();
|
|
7940
|
+
throw new Error(`Failed to start remote session: ${res.status} ${text}`);
|
|
7941
|
+
}
|
|
7942
|
+
const data = await res.json();
|
|
7943
|
+
await saveRemoteSession({
|
|
7944
|
+
sessionId: data.sessionId,
|
|
7945
|
+
prompt: opts2.prompt,
|
|
7946
|
+
repo: `${opts2.repo.owner}/${opts2.repo.name}`,
|
|
7947
|
+
workerUrl,
|
|
7948
|
+
status: "running",
|
|
7949
|
+
branch: `kimiflare/remote/${data.sessionId}`,
|
|
7950
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7951
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
7952
|
+
});
|
|
7953
|
+
return data;
|
|
7463
7954
|
}
|
|
7464
|
-
async function
|
|
7465
|
-
const
|
|
7466
|
-
|
|
7467
|
-
|
|
7468
|
-
entries = await readdir2(dir);
|
|
7469
|
-
} catch {
|
|
7470
|
-
return [];
|
|
7955
|
+
async function* streamRemoteProgress(workerUrl, sessionId, signal) {
|
|
7956
|
+
const res = await fetch(`${workerUrl}/remote/stream/${sessionId}`, { signal });
|
|
7957
|
+
if (!res.ok) {
|
|
7958
|
+
throw new Error(`Failed to connect to stream: ${res.status}`);
|
|
7471
7959
|
}
|
|
7472
|
-
|
|
7473
|
-
|
|
7474
|
-
|
|
7475
|
-
|
|
7960
|
+
if (!res.body) {
|
|
7961
|
+
throw new Error("No response body");
|
|
7962
|
+
}
|
|
7963
|
+
for await (const line of readSSE(res.body, signal)) {
|
|
7476
7964
|
try {
|
|
7477
|
-
|
|
7478
|
-
const parsed = JSON.parse(raw);
|
|
7479
|
-
const firstUser = parsed.messages.find((m) => m.role === "user");
|
|
7480
|
-
const firstPrompt = typeof firstUser?.content === "string" ? firstUser.content : firstUser?.content ? firstUser.content.find((p) => p.type === "text")?.text ?? "(no prompt)" : "(no prompt)";
|
|
7481
|
-
summaries.push({
|
|
7482
|
-
id: parsed.id,
|
|
7483
|
-
filePath: path,
|
|
7484
|
-
cwd: parsed.cwd,
|
|
7485
|
-
firstPrompt: firstPrompt.slice(0, 80),
|
|
7486
|
-
messageCount: parsed.messages.filter((m) => m.role !== "system").length,
|
|
7487
|
-
updatedAt: parsed.updatedAt ?? s.mtime.toISOString()
|
|
7488
|
-
});
|
|
7965
|
+
yield JSON.parse(line);
|
|
7489
7966
|
} catch {
|
|
7490
7967
|
}
|
|
7491
7968
|
}
|
|
7492
|
-
summaries.sort((a, b) => b.updatedAt < a.updatedAt ? -1 : 1);
|
|
7493
|
-
return summaries.slice(0, limit);
|
|
7494
7969
|
}
|
|
7495
|
-
async function
|
|
7496
|
-
const
|
|
7497
|
-
|
|
7970
|
+
async function getRemoteStatus(workerUrl, sessionId, authSecret) {
|
|
7971
|
+
const res = await fetch(`${workerUrl}/remote/status/${sessionId}`, {
|
|
7972
|
+
headers: authSecret ? { Authorization: `Bearer ${authSecret}` } : {}
|
|
7973
|
+
});
|
|
7974
|
+
if (!res.ok) {
|
|
7975
|
+
const text = await res.text();
|
|
7976
|
+
throw new Error(`Failed to get status: ${res.status} ${text}`);
|
|
7977
|
+
}
|
|
7978
|
+
return res.json();
|
|
7498
7979
|
}
|
|
7499
|
-
|
|
7500
|
-
|
|
7980
|
+
async function cancelRemoteSession(workerUrl, sessionId, authSecret) {
|
|
7981
|
+
const res = await fetch(`${workerUrl}/remote/cancel/${sessionId}`, {
|
|
7982
|
+
method: "POST",
|
|
7983
|
+
headers: authSecret ? { Authorization: `Bearer ${authSecret}` } : {}
|
|
7984
|
+
});
|
|
7985
|
+
if (!res.ok) {
|
|
7986
|
+
const text = await res.text();
|
|
7987
|
+
throw new Error(`Failed to cancel session: ${res.status} ${text}`);
|
|
7988
|
+
}
|
|
7989
|
+
}
|
|
7990
|
+
var init_worker_client = __esm({
|
|
7991
|
+
"src/remote/worker-client.ts"() {
|
|
7501
7992
|
"use strict";
|
|
7502
|
-
|
|
7993
|
+
init_session_store();
|
|
7994
|
+
init_sse();
|
|
7503
7995
|
}
|
|
7504
7996
|
});
|
|
7505
7997
|
|
|
7506
|
-
// src/
|
|
7507
|
-
|
|
7508
|
-
|
|
7509
|
-
|
|
7510
|
-
|
|
7511
|
-
if (buf.byteLength > MAX_IMAGE_BYTES) {
|
|
7512
|
-
throw new Error(
|
|
7513
|
-
`image too large (${(buf.byteLength / 1024 / 1024).toFixed(1)} MB); max is ${MAX_IMAGE_BYTES / 1024 / 1024} MB`
|
|
7514
|
-
);
|
|
7998
|
+
// src/remote/tui-deploy.ts
|
|
7999
|
+
var init_tui_deploy = __esm({
|
|
8000
|
+
"src/remote/tui-deploy.ts"() {
|
|
8001
|
+
"use strict";
|
|
8002
|
+
init_deploy();
|
|
7515
8003
|
}
|
|
7516
|
-
|
|
7517
|
-
|
|
8004
|
+
});
|
|
8005
|
+
|
|
8006
|
+
// src/ui/remote-dashboard.tsx
|
|
8007
|
+
import { useEffect as useEffect4, useState as useState7 } from "react";
|
|
8008
|
+
import { Box as Box12, Text as Text13, useInput as useInput3 } from "ink";
|
|
8009
|
+
import SelectInput4 from "ink-select-input";
|
|
8010
|
+
import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
8011
|
+
function RemoteDashboard({ onSelect, onCancel }) {
|
|
8012
|
+
const theme = useTheme();
|
|
8013
|
+
const [sessions, setSessions] = useState7([]);
|
|
8014
|
+
const [loading, setLoading] = useState7(true);
|
|
8015
|
+
const [error, setError] = useState7(null);
|
|
8016
|
+
const [refreshing, setRefreshing] = useState7(false);
|
|
8017
|
+
useEffect4(() => {
|
|
8018
|
+
loadSessions();
|
|
8019
|
+
}, []);
|
|
8020
|
+
async function loadSessions() {
|
|
8021
|
+
try {
|
|
8022
|
+
setRefreshing(true);
|
|
8023
|
+
const list = await listRemoteSessions();
|
|
8024
|
+
const updated = await Promise.all(
|
|
8025
|
+
list.map(async (s) => {
|
|
8026
|
+
if (s.status === "running" || s.status === "pending") {
|
|
8027
|
+
try {
|
|
8028
|
+
const status = await getRemoteStatus(s.workerUrl, s.sessionId);
|
|
8029
|
+
return {
|
|
8030
|
+
...s,
|
|
8031
|
+
status: status.status,
|
|
8032
|
+
prUrl: status.prUrl ?? s.prUrl,
|
|
8033
|
+
tokensUsed: status.tokensUsed ?? s.tokensUsed,
|
|
8034
|
+
tokensBudget: status.tokensBudget ?? s.tokensBudget,
|
|
8035
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
8036
|
+
};
|
|
8037
|
+
} catch {
|
|
8038
|
+
return s;
|
|
8039
|
+
}
|
|
8040
|
+
}
|
|
8041
|
+
return s;
|
|
8042
|
+
})
|
|
8043
|
+
);
|
|
8044
|
+
setSessions(updated.sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime()));
|
|
8045
|
+
setError(null);
|
|
8046
|
+
} catch (err) {
|
|
8047
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
8048
|
+
} finally {
|
|
8049
|
+
setLoading(false);
|
|
8050
|
+
setRefreshing(false);
|
|
8051
|
+
}
|
|
8052
|
+
}
|
|
8053
|
+
useInput3((input, key) => {
|
|
8054
|
+
if (input === "r" || input === "R") {
|
|
8055
|
+
void loadSessions();
|
|
8056
|
+
}
|
|
8057
|
+
if (key.escape && onCancel) {
|
|
8058
|
+
onCancel();
|
|
8059
|
+
}
|
|
8060
|
+
});
|
|
8061
|
+
const items = sessions.map((s) => ({
|
|
8062
|
+
label: formatSessionLine(s),
|
|
8063
|
+
value: s.sessionId
|
|
8064
|
+
}));
|
|
8065
|
+
if (loading) {
|
|
8066
|
+
return /* @__PURE__ */ jsx14(Box12, { flexDirection: "column", padding: 1, children: /* @__PURE__ */ jsx14(Text13, { color: theme.accent, children: "Loading remote sessions..." }) });
|
|
8067
|
+
}
|
|
8068
|
+
if (error) {
|
|
8069
|
+
return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", padding: 1, children: [
|
|
8070
|
+
/* @__PURE__ */ jsxs12(Text13, { color: theme.error, children: [
|
|
8071
|
+
"Error: ",
|
|
8072
|
+
error
|
|
8073
|
+
] }),
|
|
8074
|
+
/* @__PURE__ */ jsx14(Text13, { dimColor: true, children: "Press R to retry, Esc to close" })
|
|
8075
|
+
] });
|
|
8076
|
+
}
|
|
8077
|
+
if (sessions.length === 0) {
|
|
8078
|
+
return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", padding: 1, children: [
|
|
8079
|
+
/* @__PURE__ */ jsx14(Text13, { color: theme.accent, children: "No remote sessions yet." }),
|
|
8080
|
+
/* @__PURE__ */ jsx14(Text13, { dimColor: true, children: "Type /remote <prompt> to start one." }),
|
|
8081
|
+
/* @__PURE__ */ jsx14(Text13, { dimColor: true, children: "Press Esc to close" })
|
|
8082
|
+
] });
|
|
8083
|
+
}
|
|
8084
|
+
return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", padding: 1, children: [
|
|
8085
|
+
/* @__PURE__ */ jsxs12(Text13, { bold: true, color: theme.accent, children: [
|
|
8086
|
+
"Recent remote tasks ",
|
|
8087
|
+
refreshing ? "(refreshing...)" : ""
|
|
8088
|
+
] }),
|
|
8089
|
+
/* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(
|
|
8090
|
+
SelectInput4,
|
|
8091
|
+
{
|
|
8092
|
+
items,
|
|
8093
|
+
onSelect: (item) => {
|
|
8094
|
+
const session = sessions.find((s) => s.sessionId === item.value);
|
|
8095
|
+
if (session) onSelect?.(session);
|
|
8096
|
+
}
|
|
8097
|
+
}
|
|
8098
|
+
) }),
|
|
8099
|
+
/* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(Text13, { dimColor: true, children: "\u2191\u2193 navigate \u2022 Enter select \u2022 R refresh \u2022 Esc close" }) })
|
|
8100
|
+
] });
|
|
8101
|
+
}
|
|
8102
|
+
function formatSessionLine(s) {
|
|
8103
|
+
const icon = s.status === "done" ? "\u2705" : s.status === "error" ? "\u274C" : s.status === "cancelled" ? "\u23F9\uFE0F" : s.status === "running" ? "\u23F3" : "\u23F8";
|
|
8104
|
+
const ago = formatAgo(new Date(s.updatedAt));
|
|
8105
|
+
const prompt = s.prompt.slice(0, 30) + (s.prompt.length > 30 ? "\u2026" : "");
|
|
8106
|
+
const outcome = s.prUrl ? `PR ${s.prUrl.split("/").pop()}` : s.status;
|
|
8107
|
+
const cost = s.tokensUsed && s.tokensBudget ? ` (${formatTokens2(s.tokensUsed)}/${formatTokens2(s.tokensBudget)})` : s.tokensUsed ? ` (${formatTokens2(s.tokensUsed)})` : "";
|
|
8108
|
+
return `${icon} ${prompt} \u2192 ${outcome} ${ago}${cost}`;
|
|
8109
|
+
}
|
|
8110
|
+
function formatAgo(date) {
|
|
8111
|
+
const ms = Date.now() - date.getTime();
|
|
8112
|
+
const minutes = Math.floor(ms / 6e4);
|
|
8113
|
+
const hours = Math.floor(minutes / 60);
|
|
8114
|
+
const days = Math.floor(hours / 24);
|
|
8115
|
+
if (days > 0) return `${days}d ago`;
|
|
8116
|
+
if (hours > 0) return `${hours}h ago`;
|
|
8117
|
+
if (minutes > 0) return `${minutes}m ago`;
|
|
8118
|
+
return "just now";
|
|
8119
|
+
}
|
|
8120
|
+
function formatTokens2(n) {
|
|
8121
|
+
if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
|
|
8122
|
+
if (n >= 1e3) return `${(n / 1e3).toFixed(1)}K`;
|
|
8123
|
+
return String(n);
|
|
8124
|
+
}
|
|
8125
|
+
function RemoteSessionDetail({
|
|
8126
|
+
session,
|
|
8127
|
+
onBack,
|
|
8128
|
+
onCancel
|
|
8129
|
+
}) {
|
|
8130
|
+
const theme = useTheme();
|
|
8131
|
+
const [cancelling, setCancelling] = useState7(false);
|
|
8132
|
+
useInput3((input, key) => {
|
|
8133
|
+
if (key.escape) {
|
|
8134
|
+
onBack();
|
|
8135
|
+
}
|
|
8136
|
+
if ((input === "c" || input === "C") && onCancel && (session.status === "running" || session.status === "pending")) {
|
|
8137
|
+
void handleCancel();
|
|
8138
|
+
}
|
|
8139
|
+
});
|
|
8140
|
+
async function handleCancel() {
|
|
8141
|
+
if (!onCancel) return;
|
|
8142
|
+
setCancelling(true);
|
|
8143
|
+
try {
|
|
8144
|
+
await cancelRemoteSession(session.workerUrl, session.sessionId);
|
|
8145
|
+
onCancel(session);
|
|
8146
|
+
} catch {
|
|
8147
|
+
} finally {
|
|
8148
|
+
setCancelling(false);
|
|
8149
|
+
}
|
|
8150
|
+
}
|
|
8151
|
+
const isRunning = session.status === "running" || session.status === "pending";
|
|
8152
|
+
return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", padding: 1, children: [
|
|
8153
|
+
/* @__PURE__ */ jsx14(Text13, { bold: true, color: theme.accent, children: "Remote Session" }),
|
|
8154
|
+
/* @__PURE__ */ jsxs12(Box12, { marginTop: 1, flexDirection: "column", children: [
|
|
8155
|
+
/* @__PURE__ */ jsxs12(Text13, { children: [
|
|
8156
|
+
"ID: ",
|
|
8157
|
+
session.sessionId
|
|
8158
|
+
] }),
|
|
8159
|
+
/* @__PURE__ */ jsxs12(Text13, { children: [
|
|
8160
|
+
"Repo: ",
|
|
8161
|
+
session.repo
|
|
8162
|
+
] }),
|
|
8163
|
+
/* @__PURE__ */ jsxs12(Text13, { children: [
|
|
8164
|
+
"Status: ",
|
|
8165
|
+
session.status
|
|
8166
|
+
] }),
|
|
8167
|
+
/* @__PURE__ */ jsxs12(Text13, { children: [
|
|
8168
|
+
"Prompt: ",
|
|
8169
|
+
session.prompt
|
|
8170
|
+
] }),
|
|
8171
|
+
session.prUrl && /* @__PURE__ */ jsxs12(Text13, { children: [
|
|
8172
|
+
"PR: ",
|
|
8173
|
+
session.prUrl
|
|
8174
|
+
] }),
|
|
8175
|
+
session.errorMessage && /* @__PURE__ */ jsxs12(Text13, { color: theme.error, children: [
|
|
8176
|
+
"Error: ",
|
|
8177
|
+
session.errorMessage
|
|
8178
|
+
] }),
|
|
8179
|
+
session.tokensUsed !== void 0 && /* @__PURE__ */ jsxs12(Text13, { children: [
|
|
8180
|
+
"Tokens: ",
|
|
8181
|
+
formatTokens2(session.tokensUsed),
|
|
8182
|
+
session.tokensBudget ? ` / ${formatTokens2(session.tokensBudget)}` : ""
|
|
8183
|
+
] }),
|
|
8184
|
+
/* @__PURE__ */ jsxs12(Text13, { children: [
|
|
8185
|
+
"Created: ",
|
|
8186
|
+
new Date(session.createdAt).toLocaleString()
|
|
8187
|
+
] }),
|
|
8188
|
+
session.finishedAt && /* @__PURE__ */ jsxs12(Text13, { children: [
|
|
8189
|
+
"Finished: ",
|
|
8190
|
+
new Date(session.finishedAt).toLocaleString()
|
|
8191
|
+
] })
|
|
8192
|
+
] }),
|
|
8193
|
+
/* @__PURE__ */ jsxs12(Box12, { marginTop: 1, flexDirection: "row", gap: 2, children: [
|
|
8194
|
+
isRunning && onCancel && /* @__PURE__ */ jsx14(Text13, { color: theme.error, children: cancelling ? "Cancelling..." : "[C] Cancel session" }),
|
|
8195
|
+
/* @__PURE__ */ jsx14(Text13, { dimColor: true, children: "Esc back" })
|
|
8196
|
+
] })
|
|
8197
|
+
] });
|
|
8198
|
+
}
|
|
8199
|
+
var init_remote_dashboard = __esm({
|
|
8200
|
+
"src/ui/remote-dashboard.tsx"() {
|
|
8201
|
+
"use strict";
|
|
8202
|
+
init_theme_context();
|
|
8203
|
+
init_session_store();
|
|
8204
|
+
init_worker_client();
|
|
8205
|
+
}
|
|
8206
|
+
});
|
|
8207
|
+
|
|
8208
|
+
// src/intent/classify.ts
|
|
8209
|
+
function classifyIntent(prompt) {
|
|
8210
|
+
let intentScore = 0;
|
|
8211
|
+
let matchedIntent = "other";
|
|
8212
|
+
for (const [intent, pattern] of Object.entries(INTENT_PATTERNS)) {
|
|
8213
|
+
const matches = (prompt.match(pattern) || []).length;
|
|
8214
|
+
if (matches > intentScore) {
|
|
8215
|
+
intentScore = matches;
|
|
8216
|
+
matchedIntent = intent;
|
|
8217
|
+
}
|
|
8218
|
+
}
|
|
8219
|
+
const hasFileMentions = (prompt.match(/@\w+|\b[\w/-]+\.(ts|tsx|js|jsx|py|go|rs)\b/g) || []).length;
|
|
8220
|
+
const hasMutatingVerb = /\b(add|create|write|edit|delete|remove|rename|migrate|implement)\b/i.test(prompt);
|
|
8221
|
+
const isQuestion = prompt.trim().endsWith("?") || /\b(what|how|why|is|does|can)\b/i.test(prompt.split(" ")[0] || "");
|
|
8222
|
+
const rawScore = Math.min(
|
|
8223
|
+
1,
|
|
8224
|
+
intentScore * 0.25 + (hasFileMentions > 2 ? 0.3 : hasFileMentions * 0.1) + (hasMutatingVerb ? 0.25 : 0) + (isQuestion ? 0 : 0.1)
|
|
8225
|
+
);
|
|
8226
|
+
const tier = rawScore < 0.3 ? "light" : rawScore < 0.65 ? "medium" : "heavy";
|
|
8227
|
+
return {
|
|
8228
|
+
intent: matchedIntent,
|
|
8229
|
+
rawScore,
|
|
8230
|
+
tier,
|
|
8231
|
+
confidence: 0.5 + (intentScore > 0 ? 0.3 : 0) + (hasFileMentions > 0 ? 0.1 : 0)
|
|
8232
|
+
};
|
|
8233
|
+
}
|
|
8234
|
+
var INTENT_PATTERNS;
|
|
8235
|
+
var init_classify = __esm({
|
|
8236
|
+
"src/intent/classify.ts"() {
|
|
8237
|
+
"use strict";
|
|
8238
|
+
INTENT_PATTERNS = {
|
|
8239
|
+
qa: /\b(what|how|why|explain|describe|what's|what is)\b/i,
|
|
8240
|
+
diagnose: /\b(broken|failing|error|bug|crash|why.*fail|not working)\b/i,
|
|
8241
|
+
verify: /\b(correct|right|verify|review|check|is this|does this)\b/i,
|
|
8242
|
+
polish: /\b(rename|refactor|extract|move|clean|lint|format)\b/i,
|
|
8243
|
+
small_edit: /\b(add|change|update|fix|remove|delete)\b.+\b(line|here|this|variable|function)\b/i,
|
|
8244
|
+
feature_bounded: /\b(add|implement|create|support)\b.+\b(flag|option|param|arg|field)\b/i,
|
|
8245
|
+
feature_exploratory: /\b(add|implement|migrate|integrate|build)\b.+\b(module|system|auth|oauth|framework|service)\b/i,
|
|
8246
|
+
explore: /\b(how.*work|architecture|structure|where.*used|find.*all|understand)\b/i,
|
|
8247
|
+
meta: /\b(plan|design|strategy|ontology|roadmap|approach)\b/i
|
|
8248
|
+
};
|
|
8249
|
+
}
|
|
8250
|
+
});
|
|
8251
|
+
|
|
8252
|
+
// src/sessions.ts
|
|
8253
|
+
var sessions_exports = {};
|
|
8254
|
+
__export(sessions_exports, {
|
|
8255
|
+
listSessions: () => listSessions,
|
|
8256
|
+
loadSession: () => loadSession,
|
|
8257
|
+
makeSessionId: () => makeSessionId,
|
|
8258
|
+
pruneSessions: () => pruneSessions,
|
|
8259
|
+
saveSession: () => saveSession
|
|
8260
|
+
});
|
|
8261
|
+
import { readFile as readFile11, writeFile as writeFile7, mkdir as mkdir7, readdir as readdir3, stat as stat4 } from "fs/promises";
|
|
8262
|
+
import { homedir as homedir9 } from "os";
|
|
8263
|
+
import { join as join13 } from "path";
|
|
8264
|
+
function sessionsDir2() {
|
|
8265
|
+
const xdg = process.env.XDG_DATA_HOME || join13(homedir9(), ".local", "share");
|
|
8266
|
+
return join13(xdg, "kimiflare", "sessions");
|
|
8267
|
+
}
|
|
8268
|
+
function sanitize(text) {
|
|
8269
|
+
return text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40);
|
|
8270
|
+
}
|
|
8271
|
+
function makeSessionId(firstPrompt) {
|
|
8272
|
+
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
8273
|
+
const slug = sanitize(firstPrompt) || "session";
|
|
8274
|
+
return `${ts}_${slug}`;
|
|
8275
|
+
}
|
|
8276
|
+
async function saveSession(file) {
|
|
8277
|
+
const dir = sessionsDir2();
|
|
8278
|
+
await mkdir7(dir, { recursive: true });
|
|
8279
|
+
const path = join13(dir, `${file.id}.json`);
|
|
8280
|
+
await writeFile7(path, JSON.stringify(file, null, 2), "utf8");
|
|
8281
|
+
return path;
|
|
8282
|
+
}
|
|
8283
|
+
async function pruneSessions() {
|
|
8284
|
+
const dir = sessionsDir2();
|
|
8285
|
+
const files = await listFilesByMtime(dir, /\.json$/);
|
|
8286
|
+
return pruneFiles(files, RETENTION.sessionMaxAgeDays, RETENTION.sessionMaxCount);
|
|
8287
|
+
}
|
|
8288
|
+
async function listSessions(limit = 30, cwd) {
|
|
8289
|
+
const dir = sessionsDir2();
|
|
8290
|
+
let entries;
|
|
8291
|
+
try {
|
|
8292
|
+
entries = await readdir3(dir);
|
|
8293
|
+
} catch {
|
|
8294
|
+
return [];
|
|
8295
|
+
}
|
|
8296
|
+
const summaries = [];
|
|
8297
|
+
for (const name of entries) {
|
|
8298
|
+
if (!name.endsWith(".json")) continue;
|
|
8299
|
+
const path = join13(dir, name);
|
|
8300
|
+
try {
|
|
8301
|
+
const [s, raw] = await Promise.all([stat4(path), readFile11(path, "utf8")]);
|
|
8302
|
+
const parsed = JSON.parse(raw);
|
|
8303
|
+
if (cwd && parsed.cwd !== cwd) continue;
|
|
8304
|
+
const firstUser = parsed.messages.find((m) => m.role === "user");
|
|
8305
|
+
const firstPrompt = typeof firstUser?.content === "string" ? firstUser.content : firstUser?.content ? firstUser.content.find((p) => p.type === "text")?.text ?? "(no prompt)" : "(no prompt)";
|
|
8306
|
+
summaries.push({
|
|
8307
|
+
id: parsed.id,
|
|
8308
|
+
filePath: path,
|
|
8309
|
+
cwd: parsed.cwd,
|
|
8310
|
+
firstPrompt: firstPrompt.slice(0, 80),
|
|
8311
|
+
messageCount: parsed.messages.filter((m) => m.role !== "system").length,
|
|
8312
|
+
updatedAt: parsed.updatedAt ?? s.mtime.toISOString()
|
|
8313
|
+
});
|
|
8314
|
+
} catch {
|
|
8315
|
+
}
|
|
8316
|
+
}
|
|
8317
|
+
summaries.sort((a, b) => b.updatedAt < a.updatedAt ? -1 : 1);
|
|
8318
|
+
return summaries.slice(0, limit);
|
|
8319
|
+
}
|
|
8320
|
+
async function loadSession(filePath) {
|
|
8321
|
+
const raw = await readFile11(filePath, "utf8");
|
|
8322
|
+
return JSON.parse(raw);
|
|
8323
|
+
}
|
|
8324
|
+
var init_sessions = __esm({
|
|
8325
|
+
"src/sessions.ts"() {
|
|
8326
|
+
"use strict";
|
|
8327
|
+
init_storage_limits();
|
|
8328
|
+
}
|
|
8329
|
+
});
|
|
8330
|
+
|
|
8331
|
+
// src/util/image.ts
|
|
8332
|
+
import { readFile as readFile12 } from "fs/promises";
|
|
8333
|
+
import { basename as basename3 } from "path";
|
|
8334
|
+
async function encodeImageFile(filePath) {
|
|
8335
|
+
const buf = await readFile12(filePath);
|
|
8336
|
+
if (buf.byteLength > MAX_IMAGE_BYTES) {
|
|
8337
|
+
throw new Error(
|
|
8338
|
+
`image too large (${(buf.byteLength / 1024 / 1024).toFixed(1)} MB); max is ${MAX_IMAGE_BYTES / 1024 / 1024} MB`
|
|
8339
|
+
);
|
|
8340
|
+
}
|
|
8341
|
+
const ext = filePath.slice(filePath.lastIndexOf(".")).toLowerCase();
|
|
8342
|
+
const mime = EXT_TO_MIME[ext] ?? "image/jpeg";
|
|
7518
8343
|
const b64 = buf.toString("base64");
|
|
7519
8344
|
return {
|
|
7520
8345
|
filename: basename3(filePath),
|
|
@@ -7543,15 +8368,15 @@ var init_image = __esm({
|
|
|
7543
8368
|
});
|
|
7544
8369
|
|
|
7545
8370
|
// src/usage-tracker.ts
|
|
7546
|
-
import { readFile as
|
|
7547
|
-
import { homedir as
|
|
7548
|
-
import { join as
|
|
8371
|
+
import { readFile as readFile13, writeFile as writeFile8, mkdir as mkdir8 } from "fs/promises";
|
|
8372
|
+
import { homedir as homedir10 } from "os";
|
|
8373
|
+
import { join as join14 } from "path";
|
|
7549
8374
|
function usageDir2() {
|
|
7550
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
7551
|
-
return
|
|
8375
|
+
const xdg = process.env.XDG_DATA_HOME || join14(homedir10(), ".local", "share");
|
|
8376
|
+
return join14(xdg, "kimiflare");
|
|
7552
8377
|
}
|
|
7553
8378
|
function usagePath2() {
|
|
7554
|
-
return
|
|
8379
|
+
return join14(usageDir2(), "usage.json");
|
|
7555
8380
|
}
|
|
7556
8381
|
function today2() {
|
|
7557
8382
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
@@ -7562,7 +8387,7 @@ function cutoffDate(daysBack) {
|
|
|
7562
8387
|
}
|
|
7563
8388
|
async function loadLog2() {
|
|
7564
8389
|
try {
|
|
7565
|
-
const raw = await
|
|
8390
|
+
const raw = await readFile13(usagePath2(), "utf8");
|
|
7566
8391
|
const parsed = JSON.parse(raw);
|
|
7567
8392
|
if (parsed.version === LOG_VERSION2) return parsed;
|
|
7568
8393
|
} catch {
|
|
@@ -7570,8 +8395,8 @@ async function loadLog2() {
|
|
|
7570
8395
|
return { version: LOG_VERSION2, days: [], sessions: [] };
|
|
7571
8396
|
}
|
|
7572
8397
|
async function saveLog(log) {
|
|
7573
|
-
await
|
|
7574
|
-
await
|
|
8398
|
+
await mkdir8(usageDir2(), { recursive: true });
|
|
8399
|
+
await writeFile8(usagePath2(), JSON.stringify(log, null, 2), "utf8");
|
|
7575
8400
|
}
|
|
7576
8401
|
function getOrCreateDay(log, date) {
|
|
7577
8402
|
let day = log.days.find((d) => d.date === date);
|
|
@@ -7777,7 +8602,7 @@ __export(db_exports, {
|
|
|
7777
8602
|
updateMemoryEmbedding: () => updateMemoryEmbedding
|
|
7778
8603
|
});
|
|
7779
8604
|
import Database from "better-sqlite3";
|
|
7780
|
-
import { dirname as
|
|
8605
|
+
import { dirname as dirname6 } from "path";
|
|
7781
8606
|
import { mkdirSync, statSync as statSync2 } from "fs";
|
|
7782
8607
|
function initSchema(db) {
|
|
7783
8608
|
db.exec(`
|
|
@@ -7862,7 +8687,7 @@ function openMemoryDb(dbPath) {
|
|
|
7862
8687
|
if (dbInstance) {
|
|
7863
8688
|
dbInstance.close();
|
|
7864
8689
|
}
|
|
7865
|
-
mkdirSync(
|
|
8690
|
+
mkdirSync(dirname6(dbPath), { recursive: true });
|
|
7866
8691
|
dbInstance = new Database(dbPath);
|
|
7867
8692
|
dbInstance.pragma("journal_mode = WAL");
|
|
7868
8693
|
dbInstance.pragma("foreign_keys = ON");
|
|
@@ -8156,7 +8981,7 @@ function truncateForEmbedding(text) {
|
|
|
8156
8981
|
if (text.length <= MAX_EMBED_CHARS) return text;
|
|
8157
8982
|
return text.slice(0, MAX_EMBED_CHARS);
|
|
8158
8983
|
}
|
|
8159
|
-
async function
|
|
8984
|
+
async function sleep3(ms) {
|
|
8160
8985
|
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
8161
8986
|
}
|
|
8162
8987
|
async function fetchWithRetry(url, init, retries = 3) {
|
|
@@ -8167,7 +8992,7 @@ async function fetchWithRetry(url, init, retries = 3) {
|
|
|
8167
8992
|
if (res.ok) return res;
|
|
8168
8993
|
if (res.status === 429 || res.status >= 500) {
|
|
8169
8994
|
const delay = 1e3 * 2 ** i;
|
|
8170
|
-
await
|
|
8995
|
+
await sleep3(delay);
|
|
8171
8996
|
continue;
|
|
8172
8997
|
}
|
|
8173
8998
|
const errText = await res.text().catch(() => "unknown error");
|
|
@@ -8175,7 +9000,7 @@ async function fetchWithRetry(url, init, retries = 3) {
|
|
|
8175
9000
|
} catch (e) {
|
|
8176
9001
|
lastError = e;
|
|
8177
9002
|
if (i < retries - 1) {
|
|
8178
|
-
await
|
|
9003
|
+
await sleep3(1e3 * 2 ** i);
|
|
8179
9004
|
}
|
|
8180
9005
|
}
|
|
8181
9006
|
}
|
|
@@ -8789,16 +9614,16 @@ Context: This memory was explicitly provided by the user during a conversation.`
|
|
|
8789
9614
|
});
|
|
8790
9615
|
|
|
8791
9616
|
// src/util/state.ts
|
|
8792
|
-
import { readFile as
|
|
8793
|
-
import { homedir as
|
|
8794
|
-
import { join as
|
|
9617
|
+
import { readFile as readFile14, writeFile as writeFile9, mkdir as mkdir9 } from "fs/promises";
|
|
9618
|
+
import { homedir as homedir11 } from "os";
|
|
9619
|
+
import { join as join16 } from "path";
|
|
8795
9620
|
function statePath() {
|
|
8796
|
-
const xdg = process.env.XDG_CONFIG_HOME ||
|
|
8797
|
-
return
|
|
9621
|
+
const xdg = process.env.XDG_CONFIG_HOME || join16(homedir11(), ".config");
|
|
9622
|
+
return join16(xdg, "kimiflare", "state.json");
|
|
8798
9623
|
}
|
|
8799
9624
|
async function readState() {
|
|
8800
9625
|
try {
|
|
8801
|
-
const raw = await
|
|
9626
|
+
const raw = await readFile14(statePath(), "utf8");
|
|
8802
9627
|
return JSON.parse(raw);
|
|
8803
9628
|
} catch {
|
|
8804
9629
|
return {};
|
|
@@ -8806,8 +9631,8 @@ async function readState() {
|
|
|
8806
9631
|
}
|
|
8807
9632
|
async function writeState(state) {
|
|
8808
9633
|
const path = statePath();
|
|
8809
|
-
await
|
|
8810
|
-
await
|
|
9634
|
+
await mkdir9(join16(path, ".."), { recursive: true });
|
|
9635
|
+
await writeFile9(path, JSON.stringify(state, null, 2) + "\n", "utf8");
|
|
8811
9636
|
}
|
|
8812
9637
|
async function markCreatorMessageSeen(version) {
|
|
8813
9638
|
const state = await readState();
|
|
@@ -8880,15 +9705,15 @@ var init_frontmatter = __esm({
|
|
|
8880
9705
|
|
|
8881
9706
|
// src/commands/loader.ts
|
|
8882
9707
|
import { open, realpath } from "fs/promises";
|
|
8883
|
-
import { homedir as
|
|
8884
|
-
import { join as
|
|
9708
|
+
import { homedir as homedir12 } from "os";
|
|
9709
|
+
import { join as join17, relative as relative4, sep as sep2 } from "path";
|
|
8885
9710
|
import fg3 from "fast-glob";
|
|
8886
9711
|
function projectCommandsDir(cwd = process.cwd()) {
|
|
8887
|
-
return
|
|
9712
|
+
return join17(cwd, ".kimiflare", "commands");
|
|
8888
9713
|
}
|
|
8889
9714
|
function globalCommandsDir() {
|
|
8890
|
-
const xdg = process.env.XDG_CONFIG_HOME ||
|
|
8891
|
-
return
|
|
9715
|
+
const xdg = process.env.XDG_CONFIG_HOME || join17(homedir12(), ".config");
|
|
9716
|
+
return join17(xdg, "kimiflare", "commands");
|
|
8892
9717
|
}
|
|
8893
9718
|
async function loadCustomCommands(cwd = process.cwd()) {
|
|
8894
9719
|
const warnings = [];
|
|
@@ -9250,6 +10075,7 @@ var init_builtins = __esm({
|
|
|
9250
10075
|
{ name: "compact", description: "Summarize old turns to free context", source: "builtin" },
|
|
9251
10076
|
{ name: "clear", description: "Clear current conversation", source: "builtin" },
|
|
9252
10077
|
{ name: "init", description: "Scan repo and write KIMI.md", source: "builtin" },
|
|
10078
|
+
{ name: "remote", argHint: "<prompt>", description: "Run a remote session on Cloudflare", source: "builtin" },
|
|
9253
10079
|
{ name: "update", description: "Check for updates", source: "builtin" },
|
|
9254
10080
|
{ name: "hello", description: "Send a voice note to the creator", source: "builtin" },
|
|
9255
10081
|
{ name: "logout", description: "Clear stored credentials", source: "builtin" },
|
|
@@ -9263,8 +10089,8 @@ var init_builtins = __esm({
|
|
|
9263
10089
|
});
|
|
9264
10090
|
|
|
9265
10091
|
// src/commands/save.ts
|
|
9266
|
-
import { mkdir as
|
|
9267
|
-
import { dirname as
|
|
10092
|
+
import { mkdir as mkdir10, writeFile as writeFile10, unlink as unlink2 } from "fs/promises";
|
|
10093
|
+
import { dirname as dirname7 } from "path";
|
|
9268
10094
|
async function saveCustomCommand(opts2) {
|
|
9269
10095
|
const dir = opts2.source === "project" ? projectCommandsDir(opts2.cwd) : globalCommandsDir();
|
|
9270
10096
|
const filepath = `${dir}/${opts2.name}.md`;
|
|
@@ -9275,8 +10101,8 @@ async function saveCustomCommand(opts2) {
|
|
|
9275
10101
|
if (opts2.effort) data.effort = opts2.effort;
|
|
9276
10102
|
const frontmatter = serializeFrontmatter(data);
|
|
9277
10103
|
const content = frontmatter + opts2.template;
|
|
9278
|
-
await
|
|
9279
|
-
await
|
|
10104
|
+
await mkdir10(dirname7(filepath), { recursive: true });
|
|
10105
|
+
await writeFile10(filepath, content, "utf8");
|
|
9280
10106
|
return { filepath };
|
|
9281
10107
|
}
|
|
9282
10108
|
async function deleteCustomCommand(cmd) {
|
|
@@ -9291,21 +10117,21 @@ var init_save = __esm({
|
|
|
9291
10117
|
});
|
|
9292
10118
|
|
|
9293
10119
|
// src/ui/command-wizard.tsx
|
|
9294
|
-
import { useState as
|
|
9295
|
-
import { Box as
|
|
9296
|
-
import
|
|
9297
|
-
import { Fragment as Fragment2, jsx as
|
|
10120
|
+
import { useState as useState8 } from "react";
|
|
10121
|
+
import { Box as Box13, Text as Text14, useInput as useInput4, useWindowSize as useWindowSize2 } from "ink";
|
|
10122
|
+
import SelectInput5 from "ink-select-input";
|
|
10123
|
+
import { Fragment as Fragment2, jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
9298
10124
|
function CommandWizard({ mode, initial, existingNames, builtinNames, onDone, onSave }) {
|
|
9299
10125
|
const theme = useTheme();
|
|
9300
|
-
const [step, setStep] =
|
|
9301
|
-
const [name, setName] =
|
|
9302
|
-
const [description, setDescription] =
|
|
9303
|
-
const [template, setTemplate] =
|
|
9304
|
-
const [cmdMode, setCmdMode] =
|
|
9305
|
-
const [cmdEffort, setCmdEffort] =
|
|
9306
|
-
const [cmdModel, setCmdModel] =
|
|
9307
|
-
const [source, setSource] =
|
|
9308
|
-
const [error, setError] =
|
|
10126
|
+
const [step, setStep] = useState8("name");
|
|
10127
|
+
const [name, setName] = useState8(initial?.name ?? "");
|
|
10128
|
+
const [description, setDescription] = useState8(initial?.description ?? "");
|
|
10129
|
+
const [template, setTemplate] = useState8(initial?.template ?? "");
|
|
10130
|
+
const [cmdMode, setCmdMode] = useState8(initial?.mode);
|
|
10131
|
+
const [cmdEffort, setCmdEffort] = useState8(initial?.effort);
|
|
10132
|
+
const [cmdModel, setCmdModel] = useState8(initial?.model);
|
|
10133
|
+
const [source, setSource] = useState8(initial?.source ?? "project");
|
|
10134
|
+
const [error, setError] = useState8(null);
|
|
9309
10135
|
const { columns } = useWindowSize2();
|
|
9310
10136
|
const totalSteps = 5;
|
|
9311
10137
|
const stepIndex = step === "name" ? 1 : step === "description" ? 2 : step === "template" ? 3 : step === "advanced" || step === "mode" || step === "effort" || step === "model" ? 4 : step === "location" ? 4 : 5;
|
|
@@ -9318,7 +10144,7 @@ function CommandWizard({ mode, initial, existingNames, builtinNames, onDone, onS
|
|
|
9318
10144
|
if (existingNames.includes(trimmed) && !isEditingSelf(trimmed)) return `/${trimmed} already exists`;
|
|
9319
10145
|
return null;
|
|
9320
10146
|
};
|
|
9321
|
-
|
|
10147
|
+
useInput4((_input, key) => {
|
|
9322
10148
|
if (key.escape) {
|
|
9323
10149
|
onDone();
|
|
9324
10150
|
}
|
|
@@ -9418,8 +10244,8 @@ ${template}`;
|
|
|
9418
10244
|
const renderStep = () => {
|
|
9419
10245
|
switch (step) {
|
|
9420
10246
|
case "name":
|
|
9421
|
-
return /* @__PURE__ */
|
|
9422
|
-
/* @__PURE__ */
|
|
10247
|
+
return /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
10248
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
|
|
9423
10249
|
mode === "create" ? "Create" : "Edit",
|
|
9424
10250
|
" custom command \u2014 Name (",
|
|
9425
10251
|
stepIndex,
|
|
@@ -9427,8 +10253,8 @@ ${template}`;
|
|
|
9427
10253
|
totalSteps,
|
|
9428
10254
|
")"
|
|
9429
10255
|
] }),
|
|
9430
|
-
error && /* @__PURE__ */
|
|
9431
|
-
/* @__PURE__ */
|
|
10256
|
+
error && /* @__PURE__ */ jsx15(Text14, { color: theme.error, children: error }),
|
|
10257
|
+
/* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
|
|
9432
10258
|
CustomTextInput,
|
|
9433
10259
|
{
|
|
9434
10260
|
value: name,
|
|
@@ -9437,11 +10263,11 @@ ${template}`;
|
|
|
9437
10263
|
focus: true
|
|
9438
10264
|
}
|
|
9439
10265
|
) }),
|
|
9440
|
-
/* @__PURE__ */
|
|
10266
|
+
/* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "letters, numbers, _ - / only; must start with a letter" })
|
|
9441
10267
|
] });
|
|
9442
10268
|
case "description":
|
|
9443
|
-
return /* @__PURE__ */
|
|
9444
|
-
/* @__PURE__ */
|
|
10269
|
+
return /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
10270
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
|
|
9445
10271
|
mode === "create" ? "Create" : "Edit",
|
|
9446
10272
|
" custom command \u2014 Description (",
|
|
9447
10273
|
stepIndex,
|
|
@@ -9449,7 +10275,7 @@ ${template}`;
|
|
|
9449
10275
|
totalSteps,
|
|
9450
10276
|
")"
|
|
9451
10277
|
] }),
|
|
9452
|
-
/* @__PURE__ */
|
|
10278
|
+
/* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
|
|
9453
10279
|
CustomTextInput,
|
|
9454
10280
|
{
|
|
9455
10281
|
value: description,
|
|
@@ -9458,49 +10284,49 @@ ${template}`;
|
|
|
9458
10284
|
focus: true
|
|
9459
10285
|
}
|
|
9460
10286
|
) }),
|
|
9461
|
-
/* @__PURE__ */
|
|
10287
|
+
/* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Press Enter to skip" })
|
|
9462
10288
|
] });
|
|
9463
10289
|
case "template": {
|
|
9464
|
-
const guide = /* @__PURE__ */
|
|
9465
|
-
/* @__PURE__ */
|
|
9466
|
-
/* @__PURE__ */
|
|
9467
|
-
/* @__PURE__ */
|
|
10290
|
+
const guide = /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", paddingLeft: 1, children: [
|
|
10291
|
+
/* @__PURE__ */ jsx15(Text14, { color: theme.accent, bold: true, children: "What is this?" }),
|
|
10292
|
+
/* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "A prompt template \u2014 instructions to the AI." }),
|
|
10293
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.info.color, children: [
|
|
9468
10294
|
"When you type /",
|
|
9469
10295
|
name || "yourcommand",
|
|
9470
10296
|
" later, this gets sent to the model."
|
|
9471
10297
|
] }),
|
|
9472
|
-
/* @__PURE__ */
|
|
9473
|
-
/* @__PURE__ */
|
|
9474
|
-
/* @__PURE__ */
|
|
10298
|
+
/* @__PURE__ */ jsxs13(Box13, { marginTop: 1, flexDirection: "column", children: [
|
|
10299
|
+
/* @__PURE__ */ jsx15(Text14, { color: theme.accent, bold: true, children: "Variables" }),
|
|
10300
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.info.color, children: [
|
|
9475
10301
|
" ",
|
|
9476
10302
|
"$1, $2 ... \u2192 arguments you type"
|
|
9477
10303
|
] }),
|
|
9478
|
-
/* @__PURE__ */
|
|
10304
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.info.color, children: [
|
|
9479
10305
|
" ",
|
|
9480
10306
|
"$ARGUMENTS \u2192 everything after the command"
|
|
9481
10307
|
] })
|
|
9482
10308
|
] }),
|
|
9483
|
-
/* @__PURE__ */
|
|
9484
|
-
/* @__PURE__ */
|
|
9485
|
-
/* @__PURE__ */
|
|
10309
|
+
/* @__PURE__ */ jsxs13(Box13, { marginTop: 1, flexDirection: "column", children: [
|
|
10310
|
+
/* @__PURE__ */ jsx15(Text14, { color: theme.accent, bold: true, children: "Dynamic inlines" }),
|
|
10311
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.info.color, children: [
|
|
9486
10312
|
" ",
|
|
9487
10313
|
"!`git diff` \u2192 shell output inlined"
|
|
9488
10314
|
] }),
|
|
9489
|
-
/* @__PURE__ */
|
|
10315
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.info.color, children: [
|
|
9490
10316
|
" ",
|
|
9491
10317
|
"@README.md \u2192 file contents inlined"
|
|
9492
10318
|
] })
|
|
9493
10319
|
] }),
|
|
9494
|
-
/* @__PURE__ */
|
|
9495
|
-
/* @__PURE__ */
|
|
9496
|
-
/* @__PURE__ */
|
|
9497
|
-
/* @__PURE__ */
|
|
9498
|
-
/* @__PURE__ */
|
|
10320
|
+
/* @__PURE__ */ jsxs13(Box13, { marginTop: 1, flexDirection: "column", children: [
|
|
10321
|
+
/* @__PURE__ */ jsx15(Text14, { color: theme.accent, bold: true, children: "Example" }),
|
|
10322
|
+
/* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Review this PR diff:" }),
|
|
10323
|
+
/* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "!`git diff main...HEAD`" }),
|
|
10324
|
+
/* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Focus on: $1" })
|
|
9499
10325
|
] })
|
|
9500
10326
|
] });
|
|
9501
|
-
const inputArea = /* @__PURE__ */
|
|
9502
|
-
error && /* @__PURE__ */
|
|
9503
|
-
/* @__PURE__ */
|
|
10327
|
+
const inputArea = /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", flexGrow: 1, children: [
|
|
10328
|
+
error && /* @__PURE__ */ jsx15(Text14, { color: theme.error, children: error }),
|
|
10329
|
+
/* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
|
|
9504
10330
|
CustomTextInput,
|
|
9505
10331
|
{
|
|
9506
10332
|
value: template,
|
|
@@ -9510,13 +10336,13 @@ ${template}`;
|
|
|
9510
10336
|
enablePaste: true
|
|
9511
10337
|
}
|
|
9512
10338
|
) }),
|
|
9513
|
-
columns < 100 && /* @__PURE__ */
|
|
9514
|
-
/* @__PURE__ */
|
|
9515
|
-
/* @__PURE__ */
|
|
10339
|
+
columns < 100 && /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
10340
|
+
/* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Paste multi-line templates with Ctrl+V." }),
|
|
10341
|
+
/* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Variables: $1 $2 ... $ARGUMENTS Shell: !`cmd` File: @path" })
|
|
9516
10342
|
] })
|
|
9517
10343
|
] });
|
|
9518
|
-
return /* @__PURE__ */
|
|
9519
|
-
/* @__PURE__ */
|
|
10344
|
+
return /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
10345
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
|
|
9520
10346
|
mode === "create" ? "Create" : "Edit",
|
|
9521
10347
|
" custom command \u2014 Template (",
|
|
9522
10348
|
stepIndex,
|
|
@@ -9524,10 +10350,10 @@ ${template}`;
|
|
|
9524
10350
|
totalSteps,
|
|
9525
10351
|
")"
|
|
9526
10352
|
] }),
|
|
9527
|
-
columns >= 100 ? /* @__PURE__ */
|
|
9528
|
-
/* @__PURE__ */
|
|
9529
|
-
/* @__PURE__ */
|
|
9530
|
-
] }) : /* @__PURE__ */
|
|
10353
|
+
columns >= 100 ? /* @__PURE__ */ jsxs13(Box13, { flexDirection: "row", marginTop: 1, children: [
|
|
10354
|
+
/* @__PURE__ */ jsx15(Box13, { flexDirection: "column", width: "50%", children: inputArea }),
|
|
10355
|
+
/* @__PURE__ */ jsx15(Box13, { flexDirection: "column", width: "50%", children: guide })
|
|
10356
|
+
] }) : /* @__PURE__ */ jsx15(Box13, { flexDirection: "column", marginTop: 1, children: inputArea })
|
|
9531
10357
|
] });
|
|
9532
10358
|
}
|
|
9533
10359
|
case "advanced": {
|
|
@@ -9536,8 +10362,8 @@ ${template}`;
|
|
|
9536
10362
|
{ label: "Skip", value: "skip", key: "skip" },
|
|
9537
10363
|
{ label: "\u2190 Cancel", value: "cancel", key: "cancel" }
|
|
9538
10364
|
];
|
|
9539
|
-
return /* @__PURE__ */
|
|
9540
|
-
/* @__PURE__ */
|
|
10365
|
+
return /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
10366
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
|
|
9541
10367
|
mode === "create" ? "Create" : "Edit",
|
|
9542
10368
|
" custom command \u2014 Options (",
|
|
9543
10369
|
stepIndex,
|
|
@@ -9545,8 +10371,8 @@ ${template}`;
|
|
|
9545
10371
|
totalSteps,
|
|
9546
10372
|
")"
|
|
9547
10373
|
] }),
|
|
9548
|
-
/* @__PURE__ */
|
|
9549
|
-
|
|
10374
|
+
/* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
|
|
10375
|
+
SelectInput5,
|
|
9550
10376
|
{
|
|
9551
10377
|
items,
|
|
9552
10378
|
onSelect: (item) => {
|
|
@@ -9565,17 +10391,17 @@ ${template}`;
|
|
|
9565
10391
|
{ label: cmdMode === "auto" ? "auto \xB7 current" : "auto", value: "auto", key: "auto" },
|
|
9566
10392
|
{ label: "\u2190 Back", value: "__back__", key: "__back__" }
|
|
9567
10393
|
];
|
|
9568
|
-
return /* @__PURE__ */
|
|
9569
|
-
/* @__PURE__ */
|
|
10394
|
+
return /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
10395
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
|
|
9570
10396
|
"Mode override (",
|
|
9571
10397
|
stepIndex,
|
|
9572
10398
|
"/",
|
|
9573
10399
|
totalSteps,
|
|
9574
10400
|
")"
|
|
9575
10401
|
] }),
|
|
9576
|
-
/* @__PURE__ */
|
|
9577
|
-
/* @__PURE__ */
|
|
9578
|
-
|
|
10402
|
+
/* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Saved to file but not yet enforced at runtime" }),
|
|
10403
|
+
/* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
|
|
10404
|
+
SelectInput5,
|
|
9579
10405
|
{
|
|
9580
10406
|
items,
|
|
9581
10407
|
onSelect: (item) => {
|
|
@@ -9594,16 +10420,16 @@ ${template}`;
|
|
|
9594
10420
|
{ label: cmdEffort === "high" ? "high \xB7 current" : "high", value: "high", key: "high" },
|
|
9595
10421
|
{ label: "\u2190 Back", value: "__back__", key: "__back__" }
|
|
9596
10422
|
];
|
|
9597
|
-
return /* @__PURE__ */
|
|
9598
|
-
/* @__PURE__ */
|
|
10423
|
+
return /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
10424
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
|
|
9599
10425
|
"Reasoning effort (",
|
|
9600
10426
|
stepIndex,
|
|
9601
10427
|
"/",
|
|
9602
10428
|
totalSteps,
|
|
9603
10429
|
")"
|
|
9604
10430
|
] }),
|
|
9605
|
-
/* @__PURE__ */
|
|
9606
|
-
|
|
10431
|
+
/* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
|
|
10432
|
+
SelectInput5,
|
|
9607
10433
|
{
|
|
9608
10434
|
items,
|
|
9609
10435
|
onSelect: (item) => {
|
|
@@ -9615,15 +10441,15 @@ ${template}`;
|
|
|
9615
10441
|
] });
|
|
9616
10442
|
}
|
|
9617
10443
|
case "model":
|
|
9618
|
-
return /* @__PURE__ */
|
|
9619
|
-
/* @__PURE__ */
|
|
10444
|
+
return /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
10445
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
|
|
9620
10446
|
"Model override (",
|
|
9621
10447
|
stepIndex,
|
|
9622
10448
|
"/",
|
|
9623
10449
|
totalSteps,
|
|
9624
10450
|
")"
|
|
9625
10451
|
] }),
|
|
9626
|
-
/* @__PURE__ */
|
|
10452
|
+
/* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
|
|
9627
10453
|
CustomTextInput,
|
|
9628
10454
|
{
|
|
9629
10455
|
value: cmdModel ?? "",
|
|
@@ -9632,7 +10458,7 @@ ${template}`;
|
|
|
9632
10458
|
focus: true
|
|
9633
10459
|
}
|
|
9634
10460
|
) }),
|
|
9635
|
-
/* @__PURE__ */
|
|
10461
|
+
/* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Press Enter to skip" })
|
|
9636
10462
|
] });
|
|
9637
10463
|
case "location": {
|
|
9638
10464
|
const items = [
|
|
@@ -9640,16 +10466,16 @@ ${template}`;
|
|
|
9640
10466
|
{ label: source === "global" ? "Global \xB7 current" : "Global", value: "global", key: "global" },
|
|
9641
10467
|
{ label: "\u2190 Back", value: "__back__", key: "__back__" }
|
|
9642
10468
|
];
|
|
9643
|
-
return /* @__PURE__ */
|
|
9644
|
-
/* @__PURE__ */
|
|
10469
|
+
return /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
10470
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
|
|
9645
10471
|
"Save location (",
|
|
9646
10472
|
stepIndex,
|
|
9647
10473
|
"/",
|
|
9648
10474
|
totalSteps,
|
|
9649
10475
|
")"
|
|
9650
10476
|
] }),
|
|
9651
|
-
/* @__PURE__ */
|
|
9652
|
-
|
|
10477
|
+
/* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
|
|
10478
|
+
SelectInput5,
|
|
9653
10479
|
{
|
|
9654
10480
|
items,
|
|
9655
10481
|
onSelect: (item) => {
|
|
@@ -9658,7 +10484,7 @@ ${template}`;
|
|
|
9658
10484
|
}
|
|
9659
10485
|
}
|
|
9660
10486
|
) }),
|
|
9661
|
-
/* @__PURE__ */
|
|
10487
|
+
/* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Project: .kimiflare/commands/ Global: ~/.config/kimiflare/commands/" })
|
|
9662
10488
|
] });
|
|
9663
10489
|
}
|
|
9664
10490
|
case "confirm": {
|
|
@@ -9666,8 +10492,8 @@ ${template}`;
|
|
|
9666
10492
|
{ label: "Save", value: "save", key: "save" },
|
|
9667
10493
|
{ label: "Cancel", value: "cancel", key: "cancel" }
|
|
9668
10494
|
];
|
|
9669
|
-
return /* @__PURE__ */
|
|
9670
|
-
/* @__PURE__ */
|
|
10495
|
+
return /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
10496
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
|
|
9671
10497
|
mode === "create" ? "Create" : "Edit",
|
|
9672
10498
|
" custom command \u2014 Confirm (",
|
|
9673
10499
|
stepIndex,
|
|
@@ -9675,14 +10501,14 @@ ${template}`;
|
|
|
9675
10501
|
totalSteps,
|
|
9676
10502
|
")"
|
|
9677
10503
|
] }),
|
|
9678
|
-
/* @__PURE__ */
|
|
10504
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.info.color, children: [
|
|
9679
10505
|
source === "project" ? ".kimiflare/commands/" : "~/.config/kimiflare/commands/",
|
|
9680
10506
|
name,
|
|
9681
10507
|
".md"
|
|
9682
10508
|
] }),
|
|
9683
|
-
/* @__PURE__ */
|
|
9684
|
-
/* @__PURE__ */
|
|
9685
|
-
|
|
10509
|
+
/* @__PURE__ */ jsx15(Box13, { marginTop: 1, flexDirection: "column", children: previewContent().split("\n").map((line, i) => /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: line || " " }, i)) }),
|
|
10510
|
+
/* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
|
|
10511
|
+
SelectInput5,
|
|
9686
10512
|
{
|
|
9687
10513
|
items,
|
|
9688
10514
|
onSelect: (item) => handleConfirm(item.value)
|
|
@@ -9692,7 +10518,7 @@ ${template}`;
|
|
|
9692
10518
|
}
|
|
9693
10519
|
}
|
|
9694
10520
|
};
|
|
9695
|
-
return /* @__PURE__ */
|
|
10521
|
+
return /* @__PURE__ */ jsx15(Box13, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: renderStep() });
|
|
9696
10522
|
}
|
|
9697
10523
|
var NAME_RE;
|
|
9698
10524
|
var init_command_wizard = __esm({
|
|
@@ -9705,9 +10531,9 @@ var init_command_wizard = __esm({
|
|
|
9705
10531
|
});
|
|
9706
10532
|
|
|
9707
10533
|
// src/ui/command-picker.tsx
|
|
9708
|
-
import { Box as
|
|
9709
|
-
import
|
|
9710
|
-
import { jsx as
|
|
10534
|
+
import { Box as Box14, Text as Text15 } from "ink";
|
|
10535
|
+
import SelectInput6 from "ink-select-input";
|
|
10536
|
+
import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
9711
10537
|
function CommandPicker({ commands, title, onPick }) {
|
|
9712
10538
|
const theme = useTheme();
|
|
9713
10539
|
const items = commands.map((cmd) => ({
|
|
@@ -9716,11 +10542,11 @@ function CommandPicker({ commands, title, onPick }) {
|
|
|
9716
10542
|
key: cmd.name
|
|
9717
10543
|
}));
|
|
9718
10544
|
items.push({ label: "\u2190 Cancel", value: null, key: "__cancel__" });
|
|
9719
|
-
return /* @__PURE__ */
|
|
9720
|
-
/* @__PURE__ */
|
|
9721
|
-
/* @__PURE__ */
|
|
9722
|
-
/* @__PURE__ */
|
|
9723
|
-
|
|
10545
|
+
return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
10546
|
+
/* @__PURE__ */ jsx16(Text15, { color: theme.accent, bold: true, children: title }),
|
|
10547
|
+
/* @__PURE__ */ jsx16(Text15, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select." }),
|
|
10548
|
+
/* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(
|
|
10549
|
+
SelectInput6,
|
|
9724
10550
|
{
|
|
9725
10551
|
items,
|
|
9726
10552
|
onSelect: (item) => {
|
|
@@ -9742,64 +10568,64 @@ var init_command_picker = __esm({
|
|
|
9742
10568
|
});
|
|
9743
10569
|
|
|
9744
10570
|
// src/ui/command-list.tsx
|
|
9745
|
-
import { Box as
|
|
9746
|
-
import { jsx as
|
|
10571
|
+
import { Box as Box15, Text as Text16, useInput as useInput5 } from "ink";
|
|
10572
|
+
import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
9747
10573
|
function CommandList({ commands, onDone }) {
|
|
9748
10574
|
const theme = useTheme();
|
|
9749
|
-
|
|
10575
|
+
useInput5((_input, key) => {
|
|
9750
10576
|
if (key.escape) {
|
|
9751
10577
|
onDone();
|
|
9752
10578
|
}
|
|
9753
10579
|
});
|
|
9754
|
-
return /* @__PURE__ */
|
|
9755
|
-
/* @__PURE__ */
|
|
9756
|
-
/* @__PURE__ */
|
|
9757
|
-
/* @__PURE__ */
|
|
9758
|
-
commands.length === 0 && /* @__PURE__ */
|
|
9759
|
-
commands.map((cmd) => /* @__PURE__ */
|
|
9760
|
-
/* @__PURE__ */
|
|
10580
|
+
return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
10581
|
+
/* @__PURE__ */ jsx17(Text16, { color: theme.accent, bold: true, children: "Custom commands" }),
|
|
10582
|
+
/* @__PURE__ */ jsx17(Text16, { color: theme.info.color, dimColor: false, children: "Esc to close." }),
|
|
10583
|
+
/* @__PURE__ */ jsxs15(Box15, { marginTop: 1, flexDirection: "column", children: [
|
|
10584
|
+
commands.length === 0 && /* @__PURE__ */ jsx17(Text16, { color: theme.info.color, children: "No custom commands found." }),
|
|
10585
|
+
commands.map((cmd) => /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", marginBottom: 1, children: [
|
|
10586
|
+
/* @__PURE__ */ jsxs15(Text16, { color: theme.accent, bold: true, children: [
|
|
9761
10587
|
"/",
|
|
9762
10588
|
cmd.name
|
|
9763
10589
|
] }),
|
|
9764
|
-
/* @__PURE__ */
|
|
10590
|
+
/* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
|
|
9765
10591
|
" ",
|
|
9766
10592
|
"source: ",
|
|
9767
10593
|
cmd.source
|
|
9768
10594
|
] }),
|
|
9769
|
-
/* @__PURE__ */
|
|
10595
|
+
/* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
|
|
9770
10596
|
" ",
|
|
9771
10597
|
"path: ",
|
|
9772
10598
|
cmd.filepath
|
|
9773
10599
|
] }),
|
|
9774
|
-
cmd.description && /* @__PURE__ */
|
|
10600
|
+
cmd.description && /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
|
|
9775
10601
|
" ",
|
|
9776
10602
|
"desc: ",
|
|
9777
10603
|
cmd.description
|
|
9778
10604
|
] }),
|
|
9779
|
-
cmd.mode && /* @__PURE__ */
|
|
10605
|
+
cmd.mode && /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
|
|
9780
10606
|
" ",
|
|
9781
10607
|
"mode: ",
|
|
9782
10608
|
cmd.mode
|
|
9783
10609
|
] }),
|
|
9784
|
-
cmd.effort && /* @__PURE__ */
|
|
10610
|
+
cmd.effort && /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
|
|
9785
10611
|
" ",
|
|
9786
10612
|
"effort: ",
|
|
9787
10613
|
cmd.effort
|
|
9788
10614
|
] }),
|
|
9789
|
-
cmd.model && /* @__PURE__ */
|
|
10615
|
+
cmd.model && /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
|
|
9790
10616
|
" ",
|
|
9791
10617
|
"model: ",
|
|
9792
10618
|
cmd.model
|
|
9793
10619
|
] }),
|
|
9794
|
-
/* @__PURE__ */
|
|
10620
|
+
/* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
|
|
9795
10621
|
" ",
|
|
9796
10622
|
"template:"
|
|
9797
10623
|
] }),
|
|
9798
|
-
cmd.template.split("\n").slice(0, 5).map((line, i) => /* @__PURE__ */
|
|
10624
|
+
cmd.template.split("\n").slice(0, 5).map((line, i) => /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
|
|
9799
10625
|
" ",
|
|
9800
10626
|
line || " "
|
|
9801
10627
|
] }, i)),
|
|
9802
|
-
cmd.template.split("\n").length > 5 && /* @__PURE__ */
|
|
10628
|
+
cmd.template.split("\n").length > 5 && /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
|
|
9803
10629
|
" ",
|
|
9804
10630
|
"..."
|
|
9805
10631
|
] })
|
|
@@ -9815,20 +10641,20 @@ var init_command_list = __esm({
|
|
|
9815
10641
|
});
|
|
9816
10642
|
|
|
9817
10643
|
// src/ui/lsp-wizard.tsx
|
|
9818
|
-
import { useState as
|
|
9819
|
-
import { Box as
|
|
9820
|
-
import
|
|
10644
|
+
import { useState as useState9 } from "react";
|
|
10645
|
+
import { Box as Box16, Text as Text17 } from "ink";
|
|
10646
|
+
import SelectInput7 from "ink-select-input";
|
|
9821
10647
|
import { spawn as spawn3 } from "child_process";
|
|
9822
|
-
import { jsx as
|
|
10648
|
+
import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
9823
10649
|
function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
9824
10650
|
const theme = useTheme();
|
|
9825
|
-
const [page, setPage] =
|
|
9826
|
-
const [selectedPreset, setSelectedPreset] =
|
|
9827
|
-
const [customName, setCustomName] =
|
|
9828
|
-
const [customCommand, setCustomCommand] =
|
|
9829
|
-
const [installState, setInstallState] =
|
|
9830
|
-
const [pendingServers, setPendingServers] =
|
|
9831
|
-
const [pendingEnabled, setPendingEnabled] =
|
|
10651
|
+
const [page, setPage] = useState9("main");
|
|
10652
|
+
const [selectedPreset, setSelectedPreset] = useState9(null);
|
|
10653
|
+
const [customName, setCustomName] = useState9("");
|
|
10654
|
+
const [customCommand, setCustomCommand] = useState9("");
|
|
10655
|
+
const [installState, setInstallState] = useState9({ status: "idle", output: "" });
|
|
10656
|
+
const [pendingServers, setPendingServers] = useState9(null);
|
|
10657
|
+
const [pendingEnabled, setPendingEnabled] = useState9(true);
|
|
9832
10658
|
const runInstall = (command) => {
|
|
9833
10659
|
setInstallState({ status: "running", output: "Installing..." });
|
|
9834
10660
|
const child = spawn3("bash", ["-lc", command], {
|
|
@@ -9930,11 +10756,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
9930
10756
|
{ label: "(close)", value: "__close__", key: "__close__" }
|
|
9931
10757
|
];
|
|
9932
10758
|
if (page === "main") {
|
|
9933
|
-
return /* @__PURE__ */
|
|
9934
|
-
/* @__PURE__ */
|
|
9935
|
-
/* @__PURE__ */
|
|
9936
|
-
/* @__PURE__ */
|
|
9937
|
-
|
|
10759
|
+
return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
10760
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "LSP Servers" }),
|
|
10761
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select." }),
|
|
10762
|
+
/* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
|
|
10763
|
+
SelectInput7,
|
|
9938
10764
|
{
|
|
9939
10765
|
items: mainItems,
|
|
9940
10766
|
onSelect: (item) => {
|
|
@@ -9961,11 +10787,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
9961
10787
|
}),
|
|
9962
10788
|
{ label: "\u2190 Back", value: "__back__", key: "__back__" }
|
|
9963
10789
|
];
|
|
9964
|
-
return /* @__PURE__ */
|
|
9965
|
-
/* @__PURE__ */
|
|
9966
|
-
/* @__PURE__ */
|
|
9967
|
-
/* @__PURE__ */
|
|
9968
|
-
|
|
10790
|
+
return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
10791
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Add LSP Server" }),
|
|
10792
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Select a language server to configure." }),
|
|
10793
|
+
/* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
|
|
10794
|
+
SelectInput7,
|
|
9969
10795
|
{
|
|
9970
10796
|
items,
|
|
9971
10797
|
onSelect: (item) => {
|
|
@@ -9992,19 +10818,19 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
9992
10818
|
{ label: isSuccess ? "Save to config \u2713" : "Save anyway", value: "save", key: "save" },
|
|
9993
10819
|
{ label: "\u2190 Back", value: "__back__", key: "__back__" }
|
|
9994
10820
|
];
|
|
9995
|
-
return /* @__PURE__ */
|
|
9996
|
-
/* @__PURE__ */
|
|
10821
|
+
return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
10822
|
+
/* @__PURE__ */ jsxs16(Text17, { color: theme.accent, bold: true, children: [
|
|
9997
10823
|
"Install ",
|
|
9998
10824
|
selectedPreset.name
|
|
9999
10825
|
] }),
|
|
10000
|
-
/* @__PURE__ */
|
|
10001
|
-
/* @__PURE__ */
|
|
10002
|
-
/* @__PURE__ */
|
|
10003
|
-
/* @__PURE__ */
|
|
10826
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: selectedPreset.installHint }),
|
|
10827
|
+
/* @__PURE__ */ jsxs16(Box16, { marginTop: 1, flexDirection: "column", children: [
|
|
10828
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Command:" }),
|
|
10829
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.accent, children: selectedPreset.installCommand || "(none required)" })
|
|
10004
10830
|
] }),
|
|
10005
|
-
installState.output && /* @__PURE__ */
|
|
10006
|
-
/* @__PURE__ */
|
|
10007
|
-
|
|
10831
|
+
installState.output && /* @__PURE__ */ jsx18(Box16, { marginTop: 1, flexDirection: "column", children: /* @__PURE__ */ jsx18(Text17, { color: isSuccess ? theme.accent : theme.error, children: installState.output.slice(-500) }) }),
|
|
10832
|
+
/* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
|
|
10833
|
+
SelectInput7,
|
|
10008
10834
|
{
|
|
10009
10835
|
items,
|
|
10010
10836
|
onSelect: (item) => {
|
|
@@ -10021,16 +10847,16 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
10021
10847
|
}
|
|
10022
10848
|
}
|
|
10023
10849
|
) }),
|
|
10024
|
-
isSuccess && /* @__PURE__ */
|
|
10850
|
+
isSuccess && /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(Text17, { color: theme.accent, children: "Server saved. Run /lsp reload to start it." }) })
|
|
10025
10851
|
] });
|
|
10026
10852
|
}
|
|
10027
10853
|
if (page === "custom-name") {
|
|
10028
|
-
return /* @__PURE__ */
|
|
10029
|
-
/* @__PURE__ */
|
|
10030
|
-
/* @__PURE__ */
|
|
10031
|
-
/* @__PURE__ */
|
|
10032
|
-
/* @__PURE__ */
|
|
10033
|
-
/* @__PURE__ */
|
|
10854
|
+
return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
10855
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Custom LSP Server \u2014 Name" }),
|
|
10856
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Enter a name for this server (e.g., my-server)." }),
|
|
10857
|
+
/* @__PURE__ */ jsxs16(Box16, { marginTop: 1, children: [
|
|
10858
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.accent, children: "\u203A " }),
|
|
10859
|
+
/* @__PURE__ */ jsx18(
|
|
10034
10860
|
CustomTextInput,
|
|
10035
10861
|
{
|
|
10036
10862
|
value: customName,
|
|
@@ -10044,8 +10870,8 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
10044
10870
|
}
|
|
10045
10871
|
)
|
|
10046
10872
|
] }),
|
|
10047
|
-
/* @__PURE__ */
|
|
10048
|
-
|
|
10873
|
+
/* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
|
|
10874
|
+
SelectInput7,
|
|
10049
10875
|
{
|
|
10050
10876
|
items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
|
|
10051
10877
|
onSelect: () => setPage("add")
|
|
@@ -10054,12 +10880,12 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
10054
10880
|
] });
|
|
10055
10881
|
}
|
|
10056
10882
|
if (page === "custom-command") {
|
|
10057
|
-
return /* @__PURE__ */
|
|
10058
|
-
/* @__PURE__ */
|
|
10059
|
-
/* @__PURE__ */
|
|
10060
|
-
/* @__PURE__ */
|
|
10061
|
-
/* @__PURE__ */
|
|
10062
|
-
/* @__PURE__ */
|
|
10883
|
+
return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
10884
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Custom LSP Server \u2014 Command" }),
|
|
10885
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Enter the command to start the server (space-separated)." }),
|
|
10886
|
+
/* @__PURE__ */ jsxs16(Box16, { marginTop: 1, children: [
|
|
10887
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.accent, children: "\u203A " }),
|
|
10888
|
+
/* @__PURE__ */ jsx18(
|
|
10063
10889
|
CustomTextInput,
|
|
10064
10890
|
{
|
|
10065
10891
|
value: customCommand,
|
|
@@ -10073,8 +10899,8 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
10073
10899
|
}
|
|
10074
10900
|
)
|
|
10075
10901
|
] }),
|
|
10076
|
-
/* @__PURE__ */
|
|
10077
|
-
|
|
10902
|
+
/* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
|
|
10903
|
+
SelectInput7,
|
|
10078
10904
|
{
|
|
10079
10905
|
items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
|
|
10080
10906
|
onSelect: () => setPage("custom-name")
|
|
@@ -10097,11 +10923,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
10097
10923
|
},
|
|
10098
10924
|
{ label: "\u2190 Back", value: "__back__", key: "__back__" }
|
|
10099
10925
|
];
|
|
10100
|
-
return /* @__PURE__ */
|
|
10101
|
-
/* @__PURE__ */
|
|
10102
|
-
/* @__PURE__ */
|
|
10103
|
-
/* @__PURE__ */
|
|
10104
|
-
|
|
10926
|
+
return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
10927
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Save LSP Config" }),
|
|
10928
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Where should this server configuration be saved?" }),
|
|
10929
|
+
/* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
|
|
10930
|
+
SelectInput7,
|
|
10105
10931
|
{
|
|
10106
10932
|
items,
|
|
10107
10933
|
onSelect: (item) => {
|
|
@@ -10119,11 +10945,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
10119
10945
|
if (page === "edit") {
|
|
10120
10946
|
const keys = Object.keys(servers);
|
|
10121
10947
|
if (keys.length === 0) {
|
|
10122
|
-
return /* @__PURE__ */
|
|
10123
|
-
/* @__PURE__ */
|
|
10124
|
-
/* @__PURE__ */
|
|
10125
|
-
/* @__PURE__ */
|
|
10126
|
-
|
|
10948
|
+
return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
10949
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Edit LSP Server" }),
|
|
10950
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.info.color, children: "No servers configured." }),
|
|
10951
|
+
/* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
|
|
10952
|
+
SelectInput7,
|
|
10127
10953
|
{
|
|
10128
10954
|
items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
|
|
10129
10955
|
onSelect: () => setPage("main")
|
|
@@ -10143,11 +10969,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
10143
10969
|
}),
|
|
10144
10970
|
{ label: "\u2190 Back", value: "__back__", key: "__back__" }
|
|
10145
10971
|
];
|
|
10146
|
-
return /* @__PURE__ */
|
|
10147
|
-
/* @__PURE__ */
|
|
10148
|
-
/* @__PURE__ */
|
|
10149
|
-
/* @__PURE__ */
|
|
10150
|
-
|
|
10972
|
+
return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
10973
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Edit LSP Server" }),
|
|
10974
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Select a server to toggle enabled/disabled." }),
|
|
10975
|
+
/* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
|
|
10976
|
+
SelectInput7,
|
|
10151
10977
|
{
|
|
10152
10978
|
items,
|
|
10153
10979
|
onSelect: (item) => {
|
|
@@ -10164,11 +10990,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
10164
10990
|
if (page === "delete") {
|
|
10165
10991
|
const keys = Object.keys(servers);
|
|
10166
10992
|
if (keys.length === 0) {
|
|
10167
|
-
return /* @__PURE__ */
|
|
10168
|
-
/* @__PURE__ */
|
|
10169
|
-
/* @__PURE__ */
|
|
10170
|
-
/* @__PURE__ */
|
|
10171
|
-
|
|
10993
|
+
return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
10994
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Delete LSP Server" }),
|
|
10995
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.info.color, children: "No servers configured." }),
|
|
10996
|
+
/* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
|
|
10997
|
+
SelectInput7,
|
|
10172
10998
|
{
|
|
10173
10999
|
items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
|
|
10174
11000
|
onSelect: () => setPage("main")
|
|
@@ -10184,11 +11010,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
10184
11010
|
})),
|
|
10185
11011
|
{ label: "\u2190 Back", value: "__back__", key: "__back__" }
|
|
10186
11012
|
];
|
|
10187
|
-
return /* @__PURE__ */
|
|
10188
|
-
/* @__PURE__ */
|
|
10189
|
-
/* @__PURE__ */
|
|
10190
|
-
/* @__PURE__ */
|
|
10191
|
-
|
|
11013
|
+
return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
11014
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Delete LSP Server" }),
|
|
11015
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Select a server to remove from config." }),
|
|
11016
|
+
/* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
|
|
11017
|
+
SelectInput7,
|
|
10192
11018
|
{
|
|
10193
11019
|
items,
|
|
10194
11020
|
onSelect: (item) => {
|
|
@@ -10204,15 +11030,15 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
10204
11030
|
}
|
|
10205
11031
|
if (page === "list") {
|
|
10206
11032
|
const keys = Object.keys(servers);
|
|
10207
|
-
return /* @__PURE__ */
|
|
10208
|
-
/* @__PURE__ */
|
|
10209
|
-
keys.length === 0 ? /* @__PURE__ */
|
|
11033
|
+
return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
11034
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Configured LSP Servers" }),
|
|
11035
|
+
keys.length === 0 ? /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, children: "No servers configured." }) : /* @__PURE__ */ jsx18(Box16, { marginTop: 1, flexDirection: "column", children: keys.map((k) => {
|
|
10210
11036
|
const s = servers[k];
|
|
10211
11037
|
const status = s.enabled !== false ? "enabled" : "disabled";
|
|
10212
|
-
return /* @__PURE__ */
|
|
11038
|
+
return /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, children: ` ${k.padEnd(16)} ${status} ${s.command.join(" ")}` }, k);
|
|
10213
11039
|
}) }),
|
|
10214
|
-
/* @__PURE__ */
|
|
10215
|
-
|
|
11040
|
+
/* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
|
|
11041
|
+
SelectInput7,
|
|
10216
11042
|
{
|
|
10217
11043
|
items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
|
|
10218
11044
|
onSelect: () => setPage("main")
|
|
@@ -10338,9 +11164,9 @@ var init_lsp_wizard = __esm({
|
|
|
10338
11164
|
});
|
|
10339
11165
|
|
|
10340
11166
|
// src/ui/theme-picker.tsx
|
|
10341
|
-
import { Box as
|
|
10342
|
-
import
|
|
10343
|
-
import { jsx as
|
|
11167
|
+
import { Box as Box17, Text as Text18 } from "ink";
|
|
11168
|
+
import SelectInput8 from "ink-select-input";
|
|
11169
|
+
import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
10344
11170
|
function PaletteSwatches({ palette }) {
|
|
10345
11171
|
const colors = [
|
|
10346
11172
|
palette.primary,
|
|
@@ -10348,7 +11174,7 @@ function PaletteSwatches({ palette }) {
|
|
|
10348
11174
|
palette.success,
|
|
10349
11175
|
palette.error
|
|
10350
11176
|
];
|
|
10351
|
-
return /* @__PURE__ */
|
|
11177
|
+
return /* @__PURE__ */ jsx19(Box17, { children: colors.map((c, i) => /* @__PURE__ */ jsx19(Text18, { color: c, children: "\u2588" }, i)) });
|
|
10352
11178
|
}
|
|
10353
11179
|
function ThemePicker({ themes, onPick, onPreview }) {
|
|
10354
11180
|
const current = useTheme();
|
|
@@ -10356,10 +11182,10 @@ function ThemePicker({ themes, onPick, onPreview }) {
|
|
|
10356
11182
|
...themes.map((t) => ({ label: t.label, value: t.name })),
|
|
10357
11183
|
{ label: "< Back", value: "__back__" }
|
|
10358
11184
|
];
|
|
10359
|
-
return /* @__PURE__ */
|
|
10360
|
-
/* @__PURE__ */
|
|
10361
|
-
/* @__PURE__ */
|
|
10362
|
-
|
|
11185
|
+
return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: current.accent, paddingX: 1, children: [
|
|
11186
|
+
/* @__PURE__ */ jsx19(Text18, { color: current.accent, bold: true, children: "Pick a theme" }),
|
|
11187
|
+
/* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
|
|
11188
|
+
SelectInput8,
|
|
10363
11189
|
{
|
|
10364
11190
|
items,
|
|
10365
11191
|
onHighlight: (item) => {
|
|
@@ -10378,9 +11204,9 @@ function ThemePicker({ themes, onPick, onPreview }) {
|
|
|
10378
11204
|
itemComponent: ({ label, isSelected }) => {
|
|
10379
11205
|
const t = themes.find((x) => x.label === label);
|
|
10380
11206
|
const color = t?.accent ?? current.accent;
|
|
10381
|
-
return /* @__PURE__ */
|
|
10382
|
-
/* @__PURE__ */
|
|
10383
|
-
t && /* @__PURE__ */
|
|
11207
|
+
return /* @__PURE__ */ jsxs17(Box17, { children: [
|
|
11208
|
+
/* @__PURE__ */ jsx19(Text18, { color, bold: isSelected, dimColor: !isSelected, children: label }),
|
|
11209
|
+
t && /* @__PURE__ */ jsx19(Box17, { marginLeft: 1, children: /* @__PURE__ */ jsx19(PaletteSwatches, { palette: t.palette }) })
|
|
10384
11210
|
] });
|
|
10385
11211
|
}
|
|
10386
11212
|
}
|
|
@@ -10524,8 +11350,8 @@ var init_lsp_nudge = __esm({
|
|
|
10524
11350
|
});
|
|
10525
11351
|
|
|
10526
11352
|
// src/ui/file-picker.tsx
|
|
10527
|
-
import { Box as
|
|
10528
|
-
import { jsx as
|
|
11353
|
+
import { Box as Box18, Text as Text19 } from "ink";
|
|
11354
|
+
import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
10529
11355
|
function FilePicker({ items, selectedIndex, query }) {
|
|
10530
11356
|
const theme = useTheme();
|
|
10531
11357
|
let startIndex = 0;
|
|
@@ -10535,12 +11361,12 @@ function FilePicker({ items, selectedIndex, query }) {
|
|
|
10535
11361
|
const visible = items.slice(startIndex, startIndex + VISIBLE_LIMIT);
|
|
10536
11362
|
const hasMoreAbove = startIndex > 0;
|
|
10537
11363
|
const hasMoreBelow = items.length > startIndex + VISIBLE_LIMIT;
|
|
10538
|
-
return /* @__PURE__ */
|
|
10539
|
-
/* @__PURE__ */
|
|
10540
|
-
/* @__PURE__ */
|
|
10541
|
-
/* @__PURE__ */
|
|
10542
|
-
visible.length === 0 && /* @__PURE__ */
|
|
10543
|
-
hasMoreAbove && /* @__PURE__ */
|
|
11364
|
+
return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
11365
|
+
/* @__PURE__ */ jsx20(Text19, { color: theme.accent, bold: true, children: query ? `Files matching "${query}"` : "Mention a file" }),
|
|
11366
|
+
/* @__PURE__ */ jsx20(Text19, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select, Esc to cancel." }),
|
|
11367
|
+
/* @__PURE__ */ jsxs18(Box18, { marginTop: 1, flexDirection: "column", children: [
|
|
11368
|
+
visible.length === 0 && /* @__PURE__ */ jsx20(Text19, { color: theme.info.color, children: "No matches" }),
|
|
11369
|
+
hasMoreAbove && /* @__PURE__ */ jsxs18(Text19, { color: theme.info.color, children: [
|
|
10544
11370
|
"\u2026 ",
|
|
10545
11371
|
startIndex,
|
|
10546
11372
|
" more above"
|
|
@@ -10549,12 +11375,12 @@ function FilePicker({ items, selectedIndex, query }) {
|
|
|
10549
11375
|
const actualIndex = startIndex + i;
|
|
10550
11376
|
const isSelected = actualIndex === selectedIndex;
|
|
10551
11377
|
const label = item.isDirectory ? `${item.name}/` : item.name;
|
|
10552
|
-
return /* @__PURE__ */
|
|
11378
|
+
return /* @__PURE__ */ jsxs18(Text19, { color: isSelected ? theme.accent : void 0, bold: isSelected, children: [
|
|
10553
11379
|
isSelected ? "\u203A " : " ",
|
|
10554
11380
|
label
|
|
10555
11381
|
] }, item.name);
|
|
10556
11382
|
}),
|
|
10557
|
-
hasMoreBelow && /* @__PURE__ */
|
|
11383
|
+
hasMoreBelow && /* @__PURE__ */ jsxs18(Text19, { color: theme.info.color, children: [
|
|
10558
11384
|
"\u2026 ",
|
|
10559
11385
|
items.length - (startIndex + VISIBLE_LIMIT),
|
|
10560
11386
|
" more below"
|
|
@@ -10572,8 +11398,8 @@ var init_file_picker = __esm({
|
|
|
10572
11398
|
});
|
|
10573
11399
|
|
|
10574
11400
|
// src/ui/slash-picker.tsx
|
|
10575
|
-
import { Box as
|
|
10576
|
-
import { jsx as
|
|
11401
|
+
import { Box as Box19, Text as Text20 } from "ink";
|
|
11402
|
+
import { jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
10577
11403
|
function sourceBadge(source) {
|
|
10578
11404
|
if (source === "builtin") return "";
|
|
10579
11405
|
if (source === "project") return "project";
|
|
@@ -10593,12 +11419,12 @@ function SlashPicker({ items, selectedIndex, query }) {
|
|
|
10593
11419
|
const hasMoreBelow = items.length > startIndex + VISIBLE_LIMIT2;
|
|
10594
11420
|
const longestLabel = visible.reduce((m, it) => Math.max(m, commandLabel(it).length), 0);
|
|
10595
11421
|
const nameColWidth = Math.max(NAME_COL_MIN_WIDTH, longestLabel + NAME_DESC_GAP);
|
|
10596
|
-
return /* @__PURE__ */
|
|
10597
|
-
/* @__PURE__ */
|
|
10598
|
-
/* @__PURE__ */
|
|
10599
|
-
/* @__PURE__ */
|
|
10600
|
-
visible.length === 0 && /* @__PURE__ */
|
|
10601
|
-
hasMoreAbove && /* @__PURE__ */
|
|
11422
|
+
return /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
11423
|
+
/* @__PURE__ */ jsx21(Text20, { color: theme.accent, bold: true, children: query ? `Commands matching "/${query}"` : "Slash commands" }),
|
|
11424
|
+
/* @__PURE__ */ jsx21(Text20, { color: theme.info.color, children: "Arrow keys to navigate, Enter to select, Esc to cancel." }),
|
|
11425
|
+
/* @__PURE__ */ jsxs19(Box19, { marginTop: 1, flexDirection: "column", children: [
|
|
11426
|
+
visible.length === 0 && /* @__PURE__ */ jsx21(Text20, { color: theme.info.color, children: "No matches" }),
|
|
11427
|
+
hasMoreAbove && /* @__PURE__ */ jsxs19(Text20, { color: theme.info.color, children: [
|
|
10602
11428
|
"\u2026 ",
|
|
10603
11429
|
startIndex,
|
|
10604
11430
|
" more above"
|
|
@@ -10608,16 +11434,16 @@ function SlashPicker({ items, selectedIndex, query }) {
|
|
|
10608
11434
|
const isSelected = actualIndex === selectedIndex;
|
|
10609
11435
|
const nameCol = commandLabel(item).padEnd(nameColWidth);
|
|
10610
11436
|
const badge = sourceBadge(item.source);
|
|
10611
|
-
return /* @__PURE__ */
|
|
11437
|
+
return /* @__PURE__ */ jsxs19(Text20, { color: isSelected ? theme.accent : void 0, bold: isSelected, children: [
|
|
10612
11438
|
isSelected ? "\u203A " : " ",
|
|
10613
11439
|
nameCol,
|
|
10614
|
-
/* @__PURE__ */
|
|
11440
|
+
/* @__PURE__ */ jsxs19(Text20, { color: theme.info.color, children: [
|
|
10615
11441
|
item.description,
|
|
10616
11442
|
badge && ` [${badge}]`
|
|
10617
11443
|
] })
|
|
10618
11444
|
] }, item.name);
|
|
10619
11445
|
}),
|
|
10620
|
-
hasMoreBelow && /* @__PURE__ */
|
|
11446
|
+
hasMoreBelow && /* @__PURE__ */ jsxs19(Text20, { color: theme.info.color, children: [
|
|
10621
11447
|
"\u2026 ",
|
|
10622
11448
|
items.length - (startIndex + VISIBLE_LIMIT2),
|
|
10623
11449
|
" more below"
|
|
@@ -10697,15 +11523,15 @@ var tui_report_exports = {};
|
|
|
10697
11523
|
__export(tui_report_exports, {
|
|
10698
11524
|
getCategoryReportText: () => getCategoryReportText
|
|
10699
11525
|
});
|
|
10700
|
-
import { readFile as
|
|
10701
|
-
import { join as
|
|
10702
|
-
import { homedir as
|
|
11526
|
+
import { readFile as readFile15 } from "fs/promises";
|
|
11527
|
+
import { join as join18 } from "path";
|
|
11528
|
+
import { homedir as homedir13 } from "os";
|
|
10703
11529
|
function usageDir3() {
|
|
10704
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
10705
|
-
return
|
|
11530
|
+
const xdg = process.env.XDG_DATA_HOME || join18(homedir13(), ".local", "share");
|
|
11531
|
+
return join18(xdg, "kimiflare");
|
|
10706
11532
|
}
|
|
10707
11533
|
function usagePath3() {
|
|
10708
|
-
return
|
|
11534
|
+
return join18(usageDir3(), "usage.json");
|
|
10709
11535
|
}
|
|
10710
11536
|
function today3() {
|
|
10711
11537
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
@@ -10717,7 +11543,7 @@ function daysAgo2(n) {
|
|
|
10717
11543
|
}
|
|
10718
11544
|
async function loadLog3() {
|
|
10719
11545
|
try {
|
|
10720
|
-
const raw = await
|
|
11546
|
+
const raw = await readFile15(usagePath3(), "utf8");
|
|
10721
11547
|
return JSON.parse(raw);
|
|
10722
11548
|
} catch {
|
|
10723
11549
|
return { version: 1, days: [], sessions: [] };
|
|
@@ -10783,17 +11609,18 @@ __export(app_exports, {
|
|
|
10783
11609
|
shouldOpenMentionPicker: () => shouldOpenMentionPicker,
|
|
10784
11610
|
shouldOpenSlashPicker: () => shouldOpenSlashPicker
|
|
10785
11611
|
});
|
|
10786
|
-
import
|
|
10787
|
-
import { Box as
|
|
10788
|
-
import
|
|
11612
|
+
import React14, { useState as useState10, useRef as useRef3, useEffect as useEffect5, useCallback } from "react";
|
|
11613
|
+
import { Box as Box20, Text as Text21, useApp, useInput as useInput6, render } from "ink";
|
|
11614
|
+
import SelectInput9 from "ink-select-input";
|
|
10789
11615
|
import { existsSync as existsSync2, statSync as statSync3 } from "fs";
|
|
10790
|
-
import { join as
|
|
11616
|
+
import { join as join19 } from "path";
|
|
10791
11617
|
import { unlink as unlink3 } from "fs/promises";
|
|
11618
|
+
import { execSync as execSync2 } from "child_process";
|
|
10792
11619
|
import { spawn as spawn4 } from "child_process";
|
|
10793
11620
|
import { platform as platform2 } from "os";
|
|
10794
11621
|
import fg4 from "fast-glob";
|
|
10795
11622
|
import { readFileSync as readFileSync3 } from "fs";
|
|
10796
|
-
import { jsx as
|
|
11623
|
+
import { jsx as jsx22, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
10797
11624
|
function buildFilePickerIgnoreList(cwd) {
|
|
10798
11625
|
const hardcoded = [
|
|
10799
11626
|
// Dependencies
|
|
@@ -10864,7 +11691,7 @@ function buildFilePickerIgnoreList(cwd) {
|
|
|
10864
11691
|
];
|
|
10865
11692
|
const gitignorePatterns = [];
|
|
10866
11693
|
try {
|
|
10867
|
-
const gitignorePath =
|
|
11694
|
+
const gitignorePath = join19(cwd, ".gitignore");
|
|
10868
11695
|
const stats = statSync3(gitignorePath);
|
|
10869
11696
|
if (stats.size > MAX_GITIGNORE_SIZE) {
|
|
10870
11697
|
return hardcoded;
|
|
@@ -10938,6 +11765,26 @@ function openBrowser(url) {
|
|
|
10938
11765
|
const child = spawn4(cmd, [url], { detached: true, stdio: "ignore" });
|
|
10939
11766
|
child.unref();
|
|
10940
11767
|
}
|
|
11768
|
+
function detectGitHubRepo(cachedRepo) {
|
|
11769
|
+
if (cachedRepo) {
|
|
11770
|
+
const parts = cachedRepo.split("/");
|
|
11771
|
+
if (parts.length === 2) return { owner: parts[0], name: parts[1] };
|
|
11772
|
+
}
|
|
11773
|
+
try {
|
|
11774
|
+
const remoteUrl = execSync2("git remote get-url origin", { cwd: process.cwd(), encoding: "utf8" }).trim();
|
|
11775
|
+
const httpsMatch = remoteUrl.match(/github\.com\/([^\/]+)\/([^\/]+?)(?:\.git)?$/);
|
|
11776
|
+
if (httpsMatch) return { owner: httpsMatch[1], name: httpsMatch[2] };
|
|
11777
|
+
const sshMatch = remoteUrl.match(/github\.com:([^\/]+)\/([^\/]+?)(?:\.git)?$/);
|
|
11778
|
+
if (sshMatch) return { owner: sshMatch[1], name: sshMatch[2] };
|
|
11779
|
+
} catch {
|
|
11780
|
+
}
|
|
11781
|
+
return null;
|
|
11782
|
+
}
|
|
11783
|
+
function formatTokens3(n) {
|
|
11784
|
+
if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
|
|
11785
|
+
if (n >= 1e3) return `${(n / 1e3).toFixed(1)}K`;
|
|
11786
|
+
return String(n);
|
|
11787
|
+
}
|
|
10941
11788
|
function capEvents(prev) {
|
|
10942
11789
|
if (prev.length <= MAX_EVENTS) return prev;
|
|
10943
11790
|
return prev.slice(prev.length - MAX_EVENTS);
|
|
@@ -11000,10 +11847,10 @@ function App({
|
|
|
11000
11847
|
initialLspProjectPath
|
|
11001
11848
|
}) {
|
|
11002
11849
|
const { exit } = useApp();
|
|
11003
|
-
const [cfg, setCfg] =
|
|
11004
|
-
const [lspScope, setLspScope] =
|
|
11005
|
-
const [lspProjectPath, setLspProjectPath] =
|
|
11006
|
-
const [events, setRawEvents] =
|
|
11850
|
+
const [cfg, setCfg] = useState10(initialCfg);
|
|
11851
|
+
const [lspScope, setLspScope] = useState10(initialLspScope);
|
|
11852
|
+
const [lspProjectPath, setLspProjectPath] = useState10(initialLspProjectPath);
|
|
11853
|
+
const [events, setRawEvents] = useState10([]);
|
|
11007
11854
|
const setEvents = useCallback(
|
|
11008
11855
|
(updater) => {
|
|
11009
11856
|
setRawEvents((prev) => {
|
|
@@ -11013,45 +11860,47 @@ function App({
|
|
|
11013
11860
|
},
|
|
11014
11861
|
[]
|
|
11015
11862
|
);
|
|
11016
|
-
const [input, setInput] =
|
|
11017
|
-
const [busy, setBusy] =
|
|
11018
|
-
const [usage, setUsage] =
|
|
11019
|
-
const [sessionUsage, setSessionUsage] =
|
|
11020
|
-
const [gatewayMeta, setGatewayMeta] =
|
|
11021
|
-
const [showReasoning, setShowReasoning] =
|
|
11022
|
-
const [perm, setPerm] =
|
|
11023
|
-
const [queue, setQueue] =
|
|
11024
|
-
const [history, setHistory] =
|
|
11025
|
-
const [historyIndex, setHistoryIndex] =
|
|
11026
|
-
const [draftInput, setDraftInput] =
|
|
11027
|
-
const [mode, setMode] =
|
|
11028
|
-
const [codeMode, setCodeMode] =
|
|
11029
|
-
const filePickerEnabled = initialCfg?.filePicker ??
|
|
11030
|
-
const [effort, setEffort] =
|
|
11863
|
+
const [input, setInput] = useState10("");
|
|
11864
|
+
const [busy, setBusy] = useState10(false);
|
|
11865
|
+
const [usage, setUsage] = useState10(null);
|
|
11866
|
+
const [sessionUsage, setSessionUsage] = useState10(null);
|
|
11867
|
+
const [gatewayMeta, setGatewayMeta] = useState10(null);
|
|
11868
|
+
const [showReasoning, setShowReasoning] = useState10(false);
|
|
11869
|
+
const [perm, setPerm] = useState10(null);
|
|
11870
|
+
const [queue, setQueue] = useState10([]);
|
|
11871
|
+
const [history, setHistory] = useState10([]);
|
|
11872
|
+
const [historyIndex, setHistoryIndex] = useState10(-1);
|
|
11873
|
+
const [draftInput, setDraftInput] = useState10("");
|
|
11874
|
+
const [mode, setMode] = useState10("edit");
|
|
11875
|
+
const [codeMode, setCodeMode] = useState10(false);
|
|
11876
|
+
const filePickerEnabled = initialCfg?.filePicker ?? true;
|
|
11877
|
+
const [effort, setEffort] = useState10(
|
|
11031
11878
|
initialCfg?.reasoningEffort ?? DEFAULT_REASONING_EFFORT
|
|
11032
11879
|
);
|
|
11033
|
-
const [resumeSessions, setResumeSessions] =
|
|
11034
|
-
const [showHelpMenu, setShowHelpMenu] =
|
|
11035
|
-
const [commandWizard, setCommandWizard] =
|
|
11036
|
-
const [commandPicker, setCommandPicker] =
|
|
11037
|
-
const [commandToDelete, setCommandToDelete] =
|
|
11038
|
-
const [showCommandList, setShowCommandList] =
|
|
11039
|
-
const [showLspWizard, setShowLspWizard] =
|
|
11040
|
-
const [
|
|
11041
|
-
const [
|
|
11042
|
-
const [
|
|
11043
|
-
const [
|
|
11044
|
-
const [
|
|
11045
|
-
const [
|
|
11046
|
-
const [
|
|
11047
|
-
const [
|
|
11048
|
-
const [
|
|
11049
|
-
const [
|
|
11050
|
-
const [
|
|
11051
|
-
const [
|
|
11052
|
-
const [
|
|
11880
|
+
const [resumeSessions, setResumeSessions] = useState10(null);
|
|
11881
|
+
const [showHelpMenu, setShowHelpMenu] = useState10(false);
|
|
11882
|
+
const [commandWizard, setCommandWizard] = useState10(null);
|
|
11883
|
+
const [commandPicker, setCommandPicker] = useState10(null);
|
|
11884
|
+
const [commandToDelete, setCommandToDelete] = useState10(null);
|
|
11885
|
+
const [showCommandList, setShowCommandList] = useState10(false);
|
|
11886
|
+
const [showLspWizard, setShowLspWizard] = useState10(false);
|
|
11887
|
+
const [showRemoteDashboard, setShowRemoteDashboard] = useState10(false);
|
|
11888
|
+
const [selectedRemoteSession, setSelectedRemoteSession] = useState10(null);
|
|
11889
|
+
const [tasks, setTasks] = useState10([]);
|
|
11890
|
+
const [tasksStartedAt, setTasksStartedAt] = useState10(null);
|
|
11891
|
+
const [tasksStartTokens, setTasksStartTokens] = useState10(0);
|
|
11892
|
+
const [turnStartedAt, setTurnStartedAt] = useState10(null);
|
|
11893
|
+
const [verbose, setVerbose] = useState10(false);
|
|
11894
|
+
const [hasUpdate, setHasUpdate] = useState10(initialUpdateResult?.hasUpdate ?? false);
|
|
11895
|
+
const [latestVersion, setLatestVersion] = useState10(initialUpdateResult?.latestVersion ?? null);
|
|
11896
|
+
const [theme, setTheme] = useState10(resolveTheme(initialCfg?.theme));
|
|
11897
|
+
const [showThemePicker, setShowThemePicker] = useState10(false);
|
|
11898
|
+
const [originalTheme, setOriginalTheme] = useState10(null);
|
|
11899
|
+
const [cursorOffset, setCursorOffset] = useState10(0);
|
|
11900
|
+
const [activePicker, setActivePicker] = useState10(null);
|
|
11901
|
+
const [filePickerItems, setFilePickerItems] = useState10([]);
|
|
11053
11902
|
const filePickerLoadedRef = useRef3(false);
|
|
11054
|
-
const [customCommandsVersion, setCustomCommandsVersion] =
|
|
11903
|
+
const [customCommandsVersion, setCustomCommandsVersion] = useState10(0);
|
|
11055
11904
|
const cacheStableRef = useRef3(initialCfg?.cacheStablePrompts !== false);
|
|
11056
11905
|
const messagesRef = useRef3(
|
|
11057
11906
|
makePrefixMessages(cacheStableRef.current, cfg?.model ?? DEFAULT_MODEL, "edit", ALL_TOOLS)
|
|
@@ -11089,15 +11938,15 @@ function App({
|
|
|
11089
11938
|
const pickerCancelRef = useRef3(null);
|
|
11090
11939
|
const pickerAnchor = activePicker?.anchor ?? null;
|
|
11091
11940
|
const pickerKind = activePicker?.kind ?? null;
|
|
11092
|
-
const pickerQuery =
|
|
11941
|
+
const pickerQuery = React14.useMemo(() => {
|
|
11093
11942
|
if (pickerAnchor === null) return null;
|
|
11094
11943
|
return input.slice(pickerAnchor + 1, cursorOffset);
|
|
11095
11944
|
}, [input, cursorOffset, pickerAnchor]);
|
|
11096
|
-
const filteredFileItems =
|
|
11945
|
+
const filteredFileItems = React14.useMemo(() => {
|
|
11097
11946
|
if (pickerKind !== "file" || pickerQuery === null) return [];
|
|
11098
11947
|
return filterPickerItems(filePickerItems, pickerQuery);
|
|
11099
11948
|
}, [pickerKind, filePickerItems, pickerQuery]);
|
|
11100
|
-
const allSlashCommands =
|
|
11949
|
+
const allSlashCommands = React14.useMemo(() => {
|
|
11101
11950
|
const customs = customCommandsRef.current.filter((c) => !BUILTIN_COMMAND_NAMES.has(c.name.toLowerCase())).map((c) => ({
|
|
11102
11951
|
name: c.name,
|
|
11103
11952
|
description: c.description ?? "",
|
|
@@ -11105,11 +11954,11 @@ function App({
|
|
|
11105
11954
|
}));
|
|
11106
11955
|
return [...BUILTIN_COMMANDS, ...customs];
|
|
11107
11956
|
}, [customCommandsVersion]);
|
|
11108
|
-
const filteredSlashItems =
|
|
11957
|
+
const filteredSlashItems = React14.useMemo(() => {
|
|
11109
11958
|
if (pickerKind !== "slash" || pickerQuery === null) return [];
|
|
11110
11959
|
return fuzzyFilter(allSlashCommands, pickerQuery, (c) => c.name).slice(0, 50);
|
|
11111
11960
|
}, [pickerKind, allSlashCommands, pickerQuery]);
|
|
11112
|
-
|
|
11961
|
+
useEffect5(() => {
|
|
11113
11962
|
if (activePicker !== null) {
|
|
11114
11963
|
const trigger = activePicker.kind === "file" ? "@" : "/";
|
|
11115
11964
|
if (cursorOffset < activePicker.anchor) {
|
|
@@ -11166,14 +12015,14 @@ function App({
|
|
|
11166
12015
|
return;
|
|
11167
12016
|
}
|
|
11168
12017
|
}, [input, cursorOffset, activePicker, filePickerEnabled]);
|
|
11169
|
-
|
|
12018
|
+
useEffect5(() => {
|
|
11170
12019
|
if (activePicker?.kind !== "file") return;
|
|
11171
12020
|
const max = Math.max(0, filteredFileItems.length - 1);
|
|
11172
12021
|
if (activePicker.selected > max) {
|
|
11173
12022
|
setActivePicker({ ...activePicker, selected: max });
|
|
11174
12023
|
}
|
|
11175
12024
|
}, [filteredFileItems.length, activePicker]);
|
|
11176
|
-
|
|
12025
|
+
useEffect5(() => {
|
|
11177
12026
|
if (activePicker?.kind !== "slash") return;
|
|
11178
12027
|
const max = Math.max(0, filteredSlashItems.length - 1);
|
|
11179
12028
|
if (activePicker.selected > max) {
|
|
@@ -11217,7 +12066,7 @@ function App({
|
|
|
11217
12066
|
pickerCancelRef.current = cursorOffset;
|
|
11218
12067
|
setActivePicker(null);
|
|
11219
12068
|
}, [cursorOffset]);
|
|
11220
|
-
|
|
12069
|
+
useEffect5(() => {
|
|
11221
12070
|
const modalActive = showHelpMenu || commandWizard !== null || commandPicker !== null || commandToDelete !== null || showCommandList || showLspWizard || resumeSessions !== null || perm !== null;
|
|
11222
12071
|
if (modalActive && activePicker !== null) {
|
|
11223
12072
|
setActivePicker(null);
|
|
@@ -11233,7 +12082,7 @@ function App({
|
|
|
11233
12082
|
perm,
|
|
11234
12083
|
activePicker
|
|
11235
12084
|
]);
|
|
11236
|
-
|
|
12085
|
+
useEffect5(() => {
|
|
11237
12086
|
if (!cfg) return;
|
|
11238
12087
|
void Promise.resolve().then(() => (init_sessions(), sessions_exports)).then(
|
|
11239
12088
|
({ pruneSessions: pruneSessions2 }) => pruneSessions2().then((removed) => {
|
|
@@ -11259,7 +12108,7 @@ function App({
|
|
|
11259
12108
|
}
|
|
11260
12109
|
});
|
|
11261
12110
|
if (cfg.memoryEnabled) {
|
|
11262
|
-
const dbPath = cfg.memoryDbPath ??
|
|
12111
|
+
const dbPath = cfg.memoryDbPath ?? join19(process.cwd(), ".kimiflare", "memory.db");
|
|
11263
12112
|
const manager = new MemoryManager({
|
|
11264
12113
|
dbPath,
|
|
11265
12114
|
accountId: cfg.accountId,
|
|
@@ -11326,7 +12175,7 @@ function App({
|
|
|
11326
12175
|
}
|
|
11327
12176
|
});
|
|
11328
12177
|
}, [cfg, setEvents]);
|
|
11329
|
-
|
|
12178
|
+
useEffect5(() => {
|
|
11330
12179
|
const id = setInterval(() => {
|
|
11331
12180
|
try {
|
|
11332
12181
|
performance.clearMarks();
|
|
@@ -11351,7 +12200,7 @@ function App({
|
|
|
11351
12200
|
]);
|
|
11352
12201
|
}
|
|
11353
12202
|
}, [setEvents]);
|
|
11354
|
-
|
|
12203
|
+
useEffect5(() => {
|
|
11355
12204
|
if (!cfg || updateCheckedRef.current) return;
|
|
11356
12205
|
updateCheckedRef.current = true;
|
|
11357
12206
|
if (initialUpdateResult) {
|
|
@@ -11402,7 +12251,7 @@ function App({
|
|
|
11402
12251
|
}
|
|
11403
12252
|
});
|
|
11404
12253
|
}, [cfg, initialUpdateResult]);
|
|
11405
|
-
|
|
12254
|
+
useEffect5(() => {
|
|
11406
12255
|
modeRef.current = mode;
|
|
11407
12256
|
if (cacheStableRef.current) {
|
|
11408
12257
|
messagesRef.current[1] = {
|
|
@@ -11429,10 +12278,10 @@ function App({
|
|
|
11429
12278
|
executorRef.current.clearSessionPermissions();
|
|
11430
12279
|
}
|
|
11431
12280
|
}, [mode, cfg?.model]);
|
|
11432
|
-
|
|
12281
|
+
useEffect5(() => {
|
|
11433
12282
|
effortRef.current = effort;
|
|
11434
12283
|
}, [effort]);
|
|
11435
|
-
|
|
12284
|
+
useEffect5(() => {
|
|
11436
12285
|
if (!cfg) return;
|
|
11437
12286
|
const id = setInterval(() => {
|
|
11438
12287
|
void checkForUpdate().then((result) => {
|
|
@@ -11587,7 +12436,7 @@ function App({
|
|
|
11587
12436
|
]);
|
|
11588
12437
|
}
|
|
11589
12438
|
}, [cfg]);
|
|
11590
|
-
|
|
12439
|
+
useEffect5(() => {
|
|
11591
12440
|
if (cfg && !mcpInitRef.current) {
|
|
11592
12441
|
void initMcp();
|
|
11593
12442
|
}
|
|
@@ -11625,7 +12474,85 @@ function App({
|
|
|
11625
12474
|
} catch {
|
|
11626
12475
|
}
|
|
11627
12476
|
}, [cfg, ensureSessionId]);
|
|
11628
|
-
|
|
12477
|
+
const onIterationEnd = useCallback(
|
|
12478
|
+
async (messages, signal) => {
|
|
12479
|
+
if (signal.aborted) return messages;
|
|
12480
|
+
if (!shouldCompact({ messages })) return messages;
|
|
12481
|
+
if (compiledContextRef.current) {
|
|
12482
|
+
const store = artifactStoreRef.current;
|
|
12483
|
+
const result = compactMessages2({
|
|
12484
|
+
messages,
|
|
12485
|
+
state: sessionStateRef.current,
|
|
12486
|
+
store
|
|
12487
|
+
});
|
|
12488
|
+
if (result.metrics.rawTurnsRemoved > 0) {
|
|
12489
|
+
sessionStateRef.current = result.newState;
|
|
12490
|
+
setEvents((e) => [
|
|
12491
|
+
...e,
|
|
12492
|
+
{
|
|
12493
|
+
kind: "info",
|
|
12494
|
+
key: mkKey(),
|
|
12495
|
+
text: `auto-compacted: ${result.metrics.estimatedTokensBefore} \u2192 ${result.metrics.estimatedTokensAfter} tokens (${result.metrics.archivedArtifacts} artifacts)`
|
|
12496
|
+
}
|
|
12497
|
+
]);
|
|
12498
|
+
await saveSessionSafe();
|
|
12499
|
+
}
|
|
12500
|
+
const manager = memoryManagerRef.current;
|
|
12501
|
+
if (manager && !signal.aborted) {
|
|
12502
|
+
try {
|
|
12503
|
+
const cwd = process.cwd();
|
|
12504
|
+
const queryText = sessionStateRef.current.task || cwd;
|
|
12505
|
+
const results = await manager.recall({ text: queryText, repoPath: cwd, limit: 5 });
|
|
12506
|
+
if (results.length > 0 && !signal.aborted) {
|
|
12507
|
+
const text = await manager.synthesizeRecalled(results);
|
|
12508
|
+
const lastSystemIdx = result.newMessages.findLastIndex((m) => m.role === "system");
|
|
12509
|
+
const insertIdx = lastSystemIdx >= 0 ? lastSystemIdx + 1 : result.newMessages.length;
|
|
12510
|
+
result.newMessages.splice(insertIdx, 0, { role: "system", content: text });
|
|
12511
|
+
setEvents((e) => [
|
|
12512
|
+
...e,
|
|
12513
|
+
{
|
|
12514
|
+
kind: "memory",
|
|
12515
|
+
key: mkKey(),
|
|
12516
|
+
text: `recalled ${results.length} memory${results.length === 1 ? "" : "ies"} after compaction`
|
|
12517
|
+
}
|
|
12518
|
+
]);
|
|
12519
|
+
await saveSessionSafe();
|
|
12520
|
+
}
|
|
12521
|
+
} catch {
|
|
12522
|
+
}
|
|
12523
|
+
}
|
|
12524
|
+
return result.newMessages;
|
|
12525
|
+
}
|
|
12526
|
+
if (cfg && !signal.aborted) {
|
|
12527
|
+
try {
|
|
12528
|
+
const result = await compactMessages({
|
|
12529
|
+
accountId: cfg.accountId,
|
|
12530
|
+
apiToken: cfg.apiToken,
|
|
12531
|
+
model: cfg.model,
|
|
12532
|
+
messages,
|
|
12533
|
+
signal,
|
|
12534
|
+
gateway: gatewayFromConfig(cfg)
|
|
12535
|
+
});
|
|
12536
|
+
if (result.replacedCount > 0) {
|
|
12537
|
+
setEvents((e) => [
|
|
12538
|
+
...e,
|
|
12539
|
+
{
|
|
12540
|
+
kind: "info",
|
|
12541
|
+
key: mkKey(),
|
|
12542
|
+
text: `auto-compacted: ${result.replacedCount} messages summarized`
|
|
12543
|
+
}
|
|
12544
|
+
]);
|
|
12545
|
+
await saveSessionSafe();
|
|
12546
|
+
}
|
|
12547
|
+
return result.newMessages;
|
|
12548
|
+
} catch {
|
|
12549
|
+
}
|
|
12550
|
+
}
|
|
12551
|
+
return messages;
|
|
12552
|
+
},
|
|
12553
|
+
[cfg]
|
|
12554
|
+
);
|
|
12555
|
+
useInput6((inputChar, key) => {
|
|
11629
12556
|
if (key.ctrl && inputChar === "c") {
|
|
11630
12557
|
const hadPerm = permResolveRef.current !== null;
|
|
11631
12558
|
if (hadPerm) {
|
|
@@ -11668,10 +12595,6 @@ function App({
|
|
|
11668
12595
|
setVerbose((v) => !v);
|
|
11669
12596
|
return;
|
|
11670
12597
|
}
|
|
11671
|
-
if (key.ctrl && inputChar === "m") {
|
|
11672
|
-
setCodeMode((c) => !c);
|
|
11673
|
-
return;
|
|
11674
|
-
}
|
|
11675
12598
|
});
|
|
11676
12599
|
const flushAssistantUpdates = useCallback(() => {
|
|
11677
12600
|
flushTimeoutRef.current = null;
|
|
@@ -11823,7 +12746,7 @@ function App({
|
|
|
11823
12746
|
}
|
|
11824
12747
|
}, [cfg, busy, saveSessionSafe]);
|
|
11825
12748
|
const openResumePicker = useCallback(async () => {
|
|
11826
|
-
const sessions = await listSessions(200);
|
|
12749
|
+
const sessions = await listSessions(200, process.cwd());
|
|
11827
12750
|
setResumeSessions(sessions);
|
|
11828
12751
|
}, []);
|
|
11829
12752
|
const runInit = useCallback(async () => {
|
|
@@ -11833,23 +12756,13 @@ function App({
|
|
|
11833
12756
|
return;
|
|
11834
12757
|
}
|
|
11835
12758
|
const cwd = process.cwd();
|
|
11836
|
-
|
|
11837
|
-
|
|
11838
|
-
|
|
11839
|
-
|
|
11840
|
-
{
|
|
11841
|
-
kind: "info",
|
|
11842
|
-
key: mkKey(),
|
|
11843
|
-
text: `${name} already exists at ${join17(cwd, name)} \u2014 delete it first if you want to regenerate`
|
|
11844
|
-
}
|
|
11845
|
-
]);
|
|
11846
|
-
return;
|
|
11847
|
-
}
|
|
11848
|
-
}
|
|
11849
|
-
const prompt = [
|
|
11850
|
-
"Generate a KIMI.md at the repository root so future agents have project context.",
|
|
12759
|
+
const existingName = ["KIMI.md", "KIMIFLARE.md", "AGENT.md"].find((n) => existsSync2(join19(cwd, n)));
|
|
12760
|
+
const isRefresh = existingName !== void 0;
|
|
12761
|
+
const promptParts = [
|
|
12762
|
+
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.",
|
|
11851
12763
|
"",
|
|
11852
12764
|
"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.",
|
|
12765
|
+
isRefresh ? `Also read the existing ${existingName} so you know what to keep vs. update.` : null,
|
|
11853
12766
|
"",
|
|
11854
12767
|
"Then call the `write` tool to create `KIMI.md` at the repo root with these sections, terse (aim \u2264 100 lines total):",
|
|
11855
12768
|
"",
|
|
@@ -11860,13 +12773,23 @@ function App({
|
|
|
11860
12773
|
"- **Do / Don't** \u2014 quirks or rules future agents should know.",
|
|
11861
12774
|
"",
|
|
11862
12775
|
"Do not call `tasks_set` for this. Just read what you need, then write the file."
|
|
11863
|
-
]
|
|
11864
|
-
|
|
12776
|
+
];
|
|
12777
|
+
const prompt = promptParts.filter((p) => p !== null).join("\n");
|
|
12778
|
+
setEvents((e) => [...e, { kind: "user", key: mkKey(), text: isRefresh ? `/init (refreshing ${existingName})` : "/init" }]);
|
|
11865
12779
|
messagesRef.current.push({ role: "user", content: sanitizeString(prompt) });
|
|
11866
12780
|
setBusy(true);
|
|
11867
12781
|
setTurnStartedAt(Date.now());
|
|
11868
12782
|
const controller = new AbortController();
|
|
11869
12783
|
activeControllerRef.current = controller;
|
|
12784
|
+
const initClassification = classifyIntent(prompt);
|
|
12785
|
+
const initEffortForTier = {
|
|
12786
|
+
light: "low",
|
|
12787
|
+
medium: "medium",
|
|
12788
|
+
heavy: "high"
|
|
12789
|
+
};
|
|
12790
|
+
const initReasoningEffort = initEffortForTier[initClassification.tier] ?? effortRef.current;
|
|
12791
|
+
const effectiveCodeMode = initClassification.tier === "heavy";
|
|
12792
|
+
setCodeMode(effectiveCodeMode);
|
|
11870
12793
|
try {
|
|
11871
12794
|
await runAgentTurn({
|
|
11872
12795
|
accountId: cfg.accountId,
|
|
@@ -11878,17 +12801,21 @@ function App({
|
|
|
11878
12801
|
executor: executorRef.current,
|
|
11879
12802
|
cwd,
|
|
11880
12803
|
signal: controller.signal,
|
|
11881
|
-
reasoningEffort:
|
|
12804
|
+
reasoningEffort: initReasoningEffort,
|
|
12805
|
+
intentClassification: initClassification,
|
|
11882
12806
|
coauthor: cfg.coauthor !== false ? { name: cfg.coauthorName || "kimiflare", email: cfg.coauthorEmail || "kimiflare@proton.me" } : void 0,
|
|
11883
12807
|
sessionId: ensureSessionId(),
|
|
11884
12808
|
memoryManager: memoryManagerRef.current,
|
|
11885
|
-
codeMode,
|
|
12809
|
+
codeMode: effectiveCodeMode,
|
|
12810
|
+
maxInputTokens: effectiveCodeMode ? 2e5 : void 0,
|
|
12811
|
+
continueOnLimit: effectiveCodeMode ? true : void 0,
|
|
12812
|
+
onIterationEnd,
|
|
11886
12813
|
onFileChange: (path, content) => {
|
|
11887
12814
|
if (content) {
|
|
11888
12815
|
lspManagerRef.current.notifyChange(path, content);
|
|
11889
12816
|
} else {
|
|
11890
12817
|
void import("fs/promises").then(
|
|
11891
|
-
({ readFile:
|
|
12818
|
+
({ readFile: readFile16 }) => readFile16(path, "utf8").then((c) => lspManagerRef.current.notifyChange(path, c)).catch(() => {
|
|
11892
12819
|
})
|
|
11893
12820
|
);
|
|
11894
12821
|
}
|
|
@@ -11982,7 +12909,7 @@ function App({
|
|
|
11982
12909
|
})
|
|
11983
12910
|
}
|
|
11984
12911
|
});
|
|
11985
|
-
if (existsSync2(
|
|
12912
|
+
if (existsSync2(join19(cwd, "KIMI.md"))) {
|
|
11986
12913
|
if (cacheStableRef.current) {
|
|
11987
12914
|
messagesRef.current[1] = {
|
|
11988
12915
|
role: "system",
|
|
@@ -12029,6 +12956,7 @@ function App({
|
|
|
12029
12956
|
]);
|
|
12030
12957
|
}
|
|
12031
12958
|
} finally {
|
|
12959
|
+
setCodeMode(false);
|
|
12032
12960
|
const asstId = activeAsstIdRef.current;
|
|
12033
12961
|
if (asstId !== null) updateAssistant(asstId, () => ({ streaming: false }));
|
|
12034
12962
|
setBusy(false);
|
|
@@ -12639,13 +13567,177 @@ ${lines.join("\n")}` }]);
|
|
|
12639
13567
|
]);
|
|
12640
13568
|
return true;
|
|
12641
13569
|
}
|
|
13570
|
+
if (c === "/remote") {
|
|
13571
|
+
if (arg === "status" || arg === "cancel") {
|
|
13572
|
+
setEvents((e) => [
|
|
13573
|
+
...e,
|
|
13574
|
+
{ kind: "info", key: mkKey(), text: `Use \`kimiflare remote ${arg}\` from your shell.` }
|
|
13575
|
+
]);
|
|
13576
|
+
return true;
|
|
13577
|
+
}
|
|
13578
|
+
const prompt = rest.join(" ").trim();
|
|
13579
|
+
if (!prompt) {
|
|
13580
|
+
setShowRemoteDashboard(true);
|
|
13581
|
+
return true;
|
|
13582
|
+
}
|
|
13583
|
+
const repo = detectGitHubRepo(cfg?.githubRepo);
|
|
13584
|
+
if (!repo) {
|
|
13585
|
+
setEvents((e) => [
|
|
13586
|
+
...e,
|
|
13587
|
+
{ kind: "info", key: mkKey(), text: "Could not detect GitHub repo. Run from a repo with a GitHub remote, or set githubRepo in config." }
|
|
13588
|
+
]);
|
|
13589
|
+
return true;
|
|
13590
|
+
}
|
|
13591
|
+
(async () => {
|
|
13592
|
+
if (!cfg?.remoteWorkerUrl) {
|
|
13593
|
+
setEvents((e) => [
|
|
13594
|
+
...e,
|
|
13595
|
+
{ kind: "info", key: mkKey(), text: "Remote infrastructure not deployed yet. Setting up now (~2 min)..." }
|
|
13596
|
+
]);
|
|
13597
|
+
try {
|
|
13598
|
+
for await (const step of deployForTui()) {
|
|
13599
|
+
setEvents((e) => [
|
|
13600
|
+
...e,
|
|
13601
|
+
{ kind: step.error ? "error" : "info", key: mkKey(), text: step.message }
|
|
13602
|
+
]);
|
|
13603
|
+
if (step.done) break;
|
|
13604
|
+
}
|
|
13605
|
+
} catch {
|
|
13606
|
+
setEvents((e) => [
|
|
13607
|
+
...e,
|
|
13608
|
+
{ kind: "error", key: mkKey(), text: "Deploy failed. Fix the issue above and try /remote again." }
|
|
13609
|
+
]);
|
|
13610
|
+
return;
|
|
13611
|
+
}
|
|
13612
|
+
const { loadConfig: reloadConfig } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
13613
|
+
const newCfg = await reloadConfig();
|
|
13614
|
+
if (newCfg) setCfg(newCfg);
|
|
13615
|
+
}
|
|
13616
|
+
const currentCfg = cfg ?? await loadConfig();
|
|
13617
|
+
if (!currentCfg?.remoteWorkerUrl) {
|
|
13618
|
+
setEvents((e) => [
|
|
13619
|
+
...e,
|
|
13620
|
+
{ kind: "error", key: mkKey(), text: "Deploy seemed to succeed but config wasn't saved. Try again." }
|
|
13621
|
+
]);
|
|
13622
|
+
return;
|
|
13623
|
+
}
|
|
13624
|
+
if (!currentCfg.githubOAuthToken) {
|
|
13625
|
+
setEvents((e) => [
|
|
13626
|
+
...e,
|
|
13627
|
+
{ kind: "info", key: mkKey(), text: "GitHub not authenticated. Starting OAuth device flow..." }
|
|
13628
|
+
]);
|
|
13629
|
+
try {
|
|
13630
|
+
for await (const step of authGitHubForTui()) {
|
|
13631
|
+
setEvents((e) => [
|
|
13632
|
+
...e,
|
|
13633
|
+
{ kind: step.error ? "error" : "info", key: mkKey(), text: step.message }
|
|
13634
|
+
]);
|
|
13635
|
+
if (step.done) break;
|
|
13636
|
+
}
|
|
13637
|
+
} catch {
|
|
13638
|
+
setEvents((e) => [
|
|
13639
|
+
...e,
|
|
13640
|
+
{ kind: "error", key: mkKey(), text: "GitHub auth failed. Try `kimiflare auth github` from shell." }
|
|
13641
|
+
]);
|
|
13642
|
+
return;
|
|
13643
|
+
}
|
|
13644
|
+
const { loadConfig: reloadConfig } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
13645
|
+
const newCfg = await reloadConfig();
|
|
13646
|
+
if (newCfg) setCfg(newCfg);
|
|
13647
|
+
}
|
|
13648
|
+
const finalCfg = await loadConfig() ?? currentCfg;
|
|
13649
|
+
const ttl = finalCfg.remoteTtlMinutes ?? 30;
|
|
13650
|
+
const budget = finalCfg.remoteMaxInputTokens ?? 5e6;
|
|
13651
|
+
setEvents((e) => [
|
|
13652
|
+
...e,
|
|
13653
|
+
{ kind: "info", key: mkKey(), text: `Starting remote session for ${repo.owner}/${repo.name}...` },
|
|
13654
|
+
{ kind: "info", key: mkKey(), text: `Budget: ${formatTokens3(budget)} tokens. TTL: ${ttl} min.` }
|
|
13655
|
+
]);
|
|
13656
|
+
try {
|
|
13657
|
+
const data = await startRemoteSession({
|
|
13658
|
+
prompt,
|
|
13659
|
+
repo,
|
|
13660
|
+
cfg: finalCfg,
|
|
13661
|
+
ttlMinutes: finalCfg.remoteTtlMinutes,
|
|
13662
|
+
tokensBudget: finalCfg.remoteMaxInputTokens
|
|
13663
|
+
});
|
|
13664
|
+
setEvents((e) => [
|
|
13665
|
+
...e,
|
|
13666
|
+
{ kind: "info", key: mkKey(), text: `Session started: ${data.sessionId}` }
|
|
13667
|
+
]);
|
|
13668
|
+
for await (const ev of streamRemoteProgress(
|
|
13669
|
+
finalCfg.remoteWorkerUrl,
|
|
13670
|
+
data.sessionId,
|
|
13671
|
+
activeControllerRef.current?.signal
|
|
13672
|
+
)) {
|
|
13673
|
+
const event = ev;
|
|
13674
|
+
if (event.type === "text_delta") {
|
|
13675
|
+
setEvents((e) => [
|
|
13676
|
+
...e,
|
|
13677
|
+
{ kind: "info", key: mkKey(), text: String(event.text ?? "") }
|
|
13678
|
+
]);
|
|
13679
|
+
} else if (event.type === "tool_call") {
|
|
13680
|
+
setEvents((e) => [
|
|
13681
|
+
...e,
|
|
13682
|
+
{ kind: "info", key: mkKey(), text: `\u2192 ${String(event.name ?? "")}` }
|
|
13683
|
+
]);
|
|
13684
|
+
} else if (event.type === "done") {
|
|
13685
|
+
const prUrl = event.prUrl;
|
|
13686
|
+
const tokensUsed = event.tokensUsed;
|
|
13687
|
+
const tokensBudget = event.tokensBudget;
|
|
13688
|
+
setEvents((e) => [
|
|
13689
|
+
...e,
|
|
13690
|
+
{ kind: "info", key: mkKey(), text: prUrl ? `Done \u2014 PR: ${prUrl}` : "Done" }
|
|
13691
|
+
]);
|
|
13692
|
+
await saveRemoteSession({
|
|
13693
|
+
sessionId: data.sessionId,
|
|
13694
|
+
prompt,
|
|
13695
|
+
repo: `${repo.owner}/${repo.name}`,
|
|
13696
|
+
workerUrl: finalCfg.remoteWorkerUrl,
|
|
13697
|
+
status: "done",
|
|
13698
|
+
prUrl,
|
|
13699
|
+
tokensUsed,
|
|
13700
|
+
tokensBudget,
|
|
13701
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
13702
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
13703
|
+
});
|
|
13704
|
+
} else if (event.type === "error") {
|
|
13705
|
+
const message2 = String(event.message ?? "");
|
|
13706
|
+
const category = event.category;
|
|
13707
|
+
setEvents((e) => [
|
|
13708
|
+
...e,
|
|
13709
|
+
{ kind: "error", key: mkKey(), text: `Remote error: ${message2}` }
|
|
13710
|
+
]);
|
|
13711
|
+
await saveRemoteSession({
|
|
13712
|
+
sessionId: data.sessionId,
|
|
13713
|
+
prompt,
|
|
13714
|
+
repo: `${repo.owner}/${repo.name}`,
|
|
13715
|
+
workerUrl: finalCfg.remoteWorkerUrl,
|
|
13716
|
+
status: "error",
|
|
13717
|
+
errorCategory: category ?? "unknown",
|
|
13718
|
+
errorSummary: message2,
|
|
13719
|
+
errorMessage: message2,
|
|
13720
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
13721
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
13722
|
+
});
|
|
13723
|
+
}
|
|
13724
|
+
}
|
|
13725
|
+
} catch (err) {
|
|
13726
|
+
setEvents((e) => [
|
|
13727
|
+
...e,
|
|
13728
|
+
{ kind: "error", key: mkKey(), text: `Failed: ${err instanceof Error ? err.message : String(err)}` }
|
|
13729
|
+
]);
|
|
13730
|
+
}
|
|
13731
|
+
})();
|
|
13732
|
+
return true;
|
|
13733
|
+
}
|
|
12642
13734
|
if (c === "/help") {
|
|
12643
13735
|
setShowHelpMenu(true);
|
|
12644
13736
|
return true;
|
|
12645
13737
|
}
|
|
12646
13738
|
return false;
|
|
12647
13739
|
},
|
|
12648
|
-
[cfg, exit, usage, effort, theme, mode, openResumePicker, runCompact, runInit, initMcp, setCfg]
|
|
13740
|
+
[cfg, exit, usage, effort, theme, mode, openResumePicker, runCompact, runInit, initMcp, setCfg, setShowRemoteDashboard, setSelectedRemoteSession]
|
|
12649
13741
|
);
|
|
12650
13742
|
const handleHelpCommand = useCallback(
|
|
12651
13743
|
(command) => {
|
|
@@ -12788,6 +13880,15 @@ ${lines.join("\n")}` }]);
|
|
|
12788
13880
|
gatewayMetaRef.current = null;
|
|
12789
13881
|
setGatewayMeta(null);
|
|
12790
13882
|
setTurnStartedAt(Date.now());
|
|
13883
|
+
const classification = classifyIntent(trimmed);
|
|
13884
|
+
const effortForTier = {
|
|
13885
|
+
light: "low",
|
|
13886
|
+
medium: "medium",
|
|
13887
|
+
heavy: "high"
|
|
13888
|
+
};
|
|
13889
|
+
const turnReasoningEffort = overrideEffort ?? effortForTier[classification.tier] ?? effortRef.current;
|
|
13890
|
+
const effectiveCodeMode = classification.tier === "heavy";
|
|
13891
|
+
setCodeMode(effectiveCodeMode);
|
|
12791
13892
|
const controller = new AbortController();
|
|
12792
13893
|
activeControllerRef.current = controller;
|
|
12793
13894
|
const sharedCallbacks = {
|
|
@@ -12901,18 +14002,22 @@ ${lines.join("\n")}` }]);
|
|
|
12901
14002
|
executor: executorRef.current,
|
|
12902
14003
|
cwd: process.cwd(),
|
|
12903
14004
|
signal: controller.signal,
|
|
12904
|
-
reasoningEffort:
|
|
14005
|
+
reasoningEffort: turnReasoningEffort,
|
|
12905
14006
|
coauthor: cfg.coauthor !== false ? { name: cfg.coauthorName || "kimiflare", email: cfg.coauthorEmail || "kimiflare@proton.me" } : void 0,
|
|
12906
14007
|
sessionId: ensureSessionId(),
|
|
12907
14008
|
memoryManager: memoryManagerRef.current,
|
|
12908
14009
|
keepLastImageTurns: cfg.imageHistoryTurns ?? 2,
|
|
12909
|
-
codeMode,
|
|
14010
|
+
codeMode: effectiveCodeMode,
|
|
14011
|
+
maxInputTokens: effectiveCodeMode ? 2e5 : void 0,
|
|
14012
|
+
continueOnLimit: effectiveCodeMode ? true : void 0,
|
|
14013
|
+
onIterationEnd,
|
|
14014
|
+
intentClassification: classification,
|
|
12910
14015
|
onFileChange: (path, content2) => {
|
|
12911
14016
|
if (content2) {
|
|
12912
14017
|
lspManagerRef.current.notifyChange(path, content2);
|
|
12913
14018
|
} else {
|
|
12914
14019
|
void import("fs/promises").then(
|
|
12915
|
-
({ readFile:
|
|
14020
|
+
({ readFile: readFile16 }) => readFile16(path, "utf8").then((c) => lspManagerRef.current.notifyChange(path, c)).catch(() => {
|
|
12916
14021
|
})
|
|
12917
14022
|
);
|
|
12918
14023
|
}
|
|
@@ -13034,6 +14139,7 @@ ${lines.join("\n")}` }]);
|
|
|
13034
14139
|
}
|
|
13035
14140
|
}
|
|
13036
14141
|
} finally {
|
|
14142
|
+
setCodeMode(false);
|
|
13037
14143
|
const asstId = activeAsstIdRef.current;
|
|
13038
14144
|
if (asstId !== null) updateAssistant(asstId, () => ({ streaming: false }));
|
|
13039
14145
|
setBusy(false);
|
|
@@ -13046,7 +14152,7 @@ ${lines.join("\n")}` }]);
|
|
|
13046
14152
|
},
|
|
13047
14153
|
[cfg, handleSlash, updateAssistant, updateTool, saveSessionSafe, updateGatewayMeta]
|
|
13048
14154
|
);
|
|
13049
|
-
|
|
14155
|
+
useEffect5(() => {
|
|
13050
14156
|
if (!busy && queue.length > 0) {
|
|
13051
14157
|
const next = queue[0];
|
|
13052
14158
|
setQueue((q) => q.slice(1));
|
|
@@ -13074,7 +14180,7 @@ ${lines.join("\n")}` }]);
|
|
|
13074
14180
|
[busy, processMessage]
|
|
13075
14181
|
);
|
|
13076
14182
|
submitRef.current = submit;
|
|
13077
|
-
|
|
14183
|
+
useEffect5(() => {
|
|
13078
14184
|
if (compactSuggestedRef.current) return;
|
|
13079
14185
|
if (usage && usage.prompt_tokens / CONTEXT_LIMIT >= AUTO_COMPACT_SUGGEST_PCT) {
|
|
13080
14186
|
compactSuggestedRef.current = true;
|
|
@@ -13089,7 +14195,7 @@ ${lines.join("\n")}` }]);
|
|
|
13089
14195
|
}
|
|
13090
14196
|
}, [usage]);
|
|
13091
14197
|
if (!cfg) {
|
|
13092
|
-
return /* @__PURE__ */
|
|
14198
|
+
return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(
|
|
13093
14199
|
Onboarding,
|
|
13094
14200
|
{
|
|
13095
14201
|
onDone: (newCfg) => {
|
|
@@ -13103,10 +14209,42 @@ ${lines.join("\n")}` }]);
|
|
|
13103
14209
|
) });
|
|
13104
14210
|
}
|
|
13105
14211
|
if (resumeSessions !== null) {
|
|
13106
|
-
return /* @__PURE__ */
|
|
14212
|
+
return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", children: /* @__PURE__ */ jsx22(ResumePicker, { sessions: resumeSessions, onPick: handleResumePick }) }) });
|
|
14213
|
+
}
|
|
14214
|
+
if (showRemoteDashboard) {
|
|
14215
|
+
return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", children: selectedRemoteSession ? /* @__PURE__ */ jsx22(
|
|
14216
|
+
RemoteSessionDetail,
|
|
14217
|
+
{
|
|
14218
|
+
session: selectedRemoteSession,
|
|
14219
|
+
onBack: () => setSelectedRemoteSession(null),
|
|
14220
|
+
onCancel: async (session) => {
|
|
14221
|
+
try {
|
|
14222
|
+
const { cancelRemoteSession: cancelRemoteSession2 } = await Promise.resolve().then(() => (init_worker_client(), worker_client_exports));
|
|
14223
|
+
await cancelRemoteSession2(session.workerUrl, session.sessionId);
|
|
14224
|
+
setEvents((e) => [
|
|
14225
|
+
...e,
|
|
14226
|
+
{ kind: "info", key: mkKey(), text: `Cancelled session ${session.sessionId}` }
|
|
14227
|
+
]);
|
|
14228
|
+
} catch (err) {
|
|
14229
|
+
setEvents((e) => [
|
|
14230
|
+
...e,
|
|
14231
|
+
{ kind: "error", key: mkKey(), text: `Failed to cancel: ${err instanceof Error ? err.message : String(err)}` }
|
|
14232
|
+
]);
|
|
14233
|
+
}
|
|
14234
|
+
setSelectedRemoteSession(null);
|
|
14235
|
+
setShowRemoteDashboard(false);
|
|
14236
|
+
}
|
|
14237
|
+
}
|
|
14238
|
+
) : /* @__PURE__ */ jsx22(
|
|
14239
|
+
RemoteDashboard,
|
|
14240
|
+
{
|
|
14241
|
+
onSelect: (session) => setSelectedRemoteSession(session),
|
|
14242
|
+
onCancel: () => setShowRemoteDashboard(false)
|
|
14243
|
+
}
|
|
14244
|
+
) }) });
|
|
13107
14245
|
}
|
|
13108
14246
|
if (showHelpMenu) {
|
|
13109
|
-
return /* @__PURE__ */
|
|
14247
|
+
return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", children: /* @__PURE__ */ jsx22(
|
|
13110
14248
|
HelpMenu,
|
|
13111
14249
|
{
|
|
13112
14250
|
customCommands: customCommandsRef.current.filter((c) => !BUILTIN_COMMAND_NAMES.has(c.name.toLowerCase())).map((c) => ({ name: c.name, description: c.description })),
|
|
@@ -13117,12 +14255,12 @@ ${lines.join("\n")}` }]);
|
|
|
13117
14255
|
) }) });
|
|
13118
14256
|
}
|
|
13119
14257
|
if (showLspWizard) {
|
|
13120
|
-
return /* @__PURE__ */
|
|
14258
|
+
return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", children: /* @__PURE__ */ jsx22(
|
|
13121
14259
|
LspWizard,
|
|
13122
14260
|
{
|
|
13123
14261
|
servers: cfg?.lspServers ?? {},
|
|
13124
14262
|
currentScope: lspScope,
|
|
13125
|
-
hasProjectDir: existsSync2(
|
|
14263
|
+
hasProjectDir: existsSync2(join19(process.cwd(), ".kimiflare")),
|
|
13126
14264
|
onDone: () => setShowLspWizard(false),
|
|
13127
14265
|
onSave: (servers, enabled, scope) => {
|
|
13128
14266
|
setCfg((c) => c ? { ...c, lspEnabled: enabled, lspServers: servers } : c);
|
|
@@ -13154,7 +14292,7 @@ ${lines.join("\n")}` }]);
|
|
|
13154
14292
|
) }) });
|
|
13155
14293
|
}
|
|
13156
14294
|
if (commandWizard) {
|
|
13157
|
-
return /* @__PURE__ */
|
|
14295
|
+
return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", children: /* @__PURE__ */ jsx22(
|
|
13158
14296
|
CommandWizard,
|
|
13159
14297
|
{
|
|
13160
14298
|
mode: commandWizard.mode,
|
|
@@ -13167,7 +14305,7 @@ ${lines.join("\n")}` }]);
|
|
|
13167
14305
|
) }) });
|
|
13168
14306
|
}
|
|
13169
14307
|
if (commandPicker) {
|
|
13170
|
-
return /* @__PURE__ */
|
|
14308
|
+
return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", children: /* @__PURE__ */ jsx22(
|
|
13171
14309
|
CommandPicker,
|
|
13172
14310
|
{
|
|
13173
14311
|
commands: customCommandsRef.current,
|
|
@@ -13185,15 +14323,15 @@ ${lines.join("\n")}` }]);
|
|
|
13185
14323
|
) }) });
|
|
13186
14324
|
}
|
|
13187
14325
|
if (commandToDelete) {
|
|
13188
|
-
return /* @__PURE__ */
|
|
13189
|
-
/* @__PURE__ */
|
|
14326
|
+
return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsxs20(Box20, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
14327
|
+
/* @__PURE__ */ jsxs20(Text21, { color: theme.accent, bold: true, children: [
|
|
13190
14328
|
"Delete /",
|
|
13191
14329
|
commandToDelete.name,
|
|
13192
14330
|
"?"
|
|
13193
14331
|
] }),
|
|
13194
|
-
/* @__PURE__ */
|
|
13195
|
-
/* @__PURE__ */
|
|
13196
|
-
|
|
14332
|
+
/* @__PURE__ */ jsx22(Text21, { color: theme.info.color, children: commandToDelete.filepath }),
|
|
14333
|
+
/* @__PURE__ */ jsx22(Box20, { marginTop: 1, children: /* @__PURE__ */ jsx22(
|
|
14334
|
+
SelectInput9,
|
|
13197
14335
|
{
|
|
13198
14336
|
items: [
|
|
13199
14337
|
{ label: "Yes, delete", value: "yes", key: "yes" },
|
|
@@ -13211,7 +14349,7 @@ ${lines.join("\n")}` }]);
|
|
|
13211
14349
|
] }) });
|
|
13212
14350
|
}
|
|
13213
14351
|
if (showCommandList) {
|
|
13214
|
-
return /* @__PURE__ */
|
|
14352
|
+
return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", children: /* @__PURE__ */ jsx22(
|
|
13215
14353
|
CommandList,
|
|
13216
14354
|
{
|
|
13217
14355
|
commands: customCommandsRef.current,
|
|
@@ -13220,12 +14358,12 @@ ${lines.join("\n")}` }]);
|
|
|
13220
14358
|
) }) });
|
|
13221
14359
|
}
|
|
13222
14360
|
if (showThemePicker) {
|
|
13223
|
-
return /* @__PURE__ */
|
|
14361
|
+
return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", children: /* @__PURE__ */ jsx22(ThemePicker, { themes: themeList(), onPick: handleThemePick, onPreview: (t) => setTheme(t) }) }) });
|
|
13224
14362
|
}
|
|
13225
14363
|
const hasConversation = events.some((e) => e.kind === "user" || e.kind === "assistant");
|
|
13226
|
-
return /* @__PURE__ */
|
|
13227
|
-
!hasConversation && events.length === 0 ? /* @__PURE__ */
|
|
13228
|
-
perm ? /* @__PURE__ */
|
|
14364
|
+
return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsxs20(Box20, { flexDirection: "column", children: [
|
|
14365
|
+
!hasConversation && events.length === 0 ? /* @__PURE__ */ jsx22(Welcome, { accountId: cfg.accountId }) : /* @__PURE__ */ jsx22(ChatView, { events, showReasoning, verbose }),
|
|
14366
|
+
perm ? /* @__PURE__ */ jsx22(
|
|
13229
14367
|
PermissionModal,
|
|
13230
14368
|
{
|
|
13231
14369
|
tool: perm.tool,
|
|
@@ -13236,8 +14374,8 @@ ${lines.join("\n")}` }]);
|
|
|
13236
14374
|
setPerm(null);
|
|
13237
14375
|
}
|
|
13238
14376
|
}
|
|
13239
|
-
) : /* @__PURE__ */
|
|
13240
|
-
tasks.length > 0 && /* @__PURE__ */
|
|
14377
|
+
) : /* @__PURE__ */ jsxs20(Box20, { flexDirection: "column", marginTop: 1, children: [
|
|
14378
|
+
tasks.length > 0 && /* @__PURE__ */ jsx22(
|
|
13241
14379
|
TaskList,
|
|
13242
14380
|
{
|
|
13243
14381
|
tasks,
|
|
@@ -13245,11 +14383,11 @@ ${lines.join("\n")}` }]);
|
|
|
13245
14383
|
tokensDelta: Math.max(0, (usage?.prompt_tokens ?? 0) - tasksStartTokens)
|
|
13246
14384
|
}
|
|
13247
14385
|
),
|
|
13248
|
-
queue.length > 0 && /* @__PURE__ */
|
|
14386
|
+
queue.length > 0 && /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", marginBottom: 1, children: queue.map((q, i) => /* @__PURE__ */ jsxs20(Text21, { color: theme.info.color, children: [
|
|
13249
14387
|
"\u23F3 ",
|
|
13250
14388
|
q.display
|
|
13251
14389
|
] }, `queue_${i}`)) }),
|
|
13252
|
-
/* @__PURE__ */
|
|
14390
|
+
/* @__PURE__ */ jsx22(
|
|
13253
14391
|
StatusBar,
|
|
13254
14392
|
{
|
|
13255
14393
|
model: cfg.model,
|
|
@@ -13266,7 +14404,7 @@ ${lines.join("\n")}` }]);
|
|
|
13266
14404
|
codeMode
|
|
13267
14405
|
}
|
|
13268
14406
|
),
|
|
13269
|
-
activePicker?.kind === "file" && /* @__PURE__ */
|
|
14407
|
+
activePicker?.kind === "file" && /* @__PURE__ */ jsx22(
|
|
13270
14408
|
FilePicker,
|
|
13271
14409
|
{
|
|
13272
14410
|
items: filteredFileItems,
|
|
@@ -13274,7 +14412,7 @@ ${lines.join("\n")}` }]);
|
|
|
13274
14412
|
query: pickerQuery ?? ""
|
|
13275
14413
|
}
|
|
13276
14414
|
),
|
|
13277
|
-
activePicker?.kind === "slash" && /* @__PURE__ */
|
|
14415
|
+
activePicker?.kind === "slash" && /* @__PURE__ */ jsx22(
|
|
13278
14416
|
SlashPicker,
|
|
13279
14417
|
{
|
|
13280
14418
|
items: filteredSlashItems,
|
|
@@ -13282,9 +14420,9 @@ ${lines.join("\n")}` }]);
|
|
|
13282
14420
|
query: pickerQuery ?? ""
|
|
13283
14421
|
}
|
|
13284
14422
|
),
|
|
13285
|
-
/* @__PURE__ */
|
|
13286
|
-
/* @__PURE__ */
|
|
13287
|
-
/* @__PURE__ */
|
|
14423
|
+
/* @__PURE__ */ jsxs20(Box20, { marginTop: 1, children: [
|
|
14424
|
+
/* @__PURE__ */ jsx22(Text21, { color: "#d699b6", children: "\u203A " }),
|
|
14425
|
+
/* @__PURE__ */ jsx22(
|
|
13288
14426
|
CustomTextInput,
|
|
13289
14427
|
{
|
|
13290
14428
|
value: input,
|
|
@@ -13341,7 +14479,7 @@ ${lines.join("\n")}` }]);
|
|
|
13341
14479
|
}
|
|
13342
14480
|
async function renderApp(cfg, updateResult, lspScope = "global", lspProjectPath = null) {
|
|
13343
14481
|
const instance = render(
|
|
13344
|
-
/* @__PURE__ */
|
|
14482
|
+
/* @__PURE__ */ jsx22(
|
|
13345
14483
|
App,
|
|
13346
14484
|
{
|
|
13347
14485
|
initialCfg: cfg,
|
|
@@ -13382,7 +14520,13 @@ var init_app = __esm({
|
|
|
13382
14520
|
init_welcome();
|
|
13383
14521
|
init_help_menu();
|
|
13384
14522
|
init_config();
|
|
14523
|
+
init_worker_client();
|
|
14524
|
+
init_session_store();
|
|
14525
|
+
init_tui_deploy();
|
|
14526
|
+
init_tui_auth();
|
|
14527
|
+
init_remote_dashboard();
|
|
13385
14528
|
init_mode();
|
|
14529
|
+
init_classify();
|
|
13386
14530
|
init_sessions();
|
|
13387
14531
|
init_image();
|
|
13388
14532
|
init_usage_tracker();
|
|
@@ -13431,9 +14575,108 @@ init_system_prompt();
|
|
|
13431
14575
|
init_executor();
|
|
13432
14576
|
init_update_check();
|
|
13433
14577
|
init_version();
|
|
14578
|
+
import { Command as Command2 } from "commander";
|
|
14579
|
+
|
|
14580
|
+
// src/remote/cli.ts
|
|
14581
|
+
init_config();
|
|
14582
|
+
init_session_store();
|
|
14583
|
+
init_deploy();
|
|
13434
14584
|
import { Command } from "commander";
|
|
13435
|
-
|
|
13436
|
-
|
|
14585
|
+
function createRemoteCommand() {
|
|
14586
|
+
const remote = new Command("remote").description("Manage remote sessions");
|
|
14587
|
+
remote.command("deploy").description("Deploy the remote Worker and container image to Cloudflare").action(async () => {
|
|
14588
|
+
await runDeploy();
|
|
14589
|
+
});
|
|
14590
|
+
remote.command("setup").description("Check remote deployment status and prerequisites").action(async () => {
|
|
14591
|
+
const status = await checkDeployStatus();
|
|
14592
|
+
console.log("Remote deployment status:\n");
|
|
14593
|
+
console.log(` wrangler CLI: ${status.wrangler ? "yes" : "no"}`);
|
|
14594
|
+
console.log(` wrangler auth: ${status.wranglerAuth ? "yes" : "no"}`);
|
|
14595
|
+
console.log(` Docker: ${status.docker ? "yes" : "no"}`);
|
|
14596
|
+
console.log(` Worker URL: ${status.workerUrl ?? "not deployed"}`);
|
|
14597
|
+
console.log("\nRun `kimiflare remote deploy` to deploy.");
|
|
14598
|
+
});
|
|
14599
|
+
remote.command("list").description("List remote sessions").action(async () => {
|
|
14600
|
+
const sessions = await listRemoteSessions();
|
|
14601
|
+
if (sessions.length === 0) {
|
|
14602
|
+
console.log("No remote sessions found.");
|
|
14603
|
+
return;
|
|
14604
|
+
}
|
|
14605
|
+
console.log(`Remote sessions (${sessions.length} total):
|
|
14606
|
+
`);
|
|
14607
|
+
for (const s of sessions.slice(0, 20)) {
|
|
14608
|
+
const date = new Date(s.createdAt).toLocaleString();
|
|
14609
|
+
const statusIcon = s.status === "done" ? "\u2705" : s.status === "error" ? "\u274C" : s.status === "running" ? "\u23F3" : "\u23F9\uFE0F";
|
|
14610
|
+
console.log(` ${statusIcon} ${s.sessionId.slice(0, 8)}\u2026 ${s.status.padEnd(10)} ${date} ${s.prompt.slice(0, 50)}`);
|
|
14611
|
+
if (s.prUrl) {
|
|
14612
|
+
console.log(` PR: ${s.prUrl}`);
|
|
14613
|
+
}
|
|
14614
|
+
}
|
|
14615
|
+
});
|
|
14616
|
+
remote.command("status").description("Show remote session status").argument("[session-id]", "Session ID (defaults to most recent)").action(async (sessionId) => {
|
|
14617
|
+
const session = sessionId ? await loadRemoteSession(sessionId) : await getMostRecentRemoteSession();
|
|
14618
|
+
if (!session) {
|
|
14619
|
+
console.log(sessionId ? `Session ${sessionId} not found.` : "No remote sessions found.");
|
|
14620
|
+
return;
|
|
14621
|
+
}
|
|
14622
|
+
const cfg = await loadConfig();
|
|
14623
|
+
const workerUrl = cfg?.remoteWorkerUrl;
|
|
14624
|
+
if (!workerUrl) {
|
|
14625
|
+
console.log("Remote worker not configured.");
|
|
14626
|
+
return;
|
|
14627
|
+
}
|
|
14628
|
+
try {
|
|
14629
|
+
const res = await fetch(`${workerUrl}/remote/status/${session.sessionId}`, {
|
|
14630
|
+
headers: {
|
|
14631
|
+
Authorization: `Bearer ${cfg.remoteAuthSecret ?? ""}`
|
|
14632
|
+
}
|
|
14633
|
+
});
|
|
14634
|
+
if (!res.ok) {
|
|
14635
|
+
console.log(`Failed to fetch status: ${res.status}`);
|
|
14636
|
+
return;
|
|
14637
|
+
}
|
|
14638
|
+
const data = await res.json();
|
|
14639
|
+
console.log(`Session: ${data.sessionId}`);
|
|
14640
|
+
console.log(`Status: ${data.status}`);
|
|
14641
|
+
console.log(`Prompt: ${data.prompt}`);
|
|
14642
|
+
console.log(`Repo: ${data.repo?.owner}/${data.repo?.name}`);
|
|
14643
|
+
console.log(`Branch: ${data.branch}`);
|
|
14644
|
+
console.log(`Turns: ${data.currentTurn} / ${data.maxTurns}`);
|
|
14645
|
+
if (data.prUrl) console.log(`PR: ${data.prUrl}`);
|
|
14646
|
+
if (data.errorMessage) console.log(`Error: ${data.errorMessage}`);
|
|
14647
|
+
} catch (err) {
|
|
14648
|
+
console.log(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
14649
|
+
}
|
|
14650
|
+
});
|
|
14651
|
+
remote.command("cancel").description("Cancel a remote session").argument("<session-id>", "Session ID").action(async (sessionId) => {
|
|
14652
|
+
const cfg = await loadConfig();
|
|
14653
|
+
const workerUrl = cfg?.remoteWorkerUrl;
|
|
14654
|
+
if (!workerUrl) {
|
|
14655
|
+
console.log("Remote worker not configured.");
|
|
14656
|
+
return;
|
|
14657
|
+
}
|
|
14658
|
+
try {
|
|
14659
|
+
const res = await fetch(`${workerUrl}/remote/cancel/${sessionId}`, {
|
|
14660
|
+
method: "POST",
|
|
14661
|
+
headers: {
|
|
14662
|
+
Authorization: `Bearer ${cfg.remoteAuthSecret ?? ""}`
|
|
14663
|
+
}
|
|
14664
|
+
});
|
|
14665
|
+
if (!res.ok) {
|
|
14666
|
+
console.log(`Failed to cancel: ${res.status}`);
|
|
14667
|
+
return;
|
|
14668
|
+
}
|
|
14669
|
+
console.log(`Session ${sessionId} cancelled.`);
|
|
14670
|
+
} catch (err) {
|
|
14671
|
+
console.log(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
14672
|
+
}
|
|
14673
|
+
});
|
|
14674
|
+
return remote;
|
|
14675
|
+
}
|
|
14676
|
+
|
|
14677
|
+
// src/index.tsx
|
|
14678
|
+
var program = new Command2();
|
|
14679
|
+
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));
|
|
13437
14680
|
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) => {
|
|
13438
14681
|
const cfg = await loadConfig();
|
|
13439
14682
|
const enabled = cfg?.costAttribution ?? false;
|
|
@@ -13446,6 +14689,23 @@ program.command("cost").description("Show cost attribution by task type (require
|
|
|
13446
14689
|
const { runCostCommand: runCostCommand2 } = await Promise.resolve().then(() => (init_cli(), cli_exports));
|
|
13447
14690
|
await runCostCommand2({ ...cmdOpts, config: cfg });
|
|
13448
14691
|
});
|
|
14692
|
+
program.addCommand(createRemoteCommand());
|
|
14693
|
+
program.command("auth").description("Authenticate with external services").addCommand(
|
|
14694
|
+
new Command2("github").description("Authenticate with GitHub via OAuth device flow").action(async () => {
|
|
14695
|
+
const { authGitHubForTui: authGitHubForTui2 } = await Promise.resolve().then(() => (init_tui_auth(), tui_auth_exports));
|
|
14696
|
+
for await (const step of authGitHubForTui2()) {
|
|
14697
|
+
console.log(step.message);
|
|
14698
|
+
if (step.url && step.code) {
|
|
14699
|
+
console.log(`
|
|
14700
|
+
Open: ${step.url}`);
|
|
14701
|
+
console.log(`Code: ${step.code}
|
|
14702
|
+
`);
|
|
14703
|
+
}
|
|
14704
|
+
if (step.done) break;
|
|
14705
|
+
if (step.error) process.exit(1);
|
|
14706
|
+
}
|
|
14707
|
+
})
|
|
14708
|
+
);
|
|
13449
14709
|
program.action(async () => {
|
|
13450
14710
|
await main();
|
|
13451
14711
|
});
|
|
@@ -13482,6 +14742,8 @@ async function main() {
|
|
|
13482
14742
|
allowAll: !!opts.dangerouslyAllowAll,
|
|
13483
14743
|
showReasoning: !!opts.reasoning,
|
|
13484
14744
|
codeMode: cfg.codeMode,
|
|
14745
|
+
continueOnLimit: !!opts.continueOnLimit,
|
|
14746
|
+
maxInputTokens: opts.maxInputTokens,
|
|
13485
14747
|
updateResult
|
|
13486
14748
|
});
|
|
13487
14749
|
return;
|
|
@@ -13529,52 +14791,63 @@ async function runPrintMode(opts2) {
|
|
|
13529
14791
|
process.on("SIGINT", () => controller.abort());
|
|
13530
14792
|
let printedReasoningHeader = false;
|
|
13531
14793
|
let printedAnswerHeader = false;
|
|
13532
|
-
|
|
13533
|
-
|
|
13534
|
-
|
|
13535
|
-
|
|
13536
|
-
|
|
13537
|
-
|
|
13538
|
-
|
|
13539
|
-
|
|
13540
|
-
|
|
13541
|
-
|
|
13542
|
-
|
|
13543
|
-
|
|
13544
|
-
|
|
13545
|
-
|
|
13546
|
-
|
|
13547
|
-
|
|
13548
|
-
|
|
13549
|
-
|
|
13550
|
-
|
|
13551
|
-
|
|
13552
|
-
|
|
13553
|
-
|
|
13554
|
-
|
|
13555
|
-
|
|
13556
|
-
|
|
13557
|
-
|
|
13558
|
-
|
|
13559
|
-
|
|
13560
|
-
|
|
14794
|
+
try {
|
|
14795
|
+
await runAgentTurn({
|
|
14796
|
+
accountId: opts2.accountId,
|
|
14797
|
+
apiToken: opts2.apiToken,
|
|
14798
|
+
model: opts2.model,
|
|
14799
|
+
gateway: gatewayFromPrintOpts(opts2),
|
|
14800
|
+
messages,
|
|
14801
|
+
tools: ALL_TOOLS,
|
|
14802
|
+
executor,
|
|
14803
|
+
cwd,
|
|
14804
|
+
signal: controller.signal,
|
|
14805
|
+
codeMode: opts2.codeMode,
|
|
14806
|
+
continueOnLimit: opts2.continueOnLimit,
|
|
14807
|
+
maxInputTokens: opts2.maxInputTokens,
|
|
14808
|
+
coauthor: opts2.coauthor !== false ? { name: opts2.coauthorName || "kimiflare", email: opts2.coauthorEmail || "kimiflare@proton.me" } : void 0,
|
|
14809
|
+
callbacks: {
|
|
14810
|
+
onReasoningDelta: opts2.showReasoning ? (delta) => {
|
|
14811
|
+
if (!printedReasoningHeader) {
|
|
14812
|
+
process.stderr.write("\x1B[2m--- reasoning ---\n");
|
|
14813
|
+
printedReasoningHeader = true;
|
|
14814
|
+
}
|
|
14815
|
+
process.stderr.write(delta);
|
|
14816
|
+
} : void 0,
|
|
14817
|
+
onTextDelta: (delta) => {
|
|
14818
|
+
if (opts2.showReasoning && printedReasoningHeader && !printedAnswerHeader) {
|
|
14819
|
+
process.stderr.write("\n--- answer ---\x1B[0m\n");
|
|
14820
|
+
printedAnswerHeader = true;
|
|
14821
|
+
}
|
|
14822
|
+
process.stdout.write(delta);
|
|
14823
|
+
},
|
|
14824
|
+
onToolCallFinalized: (call) => {
|
|
14825
|
+
process.stderr.write(`\x1B[2m[tool ${call.function.name}(${call.function.arguments})]\x1B[0m
|
|
13561
14826
|
`);
|
|
13562
|
-
|
|
13563
|
-
|
|
13564
|
-
|
|
13565
|
-
|
|
14827
|
+
},
|
|
14828
|
+
onToolResult: (result) => {
|
|
14829
|
+
const snippet = result.content.length > 400 ? result.content.slice(0, 400) + "..." : result.content;
|
|
14830
|
+
process.stderr.write(`\x1B[2m[result: ${snippet.replace(/\n/g, " \u23CE ")}]\x1B[0m
|
|
13566
14831
|
`);
|
|
13567
|
-
|
|
13568
|
-
|
|
13569
|
-
|
|
13570
|
-
|
|
13571
|
-
|
|
14832
|
+
},
|
|
14833
|
+
askPermission: async ({ tool, args }) => {
|
|
14834
|
+
if (opts2.allowAll) return "allow";
|
|
14835
|
+
process.stderr.write(
|
|
14836
|
+
`\x1B[31m[permission denied: ${tool.name}(${JSON.stringify(args)}) \u2014 pass --dangerously-allow-all to approve in print mode]\x1B[0m
|
|
13572
14837
|
`
|
|
13573
|
-
|
|
13574
|
-
|
|
14838
|
+
);
|
|
14839
|
+
return "deny";
|
|
14840
|
+
}
|
|
13575
14841
|
}
|
|
14842
|
+
});
|
|
14843
|
+
} catch (err) {
|
|
14844
|
+
if (err instanceof BudgetExhaustedError) {
|
|
14845
|
+
process.stderr.write("\n\x1B[33m[Budget exhausted \u2014 exiting with code 42]\x1B[0m\n");
|
|
14846
|
+
process.exitCode = 42;
|
|
14847
|
+
return;
|
|
13576
14848
|
}
|
|
13577
|
-
|
|
14849
|
+
throw err;
|
|
14850
|
+
}
|
|
13578
14851
|
process.stdout.write("\n");
|
|
13579
14852
|
}
|
|
13580
14853
|
//# sourceMappingURL=index.js.map
|