kimiflare 0.33.0 → 0.34.1
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 +1809 -509
- 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";
|
|
@@ -74,7 +83,7 @@ async function loadConfig() {
|
|
|
74
83
|
const envCacheStable = process.env.KIMIFLARE_CACHE_STABLE_PROMPTS;
|
|
75
84
|
const cacheStablePrompts = envCacheStable === "0" || envCacheStable === "false" ? false : true;
|
|
76
85
|
const envCompiled = process.env.KIMIFLARE_COMPILED_CONTEXT;
|
|
77
|
-
const compiledContext = envCompiled === "
|
|
86
|
+
const compiledContext = envCompiled === "0" || envCompiled === "false" ? false : true;
|
|
78
87
|
const envImageTurns = process.env.KIMIFLARE_IMAGE_HISTORY_TURNS;
|
|
79
88
|
const imageHistoryTurns = envImageTurns ? parseInt(envImageTurns, 10) : void 0;
|
|
80
89
|
const envMemoryEnabled = readBooleanEnv("KIMIFLARE_MEMORY_ENABLED");
|
|
@@ -83,6 +92,7 @@ async function loadConfig() {
|
|
|
83
92
|
const envMemoryMaxEntries = readNumberEnv("KIMIFLARE_MEMORY_MAX_ENTRIES");
|
|
84
93
|
const envMemoryEmbeddingModel = process.env.KIMIFLARE_MEMORY_EMBEDDING_MODEL;
|
|
85
94
|
const envPlumbingModel = process.env.KIMIFLARE_PLUMBING_MODEL;
|
|
95
|
+
const envMemoryExtractionModel = process.env.KIMIFLARE_MEMORY_EXTRACTION_MODEL;
|
|
86
96
|
const envCodeMode = readBooleanEnv("KIMIFLARE_CODE_MODE");
|
|
87
97
|
const envCostAttribution = readBooleanEnv("KIMI_COST_ATTRIBUTION");
|
|
88
98
|
const envFilePicker = readBooleanEnv("KIMIFLARE_FILE_PICKER");
|
|
@@ -103,14 +113,15 @@ async function loadConfig() {
|
|
|
103
113
|
cacheStablePrompts,
|
|
104
114
|
compiledContext,
|
|
105
115
|
imageHistoryTurns: Number.isNaN(imageHistoryTurns) ? void 0 : imageHistoryTurns,
|
|
106
|
-
memoryEnabled: envMemoryEnabled,
|
|
116
|
+
memoryEnabled: envMemoryEnabled ?? true,
|
|
107
117
|
memoryDbPath: envMemoryDbPath,
|
|
108
118
|
memoryMaxAgeDays: envMemoryMaxAgeDays,
|
|
109
119
|
memoryMaxEntries: envMemoryMaxEntries,
|
|
110
120
|
memoryEmbeddingModel: envMemoryEmbeddingModel,
|
|
111
121
|
plumbingModel: envPlumbingModel,
|
|
112
|
-
|
|
113
|
-
|
|
122
|
+
memoryExtractionModel: envMemoryExtractionModel,
|
|
123
|
+
codeMode: envCodeMode ?? true,
|
|
124
|
+
costAttribution: envCostAttribution ?? true,
|
|
114
125
|
filePicker: envFilePicker ?? true
|
|
115
126
|
};
|
|
116
127
|
}
|
|
@@ -135,14 +146,15 @@ async function loadConfig() {
|
|
|
135
146
|
cacheStablePrompts: parsed.cacheStablePrompts ?? cacheStablePrompts,
|
|
136
147
|
compiledContext: parsed.compiledContext ?? compiledContext,
|
|
137
148
|
imageHistoryTurns: Number.isNaN(imageHistoryTurns) ? parsed.imageHistoryTurns : imageHistoryTurns,
|
|
138
|
-
memoryEnabled: envMemoryEnabled ?? parsed.memoryEnabled,
|
|
149
|
+
memoryEnabled: envMemoryEnabled ?? parsed.memoryEnabled ?? true,
|
|
139
150
|
memoryDbPath: envMemoryDbPath ?? parsed.memoryDbPath,
|
|
140
151
|
memoryMaxAgeDays: envMemoryMaxAgeDays ?? parsed.memoryMaxAgeDays,
|
|
141
152
|
memoryMaxEntries: envMemoryMaxEntries ?? parsed.memoryMaxEntries,
|
|
142
153
|
memoryEmbeddingModel: envMemoryEmbeddingModel ?? parsed.memoryEmbeddingModel,
|
|
143
154
|
plumbingModel: envPlumbingModel ?? parsed.plumbingModel,
|
|
144
|
-
|
|
145
|
-
|
|
155
|
+
memoryExtractionModel: envMemoryExtractionModel ?? parsed.memoryExtractionModel,
|
|
156
|
+
codeMode: envCodeMode ?? parsed.codeMode ?? true,
|
|
157
|
+
costAttribution: envCostAttribution ?? parsed.costAttribution ?? true,
|
|
146
158
|
filePicker: envFilePicker ?? parsed.filePicker ?? true
|
|
147
159
|
};
|
|
148
160
|
}
|
|
@@ -544,44 +556,51 @@ async function* parseStream(body, signal) {
|
|
|
544
556
|
lastUsage = chunk.usage;
|
|
545
557
|
yield { type: "usage", usage: chunk.usage };
|
|
546
558
|
}
|
|
559
|
+
if (typeof chunk.response === "string") {
|
|
560
|
+
const resp = chunk.response;
|
|
561
|
+
if (resp.length) {
|
|
562
|
+
yield { type: "text", delta: resp };
|
|
563
|
+
}
|
|
564
|
+
}
|
|
547
565
|
const choice = chunk.choices?.[0];
|
|
548
|
-
if (
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
566
|
+
if (choice) {
|
|
567
|
+
const d = choice.delta;
|
|
568
|
+
if (d) {
|
|
569
|
+
if (typeof d.reasoning_content === "string" && d.reasoning_content.length) {
|
|
570
|
+
yield { type: "reasoning", delta: d.reasoning_content };
|
|
571
|
+
}
|
|
572
|
+
if (typeof d.content === "string" && d.content.length) {
|
|
573
|
+
yield { type: "text", delta: d.content };
|
|
574
|
+
}
|
|
575
|
+
if (Array.isArray(d.tool_calls)) {
|
|
576
|
+
for (const tc of d.tool_calls) {
|
|
577
|
+
const idx = typeof tc.index === "number" ? tc.index : 0;
|
|
578
|
+
let buf = toolCalls.get(idx);
|
|
579
|
+
const incomingName = tc.function?.name ?? null;
|
|
580
|
+
const incomingId = tc.id ?? null;
|
|
581
|
+
if (!buf) {
|
|
582
|
+
buf = { id: incomingId ?? `tc_${idx}`, name: incomingName ?? "", args: "" };
|
|
583
|
+
toolCalls.set(idx, buf);
|
|
584
|
+
if (buf.name) {
|
|
585
|
+
yield { type: "tool_call_start", index: idx, id: buf.id, name: buf.name };
|
|
586
|
+
}
|
|
587
|
+
} else {
|
|
588
|
+
if (!buf.name && incomingName) {
|
|
589
|
+
buf.name = incomingName;
|
|
590
|
+
yield { type: "tool_call_start", index: idx, id: buf.id, name: buf.name };
|
|
591
|
+
}
|
|
592
|
+
if (buf.id.startsWith("tc_") && incomingId) buf.id = incomingId;
|
|
568
593
|
}
|
|
569
|
-
|
|
570
|
-
if (
|
|
571
|
-
buf.
|
|
572
|
-
yield { type: "
|
|
594
|
+
const argDelta = tc.function?.arguments;
|
|
595
|
+
if (typeof argDelta === "string" && argDelta.length) {
|
|
596
|
+
buf.args += argDelta;
|
|
597
|
+
yield { type: "tool_call_args", index: idx, argsDelta: argDelta };
|
|
573
598
|
}
|
|
574
|
-
if (buf.id.startsWith("tc_") && incomingId) buf.id = incomingId;
|
|
575
|
-
}
|
|
576
|
-
const argDelta = tc.function?.arguments;
|
|
577
|
-
if (typeof argDelta === "string" && argDelta.length) {
|
|
578
|
-
buf.args += argDelta;
|
|
579
|
-
yield { type: "tool_call_args", index: idx, argsDelta: argDelta };
|
|
580
599
|
}
|
|
581
600
|
}
|
|
582
601
|
}
|
|
602
|
+
if (choice.finish_reason) finishReason = choice.finish_reason;
|
|
583
603
|
}
|
|
584
|
-
if (choice.finish_reason) finishReason = choice.finish_reason;
|
|
585
604
|
}
|
|
586
605
|
for (const [idx, buf] of [...toolCalls.entries()].sort((a, b) => a[0] - b[0])) {
|
|
587
606
|
if (!buf.name) continue;
|
|
@@ -933,7 +952,10 @@ async function logTurnDebug(ctx) {
|
|
|
933
952
|
toolSavingsPct: toolTotalRaw > 0 ? Math.round((toolTotalRaw - toolTotalReduced) / toolTotalRaw * 100) : 0,
|
|
934
953
|
cacheDiagnostics,
|
|
935
954
|
compaction: ctx.compaction,
|
|
936
|
-
shadowStrip: ctx.shadowStrip
|
|
955
|
+
shadowStrip: ctx.shadowStrip,
|
|
956
|
+
durationMs: ctx.durationMs,
|
|
957
|
+
intentClassification: ctx.intentClassification,
|
|
958
|
+
codeMode: ctx.codeMode
|
|
937
959
|
});
|
|
938
960
|
}
|
|
939
961
|
var LOG_VERSION;
|
|
@@ -953,10 +975,129 @@ function safeJsonParse(text) {
|
|
|
953
975
|
return null;
|
|
954
976
|
}
|
|
955
977
|
}
|
|
956
|
-
|
|
978
|
+
function truncate(str, max) {
|
|
979
|
+
if (str.length <= max) return str;
|
|
980
|
+
return str.slice(0, max) + "\u2026";
|
|
981
|
+
}
|
|
982
|
+
async function callLlm(messages, llmOpts, maxTokens = 64) {
|
|
983
|
+
if (!llmOpts) return "";
|
|
984
|
+
const events = runKimi({
|
|
985
|
+
accountId: llmOpts.accountId,
|
|
986
|
+
apiToken: llmOpts.apiToken,
|
|
987
|
+
model: llmOpts.model,
|
|
988
|
+
messages,
|
|
989
|
+
temperature: 0.1,
|
|
990
|
+
maxCompletionTokens: maxTokens,
|
|
991
|
+
gateway: llmOpts.gateway,
|
|
992
|
+
signal: llmOpts.signal
|
|
993
|
+
});
|
|
994
|
+
let text = "";
|
|
995
|
+
for await (const ev of events) {
|
|
996
|
+
if (ev.type === "text") text += ev.delta;
|
|
997
|
+
}
|
|
998
|
+
return text.trim().replace(/^["']|["']$/g, "").replace(/\s+/g, " ").toLowerCase();
|
|
999
|
+
}
|
|
1000
|
+
async function synthesizeEditEvent(file, toolName, toolArgs, assistantMessage, llmOpts) {
|
|
1001
|
+
if (!llmOpts) return null;
|
|
1002
|
+
const oldString = typeof toolArgs.old_string === "string" ? toolArgs.old_string : "";
|
|
1003
|
+
const newString = typeof toolArgs.new_string === "string" ? toolArgs.new_string : "";
|
|
1004
|
+
const fullContent = typeof toolArgs.content === "string" ? toolArgs.content : "";
|
|
1005
|
+
const isWrite = toolName === "write";
|
|
1006
|
+
const before = isWrite ? "(new file)" : truncate(oldString, 600);
|
|
1007
|
+
const after = isWrite ? truncate(fullContent, 600) : truncate(newString, 600);
|
|
1008
|
+
const intent = assistantMessage ? assistantMessage.slice(-300).trim() : "";
|
|
1009
|
+
const changeContext = `File: ${file}
|
|
1010
|
+
Tool: ${toolName}
|
|
1011
|
+
|
|
1012
|
+
Before:
|
|
1013
|
+
${before}
|
|
1014
|
+
|
|
1015
|
+
After:
|
|
1016
|
+
${after}${intent ? `
|
|
1017
|
+
|
|
1018
|
+
Context: ${intent}` : ""}`;
|
|
1019
|
+
const summary1 = await callLlm(
|
|
1020
|
+
[
|
|
1021
|
+
{ role: "system", content: EDIT_SYNTHESIS_SYSTEM },
|
|
1022
|
+
{ role: "user", content: `${changeContext}
|
|
1023
|
+
|
|
1024
|
+
Summary:` }
|
|
1025
|
+
],
|
|
1026
|
+
llmOpts
|
|
1027
|
+
);
|
|
1028
|
+
if (summary1.length >= 10 && summary1.length <= 200) {
|
|
1029
|
+
const verdict = await callLlm(
|
|
1030
|
+
[
|
|
1031
|
+
{ role: "system", content: VERIFIER_SYSTEM },
|
|
1032
|
+
{
|
|
1033
|
+
role: "user",
|
|
1034
|
+
content: `${changeContext}
|
|
1035
|
+
|
|
1036
|
+
Proposed summary: "${summary1}"
|
|
1037
|
+
|
|
1038
|
+
Is this accurate?`
|
|
1039
|
+
}
|
|
1040
|
+
],
|
|
1041
|
+
llmOpts,
|
|
1042
|
+
8
|
|
1043
|
+
);
|
|
1044
|
+
if (verdict.startsWith("yes")) return summary1;
|
|
1045
|
+
}
|
|
1046
|
+
const retrySystem = `${EDIT_SYNTHESIS_SYSTEM}
|
|
1047
|
+
|
|
1048
|
+
CRITICAL: The previous summary was rejected. Be specific. Include concrete details from the After section.`;
|
|
1049
|
+
const summary2 = await callLlm(
|
|
1050
|
+
[
|
|
1051
|
+
{ role: "system", content: retrySystem },
|
|
1052
|
+
{ role: "user", content: `${changeContext}
|
|
1053
|
+
|
|
1054
|
+
Summary:` }
|
|
1055
|
+
],
|
|
1056
|
+
llmOpts
|
|
1057
|
+
);
|
|
1058
|
+
if (summary2.length >= 10 && summary2.length <= 200) {
|
|
1059
|
+
const verdict2 = await callLlm(
|
|
1060
|
+
[
|
|
1061
|
+
{ role: "system", content: VERIFIER_SYSTEM },
|
|
1062
|
+
{
|
|
1063
|
+
role: "user",
|
|
1064
|
+
content: `${changeContext}
|
|
1065
|
+
|
|
1066
|
+
Proposed summary: "${summary2}"
|
|
1067
|
+
|
|
1068
|
+
Is this accurate?`
|
|
1069
|
+
}
|
|
1070
|
+
],
|
|
1071
|
+
llmOpts,
|
|
1072
|
+
8
|
|
1073
|
+
);
|
|
1074
|
+
if (verdict2.startsWith("yes")) return summary2;
|
|
1075
|
+
}
|
|
1076
|
+
return null;
|
|
1077
|
+
}
|
|
1078
|
+
var EDIT_SYNTHESIS_SYSTEM, VERIFIER_SYSTEM, EXTRACTORS;
|
|
957
1079
|
var init_extractors = __esm({
|
|
958
1080
|
"src/memory/extractors.ts"() {
|
|
959
1081
|
"use strict";
|
|
1082
|
+
init_client();
|
|
1083
|
+
EDIT_SYNTHESIS_SYSTEM = `You summarize a SINGLE code edit. Write ONE concise sentence (max 20 words) describing exactly what changed.
|
|
1084
|
+
|
|
1085
|
+
Rules:
|
|
1086
|
+
- Use ONLY the Before/After diff below.
|
|
1087
|
+
- For new files: describe the file's content or purpose. Never say just "added a new file".
|
|
1088
|
+
- For edits: describe the specific code change.
|
|
1089
|
+
|
|
1090
|
+
Examples:
|
|
1091
|
+
- Created test-memory.md containing the text "Memory test".
|
|
1092
|
+
- Fixed race condition in loop.ts by adding AbortSignal guard.
|
|
1093
|
+
- Added vitest dependency and removed jest from package.json.
|
|
1094
|
+
|
|
1095
|
+
Respond with only the summary sentence. No quotes, no preamble.`;
|
|
1096
|
+
VERIFIER_SYSTEM = `You verify whether a summary accurately describes a code edit.
|
|
1097
|
+
Answer exactly "yes" if the summary correctly captures what changed in the file.
|
|
1098
|
+
Answer exactly "no" if the summary is vague, wrong, or misses the actual change.
|
|
1099
|
+
|
|
1100
|
+
Respond with only "yes" or "no".`;
|
|
960
1101
|
EXTRACTORS = [
|
|
961
1102
|
{
|
|
962
1103
|
id: "package_json",
|
|
@@ -1010,9 +1151,27 @@ var init_extractors = __esm({
|
|
|
1010
1151
|
{
|
|
1011
1152
|
id: "edit_event",
|
|
1012
1153
|
match: (tool, file) => (tool === "edit" || tool === "write") && !!file,
|
|
1013
|
-
extract: (_content, file) => {
|
|
1154
|
+
extract: async (_content, file, ctx) => {
|
|
1014
1155
|
if (!file) return null;
|
|
1015
1156
|
const safeKey = file.replace(/[^a-zA-Z0-9]/g, "_");
|
|
1157
|
+
if (ctx?.llmOpts && (ctx.toolArgs || ctx.assistantMessage)) {
|
|
1158
|
+
const summary = await synthesizeEditEvent(
|
|
1159
|
+
file,
|
|
1160
|
+
ctx.toolArgs?._toolName || "edit",
|
|
1161
|
+
ctx.toolArgs || {},
|
|
1162
|
+
ctx.assistantMessage,
|
|
1163
|
+
ctx.llmOpts
|
|
1164
|
+
);
|
|
1165
|
+
if (summary) {
|
|
1166
|
+
return {
|
|
1167
|
+
content: summary,
|
|
1168
|
+
category: "event",
|
|
1169
|
+
importance: 3,
|
|
1170
|
+
topicKey: `event_edit_${safeKey}`,
|
|
1171
|
+
relatedFiles: [file]
|
|
1172
|
+
};
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1016
1175
|
return {
|
|
1017
1176
|
content: `File modified: ${file}.`,
|
|
1018
1177
|
category: "event",
|
|
@@ -1356,6 +1515,7 @@ var init_code_mode = __esm({
|
|
|
1356
1515
|
|
|
1357
1516
|
// src/agent/loop.ts
|
|
1358
1517
|
async function runAgentTurn(opts2) {
|
|
1518
|
+
const turnStart = performance.now();
|
|
1359
1519
|
const max = opts2.maxToolIterations ?? 50;
|
|
1360
1520
|
const codeMode = opts2.codeMode ?? false;
|
|
1361
1521
|
let toolDefs;
|
|
@@ -1702,25 +1862,44 @@ ${sandboxResult.output}` : sandboxResult.output;
|
|
|
1702
1862
|
opts2.callbacks.onToolResult?.(result);
|
|
1703
1863
|
if (opts2.memoryManager) {
|
|
1704
1864
|
let filePath;
|
|
1865
|
+
let toolArgs = {};
|
|
1705
1866
|
try {
|
|
1706
|
-
|
|
1707
|
-
filePath =
|
|
1867
|
+
toolArgs = JSON.parse(tc.function.arguments || "{}");
|
|
1868
|
+
filePath = toolArgs.path;
|
|
1708
1869
|
} catch {
|
|
1709
1870
|
}
|
|
1871
|
+
const lastAssistant = [...opts2.messages].reverse().find(
|
|
1872
|
+
(m) => m.role === "assistant" && m.tool_calls && m.tool_calls.length > 0
|
|
1873
|
+
);
|
|
1874
|
+
const assistantMessage = lastAssistant?.content ?? "";
|
|
1875
|
+
const llmOpts = opts2.memoryManager.getExtractionLlmOpts();
|
|
1710
1876
|
for (const extractor of EXTRACTORS) {
|
|
1711
1877
|
if (extractor.match(tc.function.name, filePath)) {
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1878
|
+
void (async () => {
|
|
1879
|
+
try {
|
|
1880
|
+
const memory = await extractor.extract(result.content, filePath, {
|
|
1881
|
+
toolArgs: { ...toolArgs, _toolName: tc.function.name },
|
|
1882
|
+
assistantMessage: typeof assistantMessage === "string" ? assistantMessage : "",
|
|
1883
|
+
llmOpts: {
|
|
1884
|
+
...llmOpts,
|
|
1885
|
+
signal: opts2.signal
|
|
1886
|
+
}
|
|
1887
|
+
});
|
|
1888
|
+
if (memory) {
|
|
1889
|
+
await opts2.memoryManager.remember(
|
|
1890
|
+
memory.content,
|
|
1891
|
+
memory.category,
|
|
1892
|
+
memory.importance,
|
|
1893
|
+
opts2.cwd,
|
|
1894
|
+
opts2.sessionId ?? "unknown",
|
|
1895
|
+
opts2.signal,
|
|
1896
|
+
void 0,
|
|
1897
|
+
memory.topicKey
|
|
1898
|
+
);
|
|
1899
|
+
}
|
|
1900
|
+
} catch {
|
|
1901
|
+
}
|
|
1902
|
+
})();
|
|
1724
1903
|
}
|
|
1725
1904
|
}
|
|
1726
1905
|
}
|
|
@@ -1728,6 +1907,10 @@ ${sandboxResult.output}` : sandboxResult.output;
|
|
|
1728
1907
|
if (recentToolCalls.length > LOOP_WINDOW) recentToolCalls.shift();
|
|
1729
1908
|
}
|
|
1730
1909
|
}
|
|
1910
|
+
if (opts2.onIterationEnd) {
|
|
1911
|
+
opts2.messages = await opts2.onIterationEnd(opts2.messages, opts2.signal);
|
|
1912
|
+
if (opts2.signal.aborted) throw new DOMException("aborted", "AbortError");
|
|
1913
|
+
}
|
|
1731
1914
|
if (opts2.sessionId && lastUsage) {
|
|
1732
1915
|
void logTurnDebug({
|
|
1733
1916
|
sessionId: opts2.sessionId,
|
|
@@ -1736,7 +1919,10 @@ ${sandboxResult.output}` : sandboxResult.output;
|
|
|
1736
1919
|
previousMessages,
|
|
1737
1920
|
toolResults,
|
|
1738
1921
|
usage: lastUsage,
|
|
1739
|
-
shadowStrip: shadowStripMetrics
|
|
1922
|
+
shadowStrip: shadowStripMetrics,
|
|
1923
|
+
durationMs: Math.round(performance.now() - turnStart),
|
|
1924
|
+
intentClassification: opts2.intentClassification,
|
|
1925
|
+
codeMode: opts2.codeMode
|
|
1740
1926
|
});
|
|
1741
1927
|
}
|
|
1742
1928
|
if (budgetExhausted) {
|
|
@@ -3531,6 +3717,229 @@ var init_update_check = __esm({
|
|
|
3531
3717
|
}
|
|
3532
3718
|
});
|
|
3533
3719
|
|
|
3720
|
+
// src/remote/session-store.ts
|
|
3721
|
+
import { readFile as readFile8, writeFile as writeFile6, mkdir as mkdir6, readdir as readdir2 } from "fs/promises";
|
|
3722
|
+
import { homedir as homedir6 } from "os";
|
|
3723
|
+
import { join as join9 } from "path";
|
|
3724
|
+
function remoteDir() {
|
|
3725
|
+
const xdg = process.env.XDG_DATA_HOME || join9(homedir6(), ".config");
|
|
3726
|
+
return join9(xdg, "kimiflare", "remote");
|
|
3727
|
+
}
|
|
3728
|
+
async function saveRemoteSession(session) {
|
|
3729
|
+
const dir = remoteDir();
|
|
3730
|
+
await mkdir6(dir, { recursive: true });
|
|
3731
|
+
const path = join9(dir, `${session.sessionId}.json`);
|
|
3732
|
+
await writeFile6(path, JSON.stringify(session, null, 2) + "\n", "utf8");
|
|
3733
|
+
}
|
|
3734
|
+
async function loadRemoteSession(sessionId) {
|
|
3735
|
+
try {
|
|
3736
|
+
const path = join9(remoteDir(), `${sessionId}.json`);
|
|
3737
|
+
const raw = await readFile8(path, "utf8");
|
|
3738
|
+
return JSON.parse(raw);
|
|
3739
|
+
} catch {
|
|
3740
|
+
return null;
|
|
3741
|
+
}
|
|
3742
|
+
}
|
|
3743
|
+
async function listRemoteSessions() {
|
|
3744
|
+
const dir = remoteDir();
|
|
3745
|
+
try {
|
|
3746
|
+
const files = await readdir2(dir);
|
|
3747
|
+
const sessions = [];
|
|
3748
|
+
for (const file of files) {
|
|
3749
|
+
if (!file.endsWith(".json")) continue;
|
|
3750
|
+
try {
|
|
3751
|
+
const raw = await readFile8(join9(dir, file), "utf8");
|
|
3752
|
+
sessions.push(JSON.parse(raw));
|
|
3753
|
+
} catch {
|
|
3754
|
+
}
|
|
3755
|
+
}
|
|
3756
|
+
return sessions.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
|
|
3757
|
+
} catch {
|
|
3758
|
+
return [];
|
|
3759
|
+
}
|
|
3760
|
+
}
|
|
3761
|
+
async function getMostRecentRemoteSession() {
|
|
3762
|
+
const sessions = await listRemoteSessions();
|
|
3763
|
+
return sessions[0] ?? null;
|
|
3764
|
+
}
|
|
3765
|
+
var init_session_store = __esm({
|
|
3766
|
+
"src/remote/session-store.ts"() {
|
|
3767
|
+
"use strict";
|
|
3768
|
+
}
|
|
3769
|
+
});
|
|
3770
|
+
|
|
3771
|
+
// src/remote/deploy.ts
|
|
3772
|
+
import { execSync } from "child_process";
|
|
3773
|
+
import { join as join10, dirname as dirname5 } from "path";
|
|
3774
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
3775
|
+
import { randomBytes } from "crypto";
|
|
3776
|
+
function generateSecret() {
|
|
3777
|
+
return randomBytes(32).toString("hex");
|
|
3778
|
+
}
|
|
3779
|
+
function runCapture(cmd, cwd) {
|
|
3780
|
+
return execSync(cmd, { cwd, encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
3781
|
+
}
|
|
3782
|
+
async function* deployForTui() {
|
|
3783
|
+
yield { message: "Checking prerequisites..." };
|
|
3784
|
+
try {
|
|
3785
|
+
runCapture("wrangler --version");
|
|
3786
|
+
} catch {
|
|
3787
|
+
yield { message: "wrangler not found. Install: npm install -g wrangler", error: true };
|
|
3788
|
+
yield { message: "Then run: wrangler login", error: true };
|
|
3789
|
+
throw new Error("wrangler not installed");
|
|
3790
|
+
}
|
|
3791
|
+
yield { message: "wrangler OK" };
|
|
3792
|
+
try {
|
|
3793
|
+
runCapture("wrangler whoami");
|
|
3794
|
+
} catch {
|
|
3795
|
+
yield { message: "wrangler not authenticated. Run: wrangler login", error: true };
|
|
3796
|
+
throw new Error("wrangler not authenticated");
|
|
3797
|
+
}
|
|
3798
|
+
yield { message: "wrangler authenticated" };
|
|
3799
|
+
try {
|
|
3800
|
+
runCapture("docker --version");
|
|
3801
|
+
} catch {
|
|
3802
|
+
yield { message: "Docker not found. Install: https://docs.docker.com/get-docker/", error: true };
|
|
3803
|
+
throw new Error("docker not installed");
|
|
3804
|
+
}
|
|
3805
|
+
yield { message: "Docker OK" };
|
|
3806
|
+
yield { message: "Building remote agent bundle..." };
|
|
3807
|
+
try {
|
|
3808
|
+
runCapture("npm run build:remote-agent", join10(REMOTE_DIR, ".."));
|
|
3809
|
+
yield { message: "Agent bundle built" };
|
|
3810
|
+
} catch (err) {
|
|
3811
|
+
yield { message: `Build failed: ${err instanceof Error ? err.message : String(err)}`, error: true };
|
|
3812
|
+
throw err;
|
|
3813
|
+
}
|
|
3814
|
+
yield { message: "Deploying Worker to Cloudflare..." };
|
|
3815
|
+
try {
|
|
3816
|
+
runCapture("wrangler deploy", WORKER_DIR);
|
|
3817
|
+
yield { message: "Worker deployed" };
|
|
3818
|
+
} catch (err) {
|
|
3819
|
+
yield { message: `Deploy failed: ${err instanceof Error ? err.message : String(err)}`, error: true };
|
|
3820
|
+
throw err;
|
|
3821
|
+
}
|
|
3822
|
+
let workerUrl;
|
|
3823
|
+
try {
|
|
3824
|
+
const info = runCapture("wrangler info", WORKER_DIR);
|
|
3825
|
+
const match = info.match(/https:\/\/[^\s]+\.workers\.dev/);
|
|
3826
|
+
if (match) workerUrl = match[0];
|
|
3827
|
+
} catch {
|
|
3828
|
+
}
|
|
3829
|
+
if (!workerUrl) {
|
|
3830
|
+
yield { message: "Could not auto-detect Worker URL", error: true };
|
|
3831
|
+
throw new Error("Worker URL not found");
|
|
3832
|
+
}
|
|
3833
|
+
yield { message: `Worker URL: ${workerUrl}` };
|
|
3834
|
+
const authSecret = generateSecret();
|
|
3835
|
+
const cfg = await loadConfig();
|
|
3836
|
+
const cfToken = process.env.CF_API_TOKEN ?? cfg?.apiToken;
|
|
3837
|
+
if (!cfToken) {
|
|
3838
|
+
yield { message: "CF_API_TOKEN not found. Set CF_API_TOKEN env var or apiToken in config", error: true };
|
|
3839
|
+
throw new Error("CF_API_TOKEN missing");
|
|
3840
|
+
}
|
|
3841
|
+
yield { message: "Setting Worker secrets..." };
|
|
3842
|
+
try {
|
|
3843
|
+
execSync(`wrangler secret put REMOTE_AUTH_SECRET`, {
|
|
3844
|
+
cwd: WORKER_DIR,
|
|
3845
|
+
input: authSecret,
|
|
3846
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
3847
|
+
});
|
|
3848
|
+
execSync(`wrangler secret put CF_API_TOKEN`, {
|
|
3849
|
+
cwd: WORKER_DIR,
|
|
3850
|
+
input: cfToken,
|
|
3851
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
3852
|
+
});
|
|
3853
|
+
yield { message: "Secrets set" };
|
|
3854
|
+
} catch (err) {
|
|
3855
|
+
yield { message: `Secret setup failed: ${err instanceof Error ? err.message : String(err)}`, error: true };
|
|
3856
|
+
throw err;
|
|
3857
|
+
}
|
|
3858
|
+
const imageTag = "ghcr.io/sinameraji/kimiflare-remote-agent:latest";
|
|
3859
|
+
yield { message: "Building container image..." };
|
|
3860
|
+
try {
|
|
3861
|
+
runCapture(`docker build -t ${imageTag} .`, REMOTE_DIR);
|
|
3862
|
+
yield { message: "Image built" };
|
|
3863
|
+
} catch (err) {
|
|
3864
|
+
yield { message: `Image build failed: ${err instanceof Error ? err.message : String(err)}`, error: true };
|
|
3865
|
+
throw err;
|
|
3866
|
+
}
|
|
3867
|
+
yield { message: `Pushing ${imageTag}...` };
|
|
3868
|
+
try {
|
|
3869
|
+
runCapture(`docker push ${imageTag}`, REMOTE_DIR);
|
|
3870
|
+
yield { message: "Image pushed" };
|
|
3871
|
+
} catch (err) {
|
|
3872
|
+
yield { message: `Push failed: ${err instanceof Error ? err.message : String(err)}`, error: true };
|
|
3873
|
+
yield { message: "Make sure you're logged into ghcr.io: docker login ghcr.io -u USERNAME -p GITHUB_TOKEN", error: true };
|
|
3874
|
+
throw err;
|
|
3875
|
+
}
|
|
3876
|
+
const nextCfg = {
|
|
3877
|
+
...cfg ?? { accountId: "", apiToken: "", model: "@cf/moonshotai/kimi-k2.6" },
|
|
3878
|
+
remoteWorkerUrl: workerUrl,
|
|
3879
|
+
remoteAuthSecret: authSecret
|
|
3880
|
+
};
|
|
3881
|
+
await saveConfig(nextCfg);
|
|
3882
|
+
yield { message: "Config saved" };
|
|
3883
|
+
yield { message: "Remote infrastructure ready!", done: true };
|
|
3884
|
+
return { workerUrl, authSecret };
|
|
3885
|
+
}
|
|
3886
|
+
async function runDeploy() {
|
|
3887
|
+
console.log("kimiflare remote deploy\n");
|
|
3888
|
+
try {
|
|
3889
|
+
for await (const step of deployForTui()) {
|
|
3890
|
+
console.log(step.message);
|
|
3891
|
+
if (step.done) break;
|
|
3892
|
+
if (step.error) process.exit(1);
|
|
3893
|
+
}
|
|
3894
|
+
console.log("\nDeploy complete!");
|
|
3895
|
+
} catch (err) {
|
|
3896
|
+
console.error(`Deploy failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
3897
|
+
process.exit(1);
|
|
3898
|
+
}
|
|
3899
|
+
}
|
|
3900
|
+
async function checkDeployStatus() {
|
|
3901
|
+
let wrangler = false;
|
|
3902
|
+
let wranglerAuth = false;
|
|
3903
|
+
let docker = false;
|
|
3904
|
+
let workerUrl;
|
|
3905
|
+
try {
|
|
3906
|
+
execSync("wrangler --version", { stdio: "pipe" });
|
|
3907
|
+
wrangler = true;
|
|
3908
|
+
} catch {
|
|
3909
|
+
}
|
|
3910
|
+
if (wrangler) {
|
|
3911
|
+
try {
|
|
3912
|
+
execSync("wrangler whoami", { stdio: "pipe" });
|
|
3913
|
+
wranglerAuth = true;
|
|
3914
|
+
} catch {
|
|
3915
|
+
}
|
|
3916
|
+
}
|
|
3917
|
+
try {
|
|
3918
|
+
execSync("docker --version", { stdio: "pipe" });
|
|
3919
|
+
docker = true;
|
|
3920
|
+
} catch {
|
|
3921
|
+
}
|
|
3922
|
+
const cfg = await loadConfig();
|
|
3923
|
+
if (cfg?.remoteWorkerUrl) {
|
|
3924
|
+
try {
|
|
3925
|
+
const res = await fetch(`${cfg.remoteWorkerUrl}/health`, { signal: AbortSignal.timeout(5e3) });
|
|
3926
|
+
if (res.ok) workerUrl = cfg.remoteWorkerUrl;
|
|
3927
|
+
} catch {
|
|
3928
|
+
}
|
|
3929
|
+
}
|
|
3930
|
+
return { wrangler, wranglerAuth, docker, workerUrl };
|
|
3931
|
+
}
|
|
3932
|
+
var __dirname, REMOTE_DIR, WORKER_DIR;
|
|
3933
|
+
var init_deploy = __esm({
|
|
3934
|
+
"src/remote/deploy.ts"() {
|
|
3935
|
+
"use strict";
|
|
3936
|
+
init_config();
|
|
3937
|
+
__dirname = dirname5(fileURLToPath3(import.meta.url));
|
|
3938
|
+
REMOTE_DIR = join10(__dirname, "..", "..", "..", "remote");
|
|
3939
|
+
WORKER_DIR = join10(REMOTE_DIR, "worker");
|
|
3940
|
+
}
|
|
3941
|
+
});
|
|
3942
|
+
|
|
3534
3943
|
// src/cost-attribution/types.ts
|
|
3535
3944
|
var ALL_CATEGORIES;
|
|
3536
3945
|
var init_types = __esm({
|
|
@@ -3950,12 +4359,12 @@ var init_heuristic = __esm({
|
|
|
3950
4359
|
});
|
|
3951
4360
|
|
|
3952
4361
|
// src/cost-attribution/classify-from-session.ts
|
|
3953
|
-
import { readFile as
|
|
3954
|
-
import { join as
|
|
3955
|
-
import { homedir as
|
|
4362
|
+
import { readFile as readFile9 } from "fs/promises";
|
|
4363
|
+
import { join as join11 } from "path";
|
|
4364
|
+
import { homedir as homedir7 } from "os";
|
|
3956
4365
|
function sessionsDir() {
|
|
3957
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
3958
|
-
return
|
|
4366
|
+
const xdg = process.env.XDG_DATA_HOME || join11(homedir7(), ".local", "share");
|
|
4367
|
+
return join11(xdg, "kimiflare", "sessions");
|
|
3959
4368
|
}
|
|
3960
4369
|
function parseToolCalls(calls) {
|
|
3961
4370
|
return calls.map((c) => {
|
|
@@ -3969,7 +4378,7 @@ function parseToolCalls(calls) {
|
|
|
3969
4378
|
}
|
|
3970
4379
|
async function classifyFromSessionFile(sessionId) {
|
|
3971
4380
|
try {
|
|
3972
|
-
const raw = await
|
|
4381
|
+
const raw = await readFile9(join11(sessionsDir(), `${sessionId}.json`), "utf8");
|
|
3973
4382
|
const session = JSON.parse(raw);
|
|
3974
4383
|
const messages = session.messages ?? [];
|
|
3975
4384
|
const turns = [];
|
|
@@ -4002,15 +4411,15 @@ var cli_exports = {};
|
|
|
4002
4411
|
__export(cli_exports, {
|
|
4003
4412
|
runCostCommand: () => runCostCommand
|
|
4004
4413
|
});
|
|
4005
|
-
import { readFile as
|
|
4006
|
-
import { join as
|
|
4007
|
-
import { homedir as
|
|
4414
|
+
import { readFile as readFile10 } from "fs/promises";
|
|
4415
|
+
import { join as join12 } from "path";
|
|
4416
|
+
import { homedir as homedir8 } from "os";
|
|
4008
4417
|
function usageDir() {
|
|
4009
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
4010
|
-
return
|
|
4418
|
+
const xdg = process.env.XDG_DATA_HOME || join12(homedir8(), ".local", "share");
|
|
4419
|
+
return join12(xdg, "kimiflare");
|
|
4011
4420
|
}
|
|
4012
4421
|
function usagePath() {
|
|
4013
|
-
return
|
|
4422
|
+
return join12(usageDir(), "usage.json");
|
|
4014
4423
|
}
|
|
4015
4424
|
function today() {
|
|
4016
4425
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
@@ -4022,7 +4431,7 @@ function daysAgo(n) {
|
|
|
4022
4431
|
}
|
|
4023
4432
|
async function loadLog() {
|
|
4024
4433
|
try {
|
|
4025
|
-
const raw = await
|
|
4434
|
+
const raw = await readFile10(usagePath(), "utf8");
|
|
4026
4435
|
return JSON.parse(raw);
|
|
4027
4436
|
} catch {
|
|
4028
4437
|
return { version: 1, days: [], sessions: [] };
|
|
@@ -4108,6 +4517,94 @@ var init_cli = __esm({
|
|
|
4108
4517
|
}
|
|
4109
4518
|
});
|
|
4110
4519
|
|
|
4520
|
+
// src/remote/tui-auth.ts
|
|
4521
|
+
var tui_auth_exports = {};
|
|
4522
|
+
__export(tui_auth_exports, {
|
|
4523
|
+
authGitHubForTui: () => authGitHubForTui
|
|
4524
|
+
});
|
|
4525
|
+
function sleep2(ms) {
|
|
4526
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
4527
|
+
}
|
|
4528
|
+
async function* authGitHubForTui() {
|
|
4529
|
+
yield { message: "Starting GitHub OAuth device flow..." };
|
|
4530
|
+
const deviceRes = await fetch(GITHUB_DEVICE_AUTH_URL, {
|
|
4531
|
+
method: "POST",
|
|
4532
|
+
headers: {
|
|
4533
|
+
Accept: "application/json",
|
|
4534
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
4535
|
+
},
|
|
4536
|
+
body: new URLSearchParams({ client_id: CLIENT_ID, scope: "repo" })
|
|
4537
|
+
});
|
|
4538
|
+
if (!deviceRes.ok) {
|
|
4539
|
+
yield { message: `Failed to request device code: ${deviceRes.status}`, error: true };
|
|
4540
|
+
throw new Error("Device code request failed");
|
|
4541
|
+
}
|
|
4542
|
+
const deviceData = await deviceRes.json();
|
|
4543
|
+
yield {
|
|
4544
|
+
message: `Open ${deviceData.verification_uri} and enter code: ${deviceData.user_code}`,
|
|
4545
|
+
url: deviceData.verification_uri,
|
|
4546
|
+
code: deviceData.user_code
|
|
4547
|
+
};
|
|
4548
|
+
const startTime = Date.now();
|
|
4549
|
+
const expiresIn = deviceData.expires_in * 1e3;
|
|
4550
|
+
const interval = deviceData.interval * 1e3;
|
|
4551
|
+
while (Date.now() - startTime < expiresIn) {
|
|
4552
|
+
await sleep2(interval);
|
|
4553
|
+
const tokenRes = await fetch(GITHUB_ACCESS_TOKEN_URL, {
|
|
4554
|
+
method: "POST",
|
|
4555
|
+
headers: {
|
|
4556
|
+
Accept: "application/json",
|
|
4557
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
4558
|
+
},
|
|
4559
|
+
body: new URLSearchParams({
|
|
4560
|
+
client_id: CLIENT_ID,
|
|
4561
|
+
device_code: deviceData.device_code,
|
|
4562
|
+
grant_type: "urn:ietf:params:oauth:grant-type:device_code"
|
|
4563
|
+
})
|
|
4564
|
+
});
|
|
4565
|
+
if (!tokenRes.ok) continue;
|
|
4566
|
+
const tokenData = await tokenRes.json();
|
|
4567
|
+
if (tokenData.error === "authorization_pending") {
|
|
4568
|
+
continue;
|
|
4569
|
+
}
|
|
4570
|
+
if (tokenData.error === "slow_down") {
|
|
4571
|
+
await sleep2(interval * 2);
|
|
4572
|
+
continue;
|
|
4573
|
+
}
|
|
4574
|
+
if (tokenData.error) {
|
|
4575
|
+
yield { message: `OAuth error: ${tokenData.error}`, error: true };
|
|
4576
|
+
throw new Error(tokenData.error);
|
|
4577
|
+
}
|
|
4578
|
+
if (tokenData.access_token) {
|
|
4579
|
+
const cfg = await loadConfig() ?? {
|
|
4580
|
+
accountId: "",
|
|
4581
|
+
apiToken: "",
|
|
4582
|
+
model: "@cf/moonshotai/kimi-k2.6"
|
|
4583
|
+
};
|
|
4584
|
+
await saveConfig({
|
|
4585
|
+
...cfg,
|
|
4586
|
+
githubOAuthToken: tokenData.access_token,
|
|
4587
|
+
githubRefreshToken: tokenData.refresh_token,
|
|
4588
|
+
githubTokenExpiry: tokenData.expires_in ? Date.now() + tokenData.expires_in * 1e3 : void 0
|
|
4589
|
+
});
|
|
4590
|
+
yield { message: "GitHub authentication successful!", done: true };
|
|
4591
|
+
return;
|
|
4592
|
+
}
|
|
4593
|
+
}
|
|
4594
|
+
yield { message: "Device flow expired. Please try again.", error: true };
|
|
4595
|
+
throw new Error("Device flow expired");
|
|
4596
|
+
}
|
|
4597
|
+
var GITHUB_DEVICE_AUTH_URL, GITHUB_ACCESS_TOKEN_URL, CLIENT_ID;
|
|
4598
|
+
var init_tui_auth = __esm({
|
|
4599
|
+
"src/remote/tui-auth.ts"() {
|
|
4600
|
+
"use strict";
|
|
4601
|
+
init_config();
|
|
4602
|
+
GITHUB_DEVICE_AUTH_URL = "https://github.com/login/device/code";
|
|
4603
|
+
GITHUB_ACCESS_TOKEN_URL = "https://github.com/login/oauth/access_token";
|
|
4604
|
+
CLIENT_ID = process.env.KIMIFLARE_GITHUB_CLIENT_ID ?? "Ov23liM7lJX1xE2V1sVK";
|
|
4605
|
+
}
|
|
4606
|
+
});
|
|
4607
|
+
|
|
4111
4608
|
// src/agent/compact.ts
|
|
4112
4609
|
function indexOfNthUserFromEnd(messages, n) {
|
|
4113
4610
|
let seen = 0;
|
|
@@ -4929,12 +5426,12 @@ var init_connection = __esm({
|
|
|
4929
5426
|
});
|
|
4930
5427
|
|
|
4931
5428
|
// src/lsp/protocol.ts
|
|
4932
|
-
import { pathToFileURL, fileURLToPath as
|
|
5429
|
+
import { pathToFileURL, fileURLToPath as fileURLToPath4 } from "url";
|
|
4933
5430
|
function toUri(path) {
|
|
4934
5431
|
return pathToFileURL(path).href;
|
|
4935
5432
|
}
|
|
4936
5433
|
function fromUri(uri) {
|
|
4937
|
-
return
|
|
5434
|
+
return fileURLToPath4(uri);
|
|
4938
5435
|
}
|
|
4939
5436
|
function symbolKindName(kind) {
|
|
4940
5437
|
const names = {
|
|
@@ -7569,90 +8066,440 @@ var init_help_menu = __esm({
|
|
|
7569
8066
|
}
|
|
7570
8067
|
});
|
|
7571
8068
|
|
|
7572
|
-
// src/
|
|
7573
|
-
var
|
|
7574
|
-
__export(
|
|
7575
|
-
|
|
7576
|
-
|
|
7577
|
-
|
|
7578
|
-
|
|
7579
|
-
saveSession: () => saveSession
|
|
8069
|
+
// src/remote/worker-client.ts
|
|
8070
|
+
var worker_client_exports = {};
|
|
8071
|
+
__export(worker_client_exports, {
|
|
8072
|
+
cancelRemoteSession: () => cancelRemoteSession,
|
|
8073
|
+
getRemoteStatus: () => getRemoteStatus,
|
|
8074
|
+
startRemoteSession: () => startRemoteSession,
|
|
8075
|
+
streamRemoteProgress: () => streamRemoteProgress
|
|
7580
8076
|
});
|
|
7581
|
-
|
|
7582
|
-
|
|
7583
|
-
|
|
7584
|
-
|
|
7585
|
-
|
|
7586
|
-
|
|
7587
|
-
|
|
7588
|
-
|
|
7589
|
-
|
|
7590
|
-
}
|
|
7591
|
-
|
|
7592
|
-
|
|
7593
|
-
|
|
7594
|
-
|
|
7595
|
-
}
|
|
7596
|
-
|
|
7597
|
-
|
|
7598
|
-
|
|
7599
|
-
|
|
7600
|
-
|
|
7601
|
-
|
|
7602
|
-
|
|
7603
|
-
|
|
7604
|
-
|
|
7605
|
-
|
|
7606
|
-
|
|
8077
|
+
async function startRemoteSession(opts2) {
|
|
8078
|
+
const workerUrl = opts2.cfg.remoteWorkerUrl;
|
|
8079
|
+
if (!workerUrl) {
|
|
8080
|
+
throw new Error("Remote worker URL not configured. Set remoteWorkerUrl in config.");
|
|
8081
|
+
}
|
|
8082
|
+
const githubToken = opts2.cfg.githubOAuthToken;
|
|
8083
|
+
if (!githubToken) {
|
|
8084
|
+
throw new Error("GitHub token not found. Run `kimiflare auth github` first.");
|
|
8085
|
+
}
|
|
8086
|
+
const res = await fetch(`${workerUrl}/remote/start`, {
|
|
8087
|
+
method: "POST",
|
|
8088
|
+
headers: {
|
|
8089
|
+
"Content-Type": "application/json",
|
|
8090
|
+
Authorization: `Bearer ${opts2.cfg.remoteAuthSecret ?? ""}`
|
|
8091
|
+
},
|
|
8092
|
+
body: JSON.stringify({
|
|
8093
|
+
prompt: opts2.prompt,
|
|
8094
|
+
repo: opts2.repo,
|
|
8095
|
+
githubToken,
|
|
8096
|
+
accountId: opts2.cfg.accountId,
|
|
8097
|
+
apiToken: opts2.cfg.apiToken,
|
|
8098
|
+
model: opts2.cfg.model,
|
|
8099
|
+
reasoningEffort: opts2.cfg.reasoningEffort,
|
|
8100
|
+
ttlMinutes: opts2.ttlMinutes ?? opts2.cfg.remoteTtlMinutes,
|
|
8101
|
+
tokensBudget: opts2.tokensBudget ?? opts2.cfg.remoteMaxInputTokens
|
|
8102
|
+
})
|
|
8103
|
+
});
|
|
8104
|
+
if (!res.ok) {
|
|
8105
|
+
const text = await res.text();
|
|
8106
|
+
throw new Error(`Failed to start remote session: ${res.status} ${text}`);
|
|
8107
|
+
}
|
|
8108
|
+
const data = await res.json();
|
|
8109
|
+
await saveRemoteSession({
|
|
8110
|
+
sessionId: data.sessionId,
|
|
8111
|
+
prompt: opts2.prompt,
|
|
8112
|
+
repo: `${opts2.repo.owner}/${opts2.repo.name}`,
|
|
8113
|
+
workerUrl,
|
|
8114
|
+
status: "running",
|
|
8115
|
+
branch: `kimiflare/remote/${data.sessionId}`,
|
|
8116
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8117
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
8118
|
+
});
|
|
8119
|
+
return data;
|
|
7607
8120
|
}
|
|
7608
|
-
async function
|
|
7609
|
-
const
|
|
7610
|
-
|
|
7611
|
-
|
|
7612
|
-
entries = await readdir2(dir);
|
|
7613
|
-
} catch {
|
|
7614
|
-
return [];
|
|
8121
|
+
async function* streamRemoteProgress(workerUrl, sessionId, signal) {
|
|
8122
|
+
const res = await fetch(`${workerUrl}/remote/stream/${sessionId}`, { signal });
|
|
8123
|
+
if (!res.ok) {
|
|
8124
|
+
throw new Error(`Failed to connect to stream: ${res.status}`);
|
|
7615
8125
|
}
|
|
7616
|
-
|
|
7617
|
-
|
|
7618
|
-
|
|
7619
|
-
|
|
8126
|
+
if (!res.body) {
|
|
8127
|
+
throw new Error("No response body");
|
|
8128
|
+
}
|
|
8129
|
+
for await (const line of readSSE(res.body, signal)) {
|
|
7620
8130
|
try {
|
|
7621
|
-
|
|
7622
|
-
const parsed = JSON.parse(raw);
|
|
7623
|
-
const firstUser = parsed.messages.find((m) => m.role === "user");
|
|
7624
|
-
const firstPrompt = typeof firstUser?.content === "string" ? firstUser.content : firstUser?.content ? firstUser.content.find((p) => p.type === "text")?.text ?? "(no prompt)" : "(no prompt)";
|
|
7625
|
-
summaries.push({
|
|
7626
|
-
id: parsed.id,
|
|
7627
|
-
filePath: path,
|
|
7628
|
-
cwd: parsed.cwd,
|
|
7629
|
-
firstPrompt: firstPrompt.slice(0, 80),
|
|
7630
|
-
messageCount: parsed.messages.filter((m) => m.role !== "system").length,
|
|
7631
|
-
updatedAt: parsed.updatedAt ?? s.mtime.toISOString()
|
|
7632
|
-
});
|
|
8131
|
+
yield JSON.parse(line);
|
|
7633
8132
|
} catch {
|
|
7634
8133
|
}
|
|
7635
8134
|
}
|
|
7636
|
-
summaries.sort((a, b) => b.updatedAt < a.updatedAt ? -1 : 1);
|
|
7637
|
-
return summaries.slice(0, limit);
|
|
7638
8135
|
}
|
|
7639
|
-
async function
|
|
7640
|
-
const
|
|
7641
|
-
|
|
8136
|
+
async function getRemoteStatus(workerUrl, sessionId, authSecret) {
|
|
8137
|
+
const res = await fetch(`${workerUrl}/remote/status/${sessionId}`, {
|
|
8138
|
+
headers: authSecret ? { Authorization: `Bearer ${authSecret}` } : {}
|
|
8139
|
+
});
|
|
8140
|
+
if (!res.ok) {
|
|
8141
|
+
const text = await res.text();
|
|
8142
|
+
throw new Error(`Failed to get status: ${res.status} ${text}`);
|
|
8143
|
+
}
|
|
8144
|
+
return res.json();
|
|
7642
8145
|
}
|
|
7643
|
-
|
|
7644
|
-
|
|
8146
|
+
async function cancelRemoteSession(workerUrl, sessionId, authSecret) {
|
|
8147
|
+
const res = await fetch(`${workerUrl}/remote/cancel/${sessionId}`, {
|
|
8148
|
+
method: "POST",
|
|
8149
|
+
headers: authSecret ? { Authorization: `Bearer ${authSecret}` } : {}
|
|
8150
|
+
});
|
|
8151
|
+
if (!res.ok) {
|
|
8152
|
+
const text = await res.text();
|
|
8153
|
+
throw new Error(`Failed to cancel session: ${res.status} ${text}`);
|
|
8154
|
+
}
|
|
8155
|
+
}
|
|
8156
|
+
var init_worker_client = __esm({
|
|
8157
|
+
"src/remote/worker-client.ts"() {
|
|
7645
8158
|
"use strict";
|
|
7646
|
-
|
|
8159
|
+
init_session_store();
|
|
8160
|
+
init_sse();
|
|
7647
8161
|
}
|
|
7648
8162
|
});
|
|
7649
8163
|
|
|
7650
|
-
// src/
|
|
7651
|
-
|
|
7652
|
-
|
|
7653
|
-
|
|
7654
|
-
|
|
7655
|
-
|
|
8164
|
+
// src/remote/tui-deploy.ts
|
|
8165
|
+
var init_tui_deploy = __esm({
|
|
8166
|
+
"src/remote/tui-deploy.ts"() {
|
|
8167
|
+
"use strict";
|
|
8168
|
+
init_deploy();
|
|
8169
|
+
}
|
|
8170
|
+
});
|
|
8171
|
+
|
|
8172
|
+
// src/ui/remote-dashboard.tsx
|
|
8173
|
+
import { useEffect as useEffect4, useState as useState7 } from "react";
|
|
8174
|
+
import { Box as Box12, Text as Text13, useInput as useInput3 } from "ink";
|
|
8175
|
+
import SelectInput4 from "ink-select-input";
|
|
8176
|
+
import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
8177
|
+
function RemoteDashboard({ onSelect, onCancel }) {
|
|
8178
|
+
const theme = useTheme();
|
|
8179
|
+
const [sessions, setSessions] = useState7([]);
|
|
8180
|
+
const [loading, setLoading] = useState7(true);
|
|
8181
|
+
const [error, setError] = useState7(null);
|
|
8182
|
+
const [refreshing, setRefreshing] = useState7(false);
|
|
8183
|
+
useEffect4(() => {
|
|
8184
|
+
loadSessions();
|
|
8185
|
+
}, []);
|
|
8186
|
+
async function loadSessions() {
|
|
8187
|
+
try {
|
|
8188
|
+
setRefreshing(true);
|
|
8189
|
+
const list = await listRemoteSessions();
|
|
8190
|
+
const updated = await Promise.all(
|
|
8191
|
+
list.map(async (s) => {
|
|
8192
|
+
if (s.status === "running" || s.status === "pending") {
|
|
8193
|
+
try {
|
|
8194
|
+
const status = await getRemoteStatus(s.workerUrl, s.sessionId);
|
|
8195
|
+
return {
|
|
8196
|
+
...s,
|
|
8197
|
+
status: status.status,
|
|
8198
|
+
prUrl: status.prUrl ?? s.prUrl,
|
|
8199
|
+
tokensUsed: status.tokensUsed ?? s.tokensUsed,
|
|
8200
|
+
tokensBudget: status.tokensBudget ?? s.tokensBudget,
|
|
8201
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
8202
|
+
};
|
|
8203
|
+
} catch {
|
|
8204
|
+
return s;
|
|
8205
|
+
}
|
|
8206
|
+
}
|
|
8207
|
+
return s;
|
|
8208
|
+
})
|
|
8209
|
+
);
|
|
8210
|
+
setSessions(updated.sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime()));
|
|
8211
|
+
setError(null);
|
|
8212
|
+
} catch (err) {
|
|
8213
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
8214
|
+
} finally {
|
|
8215
|
+
setLoading(false);
|
|
8216
|
+
setRefreshing(false);
|
|
8217
|
+
}
|
|
8218
|
+
}
|
|
8219
|
+
useInput3((input, key) => {
|
|
8220
|
+
if (input === "r" || input === "R") {
|
|
8221
|
+
void loadSessions();
|
|
8222
|
+
}
|
|
8223
|
+
if (key.escape && onCancel) {
|
|
8224
|
+
onCancel();
|
|
8225
|
+
}
|
|
8226
|
+
});
|
|
8227
|
+
const items = sessions.map((s) => ({
|
|
8228
|
+
label: formatSessionLine(s),
|
|
8229
|
+
value: s.sessionId
|
|
8230
|
+
}));
|
|
8231
|
+
if (loading) {
|
|
8232
|
+
return /* @__PURE__ */ jsx14(Box12, { flexDirection: "column", padding: 1, children: /* @__PURE__ */ jsx14(Text13, { color: theme.accent, children: "Loading remote sessions..." }) });
|
|
8233
|
+
}
|
|
8234
|
+
if (error) {
|
|
8235
|
+
return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", padding: 1, children: [
|
|
8236
|
+
/* @__PURE__ */ jsxs12(Text13, { color: theme.error, children: [
|
|
8237
|
+
"Error: ",
|
|
8238
|
+
error
|
|
8239
|
+
] }),
|
|
8240
|
+
/* @__PURE__ */ jsx14(Text13, { dimColor: true, children: "Press R to retry, Esc to close" })
|
|
8241
|
+
] });
|
|
8242
|
+
}
|
|
8243
|
+
if (sessions.length === 0) {
|
|
8244
|
+
return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", padding: 1, children: [
|
|
8245
|
+
/* @__PURE__ */ jsx14(Text13, { color: theme.accent, children: "No remote sessions yet." }),
|
|
8246
|
+
/* @__PURE__ */ jsx14(Text13, { dimColor: true, children: "Type /remote <prompt> to start one." }),
|
|
8247
|
+
/* @__PURE__ */ jsx14(Text13, { dimColor: true, children: "Press Esc to close" })
|
|
8248
|
+
] });
|
|
8249
|
+
}
|
|
8250
|
+
return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", padding: 1, children: [
|
|
8251
|
+
/* @__PURE__ */ jsxs12(Text13, { bold: true, color: theme.accent, children: [
|
|
8252
|
+
"Recent remote tasks ",
|
|
8253
|
+
refreshing ? "(refreshing...)" : ""
|
|
8254
|
+
] }),
|
|
8255
|
+
/* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(
|
|
8256
|
+
SelectInput4,
|
|
8257
|
+
{
|
|
8258
|
+
items,
|
|
8259
|
+
onSelect: (item) => {
|
|
8260
|
+
const session = sessions.find((s) => s.sessionId === item.value);
|
|
8261
|
+
if (session) onSelect?.(session);
|
|
8262
|
+
}
|
|
8263
|
+
}
|
|
8264
|
+
) }),
|
|
8265
|
+
/* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(Text13, { dimColor: true, children: "\u2191\u2193 navigate \u2022 Enter select \u2022 R refresh \u2022 Esc close" }) })
|
|
8266
|
+
] });
|
|
8267
|
+
}
|
|
8268
|
+
function formatSessionLine(s) {
|
|
8269
|
+
const icon = s.status === "done" ? "\u2705" : s.status === "error" ? "\u274C" : s.status === "cancelled" ? "\u23F9\uFE0F" : s.status === "running" ? "\u23F3" : "\u23F8";
|
|
8270
|
+
const ago = formatAgo(new Date(s.updatedAt));
|
|
8271
|
+
const prompt = s.prompt.slice(0, 30) + (s.prompt.length > 30 ? "\u2026" : "");
|
|
8272
|
+
const outcome = s.prUrl ? `PR ${s.prUrl.split("/").pop()}` : s.status;
|
|
8273
|
+
const cost = s.tokensUsed && s.tokensBudget ? ` (${formatTokens2(s.tokensUsed)}/${formatTokens2(s.tokensBudget)})` : s.tokensUsed ? ` (${formatTokens2(s.tokensUsed)})` : "";
|
|
8274
|
+
return `${icon} ${prompt} \u2192 ${outcome} ${ago}${cost}`;
|
|
8275
|
+
}
|
|
8276
|
+
function formatAgo(date) {
|
|
8277
|
+
const ms = Date.now() - date.getTime();
|
|
8278
|
+
const minutes = Math.floor(ms / 6e4);
|
|
8279
|
+
const hours = Math.floor(minutes / 60);
|
|
8280
|
+
const days = Math.floor(hours / 24);
|
|
8281
|
+
if (days > 0) return `${days}d ago`;
|
|
8282
|
+
if (hours > 0) return `${hours}h ago`;
|
|
8283
|
+
if (minutes > 0) return `${minutes}m ago`;
|
|
8284
|
+
return "just now";
|
|
8285
|
+
}
|
|
8286
|
+
function formatTokens2(n) {
|
|
8287
|
+
if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
|
|
8288
|
+
if (n >= 1e3) return `${(n / 1e3).toFixed(1)}K`;
|
|
8289
|
+
return String(n);
|
|
8290
|
+
}
|
|
8291
|
+
function RemoteSessionDetail({
|
|
8292
|
+
session,
|
|
8293
|
+
onBack,
|
|
8294
|
+
onCancel
|
|
8295
|
+
}) {
|
|
8296
|
+
const theme = useTheme();
|
|
8297
|
+
const [cancelling, setCancelling] = useState7(false);
|
|
8298
|
+
useInput3((input, key) => {
|
|
8299
|
+
if (key.escape) {
|
|
8300
|
+
onBack();
|
|
8301
|
+
}
|
|
8302
|
+
if ((input === "c" || input === "C") && onCancel && (session.status === "running" || session.status === "pending")) {
|
|
8303
|
+
void handleCancel();
|
|
8304
|
+
}
|
|
8305
|
+
});
|
|
8306
|
+
async function handleCancel() {
|
|
8307
|
+
if (!onCancel) return;
|
|
8308
|
+
setCancelling(true);
|
|
8309
|
+
try {
|
|
8310
|
+
await cancelRemoteSession(session.workerUrl, session.sessionId);
|
|
8311
|
+
onCancel(session);
|
|
8312
|
+
} catch {
|
|
8313
|
+
} finally {
|
|
8314
|
+
setCancelling(false);
|
|
8315
|
+
}
|
|
8316
|
+
}
|
|
8317
|
+
const isRunning = session.status === "running" || session.status === "pending";
|
|
8318
|
+
return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", padding: 1, children: [
|
|
8319
|
+
/* @__PURE__ */ jsx14(Text13, { bold: true, color: theme.accent, children: "Remote Session" }),
|
|
8320
|
+
/* @__PURE__ */ jsxs12(Box12, { marginTop: 1, flexDirection: "column", children: [
|
|
8321
|
+
/* @__PURE__ */ jsxs12(Text13, { children: [
|
|
8322
|
+
"ID: ",
|
|
8323
|
+
session.sessionId
|
|
8324
|
+
] }),
|
|
8325
|
+
/* @__PURE__ */ jsxs12(Text13, { children: [
|
|
8326
|
+
"Repo: ",
|
|
8327
|
+
session.repo
|
|
8328
|
+
] }),
|
|
8329
|
+
/* @__PURE__ */ jsxs12(Text13, { children: [
|
|
8330
|
+
"Status: ",
|
|
8331
|
+
session.status
|
|
8332
|
+
] }),
|
|
8333
|
+
/* @__PURE__ */ jsxs12(Text13, { children: [
|
|
8334
|
+
"Prompt: ",
|
|
8335
|
+
session.prompt
|
|
8336
|
+
] }),
|
|
8337
|
+
session.prUrl && /* @__PURE__ */ jsxs12(Text13, { children: [
|
|
8338
|
+
"PR: ",
|
|
8339
|
+
session.prUrl
|
|
8340
|
+
] }),
|
|
8341
|
+
session.errorMessage && /* @__PURE__ */ jsxs12(Text13, { color: theme.error, children: [
|
|
8342
|
+
"Error: ",
|
|
8343
|
+
session.errorMessage
|
|
8344
|
+
] }),
|
|
8345
|
+
session.tokensUsed !== void 0 && /* @__PURE__ */ jsxs12(Text13, { children: [
|
|
8346
|
+
"Tokens: ",
|
|
8347
|
+
formatTokens2(session.tokensUsed),
|
|
8348
|
+
session.tokensBudget ? ` / ${formatTokens2(session.tokensBudget)}` : ""
|
|
8349
|
+
] }),
|
|
8350
|
+
/* @__PURE__ */ jsxs12(Text13, { children: [
|
|
8351
|
+
"Created: ",
|
|
8352
|
+
new Date(session.createdAt).toLocaleString()
|
|
8353
|
+
] }),
|
|
8354
|
+
session.finishedAt && /* @__PURE__ */ jsxs12(Text13, { children: [
|
|
8355
|
+
"Finished: ",
|
|
8356
|
+
new Date(session.finishedAt).toLocaleString()
|
|
8357
|
+
] })
|
|
8358
|
+
] }),
|
|
8359
|
+
/* @__PURE__ */ jsxs12(Box12, { marginTop: 1, flexDirection: "row", gap: 2, children: [
|
|
8360
|
+
isRunning && onCancel && /* @__PURE__ */ jsx14(Text13, { color: theme.error, children: cancelling ? "Cancelling..." : "[C] Cancel session" }),
|
|
8361
|
+
/* @__PURE__ */ jsx14(Text13, { dimColor: true, children: "Esc back" })
|
|
8362
|
+
] })
|
|
8363
|
+
] });
|
|
8364
|
+
}
|
|
8365
|
+
var init_remote_dashboard = __esm({
|
|
8366
|
+
"src/ui/remote-dashboard.tsx"() {
|
|
8367
|
+
"use strict";
|
|
8368
|
+
init_theme_context();
|
|
8369
|
+
init_session_store();
|
|
8370
|
+
init_worker_client();
|
|
8371
|
+
}
|
|
8372
|
+
});
|
|
8373
|
+
|
|
8374
|
+
// src/intent/classify.ts
|
|
8375
|
+
function classifyIntent(prompt) {
|
|
8376
|
+
let intentScore = 0;
|
|
8377
|
+
let matchedIntent = "other";
|
|
8378
|
+
for (const [intent, pattern] of Object.entries(INTENT_PATTERNS)) {
|
|
8379
|
+
const matches = (prompt.match(pattern) || []).length;
|
|
8380
|
+
if (matches > intentScore) {
|
|
8381
|
+
intentScore = matches;
|
|
8382
|
+
matchedIntent = intent;
|
|
8383
|
+
}
|
|
8384
|
+
}
|
|
8385
|
+
const hasFileMentions = (prompt.match(/@\w+|\b[\w/-]+\.(ts|tsx|js|jsx|py|go|rs)\b/g) || []).length;
|
|
8386
|
+
const hasMutatingVerb = /\b(add|create|write|edit|delete|remove|rename|migrate|implement)\b/i.test(prompt);
|
|
8387
|
+
const isQuestion = prompt.trim().endsWith("?") || /\b(what|how|why|is|does|can)\b/i.test(prompt.split(" ")[0] || "");
|
|
8388
|
+
const rawScore = Math.min(
|
|
8389
|
+
1,
|
|
8390
|
+
intentScore * 0.25 + (hasFileMentions > 2 ? 0.3 : hasFileMentions * 0.1) + (hasMutatingVerb ? 0.25 : 0) + (isQuestion ? 0 : 0.1)
|
|
8391
|
+
);
|
|
8392
|
+
const tier = rawScore < 0.3 ? "light" : rawScore < 0.65 ? "medium" : "heavy";
|
|
8393
|
+
return {
|
|
8394
|
+
intent: matchedIntent,
|
|
8395
|
+
rawScore,
|
|
8396
|
+
tier,
|
|
8397
|
+
confidence: 0.5 + (intentScore > 0 ? 0.3 : 0) + (hasFileMentions > 0 ? 0.1 : 0)
|
|
8398
|
+
};
|
|
8399
|
+
}
|
|
8400
|
+
var INTENT_PATTERNS;
|
|
8401
|
+
var init_classify = __esm({
|
|
8402
|
+
"src/intent/classify.ts"() {
|
|
8403
|
+
"use strict";
|
|
8404
|
+
INTENT_PATTERNS = {
|
|
8405
|
+
qa: /\b(what|how|why|explain|describe|what's|what is)\b/i,
|
|
8406
|
+
diagnose: /\b(broken|failing|error|bug|crash|why.*fail|not working)\b/i,
|
|
8407
|
+
verify: /\b(correct|right|verify|review|check|is this|does this)\b/i,
|
|
8408
|
+
polish: /\b(rename|refactor|extract|move|clean|lint|format)\b/i,
|
|
8409
|
+
small_edit: /\b(add|change|update|fix|remove|delete)\b.+\b(line|here|this|variable|function)\b/i,
|
|
8410
|
+
feature_bounded: /\b(add|implement|create|support)\b.+\b(flag|option|param|arg|field)\b/i,
|
|
8411
|
+
feature_exploratory: /\b(add|implement|migrate|integrate|build)\b.+\b(module|system|auth|oauth|framework|service)\b/i,
|
|
8412
|
+
explore: /\b(how.*work|architecture|structure|where.*used|find.*all|understand)\b/i,
|
|
8413
|
+
meta: /\b(plan|design|strategy|ontology|roadmap|approach)\b/i
|
|
8414
|
+
};
|
|
8415
|
+
}
|
|
8416
|
+
});
|
|
8417
|
+
|
|
8418
|
+
// src/sessions.ts
|
|
8419
|
+
var sessions_exports = {};
|
|
8420
|
+
__export(sessions_exports, {
|
|
8421
|
+
listSessions: () => listSessions,
|
|
8422
|
+
loadSession: () => loadSession,
|
|
8423
|
+
makeSessionId: () => makeSessionId,
|
|
8424
|
+
pruneSessions: () => pruneSessions,
|
|
8425
|
+
saveSession: () => saveSession
|
|
8426
|
+
});
|
|
8427
|
+
import { readFile as readFile11, writeFile as writeFile7, mkdir as mkdir7, readdir as readdir3, stat as stat4 } from "fs/promises";
|
|
8428
|
+
import { homedir as homedir9 } from "os";
|
|
8429
|
+
import { join as join13 } from "path";
|
|
8430
|
+
function sessionsDir2() {
|
|
8431
|
+
const xdg = process.env.XDG_DATA_HOME || join13(homedir9(), ".local", "share");
|
|
8432
|
+
return join13(xdg, "kimiflare", "sessions");
|
|
8433
|
+
}
|
|
8434
|
+
function sanitize(text) {
|
|
8435
|
+
return text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40);
|
|
8436
|
+
}
|
|
8437
|
+
function makeSessionId(firstPrompt) {
|
|
8438
|
+
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
8439
|
+
const slug = sanitize(firstPrompt) || "session";
|
|
8440
|
+
return `${ts}_${slug}`;
|
|
8441
|
+
}
|
|
8442
|
+
async function saveSession(file) {
|
|
8443
|
+
const dir = sessionsDir2();
|
|
8444
|
+
await mkdir7(dir, { recursive: true });
|
|
8445
|
+
const path = join13(dir, `${file.id}.json`);
|
|
8446
|
+
await writeFile7(path, JSON.stringify(file, null, 2), "utf8");
|
|
8447
|
+
return path;
|
|
8448
|
+
}
|
|
8449
|
+
async function pruneSessions() {
|
|
8450
|
+
const dir = sessionsDir2();
|
|
8451
|
+
const files = await listFilesByMtime(dir, /\.json$/);
|
|
8452
|
+
return pruneFiles(files, RETENTION.sessionMaxAgeDays, RETENTION.sessionMaxCount);
|
|
8453
|
+
}
|
|
8454
|
+
async function listSessions(limit = 30, cwd) {
|
|
8455
|
+
const dir = sessionsDir2();
|
|
8456
|
+
let entries;
|
|
8457
|
+
try {
|
|
8458
|
+
entries = await readdir3(dir);
|
|
8459
|
+
} catch {
|
|
8460
|
+
return [];
|
|
8461
|
+
}
|
|
8462
|
+
const summaries = [];
|
|
8463
|
+
for (const name of entries) {
|
|
8464
|
+
if (!name.endsWith(".json")) continue;
|
|
8465
|
+
const path = join13(dir, name);
|
|
8466
|
+
try {
|
|
8467
|
+
const [s, raw] = await Promise.all([stat4(path), readFile11(path, "utf8")]);
|
|
8468
|
+
const parsed = JSON.parse(raw);
|
|
8469
|
+
if (cwd && parsed.cwd !== cwd) continue;
|
|
8470
|
+
const firstUser = parsed.messages.find((m) => m.role === "user");
|
|
8471
|
+
const firstPrompt = typeof firstUser?.content === "string" ? firstUser.content : firstUser?.content ? firstUser.content.find((p) => p.type === "text")?.text ?? "(no prompt)" : "(no prompt)";
|
|
8472
|
+
summaries.push({
|
|
8473
|
+
id: parsed.id,
|
|
8474
|
+
filePath: path,
|
|
8475
|
+
cwd: parsed.cwd,
|
|
8476
|
+
firstPrompt: firstPrompt.slice(0, 80),
|
|
8477
|
+
messageCount: parsed.messages.filter((m) => m.role !== "system").length,
|
|
8478
|
+
updatedAt: parsed.updatedAt ?? s.mtime.toISOString()
|
|
8479
|
+
});
|
|
8480
|
+
} catch {
|
|
8481
|
+
}
|
|
8482
|
+
}
|
|
8483
|
+
summaries.sort((a, b) => b.updatedAt < a.updatedAt ? -1 : 1);
|
|
8484
|
+
return summaries.slice(0, limit);
|
|
8485
|
+
}
|
|
8486
|
+
async function loadSession(filePath) {
|
|
8487
|
+
const raw = await readFile11(filePath, "utf8");
|
|
8488
|
+
return JSON.parse(raw);
|
|
8489
|
+
}
|
|
8490
|
+
var init_sessions = __esm({
|
|
8491
|
+
"src/sessions.ts"() {
|
|
8492
|
+
"use strict";
|
|
8493
|
+
init_storage_limits();
|
|
8494
|
+
}
|
|
8495
|
+
});
|
|
8496
|
+
|
|
8497
|
+
// src/util/image.ts
|
|
8498
|
+
import { readFile as readFile12 } from "fs/promises";
|
|
8499
|
+
import { basename as basename3 } from "path";
|
|
8500
|
+
async function encodeImageFile(filePath) {
|
|
8501
|
+
const buf = await readFile12(filePath);
|
|
8502
|
+
if (buf.byteLength > MAX_IMAGE_BYTES) {
|
|
7656
8503
|
throw new Error(
|
|
7657
8504
|
`image too large (${(buf.byteLength / 1024 / 1024).toFixed(1)} MB); max is ${MAX_IMAGE_BYTES / 1024 / 1024} MB`
|
|
7658
8505
|
);
|
|
@@ -7687,15 +8534,15 @@ var init_image = __esm({
|
|
|
7687
8534
|
});
|
|
7688
8535
|
|
|
7689
8536
|
// src/usage-tracker.ts
|
|
7690
|
-
import { readFile as
|
|
7691
|
-
import { homedir as
|
|
7692
|
-
import { join as
|
|
8537
|
+
import { readFile as readFile13, writeFile as writeFile8, mkdir as mkdir8 } from "fs/promises";
|
|
8538
|
+
import { homedir as homedir10 } from "os";
|
|
8539
|
+
import { join as join14 } from "path";
|
|
7693
8540
|
function usageDir2() {
|
|
7694
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
7695
|
-
return
|
|
8541
|
+
const xdg = process.env.XDG_DATA_HOME || join14(homedir10(), ".local", "share");
|
|
8542
|
+
return join14(xdg, "kimiflare");
|
|
7696
8543
|
}
|
|
7697
8544
|
function usagePath2() {
|
|
7698
|
-
return
|
|
8545
|
+
return join14(usageDir2(), "usage.json");
|
|
7699
8546
|
}
|
|
7700
8547
|
function today2() {
|
|
7701
8548
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
@@ -7706,7 +8553,7 @@ function cutoffDate(daysBack) {
|
|
|
7706
8553
|
}
|
|
7707
8554
|
async function loadLog2() {
|
|
7708
8555
|
try {
|
|
7709
|
-
const raw = await
|
|
8556
|
+
const raw = await readFile13(usagePath2(), "utf8");
|
|
7710
8557
|
const parsed = JSON.parse(raw);
|
|
7711
8558
|
if (parsed.version === LOG_VERSION2) return parsed;
|
|
7712
8559
|
} catch {
|
|
@@ -7714,8 +8561,8 @@ async function loadLog2() {
|
|
|
7714
8561
|
return { version: LOG_VERSION2, days: [], sessions: [] };
|
|
7715
8562
|
}
|
|
7716
8563
|
async function saveLog(log) {
|
|
7717
|
-
await
|
|
7718
|
-
await
|
|
8564
|
+
await mkdir8(usageDir2(), { recursive: true });
|
|
8565
|
+
await writeFile8(usagePath2(), JSON.stringify(log, null, 2), "utf8");
|
|
7719
8566
|
}
|
|
7720
8567
|
function getOrCreateDay(log, date) {
|
|
7721
8568
|
let day = log.days.find((d) => d.date === date);
|
|
@@ -7921,7 +8768,7 @@ __export(db_exports, {
|
|
|
7921
8768
|
updateMemoryEmbedding: () => updateMemoryEmbedding
|
|
7922
8769
|
});
|
|
7923
8770
|
import Database from "better-sqlite3";
|
|
7924
|
-
import { dirname as
|
|
8771
|
+
import { dirname as dirname6 } from "path";
|
|
7925
8772
|
import { mkdirSync, statSync as statSync2 } from "fs";
|
|
7926
8773
|
function initSchema(db) {
|
|
7927
8774
|
db.exec(`
|
|
@@ -8006,7 +8853,7 @@ function openMemoryDb(dbPath) {
|
|
|
8006
8853
|
if (dbInstance) {
|
|
8007
8854
|
dbInstance.close();
|
|
8008
8855
|
}
|
|
8009
|
-
mkdirSync(
|
|
8856
|
+
mkdirSync(dirname6(dbPath), { recursive: true });
|
|
8010
8857
|
dbInstance = new Database(dbPath);
|
|
8011
8858
|
dbInstance.pragma("journal_mode = WAL");
|
|
8012
8859
|
dbInstance.pragma("foreign_keys = ON");
|
|
@@ -8300,7 +9147,7 @@ function truncateForEmbedding(text) {
|
|
|
8300
9147
|
if (text.length <= MAX_EMBED_CHARS) return text;
|
|
8301
9148
|
return text.slice(0, MAX_EMBED_CHARS);
|
|
8302
9149
|
}
|
|
8303
|
-
async function
|
|
9150
|
+
async function sleep3(ms) {
|
|
8304
9151
|
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
8305
9152
|
}
|
|
8306
9153
|
async function fetchWithRetry(url, init, retries = 3) {
|
|
@@ -8311,7 +9158,7 @@ async function fetchWithRetry(url, init, retries = 3) {
|
|
|
8311
9158
|
if (res.ok) return res;
|
|
8312
9159
|
if (res.status === 429 || res.status >= 500) {
|
|
8313
9160
|
const delay = 1e3 * 2 ** i;
|
|
8314
|
-
await
|
|
9161
|
+
await sleep3(delay);
|
|
8315
9162
|
continue;
|
|
8316
9163
|
}
|
|
8317
9164
|
const errText = await res.text().catch(() => "unknown error");
|
|
@@ -8319,7 +9166,7 @@ async function fetchWithRetry(url, init, retries = 3) {
|
|
|
8319
9166
|
} catch (e) {
|
|
8320
9167
|
lastError = e;
|
|
8321
9168
|
if (i < retries - 1) {
|
|
8322
|
-
await
|
|
9169
|
+
await sleep3(1e3 * 2 ** i);
|
|
8323
9170
|
}
|
|
8324
9171
|
}
|
|
8325
9172
|
}
|
|
@@ -8711,6 +9558,18 @@ Return a JSON array of strings. Example:
|
|
|
8711
9558
|
gateway: this.opts.gateway
|
|
8712
9559
|
};
|
|
8713
9560
|
}
|
|
9561
|
+
get extractionLlmOpts() {
|
|
9562
|
+
return {
|
|
9563
|
+
accountId: this.opts.accountId,
|
|
9564
|
+
apiToken: this.opts.apiToken,
|
|
9565
|
+
model: this.opts.extractionModel ?? "@cf/meta/llama-3.2-3b-instruct",
|
|
9566
|
+
gateway: this.opts.gateway
|
|
9567
|
+
};
|
|
9568
|
+
}
|
|
9569
|
+
/** Expose extraction LLM opts so the agent loop can pass them to extractors. */
|
|
9570
|
+
getExtractionLlmOpts() {
|
|
9571
|
+
return this.extractionLlmOpts;
|
|
9572
|
+
}
|
|
8714
9573
|
shouldRedact() {
|
|
8715
9574
|
return this.opts.redactSecrets !== false;
|
|
8716
9575
|
}
|
|
@@ -8718,7 +9577,7 @@ Return a JSON array of strings. Example:
|
|
|
8718
9577
|
* Store a memory with verification, topic-key normalization, hypothetical queries,
|
|
8719
9578
|
* secret redaction, and supersession.
|
|
8720
9579
|
*/
|
|
8721
|
-
async remember(content, category, importance, repoPath, sessionId, signal, agentRole) {
|
|
9580
|
+
async remember(content, category, importance, repoPath, sessionId, signal, agentRole, topicKey) {
|
|
8722
9581
|
if (!this.db) throw new Error("Memory DB not open");
|
|
8723
9582
|
let safeContent = this.shouldRedact() ? redactSecrets(content) : content;
|
|
8724
9583
|
if (!safeContent.trim()) {
|
|
@@ -8731,10 +9590,10 @@ Return a JSON array of strings. Example:
|
|
|
8731
9590
|
if (verified.corrected_content) {
|
|
8732
9591
|
safeContent = verified.corrected_content;
|
|
8733
9592
|
}
|
|
8734
|
-
const
|
|
9593
|
+
const resolvedTopicKey = topicKey?.trim() || this.normalizeTopicKey(safeContent, repoPath);
|
|
8735
9594
|
const supersededIds = [];
|
|
8736
|
-
if (
|
|
8737
|
-
const existing = findMemoriesByTopicKey(this.db, repoPath,
|
|
9595
|
+
if (resolvedTopicKey) {
|
|
9596
|
+
const existing = findMemoriesByTopicKey(this.db, repoPath, resolvedTopicKey);
|
|
8738
9597
|
for (const old of existing) {
|
|
8739
9598
|
supersedeMemory(this.db, old.id, "pending");
|
|
8740
9599
|
supersededIds.push(old.id);
|
|
@@ -8755,7 +9614,7 @@ Return a JSON array of strings. Example:
|
|
|
8755
9614
|
sourceSessionId: sessionId,
|
|
8756
9615
|
repoPath,
|
|
8757
9616
|
importance: Math.max(1, Math.min(5, importance)),
|
|
8758
|
-
topicKey:
|
|
9617
|
+
topicKey: resolvedTopicKey ?? void 0,
|
|
8759
9618
|
agentRole
|
|
8760
9619
|
};
|
|
8761
9620
|
const memory = insertMemory(this.db, input, embeddings[0]);
|
|
@@ -8933,16 +9792,16 @@ Context: This memory was explicitly provided by the user during a conversation.`
|
|
|
8933
9792
|
});
|
|
8934
9793
|
|
|
8935
9794
|
// src/util/state.ts
|
|
8936
|
-
import { readFile as
|
|
8937
|
-
import { homedir as
|
|
8938
|
-
import { join as
|
|
9795
|
+
import { readFile as readFile14, writeFile as writeFile9, mkdir as mkdir9 } from "fs/promises";
|
|
9796
|
+
import { homedir as homedir11 } from "os";
|
|
9797
|
+
import { join as join16 } from "path";
|
|
8939
9798
|
function statePath() {
|
|
8940
|
-
const xdg = process.env.XDG_CONFIG_HOME ||
|
|
8941
|
-
return
|
|
9799
|
+
const xdg = process.env.XDG_CONFIG_HOME || join16(homedir11(), ".config");
|
|
9800
|
+
return join16(xdg, "kimiflare", "state.json");
|
|
8942
9801
|
}
|
|
8943
9802
|
async function readState() {
|
|
8944
9803
|
try {
|
|
8945
|
-
const raw = await
|
|
9804
|
+
const raw = await readFile14(statePath(), "utf8");
|
|
8946
9805
|
return JSON.parse(raw);
|
|
8947
9806
|
} catch {
|
|
8948
9807
|
return {};
|
|
@@ -8950,8 +9809,8 @@ async function readState() {
|
|
|
8950
9809
|
}
|
|
8951
9810
|
async function writeState(state) {
|
|
8952
9811
|
const path = statePath();
|
|
8953
|
-
await
|
|
8954
|
-
await
|
|
9812
|
+
await mkdir9(join16(path, ".."), { recursive: true });
|
|
9813
|
+
await writeFile9(path, JSON.stringify(state, null, 2) + "\n", "utf8");
|
|
8955
9814
|
}
|
|
8956
9815
|
async function markCreatorMessageSeen(version) {
|
|
8957
9816
|
const state = await readState();
|
|
@@ -9024,15 +9883,15 @@ var init_frontmatter = __esm({
|
|
|
9024
9883
|
|
|
9025
9884
|
// src/commands/loader.ts
|
|
9026
9885
|
import { open, realpath } from "fs/promises";
|
|
9027
|
-
import { homedir as
|
|
9028
|
-
import { join as
|
|
9886
|
+
import { homedir as homedir12 } from "os";
|
|
9887
|
+
import { join as join17, relative as relative4, sep as sep2 } from "path";
|
|
9029
9888
|
import fg3 from "fast-glob";
|
|
9030
9889
|
function projectCommandsDir(cwd = process.cwd()) {
|
|
9031
|
-
return
|
|
9890
|
+
return join17(cwd, ".kimiflare", "commands");
|
|
9032
9891
|
}
|
|
9033
9892
|
function globalCommandsDir() {
|
|
9034
|
-
const xdg = process.env.XDG_CONFIG_HOME ||
|
|
9035
|
-
return
|
|
9893
|
+
const xdg = process.env.XDG_CONFIG_HOME || join17(homedir12(), ".config");
|
|
9894
|
+
return join17(xdg, "kimiflare", "commands");
|
|
9036
9895
|
}
|
|
9037
9896
|
async function loadCustomCommands(cwd = process.cwd()) {
|
|
9038
9897
|
const warnings = [];
|
|
@@ -9394,6 +10253,7 @@ var init_builtins = __esm({
|
|
|
9394
10253
|
{ name: "compact", description: "Summarize old turns to free context", source: "builtin" },
|
|
9395
10254
|
{ name: "clear", description: "Clear current conversation", source: "builtin" },
|
|
9396
10255
|
{ name: "init", description: "Scan repo and write KIMI.md", source: "builtin" },
|
|
10256
|
+
{ name: "remote", argHint: "<prompt>", description: "Run a remote session on Cloudflare", source: "builtin" },
|
|
9397
10257
|
{ name: "update", description: "Check for updates", source: "builtin" },
|
|
9398
10258
|
{ name: "hello", description: "Send a voice note to the creator", source: "builtin" },
|
|
9399
10259
|
{ name: "logout", description: "Clear stored credentials", source: "builtin" },
|
|
@@ -9407,8 +10267,8 @@ var init_builtins = __esm({
|
|
|
9407
10267
|
});
|
|
9408
10268
|
|
|
9409
10269
|
// src/commands/save.ts
|
|
9410
|
-
import { mkdir as
|
|
9411
|
-
import { dirname as
|
|
10270
|
+
import { mkdir as mkdir10, writeFile as writeFile10, unlink as unlink2 } from "fs/promises";
|
|
10271
|
+
import { dirname as dirname7 } from "path";
|
|
9412
10272
|
async function saveCustomCommand(opts2) {
|
|
9413
10273
|
const dir = opts2.source === "project" ? projectCommandsDir(opts2.cwd) : globalCommandsDir();
|
|
9414
10274
|
const filepath = `${dir}/${opts2.name}.md`;
|
|
@@ -9419,8 +10279,8 @@ async function saveCustomCommand(opts2) {
|
|
|
9419
10279
|
if (opts2.effort) data.effort = opts2.effort;
|
|
9420
10280
|
const frontmatter = serializeFrontmatter(data);
|
|
9421
10281
|
const content = frontmatter + opts2.template;
|
|
9422
|
-
await
|
|
9423
|
-
await
|
|
10282
|
+
await mkdir10(dirname7(filepath), { recursive: true });
|
|
10283
|
+
await writeFile10(filepath, content, "utf8");
|
|
9424
10284
|
return { filepath };
|
|
9425
10285
|
}
|
|
9426
10286
|
async function deleteCustomCommand(cmd) {
|
|
@@ -9435,21 +10295,21 @@ var init_save = __esm({
|
|
|
9435
10295
|
});
|
|
9436
10296
|
|
|
9437
10297
|
// src/ui/command-wizard.tsx
|
|
9438
|
-
import { useState as
|
|
9439
|
-
import { Box as
|
|
9440
|
-
import
|
|
9441
|
-
import { Fragment as Fragment2, jsx as
|
|
10298
|
+
import { useState as useState8 } from "react";
|
|
10299
|
+
import { Box as Box13, Text as Text14, useInput as useInput4, useWindowSize as useWindowSize2 } from "ink";
|
|
10300
|
+
import SelectInput5 from "ink-select-input";
|
|
10301
|
+
import { Fragment as Fragment2, jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
9442
10302
|
function CommandWizard({ mode, initial, existingNames, builtinNames, onDone, onSave }) {
|
|
9443
10303
|
const theme = useTheme();
|
|
9444
|
-
const [step, setStep] =
|
|
9445
|
-
const [name, setName] =
|
|
9446
|
-
const [description, setDescription] =
|
|
9447
|
-
const [template, setTemplate] =
|
|
9448
|
-
const [cmdMode, setCmdMode] =
|
|
9449
|
-
const [cmdEffort, setCmdEffort] =
|
|
9450
|
-
const [cmdModel, setCmdModel] =
|
|
9451
|
-
const [source, setSource] =
|
|
9452
|
-
const [error, setError] =
|
|
10304
|
+
const [step, setStep] = useState8("name");
|
|
10305
|
+
const [name, setName] = useState8(initial?.name ?? "");
|
|
10306
|
+
const [description, setDescription] = useState8(initial?.description ?? "");
|
|
10307
|
+
const [template, setTemplate] = useState8(initial?.template ?? "");
|
|
10308
|
+
const [cmdMode, setCmdMode] = useState8(initial?.mode);
|
|
10309
|
+
const [cmdEffort, setCmdEffort] = useState8(initial?.effort);
|
|
10310
|
+
const [cmdModel, setCmdModel] = useState8(initial?.model);
|
|
10311
|
+
const [source, setSource] = useState8(initial?.source ?? "project");
|
|
10312
|
+
const [error, setError] = useState8(null);
|
|
9453
10313
|
const { columns } = useWindowSize2();
|
|
9454
10314
|
const totalSteps = 5;
|
|
9455
10315
|
const stepIndex = step === "name" ? 1 : step === "description" ? 2 : step === "template" ? 3 : step === "advanced" || step === "mode" || step === "effort" || step === "model" ? 4 : step === "location" ? 4 : 5;
|
|
@@ -9462,7 +10322,7 @@ function CommandWizard({ mode, initial, existingNames, builtinNames, onDone, onS
|
|
|
9462
10322
|
if (existingNames.includes(trimmed) && !isEditingSelf(trimmed)) return `/${trimmed} already exists`;
|
|
9463
10323
|
return null;
|
|
9464
10324
|
};
|
|
9465
|
-
|
|
10325
|
+
useInput4((_input, key) => {
|
|
9466
10326
|
if (key.escape) {
|
|
9467
10327
|
onDone();
|
|
9468
10328
|
}
|
|
@@ -9562,8 +10422,8 @@ ${template}`;
|
|
|
9562
10422
|
const renderStep = () => {
|
|
9563
10423
|
switch (step) {
|
|
9564
10424
|
case "name":
|
|
9565
|
-
return /* @__PURE__ */
|
|
9566
|
-
/* @__PURE__ */
|
|
10425
|
+
return /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
10426
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
|
|
9567
10427
|
mode === "create" ? "Create" : "Edit",
|
|
9568
10428
|
" custom command \u2014 Name (",
|
|
9569
10429
|
stepIndex,
|
|
@@ -9571,8 +10431,8 @@ ${template}`;
|
|
|
9571
10431
|
totalSteps,
|
|
9572
10432
|
")"
|
|
9573
10433
|
] }),
|
|
9574
|
-
error && /* @__PURE__ */
|
|
9575
|
-
/* @__PURE__ */
|
|
10434
|
+
error && /* @__PURE__ */ jsx15(Text14, { color: theme.error, children: error }),
|
|
10435
|
+
/* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
|
|
9576
10436
|
CustomTextInput,
|
|
9577
10437
|
{
|
|
9578
10438
|
value: name,
|
|
@@ -9581,11 +10441,11 @@ ${template}`;
|
|
|
9581
10441
|
focus: true
|
|
9582
10442
|
}
|
|
9583
10443
|
) }),
|
|
9584
|
-
/* @__PURE__ */
|
|
10444
|
+
/* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "letters, numbers, _ - / only; must start with a letter" })
|
|
9585
10445
|
] });
|
|
9586
10446
|
case "description":
|
|
9587
|
-
return /* @__PURE__ */
|
|
9588
|
-
/* @__PURE__ */
|
|
10447
|
+
return /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
10448
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
|
|
9589
10449
|
mode === "create" ? "Create" : "Edit",
|
|
9590
10450
|
" custom command \u2014 Description (",
|
|
9591
10451
|
stepIndex,
|
|
@@ -9593,7 +10453,7 @@ ${template}`;
|
|
|
9593
10453
|
totalSteps,
|
|
9594
10454
|
")"
|
|
9595
10455
|
] }),
|
|
9596
|
-
/* @__PURE__ */
|
|
10456
|
+
/* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
|
|
9597
10457
|
CustomTextInput,
|
|
9598
10458
|
{
|
|
9599
10459
|
value: description,
|
|
@@ -9602,49 +10462,49 @@ ${template}`;
|
|
|
9602
10462
|
focus: true
|
|
9603
10463
|
}
|
|
9604
10464
|
) }),
|
|
9605
|
-
/* @__PURE__ */
|
|
10465
|
+
/* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Press Enter to skip" })
|
|
9606
10466
|
] });
|
|
9607
10467
|
case "template": {
|
|
9608
|
-
const guide = /* @__PURE__ */
|
|
9609
|
-
/* @__PURE__ */
|
|
9610
|
-
/* @__PURE__ */
|
|
9611
|
-
/* @__PURE__ */
|
|
10468
|
+
const guide = /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", paddingLeft: 1, children: [
|
|
10469
|
+
/* @__PURE__ */ jsx15(Text14, { color: theme.accent, bold: true, children: "What is this?" }),
|
|
10470
|
+
/* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "A prompt template \u2014 instructions to the AI." }),
|
|
10471
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.info.color, children: [
|
|
9612
10472
|
"When you type /",
|
|
9613
10473
|
name || "yourcommand",
|
|
9614
10474
|
" later, this gets sent to the model."
|
|
9615
10475
|
] }),
|
|
9616
|
-
/* @__PURE__ */
|
|
9617
|
-
/* @__PURE__ */
|
|
9618
|
-
/* @__PURE__ */
|
|
10476
|
+
/* @__PURE__ */ jsxs13(Box13, { marginTop: 1, flexDirection: "column", children: [
|
|
10477
|
+
/* @__PURE__ */ jsx15(Text14, { color: theme.accent, bold: true, children: "Variables" }),
|
|
10478
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.info.color, children: [
|
|
9619
10479
|
" ",
|
|
9620
10480
|
"$1, $2 ... \u2192 arguments you type"
|
|
9621
10481
|
] }),
|
|
9622
|
-
/* @__PURE__ */
|
|
10482
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.info.color, children: [
|
|
9623
10483
|
" ",
|
|
9624
10484
|
"$ARGUMENTS \u2192 everything after the command"
|
|
9625
10485
|
] })
|
|
9626
10486
|
] }),
|
|
9627
|
-
/* @__PURE__ */
|
|
9628
|
-
/* @__PURE__ */
|
|
9629
|
-
/* @__PURE__ */
|
|
10487
|
+
/* @__PURE__ */ jsxs13(Box13, { marginTop: 1, flexDirection: "column", children: [
|
|
10488
|
+
/* @__PURE__ */ jsx15(Text14, { color: theme.accent, bold: true, children: "Dynamic inlines" }),
|
|
10489
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.info.color, children: [
|
|
9630
10490
|
" ",
|
|
9631
10491
|
"!`git diff` \u2192 shell output inlined"
|
|
9632
10492
|
] }),
|
|
9633
|
-
/* @__PURE__ */
|
|
10493
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.info.color, children: [
|
|
9634
10494
|
" ",
|
|
9635
10495
|
"@README.md \u2192 file contents inlined"
|
|
9636
10496
|
] })
|
|
9637
10497
|
] }),
|
|
9638
|
-
/* @__PURE__ */
|
|
9639
|
-
/* @__PURE__ */
|
|
9640
|
-
/* @__PURE__ */
|
|
9641
|
-
/* @__PURE__ */
|
|
9642
|
-
/* @__PURE__ */
|
|
10498
|
+
/* @__PURE__ */ jsxs13(Box13, { marginTop: 1, flexDirection: "column", children: [
|
|
10499
|
+
/* @__PURE__ */ jsx15(Text14, { color: theme.accent, bold: true, children: "Example" }),
|
|
10500
|
+
/* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Review this PR diff:" }),
|
|
10501
|
+
/* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "!`git diff main...HEAD`" }),
|
|
10502
|
+
/* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Focus on: $1" })
|
|
9643
10503
|
] })
|
|
9644
10504
|
] });
|
|
9645
|
-
const inputArea = /* @__PURE__ */
|
|
9646
|
-
error && /* @__PURE__ */
|
|
9647
|
-
/* @__PURE__ */
|
|
10505
|
+
const inputArea = /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", flexGrow: 1, children: [
|
|
10506
|
+
error && /* @__PURE__ */ jsx15(Text14, { color: theme.error, children: error }),
|
|
10507
|
+
/* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
|
|
9648
10508
|
CustomTextInput,
|
|
9649
10509
|
{
|
|
9650
10510
|
value: template,
|
|
@@ -9654,13 +10514,13 @@ ${template}`;
|
|
|
9654
10514
|
enablePaste: true
|
|
9655
10515
|
}
|
|
9656
10516
|
) }),
|
|
9657
|
-
columns < 100 && /* @__PURE__ */
|
|
9658
|
-
/* @__PURE__ */
|
|
9659
|
-
/* @__PURE__ */
|
|
10517
|
+
columns < 100 && /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
10518
|
+
/* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Paste multi-line templates with Ctrl+V." }),
|
|
10519
|
+
/* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Variables: $1 $2 ... $ARGUMENTS Shell: !`cmd` File: @path" })
|
|
9660
10520
|
] })
|
|
9661
10521
|
] });
|
|
9662
|
-
return /* @__PURE__ */
|
|
9663
|
-
/* @__PURE__ */
|
|
10522
|
+
return /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
10523
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
|
|
9664
10524
|
mode === "create" ? "Create" : "Edit",
|
|
9665
10525
|
" custom command \u2014 Template (",
|
|
9666
10526
|
stepIndex,
|
|
@@ -9668,10 +10528,10 @@ ${template}`;
|
|
|
9668
10528
|
totalSteps,
|
|
9669
10529
|
")"
|
|
9670
10530
|
] }),
|
|
9671
|
-
columns >= 100 ? /* @__PURE__ */
|
|
9672
|
-
/* @__PURE__ */
|
|
9673
|
-
/* @__PURE__ */
|
|
9674
|
-
] }) : /* @__PURE__ */
|
|
10531
|
+
columns >= 100 ? /* @__PURE__ */ jsxs13(Box13, { flexDirection: "row", marginTop: 1, children: [
|
|
10532
|
+
/* @__PURE__ */ jsx15(Box13, { flexDirection: "column", width: "50%", children: inputArea }),
|
|
10533
|
+
/* @__PURE__ */ jsx15(Box13, { flexDirection: "column", width: "50%", children: guide })
|
|
10534
|
+
] }) : /* @__PURE__ */ jsx15(Box13, { flexDirection: "column", marginTop: 1, children: inputArea })
|
|
9675
10535
|
] });
|
|
9676
10536
|
}
|
|
9677
10537
|
case "advanced": {
|
|
@@ -9680,8 +10540,8 @@ ${template}`;
|
|
|
9680
10540
|
{ label: "Skip", value: "skip", key: "skip" },
|
|
9681
10541
|
{ label: "\u2190 Cancel", value: "cancel", key: "cancel" }
|
|
9682
10542
|
];
|
|
9683
|
-
return /* @__PURE__ */
|
|
9684
|
-
/* @__PURE__ */
|
|
10543
|
+
return /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
10544
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
|
|
9685
10545
|
mode === "create" ? "Create" : "Edit",
|
|
9686
10546
|
" custom command \u2014 Options (",
|
|
9687
10547
|
stepIndex,
|
|
@@ -9689,8 +10549,8 @@ ${template}`;
|
|
|
9689
10549
|
totalSteps,
|
|
9690
10550
|
")"
|
|
9691
10551
|
] }),
|
|
9692
|
-
/* @__PURE__ */
|
|
9693
|
-
|
|
10552
|
+
/* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
|
|
10553
|
+
SelectInput5,
|
|
9694
10554
|
{
|
|
9695
10555
|
items,
|
|
9696
10556
|
onSelect: (item) => {
|
|
@@ -9709,17 +10569,17 @@ ${template}`;
|
|
|
9709
10569
|
{ label: cmdMode === "auto" ? "auto \xB7 current" : "auto", value: "auto", key: "auto" },
|
|
9710
10570
|
{ label: "\u2190 Back", value: "__back__", key: "__back__" }
|
|
9711
10571
|
];
|
|
9712
|
-
return /* @__PURE__ */
|
|
9713
|
-
/* @__PURE__ */
|
|
10572
|
+
return /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
10573
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
|
|
9714
10574
|
"Mode override (",
|
|
9715
10575
|
stepIndex,
|
|
9716
10576
|
"/",
|
|
9717
10577
|
totalSteps,
|
|
9718
10578
|
")"
|
|
9719
10579
|
] }),
|
|
9720
|
-
/* @__PURE__ */
|
|
9721
|
-
/* @__PURE__ */
|
|
9722
|
-
|
|
10580
|
+
/* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Saved to file but not yet enforced at runtime" }),
|
|
10581
|
+
/* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
|
|
10582
|
+
SelectInput5,
|
|
9723
10583
|
{
|
|
9724
10584
|
items,
|
|
9725
10585
|
onSelect: (item) => {
|
|
@@ -9738,16 +10598,16 @@ ${template}`;
|
|
|
9738
10598
|
{ label: cmdEffort === "high" ? "high \xB7 current" : "high", value: "high", key: "high" },
|
|
9739
10599
|
{ label: "\u2190 Back", value: "__back__", key: "__back__" }
|
|
9740
10600
|
];
|
|
9741
|
-
return /* @__PURE__ */
|
|
9742
|
-
/* @__PURE__ */
|
|
10601
|
+
return /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
10602
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
|
|
9743
10603
|
"Reasoning effort (",
|
|
9744
10604
|
stepIndex,
|
|
9745
10605
|
"/",
|
|
9746
10606
|
totalSteps,
|
|
9747
10607
|
")"
|
|
9748
10608
|
] }),
|
|
9749
|
-
/* @__PURE__ */
|
|
9750
|
-
|
|
10609
|
+
/* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
|
|
10610
|
+
SelectInput5,
|
|
9751
10611
|
{
|
|
9752
10612
|
items,
|
|
9753
10613
|
onSelect: (item) => {
|
|
@@ -9759,15 +10619,15 @@ ${template}`;
|
|
|
9759
10619
|
] });
|
|
9760
10620
|
}
|
|
9761
10621
|
case "model":
|
|
9762
|
-
return /* @__PURE__ */
|
|
9763
|
-
/* @__PURE__ */
|
|
10622
|
+
return /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
10623
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
|
|
9764
10624
|
"Model override (",
|
|
9765
10625
|
stepIndex,
|
|
9766
10626
|
"/",
|
|
9767
10627
|
totalSteps,
|
|
9768
10628
|
")"
|
|
9769
10629
|
] }),
|
|
9770
|
-
/* @__PURE__ */
|
|
10630
|
+
/* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
|
|
9771
10631
|
CustomTextInput,
|
|
9772
10632
|
{
|
|
9773
10633
|
value: cmdModel ?? "",
|
|
@@ -9776,7 +10636,7 @@ ${template}`;
|
|
|
9776
10636
|
focus: true
|
|
9777
10637
|
}
|
|
9778
10638
|
) }),
|
|
9779
|
-
/* @__PURE__ */
|
|
10639
|
+
/* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Press Enter to skip" })
|
|
9780
10640
|
] });
|
|
9781
10641
|
case "location": {
|
|
9782
10642
|
const items = [
|
|
@@ -9784,16 +10644,16 @@ ${template}`;
|
|
|
9784
10644
|
{ label: source === "global" ? "Global \xB7 current" : "Global", value: "global", key: "global" },
|
|
9785
10645
|
{ label: "\u2190 Back", value: "__back__", key: "__back__" }
|
|
9786
10646
|
];
|
|
9787
|
-
return /* @__PURE__ */
|
|
9788
|
-
/* @__PURE__ */
|
|
10647
|
+
return /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
10648
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
|
|
9789
10649
|
"Save location (",
|
|
9790
10650
|
stepIndex,
|
|
9791
10651
|
"/",
|
|
9792
10652
|
totalSteps,
|
|
9793
10653
|
")"
|
|
9794
10654
|
] }),
|
|
9795
|
-
/* @__PURE__ */
|
|
9796
|
-
|
|
10655
|
+
/* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
|
|
10656
|
+
SelectInput5,
|
|
9797
10657
|
{
|
|
9798
10658
|
items,
|
|
9799
10659
|
onSelect: (item) => {
|
|
@@ -9802,7 +10662,7 @@ ${template}`;
|
|
|
9802
10662
|
}
|
|
9803
10663
|
}
|
|
9804
10664
|
) }),
|
|
9805
|
-
/* @__PURE__ */
|
|
10665
|
+
/* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Project: .kimiflare/commands/ Global: ~/.config/kimiflare/commands/" })
|
|
9806
10666
|
] });
|
|
9807
10667
|
}
|
|
9808
10668
|
case "confirm": {
|
|
@@ -9810,8 +10670,8 @@ ${template}`;
|
|
|
9810
10670
|
{ label: "Save", value: "save", key: "save" },
|
|
9811
10671
|
{ label: "Cancel", value: "cancel", key: "cancel" }
|
|
9812
10672
|
];
|
|
9813
|
-
return /* @__PURE__ */
|
|
9814
|
-
/* @__PURE__ */
|
|
10673
|
+
return /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
10674
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
|
|
9815
10675
|
mode === "create" ? "Create" : "Edit",
|
|
9816
10676
|
" custom command \u2014 Confirm (",
|
|
9817
10677
|
stepIndex,
|
|
@@ -9819,14 +10679,14 @@ ${template}`;
|
|
|
9819
10679
|
totalSteps,
|
|
9820
10680
|
")"
|
|
9821
10681
|
] }),
|
|
9822
|
-
/* @__PURE__ */
|
|
10682
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.info.color, children: [
|
|
9823
10683
|
source === "project" ? ".kimiflare/commands/" : "~/.config/kimiflare/commands/",
|
|
9824
10684
|
name,
|
|
9825
10685
|
".md"
|
|
9826
10686
|
] }),
|
|
9827
|
-
/* @__PURE__ */
|
|
9828
|
-
/* @__PURE__ */
|
|
9829
|
-
|
|
10687
|
+
/* @__PURE__ */ jsx15(Box13, { marginTop: 1, flexDirection: "column", children: previewContent().split("\n").map((line, i) => /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: line || " " }, i)) }),
|
|
10688
|
+
/* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
|
|
10689
|
+
SelectInput5,
|
|
9830
10690
|
{
|
|
9831
10691
|
items,
|
|
9832
10692
|
onSelect: (item) => handleConfirm(item.value)
|
|
@@ -9836,7 +10696,7 @@ ${template}`;
|
|
|
9836
10696
|
}
|
|
9837
10697
|
}
|
|
9838
10698
|
};
|
|
9839
|
-
return /* @__PURE__ */
|
|
10699
|
+
return /* @__PURE__ */ jsx15(Box13, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: renderStep() });
|
|
9840
10700
|
}
|
|
9841
10701
|
var NAME_RE;
|
|
9842
10702
|
var init_command_wizard = __esm({
|
|
@@ -9849,9 +10709,9 @@ var init_command_wizard = __esm({
|
|
|
9849
10709
|
});
|
|
9850
10710
|
|
|
9851
10711
|
// src/ui/command-picker.tsx
|
|
9852
|
-
import { Box as
|
|
9853
|
-
import
|
|
9854
|
-
import { jsx as
|
|
10712
|
+
import { Box as Box14, Text as Text15 } from "ink";
|
|
10713
|
+
import SelectInput6 from "ink-select-input";
|
|
10714
|
+
import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
9855
10715
|
function CommandPicker({ commands, title, onPick }) {
|
|
9856
10716
|
const theme = useTheme();
|
|
9857
10717
|
const items = commands.map((cmd) => ({
|
|
@@ -9860,11 +10720,11 @@ function CommandPicker({ commands, title, onPick }) {
|
|
|
9860
10720
|
key: cmd.name
|
|
9861
10721
|
}));
|
|
9862
10722
|
items.push({ label: "\u2190 Cancel", value: null, key: "__cancel__" });
|
|
9863
|
-
return /* @__PURE__ */
|
|
9864
|
-
/* @__PURE__ */
|
|
9865
|
-
/* @__PURE__ */
|
|
9866
|
-
/* @__PURE__ */
|
|
9867
|
-
|
|
10723
|
+
return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
10724
|
+
/* @__PURE__ */ jsx16(Text15, { color: theme.accent, bold: true, children: title }),
|
|
10725
|
+
/* @__PURE__ */ jsx16(Text15, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select." }),
|
|
10726
|
+
/* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(
|
|
10727
|
+
SelectInput6,
|
|
9868
10728
|
{
|
|
9869
10729
|
items,
|
|
9870
10730
|
onSelect: (item) => {
|
|
@@ -9886,64 +10746,64 @@ var init_command_picker = __esm({
|
|
|
9886
10746
|
});
|
|
9887
10747
|
|
|
9888
10748
|
// src/ui/command-list.tsx
|
|
9889
|
-
import { Box as
|
|
9890
|
-
import { jsx as
|
|
10749
|
+
import { Box as Box15, Text as Text16, useInput as useInput5 } from "ink";
|
|
10750
|
+
import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
9891
10751
|
function CommandList({ commands, onDone }) {
|
|
9892
10752
|
const theme = useTheme();
|
|
9893
|
-
|
|
10753
|
+
useInput5((_input, key) => {
|
|
9894
10754
|
if (key.escape) {
|
|
9895
10755
|
onDone();
|
|
9896
10756
|
}
|
|
9897
10757
|
});
|
|
9898
|
-
return /* @__PURE__ */
|
|
9899
|
-
/* @__PURE__ */
|
|
9900
|
-
/* @__PURE__ */
|
|
9901
|
-
/* @__PURE__ */
|
|
9902
|
-
commands.length === 0 && /* @__PURE__ */
|
|
9903
|
-
commands.map((cmd) => /* @__PURE__ */
|
|
9904
|
-
/* @__PURE__ */
|
|
10758
|
+
return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
10759
|
+
/* @__PURE__ */ jsx17(Text16, { color: theme.accent, bold: true, children: "Custom commands" }),
|
|
10760
|
+
/* @__PURE__ */ jsx17(Text16, { color: theme.info.color, dimColor: false, children: "Esc to close." }),
|
|
10761
|
+
/* @__PURE__ */ jsxs15(Box15, { marginTop: 1, flexDirection: "column", children: [
|
|
10762
|
+
commands.length === 0 && /* @__PURE__ */ jsx17(Text16, { color: theme.info.color, children: "No custom commands found." }),
|
|
10763
|
+
commands.map((cmd) => /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", marginBottom: 1, children: [
|
|
10764
|
+
/* @__PURE__ */ jsxs15(Text16, { color: theme.accent, bold: true, children: [
|
|
9905
10765
|
"/",
|
|
9906
10766
|
cmd.name
|
|
9907
10767
|
] }),
|
|
9908
|
-
/* @__PURE__ */
|
|
10768
|
+
/* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
|
|
9909
10769
|
" ",
|
|
9910
10770
|
"source: ",
|
|
9911
10771
|
cmd.source
|
|
9912
10772
|
] }),
|
|
9913
|
-
/* @__PURE__ */
|
|
10773
|
+
/* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
|
|
9914
10774
|
" ",
|
|
9915
10775
|
"path: ",
|
|
9916
10776
|
cmd.filepath
|
|
9917
10777
|
] }),
|
|
9918
|
-
cmd.description && /* @__PURE__ */
|
|
10778
|
+
cmd.description && /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
|
|
9919
10779
|
" ",
|
|
9920
10780
|
"desc: ",
|
|
9921
10781
|
cmd.description
|
|
9922
10782
|
] }),
|
|
9923
|
-
cmd.mode && /* @__PURE__ */
|
|
10783
|
+
cmd.mode && /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
|
|
9924
10784
|
" ",
|
|
9925
10785
|
"mode: ",
|
|
9926
10786
|
cmd.mode
|
|
9927
10787
|
] }),
|
|
9928
|
-
cmd.effort && /* @__PURE__ */
|
|
10788
|
+
cmd.effort && /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
|
|
9929
10789
|
" ",
|
|
9930
10790
|
"effort: ",
|
|
9931
10791
|
cmd.effort
|
|
9932
10792
|
] }),
|
|
9933
|
-
cmd.model && /* @__PURE__ */
|
|
10793
|
+
cmd.model && /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
|
|
9934
10794
|
" ",
|
|
9935
10795
|
"model: ",
|
|
9936
10796
|
cmd.model
|
|
9937
10797
|
] }),
|
|
9938
|
-
/* @__PURE__ */
|
|
10798
|
+
/* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
|
|
9939
10799
|
" ",
|
|
9940
10800
|
"template:"
|
|
9941
10801
|
] }),
|
|
9942
|
-
cmd.template.split("\n").slice(0, 5).map((line, i) => /* @__PURE__ */
|
|
10802
|
+
cmd.template.split("\n").slice(0, 5).map((line, i) => /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
|
|
9943
10803
|
" ",
|
|
9944
10804
|
line || " "
|
|
9945
10805
|
] }, i)),
|
|
9946
|
-
cmd.template.split("\n").length > 5 && /* @__PURE__ */
|
|
10806
|
+
cmd.template.split("\n").length > 5 && /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
|
|
9947
10807
|
" ",
|
|
9948
10808
|
"..."
|
|
9949
10809
|
] })
|
|
@@ -9959,20 +10819,20 @@ var init_command_list = __esm({
|
|
|
9959
10819
|
});
|
|
9960
10820
|
|
|
9961
10821
|
// src/ui/lsp-wizard.tsx
|
|
9962
|
-
import { useState as
|
|
9963
|
-
import { Box as
|
|
9964
|
-
import
|
|
10822
|
+
import { useState as useState9 } from "react";
|
|
10823
|
+
import { Box as Box16, Text as Text17 } from "ink";
|
|
10824
|
+
import SelectInput7 from "ink-select-input";
|
|
9965
10825
|
import { spawn as spawn3 } from "child_process";
|
|
9966
|
-
import { jsx as
|
|
10826
|
+
import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
9967
10827
|
function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
9968
10828
|
const theme = useTheme();
|
|
9969
|
-
const [page, setPage] =
|
|
9970
|
-
const [selectedPreset, setSelectedPreset] =
|
|
9971
|
-
const [customName, setCustomName] =
|
|
9972
|
-
const [customCommand, setCustomCommand] =
|
|
9973
|
-
const [installState, setInstallState] =
|
|
9974
|
-
const [pendingServers, setPendingServers] =
|
|
9975
|
-
const [pendingEnabled, setPendingEnabled] =
|
|
10829
|
+
const [page, setPage] = useState9("main");
|
|
10830
|
+
const [selectedPreset, setSelectedPreset] = useState9(null);
|
|
10831
|
+
const [customName, setCustomName] = useState9("");
|
|
10832
|
+
const [customCommand, setCustomCommand] = useState9("");
|
|
10833
|
+
const [installState, setInstallState] = useState9({ status: "idle", output: "" });
|
|
10834
|
+
const [pendingServers, setPendingServers] = useState9(null);
|
|
10835
|
+
const [pendingEnabled, setPendingEnabled] = useState9(true);
|
|
9976
10836
|
const runInstall = (command) => {
|
|
9977
10837
|
setInstallState({ status: "running", output: "Installing..." });
|
|
9978
10838
|
const child = spawn3("bash", ["-lc", command], {
|
|
@@ -10074,11 +10934,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
10074
10934
|
{ label: "(close)", value: "__close__", key: "__close__" }
|
|
10075
10935
|
];
|
|
10076
10936
|
if (page === "main") {
|
|
10077
|
-
return /* @__PURE__ */
|
|
10078
|
-
/* @__PURE__ */
|
|
10079
|
-
/* @__PURE__ */
|
|
10080
|
-
/* @__PURE__ */
|
|
10081
|
-
|
|
10937
|
+
return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
10938
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "LSP Servers" }),
|
|
10939
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select." }),
|
|
10940
|
+
/* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
|
|
10941
|
+
SelectInput7,
|
|
10082
10942
|
{
|
|
10083
10943
|
items: mainItems,
|
|
10084
10944
|
onSelect: (item) => {
|
|
@@ -10105,11 +10965,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
10105
10965
|
}),
|
|
10106
10966
|
{ label: "\u2190 Back", value: "__back__", key: "__back__" }
|
|
10107
10967
|
];
|
|
10108
|
-
return /* @__PURE__ */
|
|
10109
|
-
/* @__PURE__ */
|
|
10110
|
-
/* @__PURE__ */
|
|
10111
|
-
/* @__PURE__ */
|
|
10112
|
-
|
|
10968
|
+
return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
10969
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Add LSP Server" }),
|
|
10970
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Select a language server to configure." }),
|
|
10971
|
+
/* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
|
|
10972
|
+
SelectInput7,
|
|
10113
10973
|
{
|
|
10114
10974
|
items,
|
|
10115
10975
|
onSelect: (item) => {
|
|
@@ -10136,19 +10996,19 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
10136
10996
|
{ label: isSuccess ? "Save to config \u2713" : "Save anyway", value: "save", key: "save" },
|
|
10137
10997
|
{ label: "\u2190 Back", value: "__back__", key: "__back__" }
|
|
10138
10998
|
];
|
|
10139
|
-
return /* @__PURE__ */
|
|
10140
|
-
/* @__PURE__ */
|
|
10999
|
+
return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
11000
|
+
/* @__PURE__ */ jsxs16(Text17, { color: theme.accent, bold: true, children: [
|
|
10141
11001
|
"Install ",
|
|
10142
11002
|
selectedPreset.name
|
|
10143
11003
|
] }),
|
|
10144
|
-
/* @__PURE__ */
|
|
10145
|
-
/* @__PURE__ */
|
|
10146
|
-
/* @__PURE__ */
|
|
10147
|
-
/* @__PURE__ */
|
|
11004
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: selectedPreset.installHint }),
|
|
11005
|
+
/* @__PURE__ */ jsxs16(Box16, { marginTop: 1, flexDirection: "column", children: [
|
|
11006
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Command:" }),
|
|
11007
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.accent, children: selectedPreset.installCommand || "(none required)" })
|
|
10148
11008
|
] }),
|
|
10149
|
-
installState.output && /* @__PURE__ */
|
|
10150
|
-
/* @__PURE__ */
|
|
10151
|
-
|
|
11009
|
+
installState.output && /* @__PURE__ */ jsx18(Box16, { marginTop: 1, flexDirection: "column", children: /* @__PURE__ */ jsx18(Text17, { color: isSuccess ? theme.accent : theme.error, children: installState.output.slice(-500) }) }),
|
|
11010
|
+
/* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
|
|
11011
|
+
SelectInput7,
|
|
10152
11012
|
{
|
|
10153
11013
|
items,
|
|
10154
11014
|
onSelect: (item) => {
|
|
@@ -10165,16 +11025,16 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
10165
11025
|
}
|
|
10166
11026
|
}
|
|
10167
11027
|
) }),
|
|
10168
|
-
isSuccess && /* @__PURE__ */
|
|
11028
|
+
isSuccess && /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(Text17, { color: theme.accent, children: "Server saved. Run /lsp reload to start it." }) })
|
|
10169
11029
|
] });
|
|
10170
11030
|
}
|
|
10171
11031
|
if (page === "custom-name") {
|
|
10172
|
-
return /* @__PURE__ */
|
|
10173
|
-
/* @__PURE__ */
|
|
10174
|
-
/* @__PURE__ */
|
|
10175
|
-
/* @__PURE__ */
|
|
10176
|
-
/* @__PURE__ */
|
|
10177
|
-
/* @__PURE__ */
|
|
11032
|
+
return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
11033
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Custom LSP Server \u2014 Name" }),
|
|
11034
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Enter a name for this server (e.g., my-server)." }),
|
|
11035
|
+
/* @__PURE__ */ jsxs16(Box16, { marginTop: 1, children: [
|
|
11036
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.accent, children: "\u203A " }),
|
|
11037
|
+
/* @__PURE__ */ jsx18(
|
|
10178
11038
|
CustomTextInput,
|
|
10179
11039
|
{
|
|
10180
11040
|
value: customName,
|
|
@@ -10188,8 +11048,8 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
10188
11048
|
}
|
|
10189
11049
|
)
|
|
10190
11050
|
] }),
|
|
10191
|
-
/* @__PURE__ */
|
|
10192
|
-
|
|
11051
|
+
/* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
|
|
11052
|
+
SelectInput7,
|
|
10193
11053
|
{
|
|
10194
11054
|
items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
|
|
10195
11055
|
onSelect: () => setPage("add")
|
|
@@ -10198,12 +11058,12 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
10198
11058
|
] });
|
|
10199
11059
|
}
|
|
10200
11060
|
if (page === "custom-command") {
|
|
10201
|
-
return /* @__PURE__ */
|
|
10202
|
-
/* @__PURE__ */
|
|
10203
|
-
/* @__PURE__ */
|
|
10204
|
-
/* @__PURE__ */
|
|
10205
|
-
/* @__PURE__ */
|
|
10206
|
-
/* @__PURE__ */
|
|
11061
|
+
return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
11062
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Custom LSP Server \u2014 Command" }),
|
|
11063
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Enter the command to start the server (space-separated)." }),
|
|
11064
|
+
/* @__PURE__ */ jsxs16(Box16, { marginTop: 1, children: [
|
|
11065
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.accent, children: "\u203A " }),
|
|
11066
|
+
/* @__PURE__ */ jsx18(
|
|
10207
11067
|
CustomTextInput,
|
|
10208
11068
|
{
|
|
10209
11069
|
value: customCommand,
|
|
@@ -10217,8 +11077,8 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
10217
11077
|
}
|
|
10218
11078
|
)
|
|
10219
11079
|
] }),
|
|
10220
|
-
/* @__PURE__ */
|
|
10221
|
-
|
|
11080
|
+
/* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
|
|
11081
|
+
SelectInput7,
|
|
10222
11082
|
{
|
|
10223
11083
|
items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
|
|
10224
11084
|
onSelect: () => setPage("custom-name")
|
|
@@ -10241,11 +11101,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
10241
11101
|
},
|
|
10242
11102
|
{ label: "\u2190 Back", value: "__back__", key: "__back__" }
|
|
10243
11103
|
];
|
|
10244
|
-
return /* @__PURE__ */
|
|
10245
|
-
/* @__PURE__ */
|
|
10246
|
-
/* @__PURE__ */
|
|
10247
|
-
/* @__PURE__ */
|
|
10248
|
-
|
|
11104
|
+
return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
11105
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Save LSP Config" }),
|
|
11106
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Where should this server configuration be saved?" }),
|
|
11107
|
+
/* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
|
|
11108
|
+
SelectInput7,
|
|
10249
11109
|
{
|
|
10250
11110
|
items,
|
|
10251
11111
|
onSelect: (item) => {
|
|
@@ -10263,11 +11123,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
10263
11123
|
if (page === "edit") {
|
|
10264
11124
|
const keys = Object.keys(servers);
|
|
10265
11125
|
if (keys.length === 0) {
|
|
10266
|
-
return /* @__PURE__ */
|
|
10267
|
-
/* @__PURE__ */
|
|
10268
|
-
/* @__PURE__ */
|
|
10269
|
-
/* @__PURE__ */
|
|
10270
|
-
|
|
11126
|
+
return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
11127
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Edit LSP Server" }),
|
|
11128
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.info.color, children: "No servers configured." }),
|
|
11129
|
+
/* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
|
|
11130
|
+
SelectInput7,
|
|
10271
11131
|
{
|
|
10272
11132
|
items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
|
|
10273
11133
|
onSelect: () => setPage("main")
|
|
@@ -10287,11 +11147,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
10287
11147
|
}),
|
|
10288
11148
|
{ label: "\u2190 Back", value: "__back__", key: "__back__" }
|
|
10289
11149
|
];
|
|
10290
|
-
return /* @__PURE__ */
|
|
10291
|
-
/* @__PURE__ */
|
|
10292
|
-
/* @__PURE__ */
|
|
10293
|
-
/* @__PURE__ */
|
|
10294
|
-
|
|
11150
|
+
return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
11151
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Edit LSP Server" }),
|
|
11152
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Select a server to toggle enabled/disabled." }),
|
|
11153
|
+
/* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
|
|
11154
|
+
SelectInput7,
|
|
10295
11155
|
{
|
|
10296
11156
|
items,
|
|
10297
11157
|
onSelect: (item) => {
|
|
@@ -10308,11 +11168,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
10308
11168
|
if (page === "delete") {
|
|
10309
11169
|
const keys = Object.keys(servers);
|
|
10310
11170
|
if (keys.length === 0) {
|
|
10311
|
-
return /* @__PURE__ */
|
|
10312
|
-
/* @__PURE__ */
|
|
10313
|
-
/* @__PURE__ */
|
|
10314
|
-
/* @__PURE__ */
|
|
10315
|
-
|
|
11171
|
+
return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
11172
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Delete LSP Server" }),
|
|
11173
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.info.color, children: "No servers configured." }),
|
|
11174
|
+
/* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
|
|
11175
|
+
SelectInput7,
|
|
10316
11176
|
{
|
|
10317
11177
|
items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
|
|
10318
11178
|
onSelect: () => setPage("main")
|
|
@@ -10328,11 +11188,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
10328
11188
|
})),
|
|
10329
11189
|
{ label: "\u2190 Back", value: "__back__", key: "__back__" }
|
|
10330
11190
|
];
|
|
10331
|
-
return /* @__PURE__ */
|
|
10332
|
-
/* @__PURE__ */
|
|
10333
|
-
/* @__PURE__ */
|
|
10334
|
-
/* @__PURE__ */
|
|
10335
|
-
|
|
11191
|
+
return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
11192
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Delete LSP Server" }),
|
|
11193
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Select a server to remove from config." }),
|
|
11194
|
+
/* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
|
|
11195
|
+
SelectInput7,
|
|
10336
11196
|
{
|
|
10337
11197
|
items,
|
|
10338
11198
|
onSelect: (item) => {
|
|
@@ -10348,15 +11208,15 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
10348
11208
|
}
|
|
10349
11209
|
if (page === "list") {
|
|
10350
11210
|
const keys = Object.keys(servers);
|
|
10351
|
-
return /* @__PURE__ */
|
|
10352
|
-
/* @__PURE__ */
|
|
10353
|
-
keys.length === 0 ? /* @__PURE__ */
|
|
11211
|
+
return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
11212
|
+
/* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Configured LSP Servers" }),
|
|
11213
|
+
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) => {
|
|
10354
11214
|
const s = servers[k];
|
|
10355
11215
|
const status = s.enabled !== false ? "enabled" : "disabled";
|
|
10356
|
-
return /* @__PURE__ */
|
|
11216
|
+
return /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, children: ` ${k.padEnd(16)} ${status} ${s.command.join(" ")}` }, k);
|
|
10357
11217
|
}) }),
|
|
10358
|
-
/* @__PURE__ */
|
|
10359
|
-
|
|
11218
|
+
/* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
|
|
11219
|
+
SelectInput7,
|
|
10360
11220
|
{
|
|
10361
11221
|
items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
|
|
10362
11222
|
onSelect: () => setPage("main")
|
|
@@ -10482,9 +11342,9 @@ var init_lsp_wizard = __esm({
|
|
|
10482
11342
|
});
|
|
10483
11343
|
|
|
10484
11344
|
// src/ui/theme-picker.tsx
|
|
10485
|
-
import { Box as
|
|
10486
|
-
import
|
|
10487
|
-
import { jsx as
|
|
11345
|
+
import { Box as Box17, Text as Text18 } from "ink";
|
|
11346
|
+
import SelectInput8 from "ink-select-input";
|
|
11347
|
+
import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
10488
11348
|
function PaletteSwatches({ palette }) {
|
|
10489
11349
|
const colors = [
|
|
10490
11350
|
palette.primary,
|
|
@@ -10492,7 +11352,7 @@ function PaletteSwatches({ palette }) {
|
|
|
10492
11352
|
palette.success,
|
|
10493
11353
|
palette.error
|
|
10494
11354
|
];
|
|
10495
|
-
return /* @__PURE__ */
|
|
11355
|
+
return /* @__PURE__ */ jsx19(Box17, { children: colors.map((c, i) => /* @__PURE__ */ jsx19(Text18, { color: c, children: "\u2588" }, i)) });
|
|
10496
11356
|
}
|
|
10497
11357
|
function ThemePicker({ themes, onPick, onPreview }) {
|
|
10498
11358
|
const current = useTheme();
|
|
@@ -10500,10 +11360,10 @@ function ThemePicker({ themes, onPick, onPreview }) {
|
|
|
10500
11360
|
...themes.map((t) => ({ label: t.label, value: t.name })),
|
|
10501
11361
|
{ label: "< Back", value: "__back__" }
|
|
10502
11362
|
];
|
|
10503
|
-
return /* @__PURE__ */
|
|
10504
|
-
/* @__PURE__ */
|
|
10505
|
-
/* @__PURE__ */
|
|
10506
|
-
|
|
11363
|
+
return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: current.accent, paddingX: 1, children: [
|
|
11364
|
+
/* @__PURE__ */ jsx19(Text18, { color: current.accent, bold: true, children: "Pick a theme" }),
|
|
11365
|
+
/* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
|
|
11366
|
+
SelectInput8,
|
|
10507
11367
|
{
|
|
10508
11368
|
items,
|
|
10509
11369
|
onHighlight: (item) => {
|
|
@@ -10522,9 +11382,9 @@ function ThemePicker({ themes, onPick, onPreview }) {
|
|
|
10522
11382
|
itemComponent: ({ label, isSelected }) => {
|
|
10523
11383
|
const t = themes.find((x) => x.label === label);
|
|
10524
11384
|
const color = t?.accent ?? current.accent;
|
|
10525
|
-
return /* @__PURE__ */
|
|
10526
|
-
/* @__PURE__ */
|
|
10527
|
-
t && /* @__PURE__ */
|
|
11385
|
+
return /* @__PURE__ */ jsxs17(Box17, { children: [
|
|
11386
|
+
/* @__PURE__ */ jsx19(Text18, { color, bold: isSelected, dimColor: !isSelected, children: label }),
|
|
11387
|
+
t && /* @__PURE__ */ jsx19(Box17, { marginLeft: 1, children: /* @__PURE__ */ jsx19(PaletteSwatches, { palette: t.palette }) })
|
|
10528
11388
|
] });
|
|
10529
11389
|
}
|
|
10530
11390
|
}
|
|
@@ -10668,8 +11528,8 @@ var init_lsp_nudge = __esm({
|
|
|
10668
11528
|
});
|
|
10669
11529
|
|
|
10670
11530
|
// src/ui/file-picker.tsx
|
|
10671
|
-
import { Box as
|
|
10672
|
-
import { jsx as
|
|
11531
|
+
import { Box as Box18, Text as Text19 } from "ink";
|
|
11532
|
+
import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
10673
11533
|
function FilePicker({ items, selectedIndex, query }) {
|
|
10674
11534
|
const theme = useTheme();
|
|
10675
11535
|
let startIndex = 0;
|
|
@@ -10679,12 +11539,12 @@ function FilePicker({ items, selectedIndex, query }) {
|
|
|
10679
11539
|
const visible = items.slice(startIndex, startIndex + VISIBLE_LIMIT);
|
|
10680
11540
|
const hasMoreAbove = startIndex > 0;
|
|
10681
11541
|
const hasMoreBelow = items.length > startIndex + VISIBLE_LIMIT;
|
|
10682
|
-
return /* @__PURE__ */
|
|
10683
|
-
/* @__PURE__ */
|
|
10684
|
-
/* @__PURE__ */
|
|
10685
|
-
/* @__PURE__ */
|
|
10686
|
-
visible.length === 0 && /* @__PURE__ */
|
|
10687
|
-
hasMoreAbove && /* @__PURE__ */
|
|
11542
|
+
return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
11543
|
+
/* @__PURE__ */ jsx20(Text19, { color: theme.accent, bold: true, children: query ? `Files matching "${query}"` : "Mention a file" }),
|
|
11544
|
+
/* @__PURE__ */ jsx20(Text19, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select, Esc to cancel." }),
|
|
11545
|
+
/* @__PURE__ */ jsxs18(Box18, { marginTop: 1, flexDirection: "column", children: [
|
|
11546
|
+
visible.length === 0 && /* @__PURE__ */ jsx20(Text19, { color: theme.info.color, children: "No matches" }),
|
|
11547
|
+
hasMoreAbove && /* @__PURE__ */ jsxs18(Text19, { color: theme.info.color, children: [
|
|
10688
11548
|
"\u2026 ",
|
|
10689
11549
|
startIndex,
|
|
10690
11550
|
" more above"
|
|
@@ -10693,12 +11553,12 @@ function FilePicker({ items, selectedIndex, query }) {
|
|
|
10693
11553
|
const actualIndex = startIndex + i;
|
|
10694
11554
|
const isSelected = actualIndex === selectedIndex;
|
|
10695
11555
|
const label = item.isDirectory ? `${item.name}/` : item.name;
|
|
10696
|
-
return /* @__PURE__ */
|
|
11556
|
+
return /* @__PURE__ */ jsxs18(Text19, { color: isSelected ? theme.accent : void 0, bold: isSelected, children: [
|
|
10697
11557
|
isSelected ? "\u203A " : " ",
|
|
10698
11558
|
label
|
|
10699
11559
|
] }, item.name);
|
|
10700
11560
|
}),
|
|
10701
|
-
hasMoreBelow && /* @__PURE__ */
|
|
11561
|
+
hasMoreBelow && /* @__PURE__ */ jsxs18(Text19, { color: theme.info.color, children: [
|
|
10702
11562
|
"\u2026 ",
|
|
10703
11563
|
items.length - (startIndex + VISIBLE_LIMIT),
|
|
10704
11564
|
" more below"
|
|
@@ -10716,8 +11576,8 @@ var init_file_picker = __esm({
|
|
|
10716
11576
|
});
|
|
10717
11577
|
|
|
10718
11578
|
// src/ui/slash-picker.tsx
|
|
10719
|
-
import { Box as
|
|
10720
|
-
import { jsx as
|
|
11579
|
+
import { Box as Box19, Text as Text20 } from "ink";
|
|
11580
|
+
import { jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
10721
11581
|
function sourceBadge(source) {
|
|
10722
11582
|
if (source === "builtin") return "";
|
|
10723
11583
|
if (source === "project") return "project";
|
|
@@ -10737,12 +11597,12 @@ function SlashPicker({ items, selectedIndex, query }) {
|
|
|
10737
11597
|
const hasMoreBelow = items.length > startIndex + VISIBLE_LIMIT2;
|
|
10738
11598
|
const longestLabel = visible.reduce((m, it) => Math.max(m, commandLabel(it).length), 0);
|
|
10739
11599
|
const nameColWidth = Math.max(NAME_COL_MIN_WIDTH, longestLabel + NAME_DESC_GAP);
|
|
10740
|
-
return /* @__PURE__ */
|
|
10741
|
-
/* @__PURE__ */
|
|
10742
|
-
/* @__PURE__ */
|
|
10743
|
-
/* @__PURE__ */
|
|
10744
|
-
visible.length === 0 && /* @__PURE__ */
|
|
10745
|
-
hasMoreAbove && /* @__PURE__ */
|
|
11600
|
+
return /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
11601
|
+
/* @__PURE__ */ jsx21(Text20, { color: theme.accent, bold: true, children: query ? `Commands matching "/${query}"` : "Slash commands" }),
|
|
11602
|
+
/* @__PURE__ */ jsx21(Text20, { color: theme.info.color, children: "Arrow keys to navigate, Enter to select, Esc to cancel." }),
|
|
11603
|
+
/* @__PURE__ */ jsxs19(Box19, { marginTop: 1, flexDirection: "column", children: [
|
|
11604
|
+
visible.length === 0 && /* @__PURE__ */ jsx21(Text20, { color: theme.info.color, children: "No matches" }),
|
|
11605
|
+
hasMoreAbove && /* @__PURE__ */ jsxs19(Text20, { color: theme.info.color, children: [
|
|
10746
11606
|
"\u2026 ",
|
|
10747
11607
|
startIndex,
|
|
10748
11608
|
" more above"
|
|
@@ -10752,16 +11612,16 @@ function SlashPicker({ items, selectedIndex, query }) {
|
|
|
10752
11612
|
const isSelected = actualIndex === selectedIndex;
|
|
10753
11613
|
const nameCol = commandLabel(item).padEnd(nameColWidth);
|
|
10754
11614
|
const badge = sourceBadge(item.source);
|
|
10755
|
-
return /* @__PURE__ */
|
|
11615
|
+
return /* @__PURE__ */ jsxs19(Text20, { color: isSelected ? theme.accent : void 0, bold: isSelected, children: [
|
|
10756
11616
|
isSelected ? "\u203A " : " ",
|
|
10757
11617
|
nameCol,
|
|
10758
|
-
/* @__PURE__ */
|
|
11618
|
+
/* @__PURE__ */ jsxs19(Text20, { color: theme.info.color, children: [
|
|
10759
11619
|
item.description,
|
|
10760
11620
|
badge && ` [${badge}]`
|
|
10761
11621
|
] })
|
|
10762
11622
|
] }, item.name);
|
|
10763
11623
|
}),
|
|
10764
|
-
hasMoreBelow && /* @__PURE__ */
|
|
11624
|
+
hasMoreBelow && /* @__PURE__ */ jsxs19(Text20, { color: theme.info.color, children: [
|
|
10765
11625
|
"\u2026 ",
|
|
10766
11626
|
items.length - (startIndex + VISIBLE_LIMIT2),
|
|
10767
11627
|
" more below"
|
|
@@ -10841,15 +11701,15 @@ var tui_report_exports = {};
|
|
|
10841
11701
|
__export(tui_report_exports, {
|
|
10842
11702
|
getCategoryReportText: () => getCategoryReportText
|
|
10843
11703
|
});
|
|
10844
|
-
import { readFile as
|
|
10845
|
-
import { join as
|
|
10846
|
-
import { homedir as
|
|
11704
|
+
import { readFile as readFile15 } from "fs/promises";
|
|
11705
|
+
import { join as join18 } from "path";
|
|
11706
|
+
import { homedir as homedir13 } from "os";
|
|
10847
11707
|
function usageDir3() {
|
|
10848
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
10849
|
-
return
|
|
11708
|
+
const xdg = process.env.XDG_DATA_HOME || join18(homedir13(), ".local", "share");
|
|
11709
|
+
return join18(xdg, "kimiflare");
|
|
10850
11710
|
}
|
|
10851
11711
|
function usagePath3() {
|
|
10852
|
-
return
|
|
11712
|
+
return join18(usageDir3(), "usage.json");
|
|
10853
11713
|
}
|
|
10854
11714
|
function today3() {
|
|
10855
11715
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
@@ -10861,7 +11721,7 @@ function daysAgo2(n) {
|
|
|
10861
11721
|
}
|
|
10862
11722
|
async function loadLog3() {
|
|
10863
11723
|
try {
|
|
10864
|
-
const raw = await
|
|
11724
|
+
const raw = await readFile15(usagePath3(), "utf8");
|
|
10865
11725
|
return JSON.parse(raw);
|
|
10866
11726
|
} catch {
|
|
10867
11727
|
return { version: 1, days: [], sessions: [] };
|
|
@@ -10927,17 +11787,18 @@ __export(app_exports, {
|
|
|
10927
11787
|
shouldOpenMentionPicker: () => shouldOpenMentionPicker,
|
|
10928
11788
|
shouldOpenSlashPicker: () => shouldOpenSlashPicker
|
|
10929
11789
|
});
|
|
10930
|
-
import
|
|
10931
|
-
import { Box as
|
|
10932
|
-
import
|
|
11790
|
+
import React14, { useState as useState10, useRef as useRef3, useEffect as useEffect5, useCallback } from "react";
|
|
11791
|
+
import { Box as Box20, Text as Text21, useApp, useInput as useInput6, render } from "ink";
|
|
11792
|
+
import SelectInput9 from "ink-select-input";
|
|
10933
11793
|
import { existsSync as existsSync2, statSync as statSync3 } from "fs";
|
|
10934
|
-
import { join as
|
|
11794
|
+
import { join as join19 } from "path";
|
|
10935
11795
|
import { unlink as unlink3 } from "fs/promises";
|
|
11796
|
+
import { execSync as execSync2 } from "child_process";
|
|
10936
11797
|
import { spawn as spawn4 } from "child_process";
|
|
10937
11798
|
import { platform as platform2 } from "os";
|
|
10938
11799
|
import fg4 from "fast-glob";
|
|
10939
11800
|
import { readFileSync as readFileSync3 } from "fs";
|
|
10940
|
-
import { jsx as
|
|
11801
|
+
import { jsx as jsx22, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
10941
11802
|
function buildFilePickerIgnoreList(cwd) {
|
|
10942
11803
|
const hardcoded = [
|
|
10943
11804
|
// Dependencies
|
|
@@ -11008,7 +11869,7 @@ function buildFilePickerIgnoreList(cwd) {
|
|
|
11008
11869
|
];
|
|
11009
11870
|
const gitignorePatterns = [];
|
|
11010
11871
|
try {
|
|
11011
|
-
const gitignorePath =
|
|
11872
|
+
const gitignorePath = join19(cwd, ".gitignore");
|
|
11012
11873
|
const stats = statSync3(gitignorePath);
|
|
11013
11874
|
if (stats.size > MAX_GITIGNORE_SIZE) {
|
|
11014
11875
|
return hardcoded;
|
|
@@ -11082,6 +11943,26 @@ function openBrowser(url) {
|
|
|
11082
11943
|
const child = spawn4(cmd, [url], { detached: true, stdio: "ignore" });
|
|
11083
11944
|
child.unref();
|
|
11084
11945
|
}
|
|
11946
|
+
function detectGitHubRepo(cachedRepo) {
|
|
11947
|
+
if (cachedRepo) {
|
|
11948
|
+
const parts = cachedRepo.split("/");
|
|
11949
|
+
if (parts.length === 2) return { owner: parts[0], name: parts[1] };
|
|
11950
|
+
}
|
|
11951
|
+
try {
|
|
11952
|
+
const remoteUrl = execSync2("git remote get-url origin", { cwd: process.cwd(), encoding: "utf8" }).trim();
|
|
11953
|
+
const httpsMatch = remoteUrl.match(/github\.com\/([^\/]+)\/([^\/]+?)(?:\.git)?$/);
|
|
11954
|
+
if (httpsMatch) return { owner: httpsMatch[1], name: httpsMatch[2] };
|
|
11955
|
+
const sshMatch = remoteUrl.match(/github\.com:([^\/]+)\/([^\/]+?)(?:\.git)?$/);
|
|
11956
|
+
if (sshMatch) return { owner: sshMatch[1], name: sshMatch[2] };
|
|
11957
|
+
} catch {
|
|
11958
|
+
}
|
|
11959
|
+
return null;
|
|
11960
|
+
}
|
|
11961
|
+
function formatTokens3(n) {
|
|
11962
|
+
if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
|
|
11963
|
+
if (n >= 1e3) return `${(n / 1e3).toFixed(1)}K`;
|
|
11964
|
+
return String(n);
|
|
11965
|
+
}
|
|
11085
11966
|
function capEvents(prev) {
|
|
11086
11967
|
if (prev.length <= MAX_EVENTS) return prev;
|
|
11087
11968
|
return prev.slice(prev.length - MAX_EVENTS);
|
|
@@ -11144,10 +12025,10 @@ function App({
|
|
|
11144
12025
|
initialLspProjectPath
|
|
11145
12026
|
}) {
|
|
11146
12027
|
const { exit } = useApp();
|
|
11147
|
-
const [cfg, setCfg] =
|
|
11148
|
-
const [lspScope, setLspScope] =
|
|
11149
|
-
const [lspProjectPath, setLspProjectPath] =
|
|
11150
|
-
const [events, setRawEvents] =
|
|
12028
|
+
const [cfg, setCfg] = useState10(initialCfg);
|
|
12029
|
+
const [lspScope, setLspScope] = useState10(initialLspScope);
|
|
12030
|
+
const [lspProjectPath, setLspProjectPath] = useState10(initialLspProjectPath);
|
|
12031
|
+
const [events, setRawEvents] = useState10([]);
|
|
11151
12032
|
const setEvents = useCallback(
|
|
11152
12033
|
(updater) => {
|
|
11153
12034
|
setRawEvents((prev) => {
|
|
@@ -11157,45 +12038,47 @@ function App({
|
|
|
11157
12038
|
},
|
|
11158
12039
|
[]
|
|
11159
12040
|
);
|
|
11160
|
-
const [input, setInput] =
|
|
11161
|
-
const [busy, setBusy] =
|
|
11162
|
-
const [usage, setUsage] =
|
|
11163
|
-
const [sessionUsage, setSessionUsage] =
|
|
11164
|
-
const [gatewayMeta, setGatewayMeta] =
|
|
11165
|
-
const [showReasoning, setShowReasoning] =
|
|
11166
|
-
const [perm, setPerm] =
|
|
11167
|
-
const [queue, setQueue] =
|
|
11168
|
-
const [history, setHistory] =
|
|
11169
|
-
const [historyIndex, setHistoryIndex] =
|
|
11170
|
-
const [draftInput, setDraftInput] =
|
|
11171
|
-
const [mode, setMode] =
|
|
11172
|
-
const [codeMode, setCodeMode] =
|
|
12041
|
+
const [input, setInput] = useState10("");
|
|
12042
|
+
const [busy, setBusy] = useState10(false);
|
|
12043
|
+
const [usage, setUsage] = useState10(null);
|
|
12044
|
+
const [sessionUsage, setSessionUsage] = useState10(null);
|
|
12045
|
+
const [gatewayMeta, setGatewayMeta] = useState10(null);
|
|
12046
|
+
const [showReasoning, setShowReasoning] = useState10(false);
|
|
12047
|
+
const [perm, setPerm] = useState10(null);
|
|
12048
|
+
const [queue, setQueue] = useState10([]);
|
|
12049
|
+
const [history, setHistory] = useState10([]);
|
|
12050
|
+
const [historyIndex, setHistoryIndex] = useState10(-1);
|
|
12051
|
+
const [draftInput, setDraftInput] = useState10("");
|
|
12052
|
+
const [mode, setMode] = useState10("edit");
|
|
12053
|
+
const [codeMode, setCodeMode] = useState10(false);
|
|
11173
12054
|
const filePickerEnabled = initialCfg?.filePicker ?? true;
|
|
11174
|
-
const [effort, setEffort] =
|
|
12055
|
+
const [effort, setEffort] = useState10(
|
|
11175
12056
|
initialCfg?.reasoningEffort ?? DEFAULT_REASONING_EFFORT
|
|
11176
12057
|
);
|
|
11177
|
-
const [resumeSessions, setResumeSessions] =
|
|
11178
|
-
const [showHelpMenu, setShowHelpMenu] =
|
|
11179
|
-
const [commandWizard, setCommandWizard] =
|
|
11180
|
-
const [commandPicker, setCommandPicker] =
|
|
11181
|
-
const [commandToDelete, setCommandToDelete] =
|
|
11182
|
-
const [showCommandList, setShowCommandList] =
|
|
11183
|
-
const [showLspWizard, setShowLspWizard] =
|
|
11184
|
-
const [
|
|
11185
|
-
const [
|
|
11186
|
-
const [
|
|
11187
|
-
const [
|
|
11188
|
-
const [
|
|
11189
|
-
const [
|
|
11190
|
-
const [
|
|
11191
|
-
const [
|
|
11192
|
-
const [
|
|
11193
|
-
const [
|
|
11194
|
-
const [
|
|
11195
|
-
const [
|
|
11196
|
-
const [
|
|
12058
|
+
const [resumeSessions, setResumeSessions] = useState10(null);
|
|
12059
|
+
const [showHelpMenu, setShowHelpMenu] = useState10(false);
|
|
12060
|
+
const [commandWizard, setCommandWizard] = useState10(null);
|
|
12061
|
+
const [commandPicker, setCommandPicker] = useState10(null);
|
|
12062
|
+
const [commandToDelete, setCommandToDelete] = useState10(null);
|
|
12063
|
+
const [showCommandList, setShowCommandList] = useState10(false);
|
|
12064
|
+
const [showLspWizard, setShowLspWizard] = useState10(false);
|
|
12065
|
+
const [showRemoteDashboard, setShowRemoteDashboard] = useState10(false);
|
|
12066
|
+
const [selectedRemoteSession, setSelectedRemoteSession] = useState10(null);
|
|
12067
|
+
const [tasks, setTasks] = useState10([]);
|
|
12068
|
+
const [tasksStartedAt, setTasksStartedAt] = useState10(null);
|
|
12069
|
+
const [tasksStartTokens, setTasksStartTokens] = useState10(0);
|
|
12070
|
+
const [turnStartedAt, setTurnStartedAt] = useState10(null);
|
|
12071
|
+
const [verbose, setVerbose] = useState10(false);
|
|
12072
|
+
const [hasUpdate, setHasUpdate] = useState10(initialUpdateResult?.hasUpdate ?? false);
|
|
12073
|
+
const [latestVersion, setLatestVersion] = useState10(initialUpdateResult?.latestVersion ?? null);
|
|
12074
|
+
const [theme, setTheme] = useState10(resolveTheme(initialCfg?.theme));
|
|
12075
|
+
const [showThemePicker, setShowThemePicker] = useState10(false);
|
|
12076
|
+
const [originalTheme, setOriginalTheme] = useState10(null);
|
|
12077
|
+
const [cursorOffset, setCursorOffset] = useState10(0);
|
|
12078
|
+
const [activePicker, setActivePicker] = useState10(null);
|
|
12079
|
+
const [filePickerItems, setFilePickerItems] = useState10([]);
|
|
11197
12080
|
const filePickerLoadedRef = useRef3(false);
|
|
11198
|
-
const [customCommandsVersion, setCustomCommandsVersion] =
|
|
12081
|
+
const [customCommandsVersion, setCustomCommandsVersion] = useState10(0);
|
|
11199
12082
|
const cacheStableRef = useRef3(initialCfg?.cacheStablePrompts !== false);
|
|
11200
12083
|
const messagesRef = useRef3(
|
|
11201
12084
|
makePrefixMessages(cacheStableRef.current, cfg?.model ?? DEFAULT_MODEL, "edit", ALL_TOOLS)
|
|
@@ -11233,15 +12116,15 @@ function App({
|
|
|
11233
12116
|
const pickerCancelRef = useRef3(null);
|
|
11234
12117
|
const pickerAnchor = activePicker?.anchor ?? null;
|
|
11235
12118
|
const pickerKind = activePicker?.kind ?? null;
|
|
11236
|
-
const pickerQuery =
|
|
12119
|
+
const pickerQuery = React14.useMemo(() => {
|
|
11237
12120
|
if (pickerAnchor === null) return null;
|
|
11238
12121
|
return input.slice(pickerAnchor + 1, cursorOffset);
|
|
11239
12122
|
}, [input, cursorOffset, pickerAnchor]);
|
|
11240
|
-
const filteredFileItems =
|
|
12123
|
+
const filteredFileItems = React14.useMemo(() => {
|
|
11241
12124
|
if (pickerKind !== "file" || pickerQuery === null) return [];
|
|
11242
12125
|
return filterPickerItems(filePickerItems, pickerQuery);
|
|
11243
12126
|
}, [pickerKind, filePickerItems, pickerQuery]);
|
|
11244
|
-
const allSlashCommands =
|
|
12127
|
+
const allSlashCommands = React14.useMemo(() => {
|
|
11245
12128
|
const customs = customCommandsRef.current.filter((c) => !BUILTIN_COMMAND_NAMES.has(c.name.toLowerCase())).map((c) => ({
|
|
11246
12129
|
name: c.name,
|
|
11247
12130
|
description: c.description ?? "",
|
|
@@ -11249,11 +12132,11 @@ function App({
|
|
|
11249
12132
|
}));
|
|
11250
12133
|
return [...BUILTIN_COMMANDS, ...customs];
|
|
11251
12134
|
}, [customCommandsVersion]);
|
|
11252
|
-
const filteredSlashItems =
|
|
12135
|
+
const filteredSlashItems = React14.useMemo(() => {
|
|
11253
12136
|
if (pickerKind !== "slash" || pickerQuery === null) return [];
|
|
11254
12137
|
return fuzzyFilter(allSlashCommands, pickerQuery, (c) => c.name).slice(0, 50);
|
|
11255
12138
|
}, [pickerKind, allSlashCommands, pickerQuery]);
|
|
11256
|
-
|
|
12139
|
+
useEffect5(() => {
|
|
11257
12140
|
if (activePicker !== null) {
|
|
11258
12141
|
const trigger = activePicker.kind === "file" ? "@" : "/";
|
|
11259
12142
|
if (cursorOffset < activePicker.anchor) {
|
|
@@ -11310,14 +12193,14 @@ function App({
|
|
|
11310
12193
|
return;
|
|
11311
12194
|
}
|
|
11312
12195
|
}, [input, cursorOffset, activePicker, filePickerEnabled]);
|
|
11313
|
-
|
|
12196
|
+
useEffect5(() => {
|
|
11314
12197
|
if (activePicker?.kind !== "file") return;
|
|
11315
12198
|
const max = Math.max(0, filteredFileItems.length - 1);
|
|
11316
12199
|
if (activePicker.selected > max) {
|
|
11317
12200
|
setActivePicker({ ...activePicker, selected: max });
|
|
11318
12201
|
}
|
|
11319
12202
|
}, [filteredFileItems.length, activePicker]);
|
|
11320
|
-
|
|
12203
|
+
useEffect5(() => {
|
|
11321
12204
|
if (activePicker?.kind !== "slash") return;
|
|
11322
12205
|
const max = Math.max(0, filteredSlashItems.length - 1);
|
|
11323
12206
|
if (activePicker.selected > max) {
|
|
@@ -11361,7 +12244,7 @@ function App({
|
|
|
11361
12244
|
pickerCancelRef.current = cursorOffset;
|
|
11362
12245
|
setActivePicker(null);
|
|
11363
12246
|
}, [cursorOffset]);
|
|
11364
|
-
|
|
12247
|
+
useEffect5(() => {
|
|
11365
12248
|
const modalActive = showHelpMenu || commandWizard !== null || commandPicker !== null || commandToDelete !== null || showCommandList || showLspWizard || resumeSessions !== null || perm !== null;
|
|
11366
12249
|
if (modalActive && activePicker !== null) {
|
|
11367
12250
|
setActivePicker(null);
|
|
@@ -11377,7 +12260,7 @@ function App({
|
|
|
11377
12260
|
perm,
|
|
11378
12261
|
activePicker
|
|
11379
12262
|
]);
|
|
11380
|
-
|
|
12263
|
+
useEffect5(() => {
|
|
11381
12264
|
if (!cfg) return;
|
|
11382
12265
|
void Promise.resolve().then(() => (init_sessions(), sessions_exports)).then(
|
|
11383
12266
|
({ pruneSessions: pruneSessions2 }) => pruneSessions2().then((removed) => {
|
|
@@ -11403,13 +12286,14 @@ function App({
|
|
|
11403
12286
|
}
|
|
11404
12287
|
});
|
|
11405
12288
|
if (cfg.memoryEnabled) {
|
|
11406
|
-
const dbPath = cfg.memoryDbPath ??
|
|
12289
|
+
const dbPath = cfg.memoryDbPath ?? join19(process.cwd(), ".kimiflare", "memory.db");
|
|
11407
12290
|
const manager = new MemoryManager({
|
|
11408
12291
|
dbPath,
|
|
11409
12292
|
accountId: cfg.accountId,
|
|
11410
12293
|
apiToken: cfg.apiToken,
|
|
11411
12294
|
model: cfg.model,
|
|
11412
12295
|
plumbingModel: cfg.plumbingModel,
|
|
12296
|
+
extractionModel: cfg.memoryExtractionModel,
|
|
11413
12297
|
embeddingModel: cfg.memoryEmbeddingModel,
|
|
11414
12298
|
gateway: gatewayFromConfig(cfg),
|
|
11415
12299
|
maxAgeDays: cfg.memoryMaxAgeDays ?? RETENTION.memoryMaxAgeDays,
|
|
@@ -11470,7 +12354,7 @@ function App({
|
|
|
11470
12354
|
}
|
|
11471
12355
|
});
|
|
11472
12356
|
}, [cfg, setEvents]);
|
|
11473
|
-
|
|
12357
|
+
useEffect5(() => {
|
|
11474
12358
|
const id = setInterval(() => {
|
|
11475
12359
|
try {
|
|
11476
12360
|
performance.clearMarks();
|
|
@@ -11495,7 +12379,7 @@ function App({
|
|
|
11495
12379
|
]);
|
|
11496
12380
|
}
|
|
11497
12381
|
}, [setEvents]);
|
|
11498
|
-
|
|
12382
|
+
useEffect5(() => {
|
|
11499
12383
|
if (!cfg || updateCheckedRef.current) return;
|
|
11500
12384
|
updateCheckedRef.current = true;
|
|
11501
12385
|
if (initialUpdateResult) {
|
|
@@ -11546,7 +12430,7 @@ function App({
|
|
|
11546
12430
|
}
|
|
11547
12431
|
});
|
|
11548
12432
|
}, [cfg, initialUpdateResult]);
|
|
11549
|
-
|
|
12433
|
+
useEffect5(() => {
|
|
11550
12434
|
modeRef.current = mode;
|
|
11551
12435
|
if (cacheStableRef.current) {
|
|
11552
12436
|
messagesRef.current[1] = {
|
|
@@ -11573,10 +12457,10 @@ function App({
|
|
|
11573
12457
|
executorRef.current.clearSessionPermissions();
|
|
11574
12458
|
}
|
|
11575
12459
|
}, [mode, cfg?.model]);
|
|
11576
|
-
|
|
12460
|
+
useEffect5(() => {
|
|
11577
12461
|
effortRef.current = effort;
|
|
11578
12462
|
}, [effort]);
|
|
11579
|
-
|
|
12463
|
+
useEffect5(() => {
|
|
11580
12464
|
if (!cfg) return;
|
|
11581
12465
|
const id = setInterval(() => {
|
|
11582
12466
|
void checkForUpdate().then((result) => {
|
|
@@ -11731,7 +12615,7 @@ function App({
|
|
|
11731
12615
|
]);
|
|
11732
12616
|
}
|
|
11733
12617
|
}, [cfg]);
|
|
11734
|
-
|
|
12618
|
+
useEffect5(() => {
|
|
11735
12619
|
if (cfg && !mcpInitRef.current) {
|
|
11736
12620
|
void initMcp();
|
|
11737
12621
|
}
|
|
@@ -11769,7 +12653,85 @@ function App({
|
|
|
11769
12653
|
} catch {
|
|
11770
12654
|
}
|
|
11771
12655
|
}, [cfg, ensureSessionId]);
|
|
11772
|
-
|
|
12656
|
+
const onIterationEnd = useCallback(
|
|
12657
|
+
async (messages, signal) => {
|
|
12658
|
+
if (signal.aborted) return messages;
|
|
12659
|
+
if (!shouldCompact({ messages })) return messages;
|
|
12660
|
+
if (compiledContextRef.current) {
|
|
12661
|
+
const store = artifactStoreRef.current;
|
|
12662
|
+
const result = compactMessages2({
|
|
12663
|
+
messages,
|
|
12664
|
+
state: sessionStateRef.current,
|
|
12665
|
+
store
|
|
12666
|
+
});
|
|
12667
|
+
if (result.metrics.rawTurnsRemoved > 0) {
|
|
12668
|
+
sessionStateRef.current = result.newState;
|
|
12669
|
+
setEvents((e) => [
|
|
12670
|
+
...e,
|
|
12671
|
+
{
|
|
12672
|
+
kind: "info",
|
|
12673
|
+
key: mkKey(),
|
|
12674
|
+
text: `auto-compacted: ${result.metrics.estimatedTokensBefore} \u2192 ${result.metrics.estimatedTokensAfter} tokens (${result.metrics.archivedArtifacts} artifacts)`
|
|
12675
|
+
}
|
|
12676
|
+
]);
|
|
12677
|
+
await saveSessionSafe();
|
|
12678
|
+
}
|
|
12679
|
+
const manager = memoryManagerRef.current;
|
|
12680
|
+
if (manager && !signal.aborted) {
|
|
12681
|
+
try {
|
|
12682
|
+
const cwd = process.cwd();
|
|
12683
|
+
const queryText = sessionStateRef.current.task || cwd;
|
|
12684
|
+
const results = await manager.recall({ text: queryText, repoPath: cwd, limit: 5 });
|
|
12685
|
+
if (results.length > 0 && !signal.aborted) {
|
|
12686
|
+
const text = await manager.synthesizeRecalled(results);
|
|
12687
|
+
const lastSystemIdx = result.newMessages.findLastIndex((m) => m.role === "system");
|
|
12688
|
+
const insertIdx = lastSystemIdx >= 0 ? lastSystemIdx + 1 : result.newMessages.length;
|
|
12689
|
+
result.newMessages.splice(insertIdx, 0, { role: "system", content: text });
|
|
12690
|
+
setEvents((e) => [
|
|
12691
|
+
...e,
|
|
12692
|
+
{
|
|
12693
|
+
kind: "memory",
|
|
12694
|
+
key: mkKey(),
|
|
12695
|
+
text: `recalled ${results.length} memory${results.length === 1 ? "" : "ies"} after compaction`
|
|
12696
|
+
}
|
|
12697
|
+
]);
|
|
12698
|
+
await saveSessionSafe();
|
|
12699
|
+
}
|
|
12700
|
+
} catch {
|
|
12701
|
+
}
|
|
12702
|
+
}
|
|
12703
|
+
return result.newMessages;
|
|
12704
|
+
}
|
|
12705
|
+
if (cfg && !signal.aborted) {
|
|
12706
|
+
try {
|
|
12707
|
+
const result = await compactMessages({
|
|
12708
|
+
accountId: cfg.accountId,
|
|
12709
|
+
apiToken: cfg.apiToken,
|
|
12710
|
+
model: cfg.model,
|
|
12711
|
+
messages,
|
|
12712
|
+
signal,
|
|
12713
|
+
gateway: gatewayFromConfig(cfg)
|
|
12714
|
+
});
|
|
12715
|
+
if (result.replacedCount > 0) {
|
|
12716
|
+
setEvents((e) => [
|
|
12717
|
+
...e,
|
|
12718
|
+
{
|
|
12719
|
+
kind: "info",
|
|
12720
|
+
key: mkKey(),
|
|
12721
|
+
text: `auto-compacted: ${result.replacedCount} messages summarized`
|
|
12722
|
+
}
|
|
12723
|
+
]);
|
|
12724
|
+
await saveSessionSafe();
|
|
12725
|
+
}
|
|
12726
|
+
return result.newMessages;
|
|
12727
|
+
} catch {
|
|
12728
|
+
}
|
|
12729
|
+
}
|
|
12730
|
+
return messages;
|
|
12731
|
+
},
|
|
12732
|
+
[cfg]
|
|
12733
|
+
);
|
|
12734
|
+
useInput6((inputChar, key) => {
|
|
11773
12735
|
if (key.ctrl && inputChar === "c") {
|
|
11774
12736
|
const hadPerm = permResolveRef.current !== null;
|
|
11775
12737
|
if (hadPerm) {
|
|
@@ -11812,10 +12774,6 @@ function App({
|
|
|
11812
12774
|
setVerbose((v) => !v);
|
|
11813
12775
|
return;
|
|
11814
12776
|
}
|
|
11815
|
-
if (key.ctrl && inputChar === "m") {
|
|
11816
|
-
setCodeMode((c) => !c);
|
|
11817
|
-
return;
|
|
11818
|
-
}
|
|
11819
12777
|
});
|
|
11820
12778
|
const flushAssistantUpdates = useCallback(() => {
|
|
11821
12779
|
flushTimeoutRef.current = null;
|
|
@@ -11967,7 +12925,7 @@ function App({
|
|
|
11967
12925
|
}
|
|
11968
12926
|
}, [cfg, busy, saveSessionSafe]);
|
|
11969
12927
|
const openResumePicker = useCallback(async () => {
|
|
11970
|
-
const sessions = await listSessions(200);
|
|
12928
|
+
const sessions = await listSessions(200, process.cwd());
|
|
11971
12929
|
setResumeSessions(sessions);
|
|
11972
12930
|
}, []);
|
|
11973
12931
|
const runInit = useCallback(async () => {
|
|
@@ -11977,7 +12935,7 @@ function App({
|
|
|
11977
12935
|
return;
|
|
11978
12936
|
}
|
|
11979
12937
|
const cwd = process.cwd();
|
|
11980
|
-
const existingName = ["KIMI.md", "KIMIFLARE.md", "AGENT.md"].find((n) => existsSync2(
|
|
12938
|
+
const existingName = ["KIMI.md", "KIMIFLARE.md", "AGENT.md"].find((n) => existsSync2(join19(cwd, n)));
|
|
11981
12939
|
const isRefresh = existingName !== void 0;
|
|
11982
12940
|
const promptParts = [
|
|
11983
12941
|
isRefresh ? `Regenerate ${existingName} at the repository root to refresh project context. If the file already exists, read it first and preserve anything still accurate, updating only what has changed.` : "Generate a KIMI.md at the repository root so future agents have project context.",
|
|
@@ -12002,6 +12960,15 @@ function App({
|
|
|
12002
12960
|
setTurnStartedAt(Date.now());
|
|
12003
12961
|
const controller = new AbortController();
|
|
12004
12962
|
activeControllerRef.current = controller;
|
|
12963
|
+
const initClassification = classifyIntent(prompt);
|
|
12964
|
+
const initEffortForTier = {
|
|
12965
|
+
light: "low",
|
|
12966
|
+
medium: "medium",
|
|
12967
|
+
heavy: "high"
|
|
12968
|
+
};
|
|
12969
|
+
const initReasoningEffort = initEffortForTier[initClassification.tier] ?? effortRef.current;
|
|
12970
|
+
const effectiveCodeMode = initClassification.tier === "heavy";
|
|
12971
|
+
setCodeMode(effectiveCodeMode);
|
|
12005
12972
|
try {
|
|
12006
12973
|
await runAgentTurn({
|
|
12007
12974
|
accountId: cfg.accountId,
|
|
@@ -12013,17 +12980,19 @@ function App({
|
|
|
12013
12980
|
executor: executorRef.current,
|
|
12014
12981
|
cwd,
|
|
12015
12982
|
signal: controller.signal,
|
|
12016
|
-
reasoningEffort:
|
|
12983
|
+
reasoningEffort: initReasoningEffort,
|
|
12984
|
+
intentClassification: initClassification,
|
|
12017
12985
|
coauthor: cfg.coauthor !== false ? { name: cfg.coauthorName || "kimiflare", email: cfg.coauthorEmail || "kimiflare@proton.me" } : void 0,
|
|
12018
12986
|
sessionId: ensureSessionId(),
|
|
12019
12987
|
memoryManager: memoryManagerRef.current,
|
|
12020
|
-
codeMode,
|
|
12988
|
+
codeMode: effectiveCodeMode,
|
|
12989
|
+
onIterationEnd,
|
|
12021
12990
|
onFileChange: (path, content) => {
|
|
12022
12991
|
if (content) {
|
|
12023
12992
|
lspManagerRef.current.notifyChange(path, content);
|
|
12024
12993
|
} else {
|
|
12025
12994
|
void import("fs/promises").then(
|
|
12026
|
-
({ readFile:
|
|
12995
|
+
({ readFile: readFile16 }) => readFile16(path, "utf8").then((c) => lspManagerRef.current.notifyChange(path, c)).catch(() => {
|
|
12027
12996
|
})
|
|
12028
12997
|
);
|
|
12029
12998
|
}
|
|
@@ -12117,7 +13086,7 @@ function App({
|
|
|
12117
13086
|
})
|
|
12118
13087
|
}
|
|
12119
13088
|
});
|
|
12120
|
-
if (existsSync2(
|
|
13089
|
+
if (existsSync2(join19(cwd, "KIMI.md"))) {
|
|
12121
13090
|
if (cacheStableRef.current) {
|
|
12122
13091
|
messagesRef.current[1] = {
|
|
12123
13092
|
role: "system",
|
|
@@ -12164,6 +13133,7 @@ function App({
|
|
|
12164
13133
|
]);
|
|
12165
13134
|
}
|
|
12166
13135
|
} finally {
|
|
13136
|
+
setCodeMode(false);
|
|
12167
13137
|
const asstId = activeAsstIdRef.current;
|
|
12168
13138
|
if (asstId !== null) updateAssistant(asstId, () => ({ streaming: false }));
|
|
12169
13139
|
setBusy(false);
|
|
@@ -12774,13 +13744,177 @@ ${lines.join("\n")}` }]);
|
|
|
12774
13744
|
]);
|
|
12775
13745
|
return true;
|
|
12776
13746
|
}
|
|
13747
|
+
if (c === "/remote") {
|
|
13748
|
+
if (arg === "status" || arg === "cancel") {
|
|
13749
|
+
setEvents((e) => [
|
|
13750
|
+
...e,
|
|
13751
|
+
{ kind: "info", key: mkKey(), text: `Use \`kimiflare remote ${arg}\` from your shell.` }
|
|
13752
|
+
]);
|
|
13753
|
+
return true;
|
|
13754
|
+
}
|
|
13755
|
+
const prompt = rest.join(" ").trim();
|
|
13756
|
+
if (!prompt) {
|
|
13757
|
+
setShowRemoteDashboard(true);
|
|
13758
|
+
return true;
|
|
13759
|
+
}
|
|
13760
|
+
const repo = detectGitHubRepo(cfg?.githubRepo);
|
|
13761
|
+
if (!repo) {
|
|
13762
|
+
setEvents((e) => [
|
|
13763
|
+
...e,
|
|
13764
|
+
{ kind: "info", key: mkKey(), text: "Could not detect GitHub repo. Run from a repo with a GitHub remote, or set githubRepo in config." }
|
|
13765
|
+
]);
|
|
13766
|
+
return true;
|
|
13767
|
+
}
|
|
13768
|
+
(async () => {
|
|
13769
|
+
if (!cfg?.remoteWorkerUrl) {
|
|
13770
|
+
setEvents((e) => [
|
|
13771
|
+
...e,
|
|
13772
|
+
{ kind: "info", key: mkKey(), text: "Remote infrastructure not deployed yet. Setting up now (~2 min)..." }
|
|
13773
|
+
]);
|
|
13774
|
+
try {
|
|
13775
|
+
for await (const step of deployForTui()) {
|
|
13776
|
+
setEvents((e) => [
|
|
13777
|
+
...e,
|
|
13778
|
+
{ kind: step.error ? "error" : "info", key: mkKey(), text: step.message }
|
|
13779
|
+
]);
|
|
13780
|
+
if (step.done) break;
|
|
13781
|
+
}
|
|
13782
|
+
} catch {
|
|
13783
|
+
setEvents((e) => [
|
|
13784
|
+
...e,
|
|
13785
|
+
{ kind: "error", key: mkKey(), text: "Deploy failed. Fix the issue above and try /remote again." }
|
|
13786
|
+
]);
|
|
13787
|
+
return;
|
|
13788
|
+
}
|
|
13789
|
+
const { loadConfig: reloadConfig } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
13790
|
+
const newCfg = await reloadConfig();
|
|
13791
|
+
if (newCfg) setCfg(newCfg);
|
|
13792
|
+
}
|
|
13793
|
+
const currentCfg = cfg ?? await loadConfig();
|
|
13794
|
+
if (!currentCfg?.remoteWorkerUrl) {
|
|
13795
|
+
setEvents((e) => [
|
|
13796
|
+
...e,
|
|
13797
|
+
{ kind: "error", key: mkKey(), text: "Deploy seemed to succeed but config wasn't saved. Try again." }
|
|
13798
|
+
]);
|
|
13799
|
+
return;
|
|
13800
|
+
}
|
|
13801
|
+
if (!currentCfg.githubOAuthToken) {
|
|
13802
|
+
setEvents((e) => [
|
|
13803
|
+
...e,
|
|
13804
|
+
{ kind: "info", key: mkKey(), text: "GitHub not authenticated. Starting OAuth device flow..." }
|
|
13805
|
+
]);
|
|
13806
|
+
try {
|
|
13807
|
+
for await (const step of authGitHubForTui()) {
|
|
13808
|
+
setEvents((e) => [
|
|
13809
|
+
...e,
|
|
13810
|
+
{ kind: step.error ? "error" : "info", key: mkKey(), text: step.message }
|
|
13811
|
+
]);
|
|
13812
|
+
if (step.done) break;
|
|
13813
|
+
}
|
|
13814
|
+
} catch {
|
|
13815
|
+
setEvents((e) => [
|
|
13816
|
+
...e,
|
|
13817
|
+
{ kind: "error", key: mkKey(), text: "GitHub auth failed. Try `kimiflare auth github` from shell." }
|
|
13818
|
+
]);
|
|
13819
|
+
return;
|
|
13820
|
+
}
|
|
13821
|
+
const { loadConfig: reloadConfig } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
13822
|
+
const newCfg = await reloadConfig();
|
|
13823
|
+
if (newCfg) setCfg(newCfg);
|
|
13824
|
+
}
|
|
13825
|
+
const finalCfg = await loadConfig() ?? currentCfg;
|
|
13826
|
+
const ttl = finalCfg.remoteTtlMinutes ?? 30;
|
|
13827
|
+
const budget = finalCfg.remoteMaxInputTokens ?? 5e6;
|
|
13828
|
+
setEvents((e) => [
|
|
13829
|
+
...e,
|
|
13830
|
+
{ kind: "info", key: mkKey(), text: `Starting remote session for ${repo.owner}/${repo.name}...` },
|
|
13831
|
+
{ kind: "info", key: mkKey(), text: `Budget: ${formatTokens3(budget)} tokens. TTL: ${ttl} min.` }
|
|
13832
|
+
]);
|
|
13833
|
+
try {
|
|
13834
|
+
const data = await startRemoteSession({
|
|
13835
|
+
prompt,
|
|
13836
|
+
repo,
|
|
13837
|
+
cfg: finalCfg,
|
|
13838
|
+
ttlMinutes: finalCfg.remoteTtlMinutes,
|
|
13839
|
+
tokensBudget: finalCfg.remoteMaxInputTokens
|
|
13840
|
+
});
|
|
13841
|
+
setEvents((e) => [
|
|
13842
|
+
...e,
|
|
13843
|
+
{ kind: "info", key: mkKey(), text: `Session started: ${data.sessionId}` }
|
|
13844
|
+
]);
|
|
13845
|
+
for await (const ev of streamRemoteProgress(
|
|
13846
|
+
finalCfg.remoteWorkerUrl,
|
|
13847
|
+
data.sessionId,
|
|
13848
|
+
activeControllerRef.current?.signal
|
|
13849
|
+
)) {
|
|
13850
|
+
const event = ev;
|
|
13851
|
+
if (event.type === "text_delta") {
|
|
13852
|
+
setEvents((e) => [
|
|
13853
|
+
...e,
|
|
13854
|
+
{ kind: "info", key: mkKey(), text: String(event.text ?? "") }
|
|
13855
|
+
]);
|
|
13856
|
+
} else if (event.type === "tool_call") {
|
|
13857
|
+
setEvents((e) => [
|
|
13858
|
+
...e,
|
|
13859
|
+
{ kind: "info", key: mkKey(), text: `\u2192 ${String(event.name ?? "")}` }
|
|
13860
|
+
]);
|
|
13861
|
+
} else if (event.type === "done") {
|
|
13862
|
+
const prUrl = event.prUrl;
|
|
13863
|
+
const tokensUsed = event.tokensUsed;
|
|
13864
|
+
const tokensBudget = event.tokensBudget;
|
|
13865
|
+
setEvents((e) => [
|
|
13866
|
+
...e,
|
|
13867
|
+
{ kind: "info", key: mkKey(), text: prUrl ? `Done \u2014 PR: ${prUrl}` : "Done" }
|
|
13868
|
+
]);
|
|
13869
|
+
await saveRemoteSession({
|
|
13870
|
+
sessionId: data.sessionId,
|
|
13871
|
+
prompt,
|
|
13872
|
+
repo: `${repo.owner}/${repo.name}`,
|
|
13873
|
+
workerUrl: finalCfg.remoteWorkerUrl,
|
|
13874
|
+
status: "done",
|
|
13875
|
+
prUrl,
|
|
13876
|
+
tokensUsed,
|
|
13877
|
+
tokensBudget,
|
|
13878
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
13879
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
13880
|
+
});
|
|
13881
|
+
} else if (event.type === "error") {
|
|
13882
|
+
const message2 = String(event.message ?? "");
|
|
13883
|
+
const category = event.category;
|
|
13884
|
+
setEvents((e) => [
|
|
13885
|
+
...e,
|
|
13886
|
+
{ kind: "error", key: mkKey(), text: `Remote error: ${message2}` }
|
|
13887
|
+
]);
|
|
13888
|
+
await saveRemoteSession({
|
|
13889
|
+
sessionId: data.sessionId,
|
|
13890
|
+
prompt,
|
|
13891
|
+
repo: `${repo.owner}/${repo.name}`,
|
|
13892
|
+
workerUrl: finalCfg.remoteWorkerUrl,
|
|
13893
|
+
status: "error",
|
|
13894
|
+
errorCategory: category ?? "unknown",
|
|
13895
|
+
errorSummary: message2,
|
|
13896
|
+
errorMessage: message2,
|
|
13897
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
13898
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
13899
|
+
});
|
|
13900
|
+
}
|
|
13901
|
+
}
|
|
13902
|
+
} catch (err) {
|
|
13903
|
+
setEvents((e) => [
|
|
13904
|
+
...e,
|
|
13905
|
+
{ kind: "error", key: mkKey(), text: `Failed: ${err instanceof Error ? err.message : String(err)}` }
|
|
13906
|
+
]);
|
|
13907
|
+
}
|
|
13908
|
+
})();
|
|
13909
|
+
return true;
|
|
13910
|
+
}
|
|
12777
13911
|
if (c === "/help") {
|
|
12778
13912
|
setShowHelpMenu(true);
|
|
12779
13913
|
return true;
|
|
12780
13914
|
}
|
|
12781
13915
|
return false;
|
|
12782
13916
|
},
|
|
12783
|
-
[cfg, exit, usage, effort, theme, mode, openResumePicker, runCompact, runInit, initMcp, setCfg]
|
|
13917
|
+
[cfg, exit, usage, effort, theme, mode, openResumePicker, runCompact, runInit, initMcp, setCfg, setShowRemoteDashboard, setSelectedRemoteSession]
|
|
12784
13918
|
);
|
|
12785
13919
|
const handleHelpCommand = useCallback(
|
|
12786
13920
|
(command) => {
|
|
@@ -12923,6 +14057,15 @@ ${lines.join("\n")}` }]);
|
|
|
12923
14057
|
gatewayMetaRef.current = null;
|
|
12924
14058
|
setGatewayMeta(null);
|
|
12925
14059
|
setTurnStartedAt(Date.now());
|
|
14060
|
+
const classification = classifyIntent(trimmed);
|
|
14061
|
+
const effortForTier = {
|
|
14062
|
+
light: "low",
|
|
14063
|
+
medium: "medium",
|
|
14064
|
+
heavy: "high"
|
|
14065
|
+
};
|
|
14066
|
+
const turnReasoningEffort = overrideEffort ?? effortForTier[classification.tier] ?? effortRef.current;
|
|
14067
|
+
const effectiveCodeMode = classification.tier === "heavy";
|
|
14068
|
+
setCodeMode(effectiveCodeMode);
|
|
12926
14069
|
const controller = new AbortController();
|
|
12927
14070
|
activeControllerRef.current = controller;
|
|
12928
14071
|
const sharedCallbacks = {
|
|
@@ -13036,18 +14179,20 @@ ${lines.join("\n")}` }]);
|
|
|
13036
14179
|
executor: executorRef.current,
|
|
13037
14180
|
cwd: process.cwd(),
|
|
13038
14181
|
signal: controller.signal,
|
|
13039
|
-
reasoningEffort:
|
|
14182
|
+
reasoningEffort: turnReasoningEffort,
|
|
13040
14183
|
coauthor: cfg.coauthor !== false ? { name: cfg.coauthorName || "kimiflare", email: cfg.coauthorEmail || "kimiflare@proton.me" } : void 0,
|
|
13041
14184
|
sessionId: ensureSessionId(),
|
|
13042
14185
|
memoryManager: memoryManagerRef.current,
|
|
13043
14186
|
keepLastImageTurns: cfg.imageHistoryTurns ?? 2,
|
|
13044
|
-
codeMode,
|
|
14187
|
+
codeMode: effectiveCodeMode,
|
|
14188
|
+
onIterationEnd,
|
|
14189
|
+
intentClassification: classification,
|
|
13045
14190
|
onFileChange: (path, content2) => {
|
|
13046
14191
|
if (content2) {
|
|
13047
14192
|
lspManagerRef.current.notifyChange(path, content2);
|
|
13048
14193
|
} else {
|
|
13049
14194
|
void import("fs/promises").then(
|
|
13050
|
-
({ readFile:
|
|
14195
|
+
({ readFile: readFile16 }) => readFile16(path, "utf8").then((c) => lspManagerRef.current.notifyChange(path, c)).catch(() => {
|
|
13051
14196
|
})
|
|
13052
14197
|
);
|
|
13053
14198
|
}
|
|
@@ -13169,6 +14314,7 @@ ${lines.join("\n")}` }]);
|
|
|
13169
14314
|
}
|
|
13170
14315
|
}
|
|
13171
14316
|
} finally {
|
|
14317
|
+
setCodeMode(false);
|
|
13172
14318
|
const asstId = activeAsstIdRef.current;
|
|
13173
14319
|
if (asstId !== null) updateAssistant(asstId, () => ({ streaming: false }));
|
|
13174
14320
|
setBusy(false);
|
|
@@ -13181,7 +14327,7 @@ ${lines.join("\n")}` }]);
|
|
|
13181
14327
|
},
|
|
13182
14328
|
[cfg, handleSlash, updateAssistant, updateTool, saveSessionSafe, updateGatewayMeta]
|
|
13183
14329
|
);
|
|
13184
|
-
|
|
14330
|
+
useEffect5(() => {
|
|
13185
14331
|
if (!busy && queue.length > 0) {
|
|
13186
14332
|
const next = queue[0];
|
|
13187
14333
|
setQueue((q) => q.slice(1));
|
|
@@ -13209,7 +14355,7 @@ ${lines.join("\n")}` }]);
|
|
|
13209
14355
|
[busy, processMessage]
|
|
13210
14356
|
);
|
|
13211
14357
|
submitRef.current = submit;
|
|
13212
|
-
|
|
14358
|
+
useEffect5(() => {
|
|
13213
14359
|
if (compactSuggestedRef.current) return;
|
|
13214
14360
|
if (usage && usage.prompt_tokens / CONTEXT_LIMIT >= AUTO_COMPACT_SUGGEST_PCT) {
|
|
13215
14361
|
compactSuggestedRef.current = true;
|
|
@@ -13224,7 +14370,7 @@ ${lines.join("\n")}` }]);
|
|
|
13224
14370
|
}
|
|
13225
14371
|
}, [usage]);
|
|
13226
14372
|
if (!cfg) {
|
|
13227
|
-
return /* @__PURE__ */
|
|
14373
|
+
return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(
|
|
13228
14374
|
Onboarding,
|
|
13229
14375
|
{
|
|
13230
14376
|
onDone: (newCfg) => {
|
|
@@ -13238,10 +14384,42 @@ ${lines.join("\n")}` }]);
|
|
|
13238
14384
|
) });
|
|
13239
14385
|
}
|
|
13240
14386
|
if (resumeSessions !== null) {
|
|
13241
|
-
return /* @__PURE__ */
|
|
14387
|
+
return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", children: /* @__PURE__ */ jsx22(ResumePicker, { sessions: resumeSessions, onPick: handleResumePick }) }) });
|
|
14388
|
+
}
|
|
14389
|
+
if (showRemoteDashboard) {
|
|
14390
|
+
return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", children: selectedRemoteSession ? /* @__PURE__ */ jsx22(
|
|
14391
|
+
RemoteSessionDetail,
|
|
14392
|
+
{
|
|
14393
|
+
session: selectedRemoteSession,
|
|
14394
|
+
onBack: () => setSelectedRemoteSession(null),
|
|
14395
|
+
onCancel: async (session) => {
|
|
14396
|
+
try {
|
|
14397
|
+
const { cancelRemoteSession: cancelRemoteSession2 } = await Promise.resolve().then(() => (init_worker_client(), worker_client_exports));
|
|
14398
|
+
await cancelRemoteSession2(session.workerUrl, session.sessionId);
|
|
14399
|
+
setEvents((e) => [
|
|
14400
|
+
...e,
|
|
14401
|
+
{ kind: "info", key: mkKey(), text: `Cancelled session ${session.sessionId}` }
|
|
14402
|
+
]);
|
|
14403
|
+
} catch (err) {
|
|
14404
|
+
setEvents((e) => [
|
|
14405
|
+
...e,
|
|
14406
|
+
{ kind: "error", key: mkKey(), text: `Failed to cancel: ${err instanceof Error ? err.message : String(err)}` }
|
|
14407
|
+
]);
|
|
14408
|
+
}
|
|
14409
|
+
setSelectedRemoteSession(null);
|
|
14410
|
+
setShowRemoteDashboard(false);
|
|
14411
|
+
}
|
|
14412
|
+
}
|
|
14413
|
+
) : /* @__PURE__ */ jsx22(
|
|
14414
|
+
RemoteDashboard,
|
|
14415
|
+
{
|
|
14416
|
+
onSelect: (session) => setSelectedRemoteSession(session),
|
|
14417
|
+
onCancel: () => setShowRemoteDashboard(false)
|
|
14418
|
+
}
|
|
14419
|
+
) }) });
|
|
13242
14420
|
}
|
|
13243
14421
|
if (showHelpMenu) {
|
|
13244
|
-
return /* @__PURE__ */
|
|
14422
|
+
return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", children: /* @__PURE__ */ jsx22(
|
|
13245
14423
|
HelpMenu,
|
|
13246
14424
|
{
|
|
13247
14425
|
customCommands: customCommandsRef.current.filter((c) => !BUILTIN_COMMAND_NAMES.has(c.name.toLowerCase())).map((c) => ({ name: c.name, description: c.description })),
|
|
@@ -13252,12 +14430,12 @@ ${lines.join("\n")}` }]);
|
|
|
13252
14430
|
) }) });
|
|
13253
14431
|
}
|
|
13254
14432
|
if (showLspWizard) {
|
|
13255
|
-
return /* @__PURE__ */
|
|
14433
|
+
return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", children: /* @__PURE__ */ jsx22(
|
|
13256
14434
|
LspWizard,
|
|
13257
14435
|
{
|
|
13258
14436
|
servers: cfg?.lspServers ?? {},
|
|
13259
14437
|
currentScope: lspScope,
|
|
13260
|
-
hasProjectDir: existsSync2(
|
|
14438
|
+
hasProjectDir: existsSync2(join19(process.cwd(), ".kimiflare")),
|
|
13261
14439
|
onDone: () => setShowLspWizard(false),
|
|
13262
14440
|
onSave: (servers, enabled, scope) => {
|
|
13263
14441
|
setCfg((c) => c ? { ...c, lspEnabled: enabled, lspServers: servers } : c);
|
|
@@ -13289,7 +14467,7 @@ ${lines.join("\n")}` }]);
|
|
|
13289
14467
|
) }) });
|
|
13290
14468
|
}
|
|
13291
14469
|
if (commandWizard) {
|
|
13292
|
-
return /* @__PURE__ */
|
|
14470
|
+
return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", children: /* @__PURE__ */ jsx22(
|
|
13293
14471
|
CommandWizard,
|
|
13294
14472
|
{
|
|
13295
14473
|
mode: commandWizard.mode,
|
|
@@ -13302,7 +14480,7 @@ ${lines.join("\n")}` }]);
|
|
|
13302
14480
|
) }) });
|
|
13303
14481
|
}
|
|
13304
14482
|
if (commandPicker) {
|
|
13305
|
-
return /* @__PURE__ */
|
|
14483
|
+
return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", children: /* @__PURE__ */ jsx22(
|
|
13306
14484
|
CommandPicker,
|
|
13307
14485
|
{
|
|
13308
14486
|
commands: customCommandsRef.current,
|
|
@@ -13320,15 +14498,15 @@ ${lines.join("\n")}` }]);
|
|
|
13320
14498
|
) }) });
|
|
13321
14499
|
}
|
|
13322
14500
|
if (commandToDelete) {
|
|
13323
|
-
return /* @__PURE__ */
|
|
13324
|
-
/* @__PURE__ */
|
|
14501
|
+
return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsxs20(Box20, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
14502
|
+
/* @__PURE__ */ jsxs20(Text21, { color: theme.accent, bold: true, children: [
|
|
13325
14503
|
"Delete /",
|
|
13326
14504
|
commandToDelete.name,
|
|
13327
14505
|
"?"
|
|
13328
14506
|
] }),
|
|
13329
|
-
/* @__PURE__ */
|
|
13330
|
-
/* @__PURE__ */
|
|
13331
|
-
|
|
14507
|
+
/* @__PURE__ */ jsx22(Text21, { color: theme.info.color, children: commandToDelete.filepath }),
|
|
14508
|
+
/* @__PURE__ */ jsx22(Box20, { marginTop: 1, children: /* @__PURE__ */ jsx22(
|
|
14509
|
+
SelectInput9,
|
|
13332
14510
|
{
|
|
13333
14511
|
items: [
|
|
13334
14512
|
{ label: "Yes, delete", value: "yes", key: "yes" },
|
|
@@ -13346,7 +14524,7 @@ ${lines.join("\n")}` }]);
|
|
|
13346
14524
|
] }) });
|
|
13347
14525
|
}
|
|
13348
14526
|
if (showCommandList) {
|
|
13349
|
-
return /* @__PURE__ */
|
|
14527
|
+
return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", children: /* @__PURE__ */ jsx22(
|
|
13350
14528
|
CommandList,
|
|
13351
14529
|
{
|
|
13352
14530
|
commands: customCommandsRef.current,
|
|
@@ -13355,12 +14533,12 @@ ${lines.join("\n")}` }]);
|
|
|
13355
14533
|
) }) });
|
|
13356
14534
|
}
|
|
13357
14535
|
if (showThemePicker) {
|
|
13358
|
-
return /* @__PURE__ */
|
|
14536
|
+
return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", children: /* @__PURE__ */ jsx22(ThemePicker, { themes: themeList(), onPick: handleThemePick, onPreview: (t) => setTheme(t) }) }) });
|
|
13359
14537
|
}
|
|
13360
14538
|
const hasConversation = events.some((e) => e.kind === "user" || e.kind === "assistant");
|
|
13361
|
-
return /* @__PURE__ */
|
|
13362
|
-
!hasConversation && events.length === 0 ? /* @__PURE__ */
|
|
13363
|
-
perm ? /* @__PURE__ */
|
|
14539
|
+
return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsxs20(Box20, { flexDirection: "column", children: [
|
|
14540
|
+
!hasConversation && events.length === 0 ? /* @__PURE__ */ jsx22(Welcome, { accountId: cfg.accountId }) : /* @__PURE__ */ jsx22(ChatView, { events, showReasoning, verbose }),
|
|
14541
|
+
perm ? /* @__PURE__ */ jsx22(
|
|
13364
14542
|
PermissionModal,
|
|
13365
14543
|
{
|
|
13366
14544
|
tool: perm.tool,
|
|
@@ -13371,8 +14549,8 @@ ${lines.join("\n")}` }]);
|
|
|
13371
14549
|
setPerm(null);
|
|
13372
14550
|
}
|
|
13373
14551
|
}
|
|
13374
|
-
) : /* @__PURE__ */
|
|
13375
|
-
tasks.length > 0 && /* @__PURE__ */
|
|
14552
|
+
) : /* @__PURE__ */ jsxs20(Box20, { flexDirection: "column", marginTop: 1, children: [
|
|
14553
|
+
tasks.length > 0 && /* @__PURE__ */ jsx22(
|
|
13376
14554
|
TaskList,
|
|
13377
14555
|
{
|
|
13378
14556
|
tasks,
|
|
@@ -13380,11 +14558,11 @@ ${lines.join("\n")}` }]);
|
|
|
13380
14558
|
tokensDelta: Math.max(0, (usage?.prompt_tokens ?? 0) - tasksStartTokens)
|
|
13381
14559
|
}
|
|
13382
14560
|
),
|
|
13383
|
-
queue.length > 0 && /* @__PURE__ */
|
|
14561
|
+
queue.length > 0 && /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", marginBottom: 1, children: queue.map((q, i) => /* @__PURE__ */ jsxs20(Text21, { color: theme.info.color, children: [
|
|
13384
14562
|
"\u23F3 ",
|
|
13385
14563
|
q.display
|
|
13386
14564
|
] }, `queue_${i}`)) }),
|
|
13387
|
-
/* @__PURE__ */
|
|
14565
|
+
/* @__PURE__ */ jsx22(
|
|
13388
14566
|
StatusBar,
|
|
13389
14567
|
{
|
|
13390
14568
|
model: cfg.model,
|
|
@@ -13401,7 +14579,7 @@ ${lines.join("\n")}` }]);
|
|
|
13401
14579
|
codeMode
|
|
13402
14580
|
}
|
|
13403
14581
|
),
|
|
13404
|
-
activePicker?.kind === "file" && /* @__PURE__ */
|
|
14582
|
+
activePicker?.kind === "file" && /* @__PURE__ */ jsx22(
|
|
13405
14583
|
FilePicker,
|
|
13406
14584
|
{
|
|
13407
14585
|
items: filteredFileItems,
|
|
@@ -13409,7 +14587,7 @@ ${lines.join("\n")}` }]);
|
|
|
13409
14587
|
query: pickerQuery ?? ""
|
|
13410
14588
|
}
|
|
13411
14589
|
),
|
|
13412
|
-
activePicker?.kind === "slash" && /* @__PURE__ */
|
|
14590
|
+
activePicker?.kind === "slash" && /* @__PURE__ */ jsx22(
|
|
13413
14591
|
SlashPicker,
|
|
13414
14592
|
{
|
|
13415
14593
|
items: filteredSlashItems,
|
|
@@ -13417,9 +14595,9 @@ ${lines.join("\n")}` }]);
|
|
|
13417
14595
|
query: pickerQuery ?? ""
|
|
13418
14596
|
}
|
|
13419
14597
|
),
|
|
13420
|
-
/* @__PURE__ */
|
|
13421
|
-
/* @__PURE__ */
|
|
13422
|
-
/* @__PURE__ */
|
|
14598
|
+
/* @__PURE__ */ jsxs20(Box20, { marginTop: 1, children: [
|
|
14599
|
+
/* @__PURE__ */ jsx22(Text21, { color: "#d699b6", children: "\u203A " }),
|
|
14600
|
+
/* @__PURE__ */ jsx22(
|
|
13423
14601
|
CustomTextInput,
|
|
13424
14602
|
{
|
|
13425
14603
|
value: input,
|
|
@@ -13476,7 +14654,7 @@ ${lines.join("\n")}` }]);
|
|
|
13476
14654
|
}
|
|
13477
14655
|
async function renderApp(cfg, updateResult, lspScope = "global", lspProjectPath = null) {
|
|
13478
14656
|
const instance = render(
|
|
13479
|
-
/* @__PURE__ */
|
|
14657
|
+
/* @__PURE__ */ jsx22(
|
|
13480
14658
|
App,
|
|
13481
14659
|
{
|
|
13482
14660
|
initialCfg: cfg,
|
|
@@ -13517,7 +14695,13 @@ var init_app = __esm({
|
|
|
13517
14695
|
init_welcome();
|
|
13518
14696
|
init_help_menu();
|
|
13519
14697
|
init_config();
|
|
14698
|
+
init_worker_client();
|
|
14699
|
+
init_session_store();
|
|
14700
|
+
init_tui_deploy();
|
|
14701
|
+
init_tui_auth();
|
|
14702
|
+
init_remote_dashboard();
|
|
13520
14703
|
init_mode();
|
|
14704
|
+
init_classify();
|
|
13521
14705
|
init_sessions();
|
|
13522
14706
|
init_image();
|
|
13523
14707
|
init_usage_tracker();
|
|
@@ -13566,8 +14750,107 @@ init_system_prompt();
|
|
|
13566
14750
|
init_executor();
|
|
13567
14751
|
init_update_check();
|
|
13568
14752
|
init_version();
|
|
14753
|
+
import { Command as Command2 } from "commander";
|
|
14754
|
+
|
|
14755
|
+
// src/remote/cli.ts
|
|
14756
|
+
init_config();
|
|
14757
|
+
init_session_store();
|
|
14758
|
+
init_deploy();
|
|
13569
14759
|
import { Command } from "commander";
|
|
13570
|
-
|
|
14760
|
+
function createRemoteCommand() {
|
|
14761
|
+
const remote = new Command("remote").description("Manage remote sessions");
|
|
14762
|
+
remote.command("deploy").description("Deploy the remote Worker and container image to Cloudflare").action(async () => {
|
|
14763
|
+
await runDeploy();
|
|
14764
|
+
});
|
|
14765
|
+
remote.command("setup").description("Check remote deployment status and prerequisites").action(async () => {
|
|
14766
|
+
const status = await checkDeployStatus();
|
|
14767
|
+
console.log("Remote deployment status:\n");
|
|
14768
|
+
console.log(` wrangler CLI: ${status.wrangler ? "yes" : "no"}`);
|
|
14769
|
+
console.log(` wrangler auth: ${status.wranglerAuth ? "yes" : "no"}`);
|
|
14770
|
+
console.log(` Docker: ${status.docker ? "yes" : "no"}`);
|
|
14771
|
+
console.log(` Worker URL: ${status.workerUrl ?? "not deployed"}`);
|
|
14772
|
+
console.log("\nRun `kimiflare remote deploy` to deploy.");
|
|
14773
|
+
});
|
|
14774
|
+
remote.command("list").description("List remote sessions").action(async () => {
|
|
14775
|
+
const sessions = await listRemoteSessions();
|
|
14776
|
+
if (sessions.length === 0) {
|
|
14777
|
+
console.log("No remote sessions found.");
|
|
14778
|
+
return;
|
|
14779
|
+
}
|
|
14780
|
+
console.log(`Remote sessions (${sessions.length} total):
|
|
14781
|
+
`);
|
|
14782
|
+
for (const s of sessions.slice(0, 20)) {
|
|
14783
|
+
const date = new Date(s.createdAt).toLocaleString();
|
|
14784
|
+
const statusIcon = s.status === "done" ? "\u2705" : s.status === "error" ? "\u274C" : s.status === "running" ? "\u23F3" : "\u23F9\uFE0F";
|
|
14785
|
+
console.log(` ${statusIcon} ${s.sessionId.slice(0, 8)}\u2026 ${s.status.padEnd(10)} ${date} ${s.prompt.slice(0, 50)}`);
|
|
14786
|
+
if (s.prUrl) {
|
|
14787
|
+
console.log(` PR: ${s.prUrl}`);
|
|
14788
|
+
}
|
|
14789
|
+
}
|
|
14790
|
+
});
|
|
14791
|
+
remote.command("status").description("Show remote session status").argument("[session-id]", "Session ID (defaults to most recent)").action(async (sessionId) => {
|
|
14792
|
+
const session = sessionId ? await loadRemoteSession(sessionId) : await getMostRecentRemoteSession();
|
|
14793
|
+
if (!session) {
|
|
14794
|
+
console.log(sessionId ? `Session ${sessionId} not found.` : "No remote sessions found.");
|
|
14795
|
+
return;
|
|
14796
|
+
}
|
|
14797
|
+
const cfg = await loadConfig();
|
|
14798
|
+
const workerUrl = cfg?.remoteWorkerUrl;
|
|
14799
|
+
if (!workerUrl) {
|
|
14800
|
+
console.log("Remote worker not configured.");
|
|
14801
|
+
return;
|
|
14802
|
+
}
|
|
14803
|
+
try {
|
|
14804
|
+
const res = await fetch(`${workerUrl}/remote/status/${session.sessionId}`, {
|
|
14805
|
+
headers: {
|
|
14806
|
+
Authorization: `Bearer ${cfg.remoteAuthSecret ?? ""}`
|
|
14807
|
+
}
|
|
14808
|
+
});
|
|
14809
|
+
if (!res.ok) {
|
|
14810
|
+
console.log(`Failed to fetch status: ${res.status}`);
|
|
14811
|
+
return;
|
|
14812
|
+
}
|
|
14813
|
+
const data = await res.json();
|
|
14814
|
+
console.log(`Session: ${data.sessionId}`);
|
|
14815
|
+
console.log(`Status: ${data.status}`);
|
|
14816
|
+
console.log(`Prompt: ${data.prompt}`);
|
|
14817
|
+
console.log(`Repo: ${data.repo?.owner}/${data.repo?.name}`);
|
|
14818
|
+
console.log(`Branch: ${data.branch}`);
|
|
14819
|
+
console.log(`Turns: ${data.currentTurn} / ${data.maxTurns}`);
|
|
14820
|
+
if (data.prUrl) console.log(`PR: ${data.prUrl}`);
|
|
14821
|
+
if (data.errorMessage) console.log(`Error: ${data.errorMessage}`);
|
|
14822
|
+
} catch (err) {
|
|
14823
|
+
console.log(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
14824
|
+
}
|
|
14825
|
+
});
|
|
14826
|
+
remote.command("cancel").description("Cancel a remote session").argument("<session-id>", "Session ID").action(async (sessionId) => {
|
|
14827
|
+
const cfg = await loadConfig();
|
|
14828
|
+
const workerUrl = cfg?.remoteWorkerUrl;
|
|
14829
|
+
if (!workerUrl) {
|
|
14830
|
+
console.log("Remote worker not configured.");
|
|
14831
|
+
return;
|
|
14832
|
+
}
|
|
14833
|
+
try {
|
|
14834
|
+
const res = await fetch(`${workerUrl}/remote/cancel/${sessionId}`, {
|
|
14835
|
+
method: "POST",
|
|
14836
|
+
headers: {
|
|
14837
|
+
Authorization: `Bearer ${cfg.remoteAuthSecret ?? ""}`
|
|
14838
|
+
}
|
|
14839
|
+
});
|
|
14840
|
+
if (!res.ok) {
|
|
14841
|
+
console.log(`Failed to cancel: ${res.status}`);
|
|
14842
|
+
return;
|
|
14843
|
+
}
|
|
14844
|
+
console.log(`Session ${sessionId} cancelled.`);
|
|
14845
|
+
} catch (err) {
|
|
14846
|
+
console.log(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
14847
|
+
}
|
|
14848
|
+
});
|
|
14849
|
+
return remote;
|
|
14850
|
+
}
|
|
14851
|
+
|
|
14852
|
+
// src/index.tsx
|
|
14853
|
+
var program = new Command2();
|
|
13571
14854
|
program.name("kimiflare").description("Terminal coding agent powered by Kimi-K2.6 on Cloudflare Workers AI.").version(getAppVersion()).option("-p, --print <prompt>", "one-shot mode: send prompt, stream reply to stdout, exit").option("-m, --model <id>", "model id (defaults to @cf/moonshotai/kimi-k2.6)").option("--dangerously-allow-all", "auto-approve every permission prompt (print mode only)").option("--reasoning", "include reasoning in stdout (print mode only)").option("--continue-on-limit", "reset tool-call counter and continue when the 50-call limit is hit (print mode only)").option("--max-input-tokens <n>", "cumulative prompt token budget; exits 42 when exhausted (print mode only)", (v) => parseInt(v, 10));
|
|
13572
14855
|
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) => {
|
|
13573
14856
|
const cfg = await loadConfig();
|
|
@@ -13581,6 +14864,23 @@ program.command("cost").description("Show cost attribution by task type (require
|
|
|
13581
14864
|
const { runCostCommand: runCostCommand2 } = await Promise.resolve().then(() => (init_cli(), cli_exports));
|
|
13582
14865
|
await runCostCommand2({ ...cmdOpts, config: cfg });
|
|
13583
14866
|
});
|
|
14867
|
+
program.addCommand(createRemoteCommand());
|
|
14868
|
+
program.command("auth").description("Authenticate with external services").addCommand(
|
|
14869
|
+
new Command2("github").description("Authenticate with GitHub via OAuth device flow").action(async () => {
|
|
14870
|
+
const { authGitHubForTui: authGitHubForTui2 } = await Promise.resolve().then(() => (init_tui_auth(), tui_auth_exports));
|
|
14871
|
+
for await (const step of authGitHubForTui2()) {
|
|
14872
|
+
console.log(step.message);
|
|
14873
|
+
if (step.url && step.code) {
|
|
14874
|
+
console.log(`
|
|
14875
|
+
Open: ${step.url}`);
|
|
14876
|
+
console.log(`Code: ${step.code}
|
|
14877
|
+
`);
|
|
14878
|
+
}
|
|
14879
|
+
if (step.done) break;
|
|
14880
|
+
if (step.error) process.exit(1);
|
|
14881
|
+
}
|
|
14882
|
+
})
|
|
14883
|
+
);
|
|
13584
14884
|
program.action(async () => {
|
|
13585
14885
|
await main();
|
|
13586
14886
|
});
|