kimiflare 0.9.1 → 0.9.2

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
@@ -172,7 +172,7 @@ function isRetryable(err, attempt) {
172
172
  async function* runKimi(opts2) {
173
173
  const url = `https://api.cloudflare.com/client/v4/accounts/${opts2.accountId}/ai/run/${opts2.model}`;
174
174
  const body = {
175
- messages: opts2.messages,
175
+ messages: sanitizeMessagesForApi(opts2.messages),
176
176
  ...opts2.tools && opts2.tools.length ? { tools: opts2.tools, tool_choice: "auto", parallel_tool_calls: true } : {},
177
177
  stream: true,
178
178
  temperature: opts2.temperature ?? 0.2,
@@ -294,6 +294,30 @@ async function* parseStream(body, signal) {
294
294
  }
295
295
  yield { type: "done", finishReason, usage: lastUsage };
296
296
  }
297
+ function sanitizeMessagesForApi(messages) {
298
+ return messages.map((m) => {
299
+ if (!m.tool_calls || m.tool_calls.length === 0) return m;
300
+ return {
301
+ ...m,
302
+ tool_calls: m.tool_calls.map((tc) => ({
303
+ ...tc,
304
+ function: {
305
+ name: tc.function.name,
306
+ arguments: validateJsonArguments(tc.function.arguments)
307
+ }
308
+ }))
309
+ };
310
+ });
311
+ }
312
+ function validateJsonArguments(raw) {
313
+ if (!raw || !raw.trim()) return "{}";
314
+ try {
315
+ JSON.parse(raw);
316
+ return raw;
317
+ } catch {
318
+ return "{}";
319
+ }
320
+ }
297
321
  function extractCloudflareError(parsed) {
298
322
  if (!parsed || typeof parsed !== "object") return null;
299
323
  const cf = parsed;
@@ -387,10 +411,11 @@ async function runAgentTurn(opts2) {
387
411
  opts2.callbacks.onToolCallArgs?.(ev.index, ev.argsDelta);
388
412
  break;
389
413
  case "tool_call_complete": {
414
+ const safeArgs = validateToolArguments(ev.arguments);
390
415
  const call = {
391
416
  id: ev.id,
392
417
  type: "function",
393
- function: { name: ev.name, arguments: ev.arguments }
418
+ function: { name: ev.name, arguments: safeArgs }
394
419
  };
395
420
  toolCalls.push(call);
396
421
  opts2.callbacks.onToolCallFinalized?.(call);
@@ -438,6 +463,15 @@ async function runAgentTurn(opts2) {
438
463
  }
439
464
  throw new Error(`kimiflare: tool iteration limit reached (${opts2.maxToolIterations ?? 50})`);
440
465
  }
466
+ function validateToolArguments(raw) {
467
+ if (!raw || !raw.trim()) return "{}";
468
+ try {
469
+ JSON.parse(raw);
470
+ return raw;
471
+ } catch {
472
+ return "{}";
473
+ }
474
+ }
441
475
  var init_loop = __esm({
442
476
  "src/agent/loop.ts"() {
443
477
  "use strict";
@@ -4092,10 +4126,23 @@ use: /thinking low | medium | high`
4092
4126
  if (e.name === "AbortError") {
4093
4127
  setEvents((es) => [...es, { kind: "info", key: mkKey(), text: "(aborted)" }]);
4094
4128
  } else {
4095
- setEvents((es) => [
4096
- ...es,
4097
- { kind: "error", key: mkKey(), text: e.message ?? String(e) }
4098
- ]);
4129
+ const isInvalidJson400 = e instanceof KimiApiError && e.httpStatus === 400 && e.message.includes("invalid escaped character");
4130
+ if (isInvalidJson400) {
4131
+ messagesRef.current.pop();
4132
+ setEvents((es) => [
4133
+ ...es,
4134
+ {
4135
+ kind: "error",
4136
+ key: mkKey(),
4137
+ text: "API rejected request (invalid JSON in conversation history). Retrying may work; run /clear to reset if it persists."
4138
+ }
4139
+ ]);
4140
+ } else {
4141
+ setEvents((es) => [
4142
+ ...es,
4143
+ { kind: "error", key: mkKey(), text: e.message ?? String(e) }
4144
+ ]);
4145
+ }
4099
4146
  }
4100
4147
  } finally {
4101
4148
  setBusy(false);
@@ -4273,6 +4320,7 @@ var init_app = __esm({
4273
4320
  init_compact();
4274
4321
  init_executor();
4275
4322
  init_messages();
4323
+ init_errors();
4276
4324
  init_chat();
4277
4325
  init_status();
4278
4326
  init_permission();