kimiflare 0.13.4 → 0.13.6

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
@@ -87,8 +87,6 @@ async function* readSSE(stream, signal) {
87
87
  const reader = stream.getReader();
88
88
  const decoder = new TextDecoder("utf-8");
89
89
  let buffer = "";
90
- const onAbort = () => reader.cancel(new DOMException("aborted", "AbortError"));
91
- signal?.addEventListener("abort", onAbort, { once: true });
92
90
  try {
93
91
  while (true) {
94
92
  if (signal?.aborted) throw new DOMException("aborted", "AbortError");
@@ -108,7 +106,6 @@ async function* readSSE(stream, signal) {
108
106
  const tail = extractData(buffer.trim());
109
107
  if (tail !== null) yield tail;
110
108
  } finally {
111
- signal?.removeEventListener("abort", onAbort);
112
109
  reader.releaseLock();
113
110
  }
114
111
  }
@@ -233,87 +230,57 @@ async function* parseStream(body, signal) {
233
230
  const toolCalls = /* @__PURE__ */ new Map();
234
231
  let lastUsage = null;
235
232
  let finishReason = null;
236
- let timeoutId = null;
237
- let timedOut = false;
238
- const resetTimeout = () => {
239
- if (timeoutId) clearTimeout(timeoutId);
240
- timeoutId = setTimeout(() => {
241
- timedOut = true;
242
- }, STREAM_TIMEOUT_MS);
243
- };
244
- try {
245
- for await (const dataStr of readSSE(body, signal)) {
246
- if (timedOut) {
247
- throw new KimiApiError(
248
- `kimiflare: stream timed out (no data for ${STREAM_TIMEOUT_MS / 1e3}s)`,
249
- void 0,
250
- void 0
251
- );
252
- }
253
- resetTimeout();
254
- if (dataStr === "[DONE]") break;
255
- let chunk = null;
256
- try {
257
- chunk = JSON.parse(dataStr);
258
- } catch {
259
- continue;
233
+ for await (const dataStr of readSSE(body, signal)) {
234
+ if (dataStr === "[DONE]") break;
235
+ let chunk = null;
236
+ try {
237
+ chunk = JSON.parse(dataStr);
238
+ } catch {
239
+ continue;
240
+ }
241
+ if (!chunk) continue;
242
+ if (chunk.usage) {
243
+ lastUsage = chunk.usage;
244
+ yield { type: "usage", usage: chunk.usage };
245
+ }
246
+ const choice = chunk.choices?.[0];
247
+ if (!choice) continue;
248
+ const d = choice.delta;
249
+ if (d) {
250
+ if (typeof d.reasoning_content === "string" && d.reasoning_content.length) {
251
+ yield { type: "reasoning", delta: d.reasoning_content };
260
252
  }
261
- if (!chunk) continue;
262
- if (chunk.usage) {
263
- lastUsage = chunk.usage;
264
- yield { type: "usage", usage: chunk.usage };
253
+ if (typeof d.content === "string" && d.content.length) {
254
+ yield { type: "text", delta: d.content };
265
255
  }
266
- const choice = chunk.choices?.[0];
267
- if (!choice) continue;
268
- const d = choice.delta;
269
- if (d) {
270
- if (typeof d.reasoning_content === "string" && d.reasoning_content.length) {
271
- yield { type: "reasoning", delta: d.reasoning_content };
272
- }
273
- if (typeof d.content === "string" && d.content.length) {
274
- yield { type: "text", delta: d.content };
275
- }
276
- if (Array.isArray(d.tool_calls)) {
277
- for (const tc of d.tool_calls) {
278
- const idx = typeof tc.index === "number" ? tc.index : 0;
279
- let buf = toolCalls.get(idx);
280
- const incomingName = tc.function?.name ?? null;
281
- const incomingId = tc.id ?? null;
282
- if (!buf) {
283
- buf = { id: incomingId ?? `tc_${idx}`, name: incomingName ?? "", args: "" };
284
- toolCalls.set(idx, buf);
285
- if (buf.name) {
286
- yield { type: "tool_call_start", index: idx, id: buf.id, name: buf.name };
287
- }
288
- } else {
289
- if (!buf.name && incomingName) {
290
- buf.name = incomingName;
291
- yield { type: "tool_call_start", index: idx, id: buf.id, name: buf.name };
292
- }
293
- if (buf.id.startsWith("tc_") && incomingId) buf.id = incomingId;
256
+ if (Array.isArray(d.tool_calls)) {
257
+ for (const tc of d.tool_calls) {
258
+ const idx = typeof tc.index === "number" ? tc.index : 0;
259
+ let buf = toolCalls.get(idx);
260
+ const incomingName = tc.function?.name ?? null;
261
+ const incomingId = tc.id ?? null;
262
+ if (!buf) {
263
+ buf = { id: incomingId ?? `tc_${idx}`, name: incomingName ?? "", args: "" };
264
+ toolCalls.set(idx, buf);
265
+ if (buf.name) {
266
+ yield { type: "tool_call_start", index: idx, id: buf.id, name: buf.name };
294
267
  }
295
- const argDelta = tc.function?.arguments;
296
- if (typeof argDelta === "string" && argDelta.length) {
297
- buf.args += argDelta;
298
- yield { type: "tool_call_args", index: idx, argsDelta: argDelta };
268
+ } else {
269
+ if (!buf.name && incomingName) {
270
+ buf.name = incomingName;
271
+ yield { type: "tool_call_start", index: idx, id: buf.id, name: buf.name };
299
272
  }
273
+ if (buf.id.startsWith("tc_") && incomingId) buf.id = incomingId;
274
+ }
275
+ const argDelta = tc.function?.arguments;
276
+ if (typeof argDelta === "string" && argDelta.length) {
277
+ buf.args += argDelta;
278
+ yield { type: "tool_call_args", index: idx, argsDelta: argDelta };
300
279
  }
301
280
  }
302
281
  }
303
- if (choice.finish_reason) finishReason = choice.finish_reason;
304
282
  }
305
- for (const [idx, buf] of [...toolCalls.entries()].sort((a, b) => a[0] - b[0])) {
306
- if (!buf.name) continue;
307
- yield {
308
- type: "tool_call_complete",
309
- index: idx,
310
- id: buf.id,
311
- name: buf.name,
312
- arguments: buf.args
313
- };
314
- }
315
- } finally {
316
- if (timeoutId) clearTimeout(timeoutId);
283
+ if (choice.finish_reason) finishReason = choice.finish_reason;
317
284
  }
318
285
  for (const [idx, buf] of [...toolCalls.entries()].sort((a, b) => a[0] - b[0])) {
319
286
  if (!buf.name) continue;
@@ -387,7 +354,7 @@ function sleep(ms, signal) {
387
354
  signal?.addEventListener("abort", onAbort, { once: true });
388
355
  });
389
356
  }
390
- var RETRYABLE_CODES, MAX_ATTEMPTS, STREAM_TIMEOUT_MS;
357
+ var RETRYABLE_CODES, MAX_ATTEMPTS;
391
358
  var init_client = __esm({
392
359
  "src/agent/client.ts"() {
393
360
  "use strict";
@@ -396,7 +363,6 @@ var init_client = __esm({
396
363
  init_messages();
397
364
  RETRYABLE_CODES = /* @__PURE__ */ new Set([3040]);
398
365
  MAX_ATTEMPTS = 5;
399
- STREAM_TIMEOUT_MS = 6e4;
400
366
  }
401
367
  });
402
368
 
@@ -3626,60 +3592,6 @@ function findImagePaths(text) {
3626
3592
  }
3627
3593
  return [...new Set(paths)];
3628
3594
  }
3629
- function stripImagesFromHistory(messages) {
3630
- for (const m of messages) {
3631
- if (!Array.isArray(m.content)) continue;
3632
- let changed = false;
3633
- const next = [];
3634
- for (const part of m.content) {
3635
- if (part.type === "image_url") {
3636
- changed = true;
3637
- next.push({ type: "text", text: "[image]" });
3638
- } else {
3639
- next.push(part);
3640
- }
3641
- }
3642
- if (changed) {
3643
- m.content = next;
3644
- }
3645
- }
3646
- }
3647
- function truncateOldToolResults(messages, keepRecent) {
3648
- const toolIndices = [];
3649
- for (let i = 0; i < messages.length; i++) {
3650
- if (messages[i].role === "tool") toolIndices.push(i);
3651
- }
3652
- const cutoff = toolIndices.length - keepRecent;
3653
- for (let i = 0; i < cutoff; i++) {
3654
- const idx = toolIndices[i];
3655
- const m = messages[idx];
3656
- const text = typeof m.content === "string" ? m.content : "";
3657
- if (text.length > 500) {
3658
- m.content = text.slice(0, 500) + "\n\u2026 [truncated]";
3659
- }
3660
- }
3661
- }
3662
- async function maybeAutoCompact(messages, cfg, onInfo) {
3663
- const heapUsed = process.memoryUsage().heapUsed;
3664
- if (heapUsed < HEAP_AUTO_COMPACT_THRESHOLD || messages.length <= MSG_AUTO_COMPACT_THRESHOLD) {
3665
- return false;
3666
- }
3667
- onInfo("auto-compacting to reduce memory usage");
3668
- const result = await compactMessages({
3669
- accountId: cfg.accountId,
3670
- apiToken: cfg.apiToken,
3671
- model: cfg.model,
3672
- messages,
3673
- keepLastTurns: 2
3674
- });
3675
- if (result.replacedCount > 0) {
3676
- messages.length = 0;
3677
- messages.push(...result.newMessages);
3678
- onInfo(`compacted ${result.replacedCount} messages into a summary`);
3679
- return true;
3680
- }
3681
- return false;
3682
- }
3683
3595
  function App({ initialCfg, initialUpdateResult }) {
3684
3596
  const { exit } = useApp();
3685
3597
  const [cfg, setCfg] = useState6(initialCfg);
@@ -3731,7 +3643,6 @@ function App({ initialCfg, initialUpdateResult }) {
3731
3643
  const executorRef = useRef3(new ToolExecutor(ALL_TOOLS));
3732
3644
  const activeAsstIdRef = useRef3(null);
3733
3645
  const activeControllerRef = useRef3(null);
3734
- const permResolveRef = useRef3(null);
3735
3646
  const sessionIdRef = useRef3(null);
3736
3647
  const modeRef = useRef3(mode);
3737
3648
  const effortRef = useRef3(effort);
@@ -3740,7 +3651,6 @@ function App({ initialCfg, initialUpdateResult }) {
3740
3651
  const updateCheckedRef = useRef3(false);
3741
3652
  const updateNudgedRef = useRef3(false);
3742
3653
  const compactSuggestedRef = useRef3(false);
3743
- const interruptRequestedRef = useRef3(false);
3744
3654
  useEffect4(() => {
3745
3655
  if (!cfg || updateCheckedRef.current) return;
3746
3656
  updateCheckedRef.current = true;
@@ -3874,15 +3784,8 @@ function App({ initialCfg, initialUpdateResult }) {
3874
3784
  }, [cfg]);
3875
3785
  useInput2((inputChar, key) => {
3876
3786
  if (key.ctrl && inputChar === "c") {
3877
- if (busy) {
3878
- if (interruptRequestedRef.current) {
3879
- process.exit(0);
3880
- }
3881
- interruptRequestedRef.current = true;
3882
- activeControllerRef.current?.abort();
3883
- permResolveRef.current?.("deny");
3884
- permResolveRef.current = null;
3885
- setPerm(null);
3787
+ if (busy && activeControllerRef.current) {
3788
+ activeControllerRef.current.abort();
3886
3789
  setQueue([]);
3887
3790
  setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "(interrupted)" }]);
3888
3791
  } else {
@@ -3974,7 +3877,6 @@ function App({ initialCfg, initialUpdateResult }) {
3974
3877
  setBusy(false);
3975
3878
  setTurnStartedAt(null);
3976
3879
  activeControllerRef.current = null;
3977
- interruptRequestedRef.current = false;
3978
3880
  }
3979
3881
  }, [cfg, busy, saveSessionSafe]);
3980
3882
  const openResumePicker = useCallback(async () => {
@@ -4105,21 +4007,10 @@ function App({ initialCfg, initialUpdateResult }) {
4105
4007
  resolve2("deny");
4106
4008
  return;
4107
4009
  }
4108
- permResolveRef.current = resolve2;
4109
- setPerm({ tool: req.tool, args: req.args, resolve: (d) => {
4110
- permResolveRef.current = null;
4111
- resolve2(d);
4112
- } });
4010
+ setPerm({ tool: req.tool, args: req.args, resolve: resolve2 });
4113
4011
  })
4114
4012
  }
4115
4013
  });
4116
- stripImagesFromHistory(messagesRef.current);
4117
- truncateOldToolResults(messagesRef.current, 8);
4118
- await maybeAutoCompact(
4119
- messagesRef.current,
4120
- cfg,
4121
- (text) => setEvents((es) => [...es, { kind: "info", key: mkKey(), text }])
4122
- );
4123
4014
  if (existsSync(join6(cwd, "KIMI.md"))) {
4124
4015
  messagesRef.current[0] = {
4125
4016
  role: "system",
@@ -4136,26 +4027,17 @@ function App({ initialCfg, initialUpdateResult }) {
4136
4027
  ]);
4137
4028
  }
4138
4029
  } catch (e) {
4139
- if (e.name === "AbortError") {
4140
- setEvents((es) => [...es, { kind: "info", key: mkKey(), text: "(interrupted)" }]);
4141
- setEvents(
4142
- (evts) => evts.map((e2) => e2.kind === "tool" && e2.status === "running" ? { ...e2, status: "error", result: "(interrupted)" } : e2)
4143
- );
4144
- } else {
4030
+ if (e.name !== "AbortError") {
4145
4031
  setEvents((es) => [
4146
4032
  ...es,
4147
4033
  { kind: "error", key: mkKey(), text: `init failed: ${e.message}` }
4148
4034
  ]);
4149
4035
  }
4150
4036
  } finally {
4151
- const asstId = activeAsstIdRef.current;
4152
- if (asstId !== null) updateAssistant(asstId, () => ({ streaming: false }));
4153
4037
  setBusy(false);
4154
4038
  setTurnStartedAt(null);
4155
4039
  activeAsstIdRef.current = null;
4156
4040
  activeControllerRef.current = null;
4157
- permResolveRef.current = null;
4158
- interruptRequestedRef.current = false;
4159
4041
  }
4160
4042
  }, [cfg, busy, updateAssistant, updateTool]);
4161
4043
  const handleResumePick = useCallback(
@@ -4567,28 +4449,14 @@ use: /thinking low | medium | high`
4567
4449
  resolve2("deny");
4568
4450
  return;
4569
4451
  }
4570
- permResolveRef.current = resolve2;
4571
- setPerm({ tool: req.tool, args: req.args, resolve: (d) => {
4572
- permResolveRef.current = null;
4573
- resolve2(d);
4574
- } });
4452
+ setPerm({ tool: req.tool, args: req.args, resolve: resolve2 });
4575
4453
  })
4576
4454
  }
4577
4455
  });
4578
- stripImagesFromHistory(messagesRef.current);
4579
- truncateOldToolResults(messagesRef.current, 8);
4580
- await maybeAutoCompact(
4581
- messagesRef.current,
4582
- cfg,
4583
- (text2) => setEvents((es) => [...es, { kind: "info", key: mkKey(), text: text2 }])
4584
- );
4585
- void saveSessionSafe();
4456
+ await saveSessionSafe();
4586
4457
  } catch (e) {
4587
4458
  if (e.name === "AbortError") {
4588
- setEvents((es) => [...es, { kind: "info", key: mkKey(), text: "(interrupted)" }]);
4589
- setEvents(
4590
- (evts) => evts.map((e2) => e2.kind === "tool" && e2.status === "running" ? { ...e2, status: "error", result: "(interrupted)" } : e2)
4591
- );
4459
+ setEvents((es) => [...es, { kind: "info", key: mkKey(), text: "(aborted)" }]);
4592
4460
  } else {
4593
4461
  const isInvalidJson400 = e instanceof KimiApiError && e.httpStatus === 400 && e.message.includes("invalid escaped character");
4594
4462
  if (isInvalidJson400) {
@@ -4609,14 +4477,10 @@ use: /thinking low | medium | high`
4609
4477
  }
4610
4478
  }
4611
4479
  } finally {
4612
- const asstId = activeAsstIdRef.current;
4613
- if (asstId !== null) updateAssistant(asstId, () => ({ streaming: false }));
4614
4480
  setBusy(false);
4615
4481
  setTurnStartedAt(null);
4616
4482
  activeAsstIdRef.current = null;
4617
4483
  activeControllerRef.current = null;
4618
- permResolveRef.current = null;
4619
- interruptRequestedRef.current = false;
4620
4484
  }
4621
4485
  },
4622
4486
  [cfg, handleSlash, updateAssistant, updateTool, saveSessionSafe]
@@ -4779,7 +4643,7 @@ async function renderApp(cfg, updateResult) {
4779
4643
  const instance = render(/* @__PURE__ */ jsx13(App, { initialCfg: cfg, initialUpdateResult: updateResult }));
4780
4644
  await instance.waitUntilExit();
4781
4645
  }
4782
- var CONTEXT_LIMIT, AUTO_COMPACT_SUGGEST_PCT, MAX_EVENTS, nextAssistantId, nextKey, mkKey, MAX_IMAGES_PER_MESSAGE, EFFORT_DESCRIPTIONS, HEAP_AUTO_COMPACT_THRESHOLD, MSG_AUTO_COMPACT_THRESHOLD;
4646
+ var CONTEXT_LIMIT, AUTO_COMPACT_SUGGEST_PCT, MAX_EVENTS, nextAssistantId, nextKey, mkKey, MAX_IMAGES_PER_MESSAGE, EFFORT_DESCRIPTIONS;
4783
4647
  var init_app = __esm({
4784
4648
  "src/app.tsx"() {
4785
4649
  "use strict";
@@ -4816,8 +4680,6 @@ var init_app = __esm({
4816
4680
  medium: "medium \u2014 balanced (default). Solid quality on most edits, fast on trivial prompts.",
4817
4681
  high: "high \u2014 deepest reasoning; slowest. Best for complex debugging, architecture, multi-file refactors."
4818
4682
  };
4819
- HEAP_AUTO_COMPACT_THRESHOLD = 2e9;
4820
- MSG_AUTO_COMPACT_THRESHOLD = 50;
4821
4683
  }
4822
4684
  });
4823
4685
 
@@ -4895,10 +4757,7 @@ async function runPrintMode(opts2) {
4895
4757
  { role: "user", content: opts2.prompt }
4896
4758
  ];
4897
4759
  const controller = new AbortController();
4898
- process.once("SIGINT", () => {
4899
- controller.abort();
4900
- setTimeout(() => process.exit(1), 500);
4901
- });
4760
+ process.on("SIGINT", () => controller.abort());
4902
4761
  let printedReasoningHeader = false;
4903
4762
  let printedAnswerHeader = false;
4904
4763
  await runAgentTurn({