kimiflare 0.96.0 → 0.97.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/README.md CHANGED
@@ -17,7 +17,10 @@
17
17
  </p>
18
18
 
19
19
  <p align="center">
20
- <img src="docs/screenshot.png" alt="kimiflare TUI" width="900">
20
+ <img src="docs/demos/onboarding.gif" alt="kimiflare TUI demo" width="900">
21
+ </p>
22
+ <p align="center">
23
+ <a href="https://kimiflare.com">Watch full demos →</a>
21
24
  </p>
22
25
 
23
26
  ## How it works
package/dist/index.js CHANGED
@@ -85,12 +85,14 @@ function readProviderKeysEnv() {
85
85
  const anthropic = process.env.ANTHROPIC_API_KEY || process.env.KIMIFLARE_ANTHROPIC_KEY;
86
86
  const openai = process.env.OPENAI_API_KEY || process.env.KIMIFLARE_OPENAI_KEY;
87
87
  const google = process.env.GOOGLE_API_KEY || process.env.KIMIFLARE_GOOGLE_KEY;
88
+ const moonshotai = process.env.MOONSHOT_API_KEY || process.env.KIMIFLARE_MOONSHOT_KEY;
88
89
  const generic = process.env.KIMIFLARE_OPENAI_COMPAT_KEY;
89
- if (!anthropic && !openai && !google && !generic) return void 0;
90
+ if (!anthropic && !openai && !google && !moonshotai && !generic) return void 0;
90
91
  const out = {};
91
92
  if (anthropic) out.anthropic = anthropic;
92
93
  if (openai) out.openai = openai;
93
94
  if (google) out.google = google;
95
+ if (moonshotai) out.moonshotai = moonshotai;
94
96
  if (generic) out["openai-compatible"] = generic;
95
97
  return out;
96
98
  }
@@ -395,7 +397,7 @@ var init_config = __esm({
395
397
  "use strict";
396
398
  EFFORTS = ["low", "medium", "high"];
397
399
  DEFAULT_MODEL = "@cf/moonshotai/kimi-k2.6";
398
- DEFAULT_CLOUD_MODEL = "@cf/moonshotai/kimi-k2.7-code";
400
+ DEFAULT_CLOUD_MODEL = "moonshotai/kimi-k3";
399
401
  DEFAULT_REASONING_EFFORT = "medium";
400
402
  }
401
403
  });
@@ -2039,6 +2041,7 @@ function inferProvider(id) {
2039
2041
  if (id.startsWith("anthropic/")) return "anthropic";
2040
2042
  if (id.startsWith("openai/")) return "openai";
2041
2043
  if (id.startsWith("google-ai-studio/") || id.startsWith("google/")) return "google";
2044
+ if (id.startsWith("moonshotai/")) return "moonshotai";
2042
2045
  return "openai-compatible";
2043
2046
  }
