kimiflare 0.68.2 → 0.69.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 CHANGED
@@ -1244,7 +1244,10 @@ async function logTurnDebug(ctx) {
1244
1244
  durationMs: ctx.durationMs,
1245
1245
  intentClassification: ctx.intentClassification,
1246
1246
  codeMode: ctx.codeMode,
1247
- selectedSkills: ctx.selectedSkills?.map((s) => s.name)
1247
+ selectedSkills: ctx.selectedSkills?.map((s) => s.name),
1248
+ userPromptPreview: ctx.userPromptPreview,
1249
+ preTurnMs: ctx.preTurnMs,
1250
+ memoryRecalled: ctx.memoryRecalled
1248
1251
  });
1249
1252
  }
1250
1253
  var LOG_VERSION;
@@ -3193,9 +3196,11 @@ async function runAgentTurn(opts2) {
3193
3196
  logger.info("turn:start", { sessionId: opts2.sessionId, codeMode: opts2.codeMode ?? false });
3194
3197
  const max = opts2.maxToolIterations ?? 50;
3195
3198
  const codeMode = opts2.codeMode ?? false;
3199
+ const preTurnStart = performance.now();
3196
3200
  let memoryRecalledCount = 0;
3197
3201
  let skillResult;
3198
3202
  const lastUserPrompt = extractLastUserText(opts2.messages);
3203
+ const userPromptPreview = lastUserPrompt.slice(0, 200);
3199
3204
  const skipSkillRouting = opts2.intentClassification?.tier === "light" && lastUserPrompt.length < 40;
3200
3205
  const recallPromise = opts2.sessionStartRecall && opts2.memoryManager ? (async () => {
3201
3206
  const results = await opts2.sessionStartRecall;
@@ -3268,6 +3273,7 @@ async function runAgentTurn(opts2) {
3268
3273
  if (opts2.signal.aborted) {
3269
3274
  throw new DOMException("aborted", "AbortError");
3270
3275
  }
3276
+ const preTurnMs = Math.round(performance.now() - preTurnStart);
3271
3277
  opts2.callbacks.onMetaBanner?.({
3272
3278
  intentTier: opts2.intentClassification?.tier ?? "medium",
3273
3279
  skillsActive: skillResult?.sectionCount ?? 0,
@@ -3422,7 +3428,9 @@ Use console.log() to return results. Only console.log output will be sent back t
3422
3428
  ...opts2.gateway.metadata ?? {},
3423
3429
  feature: "chat",
3424
3430
  ...opts2.sessionId ? { sessionId: opts2.sessionId } : {},
3425
- turnIdx: turn
3431
+ tier: opts2.intentClassification?.tier ?? "medium",
3432
+ cm: codeMode ? "1" : "0",
3433
+ skl: String(skillResult?.sectionCount ?? 0)
3426
3434
  }
3427
3435
  } : void 0;
3428
3436
  const events = runKimi({
@@ -3520,7 +3528,14 @@ Use console.log() to return results. Only console.log output will be sent back t
3520
3528
  previousMessages,
3521
3529
  toolResults,
3522
3530
  usage: lastUsage,
3523
- shadowStrip: shadowStripMetrics
3531
+ shadowStrip: shadowStripMetrics,
3532
+ durationMs: Math.round(performance.now() - turnStart),
3533
+ intentClassification: opts2.intentClassification,
3534
+ codeMode: opts2.codeMode,
3535
+ selectedSkills: opts2.selectedSkills,
3536
+ userPromptPreview,
3537
+ preTurnMs,
3538
+ memoryRecalled: memoryRecalledCount > 0
3524
3539
  });
3525
3540
  }
3526
3541
  if (budgetExhausted) {
@@ -3829,7 +3844,10 @@ ${sandboxResult.output}` : sandboxResult.output;
3829
3844
  durationMs: Math.round(performance.now() - turnStart),
3830
3845
  intentClassification: opts2.intentClassification,
3831
3846
  codeMode: opts2.codeMode,
3832
- selectedSkills: opts2.selectedSkills
3847
+ selectedSkills: opts2.selectedSkills,
3848
+ userPromptPreview,
3849
+ preTurnMs,
3850
+ memoryRecalled: memoryRecalledCount > 0
3833
3851
  });
3834
3852
  }
3835
3853
  if (budgetExhausted) {
@@ -3950,15 +3968,61 @@ var init_paths = __esm({
3950
3968
 
3951
3969
  // src/tools/read.ts
3952
3970
  import { readFile as readFile3, stat as stat2 } from "fs/promises";
3953
- var MAX_BYTES, readTool;
3971
+ import { createReadStream } from "fs";
3972
+ import { createInterface } from "readline";
3973
+ function aborted(signal) {
3974
+ return signal?.aborted === true;
3975
+ }
3976
+ function abortError() {
3977
+ return new DOMException("aborted", "AbortError");
3978
+ }
3979
+ async function readSliceStreaming(abs, offset, limit, signal) {
3980
+ if (aborted(signal)) throw abortError();
3981
+ const rs = createReadStream(abs, { encoding: "utf8" });
3982
+ const onAbort = () => rs.destroy(abortError());
3983
+ signal?.addEventListener("abort", onAbort);
3984
+ try {
3985
+ const rl = createInterface({ input: rs, crlfDelay: Infinity });
3986
+ const startLine = Math.max(1, offset);
3987
+ const endLine = startLine + Math.max(0, limit) - 1;
3988
+ const collected = [];
3989
+ let lineNum = 0;
3990
+ let bytesScanned = 0;
3991
+ for await (const line of rl) {
3992
+ if (aborted(signal)) throw abortError();
3993
+ lineNum += 1;
3994
+ bytesScanned += Buffer.byteLength(line, "utf8") + 1;
3995
+ if (bytesScanned > MAX_STREAM_BYTES) {
3996
+ throw new Error(
3997
+ `file too large to stream: exceeded ${MAX_STREAM_BYTES} bytes while seeking slice at line ${startLine}`
3998
+ );
3999
+ }
4000
+ if (lineNum >= startLine && lineNum <= endLine) {
4001
+ collected.push(line);
4002
+ }
4003
+ if (lineNum >= endLine) break;
4004
+ }
4005
+ return collected;
4006
+ } finally {
4007
+ signal?.removeEventListener("abort", onAbort);
4008
+ rs.destroy();
4009
+ }
4010
+ }
4011
+ function formatLines(lines, startLine) {
4012
+ const endLine = startLine + lines.length - 1;
4013
+ const width = String(endLine).length;
4014
+ return lines.map((l, i) => `${String(startLine + i).padStart(width, " ")} ${l}`).join("\n");
4015
+ }
4016
+ var MAX_BYTES, MAX_STREAM_BYTES, readTool;
3954
4017
  var init_read = __esm({
3955
4018
  "src/tools/read.ts"() {
3956
4019
  "use strict";
3957
4020
  init_paths();
3958
4021
  MAX_BYTES = 2 * 1024 * 1024;
4022
+ MAX_STREAM_BYTES = 50 * 1024 * 1024;
3959
4023
  readTool = {
3960
4024
  name: "read",
3961
- description: "Read a text file from the local filesystem. Supports optional line offset/limit. Refuses files larger than 2MB. Returns contents with 1-indexed line numbers prefixed, cat -n style. When reading a full file without offset/limit, the output is reduced to a compact outline (imports, exports, signatures, preview) by default; use expand_artifact to retrieve the full content or specify offset/limit for a targeted slice.",
4025
+ description: "Read a text file from the local filesystem. Supports optional line offset/limit. Files up to 2MB are read in a single pass; larger files require an explicit offset+limit slice and are streamed line by line (cancellable mid-stream). Returns contents with 1-indexed line numbers prefixed, cat -n style. When reading a full file without offset/limit, the output is reduced to a compact outline (imports, exports, signatures, preview) by default; use expand_artifact to retrieve the full content or specify offset/limit for a targeted slice.",
3962
4026
  parameters: {
3963
4027
  type: "object",
3964
4028
  properties: {
@@ -3972,13 +4036,21 @@ var init_read = __esm({
3972
4036
  needsPermission: false,
3973
4037
  render: ({ path }) => ({ title: `read ${collapsePath(path, process.cwd())}` }),
3974
4038
  async run(args, ctx) {
3975
- if (ctx.signal?.aborted) throw new DOMException("aborted", "AbortError");
4039
+ if (aborted(ctx.signal)) throw abortError();
3976
4040
  const abs = resolvePath(ctx.cwd, args.path);
3977
4041
  const st = await stat2(abs);
3978
- if (st.size > MAX_BYTES) throw new Error(`file too large: ${st.size} bytes (max ${MAX_BYTES})`);
3979
- if (ctx.signal?.aborted) throw new DOMException("aborted", "AbortError");
4042
+ if (aborted(ctx.signal)) throw abortError();
4043
+ if (st.size > MAX_BYTES) {
4044
+ if (args.offset === void 0 || args.limit === void 0) {
4045
+ throw new Error(
4046
+ `file too large: ${st.size} bytes (max ${MAX_BYTES} for full read; supply offset+limit to stream a slice)`
4047
+ );
4048
+ }
4049
+ const lines2 = await readSliceStreaming(abs, args.offset, args.limit, ctx.signal);
4050
+ return formatLines(lines2, args.offset);
4051
+ }
3980
4052
  const text = await readFile3(abs, { encoding: "utf8", signal: ctx.signal });
3981
- if (ctx.signal?.aborted) throw new DOMException("aborted", "AbortError");
4053
+ if (aborted(ctx.signal)) throw abortError();
3982
4054
  const lines = text.split("\n");
3983
4055
  const start = Math.max(0, (args.offset ?? 1) - 1);
3984
4056
  const end = args.limit ? Math.min(lines.length, start + args.limit) : lines.length;
@@ -10172,7 +10244,7 @@ var rpc_exports = {};
10172
10244
  __export(rpc_exports, {
10173
10245
  startRpcServer: () => startRpcServer
10174
10246
  });
10175
- import { createInterface } from "readline";
10247
+ import { createInterface as createInterface2 } from "readline";
10176
10248
  async function startRpcServer(input = process.stdin, output = process.stdout) {
10177
10249
  let session = null;
10178
10250
  let unsubscribe = null;
@@ -10182,7 +10254,7 @@ async function startRpcServer(input = process.stdin, output = process.stdout) {
10182
10254
  function sendEvent(event) {
10183
10255
  send({ ...event });
10184
10256
  }
10185
- const rl = createInterface({
10257
+ const rl = createInterface2({
10186
10258
  input,
10187
10259
  crlfDelay: Infinity
10188
10260
  });
@@ -18822,6 +18894,61 @@ var init_use_turn_controller = __esm({
18822
18894
  }
18823
18895
  });
18824
18896
 
18897
+ // src/ui/input-handlers.ts
18898
+ function clearLimitLoopResolvers(deps) {
18899
+ const hadLimit = deps.limitResolveRef.current !== null;
18900
+ const hadLoop = deps.loopResolveRef.current !== null;
18901
+ if (hadLimit) {
18902
+ deps.limitResolveRef.current("stop");
18903
+ deps.limitResolveRef.current = null;
18904
+ deps.setLimitModal(null);
18905
+ }
18906
+ if (hadLoop) {
18907
+ deps.loopResolveRef.current("stop");
18908
+ deps.loopResolveRef.current = null;
18909
+ deps.setLoopModal(null);
18910
+ }
18911
+ return { hadLimit, hadLoop };
18912
+ }
18913
+ function interruptTurn(deps) {
18914
+ const hadPermission = deps.denyPendingPermission();
18915
+ const { hadLimit, hadLoop } = clearLimitLoopResolvers(deps);
18916
+ if (deps.busyRef.current && deps.activeScopeRef.current && !deps.isAbortingRef.current) {
18917
+ deps.isAbortingRef.current = true;
18918
+ deps.supervisorRef.current.killTurn();
18919
+ deps.activeScopeRef.current.abort("user_stopped");
18920
+ deps.setEvents((e) => [
18921
+ ...e,
18922
+ { kind: "info", key: deps.mkKey(), text: "(interrupted)" }
18923
+ ]);
18924
+ if (!deps.skipPendingToolCleanup) {
18925
+ for (const [toolId] of deps.pendingToolCallsRef.current) {
18926
+ deps.updateTool(toolId, { status: "cancelled" });
18927
+ }
18928
+ deps.pendingToolCallsRef.current.clear();
18929
+ }
18930
+ void deps.saveSessionSafe();
18931
+ deps.clearTaskTracking();
18932
+ return { hadPermission, hadLimit, hadLoop, didInterruptTurn: true };
18933
+ }
18934
+ return { hadPermission, hadLimit, hadLoop, didInterruptTurn: false };
18935
+ }
18936
+ function exitApp(deps) {
18937
+ void deps.lspManagerRef.current.stopAll().finally(() => deps.exit());
18938
+ }
18939
+ function interruptOrExit(deps) {
18940
+ const outcome = interruptTurn(deps);
18941
+ if (!outcome.didInterruptTurn && !outcome.hadPermission && !outcome.hadLimit && !outcome.hadLoop) {
18942
+ exitApp(deps);
18943
+ }
18944
+ return outcome;
18945
+ }
18946
+ var init_input_handlers = __esm({
18947
+ "src/ui/input-handlers.ts"() {
18948
+ "use strict";
18949
+ }
18950
+ });
18951
+
18825
18952
  // src/cost-attribution/tui-report.ts
18826
18953
  var tui_report_exports = {};
18827
18954
  __export(tui_report_exports, {
@@ -19928,6 +20055,7 @@ ${wcagWarnings.join("\n")}` }
19928
20055
  },
19929
20056
  [cfg]
19930
20057
  );
20058
+ const interruptDepsRef = useRef7(null);
19931
20059
  useInput10((inputChar, key) => {
19932
20060
  if (key.ctrl && inputChar === "c") {
19933
20061
  logger.info("input:ctrl+c", {
@@ -19937,33 +20065,9 @@ ${wcagWarnings.join("\n")}` }
19937
20065
  hasPerm: hasPendingPermission(),
19938
20066
  hasLimit: limitResolveRef.current !== null
19939
20067
  });
19940
- const hadPerm = denyPendingPermission();
19941
- const hadLimit = limitResolveRef.current !== null;
19942
- const hadLoop = loopResolveRef.current !== null;
19943
- if (hadLimit) {
19944
- limitResolveRef.current("stop");
19945
- limitResolveRef.current = null;
19946
- setLimitModal(null);
19947
- }
19948
- if (hadLoop) {
19949
- loopResolveRef.current("stop");
19950
- loopResolveRef.current = null;
19951
- setLoopModal(null);
19952
- }
19953
- if (busyRef.current && activeScopeRef.current && !isAbortingRef.current) {
19954
- isAbortingRef.current = true;
19955
- supervisorRef.current.killTurn();
19956
- activeScopeRef.current.abort("user_stopped");
19957
- setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "(interrupted)" }]);
19958
- for (const [toolId] of pendingToolCallsRef.current) {
19959
- updateTool(toolId, { status: "cancelled" });
19960
- }
19961
- pendingToolCallsRef.current.clear();
19962
- void saveSessionSafe();
19963
- clearTaskTracking();
19964
- } else if (!hadPerm && !hadLimit && !hadLoop) {
20068
+ const outcome = interruptOrExit(interruptDepsRef.current);
20069
+ if (!outcome.didInterruptTurn && !outcome.hadPermission && !outcome.hadLimit && !outcome.hadLoop) {
19965
20070
  logger.info("input:ctrl+c:exiting");
19966
- void lspManagerRef.current.stopAll().finally(() => exit());
19967
20071
  }
19968
20072
  return;
19969
20073
  }
@@ -19972,26 +20076,7 @@ ${wcagWarnings.join("\n")}` }
19972
20076
  const modalOpen = perm !== null || limitModal !== null || loopModal !== null || showLspWizard || showCommandList || commandWizard !== null || commandToDelete !== null || resumeSessions !== null || checkpointSession !== null || showThemePicker;
19973
20077
  if (!modalOpen && busyRef.current && activeScopeRef.current && !isAbortingRef.current && now2 - lastEscapeAtRef.current > 500) {
19974
20078
  lastEscapeAtRef.current = now2;
19975
- isAbortingRef.current = true;
19976
- supervisorRef.current.killTurn();
19977
- denyPendingPermission();
19978
- if (limitResolveRef.current) {
19979
- limitResolveRef.current("stop");
19980
- limitResolveRef.current = null;
19981
- setLimitModal(null);
19982
- }
19983
- if (loopResolveRef.current) {
19984
- loopResolveRef.current("stop");
19985
- loopResolveRef.current = null;
19986
- setLoopModal(null);
19987
- }
19988
- activeScopeRef.current.abort("user_stopped");
19989
- setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "(interrupted)" }]);
19990
- for (const [toolId] of pendingToolCallsRef.current) {
19991
- updateTool(toolId, { status: "cancelled" });
19992
- }
19993
- pendingToolCallsRef.current.clear();
19994
- clearTaskTracking();
20079
+ interruptTurn(interruptDepsRef.current);
19995
20080
  return;
19996
20081
  }
19997
20082
  }
@@ -20017,29 +20102,12 @@ ${wcagWarnings.join("\n")}` }
20017
20102
  hasLimit: limitResolveRef.current !== null,
20018
20103
  hasLoop: loopResolveRef.current !== null
20019
20104
  });
20020
- const hadPerm = denyPendingPermission();
20021
- const hadLimit = limitResolveRef.current !== null;
20022
- const hadLoop = loopResolveRef.current !== null;
20023
- if (hadLimit) {
20024
- limitResolveRef.current("stop");
20025
- limitResolveRef.current = null;
20026
- setLimitModal(null);
20027
- }
20028
- if (hadLoop) {
20029
- loopResolveRef.current("stop");
20030
- loopResolveRef.current = null;
20031
- setLoopModal(null);
20032
- }
20033
- if (busyRef.current && activeScopeRef.current && !isAbortingRef.current) {
20034
- isAbortingRef.current = true;
20035
- supervisorRef.current.killTurn();
20036
- activeScopeRef.current.abort("user_stopped");
20037
- setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "(interrupted)" }]);
20038
- void saveSessionSafe();
20039
- clearTaskTracking();
20040
- } else if (!hadPerm && !hadLimit) {
20105
+ const outcome = interruptOrExit({
20106
+ ...interruptDepsRef.current,
20107
+ skipPendingToolCleanup: true
20108
+ });
20109
+ if (!outcome.didInterruptTurn && !outcome.hadPermission && !outcome.hadLimit && !outcome.hadLoop) {
20041
20110
  logger.info("sigint:handler:exiting");
20042
- void lspManagerRef.current.stopAll().finally(() => exit());
20043
20111
  }
20044
20112
  };
20045
20113
  const flushAssistantUpdates = useCallback8(() => {
@@ -20103,6 +20171,26 @@ ${wcagWarnings.join("\n")}` }
20103
20171
  gatewayMetaRef.current = meta;
