kimiflare 0.87.0 → 0.88.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/README.md CHANGED
@@ -8,11 +8,11 @@
8
8
  <a href="https://github.com/sinameraji/kimiflare/blob/main/LICENSE"><img src="https://img.shields.io/github/license/sinameraji/kimiflare?style=flat-square&color=2ea44f" alt="license"></a>
9
9
  <img src="https://img.shields.io/badge/node-%3E%3D20-339933?style=flat-square&logo=nodedotjs&logoColor=white" alt="Node.js >= 20">
10
10
  <img src="https://img.shields.io/badge/typescript-5.7-3178c6?style=flat-square&logo=typescript&logoColor=white" alt="TypeScript">
11
- <a href="https://developers.cloudflare.com/workers-ai/models/kimi-k2"><img src="https://img.shields.io/badge/powered%20by-Kimi%20K2.6-f59e0b?style=flat-square" alt="Powered by Kimi K2.6"></a>
11
+ <a href="https://developers.cloudflare.com/workers-ai/models/kimi-k2"><img src="https://img.shields.io/badge/powered%20by-Kimi%20K2.7-f59e0b?style=flat-square" alt="Powered by Kimi K2.7"></a>
12
12
  </p>
13
13
 
14
14
  <p align="center">
15
- <strong>A terminal coding agent powered by <a href="https://developers.cloudflare.com/workers-ai/models/kimi-k2">Kimi K2.6</a> on <a href="https://developers.cloudflare.com/workers-ai/">Cloudflare Workers AI</a> — with optional routing through your own <a href="https://developers.cloudflare.com/ai-gateway/">AI Gateway</a> for first-class observability, caching, and authoritative cost.</strong><br>
15
+ <strong>A terminal coding agent powered by <a href="https://developers.cloudflare.com/workers-ai/models/kimi-k2">Kimi K2.7</a> on <a href="https://developers.cloudflare.com/workers-ai/">Cloudflare Workers AI</a> — with optional routing through your own <a href="https://developers.cloudflare.com/ai-gateway/">AI Gateway</a> for first-class observability, caching, and authoritative cost.</strong><br>
16
16
  All on your Cloudflare account.
17
17
  </p>
18
18
 
@@ -93,11 +93,11 @@ Once configured, `/cost` shows the Gateway-confirmed totals, cache hit ratio, pe
93
93
 
94
94
  ### Model
95
95
 
96
- KimiFlare runs on **Kimi K2.6** via Cloudflare Workers AI — no API key needed beyond your Cloudflare token:
96
+ KimiFlare runs on **Kimi K2.7** via Cloudflare Workers AI — no API key needed beyond your Cloudflare token:
97
97
 
98
- - `@cf/moonshotai/kimi-k2.6` — 262k context, reasoning, tools
98
+ - `@cf/moonshotai/kimi-k2.7-code` — 262k context, reasoning, tools, vision
99
99
 
100
- `@cf/moonshotai/kimi-k2.5` is also available for older sessions.
100
+ `@cf/moonshotai/kimi-k2.6` and `@cf/moonshotai/kimi-k2.5` are also available.
101
101
 
102
102
  ### One-shot mode
103
103
 
@@ -120,7 +120,7 @@ const { session } = await createAgentSession({
120
120
  accountId: process.env.CLOUDFLARE_ACCOUNT_ID,
121
121
  apiToken: process.env.CLOUDFLARE_API_TOKEN,
122
122
  aiGatewayId: process.env.CLOUDFLARE_AI_GATEWAY_ID,
123
- model: "@cf/moonshotai/kimi-k2.6",
123
+ model: "@cf/moonshotai/kimi-k2.7-code",
124
124
  },
125
125
  });
126
126
 
package/dist/index.js CHANGED
@@ -295,7 +295,7 @@ var init_config = __esm({
295
295
  "src/config.ts"() {
296
296
  "use strict";
297
297
  EFFORTS = ["low", "medium", "high"];
298
- DEFAULT_MODEL = "@cf/moonshotai/kimi-k2.6";
298
+ DEFAULT_MODEL = "@cf/moonshotai/kimi-k2.7-code";
299
299
  DEFAULT_REASONING_EFFORT = "medium";
300
300
  }
301
301
  });
