kimiflare 0.34.0 → 0.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +729 -215
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -83,7 +83,7 @@ async function loadConfig() {
|
|
|
83
83
|
const envCacheStable = process.env.KIMIFLARE_CACHE_STABLE_PROMPTS;
|
|
84
84
|
const cacheStablePrompts = envCacheStable === "0" || envCacheStable === "false" ? false : true;
|
|
85
85
|
const envCompiled = process.env.KIMIFLARE_COMPILED_CONTEXT;
|
|
86
|
-
const compiledContext = envCompiled === "
|
|
86
|
+
const compiledContext = envCompiled === "0" || envCompiled === "false" ? false : true;
|
|
87
87
|
const envImageTurns = process.env.KIMIFLARE_IMAGE_HISTORY_TURNS;
|
|
88
88
|
const imageHistoryTurns = envImageTurns ? parseInt(envImageTurns, 10) : void 0;
|
|
89
89
|
const envMemoryEnabled = readBooleanEnv("KIMIFLARE_MEMORY_ENABLED");
|
|
@@ -92,9 +92,35 @@ async function loadConfig() {
|
|
|
92
92
|
const envMemoryMaxEntries = readNumberEnv("KIMIFLARE_MEMORY_MAX_ENTRIES");
|
|
93
93
|
const envMemoryEmbeddingModel = process.env.KIMIFLARE_MEMORY_EMBEDDING_MODEL;
|
|
94
94
|
const envPlumbingModel = process.env.KIMIFLARE_PLUMBING_MODEL;
|
|
95
|
+
const envMemoryExtractionModel = process.env.KIMIFLARE_MEMORY_EXTRACTION_MODEL;
|
|
95
96
|
const envCodeMode = readBooleanEnv("KIMIFLARE_CODE_MODE");
|
|
96
97
|
const envCostAttribution = readBooleanEnv("KIMI_COST_ATTRIBUTION");
|
|
97
98
|
const envFilePicker = readBooleanEnv("KIMIFLARE_FILE_PICKER");
|
|
99
|
+
const envCloudMode = readBooleanEnv("KIMIFLARE_CLOUD");
|
|
100
|
+
if (envCloudMode) {
|
|
101
|
+
return {
|
|
102
|
+
accountId: "",
|
|
103
|
+
apiToken: "",
|
|
104
|
+
model: envModel,
|
|
105
|
+
cloudMode: true,
|
|
106
|
+
reasoningEffort: envEffort,
|
|
107
|
+
coauthor: envCoauthor?.enabled ?? true,
|
|
108
|
+
coauthorName: envCoauthor?.name,
|
|
109
|
+
coauthorEmail: envCoauthor?.email,
|
|
110
|
+
cacheStablePrompts,
|
|
111
|
+
compiledContext,
|
|
112
|
+
imageHistoryTurns: Number.isNaN(imageHistoryTurns) ? void 0 : imageHistoryTurns,
|
|
113
|
+
memoryEnabled: envMemoryEnabled,
|
|
114
|
+
memoryDbPath: envMemoryDbPath,
|
|
115
|
+
memoryMaxAgeDays: envMemoryMaxAgeDays,
|
|
116
|
+
memoryMaxEntries: envMemoryMaxEntries,
|
|
117
|
+
memoryEmbeddingModel: envMemoryEmbeddingModel,
|
|
118
|
+
plumbingModel: envPlumbingModel,
|
|
119
|
+
codeMode: envCodeMode,
|
|
120
|
+
costAttribution: envCostAttribution ?? false,
|
|
121
|
+
filePicker: envFilePicker ?? true
|
|
122
|
+
};
|
|
123
|
+
}
|
|
98
124
|
if (envAccount && envToken) {
|
|
99
125
|
return {
|
|
100
126
|
accountId: envAccount,
|
|
@@ -112,20 +138,46 @@ async function loadConfig() {
|
|
|
112
138
|
cacheStablePrompts,
|
|
113
139
|
compiledContext,
|
|
114
140
|
imageHistoryTurns: Number.isNaN(imageHistoryTurns) ? void 0 : imageHistoryTurns,
|
|
115
|
-
memoryEnabled: envMemoryEnabled,
|
|
141
|
+
memoryEnabled: envMemoryEnabled ?? true,
|
|
116
142
|
memoryDbPath: envMemoryDbPath,
|
|
117
143
|
memoryMaxAgeDays: envMemoryMaxAgeDays,
|
|
118
144
|
memoryMaxEntries: envMemoryMaxEntries,
|
|
119
145
|
memoryEmbeddingModel: envMemoryEmbeddingModel,
|
|
120
146
|
plumbingModel: envPlumbingModel,
|
|
121
|
-
|
|
122
|
-
|
|
147
|
+
memoryExtractionModel: envMemoryExtractionModel,
|
|
148
|
+
codeMode: envCodeMode ?? true,
|
|
149
|
+
costAttribution: envCostAttribution ?? true,
|
|
123
150
|
filePicker: envFilePicker ?? true
|
|
124
151
|
};
|
|
125
152
|
}
|
|
126
153
|
try {
|
|
127
154
|
const raw = await readFile(configPath(), "utf8");
|
|
128
155
|
const parsed = JSON.parse(raw);
|
|
156
|
+
if (parsed.cloudMode) {
|
|
157
|
+
return {
|
|
158
|
+
accountId: envAccount ?? parsed.accountId ?? "",
|
|
159
|
+
apiToken: envToken ?? parsed.apiToken ?? "",
|
|
160
|
+
model: envModel ?? parsed.model ?? DEFAULT_MODEL,
|
|
161
|
+
cloudMode: true,
|
|
162
|
+
reasoningEffort: envEffort ?? parsed.reasoningEffort,
|
|
163
|
+
coauthor: envCoauthor?.enabled ?? parsed.coauthor ?? true,
|
|
164
|
+
coauthorName: envCoauthor?.name ?? parsed.coauthorName,
|
|
165
|
+
coauthorEmail: envCoauthor?.email ?? parsed.coauthorEmail,
|
|
166
|
+
mcpServers: parsed.mcpServers,
|
|
167
|
+
cacheStablePrompts: parsed.cacheStablePrompts ?? cacheStablePrompts,
|
|
168
|
+
compiledContext: parsed.compiledContext ?? compiledContext,
|
|
169
|
+
imageHistoryTurns: Number.isNaN(imageHistoryTurns) ? parsed.imageHistoryTurns : imageHistoryTurns,
|
|
170
|
+
memoryEnabled: envMemoryEnabled ?? parsed.memoryEnabled,
|
|
171
|
+
memoryDbPath: envMemoryDbPath ?? parsed.memoryDbPath,
|
|
172
|
+
memoryMaxAgeDays: envMemoryMaxAgeDays ?? parsed.memoryMaxAgeDays,
|
|
173
|
+
memoryMaxEntries: envMemoryMaxEntries ?? parsed.memoryMaxEntries,
|
|
174
|
+
memoryEmbeddingModel: envMemoryEmbeddingModel ?? parsed.memoryEmbeddingModel,
|
|
175
|
+
plumbingModel: envPlumbingModel ?? parsed.plumbingModel,
|
|
176
|
+
codeMode: envCodeMode ?? parsed.codeMode,
|
|
177
|
+
costAttribution: envCostAttribution ?? parsed.costAttribution ?? false,
|
|
178
|
+
filePicker: envFilePicker ?? parsed.filePicker ?? true
|
|
179
|
+
};
|
|
180
|
+
}
|
|
129
181
|
if (parsed.accountId && parsed.apiToken) {
|
|
130
182
|
return {
|
|
131
183
|
accountId: envAccount ?? parsed.accountId,
|
|
@@ -144,15 +196,17 @@ async function loadConfig() {
|
|
|
144
196
|
cacheStablePrompts: parsed.cacheStablePrompts ?? cacheStablePrompts,
|
|
145
197
|
compiledContext: parsed.compiledContext ?? compiledContext,
|
|
146
198
|
imageHistoryTurns: Number.isNaN(imageHistoryTurns) ? parsed.imageHistoryTurns : imageHistoryTurns,
|
|
147
|
-
memoryEnabled: envMemoryEnabled ?? parsed.memoryEnabled,
|
|
199
|
+
memoryEnabled: envMemoryEnabled ?? parsed.memoryEnabled ?? true,
|
|
148
200
|
memoryDbPath: envMemoryDbPath ?? parsed.memoryDbPath,
|
|
149
201
|
memoryMaxAgeDays: envMemoryMaxAgeDays ?? parsed.memoryMaxAgeDays,
|
|
150
202
|
memoryMaxEntries: envMemoryMaxEntries ?? parsed.memoryMaxEntries,
|
|
151
203
|
memoryEmbeddingModel: envMemoryEmbeddingModel ?? parsed.memoryEmbeddingModel,
|
|
152
204
|
plumbingModel: envPlumbingModel ?? parsed.plumbingModel,
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
205
|
+
memoryExtractionModel: envMemoryExtractionModel ?? parsed.memoryExtractionModel,
|
|
206
|
+
codeMode: envCodeMode ?? parsed.codeMode ?? true,
|
|
207
|
+
costAttribution: envCostAttribution ?? parsed.costAttribution ?? true,
|
|
208
|
+
filePicker: envFilePicker ?? parsed.filePicker ?? true,
|
|
209
|
+
cloudMode: envCloudMode ?? parsed.cloudMode
|
|
156
210
|
};
|
|
157
211
|
}
|
|
158
212
|
} catch {
|
|
@@ -440,7 +494,7 @@ async function* runKimi(opts2) {
|
|
|
440
494
|
let res;
|
|
441
495
|
try {
|
|
442
496
|
const headers = {
|
|
443
|
-
Authorization: `Bearer ${opts2.apiToken}`,
|
|
497
|
+
Authorization: `Bearer ${opts2.cloudMode && opts2.cloudToken ? opts2.cloudToken : opts2.apiToken}`,
|
|
444
498
|
"Content-Type": "application/json",
|
|
445
499
|
"User-Agent": getUserAgent(),
|
|
446
500
|
...gatewayHeaders
|
|
@@ -497,6 +551,12 @@ function validateModelId(model) {
|
|
|
497
551
|
}
|
|
498
552
|
function buildKimiRequestTarget(opts2) {
|
|
499
553
|
validateModelId(opts2.model);
|
|
554
|
+
if (opts2.cloudMode) {
|
|
555
|
+
return {
|
|
556
|
+
url: "https://api.kimiflare.com/v1/chat",
|
|
557
|
+
headers: opts2.cloudToken ? { Authorization: `Bearer ${opts2.cloudToken}` } : {}
|
|
558
|
+
};
|
|
559
|
+
}
|
|
500
560
|
if (!opts2.gateway?.id) {
|
|
501
561
|
return {
|
|
502
562
|
url: `https://api.cloudflare.com/client/v4/accounts/${encodeURIComponent(opts2.accountId)}/ai/run/${opts2.model}`,
|
|
@@ -553,44 +613,51 @@ async function* parseStream(body, signal) {
|
|
|
553
613
|
lastUsage = chunk.usage;
|
|
554
614
|
yield { type: "usage", usage: chunk.usage };
|
|
555
615
|
}
|
|
616
|
+
if (typeof chunk.response === "string") {
|
|
617
|
+
const resp = chunk.response;
|
|
618
|
+
if (resp.length) {
|
|
619
|
+
yield { type: "text", delta: resp };
|
|
620
|
+
}
|
|
621
|
+
}
|
|
556
622
|
const choice = chunk.choices?.[0];
|
|
557
|
-
if (
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
623
|
+
if (choice) {
|
|
624
|
+
const d = choice.delta;
|
|
625
|
+
if (d) {
|
|
626
|
+
if (typeof d.reasoning_content === "string" && d.reasoning_content.length) {
|
|
627
|
+
yield { type: "reasoning", delta: d.reasoning_content };
|
|
628
|
+
}
|
|
629
|
+
if (typeof d.content === "string" && d.content.length) {
|
|
630
|
+
yield { type: "text", delta: d.content };
|
|
631
|
+
}
|
|
632
|
+
if (Array.isArray(d.tool_calls)) {
|
|
633
|
+
for (const tc of d.tool_calls) {
|
|
634
|
+
const idx = typeof tc.index === "number" ? tc.index : 0;
|
|
635
|
+
let buf = toolCalls.get(idx);
|
|
636
|
+
const incomingName = tc.function?.name ?? null;
|
|
637
|
+
const incomingId = tc.id ?? null;
|
|
638
|
+
if (!buf) {
|
|
639
|
+
buf = { id: incomingId ?? `tc_${idx}`, name: incomingName ?? "", args: "" };
|
|
640
|
+
toolCalls.set(idx, buf);
|
|
641
|
+
if (buf.name) {
|
|
642
|
+
yield { type: "tool_call_start", index: idx, id: buf.id, name: buf.name };
|
|
643
|
+
}
|
|
644
|
+
} else {
|
|
645
|
+
if (!buf.name && incomingName) {
|
|
646
|
+
buf.name = incomingName;
|
|
647
|
+
yield { type: "tool_call_start", index: idx, id: buf.id, name: buf.name };
|
|
648
|
+
}
|
|
649
|
+
if (buf.id.startsWith("tc_") && incomingId) buf.id = incomingId;
|
|
577
650
|
}
|
|
578
|
-
|
|
579
|
-
if (
|
|
580
|
-
buf.
|
|
581
|
-
yield { type: "
|
|
651
|
+
const argDelta = tc.function?.arguments;
|
|
652
|
+
if (typeof argDelta === "string" && argDelta.length) {
|
|
653
|
+
buf.args += argDelta;
|
|
654
|
+
yield { type: "tool_call_args", index: idx, argsDelta: argDelta };
|
|
582
655
|
}
|
|
583
|
-
if (buf.id.startsWith("tc_") && incomingId) buf.id = incomingId;
|
|
584
|
-
}
|
|
585
|
-
const argDelta = tc.function?.arguments;
|
|
586
|
-
if (typeof argDelta === "string" && argDelta.length) {
|
|
587
|
-
buf.args += argDelta;
|
|
588
|
-
yield { type: "tool_call_args", index: idx, argsDelta: argDelta };
|
|
589
656
|
}
|
|
590
657
|
}
|
|
591
658
|
}
|
|
659
|
+
if (choice.finish_reason) finishReason = choice.finish_reason;
|
|
592
660
|
}
|
|
593
|
-
if (choice.finish_reason) finishReason = choice.finish_reason;
|
|
594
661
|
}
|
|
595
662
|
for (const [idx, buf] of [...toolCalls.entries()].sort((a, b) => a[0] - b[0])) {
|
|
596
663
|
if (!buf.name) continue;
|
|
@@ -965,10 +1032,129 @@ function safeJsonParse(text) {
|
|
|
965
1032
|
return null;
|
|
966
1033
|
}
|
|
967
1034
|
}
|
|
968
|
-
|
|
1035
|
+
function truncate(str, max) {
|
|
1036
|
+
if (str.length <= max) return str;
|
|
1037
|
+
return str.slice(0, max) + "\u2026";
|
|
1038
|
+
}
|
|
1039
|
+
async function callLlm(messages, llmOpts, maxTokens = 64) {
|
|
1040
|
+
if (!llmOpts) return "";
|
|
1041
|
+
const events = runKimi({
|
|
1042
|
+
accountId: llmOpts.accountId,
|
|
1043
|
+
apiToken: llmOpts.apiToken,
|
|
1044
|
+
model: llmOpts.model,
|
|
1045
|
+
messages,
|
|
1046
|
+
temperature: 0.1,
|
|
1047
|
+
maxCompletionTokens: maxTokens,
|
|
1048
|
+
gateway: llmOpts.gateway,
|
|
1049
|
+
signal: llmOpts.signal
|
|
1050
|
+
});
|
|
1051
|
+
let text = "";
|
|
1052
|
+
for await (const ev of events) {
|
|
1053
|
+
if (ev.type === "text") text += ev.delta;
|
|
1054
|
+
}
|
|
1055
|
+
return text.trim().replace(/^["']|["']$/g, "").replace(/\s+/g, " ").toLowerCase();
|
|
1056
|
+
}
|
|
1057
|
+
async function synthesizeEditEvent(file, toolName, toolArgs, assistantMessage, llmOpts) {
|
|
1058
|
+
if (!llmOpts) return null;
|
|
1059
|
+
const oldString = typeof toolArgs.old_string === "string" ? toolArgs.old_string : "";
|
|
1060
|
+
const newString = typeof toolArgs.new_string === "string" ? toolArgs.new_string : "";
|
|
1061
|
+
const fullContent = typeof toolArgs.content === "string" ? toolArgs.content : "";
|
|
1062
|
+
const isWrite = toolName === "write";
|
|
1063
|
+
const before = isWrite ? "(new file)" : truncate(oldString, 600);
|
|
1064
|
+
const after = isWrite ? truncate(fullContent, 600) : truncate(newString, 600);
|
|
1065
|
+
const intent = assistantMessage ? assistantMessage.slice(-300).trim() : "";
|
|
1066
|
+
const changeContext = `File: ${file}
|
|
1067
|
+
Tool: ${toolName}
|
|
1068
|
+
|
|
1069
|
+
Before:
|
|
1070
|
+
${before}
|
|
1071
|
+
|
|
1072
|
+
After:
|
|
1073
|
+
${after}${intent ? `
|
|
1074
|
+
|
|
1075
|
+
Context: ${intent}` : ""}`;
|
|
1076
|
+
const summary1 = await callLlm(
|
|
1077
|
+
[
|
|
1078
|
+
{ role: "system", content: EDIT_SYNTHESIS_SYSTEM },
|
|
1079
|
+
{ role: "user", content: `${changeContext}
|
|
1080
|
+
|
|
1081
|
+
Summary:` }
|
|
1082
|
+
],
|
|
1083
|
+
llmOpts
|
|
1084
|
+
);
|
|
1085
|
+
if (summary1.length >= 10 && summary1.length <= 200) {
|
|
1086
|
+
const verdict = await callLlm(
|
|
1087
|
+
[
|
|
1088
|
+
{ role: "system", content: VERIFIER_SYSTEM },
|
|
1089
|
+
{
|
|
1090
|
+
role: "user",
|
|
1091
|
+
content: `${changeContext}
|
|
1092
|
+
|
|
1093
|
+
Proposed summary: "${summary1}"
|
|
1094
|
+
|
|
1095
|
+
Is this accurate?`
|
|
1096
|
+
}
|
|
1097
|
+
],
|
|
1098
|
+
llmOpts,
|
|
1099
|
+
8
|
|
1100
|
+
);
|
|
1101
|
+
if (verdict.startsWith("yes")) return summary1;
|
|
1102
|
+
}
|
|
1103
|
+
const retrySystem = `${EDIT_SYNTHESIS_SYSTEM}
|
|
1104
|
+
|
|
1105
|
+
CRITICAL: The previous summary was rejected. Be specific. Include concrete details from the After section.`;
|
|
1106
|
+
const summary2 = await callLlm(
|
|
1107
|
+
[
|
|
1108
|
+
{ role: "system", content: retrySystem },
|
|
1109
|
+
{ role: "user", content: `${changeContext}
|
|
1110
|
+
|
|
1111
|
+
Summary:` }
|
|
1112
|
+
],
|
|
1113
|
+
llmOpts
|
|
1114
|
+
);
|
|
1115
|
+
if (summary2.length >= 10 && summary2.length <= 200) {
|
|
1116
|
+
const verdict2 = await callLlm(
|
|
1117
|
+
[
|
|
1118
|
+
{ role: "system", content: VERIFIER_SYSTEM },
|
|
1119
|
+
{
|
|
1120
|
+
role: "user",
|
|
1121
|
+
content: `${changeContext}
|
|
1122
|
+
|
|
1123
|
+
Proposed summary: "${summary2}"
|
|
1124
|
+
|
|
1125
|
+
Is this accurate?`
|
|
1126
|
+
}
|
|
1127
|
+
],
|
|
1128
|
+
llmOpts,
|
|
1129
|
+
8
|
|
1130
|
+
);
|
|
1131
|
+
if (verdict2.startsWith("yes")) return summary2;
|
|
1132
|
+
}
|
|
1133
|
+
return null;
|
|
1134
|
+
}
|
|
1135
|
+
var EDIT_SYNTHESIS_SYSTEM, VERIFIER_SYSTEM, EXTRACTORS;
|
|
969
1136
|
var init_extractors = __esm({
|
|
970
1137
|
"src/memory/extractors.ts"() {
|
|
971
1138
|
"use strict";
|
|
1139
|
+
init_client();
|
|
1140
|
+
EDIT_SYNTHESIS_SYSTEM = `You summarize a SINGLE code edit. Write ONE concise sentence (max 20 words) describing exactly what changed.
|
|
1141
|
+
|
|
1142
|
+
Rules:
|
|
1143
|
+
- Use ONLY the Before/After diff below.
|
|
1144
|
+
- For new files: describe the file's content or purpose. Never say just "added a new file".
|
|
1145
|
+
- For edits: describe the specific code change.
|
|
1146
|
+
|
|
1147
|
+
Examples:
|
|
1148
|
+
- Created test-memory.md containing the text "Memory test".
|
|
1149
|
+
- Fixed race condition in loop.ts by adding AbortSignal guard.
|
|
1150
|
+
- Added vitest dependency and removed jest from package.json.
|
|
1151
|
+
|
|
1152
|
+
Respond with only the summary sentence. No quotes, no preamble.`;
|
|
1153
|
+
VERIFIER_SYSTEM = `You verify whether a summary accurately describes a code edit.
|
|
1154
|
+
Answer exactly "yes" if the summary correctly captures what changed in the file.
|
|
1155
|
+
Answer exactly "no" if the summary is vague, wrong, or misses the actual change.
|
|
1156
|
+
|
|
1157
|
+
Respond with only "yes" or "no".`;
|
|
972
1158
|
EXTRACTORS = [
|
|
973
1159
|
{
|
|
974
1160
|
id: "package_json",
|
|
@@ -1022,9 +1208,27 @@ var init_extractors = __esm({
|
|
|
1022
1208
|
{
|
|
1023
1209
|
id: "edit_event",
|
|
1024
1210
|
match: (tool, file) => (tool === "edit" || tool === "write") && !!file,
|
|
1025
|
-
extract: (_content, file) => {
|
|
1211
|
+
extract: async (_content, file, ctx) => {
|
|
1026
1212
|
if (!file) return null;
|
|
1027
1213
|
const safeKey = file.replace(/[^a-zA-Z0-9]/g, "_");
|
|
1214
|
+
if (ctx?.llmOpts && (ctx.toolArgs || ctx.assistantMessage)) {
|
|
1215
|
+
const summary = await synthesizeEditEvent(
|
|
1216
|
+
file,
|
|
1217
|
+
ctx.toolArgs?._toolName || "edit",
|
|
1218
|
+
ctx.toolArgs || {},
|
|
1219
|
+
ctx.assistantMessage,
|
|
1220
|
+
ctx.llmOpts
|
|
1221
|
+
);
|
|
1222
|
+
if (summary) {
|
|
1223
|
+
return {
|
|
1224
|
+
content: summary,
|
|
1225
|
+
category: "event",
|
|
1226
|
+
importance: 3,
|
|
1227
|
+
topicKey: `event_edit_${safeKey}`,
|
|
1228
|
+
relatedFiles: [file]
|
|
1229
|
+
};
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1028
1232
|
return {
|
|
1029
1233
|
content: `File modified: ${file}.`,
|
|
1030
1234
|
category: "event",
|
|
@@ -1179,6 +1383,8 @@ var init_api_generator = __esm({
|
|
|
1179
1383
|
});
|
|
1180
1384
|
|
|
1181
1385
|
// src/code-mode/sandbox.ts
|
|
1386
|
+
import { join as join6, dirname as dirname3 } from "path";
|
|
1387
|
+
import { pathToFileURL } from "url";
|
|
1182
1388
|
function stripTypescript(code) {
|
|
1183
1389
|
let js = code;
|
|
1184
1390
|
js = js.replace(/interface\s+\w+\s*\{[\s\S]*?\n\}/g, "");
|
|
@@ -1195,6 +1401,36 @@ function stripTypescript(code) {
|
|
|
1195
1401
|
js = js.replace(/\n{3,}/g, "\n\n");
|
|
1196
1402
|
return js.trim();
|
|
1197
1403
|
}
|
|
1404
|
+
async function loadTypescript(cwd) {
|
|
1405
|
+
let dir = cwd;
|
|
1406
|
+
while (dir !== dirname3(dir)) {
|
|
1407
|
+
try {
|
|
1408
|
+
const tsPath = join6(dir, "node_modules", "typescript", "lib", "typescript.js");
|
|
1409
|
+
return await import(pathToFileURL(tsPath).href);
|
|
1410
|
+
} catch {
|
|
1411
|
+
}
|
|
1412
|
+
dir = dirname3(dir);
|
|
1413
|
+
}
|
|
1414
|
+
return null;
|
|
1415
|
+
}
|
|
1416
|
+
async function transpileOrStrip(code, cwd) {
|
|
1417
|
+
const ts = await loadTypescript(cwd);
|
|
1418
|
+
if (ts) {
|
|
1419
|
+
const result = ts.transpileModule(code, {
|
|
1420
|
+
compilerOptions: {
|
|
1421
|
+
module: ts.ModuleKind.ES2022,
|
|
1422
|
+
target: ts.ScriptTarget.ES2022,
|
|
1423
|
+
esModuleInterop: true,
|
|
1424
|
+
isolatedModules: true
|
|
1425
|
+
}
|
|
1426
|
+
});
|
|
1427
|
+
return { js: result.outputText, warnings: [] };
|
|
1428
|
+
}
|
|
1429
|
+
return {
|
|
1430
|
+
js: stripTypescript(code),
|
|
1431
|
+
warnings: ["TypeScript not found in node_modules. Using fallback parser; install typescript for reliable transpilation."]
|
|
1432
|
+
};
|
|
1433
|
+
}
|
|
1198
1434
|
async function runWithIsolatedVm(opts2) {
|
|
1199
1435
|
const { Isolate } = await import("isolated-vm");
|
|
1200
1436
|
const isolate = new Isolate({ memoryLimit: opts2.memoryLimitMB ?? 128 });
|
|
@@ -1242,7 +1478,7 @@ async function runWithIsolatedVm(opts2) {
|
|
|
1242
1478
|
await context.eval(`var api = {
|
|
1243
1479
|
${apiMethods}
|
|
1244
1480
|
};`);
|
|
1245
|
-
const jsCode =
|
|
1481
|
+
const { js: jsCode, warnings } = await transpileOrStrip(opts2.code, opts2.ctx.cwd);
|
|
1246
1482
|
const wrapped = `(async function() {
|
|
1247
1483
|
${jsCode}
|
|
1248
1484
|
})();`;
|
|
@@ -1253,11 +1489,11 @@ ${jsCode}
|
|
|
1253
1489
|
await new Promise((r) => setTimeout(r, 10));
|
|
1254
1490
|
} catch (err) {
|
|
1255
1491
|
const message2 = err instanceof Error ? err.message : String(err);
|
|
1256
|
-
return { output: "", logs, error: message2, toolCalls };
|
|
1492
|
+
return { output: "", logs, error: message2, toolCalls, warnings };
|
|
1257
1493
|
} finally {
|
|
1258
1494
|
isolate.dispose();
|
|
1259
1495
|
}
|
|
1260
|
-
return { output: logs.join("\n"), logs, toolCalls };
|
|
1496
|
+
return { output: logs.join("\n"), logs, toolCalls, warnings };
|
|
1261
1497
|
}
|
|
1262
1498
|
async function runWithNodeVm(opts2) {
|
|
1263
1499
|
const { runInNewContext } = await import("vm");
|
|
@@ -1325,7 +1561,7 @@ async function runWithNodeVm(opts2) {
|
|
|
1325
1561
|
return result.content;
|
|
1326
1562
|
};
|
|
1327
1563
|
}
|
|
1328
|
-
const jsCode =
|
|
1564
|
+
const { js: jsCode, warnings } = await transpileOrStrip(opts2.code, opts2.ctx.cwd);
|
|
1329
1565
|
const wrapped = `"use strict";
|
|
1330
1566
|
(async function() {
|
|
1331
1567
|
${jsCode}
|
|
@@ -1336,9 +1572,9 @@ ${jsCode}
|
|
|
1336
1572
|
await new Promise((r) => setTimeout(r, 10));
|
|
1337
1573
|
} catch (err) {
|
|
1338
1574
|
const message2 = err instanceof Error ? err.message : String(err);
|
|
1339
|
-
return { output: "", logs, error: message2, toolCalls };
|
|
1575
|
+
return { output: "", logs, error: message2, toolCalls, warnings };
|
|
1340
1576
|
}
|
|
1341
|
-
return { output: logs.join("\n"), logs, toolCalls };
|
|
1577
|
+
return { output: logs.join("\n"), logs, toolCalls, warnings };
|
|
1342
1578
|
}
|
|
1343
1579
|
async function runInSandbox(opts2) {
|
|
1344
1580
|
try {
|
|
@@ -1499,7 +1735,9 @@ Use console.log() to return results. Only console.log output will be sent back t
|
|
|
1499
1735
|
maxCompletionTokens: opts2.maxCompletionTokens,
|
|
1500
1736
|
reasoningEffort: opts2.reasoningEffort,
|
|
1501
1737
|
sessionId: opts2.sessionId,
|
|
1502
|
-
gateway: opts2.gateway
|
|
1738
|
+
gateway: opts2.gateway,
|
|
1739
|
+
cloudMode: opts2.cloudMode,
|
|
1740
|
+
cloudToken: opts2.cloudToken
|
|
1503
1741
|
});
|
|
1504
1742
|
for await (const ev of events) {
|
|
1505
1743
|
switch (ev.type) {
|
|
@@ -1678,10 +1916,13 @@ Use console.log() to return results. Only console.log output will be sent back t
|
|
|
1678
1916
|
toolResults.push(toolResult);
|
|
1679
1917
|
opts2.callbacks.onToolResult?.(toolResult);
|
|
1680
1918
|
}
|
|
1681
|
-
const
|
|
1919
|
+
const warningPrefix = sandboxResult.warnings?.length ? `Warning: ${sandboxResult.warnings.join(" ")}
|
|
1920
|
+
|
|
1921
|
+
` : "";
|
|
1922
|
+
const resultContent = sandboxResult.error ? `${warningPrefix}Error: ${sandboxResult.error}
|
|
1682
1923
|
|
|
1683
1924
|
Output:
|
|
1684
|
-
${sandboxResult.output}` : sandboxResult.output
|
|
1925
|
+
${sandboxResult.output}` : `${warningPrefix}${sandboxResult.output}`;
|
|
1685
1926
|
const result = {
|
|
1686
1927
|
tool_call_id: tc.id,
|
|
1687
1928
|
name: "execute_code",
|
|
@@ -1715,25 +1956,44 @@ ${sandboxResult.output}` : sandboxResult.output;
|
|
|
1715
1956
|
opts2.callbacks.onToolResult?.(result);
|
|
1716
1957
|
if (opts2.memoryManager) {
|
|
1717
1958
|
let filePath;
|
|
1959
|
+
let toolArgs = {};
|
|
1718
1960
|
try {
|
|
1719
|
-
|
|
1720
|
-
filePath =
|
|
1961
|
+
toolArgs = JSON.parse(tc.function.arguments || "{}");
|
|
1962
|
+
filePath = toolArgs.path;
|
|
1721
1963
|
} catch {
|
|
1722
1964
|
}
|
|
1965
|
+
const lastAssistant = [...opts2.messages].reverse().find(
|
|
1966
|
+
(m) => m.role === "assistant" && m.tool_calls && m.tool_calls.length > 0
|
|
1967
|
+
);
|
|
1968
|
+
const assistantMessage = lastAssistant?.content ?? "";
|
|
1969
|
+
const llmOpts = opts2.memoryManager.getExtractionLlmOpts();
|
|
1723
1970
|
for (const extractor of EXTRACTORS) {
|
|
1724
1971
|
if (extractor.match(tc.function.name, filePath)) {
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1972
|
+
void (async () => {
|
|
1973
|
+
try {
|
|
1974
|
+
const memory = await extractor.extract(result.content, filePath, {
|
|
1975
|
+
toolArgs: { ...toolArgs, _toolName: tc.function.name },
|
|
1976
|
+
assistantMessage: typeof assistantMessage === "string" ? assistantMessage : "",
|
|
1977
|
+
llmOpts: {
|
|
1978
|
+
...llmOpts,
|
|
1979
|
+
signal: opts2.signal
|
|
1980
|
+
}
|
|
1981
|
+
});
|
|
1982
|
+
if (memory) {
|
|
1983
|
+
await opts2.memoryManager.remember(
|
|
1984
|
+
memory.content,
|
|
1985
|
+
memory.category,
|
|
1986
|
+
memory.importance,
|
|
1987
|
+
opts2.cwd,
|
|
1988
|
+
opts2.sessionId ?? "unknown",
|
|
1989
|
+
opts2.signal,
|
|
1990
|
+
void 0,
|
|
1991
|
+
memory.topicKey
|
|
1992
|
+
);
|
|
1993
|
+
}
|
|
1994
|
+
} catch {
|
|
1995
|
+
}
|
|
1996
|
+
})();
|
|
1737
1997
|
}
|
|
1738
1998
|
}
|
|
1739
1999
|
}
|
|
@@ -2014,11 +2274,11 @@ var init_mode = __esm({
|
|
|
2014
2274
|
|
|
2015
2275
|
// src/agent/system-prompt.ts
|
|
2016
2276
|
import { platform, release, homedir as homedir3 } from "os";
|
|
2017
|
-
import { basename, join as
|
|
2277
|
+
import { basename, join as join7 } from "path";
|
|
2018
2278
|
import { readFileSync as readFileSync2, statSync } from "fs";
|
|
2019
2279
|
function loadContextFile(cwd) {
|
|
2020
2280
|
for (const name of CONTEXT_FILENAMES) {
|
|
2021
|
-
const path =
|
|
2281
|
+
const path = join7(cwd, name);
|
|
2022
2282
|
try {
|
|
2023
2283
|
const s = statSync(path);
|
|
2024
2284
|
if (!s.isFile() || s.size > MAX_CONTEXT_BYTES) continue;
|
|
@@ -2173,7 +2433,7 @@ var init_read = __esm({
|
|
|
2173
2433
|
|
|
2174
2434
|
// src/tools/write.ts
|
|
2175
2435
|
import { mkdir as mkdir4, readFile as readFile4, writeFile as writeFile3 } from "fs/promises";
|
|
2176
|
-
import { dirname as
|
|
2436
|
+
import { dirname as dirname4 } from "path";
|
|
2177
2437
|
var writeTool;
|
|
2178
2438
|
var init_write = __esm({
|
|
2179
2439
|
"src/tools/write.ts"() {
|
|
@@ -2203,7 +2463,7 @@ var init_write = __esm({
|
|
|
2203
2463
|
before = await readFile4(abs, "utf8");
|
|
2204
2464
|
} catch {
|
|
2205
2465
|
}
|
|
2206
|
-
await mkdir4(
|
|
2466
|
+
await mkdir4(dirname4(abs), { recursive: true });
|
|
2207
2467
|
await writeFile3(abs, args.content, "utf8");
|
|
2208
2468
|
const verb = before ? "Overwrote" : "Created";
|
|
2209
2469
|
return `${verb} ${args.path} (${args.content.length} chars).`;
|
|
@@ -2270,7 +2530,7 @@ var init_edit = __esm({
|
|
|
2270
2530
|
// src/tools/bash.ts
|
|
2271
2531
|
import { spawn } from "child_process";
|
|
2272
2532
|
import { tmpdir } from "os";
|
|
2273
|
-
import { join as
|
|
2533
|
+
import { join as join8 } from "path";
|
|
2274
2534
|
function formatBashTitle(raw) {
|
|
2275
2535
|
let cmd = (raw ?? "").trim();
|
|
2276
2536
|
const m = cmd.match(/^cd\s+([^\s&;]+)\s*(?:&&|;)\s*(.*)$/);
|
|
@@ -2288,7 +2548,7 @@ function injectCoauthor(command, coauthor) {
|
|
|
2288
2548
|
const mentionsGit = /\bgit\b/.test(trimmed);
|
|
2289
2549
|
if (!createsCommit && !isRebaseContinue && !mentionsGit) return command;
|
|
2290
2550
|
if (movesHeadOnly) return command;
|
|
2291
|
-
const tmpFile =
|
|
2551
|
+
const tmpFile = join8(tmpdir(), `kf-coauthor-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`);
|
|
2292
2552
|
const amendBlock = `
|
|
2293
2553
|
if ! git log -1 --pretty=%B 2>/dev/null | grep -qF "${trailer}"; then
|
|
2294
2554
|
git log -1 --pretty=%B | git interpret-trailers --trailer "${trailer}" > "${tmpFile}" && git commit --amend -F "${tmpFile}" --no-edit && rm -f "${tmpFile}"
|
|
@@ -3452,16 +3712,16 @@ var init_executor = __esm({
|
|
|
3452
3712
|
// src/util/update-check.ts
|
|
3453
3713
|
import { readFile as readFile7, writeFile as writeFile5, mkdir as mkdir5 } from "fs/promises";
|
|
3454
3714
|
import { homedir as homedir5 } from "os";
|
|
3455
|
-
import { join as
|
|
3715
|
+
import { join as join9, dirname as dirname5 } from "path";
|
|
3456
3716
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
3457
3717
|
function cachePath() {
|
|
3458
|
-
const xdg = process.env.XDG_CONFIG_HOME ||
|
|
3459
|
-
return
|
|
3718
|
+
const xdg = process.env.XDG_CONFIG_HOME || join9(homedir5(), ".config");
|
|
3719
|
+
return join9(xdg, "kimiflare", "update-check.json");
|
|
3460
3720
|
}
|
|
3461
3721
|
async function findPackageJson(startDir) {
|
|
3462
3722
|
let dir = startDir;
|
|
3463
3723
|
while (true) {
|
|
3464
|
-
const candidate =
|
|
3724
|
+
const candidate = join9(dir, "package.json");
|
|
3465
3725
|
try {
|
|
3466
3726
|
const raw = await readFile7(candidate, "utf8");
|
|
3467
3727
|
const parsed = JSON.parse(raw);
|
|
@@ -3470,14 +3730,14 @@ async function findPackageJson(startDir) {
|
|
|
3470
3730
|
}
|
|
3471
3731
|
} catch {
|
|
3472
3732
|
}
|
|
3473
|
-
const parent =
|
|
3733
|
+
const parent = dirname5(dir);
|
|
3474
3734
|
if (parent === dir) break;
|
|
3475
3735
|
dir = parent;
|
|
3476
3736
|
}
|
|
3477
3737
|
return null;
|
|
3478
3738
|
}
|
|
3479
3739
|
async function readLocalVersion() {
|
|
3480
|
-
const here =
|
|
3740
|
+
const here = dirname5(fileURLToPath2(import.meta.url));
|
|
3481
3741
|
const found = await findPackageJson(here);
|
|
3482
3742
|
return found?.version ?? null;
|
|
3483
3743
|
}
|
|
@@ -3494,7 +3754,7 @@ async function readCache() {
|
|
|
3494
3754
|
}
|
|
3495
3755
|
async function writeCache(entry) {
|
|
3496
3756
|
const p = cachePath();
|
|
3497
|
-
await mkdir5(
|
|
3757
|
+
await mkdir5(dirname5(p), { recursive: true });
|
|
3498
3758
|
await writeFile5(p, JSON.stringify(entry), "utf8");
|
|
3499
3759
|
}
|
|
3500
3760
|
async function fetchLatestVersion() {
|
|
@@ -3554,20 +3814,20 @@ var init_update_check = __esm({
|
|
|
3554
3814
|
// src/remote/session-store.ts
|
|
3555
3815
|
import { readFile as readFile8, writeFile as writeFile6, mkdir as mkdir6, readdir as readdir2 } from "fs/promises";
|
|
3556
3816
|
import { homedir as homedir6 } from "os";
|
|
3557
|
-
import { join as
|
|
3817
|
+
import { join as join10 } from "path";
|
|
3558
3818
|
function remoteDir() {
|
|
3559
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
3560
|
-
return
|
|
3819
|
+
const xdg = process.env.XDG_DATA_HOME || join10(homedir6(), ".config");
|
|
3820
|
+
return join10(xdg, "kimiflare", "remote");
|
|
3561
3821
|
}
|
|
3562
3822
|
async function saveRemoteSession(session) {
|
|
3563
3823
|
const dir = remoteDir();
|
|
3564
3824
|
await mkdir6(dir, { recursive: true });
|
|
3565
|
-
const path =
|
|
3825
|
+
const path = join10(dir, `${session.sessionId}.json`);
|
|
3566
3826
|
await writeFile6(path, JSON.stringify(session, null, 2) + "\n", "utf8");
|
|
3567
3827
|
}
|
|
3568
3828
|
async function loadRemoteSession(sessionId) {
|
|
3569
3829
|
try {
|
|
3570
|
-
const path =
|
|
3830
|
+
const path = join10(remoteDir(), `${sessionId}.json`);
|
|
3571
3831
|
const raw = await readFile8(path, "utf8");
|
|
3572
3832
|
return JSON.parse(raw);
|
|
3573
3833
|
} catch {
|
|
@@ -3582,7 +3842,7 @@ async function listRemoteSessions() {
|
|
|
3582
3842
|
for (const file of files) {
|
|
3583
3843
|
if (!file.endsWith(".json")) continue;
|
|
3584
3844
|
try {
|
|
3585
|
-
const raw = await readFile8(
|
|
3845
|
+
const raw = await readFile8(join10(dir, file), "utf8");
|
|
3586
3846
|
sessions.push(JSON.parse(raw));
|
|
3587
3847
|
} catch {
|
|
3588
3848
|
}
|
|
@@ -3604,7 +3864,7 @@ var init_session_store = __esm({
|
|
|
3604
3864
|
|
|
3605
3865
|
// src/remote/deploy.ts
|
|
3606
3866
|
import { execSync } from "child_process";
|
|
3607
|
-
import { join as
|
|
3867
|
+
import { join as join11, dirname as dirname6 } from "path";
|
|
3608
3868
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
3609
3869
|
import { randomBytes } from "crypto";
|
|
3610
3870
|
function generateSecret() {
|
|
@@ -3639,7 +3899,7 @@ async function* deployForTui() {
|
|
|
3639
3899
|
yield { message: "Docker OK" };
|
|
3640
3900
|
yield { message: "Building remote agent bundle..." };
|
|
3641
3901
|
try {
|
|
3642
|
-
runCapture("npm run build:remote-agent",
|
|
3902
|
+
runCapture("npm run build:remote-agent", join11(REMOTE_DIR, ".."));
|
|
3643
3903
|
yield { message: "Agent bundle built" };
|
|
3644
3904
|
} catch (err) {
|
|
3645
3905
|
yield { message: `Build failed: ${err instanceof Error ? err.message : String(err)}`, error: true };
|
|
@@ -3768,9 +4028,9 @@ var init_deploy = __esm({
|
|
|
3768
4028
|
"src/remote/deploy.ts"() {
|
|
3769
4029
|
"use strict";
|
|
3770
4030
|
init_config();
|
|
3771
|
-
__dirname =
|
|
3772
|
-
REMOTE_DIR =
|
|
3773
|
-
WORKER_DIR =
|
|
4031
|
+
__dirname = dirname6(fileURLToPath3(import.meta.url));
|
|
4032
|
+
REMOTE_DIR = join11(__dirname, "..", "..", "..", "remote");
|
|
4033
|
+
WORKER_DIR = join11(REMOTE_DIR, "worker");
|
|
3774
4034
|
}
|
|
3775
4035
|
});
|
|
3776
4036
|
|
|
@@ -4194,11 +4454,11 @@ var init_heuristic = __esm({
|
|
|
4194
4454
|
|
|
4195
4455
|
// src/cost-attribution/classify-from-session.ts
|
|
4196
4456
|
import { readFile as readFile9 } from "fs/promises";
|
|
4197
|
-
import { join as
|
|
4457
|
+
import { join as join12 } from "path";
|
|
4198
4458
|
import { homedir as homedir7 } from "os";
|
|
4199
4459
|
function sessionsDir() {
|
|
4200
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
4201
|
-
return
|
|
4460
|
+
const xdg = process.env.XDG_DATA_HOME || join12(homedir7(), ".local", "share");
|
|
4461
|
+
return join12(xdg, "kimiflare", "sessions");
|
|
4202
4462
|
}
|
|
4203
4463
|
function parseToolCalls(calls) {
|
|
4204
4464
|
return calls.map((c) => {
|
|
@@ -4212,7 +4472,7 @@ function parseToolCalls(calls) {
|
|
|
4212
4472
|
}
|
|
4213
4473
|
async function classifyFromSessionFile(sessionId) {
|
|
4214
4474
|
try {
|
|
4215
|
-
const raw = await readFile9(
|
|
4475
|
+
const raw = await readFile9(join12(sessionsDir(), `${sessionId}.json`), "utf8");
|
|
4216
4476
|
const session = JSON.parse(raw);
|
|
4217
4477
|
const messages = session.messages ?? [];
|
|
4218
4478
|
const turns = [];
|
|
@@ -4246,14 +4506,14 @@ __export(cli_exports, {
|
|
|
4246
4506
|
runCostCommand: () => runCostCommand
|
|
4247
4507
|
});
|
|
4248
4508
|
import { readFile as readFile10 } from "fs/promises";
|
|
4249
|
-
import { join as
|
|
4509
|
+
import { join as join13 } from "path";
|
|
4250
4510
|
import { homedir as homedir8 } from "os";
|
|
4251
4511
|
function usageDir() {
|
|
4252
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
4253
|
-
return
|
|
4512
|
+
const xdg = process.env.XDG_DATA_HOME || join13(homedir8(), ".local", "share");
|
|
4513
|
+
return join13(xdg, "kimiflare");
|
|
4254
4514
|
}
|
|
4255
4515
|
function usagePath() {
|
|
4256
|
-
return
|
|
4516
|
+
return join13(usageDir(), "usage.json");
|
|
4257
4517
|
}
|
|
4258
4518
|
function today() {
|
|
4259
4519
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
@@ -4351,6 +4611,98 @@ var init_cli = __esm({
|
|
|
4351
4611
|
}
|
|
4352
4612
|
});
|
|
4353
4613
|
|
|
4614
|
+
// src/cloud/auth.ts
|
|
4615
|
+
var auth_exports = {};
|
|
4616
|
+
__export(auth_exports, {
|
|
4617
|
+
authenticateDevice: () => authenticateDevice,
|
|
4618
|
+
clearCloudCredentials: () => clearCloudCredentials,
|
|
4619
|
+
loadCloudCredentials: () => loadCloudCredentials,
|
|
4620
|
+
saveCloudCredentials: () => saveCloudCredentials
|
|
4621
|
+
});
|
|
4622
|
+
import { readFile as readFile11, writeFile as writeFile7 } from "fs/promises";
|
|
4623
|
+
import { homedir as homedir9 } from "os";
|
|
4624
|
+
import { join as join14 } from "path";
|
|
4625
|
+
function cloudCredPath() {
|
|
4626
|
+
const xdg = process.env.XDG_CONFIG_HOME || join14(homedir9(), ".config");
|
|
4627
|
+
return join14(xdg, "kimiflare", "cloud.json");
|
|
4628
|
+
}
|
|
4629
|
+
function generateCode() {
|
|
4630
|
+
const chars = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
|
|
4631
|
+
let out = "";
|
|
4632
|
+
for (let i = 0; i < 8; i++) {
|
|
4633
|
+
out += chars[Math.floor(Math.random() * chars.length)];
|
|
4634
|
+
}
|
|
4635
|
+
return out;
|
|
4636
|
+
}
|
|
4637
|
+
async function loadCloudCredentials() {
|
|
4638
|
+
try {
|
|
4639
|
+
const raw = await readFile11(cloudCredPath(), "utf8");
|
|
4640
|
+
const parsed = JSON.parse(raw);
|
|
4641
|
+
if (parsed.expiresAt && parsed.expiresAt > Date.now() / 1e3) {
|
|
4642
|
+
return parsed;
|
|
4643
|
+
}
|
|
4644
|
+
} catch {
|
|
4645
|
+
}
|
|
4646
|
+
return null;
|
|
4647
|
+
}
|
|
4648
|
+
async function saveCloudCredentials(creds) {
|
|
4649
|
+
const p = cloudCredPath();
|
|
4650
|
+
await writeFile7(p, JSON.stringify(creds, null, 2), "utf8");
|
|
4651
|
+
}
|
|
4652
|
+
async function clearCloudCredentials() {
|
|
4653
|
+
try {
|
|
4654
|
+
const { unlink: unlink4 } = await import("fs/promises");
|
|
4655
|
+
await unlink4(cloudCredPath());
|
|
4656
|
+
} catch {
|
|
4657
|
+
}
|
|
4658
|
+
}
|
|
4659
|
+
async function authenticateDevice(onStatus) {
|
|
4660
|
+
const deviceCode = `device-${generateCode()}-${Date.now()}`;
|
|
4661
|
+
const userCode = `${generateCode()}-${generateCode()}`;
|
|
4662
|
+
const registerRes = await fetch(`${CLOUD_API_URL}/auth/device`, {
|
|
4663
|
+
method: "POST",
|
|
4664
|
+
headers: { "Content-Type": "application/json" },
|
|
4665
|
+
body: JSON.stringify({ device_code: deviceCode, user_code: userCode })
|
|
4666
|
+
});
|
|
4667
|
+
if (!registerRes.ok) {
|
|
4668
|
+
const err = await registerRes.json().catch(() => ({}));
|
|
4669
|
+
throw new Error(`Failed to register device: ${err.error || registerRes.statusText}`);
|
|
4670
|
+
}
|
|
4671
|
+
const authUrl = `${CLOUD_API_URL}/auth/github?code=${encodeURIComponent(userCode)}`;
|
|
4672
|
+
onStatus({ url: authUrl, userCode, polling: false });
|
|
4673
|
+
const startTime = Date.now();
|
|
4674
|
+
while (Date.now() - startTime < POLL_TIMEOUT_MS) {
|
|
4675
|
+
await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
|
|
4676
|
+
onStatus({ url: authUrl, userCode, polling: true });
|
|
4677
|
+
const pollRes = await fetch(`${CLOUD_API_URL}/auth/poll`, {
|
|
4678
|
+
method: "POST",
|
|
4679
|
+
headers: { "Content-Type": "application/json" },
|
|
4680
|
+
body: JSON.stringify({ device_code: deviceCode })
|
|
4681
|
+
});
|
|
4682
|
+
if (!pollRes.ok) continue;
|
|
4683
|
+
const pollData = await pollRes.json();
|
|
4684
|
+
if (pollData.status === "approved" && pollData.access_token) {
|
|
4685
|
+
const creds = {
|
|
4686
|
+
accessToken: pollData.access_token,
|
|
4687
|
+
expiresAt: Math.floor(Date.now() / 1e3) + 7 * 24 * 60 * 60
|
|
4688
|
+
// 7 days
|
|
4689
|
+
};
|
|
4690
|
+
await saveCloudCredentials(creds);
|
|
4691
|
+
return creds;
|
|
4692
|
+
}
|
|
4693
|
+
}
|
|
4694
|
+
throw new Error("Authentication timed out. Please try again.");
|
|
4695
|
+
}
|
|
4696
|
+
var CLOUD_API_URL, POLL_INTERVAL_MS, POLL_TIMEOUT_MS;
|
|
4697
|
+
var init_auth = __esm({
|
|
4698
|
+
"src/cloud/auth.ts"() {
|
|
4699
|
+
"use strict";
|
|
4700
|
+
CLOUD_API_URL = "https://api.kimiflare.com";
|
|
4701
|
+
POLL_INTERVAL_MS = 5e3;
|
|
4702
|
+
POLL_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
4703
|
+
}
|
|
4704
|
+
});
|
|
4705
|
+
|
|
4354
4706
|
// src/remote/tui-auth.ts
|
|
4355
4707
|
var tui_auth_exports = {};
|
|
4356
4708
|
__export(tui_auth_exports, {
|
|
@@ -5260,9 +5612,9 @@ var init_connection = __esm({
|
|
|
5260
5612
|
});
|
|
5261
5613
|
|
|
5262
5614
|
// src/lsp/protocol.ts
|
|
5263
|
-
import { pathToFileURL, fileURLToPath as fileURLToPath4 } from "url";
|
|
5615
|
+
import { pathToFileURL as pathToFileURL2, fileURLToPath as fileURLToPath4 } from "url";
|
|
5264
5616
|
function toUri(path) {
|
|
5265
|
-
return
|
|
5617
|
+
return pathToFileURL2(path).href;
|
|
5266
5618
|
}
|
|
5267
5619
|
function fromUri(uri) {
|
|
5268
5620
|
return fileURLToPath4(uri);
|
|
@@ -6402,7 +6754,7 @@ import { useEffect, useState } from "react";
|
|
|
6402
6754
|
import { Box as Box5, Text as Text5 } from "ink";
|
|
6403
6755
|
import Spinner3 from "ink-spinner";
|
|
6404
6756
|
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
6405
|
-
function StatusBar({ model, usage, sessionUsage, thinking, turnStartedAt, mode, effort, contextLimit, hasUpdate, latestVersion, gatewayMeta, codeMode }) {
|
|
6757
|
+
function StatusBar({ model, usage, sessionUsage, thinking, turnStartedAt, mode, effort, contextLimit, hasUpdate, latestVersion, gatewayMeta, codeMode, cloudMode }) {
|
|
6406
6758
|
const theme = useTheme();
|
|
6407
6759
|
const [now2, setNow] = useState(Date.now());
|
|
6408
6760
|
const modeColor = mode === "plan" ? theme.modeBadge.plan : mode === "auto" ? theme.modeBadge.auto : theme.modeBadge.edit;
|
|
@@ -6414,6 +6766,7 @@ function StatusBar({ model, usage, sessionUsage, thinking, turnStartedAt, mode,
|
|
|
6414
6766
|
}, [thinking, turnStartedAt]);
|
|
6415
6767
|
const elapsed = turnStartedAt !== null ? formatElapsed(now2 - turnStartedAt) : null;
|
|
6416
6768
|
const leftParts = [`${shortModel(model)}`, effort];
|
|
6769
|
+
if (cloudMode) leftParts.push("CLOUD");
|
|
6417
6770
|
if (codeMode) leftParts.push("CODE");
|
|
6418
6771
|
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
|
|
6419
6772
|
/* @__PURE__ */ jsxs5(Box5, { children: [
|
|
@@ -7468,15 +7821,25 @@ var init_text_input = __esm({
|
|
|
7468
7821
|
// src/ui/onboarding.tsx
|
|
7469
7822
|
import { useState as useState5 } from "react";
|
|
7470
7823
|
import { Box as Box9, Text as Text10 } from "ink";
|
|
7824
|
+
import SelectInput3 from "ink-select-input";
|
|
7471
7825
|
import { Fragment, jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
7472
7826
|
function Onboarding({ onDone }) {
|
|
7473
7827
|
const theme = useTheme();
|
|
7474
|
-
const [step, setStep] = useState5("
|
|
7828
|
+
const [step, setStep] = useState5("mode");
|
|
7829
|
+
const [mode, setMode] = useState5("byok");
|
|
7475
7830
|
const [accountId, setAccountId] = useState5("");
|
|
7476
7831
|
const [apiToken, setApiToken] = useState5("");
|
|
7477
7832
|
const [model, setModel] = useState5(DEFAULT_MODEL);
|
|
7478
7833
|
const [savedPath, setSavedPath] = useState5(null);
|
|
7479
|
-
const
|
|
7834
|
+
const handleModeSelect = (item) => {
|
|
7835
|
+
if (item.value === "cloud") {
|
|
7836
|
+
setMode("cloud");
|
|
7837
|
+
setStep("cloudDone");
|
|
7838
|
+
} else {
|
|
7839
|
+
setMode("byok");
|
|
7840
|
+
setStep("accountId");
|
|
7841
|
+
}
|
|
7842
|
+
};
|
|
7480
7843
|
const handleAccountIdSubmit = (value) => {
|
|
7481
7844
|
const trimmed = value.trim();
|
|
7482
7845
|
if (!trimmed) return;
|
|
@@ -7495,7 +7858,7 @@ function Onboarding({ onDone }) {
|
|
|
7495
7858
|
setStep("confirm");
|
|
7496
7859
|
};
|
|
7497
7860
|
const handleConfirm = async () => {
|
|
7498
|
-
const cfg = { accountId, apiToken, model };
|
|
7861
|
+
const cfg = mode === "cloud" ? { accountId: "", apiToken: "", model, cloudMode: true } : { accountId, apiToken, model };
|
|
7499
7862
|
try {
|
|
7500
7863
|
const path = await saveConfig(cfg);
|
|
7501
7864
|
setSavedPath(path);
|
|
@@ -7504,6 +7867,19 @@ function Onboarding({ onDone }) {
|
|
|
7504
7867
|
setSavedPath(`error: ${e.message}`);
|
|
7505
7868
|
}
|
|
7506
7869
|
};
|
|
7870
|
+
const handleCloudSave = async () => {
|
|
7871
|
+
const cfg = { accountId: "", apiToken: "", model: DEFAULT_MODEL, cloudMode: true };
|
|
7872
|
+
try {
|
|
7873
|
+
const path = await saveConfig(cfg);
|
|
7874
|
+
setSavedPath(path);
|
|
7875
|
+
onDone(cfg);
|
|
7876
|
+
} catch (e) {
|
|
7877
|
+
setSavedPath(`error: ${e.message}`);
|
|
7878
|
+
}
|
|
7879
|
+
};
|
|
7880
|
+
const byokSteps = ["accountId", "apiToken", "model", "confirm"];
|
|
7881
|
+
const stepIndex = step === "mode" ? 1 : step === "cloudDone" ? 2 : byokSteps.indexOf(step) + 2;
|
|
7882
|
+
const totalSteps = mode === "cloud" ? 2 : byokSteps.length + 1;
|
|
7507
7883
|
return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", paddingY: 1, children: [
|
|
7508
7884
|
/* @__PURE__ */ jsxs9(Box9, { marginBottom: 1, children: [
|
|
7509
7885
|
/* @__PURE__ */ jsx11(Text10, { bold: true, color: theme.palette.primary, children: "kimiflare" }),
|
|
@@ -7516,9 +7892,22 @@ function Onboarding({ onDone }) {
|
|
|
7516
7892
|
"Step ",
|
|
7517
7893
|
stepIndex,
|
|
7518
7894
|
" of ",
|
|
7519
|
-
|
|
7895
|
+
totalSteps
|
|
7520
7896
|
] }),
|
|
7521
7897
|
/* @__PURE__ */ jsxs9(Box9, { marginTop: 1, flexDirection: "column", children: [
|
|
7898
|
+
step === "mode" && /* @__PURE__ */ jsxs9(Fragment, { children: [
|
|
7899
|
+
/* @__PURE__ */ jsx11(Text10, { children: "How do you want to connect?" }),
|
|
7900
|
+
/* @__PURE__ */ jsx11(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx11(
|
|
7901
|
+
SelectInput3,
|
|
7902
|
+
{
|
|
7903
|
+
items: [
|
|
7904
|
+
{ label: "Cloud (managed) \u2014 no API key needed", value: "cloud" },
|
|
7905
|
+
{ label: "BYOK \u2014 bring your own Cloudflare key", value: "byok" }
|
|
7906
|
+
],
|
|
7907
|
+
onSelect: handleModeSelect
|
|
7908
|
+
}
|
|
7909
|
+
) })
|
|
7910
|
+
] }),
|
|
7522
7911
|
step === "accountId" && /* @__PURE__ */ jsxs9(Fragment, { children: [
|
|
7523
7912
|
/* @__PURE__ */ jsx11(Text10, { children: "Enter your Cloudflare Account ID" }),
|
|
7524
7913
|
/* @__PURE__ */ jsxs9(Box9, { marginTop: 1, children: [
|
|
@@ -7608,6 +7997,23 @@ function Onboarding({ onDone }) {
|
|
|
7608
7997
|
)
|
|
7609
7998
|
] })
|
|
7610
7999
|
] }),
|
|
8000
|
+
step === "cloudDone" && /* @__PURE__ */ jsxs9(Fragment, { children: [
|
|
8001
|
+
/* @__PURE__ */ jsx11(Text10, { children: "Cloud mode selected" }),
|
|
8002
|
+
/* @__PURE__ */ jsx11(Text10, { color: theme.info.color, children: "No API key needed. Run `kimiflare auth cloud` to sign in." }),
|
|
8003
|
+
/* @__PURE__ */ jsx11(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx11(Text10, { children: "Press Enter to save, or Ctrl+C to cancel" }) }),
|
|
8004
|
+
/* @__PURE__ */ jsxs9(Box9, { marginTop: 1, children: [
|
|
8005
|
+
/* @__PURE__ */ jsx11(Text10, { color: theme.palette.primary, children: "\u203A " }),
|
|
8006
|
+
/* @__PURE__ */ jsx11(
|
|
8007
|
+
CustomTextInput,
|
|
8008
|
+
{
|
|
8009
|
+
value: "",
|
|
8010
|
+
onChange: () => {
|
|
8011
|
+
},
|
|
8012
|
+
onSubmit: handleCloudSave
|
|
8013
|
+
}
|
|
8014
|
+
)
|
|
8015
|
+
] })
|
|
8016
|
+
] }),
|
|
7611
8017
|
savedPath && /* @__PURE__ */ jsxs9(Text10, { color: theme.palette.success, children: [
|
|
7612
8018
|
"Config saved to ",
|
|
7613
8019
|
savedPath
|
|
@@ -7615,14 +8021,12 @@ function Onboarding({ onDone }) {
|
|
|
7615
8021
|
] })
|
|
7616
8022
|
] });
|
|
7617
8023
|
}
|
|
7618
|
-
var STEPS;
|
|
7619
8024
|
var init_onboarding = __esm({
|
|
7620
8025
|
"src/ui/onboarding.tsx"() {
|
|
7621
8026
|
"use strict";
|
|
7622
8027
|
init_text_input();
|
|
7623
8028
|
init_config();
|
|
7624
8029
|
init_theme_context();
|
|
7625
|
-
STEPS = ["accountId", "apiToken", "model", "confirm"];
|
|
7626
8030
|
}
|
|
7627
8031
|
});
|
|
7628
8032
|
|
|
@@ -7673,9 +8077,9 @@ var init_welcome = __esm({
|
|
|
7673
8077
|
// src/ui/help-menu.tsx
|
|
7674
8078
|
import { useState as useState6 } from "react";
|
|
7675
8079
|
import { Box as Box11, Text as Text12, useInput as useInput2 } from "ink";
|
|
7676
|
-
import
|
|
8080
|
+
import SelectInput4 from "ink-select-input";
|
|
7677
8081
|
import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
7678
|
-
function HelpMenu({ customCommands, costAttributionEnabled, onDone, onCommand }) {
|
|
8082
|
+
function HelpMenu({ customCommands, costAttributionEnabled, cloudMode, onDone, onCommand }) {
|
|
7679
8083
|
const theme = useTheme();
|
|
7680
8084
|
const [page, setPage] = useState6("main");
|
|
7681
8085
|
const customs = customCommands ?? [];
|
|
@@ -7692,8 +8096,9 @@ function HelpMenu({ customCommands, costAttributionEnabled, onDone, onCommand })
|
|
|
7692
8096
|
onCommand(command);
|
|
7693
8097
|
onDone();
|
|
7694
8098
|
};
|
|
8099
|
+
const categories = cloudMode ? CATEGORIES.filter((c) => c.key !== "gateway") : CATEGORIES;
|
|
7695
8100
|
if (page === "main") {
|
|
7696
|
-
const items2 =
|
|
8101
|
+
const items2 = categories.map((cat) => ({
|
|
7697
8102
|
label: cat.label,
|
|
7698
8103
|
value: cat.key,
|
|
7699
8104
|
key: cat.key
|
|
@@ -7706,7 +8111,7 @@ function HelpMenu({ customCommands, costAttributionEnabled, onDone, onCommand })
|
|
|
7706
8111
|
/* @__PURE__ */ jsx13(Text12, { color: theme.accent, bold: true, children: "Help" }),
|
|
7707
8112
|
/* @__PURE__ */ jsx13(Text12, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select, Esc to close." }),
|
|
7708
8113
|
/* @__PURE__ */ jsx13(Box11, { marginTop: 1, children: /* @__PURE__ */ jsx13(
|
|
7709
|
-
|
|
8114
|
+
SelectInput4,
|
|
7710
8115
|
{
|
|
7711
8116
|
items: items2,
|
|
7712
8117
|
onSelect: (item) => {
|
|
@@ -7733,7 +8138,7 @@ function HelpMenu({ customCommands, costAttributionEnabled, onDone, onCommand })
|
|
|
7733
8138
|
/* @__PURE__ */ jsx13(Text12, { color: theme.accent, bold: true, children: "Custom commands" }),
|
|
7734
8139
|
/* @__PURE__ */ jsx13(Text12, { color: theme.info.color, dimColor: false, children: customs.length === 0 ? "no custom commands found in .kimiflare/commands/" : "Arrow keys to navigate, Enter to run, Esc to go back." }),
|
|
7735
8140
|
/* @__PURE__ */ jsx13(Box11, { marginTop: 1, children: /* @__PURE__ */ jsx13(
|
|
7736
|
-
|
|
8141
|
+
SelectInput4,
|
|
7737
8142
|
{
|
|
7738
8143
|
items: items2,
|
|
7739
8144
|
onSelect: (item) => {
|
|
@@ -7747,7 +8152,7 @@ function HelpMenu({ customCommands, costAttributionEnabled, onDone, onCommand })
|
|
|
7747
8152
|
) })
|
|
7748
8153
|
] });
|
|
7749
8154
|
}
|
|
7750
|
-
const category =
|
|
8155
|
+
const category = categories.find((c) => c.key === page);
|
|
7751
8156
|
const selectable = category.commands.filter((cmd) => cmd.selectable !== false);
|
|
7752
8157
|
const staticCmds = category.commands.filter((cmd) => cmd.selectable === false);
|
|
7753
8158
|
const items = selectable.map((cmd) => ({
|
|
@@ -7760,7 +8165,7 @@ function HelpMenu({ customCommands, costAttributionEnabled, onDone, onCommand })
|
|
|
7760
8165
|
/* @__PURE__ */ jsx13(Text12, { color: theme.accent, bold: true, children: category.label }),
|
|
7761
8166
|
/* @__PURE__ */ jsx13(Text12, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to execute, Esc to go back." }),
|
|
7762
8167
|
/* @__PURE__ */ jsx13(Box11, { marginTop: 1, children: /* @__PURE__ */ jsx13(
|
|
7763
|
-
|
|
8168
|
+
SelectInput4,
|
|
7764
8169
|
{
|
|
7765
8170
|
items,
|
|
7766
8171
|
onSelect: (item) => {
|
|
@@ -8006,7 +8411,7 @@ var init_tui_deploy = __esm({
|
|
|
8006
8411
|
// src/ui/remote-dashboard.tsx
|
|
8007
8412
|
import { useEffect as useEffect4, useState as useState7 } from "react";
|
|
8008
8413
|
import { Box as Box12, Text as Text13, useInput as useInput3 } from "ink";
|
|
8009
|
-
import
|
|
8414
|
+
import SelectInput5 from "ink-select-input";
|
|
8010
8415
|
import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
8011
8416
|
function RemoteDashboard({ onSelect, onCancel }) {
|
|
8012
8417
|
const theme = useTheme();
|
|
@@ -8087,7 +8492,7 @@ function RemoteDashboard({ onSelect, onCancel }) {
|
|
|
8087
8492
|
refreshing ? "(refreshing...)" : ""
|
|
8088
8493
|
] }),
|
|
8089
8494
|
/* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(
|
|
8090
|
-
|
|
8495
|
+
SelectInput5,
|
|
8091
8496
|
{
|
|
8092
8497
|
items,
|
|
8093
8498
|
onSelect: (item) => {
|
|
@@ -8258,12 +8663,12 @@ __export(sessions_exports, {
|
|
|
8258
8663
|
pruneSessions: () => pruneSessions,
|
|
8259
8664
|
saveSession: () => saveSession
|
|
8260
8665
|
});
|
|
8261
|
-
import { readFile as
|
|
8262
|
-
import { homedir as
|
|
8263
|
-
import { join as
|
|
8666
|
+
import { readFile as readFile12, writeFile as writeFile8, mkdir as mkdir7, readdir as readdir3, stat as stat4 } from "fs/promises";
|
|
8667
|
+
import { homedir as homedir10 } from "os";
|
|
8668
|
+
import { join as join15 } from "path";
|
|
8264
8669
|
function sessionsDir2() {
|
|
8265
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
8266
|
-
return
|
|
8670
|
+
const xdg = process.env.XDG_DATA_HOME || join15(homedir10(), ".local", "share");
|
|
8671
|
+
return join15(xdg, "kimiflare", "sessions");
|
|
8267
8672
|
}
|
|
8268
8673
|
function sanitize(text) {
|
|
8269
8674
|
return text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40);
|
|
@@ -8276,8 +8681,8 @@ function makeSessionId(firstPrompt) {
|
|
|
8276
8681
|
async function saveSession(file) {
|
|
8277
8682
|
const dir = sessionsDir2();
|
|
8278
8683
|
await mkdir7(dir, { recursive: true });
|
|
8279
|
-
const path =
|
|
8280
|
-
await
|
|
8684
|
+
const path = join15(dir, `${file.id}.json`);
|
|
8685
|
+
await writeFile8(path, JSON.stringify(file, null, 2), "utf8");
|
|
8281
8686
|
return path;
|
|
8282
8687
|
}
|
|
8283
8688
|
async function pruneSessions() {
|
|
@@ -8296,9 +8701,9 @@ async function listSessions(limit = 30, cwd) {
|
|
|
8296
8701
|
const summaries = [];
|
|
8297
8702
|
for (const name of entries) {
|
|
8298
8703
|
if (!name.endsWith(".json")) continue;
|
|
8299
|
-
const path =
|
|
8704
|
+
const path = join15(dir, name);
|
|
8300
8705
|
try {
|
|
8301
|
-
const [s, raw] = await Promise.all([stat4(path),
|
|
8706
|
+
const [s, raw] = await Promise.all([stat4(path), readFile12(path, "utf8")]);
|
|
8302
8707
|
const parsed = JSON.parse(raw);
|
|
8303
8708
|
if (cwd && parsed.cwd !== cwd) continue;
|
|
8304
8709
|
const firstUser = parsed.messages.find((m) => m.role === "user");
|
|
@@ -8318,7 +8723,7 @@ async function listSessions(limit = 30, cwd) {
|
|
|
8318
8723
|
return summaries.slice(0, limit);
|
|
8319
8724
|
}
|
|
8320
8725
|
async function loadSession(filePath) {
|
|
8321
|
-
const raw = await
|
|
8726
|
+
const raw = await readFile12(filePath, "utf8");
|
|
8322
8727
|
return JSON.parse(raw);
|
|
8323
8728
|
}
|
|
8324
8729
|
var init_sessions = __esm({
|
|
@@ -8329,10 +8734,10 @@ var init_sessions = __esm({
|
|
|
8329
8734
|
});
|
|
8330
8735
|
|
|
8331
8736
|
// src/util/image.ts
|
|
8332
|
-
import { readFile as
|
|
8737
|
+
import { readFile as readFile13 } from "fs/promises";
|
|
8333
8738
|
import { basename as basename3 } from "path";
|
|
8334
8739
|
async function encodeImageFile(filePath) {
|
|
8335
|
-
const buf = await
|
|
8740
|
+
const buf = await readFile13(filePath);
|
|
8336
8741
|
if (buf.byteLength > MAX_IMAGE_BYTES) {
|
|
8337
8742
|
throw new Error(
|
|
8338
8743
|
`image too large (${(buf.byteLength / 1024 / 1024).toFixed(1)} MB); max is ${MAX_IMAGE_BYTES / 1024 / 1024} MB`
|
|
@@ -8368,15 +8773,15 @@ var init_image = __esm({
|
|
|
8368
8773
|
});
|
|
8369
8774
|
|
|
8370
8775
|
// src/usage-tracker.ts
|
|
8371
|
-
import { readFile as
|
|
8372
|
-
import { homedir as
|
|
8373
|
-
import { join as
|
|
8776
|
+
import { readFile as readFile14, writeFile as writeFile9, mkdir as mkdir8 } from "fs/promises";
|
|
8777
|
+
import { homedir as homedir11 } from "os";
|
|
8778
|
+
import { join as join16 } from "path";
|
|
8374
8779
|
function usageDir2() {
|
|
8375
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
8376
|
-
return
|
|
8780
|
+
const xdg = process.env.XDG_DATA_HOME || join16(homedir11(), ".local", "share");
|
|
8781
|
+
return join16(xdg, "kimiflare");
|
|
8377
8782
|
}
|
|
8378
8783
|
function usagePath2() {
|
|
8379
|
-
return
|
|
8784
|
+
return join16(usageDir2(), "usage.json");
|
|
8380
8785
|
}
|
|
8381
8786
|
function today2() {
|
|
8382
8787
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
@@ -8387,7 +8792,7 @@ function cutoffDate(daysBack) {
|
|
|
8387
8792
|
}
|
|
8388
8793
|
async function loadLog2() {
|
|
8389
8794
|
try {
|
|
8390
|
-
const raw = await
|
|
8795
|
+
const raw = await readFile14(usagePath2(), "utf8");
|
|
8391
8796
|
const parsed = JSON.parse(raw);
|
|
8392
8797
|
if (parsed.version === LOG_VERSION2) return parsed;
|
|
8393
8798
|
} catch {
|
|
@@ -8396,7 +8801,7 @@ async function loadLog2() {
|
|
|
8396
8801
|
}
|
|
8397
8802
|
async function saveLog(log) {
|
|
8398
8803
|
await mkdir8(usageDir2(), { recursive: true });
|
|
8399
|
-
await
|
|
8804
|
+
await writeFile9(usagePath2(), JSON.stringify(log, null, 2), "utf8");
|
|
8400
8805
|
}
|
|
8401
8806
|
function getOrCreateDay(log, date) {
|
|
8402
8807
|
let day = log.days.find((d) => d.date === date);
|
|
@@ -8602,7 +9007,7 @@ __export(db_exports, {
|
|
|
8602
9007
|
updateMemoryEmbedding: () => updateMemoryEmbedding
|
|
8603
9008
|
});
|
|
8604
9009
|
import Database from "better-sqlite3";
|
|
8605
|
-
import { dirname as
|
|
9010
|
+
import { dirname as dirname7 } from "path";
|
|
8606
9011
|
import { mkdirSync, statSync as statSync2 } from "fs";
|
|
8607
9012
|
function initSchema(db) {
|
|
8608
9013
|
db.exec(`
|
|
@@ -8687,7 +9092,7 @@ function openMemoryDb(dbPath) {
|
|
|
8687
9092
|
if (dbInstance) {
|
|
8688
9093
|
dbInstance.close();
|
|
8689
9094
|
}
|
|
8690
|
-
mkdirSync(
|
|
9095
|
+
mkdirSync(dirname7(dbPath), { recursive: true });
|
|
8691
9096
|
dbInstance = new Database(dbPath);
|
|
8692
9097
|
dbInstance.pragma("journal_mode = WAL");
|
|
8693
9098
|
dbInstance.pragma("foreign_keys = ON");
|
|
@@ -9392,6 +9797,18 @@ Return a JSON array of strings. Example:
|
|
|
9392
9797
|
gateway: this.opts.gateway
|
|
9393
9798
|
};
|
|
9394
9799
|
}
|
|
9800
|
+
get extractionLlmOpts() {
|
|
9801
|
+
return {
|
|
9802
|
+
accountId: this.opts.accountId,
|
|
9803
|
+
apiToken: this.opts.apiToken,
|
|
9804
|
+
model: this.opts.extractionModel ?? "@cf/meta/llama-3.2-3b-instruct",
|
|
9805
|
+
gateway: this.opts.gateway
|
|
9806
|
+
};
|
|
9807
|
+
}
|
|
9808
|
+
/** Expose extraction LLM opts so the agent loop can pass them to extractors. */
|
|
9809
|
+
getExtractionLlmOpts() {
|
|
9810
|
+
return this.extractionLlmOpts;
|
|
9811
|
+
}
|
|
9395
9812
|
shouldRedact() {
|
|
9396
9813
|
return this.opts.redactSecrets !== false;
|
|
9397
9814
|
}
|
|
@@ -9399,7 +9816,7 @@ Return a JSON array of strings. Example:
|
|
|
9399
9816
|
* Store a memory with verification, topic-key normalization, hypothetical queries,
|
|
9400
9817
|
* secret redaction, and supersession.
|
|
9401
9818
|
*/
|
|
9402
|
-
async remember(content, category, importance, repoPath, sessionId, signal, agentRole) {
|
|
9819
|
+
async remember(content, category, importance, repoPath, sessionId, signal, agentRole, topicKey) {
|
|
9403
9820
|
if (!this.db) throw new Error("Memory DB not open");
|
|
9404
9821
|
let safeContent = this.shouldRedact() ? redactSecrets(content) : content;
|
|
9405
9822
|
if (!safeContent.trim()) {
|
|
@@ -9412,10 +9829,10 @@ Return a JSON array of strings. Example:
|
|
|
9412
9829
|
if (verified.corrected_content) {
|
|
9413
9830
|
safeContent = verified.corrected_content;
|
|
9414
9831
|
}
|
|
9415
|
-
const
|
|
9832
|
+
const resolvedTopicKey = topicKey?.trim() || this.normalizeTopicKey(safeContent, repoPath);
|
|
9416
9833
|
const supersededIds = [];
|
|
9417
|
-
if (
|
|
9418
|
-
const existing = findMemoriesByTopicKey(this.db, repoPath,
|
|
9834
|
+
if (resolvedTopicKey) {
|
|
9835
|
+
const existing = findMemoriesByTopicKey(this.db, repoPath, resolvedTopicKey);
|
|
9419
9836
|
for (const old of existing) {
|
|
9420
9837
|
supersedeMemory(this.db, old.id, "pending");
|
|
9421
9838
|
supersededIds.push(old.id);
|
|
@@ -9436,7 +9853,7 @@ Return a JSON array of strings. Example:
|
|
|
9436
9853
|
sourceSessionId: sessionId,
|
|
9437
9854
|
repoPath,
|
|
9438
9855
|
importance: Math.max(1, Math.min(5, importance)),
|
|
9439
|
-
topicKey:
|
|
9856
|
+
topicKey: resolvedTopicKey ?? void 0,
|
|
9440
9857
|
agentRole
|
|
9441
9858
|
};
|
|
9442
9859
|
const memory = insertMemory(this.db, input, embeddings[0]);
|
|
@@ -9614,16 +10031,16 @@ Context: This memory was explicitly provided by the user during a conversation.`
|
|
|
9614
10031
|
});
|
|
9615
10032
|
|
|
9616
10033
|
// src/util/state.ts
|
|
9617
|
-
import { readFile as
|
|
9618
|
-
import { homedir as
|
|
9619
|
-
import { join as
|
|
10034
|
+
import { readFile as readFile15, writeFile as writeFile10, mkdir as mkdir9 } from "fs/promises";
|
|
10035
|
+
import { homedir as homedir12 } from "os";
|
|
10036
|
+
import { join as join18 } from "path";
|
|
9620
10037
|
function statePath() {
|
|
9621
|
-
const xdg = process.env.XDG_CONFIG_HOME ||
|
|
9622
|
-
return
|
|
10038
|
+
const xdg = process.env.XDG_CONFIG_HOME || join18(homedir12(), ".config");
|
|
10039
|
+
return join18(xdg, "kimiflare", "state.json");
|
|
9623
10040
|
}
|
|
9624
10041
|
async function readState() {
|
|
9625
10042
|
try {
|
|
9626
|
-
const raw = await
|
|
10043
|
+
const raw = await readFile15(statePath(), "utf8");
|
|
9627
10044
|
return JSON.parse(raw);
|
|
9628
10045
|
} catch {
|
|
9629
10046
|
return {};
|
|
@@ -9631,8 +10048,8 @@ async function readState() {
|
|
|
9631
10048
|
}
|
|
9632
10049
|
async function writeState(state) {
|
|
9633
10050
|
const path = statePath();
|
|
9634
|
-
await mkdir9(
|
|
9635
|
-
await
|
|
10051
|
+
await mkdir9(join18(path, ".."), { recursive: true });
|
|
10052
|
+
await writeFile10(path, JSON.stringify(state, null, 2) + "\n", "utf8");
|
|
9636
10053
|
}
|
|
9637
10054
|
async function markCreatorMessageSeen(version) {
|
|
9638
10055
|
const state = await readState();
|
|
@@ -9705,15 +10122,15 @@ var init_frontmatter = __esm({
|
|
|
9705
10122
|
|
|
9706
10123
|
// src/commands/loader.ts
|
|
9707
10124
|
import { open, realpath } from "fs/promises";
|
|
9708
|
-
import { homedir as
|
|
9709
|
-
import { join as
|
|
10125
|
+
import { homedir as homedir13 } from "os";
|
|
10126
|
+
import { join as join19, relative as relative4, sep as sep2 } from "path";
|
|
9710
10127
|
import fg3 from "fast-glob";
|
|
9711
10128
|
function projectCommandsDir(cwd = process.cwd()) {
|
|
9712
|
-
return
|
|
10129
|
+
return join19(cwd, ".kimiflare", "commands");
|
|
9713
10130
|
}
|
|
9714
10131
|
function globalCommandsDir() {
|
|
9715
|
-
const xdg = process.env.XDG_CONFIG_HOME ||
|
|
9716
|
-
return
|
|
10132
|
+
const xdg = process.env.XDG_CONFIG_HOME || join19(homedir13(), ".config");
|
|
10133
|
+
return join19(xdg, "kimiflare", "commands");
|
|
9717
10134
|
}
|
|
9718
10135
|
async function loadCustomCommands(cwd = process.cwd()) {
|
|
9719
10136
|
const warnings = [];
|
|
@@ -10089,8 +10506,8 @@ var init_builtins = __esm({
|
|
|
10089
10506
|
});
|
|
10090
10507
|
|
|
10091
10508
|
// src/commands/save.ts
|
|
10092
|
-
import { mkdir as mkdir10, writeFile as
|
|
10093
|
-
import { dirname as
|
|
10509
|
+
import { mkdir as mkdir10, writeFile as writeFile11, unlink as unlink2 } from "fs/promises";
|
|
10510
|
+
import { dirname as dirname8 } from "path";
|
|
10094
10511
|
async function saveCustomCommand(opts2) {
|
|
10095
10512
|
const dir = opts2.source === "project" ? projectCommandsDir(opts2.cwd) : globalCommandsDir();
|
|
10096
10513
|
const filepath = `${dir}/${opts2.name}.md`;
|
|
@@ -10101,8 +10518,8 @@ async function saveCustomCommand(opts2) {
|
|
|
10101
10518
|
if (opts2.effort) data.effort = opts2.effort;
|
|
10102
10519
|
const frontmatter = serializeFrontmatter(data);
|
|
10103
10520
|
const content = frontmatter + opts2.template;
|
|
10104
|
-
await mkdir10(
|
|
10105
|
-
await
|
|
10521
|
+
await mkdir10(dirname8(filepath), { recursive: true });
|
|
10522
|
+
await writeFile11(filepath, content, "utf8");
|
|
10106
10523
|
return { filepath };
|
|
10107
10524
|
}
|
|
10108
10525
|
async function deleteCustomCommand(cmd) {
|
|
@@ -10119,7 +10536,7 @@ var init_save = __esm({
|
|
|
10119
10536
|
// src/ui/command-wizard.tsx
|
|
10120
10537
|
import { useState as useState8 } from "react";
|
|
10121
10538
|
import { Box as Box13, Text as Text14, useInput as useInput4, useWindowSize as useWindowSize2 } from "ink";
|
|
10122
|
-
import
|
|
10539
|
+
import SelectInput6 from "ink-select-input";
|
|
10123
10540
|
import { Fragment as Fragment2, jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
10124
10541
|
function CommandWizard({ mode, initial, existingNames, builtinNames, onDone, onSave }) {
|
|
10125
10542
|
const theme = useTheme();
|
|
@@ -10372,7 +10789,7 @@ ${template}`;
|
|
|
10372
10789
|
")"
|
|
10373
10790
|
] }),
|
|
10374
10791
|
/* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
|
|
10375
|
-
|
|
10792
|
+
SelectInput6,
|
|
10376
10793
|
{
|
|
10377
10794
|
items,
|
|
10378
10795
|
onSelect: (item) => {
|
|
@@ -10401,7 +10818,7 @@ ${template}`;
|
|
|
10401
10818
|
] }),
|
|
10402
10819
|
/* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Saved to file but not yet enforced at runtime" }),
|
|
10403
10820
|
/* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
|
|
10404
|
-
|
|
10821
|
+
SelectInput6,
|
|
10405
10822
|
{
|
|
10406
10823
|
items,
|
|
10407
10824
|
onSelect: (item) => {
|
|
@@ -10429,7 +10846,7 @@ ${template}`;
|
|
|
10429
10846
|
")"
|
|
10430
10847
|
] }),
|
|
10431
10848
|
/* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
|
|
10432
|
-
|
|
10849
|
+
SelectInput6,
|
|
10433
10850
|
{
|
|
10434
10851
|
items,
|
|
10435
10852
|
onSelect: (item) => {
|
|
@@ -10475,7 +10892,7 @@ ${template}`;
|
|
|
10475
10892
|
")"
|
|
10476
10893
|
] }),
|
|
10477
10894
|
/* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
|
|
10478
|
-
|
|
10895
|
+
SelectInput6,
|
|
10479
10896
|
{
|
|
10480
10897
|
items,
|
|
10481
10898
|
onSelect: (item) => {
|
|
@@ -10508,7 +10925,7 @@ ${template}`;
|
|
|
10508
10925
|
] }),
|
|
10509
10926
|
/* @__PURE__ */ jsx15(Box13, { marginTop: 1, flexDirection: "column", children: previewContent().split("\n").map((line, i) => /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: line || " " }, i)) }),
|
|
10510
10927
|
/* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
|
|
10511
|
-
|
|
10928
|
+
SelectInput6,
|
|
10512
10929
|
{
|
|
10513
10930
|
items,
|
|
10514
10931
|
onSelect: (item) => handleConfirm(item.value)
|
|
@@ -10532,7 +10949,7 @@ var init_command_wizard = __esm({
|
|
|
10532
10949
|
|
|
10533
10950
|
// src/ui/command-picker.tsx
|
|
10534
10951
|
import { Box as Box14, Text as Text15 } from "ink";
|
|
10535
|
-
import
|
|
10952
|
+
import SelectInput7 from "ink-select-input";
|
|
10536
10953
|
import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
10537
10954
|
function CommandPicker({ commands, title, onPick }) {
|
|
10538
10955
|
const theme = useTheme();
|
|
@@ -10546,7 +10963,7 @@ function CommandPicker({ commands, title, onPick }) {
|
|
|
10546
10963
|
/* @__PURE__ */ jsx16(Text15, { color: theme.accent, bold: true, children: title }),
|
|
10547
10964
|
/* @__PURE__ */ jsx16(Text15, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select." }),
|
|
10548
10965
|
/* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(
|
|
10549
|
-
|
|
10966
|
+
SelectInput7,
|
|
10550
10967
|
{
|
|
10551
10968
|
items,
|
|
10552
10969
|
onSelect: (item) => {
|
|
@@ -10643,7 +11060,7 @@ var init_command_list = __esm({
|
|
|
10643
11060
|
// src/ui/lsp-wizard.tsx
|
|
10644
11061
|
import { useState as useState9 } from "react";
|
|
10645
11062
|
import { Box as Box16, Text as Text17 } from "ink";
|
|
10646
|
-
import
|
|
11063
|
+
import SelectInput8 from "ink-select-input";
|
|
10647
11064
|
import { spawn as spawn3 } from "child_process";
|
|
10648
11065
|
import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
10649
11066
|
function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
@@ -10760,7 +11177,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
10760
11177
|
/* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "LSP Servers" }),
|
|
10761
11178
|
/* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select." }),
|
|
10762
11179
|
/* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
|
|
10763
|
-
|
|
11180
|
+
SelectInput8,
|
|
10764
11181
|
{
|
|
10765
11182
|
items: mainItems,
|
|
10766
11183
|
onSelect: (item) => {
|
|
@@ -10791,7 +11208,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
10791
11208
|
/* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Add LSP Server" }),
|
|
10792
11209
|
/* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Select a language server to configure." }),
|
|
10793
11210
|
/* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
|
|
10794
|
-
|
|
11211
|
+
SelectInput8,
|
|
10795
11212
|
{
|
|
10796
11213
|
items,
|
|
10797
11214
|
onSelect: (item) => {
|
|
@@ -10830,7 +11247,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
10830
11247
|
] }),
|
|
10831
11248
|
installState.output && /* @__PURE__ */ jsx18(Box16, { marginTop: 1, flexDirection: "column", children: /* @__PURE__ */ jsx18(Text17, { color: isSuccess ? theme.accent : theme.error, children: installState.output.slice(-500) }) }),
|
|
10832
11249
|
/* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
|
|
10833
|
-
|
|
11250
|
+
SelectInput8,
|
|
10834
11251
|
{
|
|
10835
11252
|
items,
|
|
10836
11253
|
onSelect: (item) => {
|
|
@@ -10871,7 +11288,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
10871
11288
|
)
|
|
10872
11289
|
] }),
|
|
10873
11290
|
/* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
|
|
10874
|
-
|
|
11291
|
+
SelectInput8,
|
|
10875
11292
|
{
|
|
10876
11293
|
items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
|
|
10877
11294
|
onSelect: () => setPage("add")
|
|
@@ -10900,7 +11317,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
10900
11317
|
)
|
|
10901
11318
|
] }),
|
|
10902
11319
|
/* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
|
|
10903
|
-
|
|
11320
|
+
SelectInput8,
|
|
10904
11321
|
{
|
|
10905
11322
|
items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
|
|
10906
11323
|
onSelect: () => setPage("custom-name")
|
|
@@ -10927,7 +11344,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
10927
11344
|
/* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Save LSP Config" }),
|
|
10928
11345
|
/* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Where should this server configuration be saved?" }),
|
|
10929
11346
|
/* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
|
|
10930
|
-
|
|
11347
|
+
SelectInput8,
|
|
10931
11348
|
{
|
|
10932
11349
|
items,
|
|
10933
11350
|
onSelect: (item) => {
|
|
@@ -10949,7 +11366,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
10949
11366
|
/* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Edit LSP Server" }),
|
|
10950
11367
|
/* @__PURE__ */ jsx18(Text17, { color: theme.info.color, children: "No servers configured." }),
|
|
10951
11368
|
/* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
|
|
10952
|
-
|
|
11369
|
+
SelectInput8,
|
|
10953
11370
|
{
|
|
10954
11371
|
items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
|
|
10955
11372
|
onSelect: () => setPage("main")
|
|
@@ -10973,7 +11390,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
10973
11390
|
/* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Edit LSP Server" }),
|
|
10974
11391
|
/* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Select a server to toggle enabled/disabled." }),
|
|
10975
11392
|
/* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
|
|
10976
|
-
|
|
11393
|
+
SelectInput8,
|
|
10977
11394
|
{
|
|
10978
11395
|
items,
|
|
10979
11396
|
onSelect: (item) => {
|
|
@@ -10994,7 +11411,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
10994
11411
|
/* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Delete LSP Server" }),
|
|
10995
11412
|
/* @__PURE__ */ jsx18(Text17, { color: theme.info.color, children: "No servers configured." }),
|
|
10996
11413
|
/* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
|
|
10997
|
-
|
|
11414
|
+
SelectInput8,
|
|
10998
11415
|
{
|
|
10999
11416
|
items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
|
|
11000
11417
|
onSelect: () => setPage("main")
|
|
@@ -11014,7 +11431,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
11014
11431
|
/* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Delete LSP Server" }),
|
|
11015
11432
|
/* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Select a server to remove from config." }),
|
|
11016
11433
|
/* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
|
|
11017
|
-
|
|
11434
|
+
SelectInput8,
|
|
11018
11435
|
{
|
|
11019
11436
|
items,
|
|
11020
11437
|
onSelect: (item) => {
|
|
@@ -11038,7 +11455,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
11038
11455
|
return /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, children: ` ${k.padEnd(16)} ${status} ${s.command.join(" ")}` }, k);
|
|
11039
11456
|
}) }),
|
|
11040
11457
|
/* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
|
|
11041
|
-
|
|
11458
|
+
SelectInput8,
|
|
11042
11459
|
{
|
|
11043
11460
|
items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
|
|
11044
11461
|
onSelect: () => setPage("main")
|
|
@@ -11165,7 +11582,7 @@ var init_lsp_wizard = __esm({
|
|
|
11165
11582
|
|
|
11166
11583
|
// src/ui/theme-picker.tsx
|
|
11167
11584
|
import { Box as Box17, Text as Text18 } from "ink";
|
|
11168
|
-
import
|
|
11585
|
+
import SelectInput9 from "ink-select-input";
|
|
11169
11586
|
import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
11170
11587
|
function PaletteSwatches({ palette }) {
|
|
11171
11588
|
const colors = [
|
|
@@ -11185,7 +11602,7 @@ function ThemePicker({ themes, onPick, onPreview }) {
|
|
|
11185
11602
|
return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: current.accent, paddingX: 1, children: [
|
|
11186
11603
|
/* @__PURE__ */ jsx19(Text18, { color: current.accent, bold: true, children: "Pick a theme" }),
|
|
11187
11604
|
/* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
|
|
11188
|
-
|
|
11605
|
+
SelectInput9,
|
|
11189
11606
|
{
|
|
11190
11607
|
items,
|
|
11191
11608
|
onHighlight: (item) => {
|
|
@@ -11523,15 +11940,15 @@ var tui_report_exports = {};
|
|
|
11523
11940
|
__export(tui_report_exports, {
|
|
11524
11941
|
getCategoryReportText: () => getCategoryReportText
|
|
11525
11942
|
});
|
|
11526
|
-
import { readFile as
|
|
11527
|
-
import { join as
|
|
11528
|
-
import { homedir as
|
|
11943
|
+
import { readFile as readFile16 } from "fs/promises";
|
|
11944
|
+
import { join as join20 } from "path";
|
|
11945
|
+
import { homedir as homedir14 } from "os";
|
|
11529
11946
|
function usageDir3() {
|
|
11530
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
11531
|
-
return
|
|
11947
|
+
const xdg = process.env.XDG_DATA_HOME || join20(homedir14(), ".local", "share");
|
|
11948
|
+
return join20(xdg, "kimiflare");
|
|
11532
11949
|
}
|
|
11533
11950
|
function usagePath3() {
|
|
11534
|
-
return
|
|
11951
|
+
return join20(usageDir3(), "usage.json");
|
|
11535
11952
|
}
|
|
11536
11953
|
function today3() {
|
|
11537
11954
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
@@ -11543,7 +11960,7 @@ function daysAgo2(n) {
|
|
|
11543
11960
|
}
|
|
11544
11961
|
async function loadLog3() {
|
|
11545
11962
|
try {
|
|
11546
|
-
const raw = await
|
|
11963
|
+
const raw = await readFile16(usagePath3(), "utf8");
|
|
11547
11964
|
return JSON.parse(raw);
|
|
11548
11965
|
} catch {
|
|
11549
11966
|
return { version: 1, days: [], sessions: [] };
|
|
@@ -11611,9 +12028,9 @@ __export(app_exports, {
|
|
|
11611
12028
|
});
|
|
11612
12029
|
import React14, { useState as useState10, useRef as useRef3, useEffect as useEffect5, useCallback } from "react";
|
|
11613
12030
|
import { Box as Box20, Text as Text21, useApp, useInput as useInput6, render } from "ink";
|
|
11614
|
-
import
|
|
12031
|
+
import SelectInput10 from "ink-select-input";
|
|
11615
12032
|
import { existsSync as existsSync2, statSync as statSync3 } from "fs";
|
|
11616
|
-
import { join as
|
|
12033
|
+
import { join as join21 } from "path";
|
|
11617
12034
|
import { unlink as unlink3 } from "fs/promises";
|
|
11618
12035
|
import { execSync as execSync2 } from "child_process";
|
|
11619
12036
|
import { spawn as spawn4 } from "child_process";
|
|
@@ -11691,7 +12108,7 @@ function buildFilePickerIgnoreList(cwd) {
|
|
|
11691
12108
|
];
|
|
11692
12109
|
const gitignorePatterns = [];
|
|
11693
12110
|
try {
|
|
11694
|
-
const gitignorePath =
|
|
12111
|
+
const gitignorePath = join21(cwd, ".gitignore");
|
|
11695
12112
|
const stats = statSync3(gitignorePath);
|
|
11696
12113
|
if (stats.size > MAX_GITIGNORE_SIZE) {
|
|
11697
12114
|
return hardcoded;
|
|
@@ -11844,7 +12261,8 @@ function App({
|
|
|
11844
12261
|
initialCfg,
|
|
11845
12262
|
initialUpdateResult,
|
|
11846
12263
|
initialLspScope,
|
|
11847
|
-
initialLspProjectPath
|
|
12264
|
+
initialLspProjectPath,
|
|
12265
|
+
initialCloudToken
|
|
11848
12266
|
}) {
|
|
11849
12267
|
const { exit } = useApp();
|
|
11850
12268
|
const [cfg, setCfg] = useState10(initialCfg);
|
|
@@ -12108,13 +12526,14 @@ function App({
|
|
|
12108
12526
|
}
|
|
12109
12527
|
});
|
|
12110
12528
|
if (cfg.memoryEnabled) {
|
|
12111
|
-
const dbPath = cfg.memoryDbPath ??
|
|
12529
|
+
const dbPath = cfg.memoryDbPath ?? join21(process.cwd(), ".kimiflare", "memory.db");
|
|
12112
12530
|
const manager = new MemoryManager({
|
|
12113
12531
|
dbPath,
|
|
12114
12532
|
accountId: cfg.accountId,
|
|
12115
12533
|
apiToken: cfg.apiToken,
|
|
12116
12534
|
model: cfg.model,
|
|
12117
12535
|
plumbingModel: cfg.plumbingModel,
|
|
12536
|
+
extractionModel: cfg.memoryExtractionModel,
|
|
12118
12537
|
embeddingModel: cfg.memoryEmbeddingModel,
|
|
12119
12538
|
gateway: gatewayFromConfig(cfg),
|
|
12120
12539
|
maxAgeDays: cfg.memoryMaxAgeDays ?? RETENTION.memoryMaxAgeDays,
|
|
@@ -12756,7 +13175,7 @@ function App({
|
|
|
12756
13175
|
return;
|
|
12757
13176
|
}
|
|
12758
13177
|
const cwd = process.cwd();
|
|
12759
|
-
const existingName = ["KIMI.md", "KIMIFLARE.md", "AGENT.md"].find((n) => existsSync2(
|
|
13178
|
+
const existingName = ["KIMI.md", "KIMIFLARE.md", "AGENT.md"].find((n) => existsSync2(join21(cwd, n)));
|
|
12760
13179
|
const isRefresh = existingName !== void 0;
|
|
12761
13180
|
const promptParts = [
|
|
12762
13181
|
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.",
|
|
@@ -12807,15 +13226,15 @@ function App({
|
|
|
12807
13226
|
sessionId: ensureSessionId(),
|
|
12808
13227
|
memoryManager: memoryManagerRef.current,
|
|
12809
13228
|
codeMode: effectiveCodeMode,
|
|
12810
|
-
|
|
12811
|
-
|
|
13229
|
+
cloudMode: cfg.cloudMode,
|
|
13230
|
+
cloudToken: initialCloudToken,
|
|
12812
13231
|
onIterationEnd,
|
|
12813
13232
|
onFileChange: (path, content) => {
|
|
12814
13233
|
if (content) {
|
|
12815
13234
|
lspManagerRef.current.notifyChange(path, content);
|
|
12816
13235
|
} else {
|
|
12817
13236
|
void import("fs/promises").then(
|
|
12818
|
-
({ readFile:
|
|
13237
|
+
({ readFile: readFile17 }) => readFile17(path, "utf8").then((c) => lspManagerRef.current.notifyChange(path, c)).catch(() => {
|
|
12819
13238
|
})
|
|
12820
13239
|
);
|
|
12821
13240
|
}
|
|
@@ -12909,7 +13328,7 @@ function App({
|
|
|
12909
13328
|
})
|
|
12910
13329
|
}
|
|
12911
13330
|
});
|
|
12912
|
-
if (existsSync2(
|
|
13331
|
+
if (existsSync2(join21(cwd, "KIMI.md"))) {
|
|
12913
13332
|
if (cacheStableRef.current) {
|
|
12914
13333
|
messagesRef.current[1] = {
|
|
12915
13334
|
role: "system",
|
|
@@ -13138,6 +13557,10 @@ function App({
|
|
|
13138
13557
|
setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "no config loaded" }]);
|
|
13139
13558
|
return true;
|
|
13140
13559
|
}
|
|
13560
|
+
if (cfg.cloudMode) {
|
|
13561
|
+
setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "AI Gateway is managed by Kimiflare Cloud" }]);
|
|
13562
|
+
return true;
|
|
13563
|
+
}
|
|
13141
13564
|
const sub = rest[0]?.toLowerCase() ?? "";
|
|
13142
13565
|
const subArg = rest.slice(1).join(" ").trim();
|
|
13143
13566
|
if (!sub || sub === "status") {
|
|
@@ -14008,8 +14431,8 @@ ${lines.join("\n")}` }]);
|
|
|
14008
14431
|
memoryManager: memoryManagerRef.current,
|
|
14009
14432
|
keepLastImageTurns: cfg.imageHistoryTurns ?? 2,
|
|
14010
14433
|
codeMode: effectiveCodeMode,
|
|
14011
|
-
|
|
14012
|
-
|
|
14434
|
+
cloudMode: cfg.cloudMode,
|
|
14435
|
+
cloudToken: initialCloudToken,
|
|
14013
14436
|
onIterationEnd,
|
|
14014
14437
|
intentClassification: classification,
|
|
14015
14438
|
onFileChange: (path, content2) => {
|
|
@@ -14017,7 +14440,7 @@ ${lines.join("\n")}` }]);
|
|
|
14017
14440
|
lspManagerRef.current.notifyChange(path, content2);
|
|
14018
14441
|
} else {
|
|
14019
14442
|
void import("fs/promises").then(
|
|
14020
|
-
({ readFile:
|
|
14443
|
+
({ readFile: readFile17 }) => readFile17(path, "utf8").then((c) => lspManagerRef.current.notifyChange(path, c)).catch(() => {
|
|
14021
14444
|
})
|
|
14022
14445
|
);
|
|
14023
14446
|
}
|
|
@@ -14198,12 +14621,28 @@ ${lines.join("\n")}` }]);
|
|
|
14198
14621
|
return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(
|
|
14199
14622
|
Onboarding,
|
|
14200
14623
|
{
|
|
14201
|
-
onDone: (newCfg) => {
|
|
14624
|
+
onDone: async (newCfg) => {
|
|
14202
14625
|
setCfg(newCfg);
|
|
14203
|
-
|
|
14204
|
-
|
|
14205
|
-
|
|
14206
|
-
|
|
14626
|
+
if (newCfg.cloudMode) {
|
|
14627
|
+
const { loadCloudCredentials: loadCloudCredentials2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
|
|
14628
|
+
const creds = await loadCloudCredentials2();
|
|
14629
|
+
if (creds) {
|
|
14630
|
+
setEvents((e) => [
|
|
14631
|
+
...e,
|
|
14632
|
+
{ kind: "info", key: mkKey(), text: "configuration saved \u2014 welcome to kimiflare! (cloud mode)" }
|
|
14633
|
+
]);
|
|
14634
|
+
} else {
|
|
14635
|
+
setEvents((e) => [
|
|
14636
|
+
...e,
|
|
14637
|
+
{ kind: "info", key: mkKey(), text: "cloud mode configured \u2014 run `kimiflare auth cloud` to sign in" }
|
|
14638
|
+
]);
|
|
14639
|
+
}
|
|
14640
|
+
} else {
|
|
14641
|
+
setEvents((e) => [
|
|
14642
|
+
...e,
|
|
14643
|
+
{ kind: "info", key: mkKey(), text: "configuration saved \u2014 welcome to kimiflare!" }
|
|
14644
|
+
]);
|
|
14645
|
+
}
|
|
14207
14646
|
}
|
|
14208
14647
|
}
|
|
14209
14648
|
) });
|
|
@@ -14249,6 +14688,7 @@ ${lines.join("\n")}` }]);
|
|
|
14249
14688
|
{
|
|
14250
14689
|
customCommands: customCommandsRef.current.filter((c) => !BUILTIN_COMMAND_NAMES.has(c.name.toLowerCase())).map((c) => ({ name: c.name, description: c.description })),
|
|
14251
14690
|
costAttributionEnabled: cfg?.costAttribution,
|
|
14691
|
+
cloudMode: cfg?.cloudMode,
|
|
14252
14692
|
onDone: () => setShowHelpMenu(false),
|
|
14253
14693
|
onCommand: handleHelpCommand
|
|
14254
14694
|
}
|
|
@@ -14260,7 +14700,7 @@ ${lines.join("\n")}` }]);
|
|
|
14260
14700
|
{
|
|
14261
14701
|
servers: cfg?.lspServers ?? {},
|
|
14262
14702
|
currentScope: lspScope,
|
|
14263
|
-
hasProjectDir: existsSync2(
|
|
14703
|
+
hasProjectDir: existsSync2(join21(process.cwd(), ".kimiflare")),
|
|
14264
14704
|
onDone: () => setShowLspWizard(false),
|
|
14265
14705
|
onSave: (servers, enabled, scope) => {
|
|
14266
14706
|
setCfg((c) => c ? { ...c, lspEnabled: enabled, lspServers: servers } : c);
|
|
@@ -14331,7 +14771,7 @@ ${lines.join("\n")}` }]);
|
|
|
14331
14771
|
] }),
|
|
14332
14772
|
/* @__PURE__ */ jsx22(Text21, { color: theme.info.color, children: commandToDelete.filepath }),
|
|
14333
14773
|
/* @__PURE__ */ jsx22(Box20, { marginTop: 1, children: /* @__PURE__ */ jsx22(
|
|
14334
|
-
|
|
14774
|
+
SelectInput10,
|
|
14335
14775
|
{
|
|
14336
14776
|
items: [
|
|
14337
14777
|
{ label: "Yes, delete", value: "yes", key: "yes" },
|
|
@@ -14401,7 +14841,8 @@ ${lines.join("\n")}` }]);
|
|
|
14401
14841
|
hasUpdate,
|
|
14402
14842
|
latestVersion,
|
|
14403
14843
|
gatewayMeta,
|
|
14404
|
-
codeMode
|
|
14844
|
+
codeMode,
|
|
14845
|
+
cloudMode: cfg.cloudMode
|
|
14405
14846
|
}
|
|
14406
14847
|
),
|
|
14407
14848
|
activePicker?.kind === "file" && /* @__PURE__ */ jsx22(
|
|
@@ -14477,7 +14918,7 @@ ${lines.join("\n")}` }]);
|
|
|
14477
14918
|
] })
|
|
14478
14919
|
] }) });
|
|
14479
14920
|
}
|
|
14480
|
-
async function renderApp(cfg, updateResult, lspScope = "global", lspProjectPath = null) {
|
|
14921
|
+
async function renderApp(cfg, updateResult, lspScope = "global", lspProjectPath = null, cloudToken) {
|
|
14481
14922
|
const instance = render(
|
|
14482
14923
|
/* @__PURE__ */ jsx22(
|
|
14483
14924
|
App,
|
|
@@ -14485,7 +14926,8 @@ async function renderApp(cfg, updateResult, lspScope = "global", lspProjectPath
|
|
|
14485
14926
|
initialCfg: cfg,
|
|
14486
14927
|
initialUpdateResult: updateResult,
|
|
14487
14928
|
initialLspScope: lspScope,
|
|
14488
|
-
initialLspProjectPath: lspProjectPath
|
|
14929
|
+
initialLspProjectPath: lspProjectPath,
|
|
14930
|
+
initialCloudToken: cloudToken
|
|
14489
14931
|
}
|
|
14490
14932
|
),
|
|
14491
14933
|
{
|
|
@@ -14676,7 +15118,7 @@ function createRemoteCommand() {
|
|
|
14676
15118
|
|
|
14677
15119
|
// src/index.tsx
|
|
14678
15120
|
var program = new Command2();
|
|
14679
|
-
program.name("kimiflare").description("Terminal coding agent powered by Kimi-K2.6 on Cloudflare Workers AI.").version(getAppVersion()).option("-p, --print <prompt>", "one-shot mode: send prompt, stream reply to stdout, exit").option("-m, --model <id>", "model id (defaults to @cf/moonshotai/kimi-k2.6)").option("--dangerously-allow-all", "auto-approve every permission prompt (print mode only)").option("--reasoning", "include reasoning in stdout (print mode only)").option("--continue-on-limit", "reset tool-call counter and continue when the 50-call limit is hit (print mode only)").option("--max-input-tokens <n>", "cumulative prompt token budget; exits 42 when exhausted (print mode only)", (v) => parseInt(v, 10));
|
|
15121
|
+
program.name("kimiflare").description("Terminal coding agent powered by Kimi-K2.6 on Cloudflare Workers AI.").version(getAppVersion()).option("-p, --print <prompt>", "one-shot mode: send prompt, stream reply to stdout, exit").option("-m, --model <id>", "model id (defaults to @cf/moonshotai/kimi-k2.6)").option("--cloud", "use Kimiflare Cloud (api.kimiflare.com) instead of direct Workers AI").option("--dangerously-allow-all", "auto-approve every permission prompt (print mode only)").option("--reasoning", "include reasoning in stdout (print mode only)").option("--continue-on-limit", "reset tool-call counter and continue when the 50-call limit is hit (print mode only)").option("--max-input-tokens <n>", "cumulative prompt token budget; exits 42 when exhausted (print mode only)", (v) => parseInt(v, 10));
|
|
14680
15122
|
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) => {
|
|
14681
15123
|
const cfg = await loadConfig();
|
|
14682
15124
|
const enabled = cfg?.costAttribution ?? false;
|
|
@@ -14689,6 +15131,25 @@ program.command("cost").description("Show cost attribution by task type (require
|
|
|
14689
15131
|
const { runCostCommand: runCostCommand2 } = await Promise.resolve().then(() => (init_cli(), cli_exports));
|
|
14690
15132
|
await runCostCommand2({ ...cmdOpts, config: cfg });
|
|
14691
15133
|
});
|
|
15134
|
+
program.command("usage").description("Show Kimiflare Cloud token usage (requires cloud authentication)").action(async () => {
|
|
15135
|
+
const { loadCloudCredentials: loadCloudCredentials2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
|
|
15136
|
+
const creds = await loadCloudCredentials2();
|
|
15137
|
+
if (!creds) {
|
|
15138
|
+
console.error("Not authenticated with Kimiflare Cloud. Run: kimiflare auth cloud");
|
|
15139
|
+
process.exit(1);
|
|
15140
|
+
}
|
|
15141
|
+
const res = await fetch("https://api.kimiflare.com/v1/usage", {
|
|
15142
|
+
headers: { Authorization: `Bearer ${creds.accessToken}` }
|
|
15143
|
+
});
|
|
15144
|
+
if (!res.ok) {
|
|
15145
|
+
console.error(`Failed to fetch usage: ${res.status} ${res.statusText}`);
|
|
15146
|
+
process.exit(1);
|
|
15147
|
+
}
|
|
15148
|
+
const usage = await res.json();
|
|
15149
|
+
console.log(`Token budget: ${usage.remaining.toLocaleString()} / ${usage.input_token_limit.toLocaleString()} remaining`);
|
|
15150
|
+
console.log(`Used: ${usage.input_tokens_used.toLocaleString()}`);
|
|
15151
|
+
console.log(`Grant expires: ${usage.expires_at}`);
|
|
15152
|
+
});
|
|
14692
15153
|
program.addCommand(createRemoteCommand());
|
|
14693
15154
|
program.command("auth").description("Authenticate with external services").addCommand(
|
|
14694
15155
|
new Command2("github").description("Authenticate with GitHub via OAuth device flow").action(async () => {
|
|
@@ -14705,6 +15166,37 @@ Open: ${step.url}`);
|
|
|
14705
15166
|
if (step.error) process.exit(1);
|
|
14706
15167
|
}
|
|
14707
15168
|
})
|
|
15169
|
+
).addCommand(
|
|
15170
|
+
new Command2("cloud").description("Authenticate with Kimiflare Cloud").action(async () => {
|
|
15171
|
+
const { authenticateDevice: authenticateDevice2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
|
|
15172
|
+
try {
|
|
15173
|
+
const creds = await authenticateDevice2(({ url, userCode, polling }) => {
|
|
15174
|
+
if (!polling) {
|
|
15175
|
+
console.log(`
|
|
15176
|
+
Kimiflare Cloud Authentication`);
|
|
15177
|
+
console.log(`
|
|
15178
|
+
1. Open this URL in your browser:`);
|
|
15179
|
+
console.log(` ${url}`);
|
|
15180
|
+
console.log(`
|
|
15181
|
+
2. Sign in with GitHub
|
|
15182
|
+
`);
|
|
15183
|
+
}
|
|
15184
|
+
});
|
|
15185
|
+
console.log(`Authenticated! Token expires at ${new Date(creds.expiresAt * 1e3).toISOString()}`);
|
|
15186
|
+
const usageRes = await fetch("https://api.kimiflare.com/v1/usage", {
|
|
15187
|
+
headers: { Authorization: `Bearer ${creds.accessToken}` }
|
|
15188
|
+
});
|
|
15189
|
+
if (usageRes.ok) {
|
|
15190
|
+
const usage = await usageRes.json();
|
|
15191
|
+
console.log(`
|
|
15192
|
+
Token budget: ${usage.remaining.toLocaleString()} / ${usage.input_token_limit.toLocaleString()} remaining`);
|
|
15193
|
+
console.log(`Grant expires: ${usage.expires_at}`);
|
|
15194
|
+
}
|
|
15195
|
+
} catch (err) {
|
|
15196
|
+
console.error("Authentication failed:", err instanceof Error ? err.message : String(err));
|
|
15197
|
+
process.exit(1);
|
|
15198
|
+
}
|
|
15199
|
+
})
|
|
14708
15200
|
);
|
|
14709
15201
|
program.action(async () => {
|
|
14710
15202
|
await main();
|
|
@@ -14727,10 +15219,25 @@ async function main() {
|
|
|
14727
15219
|
lspScope = resolved.scope;
|
|
14728
15220
|
lspProjectPath = resolved.projectPath;
|
|
14729
15221
|
}
|
|
15222
|
+
const cloudMode = opts.cloud ?? cfg?.cloudMode ?? false;
|
|
15223
|
+
let cloudToken;
|
|
15224
|
+
if (cloudMode) {
|
|
15225
|
+
const { loadCloudCredentials: loadCloudCredentials2, authenticateDevice: authenticateDevice2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
|
|
15226
|
+
let cloudCreds = await loadCloudCredentials2();
|
|
15227
|
+
if (!cloudCreds) {
|
|
15228
|
+
console.error("kimiflare: cloud mode requires authentication.\nRun: kimiflare auth cloud\n");
|
|
15229
|
+
process.exit(2);
|
|
15230
|
+
}
|
|
15231
|
+
cloudToken = cloudCreds.accessToken;
|
|
15232
|
+
cfg = {
|
|
15233
|
+
...cfg ?? { accountId: "", apiToken: "", model: DEFAULT_MODEL },
|
|
15234
|
+
cloudMode: true
|
|
15235
|
+
};
|
|
15236
|
+
}
|
|
14730
15237
|
if (opts.print !== void 0) {
|
|
14731
15238
|
if (!cfg) {
|
|
14732
15239
|
console.error(
|
|
14733
|
-
'kimiflare: missing credentials.\nSet CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_API_TOKEN, or write them to\n ~/.config/kimiflare/config.json (chmod 600)\n { "accountId": "...", "apiToken": "...", "model": "@cf/moonshotai/kimi-k2.6" }'
|
|
15240
|
+
'kimiflare: missing credentials.\nSet CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_API_TOKEN, or write them to\n ~/.config/kimiflare/config.json (chmod 600)\n { "accountId": "...", "apiToken": "...", "model": "@cf/moonshotai/kimi-k2.6" }\nOr use cloud mode: kimiflare --cloud -p "..."'
|
|
14734
15241
|
);
|
|
14735
15242
|
process.exit(2);
|
|
14736
15243
|
}
|
|
@@ -14742,6 +15249,7 @@ async function main() {
|
|
|
14742
15249
|
allowAll: !!opts.dangerouslyAllowAll,
|
|
14743
15250
|
showReasoning: !!opts.reasoning,
|
|
14744
15251
|
codeMode: cfg.codeMode,
|
|
15252
|
+
cloudToken,
|
|
14745
15253
|
continueOnLimit: !!opts.continueOnLimit,
|
|
14746
15254
|
maxInputTokens: opts.maxInputTokens,
|
|
14747
15255
|
updateResult
|
|
@@ -14757,9 +15265,9 @@ async function main() {
|
|
|
14757
15265
|
const { renderApp: renderApp2 } = await Promise.resolve().then(() => (init_app(), app_exports));
|
|
14758
15266
|
if (cfg) {
|
|
14759
15267
|
const model = opts.model ?? cfg.model ?? DEFAULT_MODEL;
|
|
14760
|
-
await renderApp2({ ...cfg, model }, updateResult, lspScope, lspProjectPath);
|
|
15268
|
+
await renderApp2({ ...cfg, model }, updateResult, lspScope, lspProjectPath, cloudToken);
|
|
14761
15269
|
} else {
|
|
14762
|
-
await renderApp2(null, updateResult, lspScope, lspProjectPath);
|
|
15270
|
+
await renderApp2(null, updateResult, lspScope, lspProjectPath, cloudToken);
|
|
14763
15271
|
}
|
|
14764
15272
|
}
|
|
14765
15273
|
function gatewayFromPrintOpts(opts2) {
|
|
@@ -14773,6 +15281,10 @@ function gatewayFromPrintOpts(opts2) {
|
|
|
14773
15281
|
};
|
|
14774
15282
|
}
|
|
14775
15283
|
async function runPrintMode(opts2) {
|
|
15284
|
+
if (opts2.cloudMode) {
|
|
15285
|
+
process.stderr.write(`[cloud mode: api.kimiflare.com]
|
|
15286
|
+
`);
|
|
15287
|
+
}
|
|
14776
15288
|
if (opts2.updateResult.hasUpdate) {
|
|
14777
15289
|
process.stderr.write(
|
|
14778
15290
|
`\x1B[33mkimiflare update available: ${opts2.updateResult.localVersion} \u2192 ${opts2.updateResult.latestVersion}\x1B[0m
|
|
@@ -14805,6 +15317,8 @@ async function runPrintMode(opts2) {
|
|
|
14805
15317
|
codeMode: opts2.codeMode,
|
|
14806
15318
|
continueOnLimit: opts2.continueOnLimit,
|
|
14807
15319
|
maxInputTokens: opts2.maxInputTokens,
|
|
15320
|
+
cloudMode: opts2.cloudMode,
|
|
15321
|
+
cloudToken: opts2.cloudToken,
|
|
14808
15322
|
coauthor: opts2.coauthor !== false ? { name: opts2.coauthorName || "kimiflare", email: opts2.coauthorEmail || "kimiflare@proton.me" } : void 0,
|
|
14809
15323
|
callbacks: {
|
|
14810
15324
|
onReasoningDelta: opts2.showReasoning ? (delta) => {
|