20104
20172
  setGatewayMeta(meta);
20105
20173
  }, []);
20174
+ interruptDepsRef.current = {
20175
+ busyRef,
20176
+ activeScopeRef,
20177
+ isAbortingRef,
20178
+ supervisorRef,
20179
+ limitResolveRef,
20180
+ loopResolveRef,
20181
+ setLimitModal,
20182
+ setLoopModal,
20183
+ hasPendingPermission,
20184
+ denyPendingPermission,
20185
+ pendingToolCallsRef,
20186
+ updateTool,
20187
+ setEvents,
20188
+ mkKey,
20189
+ saveSessionSafe,
20190
+ clearTaskTracking,
20191
+ lspManagerRef,
20192
+ exit
20193
+ };
20106
20194
  const runCompact = useCallback8(async () => {
20107
20195
  if (!cfg) return;
20108
20196
  if (busy) {
@@ -22414,6 +22502,7 @@ var init_app = __esm({
22414
22502
  init_modal_host();
22415
22503
  init_use_session_manager();
22416
22504
  init_use_turn_controller();
22505
+ init_input_handlers();
22417
22506
  MAX_GITIGNORE_SIZE = 1 * 1024 * 1024;
22418
22507
  FEEDBACK_WORKER_URL2 = "https://hello.kimiflare.com";
22419
22508
  CONTEXT_LIMIT = 262e3;