@@ -709,7 +709,7 @@ async function* deployForTui() {
709
709
  throw err;
710
710
  }
711
711
  const nextCfg = {
712
- ...cfg ?? { accountId: "", apiToken: "", model: "@cf/moonshotai/kimi-k2.6" },
712
+ ...cfg ?? { accountId: "", apiToken: "", model: "@cf/moonshotai/kimi-k2.7-code" },
713
713
  remoteWorkerUrl: workerUrl,
714
714
  remoteAuthSecret: authSecret
715
715
  };
@@ -1413,6 +1413,15 @@ var init_registry = __esm({
1413
1413
  ]);
1414
1414
  SEED = [
1415
1415
  // ── Kimi models (Cloudflare Workers AI, native to kimiflare) ──────────────
1416
+ {
1417
+ id: "@cf/moonshotai/kimi-k2.7-code",
1418
+ provider: "workers-ai",
1419
+ contextWindow: 262144,
1420
+ maxOutputTokens: 16384,
1421
+ pricing: { inputPerMtok: 0.95, cachedInputPerMtok: 0.19, outputPerMtok: 4 },
1422
+ supports: { tools: true, reasoning: true, streaming: true, vision: true },
1423
+ billingMode: "unified"
1424
+ },
1416
1425
  {
1417
1426
  id: "@cf/moonshotai/kimi-k2.6",
1418
1427
  provider: "workers-ai",
@@ -1539,7 +1548,7 @@ async function* runKimi(opts2) {
1539
1548
  `Your stored ${modelProvider} key is likely invalid or expired. Fix:`,
1540
1549
  ` /keys set ${modelProvider} <new-key> replace the stored key`,
1541
1550
  ` /keys clear ${modelProvider} remove it and reopen the picker to paste fresh`,
1542
- ` /model @cf/moonshotai/kimi-k2.6 switch back to Workers AI (no key needed)`
1551
+ ` /model @cf/moonshotai/kimi-k2.7-code switch back to Workers AI (no key needed)`
1543
1552
  ].join("\n") : msg;
1544
1553
  const apiErr = new KimiApiError(`kimiflare: ${wrappedMsg}`, err?.code, res.status);
1545
1554
  if (isRetryable(apiErr, attempt)) {
@@ -1580,7 +1589,7 @@ function missingKeyMessage(model, provider, unifiedAvailable) {
1580
1589
  if (unifiedAvailable) {
1581
1590
  lines.push(` 2. Enable Cloudflare Unified Billing for this gateway in the CF dashboard, then run: /keys unified on`);
1582
1591
  }
1583
- lines.push(` ${unifiedAvailable ? "3" : "2"}. Switch back to a Workers AI model: /model @cf/moonshotai/kimi-k2.6`);
1592
+ lines.push(` ${unifiedAvailable ? "3" : "2"}. Switch back to a Workers AI model: /model @cf/moonshotai/kimi-k2.7-code`);
1584
1593
  return lines.join("\n");
1585
1594
  }
1586
1595
  function gatewayHeadersFor(opts2) {
@@ -7198,7 +7207,7 @@ var init_spawn_worker = __esm({
7198
7207
  },
7199
7208
  model: {
7200
7209
  type: "string",
7201
- description: "Model to use for the worker. Defaults to @cf/moonshotai/kimi-k2.6."
7210
+ description: "Model to use for the worker. Defaults to @cf/moonshotai/kimi-k2.7-code."
7202
7211
  },
7203
7212
  branchName: {
7204
7213
  type: "string",
@@ -7243,7 +7252,7 @@ var init_spawn_worker = __esm({
7243
7252
  budget: { maxCostUsd: budgetUsd },
7244
7253
  outputFormat: args.outputFormat ?? "structured",
7245
7254
  tools: args.tools ?? (args.mode === "plan" ? "read-only" : "all"),
7246
- model: args.model ?? "@cf/moonshotai/kimi-k2.6",
7255
+ model: args.model ?? "@cf/moonshotai/kimi-k2.7-code",
7247
7256
  ...args.mode === "execute" ? {
7248
7257
  branchName: args.branchName,
7249
7258
  baseBranch: args.baseBranch ?? "main",
@@ -9628,7 +9637,7 @@ async function* authGitHubForTui() {
9628
9637
  const cfg = await loadConfig() ?? {
9629
9638
  accountId: "",
9630
9639
  apiToken: "",
9631
- model: "@cf/moonshotai/kimi-k2.6"
9640
+ model: "@cf/moonshotai/kimi-k2.7-code"
9632
9641
  };
9633
9642
  await saveConfig({
9634
9643
  ...cfg,
@@ -10101,7 +10110,7 @@ function setupRoutes(config2) {
10101
10110
  if (pathname === "/prompt" && method === "POST") {
10102
10111
  const body = await readBody(req);
10103
10112
  const prompt = typeof body.prompt === "string" ? body.prompt : "";
10104
- const model = typeof body.model === "string" ? body.model : config2.model ?? "@cf/moonshotai/kimi-k2.6";
10113
+ const model = typeof body.model === "string" ? body.model : config2.model ?? "@cf/moonshotai/kimi-k2.7-code";
10105
10114
  const cwd = typeof body.cwd === "string" ? body.cwd : process.cwd();
10106
10115
  const title = typeof body.title === "string" ? body.title : void 0;
10107
10116
  const files = Array.isArray(body.files) ? body.files.filter((f) => typeof f === "string") : [];
@@ -11105,7 +11114,7 @@ Return a JSON array of strings. Example:
11105
11114
  return {
11106
11115
  accountId: this.opts.accountId,
11107
11116
  apiToken: this.opts.apiToken,
11108
- model: this.opts.model ?? "@cf/moonshotai/kimi-k2.6",
11117
+ model: this.opts.model ?? "@cf/moonshotai/kimi-k2.7-code",
11109
11118
  gateway: this.opts.gateway
11110
11119
  };
11111
11120
  }
@@ -14034,7 +14043,7 @@ ${w.context ?? ""}` : w.context ?? "",
14034
14043
  budget: { maxCostUsd },
14035
14044
  outputFormat: "structured",
14036
14045
  tools: w.mode === "plan" ? "read-only" : "all",
14037
- model: w.model ?? "@cf/moonshotai/kimi-k2.6",
14046
+ model: w.model ?? "@cf/moonshotai/kimi-k2.7-code",
14038
14047
  // Sandbox-driven worker needs the repo to clone:
14039
14048
  githubToken: repo.token,
14040
14049
  owner: repo.owner,
@@ -15997,7 +16006,7 @@ var init_builtins = __esm({
15997
16006
  { name: "mode", argHint: "edit|plan|auto|multi-agent-experimental", description: "Switch agent mode", source: "builtin" },
15998
16007
  { name: "multi-agent", argHint: "[enable|disable|status|setup]", description: "Configure multi-agent (endpoint, auto-implement, set up)", source: "builtin" },
15999
16008
  { name: "theme", argHint: "[<name>]", description: "Switch color theme", source: "builtin" },
16000
- { name: "ui", argHint: "ink|camouflage", description: "Switch UI engine (takes effect on next launch)", source: "builtin" },
16009
+ { name: "ui", argHint: "ink", description: "Switch UI engine to React Ink (takes effect on next launch). Camouflage is opt-in via --ui camouflage.", source: "builtin" },
16001
16010
  { name: "plan", description: "Switch to plan mode", source: "builtin" },
16002
16011
  { name: "auto", description: "Switch to auto mode", source: "builtin" },
16003
16012
  { name: "edit", description: "Switch to edit mode", source: "builtin" },
@@ -20647,7 +20656,7 @@ Executor opened PR: ${prUrl}` : plan });
20647
20656
  {
20648
20657
  value: "camouflage",
20649
20658
  label: "Camouflage",
20650
- description: "experimental Rust TUI \u2014 bail with `kimiflare --ui ink`"
20659
+ description: "experimental \u2014 opt in with `kimiflare --ui camouflage`"
20651
20660
  }
20652
20661
  ],
20653
20662
  default: current,
@@ -20667,6 +20676,14 @@ Executor opened PR: ${prUrl}` : plan });
20667
20676
  });
20668
20677
  return true;
20669
20678
  }
20679
+ if (nextUi === "camouflage") {
20680
+ cam.send("ShowToast", {
20681
+ text: "Camouflage is experimental and must be opted into explicitly. Launch with `kimiflare --ui camouflage` or set `KIMIFLARE_UI=camouflage`.",
20682
+ kind: "error",
20683
+ ttl_ms: 12e3
20684
+ });
20685
+ return true;
20686
+ }
20670
20687
  try {
20671
20688
  const existing = await loadConfig() ?? null;
20672
20689
  if (existing) {
@@ -20681,7 +20698,7 @@ Executor opened PR: ${prUrl}` : plan });
20681
20698
  return true;
20682
20699
  }
20683
20700
  cam.send("ShowToast", {
20684
- text: `UI engine set to "${nextUi}". RESTART kimiflare for it to take effect.` + (nextUi === "ink" ? " (or `unset KIMIFLARE_UI` if you previously exported it)" : " (Camouflage is EXPERIMENTAL \u2014 `kimiflare --ui ink` to bail.)"),
20701
+ text: `UI engine set to "${nextUi}". RESTART kimiflare for it to take effect. (or \`unset KIMIFLARE_UI\` if you previously exported it)`,
20685
20702
  kind: "error",
20686
20703
  ttl_ms: 12e3
20687
20704
  });
@@ -28589,7 +28606,7 @@ function UiPicker({ current, onPick }) {
28589
28606
  {
28590
28607
  label: "Camouflage",
28591
28608
  value: "camouflage",
28592
- description: "experimental Rust TUI \u2014 bail with `kimiflare --ui ink`"
28609
+ description: "experimental \u2014 opt in with `kimiflare --ui camouflage`"
28593
28610
  },
28594
28611
  { label: "< Back", value: "__back__", description: "" }
28595
28612
  ];
@@ -31397,7 +31414,7 @@ function executeFreshStart(ctx, planText, overrideMode) {
31397
31414
  rebuildSystemPromptForMode(
31398
31415
  ctx.messagesRef.current,
31399
31416
  ctx.cacheStableRef.current,
31400
- ctx.cfg?.model ?? "@cf/moonshotai/kimi-k2.6",
31417
+ ctx.cfg?.model ?? "@cf/moonshotai/kimi-k2.7-code",
31401
31418
  overrideMode ?? ctx.mode,
31402
31419
  [...ALL_TOOLS, ...ctx.mcpToolsRef.current, ...ctx.lspToolsRef.current]
31403
31420
  );
@@ -31967,6 +31984,17 @@ var init_slash_commands = __esm({
31967
31984
  return true;
31968
31985
  }
31969
31986
  const next = arg;
31987
+ if (next === "camouflage") {
31988
+ setEvents((e) => [
31989
+ ...e,
31990
+ {
31991
+ kind: "error",
31992
+ key: mkKey2(),
31993
+ text: "Camouflage is experimental and must be opted into explicitly. Launch with `kimiflare --ui camouflage` or set `KIMIFLARE_UI=camouflage`."
31994
+ }
31995
+ ]);
31996
+ return true;
31997
+ }
31970
31998
  ctx.setCfg((prev) => {
31971
31999
  if (!prev) return prev;
31972
32000
  const updated = { ...prev, uiEngine: next };
@@ -31979,7 +32007,7 @@ var init_slash_commands = __esm({
31979
32007
  {
31980
32008
  kind: "error",
31981
32009
  key: mkKey2(),
31982
- text: `UI engine set to "${next}". RESTART kimiflare for it to take effect.` + (next === "camouflage" ? " (Camouflage is EXPERIMENTAL \u2014 `kimiflare --ui ink` or `unset KIMIFLARE_UI` to bail.)" : "")
32010
+ text: `UI engine set to "${next}". RESTART kimiflare for it to take effect.`
31983
32011
  }
31984
32012
  ]);
31985
32013
  return true;
@@ -34630,6 +34658,17 @@ ${wcagWarnings.join("\n")}` }
34630
34658
  (picked) => {
34631
34659
  setShowUiPicker(false);
34632
34660
  if (!picked) return;
34661
+ if (picked === "camouflage") {
34662
+ setEvents((e) => [
34663
+ ...e,
34664
+ {
34665
+ kind: "error",
34666
+ key: mkKey(),
34667
+ text: "Camouflage is experimental and must be opted into explicitly. Launch with `kimiflare --ui camouflage` or set `KIMIFLARE_UI=camouflage`."
34668
+ }
34669
+ ]);
34670
+ return;
34671
+ }
34633
34672
  setCfg((c) => {
34634
34673
  if (!c) return c;
34635
34674
  const updated = { ...c, uiEngine: picked };
@@ -34642,7 +34681,7 @@ ${wcagWarnings.join("\n")}` }
34642
34681
  {
34643
34682
  kind: "error",
34644
34683
  key: mkKey(),
34645
- text: `UI engine set to "${picked}". RESTART kimiflare for it to take effect.` + (picked === "camouflage" ? " (Camouflage is EXPERIMENTAL \u2014 `kimiflare --ui ink` or `unset KIMIFLARE_UI` to bail.)" : "")
34684
+ text: `UI engine set to "${picked}". RESTART kimiflare for it to take effect.`
34646
34685
  }
34647
34686
  ]);
34648
34687
  },
@@ -36357,7 +36396,7 @@ function buildTextLines(version) {
36357
36396
  ` ${bold}${accent}Kimiflare${reset}`,
36358
36397
  "",
36359
36398
  ` ${dim}Terminal coding agent${reset}`,
36360
- ` ${dim}powered by Kimi-K2.6${reset}`,
36399
+ ` ${dim}powered by Kimi-K2.7${reset}`,
36361
36400
  "",
36362
36401
  ` ${dim}v${version}${reset}`,
36363
36402
  "",
@@ -36720,7 +36759,7 @@ async function runPrintMode(opts2) {
36720
36759
 
36721
36760
  // src/index.tsx
36722
36761
  var program = new Command2();
36723
- program.name("kimiflare").description("Terminal coding agent powered by Kimi-K2.6 on Cloudflare Workers AI.").version(getAppVersion()).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)").option("--thinking", "alias for --reasoning").option("--continue-on-limit", "reset tool-call counter and continue when the 200-call limit is hit (print mode only)").option("--max-input-tokens <n>", "cumulative prompt token budget; exits 42 when exhausted (print mode only)", (v) => parseInt(v, 10)).option("--emit-events", "emit Camouflage NDJSON events to stdout; requires -p (for initial prompt)").option("--multi-turn", "with --emit-events: keep reading stdin for UserInputSubmitted follow-ups after the initial turn").option("--ui <name>", "render UI with the given engine: `ink` (default, stable) or `camouflage` (experimental Rust TUI). Can also be set via the KIMIFLARE_UI environment variable.").option("--camouflage-bin <path>", "with --ui camouflage: path to the camouflage-tui binary (defaults to PATH lookup)").option("--mode <mode>", "run mode: interactive (default), print, rpc").option("-c, --continue", "continue the most recent session in the current working directory (print mode only)").option("-S, --session <id>", "resume a specific session by id (print mode only)").option("-f, --file <path>", "attach file(s) to the prompt; repeatable, supports globs (print mode only)", (v, prev) => (prev ?? []).concat(v)).option("--format <mode>", "output format for print mode: text (default), json, stream-json").option("--dir <path>", "run in the specified directory instead of the current one (print mode only)").option("--title <title>", "override the auto-generated session title (print mode only)").option("--attach <url>", "attach to a running kimiflare serve instance (print mode only)");
36762
+ program.name("kimiflare").description("Terminal coding agent powered by Kimi-K2.7 on Cloudflare Workers AI.").version(getAppVersion()).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.7-code)").option("--dangerously-allow-all", "auto-approve every permission prompt (print mode only)").option("--reasoning", "include reasoning in stdout (print mode only)").option("--thinking", "alias for --reasoning").option("--continue-on-limit", "reset tool-call counter and continue when the 200-call limit is hit (print mode only)").option("--max-input-tokens <n>", "cumulative prompt token budget; exits 42 when exhausted (print mode only)", (v) => parseInt(v, 10)).option("--emit-events", "emit Camouflage NDJSON events to stdout; requires -p (for initial prompt)").option("--multi-turn", "with --emit-events: keep reading stdin for UserInputSubmitted follow-ups after the initial turn").option("--ui <name>", "render UI with the given engine: `ink` (default, stable) or `camouflage` (experimental Rust TUI). Can also be set via the KIMIFLARE_UI environment variable.").option("--camouflage-bin <path>", "with --ui camouflage: path to the camouflage-tui binary (defaults to PATH lookup)").option("--mode <mode>", "run mode: interactive (default), print, rpc").option("-c, --continue", "continue the most recent session in the current working directory (print mode only)").option("-S, --session <id>", "resume a specific session by id (print mode only)").option("-f, --file <path>", "attach file(s) to the prompt; repeatable, supports globs (print mode only)", (v, prev) => (prev ?? []).concat(v)).option("--format <mode>", "output format for print mode: text (default), json, stream-json").option("--dir <path>", "run in the specified directory instead of the current one (print mode only)").option("--title <title>", "override the auto-generated session title (print mode only)").option("--attach <url>", "attach to a running kimiflare serve instance (print mode only)");
36724
36763
  program.command("cost").description("Show cost attribution by task type (requires costAttribution enabled)").option("-w, --week", "last 7 days (default)").option("-m, --month", "last 30 days").option("-d, --day", "today only").option("-s, --session <id>", "single session detail").option("-c, --category <name>", "filter by category").option("--json", "machine-readable output").option("--reclassify", "re-run classification on all sessions").option("--local-only", "skip Cloudflare reconciliation").action(async (cmdOpts) => {
36725
36764
  const cfg = await loadConfig();
36726
36765
  const enabled = cfg?.costAttribution ?? false;
@@ -36845,7 +36884,7 @@ async function main() {
36845
36884
  if (opts.print !== void 0) {
36846
36885
  if (!cfg) {
36847
36886
  console.error(
36848
- 'kimiflare: missing credentials.\nSet CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_API_TOKEN, or write them to\n ~/.config/kimiflare/config.json (chmod 600)\n { "accountId": "...", "apiToken": "...", "model": "@cf/moonshotai/kimi-k2.6" }'
36887
+ 'kimiflare: missing credentials.\nSet CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_API_TOKEN, or write them to\n ~/.config/kimiflare/config.json (chmod 600)\n { "accountId": "...", "apiToken": "...", "model": "@cf/moonshotai/kimi-k2.7-code" }'
36849
36888
  );
36850
36889
  process.exit(2);
36851
36890
  }
@@ -36895,7 +36934,8 @@ async function main() {
36895
36934
  process.exit(2);
36896
36935
  }
36897
36936
  const logoText = renderLogo(getAppVersion());
36898
- const uiEngine = (opts.ui ?? process.env.KIMIFLARE_UI ?? cfg?.uiEngine ?? "ink").toLowerCase();
36937
+ const explicitUi = opts.ui ?? process.env.KIMIFLARE_UI;
36938
+ const uiEngine = (explicitUi ?? (cfg?.uiEngine === "ink" ? "ink" : void 0) ?? "ink").toLowerCase();
36899
36939
  if (uiEngine !== "camouflage") {
36900
36940
  console.log(logoText);
36901
36941
  }