kimiflare 0.48.1 → 0.48.3

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
@@ -357,7 +357,7 @@ function log(level, event, data) {
357
357
  };
358
358
  console.error(JSON.stringify(entry));
359
359
  }
360
- var globalMinLevel, LEVEL_ORDER, logger;
360
+ var globalMinLevel, LEVEL_ORDER, logger2;
361
361
  var init_logger = __esm({
362
362
  "src/util/logger.ts"() {
363
363
  "use strict";
@@ -369,7 +369,7 @@ var init_logger = __esm({
369
369
  error: 3,
370
370
  off: 4
371
371
  };
372
- logger = {
372
+ logger2 = {
373
373
  debug: (event, data) => log("debug", event, data),
374
374
  info: (event, data) => log("info", event, data),
375
375
  warn: (event, data) => log("warn", event, data),
@@ -406,7 +406,7 @@ async function* readSSE(stream, signal, idleTimeoutMs) {
406
406
  while (true) {
407
407
  if (signal?.aborted) throw new DOMException("aborted", "AbortError");
408
408
  if (idleTimeoutMs !== void 0 && Date.now() - lastDataAt > idleTimeoutMs) {
409
- logger.warn("sse:idle_timeout", { idleTimeoutMs });
409
+ logger2.warn("sse:idle_timeout", { idleTimeoutMs });
410
410
  throw new DOMException(
411
411
  `kimiflare: stream idle for ${idleTimeoutMs}ms \u2014 no data received from API`,
412
412
  "TimeoutError"
@@ -581,7 +581,7 @@ async function* runKimi(opts2) {
581
581
  if (opts2.reasoningEffort) {
582
582
  body.reasoning_effort = opts2.reasoningEffort;
583
583
  }
584
- logger.debug("runKimi:request", { requestId, attempt: 0, model: opts2.model });
584
+ logger2.debug("runKimi:request", { requestId, attempt: 0, model: opts2.model });
585
585
  for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {
586
586
  let res;
587
587
  try {
@@ -604,7 +604,7 @@ async function* runKimi(opts2) {
604
604
  });
605
605
  } catch (fetchErr) {
606
606
  const msg = fetchErr instanceof Error ? fetchErr.message : String(fetchErr);
607
- logger.warn("runKimi:fetch_error", { requestId, attempt, error: msg });
607
+ logger2.warn("runKimi:fetch_error", { requestId, attempt, error: msg });
608
608
  if (attempt < MAX_ATTEMPTS - 1) {
609
609
  const delay = 500 * 2 ** attempt + Math.random() * 250;
610
610
  await sleep(delay, opts2.signal);
@@ -635,12 +635,12 @@ async function* runKimi(opts2) {
635
635
  const meta = readGatewayMeta(res.headers);
636
636
  if (meta) yield { type: "gateway_meta", meta };
637
637
  let lastUsage = null;
638
- logger.debug("runKimi:stream_start", { requestId });
638
+ logger2.debug("runKimi:stream_start", { requestId });
639
639
  for await (const ev of parseStream(res.body, opts2.signal, opts2.idleTimeoutMs)) {
640
640
  if (ev.type === "usage") lastUsage = ev.usage;
641
641
  yield ev;
642
642
  }
643
- logger.debug("runKimi:stream_end", { requestId });
643
+ logger2.debug("runKimi:stream_end", { requestId });
644
644
  if (opts2.cloudMode && lastUsage && opts2.cloudToken) {
645
645
  const reportUrl = "https://api.kimiflare.com/v1/usage/report";
646
646
  const reportHeaders = {
@@ -2375,7 +2375,7 @@ function isHighSignalMemory(memory) {
2375
2375
  }
2376
2376
  async function runAgentTurn(opts2) {
2377
2377
  const turnStart = performance.now();
2378
- logger.info("turn:start", { sessionId: opts2.sessionId, codeMode: opts2.codeMode ?? false });
2378
+ logger2.info("turn:start", { sessionId: opts2.sessionId, codeMode: opts2.codeMode ?? false });
2379
2379
  const max = opts2.maxToolIterations ?? 50;
2380
2380
  const codeMode = opts2.codeMode ?? false;
2381
2381
  let toolDefs;
@@ -2512,7 +2512,7 @@ Use console.log() to return results. Only console.log output will be sent back t
2512
2512
  `kimiflare: context window exceeded (~${promptTokens.toLocaleString()} tokens). Run /compact to summarize older turns, or /clear to start fresh.`
2513
2513
  );
2514
2514
  }
2515
- logger.debug("turn:api_request", { sessionId: opts2.sessionId, messageCount: apiMessages.length });
2515
+ logger2.debug("turn:api_request", { sessionId: opts2.sessionId, messageCount: apiMessages.length });
2516
2516
  const events = runKimi({
2517
2517
  accountId: opts2.accountId,
2518
2518
  apiToken: opts2.apiToken,
@@ -2534,7 +2534,7 @@ Use console.log() to return results. Only console.log output will be sent back t
2534
2534
  for await (const ev of events) {
2535
2535
  if (!gotFirstChunk) {
2536
2536
  gotFirstChunk = true;
2537
- logger.debug("turn:api_first_chunk", { sessionId: opts2.sessionId });
2537
+ logger2.debug("turn:api_first_chunk", { sessionId: opts2.sessionId });
2538
2538
  }
2539
2539
  switch (ev.type) {
2540
2540
  case "gateway_meta":
@@ -2613,7 +2613,7 @@ Use console.log() to return results. Only console.log output will be sent back t
2613
2613
  if (budgetExhausted) {
2614
2614
  throw new BudgetExhaustedError();
2615
2615
  }
2616
- logger.info("turn:complete", { sessionId: opts2.sessionId, durationMs: Math.round(performance.now() - turnStart) });
2616
+ logger2.info("turn:complete", { sessionId: opts2.sessionId, durationMs: Math.round(performance.now() - turnStart) });
2617
2617
  return;
2618
2618
  }
2619
2619
  for (const tc of toolCalls) {
@@ -2742,7 +2742,7 @@ ${sandboxResult.output}` : `${warningPrefix}${sandboxResult.output}`;
2742
2742
  recentToolCalls.push(loopSignature);
2743
2743
  if (recentToolCalls.length > LOOP_WINDOW) recentToolCalls.shift();
2744
2744
  } else {
2745
- logger.debug("turn:tool_start", { sessionId: opts2.sessionId, tool: tc.function.name, toolCallId: tc.id });
2745
+ logger2.debug("turn:tool_start", { sessionId: opts2.sessionId, tool: tc.function.name, toolCallId: tc.id });
2746
2746
  const result = await opts2.executor.run(
2747
2747
  { id: tc.id, name: tc.function.name, arguments: tc.function.arguments },
2748
2748
  opts2.callbacks.askPermission,
@@ -2755,7 +2755,7 @@ ${sandboxResult.output}` : `${warningPrefix}${sandboxResult.output}`;
2755
2755
 
2756
2756
  [truncated: ${content2.length - MAX_TOOL_CONTENT_CHARS} chars omitted]`;
2757
2757
  }
2758
- logger.debug("turn:tool_end", { sessionId: opts2.sessionId, tool: tc.function.name, toolCallId: tc.id, ok: result.ok });
2758
+ logger2.debug("turn:tool_end", { sessionId: opts2.sessionId, tool: tc.function.name, toolCallId: tc.id, ok: result.ok });
2759
2759
  toolResults.push(result);
2760
2760
  opts2.messages.push({
2761
2761
  role: "tool",
@@ -3411,7 +3411,7 @@ function runBash(args, ctx) {
3411
3411
  const timeout = Math.min(Math.max(1e3, args.timeout_ms ?? DEFAULT_TIMEOUT), MAX_TIMEOUT);
3412
3412
  const command = injectCoauthor(args.command, ctx.coauthor);
3413
3413
  return new Promise((resolve2, reject) => {
3414
- logger.debug("bash:spawn", { command: args.command.slice(0, 200), cwd: ctx.cwd });
3414
+ logger2.debug("bash:spawn", { command: args.command.slice(0, 200), cwd: ctx.cwd });
3415
3415
  const child = spawn("bash", ["-lc", command], {
3416
3416
  cwd: ctx.cwd,
3417
3417
  env: {
@@ -3425,12 +3425,12 @@ function runBash(args, ctx) {
3425
3425
  let killedByAbort = false;
3426
3426
  const timer = setTimeout(() => {
3427
3427
  killedByTimeout = true;
3428
- logger.warn("bash:kill_timeout", { command: args.command.slice(0, 200) });
3428
+ logger2.warn("bash:kill_timeout", { command: args.command.slice(0, 200) });
3429
3429
  child.kill("SIGKILL");
3430
3430
  }, timeout);
3431
3431
  const onAbort = () => {
3432
3432
  killedByAbort = true;
3433
- logger.warn("bash:kill_abort", { command: args.command.slice(0, 200) });
3433
+ logger2.warn("bash:kill_abort", { command: args.command.slice(0, 200), pid: child.pid });
3434
3434
  child.kill("SIGKILL");
3435
3435
  };
3436
3436
  ctx.signal?.addEventListener("abort", onAbort, { once: true });
@@ -3443,13 +3443,18 @@ function runBash(args, ctx) {
3443
3443
  child.on("error", (e) => {
3444
3444
  clearTimeout(timer);
3445
3445
  ctx.signal?.removeEventListener("abort", onAbort);
3446
- logger.error("bash:error", { error: e.message });
3446
+ logger2.error("bash:error", { error: e.message, pid: child.pid });
3447
3447
  reject(e);
3448
3448
  });
3449
+ child.on("exit", (code, signal) => {
3450
+ logger2.debug("bash:exit", { code, signal, pid: child.pid, killedByTimeout, killedByAbort });
3451
+ child.stdout?.destroy();
3452
+ child.stderr?.destroy();
3453
+ });
3449
3454
  child.on("close", (code, signal) => {
3450
3455
  clearTimeout(timer);
3451
3456
  ctx.signal?.removeEventListener("abort", onAbort);
3452
- logger.debug("bash:close", { code, signal, killedByTimeout, killedByAbort });
3457
+ logger2.debug("bash:close", { code, signal, pid: child.pid, killedByTimeout, killedByAbort });
3453
3458
  const header = killedByTimeout ? `(timed out after ${timeout}ms)` : killedByAbort ? `(aborted \u2014 sent SIGKILL)` : `exit=${code ?? "?"}${signal ? ` signal=${signal}` : ""}`;
3454
3459
  const parts = [header];
3455
3460
  if (stdout) parts.push(`--- stdout ---
@@ -6244,24 +6249,24 @@ var init_supervisor = __esm({
6244
6249
  }
6245
6250
  startTurn(opts2, callbacks) {
6246
6251
  if (this.isRunning) {
6247
- logger.warn("supervisor:start_rejected", { reason: "turn_already_running", phase: this._phase });
6252
+ logger2.warn("supervisor:start_rejected", { reason: "turn_already_running", phase: this._phase });
6248
6253
  throw new Error("TurnSupervisor: turn already in progress");
6249
6254
  }
6250
6255
  this._phase = "streaming";
6251
6256
  this._killRequested = false;
6252
- logger.debug("supervisor:turn_start", { sessionId: opts2.sessionId });
6257
+ logger2.debug("supervisor:turn_start", { sessionId: opts2.sessionId });
6253
6258
  this.currentTurn = runAgentTurn(opts2).then(async () => {
6254
6259
  this._phase = "idle";
6255
6260
  if (this._killRequested) {
6256
- logger.debug("supervisor:turn_killed", { sessionId: opts2.sessionId });
6261
+ logger2.debug("supervisor:turn_killed", { sessionId: opts2.sessionId });
6257
6262
  } else {
6258
- logger.debug("supervisor:turn_done", { sessionId: opts2.sessionId });
6263
+ logger2.debug("supervisor:turn_done", { sessionId: opts2.sessionId });
6259
6264
  }
6260
6265
  await callbacks?.onDone?.();
6261
6266
  }).catch(async (error) => {
6262
6267
  this._phase = "idle";
6263
6268
  const err = error;
6264
- logger.warn("supervisor:turn_error", {
6269
+ logger2.warn("supervisor:turn_error", {
6265
6270
  sessionId: opts2.sessionId,
6266
6271
  error: err.message ?? String(err),
6267
6272
  name: err.name
@@ -6279,7 +6284,7 @@ var init_supervisor = __esm({
6279
6284
  killTurn() {
6280
6285
  if (!this.isRunning) return;
6281
6286
  this._killRequested = true;
6282
- logger.debug("supervisor:kill_requested", { phase: this._phase });
6287
+ logger2.debug("supervisor:kill_requested", { phase: this._phase });
6283
6288
  }
6284
6289
  };
6285
6290
  }
@@ -8248,7 +8253,7 @@ var init_cloud_quota_message = __esm({
8248
8253
 
8249
8254
  // src/ui/chat.tsx
8250
8255
  import React4 from "react";
8251
- import { Box as Box5, Text as Text5, Static } from "ink";
8256
+ import { Box as Box5, Text as Text5 } from "ink";
8252
8257
  import Spinner2 from "ink-spinner";
8253
8258
  import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
8254
8259
  function toolSignature(name, args) {
@@ -8265,8 +8270,6 @@ var init_chat = __esm({
8265
8270
  init_cloud_quota_message();
8266
8271
  ChatView = React4.memo(function ChatView2({ events, showReasoning, verbose, intentTier }) {
8267
8272
  const theme = useTheme();
8268
- const finalized = [];
8269
- const active = [];
8270
8273
  const toolCounts = /* @__PURE__ */ new Map();
8271
8274
  for (const e of events) {
8272
8275
  if (e.kind === "tool") {
@@ -8278,31 +8281,14 @@ var init_chat = __esm({
8278
8281
  for (const [sig, count] of toolCounts) {
8279
8282
  if (count >= 3) repeatedSigs.add(sig);
8280
8283
  }
8281
- for (let i = 0; i < events.length; i++) {
8282
- const e = events[i];
8283
- const isStreaming = e.kind === "assistant" && e.streaming;
8284
- if (isStreaming) {
8285
- active.push(e);
8286
- } else {
8287
- const prev = events[i - 1];
8288
- const showSeparator = !!(e.kind === "user" && prev && (prev.kind === "assistant" || prev.kind === "tool"));
8289
- finalized.push({ id: e.key, evt: e, showSeparator });
8290
- }
8291
- }
8292
- return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
8293
- /* @__PURE__ */ jsx6(Static, { items: finalized, children: (item) => /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
8294
- item.showSeparator && /* @__PURE__ */ jsx6(Box5, { marginY: 1, children: /* @__PURE__ */ jsx6(Text5, { color: theme.info.color, children: "\u2500".repeat(40) }) }),
8295
- /* @__PURE__ */ jsx6(EventView, { evt: item.evt, showReasoning, verbose, repeatedSigs, intentTier })
8296
- ] }, item.id) }),
8297
- active.map((e, i) => {
8298
- const prevEvt = i > 0 ? active[i - 1] : finalized[finalized.length - 1]?.evt;
8299
- const showSeparator = e.kind === "user" && prevEvt && (prevEvt.kind === "assistant" || prevEvt.kind === "tool");
8300
- return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
8301
- showSeparator && /* @__PURE__ */ jsx6(Box5, { marginY: 1, children: /* @__PURE__ */ jsx6(Text5, { color: theme.info.color, children: "\u2500".repeat(40) }) }),
8302
- /* @__PURE__ */ jsx6(EventView, { evt: e, showReasoning, verbose, repeatedSigs, intentTier })
8303
- ] }, e.key);
8304
- })
8305
- ] });
8284
+ return /* @__PURE__ */ jsx6(Box5, { flexDirection: "column", children: events.map((e, i) => {
8285
+ const prev = events[i - 1];
8286
+ const showSeparator = !!(e.kind === "user" && prev && (prev.kind === "assistant" || prev.kind === "tool"));
8287
+ return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
8288
+ showSeparator && /* @__PURE__ */ jsx6(Box5, { marginY: 1, children: /* @__PURE__ */ jsx6(Text5, { color: theme.info.color, children: "\u2500".repeat(40) }) }),
8289
+ /* @__PURE__ */ jsx6(EventView, { evt: e, showReasoning, verbose, repeatedSigs, intentTier })
8290
+ ] }, e.key);
8291
+ }) });
8306
8292
  });
8307
8293
  EventView = React4.memo(function EventView2({
8308
8294
  evt,
@@ -16013,6 +15999,18 @@ function App({
16013
15999
  })
16014
16000
  );
16015
16001
  }, []);
16002
+ useEffect7(() => {
16003
+ const onSigint = () => {
16004
+ logger.info("sigint:fired", {
16005
+ hasHandler: sigintHandlerRef.current !== null
16006
+ });
16007
+ sigintHandlerRef.current?.();
16008
+ };
16009
+ process.on("SIGINT", onSigint);
16010
+ return () => {
16011
+ process.off("SIGINT", onSigint);
16012
+ };
16013
+ }, []);
16016
16014
  useEffect7(() => {
16017
16015
  let cancelled = false;
16018
16016
  loadAndMergeThemes().then(({ errors, wcagWarnings }) => {
@@ -16068,6 +16066,7 @@ ${wcagWarnings.join("\n")}` }
16068
16066
  const supervisorRef = useRef3(new TurnSupervisor());
16069
16067
  const isAbortingRef = useRef3(false);
16070
16068
  const lastEscapeAtRef = useRef3(0);
16069
+ const sigintHandlerRef = useRef3(null);
16071
16070
  const permResolveRef = useRef3(null);
16072
16071
  const limitResolveRef = useRef3(null);
16073
16072
  const pendingToolCallsRef = useRef3(/* @__PURE__ */ new Map());
@@ -16751,6 +16750,13 @@ ${wcagWarnings.join("\n")}` }
16751
16750
  );
16752
16751
  useInput8((inputChar, key) => {
16753
16752
  if (key.ctrl && inputChar === "c") {
16753
+ logger.info("input:ctrl+c", {
16754
+ busy: busyRef.current,
16755
+ hasActiveScope: activeScopeRef.current !== null,
16756
+ isAborting: isAbortingRef.current,
16757
+ hasPerm: permResolveRef.current !== null,
16758
+ hasLimit: limitResolveRef.current !== null
16759
+ });
16754
16760
  const hadPerm = permResolveRef.current !== null;
16755
16761
  const hadLimit = limitResolveRef.current !== null;
16756
16762
  if (hadPerm) {
@@ -16775,6 +16781,7 @@ ${wcagWarnings.join("\n")}` }
16775
16781
  setTasksStartTokens(0);
16776
16782
  tasksRef.current = [];
16777
16783
  } else if (!hadPerm && !hadLimit) {
16784
+ logger.info("input:ctrl+c:exiting");
16778
16785
  void lspManagerRef.current.stopAll().finally(() => exit());
16779
16786
  }
16780
16787
  return;
@@ -16819,6 +16826,42 @@ ${wcagWarnings.join("\n")}` }
16819
16826
  return;
16820
16827
  }
16821
16828
  });
16829
+ sigintHandlerRef.current = () => {
16830
+ logger.info("sigint:handler", {
16831
+ busy: busyRef.current,
16832
+ hasActiveScope: activeScopeRef.current !== null,
16833
+ isAborting: isAbortingRef.current,
16834
+ hasPerm: permResolveRef.current !== null,
16835
+ hasLimit: limitResolveRef.current !== null
16836
+ });
16837
+ const hadPerm = permResolveRef.current !== null;
16838
+ const hadLimit = limitResolveRef.current !== null;
16839
+ if (hadPerm) {
16840
+ permResolveRef.current("deny");
16841
+ permResolveRef.current = null;
16842
+ setPerm(null);
16843
+ }
16844
+ if (hadLimit) {
16845
+ limitResolveRef.current("stop");
16846
+ limitResolveRef.current = null;
16847
+ setLimitModal(null);
16848
+ }
16849
+ if (busyRef.current && activeScopeRef.current && !isAbortingRef.current) {
16850
+ isAbortingRef.current = true;
16851
+ supervisorRef.current.killTurn();
16852
+ activeScopeRef.current.abort("user_stopped");
16853
+ setQueue([]);
16854
+ setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "(interrupted)" }]);
16855
+ void saveSessionSafe();
16856
+ setTasks([]);
16857
+ setTasksStartedAt(null);
16858
+ setTasksStartTokens(0);
16859
+ tasksRef.current = [];
16860
+ } else if (!hadPerm && !hadLimit) {
16861
+ logger.info("sigint:handler:exiting");
16862
+ void lspManagerRef.current.stopAll().finally(() => exit());
16863
+ }
16864
+ };
16822
16865
  const flushAssistantUpdates = useCallback2(() => {
16823
16866
  flushTimeoutRef.current = null;
16824
16867
  const pending = pendingTextRef.current;
@@ -16962,6 +17005,7 @@ ${wcagWarnings.join("\n")}` }
16962
17005
  ]);
16963
17006
  }
16964
17007
  } finally {
17008
+ logger.info("runCompact:finally");
16965
17009
  setBusy(false);
16966
17010
  busyRef.current = false;
16967
17011
  setTurnStartedAt(null);
@@ -16969,6 +17013,7 @@ ${wcagWarnings.join("\n")}` }
16969
17013
  setCurrentToolName(null);
16970
17014
  setLastActivityAt(null);
16971
17015
  activeScopeRef.current = null;
17016
+ isAbortingRef.current = false;
16972
17017
  permResolveRef.current = null;
16973
17018
  limitResolveRef.current = null;
16974
17019
  pendingToolCallsRef.current.clear();
@@ -17227,6 +17272,7 @@ ${wcagWarnings.join("\n")}` }
17227
17272
  ]);
17228
17273
  }
17229
17274
  } finally {
17275
+ logger.info("runInit:finally");
17230
17276
  setCodeMode(false);
17231
17277
  const asstId = activeAsstIdRef.current;
17232
17278
  if (asstId !== null) updateAssistant(asstId, () => ({ streaming: false }));
@@ -17238,6 +17284,7 @@ ${wcagWarnings.join("\n")}` }
17238
17284
  setLastActivityAt(null);
17239
17285
  activeAsstIdRef.current = null;
17240
17286
  activeScopeRef.current = null;
17287
+ isAbortingRef.current = false;
17241
17288
  permResolveRef.current = null;
17242
17289
  limitResolveRef.current = null;
17243
17290
  pendingToolCallsRef.current.clear();
@@ -18578,6 +18625,7 @@ ${lines.join("\n")}` }]);
18578
18625
  }
18579
18626
  };
18580
18627
  const cleanupTurn = () => {
18628
+ logger.info("cleanupTurn");
18581
18629
  setCodeMode(false);
18582
18630
  const asstId = activeAsstIdRef.current;
18583
18631
  if (asstId !== null) updateAssistant(asstId, () => ({ streaming: false }));