2044
2047
  function listModels() {
@@ -2068,6 +2071,19 @@ var init_registry = __esm({
2068
2071
  supports: { tools: true, reasoning: true, streaming: true, vision: true },
2069
2072
  billingMode: "unified"
2070
2073
  },
2074
+ // ── Kimi K3 (AI Gateway / Moonshot AI, provider-native routing) ──────────
2075
+ {
2076
+ id: "moonshotai/kimi-k3",
2077
+ provider: "moonshotai",
2078
+ contextWindow: 1e6,
2079
+ maxOutputTokens: 32768,
2080
+ // Placeholder pricing — verify against Cloudflare AI Gateway docs once rendered.
2081
+ pricing: { inputPerMtok: 3, outputPerMtok: 15 },
2082
+ supports: { tools: true, reasoning: true, streaming: true, vision: true },
2083
+ // Cloudflare Unified Billing does not currently cover Moonshot AI.
2084
+ // Use a Moonshot API key (BYOK) via cf-aig-authorization.
2085
+ billingMode: "byok"
2086
+ },
2071
2087
  {
2072
2088
  id: "@cf/moonshotai/kimi-k2.6",
2073
2089
  provider: "workers-ai",
@@ -2387,7 +2403,7 @@ function buildKimiRequestTarget(opts2) {
2387
2403
  }
2388
2404
  const headers = gatewayHeadersFor(opts2);
2389
2405
  if (entry.provider !== "workers-ai") {
2390
- const useUnified = !!opts2.unifiedBilling;
2406
+ const useUnified = !!opts2.unifiedBilling && isUnifiedEligible(entry);
2391
2407
  const alias = opts2.providerKeyAliases?.[entry.provider];
2392
2408
  const providerKey = opts2.providerKeys?.[entry.provider];
2393
2409
  if (useUnified) {
@@ -2583,6 +2599,7 @@ var init_client = __esm({
2583
2599
  anthropic: { name: "Anthropic", where: "https://console.anthropic.com/settings/keys" },
2584
2600
  openai: { name: "OpenAI", where: "https://platform.openai.com/api-keys" },
2585
2601
  google: { name: "Google AI Studio", where: "https://aistudio.google.com/app/apikey" },
2602
+ moonshotai: { name: "Moonshot AI", where: "https://platform.moonshot.cn/" },
2586
2603
  "openai-compatible": { name: "your provider", where: "your provider's dashboard" }
2587
2604
  };
2588
2605
  DEFAULT_IDLE_TIMEOUT_MS = 6e4;
@@ -7974,7 +7991,8 @@ var init_plan_options = __esm({
7974
7991
  "Present a list of plan options to the user and let them pick one.",
7975
7992
  "Use this when you have multiple viable approaches and want the user to choose",
7976
7993
  "which plan to pursue. Each option needs a short label and the full plan text.",
7977
- "After the user selects an option, the session resets and starts fresh with the chosen plan."
7994
+ "After the user selects an option, they choose an execution mode and the",
7995
+ "session starts fresh seeded with the chosen plan."
7978
7996
  ].join(" "),
7979
7997
  parameters: {
7980
7998
  type: "object",
@@ -19466,12 +19484,12 @@ function buildRowsFlat(opts2) {
19466
19484
  }
19467
19485
  return rows;
19468
19486
  }
19469
- function ModelPicker({ current, onPick }) {
19487
+ function ModelPicker({ current, onPick, models }) {
19470
19488
  const theme = useTheme();
19471
19489
  const [query, setQuery] = useState11("");
19472
19490
  const [page, setPage] = useState11(0);
19473
19491
  const [selectedIndex, setSelectedIndex] = useState11(0);
19474
- const allModels = useMemo2(() => listModels(), []);
19492
+ const allModels = useMemo2(() => models ?? listModels(), [models]);
19475
19493
  const filtered = useMemo2(() => {
19476
19494
  if (!query.trim()) return allModels;
19477
19495
  return fuzzyFilter(allModels, query, (m) => `${m.id} ${m.provider}`);
@@ -19607,6 +19625,7 @@ var init_model_picker = __esm({
19607
19625
  init_fuzzy();
19608
19626
  PROVIDER_ORDER = [
19609
19627
  "workers-ai",
19628
+ "moonshotai",
19610
19629
  "anthropic",
19611
19630
  "openai",
19612
19631
  "google",
@@ -19614,6 +19633,7 @@ var init_model_picker = __esm({
19614
19633
  ];
19615
19634
  PROVIDER_LABEL = {
19616
19635
  "workers-ai": "Cloudflare Workers AI",
19636
+ moonshotai: "Moonshot AI",
19617
19637
  anthropic: "Anthropic",
19618
19638
  openai: "OpenAI",
19619
19639
  google: "Google",
@@ -19670,6 +19690,7 @@ var init_billing_chooser = __esm({
19670
19690
  init_theme_context();
19671
19691
  PROVIDER_NAME = {
19672
19692
  "workers-ai": "Cloudflare Workers AI",
19693
+ moonshotai: "Moonshot AI",
19673
19694
  anthropic: "Anthropic",
19674
19695
  openai: "OpenAI",
19675
19696
  google: "Google AI Studio",
@@ -19991,7 +20012,7 @@ function UnifiedBillingStatus({
19991
20012
  /* @__PURE__ */ jsx19(Text18, { bold: true, children: `"I've enabled it \u2014 try again"` }),
19992
20013
  "."
19993
20014
  ] }),
19994
- /* @__PURE__ */ jsx19(Box18, { marginTop: 1, children: /* @__PURE__ */ jsx19(Text18, { color: theme.muted?.color ?? theme.info.color, dimColor: true, children: "Credits are one account-wide pool. Confirmed providers: OpenAI & Anthropic. Others (Google, Groq, xAI) may not be supported yet \u2014 the retry will tell you." }) }),
20015
+ /* @__PURE__ */ jsx19(Box18, { marginTop: 1, children: /* @__PURE__ */ jsx19(Text18, { color: theme.muted?.color ?? theme.info.color, dimColor: true, children: "Credits are one account-wide pool. Confirmed providers: OpenAI & Anthropic. Others (Google, Groq, xAI, Moonshot AI) may not be supported yet \u2014 the retry will tell you." }) }),
19995
20016
  /* @__PURE__ */ jsx19(Box18, { marginTop: 1, flexDirection: "column", children: /* @__PURE__ */ jsx19(Text18, { color: theme.muted?.color ?? theme.info.color, dimColor: true, children: 'Hint: if you already have credits, your gateway probably has Authentication turned off. CF needs it ON for Unified Billing to activate. Picking "Enable Authentication" above flips it for you.' }) }),
19996
20017
  phase.eventId ? /* @__PURE__ */ jsxs17(Box18, { marginTop: 1, flexDirection: "column", children: [
19997
20018
  /* @__PURE__ */ jsxs17(Text18, { color: theme.muted?.color ?? theme.info.color, dimColor: true, children: [
@@ -20080,6 +20101,7 @@ var init_unified_billing_status = __esm({
20080
20101
  init_ai_gateway_api();
20081
20102
  PROVIDER_NAME2 = {
20082
20103
  "workers-ai": "Cloudflare Workers AI",
20104
+ moonshotai: "Moonshot AI",
20083
20105
  anthropic: "Anthropic",
20084
20106
  openai: "OpenAI",
20085
20107
  google: "Google AI Studio",
@@ -20390,6 +20412,11 @@ var init_key_entry_modal = __esm({
20390
20412
  url: "https://dash.cloudflare.com/profile/api-tokens",
20391
20413
  hint: "Use a token with the Workers AI permission."
20392
20414
  },
20415
+ moonshotai: {
20416
+ name: "Moonshot AI",
20417
+ url: "https://platform.moonshot.cn/",
20418
+ hint: "Create a key in the Moonshot console. Starts with `sk-`."
20419
+ },
20393
20420
  anthropic: {
20394
20421
  name: "Anthropic",
20395
20422
  url: "https://console.anthropic.com/settings/keys",
@@ -20884,7 +20911,8 @@ function Onboarding({ onDone, onCancel }) {
20884
20911
  setCloudMode(true);
20885
20912
  setAccountId("");
20886
20913
  setApiToken("");
20887
- setStep("confirm");
20914
+ setModel(DEFAULT_CLOUD_MODEL);
20915
+ setStep("cloudModel");
20888
20916
  }).catch((err) => {
20889
20917
  setCloudAuthError(err instanceof Error ? err.message : String(err));
20890
20918
  });
@@ -20897,6 +20925,10 @@ function Onboarding({ onDone, onCancel }) {
20897
20925
  }
20898
20926
  setModel(picked.id);
20899
20927
  setPickedEntry(picked);
20928
+ if (cloudMode) {
20929
+ setStep("confirm");
20930
+ return;
20931
+ }
20900
20932
  if (picked.provider === "workers-ai") {
20901
20933
  setStep("confirm");
20902
20934
  } else if (isUnifiedEligible(picked)) {
@@ -20960,6 +20992,13 @@ function Onboarding({ onDone, onCancel }) {
20960
20992
  setSavedPath(`error: ${e.message}`);
20961
20993
  }
20962
20994
  };
20995
+ const CLOUD_MODEL_IDS = [
20996
+ "moonshotai/kimi-k3",
20997
+ "@cf/moonshotai/kimi-k2.7-code",
20998
+ "@cf/moonshotai/kimi-k2.6",
20999
+ "@cf/moonshotai/kimi-k2.5"
21000
+ ];
21001
+ const cloudModels = CLOUD_MODEL_IDS.map((id) => getModel(id)).filter((m) => !!m);
20963
21002
  const visibleSteps = ["mode", "accountId", "apiToken", "routingMode", "model", "confirm"];
20964
21003
  const stepIndex = Math.max(1, visibleSteps.indexOf(step) === -1 ? 3 : visibleSteps.indexOf(step) + 1);
20965
21004
  const totalSteps = visibleSteps.length;
@@ -21140,6 +21179,16 @@ function Onboarding({ onDone, onCancel }) {
21140
21179
  ") and continues."
21141
21180
  ] }) })
21142
21181
  ] }),
21182
+ step === "cloudModel" && /* @__PURE__ */ jsxs19(Fragment, { children: [
21183
+ /* @__PURE__ */ jsx21(Text20, { children: "Pick a Kimi model for KimiFlare Cloud" }),
21184
+ /* @__PURE__ */ jsx21(Text20, { color: theme.info.color, dimColor: true, children: "K3 runs through Cloudflare AI Gateway; K2.7/2.6/2.5 run on Workers AI." }),
21185
+ /* @__PURE__ */ jsx21(Box20, { marginTop: 1, children: /* @__PURE__ */ jsx21(ModelPicker, { current: model, onPick: handleModelPick, models: cloudModels }) }),
21186
+ /* @__PURE__ */ jsx21(Box20, { marginTop: 1, children: /* @__PURE__ */ jsxs19(Text20, { color: theme.info.color, dimColor: true, children: [
21187
+ "Tip: Esc keeps the default (",
21188
+ DEFAULT_CLOUD_MODEL,
21189
+ ") and continues."
21190
+ ] }) })
21191
+ ] }),
21143
21192
  step === "billingChoice" && pickedEntry && /* @__PURE__ */ jsx21(Box20, { marginTop: 1, children: /* @__PURE__ */ jsx21(BillingChooser, { model: pickedEntry, onPick: handleBillingChoice }) }),
21144
21193
  step === "cloudAuth" && /* @__PURE__ */ jsxs19(Box20, { flexDirection: "column", marginTop: 1, children: [
21145
21194
  /* @__PURE__ */ jsx21(Text20, { bold: true, color: theme.accent, children: "Kimiflare Cloud Authentication" }),
@@ -21210,6 +21259,10 @@ function Onboarding({ onDone, onCancel }) {
21210
21259
  "AI Gateway: ",
21211
21260
  aiGatewayId
21212
21261
  ] }) : /* @__PURE__ */ jsx21(Text20, { color: theme.info.color, children: "Routing: Workers AI (direct)" })),
21262
+ cloudMode && /* @__PURE__ */ jsxs19(Text20, { color: theme.info.color, children: [
21263
+ "Model: ",
21264
+ model
21265
+ ] }),
21213
21266
  cloudMode && /* @__PURE__ */ jsx21(Text20, { color: theme.info.color, children: "Billing: KimiFlare Cloud (free 5M tokens, then $10/mo Pro)" }),
21214
21267
  unifiedBilling && /* @__PURE__ */ jsx21(Text20, { color: theme.info.color, children: "Billing: Cloudflare credits (Unified Billing)" }),
21215
21268
  Object.keys(providerKeyAliases).length > 0 && /* @__PURE__ */ jsxs19(Text20, { color: theme.info.color, children: [
@@ -32432,6 +32485,7 @@ ${wcagWarnings.join("\n")}` }
32432
32485
  const sessionStartRecallRef = useRef7(null);
32433
32486
  const kimiMdStaleNudgedRef = useRef7(false);
32434
32487
  const sessionPlanRef = useRef7(null);
32488
+ const planCompletePlanRef = useRef7(null);
32435
32489
  const sessionMgr = useSessionManager({
32436
32490
  cfg,
32437
32491
  mode,
@@ -33495,8 +33549,10 @@ ${wcagWarnings.join("\n")}` }
33495
33549
  const handlePlanCompletePick = useCallback10(
33496
33550
  (picked) => {
33497
33551
  setShowPlanCompletePicker(false);
33552
+ const boundPlan = planCompletePlanRef.current;
33553
+ planCompletePlanRef.current = null;
33498
33554
  if (!picked || picked === "continue") return;
33499
- const plan = resolvePlanForFresh({
33555
+ const plan = boundPlan ?? resolvePlanForFresh({
33500
33556
  mode: "plan",
33501
33557
  messages: messagesRef.current,
33502
33558
  sessionPlan: sessionPlanRef.current,
@@ -34351,7 +34407,10 @@ ${conflicts.join("\n")}` }
34351
34407
  void memoryManagerRef.current.rememberPlan(plan, process.cwd(), sessionIdRef.current).catch(() => {
34352
34408
  });
34353
34409
  }
34354
- setShowPlanCompletePicker(true);
34410
+ if (!planOptionsRef.current) {
34411
+ planCompletePlanRef.current = plan;
34412
+ setShowPlanCompletePicker(true);
34413
+ }
34355
34414
  }
34356
34415
  }
34357
34416
  if (planOptionsRef.current) {
@@ -34508,22 +34567,21 @@ ${conflicts.join("\n")}` }
34508
34567
  setPlanOptions(null);
34509
34568
  planOptionsRef.current = null;
34510
34569
  if (option) {
34511
- const ctx = buildSlashContext();
34512
- const clipResult = executeFreshStart(ctx, option.plan);
34570
+ sessionPlanRef.current = option.plan;
34571
+ if (cfg?.memoryEnabled && memoryManagerRef.current && sessionIdRef.current) {
34572
+ void memoryManagerRef.current.rememberPlan(option.plan, process.cwd(), sessionIdRef.current).catch(() => {
34573
+ });
34574
+ }
34575
+ planCompletePlanRef.current = option.plan;
34576
+ setShowPlanCompletePicker(true);
34513
34577
  setEvents((e) => [
34514
34578
  ...e,
34515
34579
  {
34516
34580
  kind: "info",
34517
34581
  key: mkKey(),
34518
- text: clipResult.success ? `Plan "${option.label}" copied to clipboard. Starting fresh session with plan only\u2026` : `Starting fresh session with plan "${option.label}"\u2026`
34582
+ text: `Selected plan "${option.label}" \u2014 choose how to execute.`
34519
34583
  }
34520
34584
  ]);
34521
- if (!clipResult.success) {
34522
- setEvents((e) => [
34523
- ...e,
34524
- { kind: "info", key: mkKey(), text: "--- Plan ---\n" + option.plan }
34525
- ]);
34526
- }
34527
34585
  }
34528
34586
  }
34529
34587
  }
@@ -35532,7 +35590,7 @@ function isCloudModeConfigured() {
35532
35590
  }
35533
35591
  }
35534
35592
  var helpDefaultModel = isCloudModeConfigured() ? DEFAULT_CLOUD_MODEL : DEFAULT_MODEL;
35535
- var helpModelName = helpDefaultModel === DEFAULT_CLOUD_MODEL ? "Kimi-K2.7" : "Kimi-K2.6";
35593
+ var helpModelName = helpDefaultModel === DEFAULT_CLOUD_MODEL ? "Kimi-K3" : "Kimi-K2.6";
35536
35594
  var program = new Command2();
35537
35595
  program.name("kimiflare").description(`Terminal coding agent powered by ${helpModelName} 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 ${helpDefaultModel})`).option("--cloud", "use Kimiflare Cloud (api.kimiflare.com) instead of direct Workers AI").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 React Ink (the only supported engine). This flag and KIMIFLARE_UI are currently ignored.").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)");
35538
35596
  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) => {
@@ -35620,7 +35678,7 @@ Kimiflare Cloud Authentication`);
35620
35678
  await saveConfig({
35621
35679
  accountId: "",
35622
35680
  apiToken: "",
35623
- model: existing?.model ?? DEFAULT_MODEL,
35681
+ model: existing?.model ?? DEFAULT_CLOUD_MODEL,
35624
35682
  cloudMode: true
35625
35683
  });
35626
35684
  console.log("Cloud mode enabled. Run `kimiflare` to start using it.");