kimiflare 0.20.0 → 0.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -41,12 +41,6 @@ async function loadConfig() {
41
41
  const compiledContext = envCompiled === "1" || envCompiled === "true" ? true : false;
42
42
  const envImageTurns = process.env.KIMIFLARE_IMAGE_HISTORY_TURNS;
43
43
  const imageHistoryTurns = envImageTurns ? parseInt(envImageTurns, 10) : void 0;
44
- const envMaxToolIterations = process.env.KIMIFLARE_MAX_TOOL_ITERATIONS;
45
- const maxToolIterations = envMaxToolIterations ? parseInt(envMaxToolIterations, 10) : void 0;
46
- const envMaxInputTokens = process.env.KIMIFLARE_MAX_INPUT_TOKENS;
47
- const maxInputTokens = envMaxInputTokens ? parseInt(envMaxInputTokens, 10) : void 0;
48
- const envMaxCompletionTokens = process.env.KIMIFLARE_MAX_COMPLETION_TOKENS;
49
- const maxCompletionTokens = envMaxCompletionTokens ? parseInt(envMaxCompletionTokens, 10) : void 0;
50
44
  if (envAccount && envToken) {
51
45
  return {
52
46
  accountId: envAccount,
@@ -59,10 +53,7 @@ async function loadConfig() {
59
53
  coauthorEmail: envCoauthor?.email,
60
54
  cacheStablePrompts,
61
55
  compiledContext,
62
- imageHistoryTurns: Number.isNaN(imageHistoryTurns) ? void 0 : imageHistoryTurns,
63
- maxToolIterations: Number.isNaN(maxToolIterations) ? void 0 : maxToolIterations,
64
- maxInputTokens: Number.isNaN(maxInputTokens) ? void 0 : maxInputTokens,
65
- maxCompletionTokens: Number.isNaN(maxCompletionTokens) ? void 0 : maxCompletionTokens
56
+ imageHistoryTurns: Number.isNaN(imageHistoryTurns) ? void 0 : imageHistoryTurns
66
57
  };
67
58
  }
68
59
  try {
@@ -81,10 +72,7 @@ async function loadConfig() {
81
72
  mcpServers: parsed.mcpServers,
82
73
  cacheStablePrompts: parsed.cacheStablePrompts ?? cacheStablePrompts,
83
74
  compiledContext: parsed.compiledContext ?? compiledContext,
84
- imageHistoryTurns: Number.isNaN(imageHistoryTurns) ? parsed.imageHistoryTurns : imageHistoryTurns,
85
- maxToolIterations: Number.isNaN(maxToolIterations) ? parsed.maxToolIterations : maxToolIterations,
86
- maxInputTokens: Number.isNaN(maxInputTokens) ? parsed.maxInputTokens : maxInputTokens,
87
- maxCompletionTokens: Number.isNaN(maxCompletionTokens) ? parsed.maxCompletionTokens : maxCompletionTokens
75
+ imageHistoryTurns: Number.isNaN(imageHistoryTurns) ? parsed.imageHistoryTurns : imageHistoryTurns
88
76
  };
89
77
  }
90
78
  } catch {
@@ -191,14 +179,14 @@ function stableStringify(value, replacer, space) {
191
179
  const sorted = sortKeys(value);
192
180
  return JSON.stringify(sorted, replacer, space);
193
181
  }
194
- function stripOldImages(messages, keepLastTurns2) {
195
- if (keepLastTurns2 < 0) return messages;
182
+ function stripOldImages(messages, keepLastTurns) {
183
+ if (keepLastTurns < 0) return messages;
196
184
  let userCount = 0;
197
185
  let cutoffIndex = messages.length;
198
186
  for (let i = messages.length - 1; i >= 0; i--) {
199
187
  if (messages[i].role === "user") {
200
188
  userCount++;
201
- if (userCount === keepLastTurns2) {
189
+ if (userCount === keepLastTurns) {
202
190
  cutoffIndex = i;
203
191
  break;
204
192
  }
@@ -239,7 +227,7 @@ async function* runKimi(opts2) {
239
227
  ...opts2.tools && opts2.tools.length ? { tools: opts2.tools, tool_choice: "auto", parallel_tool_calls: true } : {},
240
228
  stream: true,
241
229
  temperature: opts2.temperature ?? 0.2,
242
- max_completion_tokens: opts2.maxCompletionTokens ?? 4096
230
+ max_completion_tokens: opts2.maxCompletionTokens ?? 16384
243
231
  };
244
232
  if (opts2.reasoningEffort) {
245
233
  body.reasoning_effort = opts2.reasoningEffort;
@@ -429,7 +417,7 @@ var init_client = __esm({
429
417
  init_errors();
430
418
  init_messages();
431
419
  RETRYABLE_CODES = /* @__PURE__ */ new Set([3040]);
432
- MAX_ATTEMPTS = 2;
420
+ MAX_ATTEMPTS = 5;
433
421
  }
434
422
  });
435
423
 
@@ -609,37 +597,6 @@ async function logCostDebug(entry) {
609
597
  await rotateJsonl(debugPath(), RETENTION.costDebugMaxBytes, RETENTION.costDebugRotations);
610
598
  await appendFile(debugPath(), JSON.stringify(entry) + "\n", "utf8");
611
599
  }
612
- function usageDir() {
613
- return join3(homedir2(), ".kimiflare");
614
- }
615
- function usagePath() {
616
- return join3(usageDir(), "usage.jsonl");
617
- }
618
- async function logTurnTokenMetrics(metrics) {
619
- await mkdir2(usageDir(), { recursive: true });
620
- await rotateJsonl(usagePath(), RETENTION.costDebugMaxBytes, RETENTION.costDebugRotations);
621
- await appendFile(usagePath(), JSON.stringify(metrics) + "\n", "utf8");
622
- }
623
- function buildTurnTokenMetrics(sessionId, turn, breakdown, estimatedOutputTokenCap, wasCompacted, removedCount, exceedsLimit) {
624
- return {
625
- v: LOG_VERSION,
626
- ts: now(),
627
- sessionId,
628
- turn,
629
- estimatedInputTokens: breakdown.total,
630
- estimatedOutputTokenCap,
631
- messageCount: breakdown.messageCount,
632
- toolOutputCount: breakdown.toolOutputCount,
633
- tokensFromSystem: breakdown.fromSystem,
634
- tokensFromSession: breakdown.fromSession,
635
- tokensFromTools: breakdown.fromTools,
636
- tokensFromHistory: breakdown.fromHistory,
637
- tokensFromUserInput: breakdown.fromUserInput,
638
- wasCompacted,
639
- removedCount,
640
- exceedsLimit
641
- };
642
- }
643
600
  function serializePrefix(messages) {
644
601
  let end = 0;
645
602
  while (end < messages.length && messages[end].role === "system") {
@@ -784,282 +741,12 @@ var init_strip_reasoning = __esm({
784
741
  }
785
742
  });
786
743
 
787
- // src/agent/token-limits.ts
788
- function loadSafetyLimits() {
789
- return {
790
- maxInputTokensPerRequest: parseIntEnv("KIMIFLARE_MAX_INPUT_TOKENS", DEFAULT_SAFETY_LIMITS.maxInputTokensPerRequest),
791
- warningThreshold: parseIntEnv("KIMIFLARE_WARNING_TOKENS", DEFAULT_SAFETY_LIMITS.warningThreshold),
792
- maxLlmCallsPerUserAction: parseIntEnv("KIMIFLARE_MAX_LLM_CALLS", DEFAULT_SAFETY_LIMITS.maxLlmCallsPerUserAction),
793
- maxRetriesPerLlmCall: parseIntEnv("KIMIFLARE_MAX_RETRIES", DEFAULT_SAFETY_LIMITS.maxRetriesPerLlmCall),
794
- maxCompletionTokens: parseIntEnv("KIMIFLARE_MAX_COMPLETION_TOKENS", DEFAULT_SAFETY_LIMITS.maxCompletionTokens),
795
- maxToolIterations: parseIntEnv("KIMIFLARE_MAX_TOOL_ITERATIONS", DEFAULT_SAFETY_LIMITS.maxToolIterations),
796
- maxRecentMessages: parseIntEnv("KIMIFLARE_MAX_RECENT_MESSAGES", DEFAULT_SAFETY_LIMITS.maxRecentMessages),
797
- maxToolOutputChars: parseIntEnv("KIMIFLARE_MAX_TOOL_OUTPUT_CHARS", DEFAULT_SAFETY_LIMITS.maxToolOutputChars)
798
- };
799
- }
800
- function parseIntEnv(name, fallback) {
801
- const raw = process.env[name];
802
- if (!raw) return fallback;
803
- const n = parseInt(raw, 10);
804
- return Number.isNaN(n) ? fallback : n;
805
- }
806
- function estimateTokens(text) {
807
- return Math.ceil(text.length / 4);
808
- }
809
- function estimateMessageTokens(m) {
810
- let chars = 0;
811
- if (typeof m.content === "string") {
812
- chars = m.content.length;
813
- } else if (Array.isArray(m.content)) {
814
- for (const part of m.content) {
815
- if (part.type === "text") chars += part.text.length;
816
- else if (part.type === "image_url") chars += 1e3;
817
- }
818
- }
819
- if (m.reasoning_content) chars += m.reasoning_content.length;
820
- if (m.tool_calls) {
821
- for (const tc of m.tool_calls) {
822
- chars += tc.function.name.length;
823
- chars += tc.function.arguments.length;
824
- }
825
- }
826
- return Math.ceil(chars / 4) + 4;
827
- }
828
- function estimateMessagesTokens(messages) {
829
- return messages.reduce((sum, m) => sum + estimateMessageTokens(m), 0);
830
- }
831
- function estimateToolDefsTokens(tools) {
832
- return estimateTokens(JSON.stringify(tools));
833
- }
834
- function breakdownTokens(systemMessages, sessionMessages, toolDefs, historyMessages, userMessage) {
835
- const fromSystem = estimateMessagesTokens(systemMessages);
836
- const fromSession = estimateMessagesTokens(sessionMessages);
837
- const fromTools = estimateToolDefsTokens(toolDefs);
838
- const fromHistory = estimateMessagesTokens(historyMessages);
839
- const fromUserInput = userMessage ? estimateMessageTokens(userMessage) : 0;
840
- return {
841
- total: fromSystem + fromSession + fromTools + fromHistory + fromUserInput,
842
- fromSystem,
843
- fromSession,
844
- fromTools,
845
- fromHistory,
846
- fromUserInput,
847
- messageCount: systemMessages.length + sessionMessages.length + historyMessages.length + (userMessage ? 1 : 0),
848
- toolOutputCount: historyMessages.filter((m) => m.role === "tool").length
849
- };
850
- }
851
- function compactHistoryForSafety(messages, targetTokens) {
852
- let compacted = messages.map((m) => {
853
- if (m.role === "tool" && typeof m.content === "string" && m.content.length > 200) {
854
- const lines = m.content.split("\n");
855
- const firstLine2 = lines[0] ?? "";
856
- const truncated = lines.length > 3 || m.content.length > 200;
857
- return {
858
- ...m,
859
- content: `[${m.name ?? "tool"} result${truncated ? " (truncated)" : ""}] ${firstLine2.slice(0, 120)}`
860
- };
861
- }
862
- return m;
863
- });
864
- let removedCount = 0;
865
- while (estimateMessagesTokens(compacted) > targetTokens && compacted.length > 2) {
866
- const dropIndex = compacted.findIndex((m, i) => i > 0 && m.role !== "system" && m.role !== "user");
867
- if (dropIndex === -1) break;
868
- compacted.splice(dropIndex, 1);
869
- removedCount++;
870
- }
871
- return { messages: compacted, removedCount };
872
- }
873
- var DEFAULT_SAFETY_LIMITS;
874
- var init_token_limits = __esm({
875
- "src/agent/token-limits.ts"() {
876
- "use strict";
877
- DEFAULT_SAFETY_LIMITS = {
878
- maxInputTokensPerRequest: 3e4,
879
- warningThreshold: 15e3,
880
- maxLlmCallsPerUserAction: 10,
881
- maxRetriesPerLlmCall: 2,
882
- maxCompletionTokens: 4096,
883
- maxToolIterations: 10,
884
- maxRecentMessages: 4,
885
- maxToolOutputChars: 800
886
- };
887
- }
888
- });
889
-
890
- // src/agent/tool-output-summarizer.ts
891
- import { createHash } from "crypto";
892
- function normalizeForHash(text) {
893
- return text.toLowerCase().replace(/\s+/g, " ").trim().slice(0, 5e3);
894
- }
895
- function stableHash(text) {
896
- return createHash("sha256").update(text).digest("hex").slice(0, 16);
897
- }
898
- function clearOutputHashCache() {
899
- outputHashCache.clear();
900
- }
901
- function summarizeToolOutput(toolCallId, name, rawContent, maxChars = DEFAULT_MAX_CHARS) {
902
- const normalized = normalizeForHash(rawContent);
903
- const hash = stableHash(normalized);
904
- const cached = outputHashCache.get(hash);
905
- if (cached && cached.firstSeenId !== toolCallId) {
906
- const ref = `same as previous ${cached.name ?? "tool"} call (result_id=${hash})`;
907
- return {
908
- tool_call_id: toolCallId,
909
- name,
910
- content: ref,
911
- truncated: false
912
- };
913
- }
914
- if (!cached) {
915
- const preview = rawContent.slice(0, 120).replace(/\s+/g, " ");
916
- outputHashCache.set(hash, { name, firstSeenId: toolCallId, preview });
917
- }
918
- const isFailure = rawContent.startsWith("Error:") || rawContent.startsWith("error:") || rawContent.includes("exit code") || rawContent.includes("not found") || rawContent.includes("No such file");
919
- const isNoisy = rawContent.length > 0 && (rawContent.split("\n").length > 100 || rawContent.length > maxChars * 2);
920
- if (isFailure && rawContent.length > 200) {
921
- const firstLine2 = rawContent.split("\n")[0] ?? "";
922
- return {
923
- tool_call_id: toolCallId,
924
- name,
925
- content: `[${name ?? "tool"} failed] ${firstLine2.slice(0, 160)}`,
926
- truncated: true
927
- };
928
- }
929
- if (rawContent.length <= maxChars) {
930
- return {
931
- tool_call_id: toolCallId,
932
- name,
933
- content: rawContent,
934
- truncated: false
935
- };
936
- }
937
- const truncated = rawContent.slice(0, maxChars);
938
- const lastNewline = truncated.lastIndexOf("\n");
939
- const clean = lastNewline > maxChars * 0.5 ? truncated.slice(0, lastNewline) : truncated;
940
- return {
941
- tool_call_id: toolCallId,
942
- name,
943
- content: `${clean}
944
- ... (${rawContent.length - clean.length} more chars truncated)`,
945
- truncated: true
946
- };
947
- }
948
- function summarizeToolMessage(msg, maxChars = DEFAULT_MAX_CHARS) {
949
- if (msg.role !== "tool" || typeof msg.content !== "string") {
950
- return msg;
951
- }
952
- const summary = summarizeToolOutput(msg.tool_call_id ?? "", msg.name, msg.content, maxChars);
953
- return {
954
- ...msg,
955
- content: summary.content
956
- };
957
- }
958
- function summarizeToolMessages(messages, maxChars = DEFAULT_MAX_CHARS) {
959
- return messages.map((m) => m.role === "tool" ? summarizeToolMessage(m, maxChars) : m);
960
- }
961
- var DEFAULT_MAX_CHARS, outputHashCache;
962
- var init_tool_output_summarizer = __esm({
963
- "src/agent/tool-output-summarizer.ts"() {
964
- "use strict";
965
- DEFAULT_MAX_CHARS = 800;
966
- outputHashCache = /* @__PURE__ */ new Map();
967
- }
968
- });
969
-
970
- // src/agent/context-builder.ts
971
- function buildContext(opts2) {
972
- const { allMessages, systemMessages, sessionMessages, toolDefs, limits, currentUserMessage } = opts2;
973
- const prefixLength = systemMessages.length + sessionMessages.length;
974
- let history = allMessages.slice(prefixLength);
975
- history = summarizeToolMessages(history, limits.maxToolOutputChars);
976
- const recentHistory = keepLastTurns(history, limits.maxRecentMessages);
977
- const contextMessages = [
978
- ...systemMessages,
979
- ...sessionMessages,
980
- ...recentHistory
981
- ];
982
- if (currentUserMessage) {
983
- contextMessages.push(currentUserMessage);
984
- }
985
- let breakdown = breakdownTokens(
986
- systemMessages,
987
- sessionMessages,
988
- toolDefs,
989
- recentHistory,
990
- currentUserMessage ?? null
991
- );
992
- let wasCompacted = false;
993
- let removedCount = 0;
994
- if (breakdown.total > limits.maxInputTokensPerRequest) {
995
- const target = limits.maxInputTokensPerRequest;
996
- const compacted = compactHistoryForSafety(recentHistory, target - breakdown.fromSystem - breakdown.fromSession - breakdown.fromTools - breakdown.fromUserInput);
997
- if (compacted.removedCount > 0) {
998
- wasCompacted = true;
999
- removedCount = compacted.removedCount;
1000
- const newContext = [
1001
- ...systemMessages,
1002
- ...sessionMessages,
1003
- ...compacted.messages
1004
- ];
1005
- if (currentUserMessage) {
1006
- newContext.push(currentUserMessage);
1007
- }
1008
- breakdown = breakdownTokens(
1009
- systemMessages,
1010
- sessionMessages,
1011
- toolDefs,
1012
- compacted.messages,
1013
- currentUserMessage ?? null
1014
- );
1015
- return {
1016
- messages: newContext,
1017
- breakdown,
1018
- wasCompacted,
1019
- removedCount,
1020
- exceedsLimit: breakdown.total > limits.maxInputTokensPerRequest
1021
- };
1022
- }
1023
- }
1024
- return {
1025
- messages: contextMessages,
1026
- breakdown,
1027
- wasCompacted,
1028
- removedCount,
1029
- exceedsLimit: breakdown.total > limits.maxInputTokensPerRequest
1030
- };
1031
- }
1032
- function keepLastTurns(messages, maxTurns) {
1033
- if (maxTurns <= 0) return [];
1034
- const turnStarts = [];
1035
- for (let i = 0; i < messages.length; i++) {
1036
- if (messages[i].role === "user") {
1037
- turnStarts.push(i);
1038
- }
1039
- }
1040
- if (turnStarts.length <= maxTurns) {
1041
- return messages;
1042
- }
1043
- const startIndex = turnStarts[turnStarts.length - maxTurns] ?? 0;
1044
- return messages.slice(startIndex);
1045
- }
1046
- var init_context_builder = __esm({
1047
- "src/agent/context-builder.ts"() {
1048
- "use strict";
1049
- init_token_limits();
1050
- init_tool_output_summarizer();
1051
- }
1052
- });
1053
-
1054
744
  // src/agent/loop.ts
1055
745
  async function runAgentTurn(opts2) {
1056
- const limits = loadSafetyLimits();
1057
- const max = opts2.maxToolIterations ?? limits.maxToolIterations;
746
+ const max = opts2.maxToolIterations ?? 50;
1058
747
  const toolDefs = toOpenAIToolDefs(opts2.tools);
1059
748
  let turn = 0;
1060
749
  let lastUsage = null;
1061
- const systemMessages = opts2.systemMessages ?? extractSystemMessages(opts2.messages);
1062
- const sessionMessages = opts2.sessionMessages ?? [];
1063
750
  for (let iter = 0; iter < max; iter++) {
1064
751
  turn++;
1065
752
  const previousMessages = opts2.messages.slice();
@@ -1079,8 +766,8 @@ async function runAgentTurn(opts2) {
1079
766
  keepLast: Number.isNaN(keepLast) ? 1 : keepLast
1080
767
  });
1081
768
  if (shadowStrip) {
1082
- const originalSections = analyzePromptSections(opts2.messages);
1083
- const strippedSections = analyzePromptSections(stripped);
769
+ const originalSections = analyzePrompt(opts2.messages);
770
+ const strippedSections = analyzePrompt(stripped);
1084
771
  const originalApproxTokens = originalSections.reduce(
1085
772
  (sum, s) => sum + s.approxTokens,
1086
773
  0
@@ -1104,46 +791,15 @@ async function runAgentTurn(opts2) {
1104
791
  if (opts2.keepLastImageTurns !== void 0) {
1105
792
  apiMessages = stripOldImages(apiMessages, opts2.keepLastImageTurns);
1106
793
  }
1107
- const currentUserMessage = findCurrentUserMessage(apiMessages);
1108
- const context = buildContext({
1109
- allMessages: apiMessages,
1110
- systemMessages,
1111
- sessionMessages,
1112
- toolDefs,
1113
- limits,
1114
- currentUserMessage
1115
- });
1116
- if (opts2.sessionId) {
1117
- void logTurnTokenMetrics(
1118
- buildTurnTokenMetrics(
1119
- opts2.sessionId,
1120
- turn,
1121
- context.breakdown,
1122
- opts2.maxCompletionTokens ?? limits.maxCompletionTokens,
1123
- context.wasCompacted,
1124
- context.removedCount,
1125
- context.exceedsLimit
1126
- )
1127
- );
1128
- }
1129
- if (context.exceedsLimit) {
1130
- const assistantMsg3 = {
1131
- role: "assistant",
1132
- content: `I cannot continue: the conversation context exceeds the safety limit of ${limits.maxInputTokensPerRequest} tokens. Try running /compact or /clear to reduce context size.`
1133
- };
1134
- opts2.messages.push(assistantMsg3);
1135
- opts2.callbacks.onAssistantFinal?.(assistantMsg3);
1136
- return;
1137
- }
1138
794
  const events = runKimi({
1139
795
  accountId: opts2.accountId,
1140
796
  apiToken: opts2.apiToken,
1141
797
  model: opts2.model,
1142
- messages: context.messages,
798
+ messages: apiMessages,
1143
799
  tools: toolDefs,
1144
800
  signal: opts2.signal,
1145
801
  temperature: opts2.temperature,
1146
- maxCompletionTokens: opts2.maxCompletionTokens ?? limits.maxCompletionTokens,
802
+ maxCompletionTokens: opts2.maxCompletionTokens,
1147
803
  reasoningEffort: opts2.reasoningEffort,
1148
804
  sessionId: opts2.sessionId
1149
805
  });
@@ -1182,7 +838,7 @@ async function runAgentTurn(opts2) {
1182
838
  break;
1183
839
  }
1184
840
  }
1185
- const assistantMsg2 = {
841
+ const assistantMsg = {
1186
842
  role: "assistant",
1187
843
  content: content ? sanitizeString(content) : null,
1188
844
  ...reasoning ? { reasoning_content: sanitizeString(reasoning) } : {},
@@ -1196,8 +852,8 @@ async function runAgentTurn(opts2) {
1196
852
  }))
1197
853
  } : {}
1198
854
  };
1199
- opts2.messages.push(assistantMsg2);
1200
- opts2.callbacks.onAssistantFinal?.(assistantMsg2);
855
+ opts2.messages.push(assistantMsg);
856
+ opts2.callbacks.onAssistantFinal?.(assistantMsg);
1201
857
  if (toolCalls.length === 0) {
1202
858
  if (opts2.sessionId && lastUsage) {
1203
859
  void logTurnDebug({
@@ -1240,36 +896,7 @@ async function runAgentTurn(opts2) {
1240
896
  });
1241
897
  }
1242
898
  }
1243
- const remaining = toolCallsFromMessages(opts2.messages);
1244
- const assistantMsg = {
1245
- role: "assistant",
1246
- content: `I reached the tool iteration limit (${max}). There ${remaining === 1 ? "is" : "are"} ${remaining} pending tool call${remaining === 1 ? "" : "s"} that could not be executed. Run /compact or /clear to reset context, or rephrase your request.`
1247
- };
1248
- opts2.messages.push(assistantMsg);
1249
- opts2.callbacks.onAssistantFinal?.(assistantMsg);
1250
- }
1251
- function extractSystemMessages(messages) {
1252
- const end = messages.findIndex((m) => m.role !== "system");
1253
- return end === -1 ? messages.slice() : messages.slice(0, end);
1254
- }
1255
- function findCurrentUserMessage(messages) {
1256
- const prefixEnd = messages.findIndex((m) => m.role !== "system");
1257
- const history = prefixEnd === -1 ? [] : messages.slice(prefixEnd);
1258
- for (let i = history.length - 1; i >= 0; i--) {
1259
- if (history[i].role === "user") {
1260
- return history[i];
1261
- }
1262
- }
1263
- return null;
1264
- }
1265
- function toolCallsFromMessages(messages) {
1266
- let count = 0;
1267
- for (const m of messages) {
1268
- if (m.role === "assistant" && m.tool_calls) {
1269
- count += m.tool_calls.length;
1270
- }
1271
- }
1272
- return count;
899
+ throw new Error(`kimiflare: tool iteration limit reached (${opts2.maxToolIterations ?? 50})`);
1273
900
  }
1274
901
  function validateToolArguments(raw) {
1275
902
  if (!raw || !raw.trim()) return "{}";
@@ -1280,25 +907,6 @@ function validateToolArguments(raw) {
1280
907
  return "{}";
1281
908
  }
1282
909
  }
1283
- function analyzePromptSections(messages) {
1284
- return messages.map((m) => {
1285
- let chars = 0;
1286
- if (typeof m.content === "string") {
1287
- chars = m.content.length;
1288
- } else if (Array.isArray(m.content)) {
1289
- for (const p of m.content) {
1290
- if (p.type === "text") chars += p.text.length;
1291
- }
1292
- }
1293
- if (m.reasoning_content) chars += m.reasoning_content.length;
1294
- if (m.tool_calls) {
1295
- for (const tc of m.tool_calls) {
1296
- chars += tc.function.name.length + tc.function.arguments.length;
1297
- }
1298
- }
1299
- return { role: m.role, chars, approxTokens: Math.ceil(chars / 4) };
1300
- });
1301
- }
1302
910
  var init_loop = __esm({
1303
911
  "src/agent/loop.ts"() {
1304
912
  "use strict";
@@ -1307,8 +915,6 @@ var init_loop = __esm({
1307
915
  init_messages();
1308
916
  init_cost_debug();
1309
917
  init_strip_reasoning();
1310
- init_token_limits();
1311
- init_context_builder();
1312
918
  }
1313
919
  });
1314
920
 
@@ -2793,77 +2399,6 @@ var init_update_check = __esm({
2793
2399
  }
2794
2400
  });
2795
2401
 
2796
- // src/usage-cli.ts
2797
- var usage_cli_exports = {};
2798
- __export(usage_cli_exports, {
2799
- showUsageLog: () => showUsageLog
2800
- });
2801
- import { readFile as readFile7 } from "fs/promises";
2802
- import { homedir as homedir6 } from "os";
2803
- import { join as join7 } from "path";
2804
- function usagePath2() {
2805
- return join7(homedir6(), ".kimiflare", "usage.jsonl");
2806
- }
2807
- function fmt(n) {
2808
- return n.toLocaleString();
2809
- }
2810
- async function showUsageLog() {
2811
- const path = usagePath2();
2812
- let raw;
2813
- try {
2814
- raw = await readFile7(path, "utf8");
2815
- } catch {
2816
- console.log("No usage log found at " + path);
2817
- return;
2818
- }
2819
- const lines = raw.trim().split("\n").filter(Boolean);
2820
- if (lines.length === 0) {
2821
- console.log("Usage log is empty.");
2822
- return;
2823
- }
2824
- const entries = [];
2825
- for (const line of lines) {
2826
- try {
2827
- entries.push(JSON.parse(line));
2828
- } catch {
2829
- }
2830
- }
2831
- if (entries.length === 0) {
2832
- console.log("No valid entries in usage log.");
2833
- return;
2834
- }
2835
- const bySession = /* @__PURE__ */ new Map();
2836
- for (const e of entries) {
2837
- const arr = bySession.get(e.sessionId) ?? [];
2838
- arr.push(e);
2839
- bySession.set(e.sessionId, arr);
2840
- }
2841
- console.log(`Usage log: ${lines.length} entries, ${bySession.size} session(s)
2842
- `);
2843
- for (const [sessionId, sessEntries] of bySession) {
2844
- const last = sessEntries[sessEntries.length - 1];
2845
- const totalInput = sessEntries.reduce((s, e) => s + e.estimatedInputTokens, 0);
2846
- const avgInput = Math.round(totalInput / sessEntries.length);
2847
- console.log(`Session: ${sessionId.slice(0, 16)}\u2026 Turns: ${sessEntries.length}`);
2848
- console.log(` Last turn: ${fmt(last.estimatedInputTokens)} input tokens / ${fmt(last.estimatedOutputTokenCap)} output cap`);
2849
- console.log(` Avg input: ${fmt(avgInput)} tokens`);
2850
- console.log(` Messages: ${last.messageCount} | Tool outputs: ${last.toolOutputCount}`);
2851
- console.log(` Breakdown: system=${fmt(last.tokensFromSystem)} session=${fmt(last.tokensFromSession)} tools=${fmt(last.tokensFromTools)} history=${fmt(last.tokensFromHistory)} user=${fmt(last.tokensFromUserInput)}`);
2852
- if (last.wasCompacted) {
2853
- console.log(` \u26A0\uFE0F Compacted: removed ${last.removedCount} messages`);
2854
- }
2855
- if (last.exceedsLimit) {
2856
- console.log(` \u274C EXCEEDS LIMIT`);
2857
- }
2858
- console.log("");
2859
- }
2860
- }
2861
- var init_usage_cli = __esm({
2862
- "src/usage-cli.ts"() {
2863
- "use strict";
2864
- }
2865
- });
2866
-
2867
2402
  // src/agent/compact.ts
2868
2403
  function indexOfNthUserFromEnd(messages, n) {
2869
2404
  let seen = 0;
@@ -3070,7 +2605,7 @@ var init_session_state = __esm({
3070
2605
  function approxTokens2(n) {
3071
2606
  return Math.round(n / 4);
3072
2607
  }
3073
- function estimateMessageTokens2(m) {
2608
+ function estimateMessageTokens(m) {
3074
2609
  let chars = 0;
3075
2610
  if (typeof m.content === "string") {
3076
2611
  chars = m.content.length;
@@ -3086,7 +2621,7 @@ function estimateMessageTokens2(m) {
3086
2621
  return approxTokens2(chars);
3087
2622
  }
3088
2623
  function estimatePromptTokens(messages) {
3089
- return messages.reduce((sum, m) => sum + estimateMessageTokens2(m), 0);
2624
+ return messages.reduce((sum, m) => sum + estimateMessageTokens(m), 0);
3090
2625
  }
3091
2626
  function groupIntoTurns(messages) {
3092
2627
  const prefix = [];
@@ -3266,10 +2801,10 @@ function shouldCompact(opts2) {
3266
2801
  return tokens > tokenThreshold || turns.length > turnThreshold;
3267
2802
  }
3268
2803
  function compactMessages2(opts2) {
3269
- const keepLastTurns2 = opts2.keepLastTurns ?? 4;
2804
+ const keepLastTurns = opts2.keepLastTurns ?? 4;
3270
2805
  const { prefix, turns } = groupIntoTurns(opts2.messages);
3271
2806
  const tokensBefore = estimatePromptTokens(opts2.messages);
3272
- if (turns.length <= keepLastTurns2) {
2807
+ if (turns.length <= keepLastTurns) {
3273
2808
  return {
3274
2809
  newMessages: opts2.messages,
3275
2810
  newState: opts2.state,
@@ -3283,8 +2818,8 @@ function compactMessages2(opts2) {
3283
2818
  }
3284
2819
  };
3285
2820
  }
3286
- const toCompact = turns.slice(0, turns.length - keepLastTurns2);
3287
- const toKeep = turns.slice(turns.length - keepLastTurns2);
2821
+ const toCompact = turns.slice(0, turns.length - keepLastTurns);
2822
+ const toKeep = turns.slice(turns.length - keepLastTurns);
3288
2823
  let newState = { ...opts2.state };
3289
2824
  let archivedCount = 0;
3290
2825
  for (let i = 0; i < toCompact.length; i++) {
@@ -5315,12 +4850,12 @@ __export(sessions_exports, {
5315
4850
  pruneSessions: () => pruneSessions,
5316
4851
  saveSession: () => saveSession
5317
4852
  });
5318
- import { readFile as readFile8, writeFile as writeFile5, mkdir as mkdir5, readdir as readdir2, stat as stat3 } from "fs/promises";
5319
- import { homedir as homedir7 } from "os";
5320
- import { join as join8 } from "path";
4853
+ import { readFile as readFile7, writeFile as writeFile5, mkdir as mkdir5, readdir as readdir2, stat as stat3 } from "fs/promises";
4854
+ import { homedir as homedir6 } from "os";
4855
+ import { join as join7 } from "path";
5321
4856
  function sessionsDir() {
5322
- const xdg = process.env.XDG_DATA_HOME || join8(homedir7(), ".local", "share");
5323
- return join8(xdg, "kimiflare", "sessions");
4857
+ const xdg = process.env.XDG_DATA_HOME || join7(homedir6(), ".local", "share");
4858
+ return join7(xdg, "kimiflare", "sessions");
5324
4859
  }
5325
4860
  function sanitize(text) {
5326
4861
  return text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40);
@@ -5333,7 +4868,7 @@ function makeSessionId(firstPrompt) {
5333
4868
  async function saveSession(file) {
5334
4869
  const dir = sessionsDir();
5335
4870
  await mkdir5(dir, { recursive: true });
5336
- const path = join8(dir, `${file.id}.json`);
4871
+ const path = join7(dir, `${file.id}.json`);
5337
4872
  await writeFile5(path, JSON.stringify(file, null, 2), "utf8");
5338
4873
  return path;
5339
4874
  }
@@ -5353,9 +4888,9 @@ async function listSessions(limit = 30) {
5353
4888
  const summaries = [];
5354
4889
  for (const name of entries) {
5355
4890
  if (!name.endsWith(".json")) continue;
5356
- const path = join8(dir, name);
4891
+ const path = join7(dir, name);
5357
4892
  try {
5358
- const [s, raw] = await Promise.all([stat3(path), readFile8(path, "utf8")]);
4893
+ const [s, raw] = await Promise.all([stat3(path), readFile7(path, "utf8")]);
5359
4894
  const parsed = JSON.parse(raw);
5360
4895
  const firstUser = parsed.messages.find((m) => m.role === "user");
5361
4896
  const firstPrompt = typeof firstUser?.content === "string" ? firstUser.content : firstUser?.content ? firstUser.content.find((p) => p.type === "text")?.text ?? "(no prompt)" : "(no prompt)";
@@ -5374,7 +4909,7 @@ async function listSessions(limit = 30) {
5374
4909
  return summaries.slice(0, limit);
5375
4910
  }
5376
4911
  async function loadSession(filePath) {
5377
- const raw = await readFile8(filePath, "utf8");
4912
+ const raw = await readFile7(filePath, "utf8");
5378
4913
  return JSON.parse(raw);
5379
4914
  }
5380
4915
  var init_sessions = __esm({
@@ -5385,10 +4920,10 @@ var init_sessions = __esm({
5385
4920
  });
5386
4921
 
5387
4922
  // src/util/image.ts
5388
- import { readFile as readFile9 } from "fs/promises";
4923
+ import { readFile as readFile8 } from "fs/promises";
5389
4924
  import { basename as basename2 } from "path";
5390
4925
  async function encodeImageFile(filePath) {
5391
- const buf = await readFile9(filePath);
4926
+ const buf = await readFile8(filePath);
5392
4927
  if (buf.byteLength > MAX_IMAGE_BYTES) {
5393
4928
  throw new Error(
5394
4929
  `image too large (${(buf.byteLength / 1024 / 1024).toFixed(1)} MB); max is ${MAX_IMAGE_BYTES / 1024 / 1024} MB`
@@ -5424,15 +4959,15 @@ var init_image = __esm({
5424
4959
  });
5425
4960
 
5426
4961
  // src/usage-tracker.ts
5427
- import { readFile as readFile10, writeFile as writeFile6, mkdir as mkdir6 } from "fs/promises";
5428
- import { homedir as homedir8 } from "os";
5429
- import { join as join9 } from "path";
5430
- function usageDir2() {
5431
- const xdg = process.env.XDG_DATA_HOME || join9(homedir8(), ".local", "share");
5432
- return join9(xdg, "kimiflare");
4962
+ import { readFile as readFile9, writeFile as writeFile6, mkdir as mkdir6 } from "fs/promises";
4963
+ import { homedir as homedir7 } from "os";
4964
+ import { join as join8 } from "path";
4965
+ function usageDir() {
4966
+ const xdg = process.env.XDG_DATA_HOME || join8(homedir7(), ".local", "share");
4967
+ return join8(xdg, "kimiflare");
5433
4968
  }
5434
- function usagePath3() {
5435
- return join9(usageDir2(), "usage.json");
4969
+ function usagePath() {
4970
+ return join8(usageDir(), "usage.json");
5436
4971
  }
5437
4972
  function today() {
5438
4973
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
@@ -5443,7 +4978,7 @@ function cutoffDate(daysBack) {
5443
4978
  }
5444
4979
  async function loadLog() {
5445
4980
  try {
5446
- const raw = await readFile10(usagePath3(), "utf8");
4981
+ const raw = await readFile9(usagePath(), "utf8");
5447
4982
  const parsed = JSON.parse(raw);
5448
4983
  if (parsed.version === LOG_VERSION2) return parsed;
5449
4984
  } catch {
@@ -5451,8 +4986,8 @@ async function loadLog() {
5451
4986
  return { version: LOG_VERSION2, days: [], sessions: [] };
5452
4987
  }
5453
4988
  async function saveLog(log) {
5454
- await mkdir6(usageDir2(), { recursive: true });
5455
- await writeFile6(usagePath3(), JSON.stringify(log, null, 2), "utf8");
4989
+ await mkdir6(usageDir(), { recursive: true });
4990
+ await writeFile6(usagePath(), JSON.stringify(log, null, 2), "utf8");
5456
4991
  }
5457
4992
  function getOrCreateDay(log, date) {
5458
4993
  let day = log.days.find((d) => d.date === date);
@@ -5569,7 +5104,7 @@ __export(app_exports, {
5569
5104
  import { useState as useState6, useRef as useRef3, useEffect as useEffect4, useCallback } from "react";
5570
5105
  import { Box as Box12, Text as Text13, useApp, useInput as useInput2, render } from "ink";
5571
5106
  import { existsSync } from "fs";
5572
- import { join as join10 } from "path";
5107
+ import { join as join9 } from "path";
5573
5108
  import { unlink as unlink2 } from "fs/promises";
5574
5109
  import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
5575
5110
  function capEvents(prev) {
@@ -5635,10 +5170,9 @@ function App({ initialCfg, initialUpdateResult }) {
5635
5170
  const [hasUpdate, setHasUpdate] = useState6(initialUpdateResult?.hasUpdate ?? false);
5636
5171
  const [latestVersion, setLatestVersion] = useState6(initialUpdateResult?.latestVersion ?? null);
5637
5172
  const cacheStableRef = useRef3(initialCfg?.cacheStablePrompts !== false);
5638
- const systemMessagesRef = useRef3(
5173
+ const messagesRef = useRef3(
5639
5174
  makePrefixMessages(cacheStableRef.current, cfg?.model ?? DEFAULT_MODEL, "edit", ALL_TOOLS)
5640
5175
  );
5641
- const messagesRef = useRef3(systemMessagesRef.current.slice());
5642
5176
  const executorRef = useRef3(new ToolExecutor(ALL_TOOLS));
5643
5177
  const activeAsstIdRef = useRef3(null);
5644
5178
  const activeControllerRef = useRef3(null);
@@ -5723,7 +5257,7 @@ function App({ initialCfg, initialUpdateResult }) {
5723
5257
  useEffect4(() => {
5724
5258
  modeRef.current = mode;
5725
5259
  if (cacheStableRef.current) {
5726
- const sessionMsg = {
5260
+ messagesRef.current[1] = {
5727
5261
  role: "system",
5728
5262
  content: buildSessionPrefix({
5729
5263
  cwd: process.cwd(),
@@ -5732,10 +5266,8 @@ function App({ initialCfg, initialUpdateResult }) {
5732
5266
  mode
5733
5267
  })
5734
5268
  };
5735
- messagesRef.current[1] = sessionMsg;
5736
- systemMessagesRef.current[1] = sessionMsg;
5737
5269
  } else {
5738
- const sysMsg = {
5270
+ messagesRef.current[0] = {
5739
5271
  role: "system",
5740
5272
  content: buildSystemPrompt({
5741
5273
  cwd: process.cwd(),
@@ -5744,8 +5276,6 @@ function App({ initialCfg, initialUpdateResult }) {
5744
5276
  mode
5745
5277
  })
5746
5278
  };
5747
- messagesRef.current[0] = sysMsg;
5748
- systemMessagesRef.current[0] = sysMsg;
5749
5279
  }
5750
5280
  if (mode === "plan") {
5751
5281
  executorRef.current.clearSessionPermissions();
@@ -5820,7 +5350,7 @@ function App({ initialCfg, initialUpdateResult }) {
5820
5350
  }
5821
5351
  if (totalTools > 0) {
5822
5352
  if (cacheStableRef.current) {
5823
- const sessionMsg = {
5353
+ messagesRef.current[1] = {
5824
5354
  role: "system",
5825
5355
  content: buildSessionPrefix({
5826
5356
  cwd: process.cwd(),
@@ -5829,10 +5359,8 @@ function App({ initialCfg, initialUpdateResult }) {
5829
5359
  mode: modeRef.current
5830
5360
  })
5831
5361
  };
5832
- messagesRef.current[1] = sessionMsg;
5833
- systemMessagesRef.current[1] = sessionMsg;
5834
5362
  } else {
5835
- const sysMsg = {
5363
+ messagesRef.current[0] = {
5836
5364
  role: "system",
5837
5365
  content: buildSystemPrompt({
5838
5366
  cwd: process.cwd(),
@@ -5841,8 +5369,6 @@ function App({ initialCfg, initialUpdateResult }) {
5841
5369
  mode: modeRef.current
5842
5370
  })
5843
5371
  };
5844
- messagesRef.current[0] = sysMsg;
5845
- systemMessagesRef.current[0] = sysMsg;
5846
5372
  }
5847
5373
  setEvents((e) => [
5848
5374
  ...e,
@@ -6019,13 +5545,13 @@ function App({ initialCfg, initialUpdateResult }) {
6019
5545
  }
6020
5546
  const cwd = process.cwd();
6021
5547
  for (const name of ["KIMI.md", "KIMIFLARE.md", "AGENT.md"]) {
6022
- if (existsSync(join10(cwd, name))) {
5548
+ if (existsSync(join9(cwd, name))) {
6023
5549
  setEvents((e) => [
6024
5550
  ...e,
6025
5551
  {
6026
5552
  kind: "info",
6027
5553
  key: mkKey(),
6028
- text: `${name} already exists at ${join10(cwd, name)} \u2014 delete it first if you want to regenerate`
5554
+ text: `${name} already exists at ${join9(cwd, name)} \u2014 delete it first if you want to regenerate`
6029
5555
  }
6030
5556
  ]);
6031
5557
  return;
@@ -6065,7 +5591,6 @@ function App({ initialCfg, initialUpdateResult }) {
6065
5591
  reasoningEffort: effortRef.current,
6066
5592
  coauthor: cfg.coauthor !== false ? { name: cfg.coauthorName || "kimiflare", email: cfg.coauthorEmail || "kimiflare@proton.me" } : void 0,
6067
5593
  sessionId: ensureSessionId(),
6068
- systemMessages: systemMessagesRef.current,
6069
5594
  callbacks: {
6070
5595
  onAssistantStart: () => {
6071
5596
  const id = nextAssistantId++;
@@ -6143,9 +5668,9 @@ function App({ initialCfg, initialUpdateResult }) {
6143
5668
  })
6144
5669
  }
6145
5670
  });
6146
- if (existsSync(join10(cwd, "KIMI.md"))) {
5671
+ if (existsSync(join9(cwd, "KIMI.md"))) {
6147
5672
  if (cacheStableRef.current) {
6148
- const sessionMsg = {
5673
+ messagesRef.current[1] = {
6149
5674
  role: "system",
6150
5675
  content: buildSessionPrefix({
6151
5676
  cwd,
@@ -6154,10 +5679,8 @@ function App({ initialCfg, initialUpdateResult }) {
6154
5679
  mode: modeRef.current
6155
5680
  })
6156
5681
  };
6157
- messagesRef.current[1] = sessionMsg;
6158
- systemMessagesRef.current[1] = sessionMsg;
6159
5682
  } else {
6160
- const sysMsg = {
5683
+ messagesRef.current[0] = {
6161
5684
  role: "system",
6162
5685
  content: buildSystemPrompt({
6163
5686
  cwd,
@@ -6166,8 +5689,6 @@ function App({ initialCfg, initialUpdateResult }) {
6166
5689
  mode: modeRef.current
6167
5690
  })
6168
5691
  };
6169
- messagesRef.current[0] = sysMsg;
6170
- systemMessagesRef.current[0] = sysMsg;
6171
5692
  }
6172
5693
  setEvents((e) => [
6173
5694
  ...e,
@@ -6194,10 +5715,7 @@ function App({ initialCfg, initialUpdateResult }) {
6194
5715
  if (!picked) return;
6195
5716
  try {
6196
5717
  const file = await loadSession(picked.filePath);
6197
- const prefixEnd = file.messages.findIndex((m) => m.role !== "system");
6198
- systemMessagesRef.current = prefixEnd === -1 ? file.messages.slice() : file.messages.slice(0, prefixEnd);
6199
5718
  messagesRef.current = file.messages;
6200
- clearOutputHashCache();
6201
5719
  sessionIdRef.current = file.id;
6202
5720
  if (file.sessionState && compiledContextRef.current) {
6203
5721
  sessionStateRef.current = file.sessionState;
@@ -6260,12 +5778,10 @@ function App({ initialCfg, initialUpdateResult }) {
6260
5778
  }
6261
5779
  if (c === "/clear") {
6262
5780
  if (cacheStableRef.current && messagesRef.current.length >= 2) {
6263
- systemMessagesRef.current = [messagesRef.current[0], messagesRef.current[1]];
5781
+ messagesRef.current = [messagesRef.current[0], messagesRef.current[1]];
6264
5782
  } else {
6265
- systemMessagesRef.current = [messagesRef.current[0]];
5783
+ messagesRef.current = [messagesRef.current[0]];
6266
5784
  }
6267
- messagesRef.current = systemMessagesRef.current.slice();
6268
- clearOutputHashCache();
6269
5785
  sessionIdRef.current = null;
6270
5786
  sessionStateRef.current = emptySessionState();
6271
5787
  artifactStoreRef.current = new ArtifactStore();
@@ -6587,7 +6103,6 @@ use: /thinking low | medium | high`
6587
6103
  coauthor: cfg.coauthor !== false ? { name: cfg.coauthorName || "kimiflare", email: cfg.coauthorEmail || "kimiflare@proton.me" } : void 0,
6588
6104
  sessionId: ensureSessionId(),
6589
6105
  keepLastImageTurns: cfg.imageHistoryTurns ?? 2,
6590
- systemMessages: systemMessagesRef.current,
6591
6106
  callbacks: {
6592
6107
  onAssistantStart: () => {
6593
6108
  const id = nextAssistantId++;
@@ -6918,7 +6433,6 @@ var init_app = __esm({
6918
6433
  init_sessions();
6919
6434
  init_image();
6920
6435
  init_usage_tracker();
6921
- init_tool_output_summarizer();
6922
6436
  CONTEXT_LIMIT = 262e3;
6923
6437
  AUTO_COMPACT_SUGGEST_PCT = 0.8;
6924
6438
  MAX_EVENTS = 500;
@@ -6943,30 +6457,22 @@ init_update_check();
6943
6457
  import { Command } from "commander";
6944
6458
  import { readFileSync as readFileSync2 } from "fs";
6945
6459
  import { fileURLToPath as fileURLToPath2 } from "url";
6946
- import { dirname as dirname3, join as join11 } from "path";
6460
+ import { dirname as dirname3, join as join10 } from "path";
6947
6461
  function readPackageVersion() {
6948
6462
  try {
6949
6463
  const here = dirname3(fileURLToPath2(import.meta.url));
6950
- const pkg = JSON.parse(readFileSync2(join11(here, "..", "package.json"), "utf8"));
6464
+ const pkg = JSON.parse(readFileSync2(join10(here, "..", "package.json"), "utf8"));
6951
6465
  return pkg.version ?? "0.0.0";
6952
6466
  } catch {
6953
6467
  return "0.0.0";
6954
6468
  }
6955
6469
  }
6956
6470
  var program = new Command();
6957
- program.name("kimiflare").description("Terminal coding agent powered by Kimi-K2.6 on Cloudflare Workers AI.").version(readPackageVersion()).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)").command("usage").description("show per-turn token usage log from ~/.kimiflare/usage.jsonl").action(async () => {
6958
- const { showUsageLog: showUsageLog2 } = await Promise.resolve().then(() => (init_usage_cli(), usage_cli_exports));
6959
- await showUsageLog2();
6960
- });
6961
- program.parse();
6471
+ program.name("kimiflare").description("Terminal coding agent powered by Kimi-K2.6 on Cloudflare Workers AI.").version(readPackageVersion()).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)").parse();
6962
6472
  var opts = program.opts();
6963
6473
  async function main() {
6964
6474
  const cfg = await loadConfig();
6965
6475
  const updateResult = await checkForUpdate();
6966
- const args = program.args;
6967
- if (args[0] === "usage") {
6968
- return;
6969
- }
6970
6476
  if (opts.print !== void 0) {
6971
6477
  if (!cfg) {
6972
6478
  console.error(
@@ -7010,11 +6516,8 @@ async function runPrintMode(opts2) {
7010
6516
  }
7011
6517
  const cwd = process.cwd();
7012
6518
  const executor = new ToolExecutor(ALL_TOOLS);
7013
- const systemMessages = [
7014
- { role: "system", content: buildSystemPrompt({ cwd, tools: ALL_TOOLS, model: opts2.model }) }
7015
- ];
7016
6519
  const messages = [
7017
- ...systemMessages,
6520
+ { role: "system", content: buildSystemPrompt({ cwd, tools: ALL_TOOLS, model: opts2.model }) },
7018
6521
  { role: "user", content: opts2.prompt }
7019
6522
  ];
7020
6523
  const controller = new AbortController();
@@ -7030,7 +6533,6 @@ async function runPrintMode(opts2) {
7030
6533
  executor,
7031
6534
  cwd,
7032
6535
  signal: controller.signal,
7033
- systemMessages,
7034
6536
  coauthor: opts2.coauthor !== false ? { name: opts2.coauthorName || "kimiflare", email: opts2.coauthorEmail || "kimiflare@proton.me" } : void 0,
7035
6537
  callbacks: {
7036
6538
  onReasoningDelta: opts2.showReasoning ? (delta) => {