kimiflare 0.73.2 → 0.74.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/dist/index.js CHANGED
@@ -873,7 +873,11 @@ function isKillSwitchError(err) {
873
873
  }
874
874
  async function detectKillSwitch(res) {
875
875
  if (res.status === 503) {
876
- const data = await res.json().catch(() => ({}));
876
+ let data = {};
877
+ try {
878
+ data = await res.clone().json();
879
+ } catch {
880
+ }
877
881
  if (data.error === "SERVICE_ENDED") {
878
882
  throw new KillSwitchError(typeof data.ended_at === "string" ? data.ended_at : void 0);
879
883
  }
@@ -1077,7 +1081,7 @@ var init_registry = __esm({
1077
1081
  "xai"
1078
1082
  ]);
1079
1083
  SEED = [
1080
- // ── Workers AI (Cloudflare-hosted, native to kimiflare) ───────────────────
1084
+ // ── Kimi models (Cloudflare Workers AI, native to kimiflare) ──────────────
1081
1085
  {
1082
1086
  id: "@cf/moonshotai/kimi-k2.6",
1083
1087
  provider: "workers-ai",
@@ -1088,105 +1092,14 @@ var init_registry = __esm({
1088
1092
  billingMode: "unified"
1089
1093
  },
1090
1094
  {
1091
- id: "@cf/meta/llama-3.3-70b-instruct-fp8-fast",
1095
+ id: "@cf/moonshotai/kimi-k2.5",
1092
1096
  provider: "workers-ai",
1093
- contextWindow: 24e3,
1094
- maxOutputTokens: 4096,
1095
- pricing: { inputPerMtok: 0.29, outputPerMtok: 2.25 },
1096
- supports: { tools: true, reasoning: false, streaming: true },
1097
- billingMode: "unified"
1098
- },
1099
- {
1100
- id: "@cf/meta/llama-4-scout-17b-16e-instruct",
1101
- provider: "workers-ai",
1102
- contextWindow: 131e3,
1103
- maxOutputTokens: 4096,
1104
- pricing: { inputPerMtok: 0.27, outputPerMtok: 0.85 },
1105
- supports: { tools: true, reasoning: false, streaming: true },
1106
- billingMode: "unified"
1107
- },
1108
- // ── Anthropic (via Gateway Universal Endpoint) ────────────────────────────
1109
- {
1110
- id: "anthropic/claude-opus-4-7",
1111
- provider: "anthropic",
1112
- contextWindow: 1e6,
1113
- maxOutputTokens: 32e3,
1114
- pricing: { inputPerMtok: 15, cachedInputPerMtok: 1.5, outputPerMtok: 75 },
1115
- supports: { tools: true, reasoning: true, streaming: true, temperature: false },
1116
- billingMode: "byok"
1117
- },
1118
- {
1119
- id: "anthropic/claude-sonnet-4-6",
1120
- provider: "anthropic",
1121
- contextWindow: 1e6,
1122
- maxOutputTokens: 32e3,
1123
- pricing: { inputPerMtok: 3, cachedInputPerMtok: 0.3, outputPerMtok: 15 },
1124
- supports: { tools: true, reasoning: true, streaming: true },
1125
- billingMode: "byok"
1126
- },
1127
- {
1128
- id: "anthropic/claude-haiku-4-5",
1129
- provider: "anthropic",
1130
- contextWindow: 2e5,
1131
- maxOutputTokens: 16e3,
1132
- pricing: { inputPerMtok: 1, cachedInputPerMtok: 0.1, outputPerMtok: 5 },
1133
- supports: { tools: true, reasoning: false, streaming: true },
1134
- billingMode: "byok"
1135
- },
1136
- // ── OpenAI (via Gateway Universal Endpoint) ───────────────────────────────
1137
- {
1138
- id: "openai/gpt-5",
1139
- provider: "openai",
1140
- contextWindow: 4e5,
1141
- maxOutputTokens: 16384,
1142
- pricing: { inputPerMtok: 5, cachedInputPerMtok: 0.5, outputPerMtok: 20 },
1143
- supports: { tools: true, reasoning: true, streaming: true, temperature: false },
1144
- billingMode: "byok"
1145
- },
1146
- {
1147
- id: "openai/gpt-5-mini",
1148
- provider: "openai",
1149
- contextWindow: 4e5,
1097
+ contextWindow: 262144,
1150
1098
  maxOutputTokens: 16384,
1151
- pricing: { inputPerMtok: 0.25, cachedInputPerMtok: 0.025, outputPerMtok: 2 },
1152
- supports: { tools: true, reasoning: true, streaming: true, temperature: false },
1153
- billingMode: "byok"
1154
- },
1155
- // ── Google (via Gateway Universal Endpoint) ───────────────────────────────
1156
- {
1157
- id: "google-ai-studio/gemini-2.5-pro",
1158
- provider: "google",
1159
- contextWindow: 1e6,
1160
- maxOutputTokens: 8192,
1161
- pricing: { inputPerMtok: 1.25, outputPerMtok: 10 },
1099
+ pricing: { inputPerMtok: 0.55, cachedInputPerMtok: 0.11, outputPerMtok: 2.19 },
1162
1100
  supports: { tools: true, reasoning: true, streaming: true },
1163
- billingMode: "byok"
1164
- },
1165
- {
1166
- id: "google-ai-studio/gemini-2.5-flash",
1167
- provider: "google",
1168
- contextWindow: 1e6,
1169
- maxOutputTokens: 8192,
1170
- pricing: { inputPerMtok: 0.075, outputPerMtok: 0.3 },
1171
- supports: { tools: true, reasoning: false, streaming: true },
1172
- billingMode: "byok"
1173
- },
1174
- // ── Other OpenAI-compatible providers via Gateway ─────────────────────────
1175
- {
1176
- id: "groq/llama-3.3-70b-versatile",
1177
- provider: "openai-compatible",
1178
- contextWindow: 128e3,
1179
- maxOutputTokens: 8e3,
1180
- pricing: { inputPerMtok: 0.59, outputPerMtok: 0.79 },
1181
- supports: { tools: true, reasoning: false, streaming: true },
1182
- billingMode: "byok"
1183
- }
1184
- // NOTE: DeepSeek is intentionally NOT seeded yet.
1185
- // Our `providerKeys` schema has a single "openai-compatible" slot shared by
1186
- // every upstream in this category — so a stored Groq key would be sent to
1187
- // DeepSeek (and rejected with HTTP 401 "Authentication Fails (governor)").
1188
- // Add DeepSeek back once providerKeys is per-upstream (groq/deepseek/...)
1189
- // instead of per-provider-category.
1101
+ billingMode: "unified"
1102
+ }
1190
1103
  ];
1191
1104
  seedIndex = new Map(SEED.map((m) => [m.id, m]));
1192
1105
  userOverrides = /* @__PURE__ */ new Map();
@@ -1215,6 +1128,7 @@ async function* runKimi(opts2) {
1215
1128
  const entry = getModelOrInfer(opts2.model);
1216
1129
  const supportsTemperature = entry.supports.temperature !== false;
1217
1130
  const supportsReasoning = entry.supports.reasoning === true;
1131
+ const isDirectWorkersAi = url.startsWith("https://api.cloudflare.com/client/v4/accounts/");
1218
1132
  const compatModel = entry.provider === "workers-ai" ? `workers-ai/${opts2.model}` : opts2.model;
1219
1133
  const body = {
1220
1134
  messages: sanitizeMessagesForApi(opts2.messages),
@@ -1222,13 +1136,15 @@ async function* runKimi(opts2) {
1222
1136
  stream: true,
1223
1137
  ...supportsTemperature ? { temperature: opts2.temperature ?? 0.2 } : {},
1224
1138
  max_completion_tokens: opts2.maxCompletionTokens ?? 16384,
1225
- ...isCloudEndpoint ? {} : { model: compatModel },
1139
+ ...isCloudEndpoint || isDirectWorkersAi ? {} : { model: compatModel },
1226
1140
  // OpenAI's streaming API omits `usage` by default — you have to explicitly
1227
1141
  // opt in via stream_options. Without this, the status bar's token /
1228
1142
  // context-% / cost columns stay blank. CF docs don't mention
1229
1143
  // stream_options but accept it transparently and forward it upstream;
1230
1144
  // providers that don't recognize the field ignore it.
1231
- ...isCloudEndpoint ? {} : { stream_options: { include_usage: true } }
1145
+ // Only relevant for the AI Gateway /compat path; direct Workers AI and
1146
+ // cloud mode use their own response shapes.
1147
+ ...isCloudEndpoint || isDirectWorkersAi ? {} : { stream_options: { include_usage: true } }
1232
1148
  };
1233
1149
  if (opts2.reasoningEffort && supportsReasoning) {
1234
1150
  body.reasoning_effort = opts2.reasoningEffort;
@@ -1268,6 +1184,13 @@ async function* runKimi(opts2) {
1268
1184
  }
1269
1185
  const contentType = res.headers.get("content-type") ?? "";
1270
1186
  if (!contentType.includes("text/event-stream")) {
1187
+ if (res.bodyUsed) {
1188
+ throw new KimiApiError(
1189
+ `kimiflare: Received HTTP ${res.status} but could not read the response body. Please try again.`,
1190
+ void 0,
1191
+ res.status
1192
+ );
1193
+ }
1271
1194
  const text = await res.text();
1272
1195
  let parsed = null;
1273
1196
  try {
@@ -1382,10 +1305,22 @@ function buildKimiRequestTarget(opts2) {
1382
1305
  if (opts2.cloudDeviceId) headers2["X-Device-ID"] = opts2.cloudDeviceId;
1383
1306
  return { url: "https://api.kimiflare.com/v1/chat", headers: headers2 };
1384
1307
  }
1308
+ const entry = getModelOrInfer(opts2.model);
1385
1309
  if (!opts2.gateway?.id) {
1310
+ if (entry.provider === "workers-ai") {
1311
+ return {
1312
+ url: `https://api.cloudflare.com/client/v4/accounts/${encodeURIComponent(
1313
+ opts2.accountId
1314
+ )}/ai/run/${opts2.model}`,
1315
+ headers: {
1316
+ Authorization: `Bearer ${opts2.apiToken}`,
1317
+ "Content-Type": "application/json"
1318
+ }
1319
+ };
1320
+ }
1386
1321
  throw new KimiApiError(
1387
1322
  [
1388
- `kimiflare: ${opts2.model} routes through Cloudflare AI Gateway, but no gateway is configured.`,
1323
+ `kimiflare: ${opts2.model} requires Cloudflare AI Gateway, but no gateway is configured.`,
1389
1324
  ``,
1390
1325
  `To fix: run /gateway <your-gateway-id> (create one at https://dash.cloudflare.com/?to=/:account/ai-gateway).`
1391
1326
  ].join("\n"),
@@ -1393,7 +1328,6 @@ function buildKimiRequestTarget(opts2) {
1393
1328
  400
1394
1329
  );
1395
1330
  }
1396
- const entry = getModelOrInfer(opts2.model);
1397
1331
  const headers = gatewayHeadersFor(opts2);
1398
1332
  if (entry.provider !== "workers-ai") {
1399
1333
  const useUnified = !!opts2.unifiedBilling;
@@ -3189,12 +3123,7 @@ async function fetchEmbeddings(opts2) {
3189
3123
  url = "https://api.kimiflare.com/v1/embeddings";
3190
3124
  if (opts2.cloudToken) headers.Authorization = `Bearer ${opts2.cloudToken}`;
3191
3125
  if (opts2.cloudDeviceId) headers["X-Device-ID"] = opts2.cloudDeviceId;
3192
- } else {
3193
- if (!opts2.gateway) {
3194
- throw new Error(
3195
- "embeddings require an AI Gateway to be configured (run /gateway <id> or set aiGatewayId in config)"
3196
- );
3197
- }
3126
+ } else if (opts2.gateway) {
3198
3127
  url = `https://gateway.ai.cloudflare.com/v1/${opts2.accountId}/${opts2.gateway.id}/workers-ai/${model}`;
3199
3128
  headers.Authorization = `Bearer ${opts2.apiToken}`;
3200
3129
  const merged = {
@@ -3209,6 +3138,9 @@ async function fetchEmbeddings(opts2) {
3209
3138
  if (opts2.gateway.skipCache !== void 0) {
3210
3139
  headers["cf-aig-skip-cache"] = String(opts2.gateway.skipCache);
3211
3140
  }
3141
+ } else {
3142
+ url = `https://api.cloudflare.com/client/v4/accounts/${opts2.accountId}/ai/run/${model}`;
3143
+ headers.Authorization = `Bearer ${opts2.apiToken}`;
3212
3144
  }
3213
3145
  const results = [];
3214
3146
  for (const text of opts2.texts) {
@@ -9054,7 +8986,7 @@ Return a JSON array of strings. Example:
9054
8986
  return {
9055
8987
  accountId: this.opts.accountId,
9056
8988
  apiToken: this.opts.apiToken,
9057
- model: this.opts.plumbingModel ?? "@cf/meta/llama-4-scout-17b-16e-instruct",
8989
+ model: this.opts.plumbingModel ?? "@cf/moonshotai/kimi-k2.5",
9058
8990
  gateway: this.opts.gateway
9059
8991
  };
9060
8992
  }
@@ -9062,7 +8994,7 @@ Return a JSON array of strings. Example:
9062
8994
  return {
9063
8995
  accountId: this.opts.accountId,
9064
8996
  apiToken: this.opts.apiToken,
9065
- model: this.opts.extractionModel ?? "@cf/meta/llama-3.2-3b-instruct",
8997
+ model: this.opts.extractionModel ?? "@cf/moonshotai/kimi-k2.5",
9066
8998
  gateway: this.opts.gateway
9067
8999
  };
9068
9000
  }
@@ -15010,9 +14942,8 @@ var init_task_list = __esm({
15010
14942
  });
15011
14943
 
15012
14944
  // src/ui/model-picker.tsx
15013
- import { useMemo as useMemo2, useState as useState9 } from "react";
14945
+ import { useEffect as useEffect5, useMemo as useMemo2, useState as useState9 } from "react";
15014
14946
  import { Box as Box13, Text as Text14, useInput as useInput5 } from "ink";
15015
- import SelectInput3 from "ink-select-input";
15016
14947
  import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
15017
14948
  function formatContext(n) {
15018
14949
  if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
@@ -15139,6 +15070,10 @@ function ModelPicker({ current, onPick }) {
15139
15070
  const totalPages = pages.length;
15140
15071
  const safePage = Math.min(page, totalPages - 1);
15141
15072
  const pageRows = pages[safePage] ?? [];
15073
+ const firstSelectable = useMemo2(() => pageRows.findIndex((r) => r.kind === "model"), [pageRows]);
15074
+ useEffect5(() => {
15075
+ setSelectedIndex(Math.max(0, firstSelectable));
15076
+ }, [firstSelectable]);
15142
15077
  useInput5((input, key) => {
15143
15078
  if (key.escape || input === "q") {
15144
15079
  onPick(null);
@@ -15154,6 +15089,25 @@ function ModelPicker({ current, onPick }) {
15154
15089
  setSelectedIndex(0);
15155
15090
  return;
15156
15091
  }
15092
+ if (key.upArrow) {
15093
+ let idx = selectedIndex - 1;
15094
+ while (idx >= 0 && pageRows[idx]?.kind !== "model") idx--;
15095
+ if (idx >= 0) setSelectedIndex(idx);
15096
+ return;
15097
+ }
15098
+ if (key.downArrow) {
15099
+ let idx = selectedIndex + 1;
15100
+ while (idx < pageRows.length && pageRows[idx]?.kind !== "model") idx++;
15101
+ if (idx < pageRows.length) setSelectedIndex(idx);
15102
+ return;
15103
+ }
15104
+ if (key.return) {
15105
+ const row = pageRows[selectedIndex];
15106
+ if (row?.kind === "model") {
15107
+ onPick(row.model);
15108
+ }
15109
+ return;
15110
+ }
15157
15111
  if (key.backspace || key.delete) {
15158
15112
  setQuery((q) => q.slice(0, -1));
15159
15113
  setPage(0);
@@ -15168,17 +15122,6 @@ function ModelPicker({ current, onPick }) {
15168
15122
  }
15169
15123
  });
15170
15124
  const maxIdRender = Math.min(idColWidth, 48);
15171
- const items = pageRows.map((row, i) => {
15172
- if (row.kind === "header") {
15173
- return { label: `__hdr__::${row.label}`, value: row.key };
15174
- }
15175
- const id = truncateMiddle(row.displayId, maxIdRender);
15176
- const marker = row.isCurrent ? "\u25CF " : " ";
15177
- const idCell = padRight(`${marker}${id}`, maxIdRender + 2);
15178
- const ctxCell = padRight(row.context, ctxColWidth);
15179
- const label = `${idCell} ${ctxCell} ${row.price}`;
15180
- return { label, value: `model::${row.model.id}::${i}` };
15181
- });
15182
15125
  const headerIdCell = padRight("", maxIdRender + 2);
15183
15126
  const headerCtxCell = padRight("context", ctxColWidth);
15184
15127
  const headerLine = `${headerIdCell} ${headerCtxCell} in / out / cached`;
@@ -15193,31 +15136,21 @@ function ModelPicker({ current, onPick }) {
15193
15136
  ` \xB7 ${modelRows.length} model${modelRows.length === 1 ? "" : "s"}`
15194
15137
  ] }),
15195
15138
  /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(Text14, { color: theme.muted?.color ?? theme.info.color, dimColor: true, children: headerLine }) }),
15196
- /* @__PURE__ */ jsx15(Box13, { children: /* @__PURE__ */ jsx15(
15197
- SelectInput3,
15198
- {
15199
- items,
15200
- initialIndex: selectedIndex,
15201
- onHighlight: (item) => {
15202
- const idx = items.findIndex((i) => i.value === item.value);
15203
- if (idx >= 0) setSelectedIndex(idx);
15204
- },
15205
- onSelect: (item) => {
15206
- if (item.value.startsWith("__hdr_")) return;
15207
- if (!item.value.startsWith("model::")) return;
15208
- const modelId = item.value.slice("model::".length).split("::")[0];
15209
- const picked = allModels.find((m) => m.id === modelId) ?? null;
15210
- onPick(picked);
15211
- },
15212
- itemComponent: ({ label, isSelected }) => {
15213
- if (label.startsWith("__hdr__::")) {
15214
- const name = label.slice("__hdr__::".length);
15215
- return /* @__PURE__ */ jsx15(Text14, { color: theme.muted?.color ?? theme.info.color, dimColor: true, children: name });
15216
- }
15217
- return /* @__PURE__ */ jsx15(Text14, { color: isSelected ? theme.accent : theme.info.color, bold: isSelected, children: label });
15218
- }
15219
- }
15220
- ) }),
15139
+ /* @__PURE__ */ jsx15(Box13, { flexDirection: "column", children: pageRows.map((row, i) => {
15140
+ if (row.kind === "header") {
15141
+ return /* @__PURE__ */ jsx15(Box13, { children: /* @__PURE__ */ jsx15(Text14, { color: theme.muted?.color ?? theme.info.color, dimColor: true, children: row.label }) }, row.key);
15142
+ }
15143
+ const isSelected = i === selectedIndex;
15144
+ const id = truncateMiddle(row.displayId, maxIdRender);
15145
+ const marker = row.isCurrent ? "\u25CF " : " ";
15146
+ const idCell = padRight(`${marker}${id}`, maxIdRender + 2);
15147
+ const ctxCell = padRight(row.context, ctxColWidth);
15148
+ const label = `${idCell} ${ctxCell} ${row.price}`;
15149
+ return /* @__PURE__ */ jsx15(Box13, { children: /* @__PURE__ */ jsxs13(Text14, { color: isSelected ? theme.accent : theme.info.color, bold: isSelected, children: [
15150
+ isSelected ? "\u203A " : " ",
15151
+ label
15152
+ ] }) }, row.model.id);
15153
+ }) }),
15221
15154
  /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsxs13(Text14, { color: theme.muted?.color ?? theme.info.color, dimColor: true, children: [
15222
15155
  safePage > 0 ? "\u2190 prev " : "",
15223
15156
  safePage < totalPages - 1 ? "\u2192 next " : "",
@@ -15253,7 +15186,7 @@ var init_model_picker = __esm({
15253
15186
 
15254
15187
  // src/ui/billing-chooser.tsx
15255
15188
  import { Box as Box14, Text as Text15, useInput as useInput6 } from "ink";
15256
- import SelectInput4 from "ink-select-input";
15189
+ import SelectInput3 from "ink-select-input";
15257
15190
  import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
15258
15191
  function BillingChooser({ model, onPick }) {
15259
15192
  const theme = useTheme();
@@ -15283,7 +15216,7 @@ function BillingChooser({ model, onPick }) {
15283
15216
  /* @__PURE__ */ jsx16(Text15, { bold: true, children: model.id }),
15284
15217
  ". How would you like to pay for it?"
15285
15218
  ] }) }),
15286
- /* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(SelectInput4, { items, onSelect: (item) => onPick(item.value) }) }),
15219
+ /* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(SelectInput3, { items, onSelect: (item) => onPick(item.value) }) }),
15287
15220
  /* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(Text15, { color: theme.muted?.color ?? theme.info.color, dimColor: true, children: "\u2191/\u2193 select \xB7 Enter \xB7 Esc cancel" }) })
15288
15221
  ]
15289
15222
  }
@@ -15519,9 +15452,9 @@ var init_ai_gateway_api = __esm({
15519
15452
  });
15520
15453
 
15521
15454
  // src/ui/unified-billing-status.tsx
15522
- import { useEffect as useEffect5, useState as useState10 } from "react";
15455
+ import { useEffect as useEffect6, useState as useState10 } from "react";
15523
15456
  import { Box as Box15, Text as Text16, useInput as useInput7 } from "ink";
15524
- import SelectInput5 from "ink-select-input";
15457
+ import SelectInput4 from "ink-select-input";
15525
15458
  import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
15526
15459
  function UnifiedBillingStatus({
15527
15460
  model,
@@ -15534,7 +15467,7 @@ function UnifiedBillingStatus({
15534
15467
  const [phase, setPhase] = useState10({ kind: "probing" });
15535
15468
  const [attempt, setAttempt] = useState10(0);
15536
15469
  const name = PROVIDER_NAME2[model.provider];
15537
- useEffect5(() => {
15470
+ useEffect6(() => {
15538
15471
  let cancelled = false;
15539
15472
  (async () => {
15540
15473
  const r = await probeUnifiedBilling({
@@ -15635,7 +15568,7 @@ function UnifiedBillingStatus({
15635
15568
  ] }) : null
15636
15569
  ] }),
15637
15570
  /* @__PURE__ */ jsx17(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx17(
15638
- SelectInput5,
15571
+ SelectInput4,
15639
15572
  {
15640
15573
  items: items2,
15641
15574
  onSelect: (item) => {
@@ -15685,7 +15618,7 @@ function UnifiedBillingStatus({
15685
15618
  /* @__PURE__ */ jsx17(Text16, { color: theme.accent, underline: true, children: ` https://dash.cloudflare.com/${accountId}/ai/ai-gateway/gateways/${gatewayId}/logs` })
15686
15619
  ] }) : null,
15687
15620
  /* @__PURE__ */ jsx17(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx17(
15688
- SelectInput5,
15621
+ SelectInput4,
15689
15622
  {
15690
15623
  items,
15691
15624
  onSelect: (item) => {
@@ -15801,7 +15734,7 @@ var init_secrets_store = __esm({
15801
15734
  // src/ui/key-entry-modal.tsx
15802
15735
  import { useState as useState11 } from "react";
15803
15736
  import { Box as Box16, Text as Text17, useInput as useInput8 } from "ink";
15804
- import SelectInput6 from "ink-select-input";
15737
+ import SelectInput5 from "ink-select-input";
15805
15738
  import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
15806
15739
  function maskPreview(value) {
15807
15740
  if (!value) return "";
@@ -15909,7 +15842,7 @@ function KeyEntryModal({
15909
15842
  /* @__PURE__ */ jsx18(Text17, { color: theme.accent, underline: true, children: "https://dash.cloudflare.com/profile/api-tokens" })
15910
15843
  ] }),
15911
15844
  /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
15912
- SelectInput6,
15845
+ SelectInput5,
15913
15846
  {
15914
15847
  items: fallbackItems,
15915
15848
  onSelect: (item) => {
@@ -15941,7 +15874,7 @@ function KeyEntryModal({
15941
15874
  /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Couldn't store the key." }),
15942
15875
  /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, children: phase.message }) }),
15943
15876
  /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
15944
- SelectInput6,
15877
+ SelectInput5,
15945
15878
  {
15946
15879
  items: [
15947
15880
  { label: "Try again", value: "retry" },
@@ -16041,7 +15974,7 @@ var init_key_entry_modal = __esm({
16041
15974
  });
16042
15975
 
16043
15976
  // src/ui/onboarding.tsx
16044
- import { useState as useState12, useCallback as useCallback3, useEffect as useEffect6 } from "react";
15977
+ import { useState as useState12, useCallback as useCallback3, useEffect as useEffect7 } from "react";
16045
15978
  import { Box as Box17, Text as Text18, useInput as useInput9 } from "ink";
16046
15979
  import { Fragment, jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
16047
15980
  function Onboarding({ onDone, onCancel }) {
@@ -16051,6 +15984,8 @@ function Onboarding({ onDone, onCancel }) {
16051
15984
  const [apiToken, setApiToken] = useState12("");
16052
15985
  const [model, setModel] = useState12(DEFAULT_MODEL);
16053
15986
  const [savedPath, setSavedPath] = useState12(null);
15987
+ const [useGateway, setUseGateway] = useState12(null);
15988
+ const [routingPickIdx, setRoutingPickIdx] = useState12(0);
16054
15989
  const [gateways, setGateways] = useState12([]);
16055
15990
  const [gatewayPickIdx, setGatewayPickIdx] = useState12(0);
16056
15991
  const [aiGatewayId, setAiGatewayId] = useState12("");
@@ -16073,6 +16008,25 @@ function Onboarding({ onDone, onCancel }) {
16073
16008
  [onCancel]
16074
16009
  )
16075
16010
  );
16011
+ useInput9(
16012
+ (_input, key) => {
16013
+ if (step !== "routingMode") return;
16014
+ const total = 2;
16015
+ if (key.upArrow) {
16016
+ setRoutingPickIdx((i) => (i - 1 + total) % total);
16017
+ } else if (key.downArrow) {
16018
+ setRoutingPickIdx((i) => (i + 1) % total);
16019
+ } else if (key.return) {
16020
+ if (routingPickIdx === 0) {
16021
+ setUseGateway(false);
16022
+ setStep("model");
16023
+ } else {
16024
+ setUseGateway(true);
16025
+ setStep("gatewayLoading");
16026
+ }
16027
+ }
16028
+ }
16029
+ );
16076
16030
  useInput9(
16077
16031
  (_input, key) => {
16078
16032
  if (step !== "gatewayPick") return;
@@ -16094,7 +16048,7 @@ function Onboarding({ onDone, onCancel }) {
16094
16048
  }
16095
16049
  }
16096
16050
  );
16097
- useEffect6(() => {
16051
+ useEffect7(() => {
16098
16052
  if (step !== "gatewayLoading") return;
16099
16053
  let cancelled = false;
16100
16054
  (async () => {
@@ -16146,7 +16100,7 @@ function Onboarding({ onDone, onCancel }) {
16146
16100
  const trimmed = value.trim();
16147
16101
  if (!trimmed) return;
16148
16102
  setApiToken(trimmed);
16149
- setStep("gatewayLoading");
16103
+ setStep("routingMode");
16150
16104
  };
16151
16105
  const handleGatewayCreateSubmit = async (value) => {
16152
16106
  const name = (value.trim() || "kimiflare").toLowerCase().replace(/[^a-z0-9_-]/g, "-");
@@ -16238,7 +16192,7 @@ function Onboarding({ onDone, onCancel }) {
16238
16192
  setSavedPath(`error: ${e.message}`);
16239
16193
  }
16240
16194
  };
16241
- const visibleSteps = ["accountId", "apiToken", "gatewayLoading", "model", "confirm"];
16195
+ const visibleSteps = ["accountId", "apiToken", "routingMode", "model", "confirm"];
16242
16196
  const stepIndex = Math.max(1, visibleSteps.indexOf(step) === -1 ? 3 : visibleSteps.indexOf(step) + 1);
16243
16197
  const totalSteps = visibleSteps.length;
16244
16198
  return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", paddingY: 1, children: [
@@ -16287,6 +16241,29 @@ function Onboarding({ onDone, onCancel }) {
16287
16241
  )
16288
16242
  ] })
16289
16243
  ] }),
16244
+ step === "routingMode" && /* @__PURE__ */ jsxs17(Fragment, { children: [
16245
+ /* @__PURE__ */ jsx19(Text18, { children: "Choose how to route AI requests" }),
16246
+ /* @__PURE__ */ jsx19(Text18, { color: theme.info.color, children: "Use \u2191/\u2193 to navigate, Enter to select." }),
16247
+ /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", marginTop: 1, children: [
16248
+ /* @__PURE__ */ jsxs17(Text18, { color: routingPickIdx === 0 ? theme.palette.primary : void 0, children: [
16249
+ routingPickIdx === 0 ? "\u203A " : " ",
16250
+ "Workers AI (direct) \u2014 fastest, no gateway overhead"
16251
+ ] }),
16252
+ /* @__PURE__ */ jsxs17(Text18, { color: theme.info.color, dimColor: true, children: [
16253
+ " ",
16254
+ "Recommended for the best terminal experience. Uses Cloudflare Workers AI directly."
16255
+ ] }),
16256
+ /* @__PURE__ */ jsx19(Text18, { children: " " }),
16257
+ /* @__PURE__ */ jsxs17(Text18, { color: routingPickIdx === 1 ? theme.palette.primary : void 0, children: [
16258
+ routingPickIdx === 1 ? "\u203A " : " ",
16259
+ "AI Gateway \u2014 logs, caching, multi-provider support"
16260
+ ] }),
16261
+ /* @__PURE__ */ jsxs17(Text18, { color: theme.info.color, dimColor: true, children: [
16262
+ " ",
16263
+ "Slightly higher latency, but gives you a dashboard, request logs, and the ability to use non-Workers-AI models later."
16264
+ ] })
16265
+ ] })
16266
+ ] }),
16290
16267
  step === "gatewayLoading" && /* @__PURE__ */ jsx19(Text18, { color: theme.info.color, children: "Looking up your AI Gateways\u2026" }),
16291
16268
  step === "gatewayPick" && /* @__PURE__ */ jsxs17(Fragment, { children: [
16292
16269
  /* @__PURE__ */ jsx19(Text18, { children: "Pick an AI Gateway to route requests through" }),
@@ -16364,6 +16341,7 @@ function Onboarding({ onDone, onCancel }) {
16364
16341
  aiGatewayId,
16365
16342
  " \u2713"
16366
16343
  ] }),
16344
+ !aiGatewayId && useGateway === false && /* @__PURE__ */ jsx19(Text18, { color: theme.palette.success, children: "Routing: Workers AI (direct) \u2713" }),
16367
16345
  /* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(ModelPicker, { current: model, onPick: handleModelPick }) }),
16368
16346
  /* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsxs17(Text18, { color: theme.info.color, dimColor: true, children: [
16369
16347
  "Tip: Esc keeps the default (",
@@ -16417,10 +16395,10 @@ function Onboarding({ onDone, onCancel }) {
16417
16395
  "Model: ",
16418
16396
  model
16419
16397
  ] }),
16420
- aiGatewayId && /* @__PURE__ */ jsxs17(Text18, { color: theme.info.color, children: [
16398
+ aiGatewayId ? /* @__PURE__ */ jsxs17(Text18, { color: theme.info.color, children: [
16421
16399
  "AI Gateway: ",
16422
16400
  aiGatewayId
16423
- ] }),
16401
+ ] }) : /* @__PURE__ */ jsx19(Text18, { color: theme.info.color, children: "Routing: Workers AI (direct)" }),
16424
16402
  unifiedBilling && /* @__PURE__ */ jsx19(Text18, { color: theme.info.color, children: "Billing: Cloudflare credits (Unified Billing)" }),
16425
16403
  Object.keys(providerKeyAliases).length > 0 && /* @__PURE__ */ jsxs17(Text18, { color: theme.info.color, children: [
16426
16404
  "Provider keys: ",
@@ -18386,7 +18364,7 @@ var init_slash_picker = __esm({
18386
18364
  });
18387
18365
 
18388
18366
  // src/ui/use-picker-controller.ts
18389
- import { useCallback as useCallback4, useEffect as useEffect7, useMemo as useMemo3, useRef as useRef4, useState as useState13 } from "react";
18367
+ import { useCallback as useCallback4, useEffect as useEffect8, useMemo as useMemo3, useRef as useRef4, useState as useState13 } from "react";
18390
18368
  function filterPickerItems(items, query) {
18391
18369
  return fuzzyFilter(items, query, (item) => item.name).slice(0, 50);
18392
18370
  }
@@ -18489,7 +18467,7 @@ function usePickerController(opts2) {
18489
18467
  if (activeKind !== "slash") return [];
18490
18468
  return fuzzyFilter(allSlashCommands, query, (c) => c.name).slice(0, 50);
18491
18469
  }, [activeKind, allSlashCommands, query]);
18492
- useEffect7(() => {
18470
+ useEffect8(() => {
18493
18471
  const t = decidePickerTransition(
18494
18472
  active,
18495
18473
  input,
@@ -18513,21 +18491,21 @@ function usePickerController(opts2) {
18513
18491
  }
18514
18492
  }
18515
18493
  }, [input, cursorOffset, active, filePickerEnabled]);
18516
- useEffect7(() => {
18494
+ useEffect8(() => {
18517
18495
  if (active?.kind !== "file") return;
18518
18496
  const max = Math.max(0, fileItems.length - 1);
18519
18497
  if (active.selected > max) {
18520
18498
  setActive({ ...active, selected: max });
18521
18499
  }
18522
18500
  }, [fileItems.length, active]);
18523
- useEffect7(() => {
18501
+ useEffect8(() => {
18524
18502
  if (active?.kind !== "slash") return;
18525
18503
  const max = Math.max(0, slashItems.length - 1);
18526
18504
  if (active.selected > max) {
18527
18505
  setActive({ ...active, selected: max });
18528
18506
  }
18529
18507
  }, [slashItems.length, active]);
18530
- useEffect7(() => {
18508
+ useEffect8(() => {
18531
18509
  if (modalActive && active !== null) {
18532
18510
  setActive(null);
18533
18511
  }
@@ -18674,7 +18652,7 @@ var init_use_modal_host = __esm({
18674
18652
 
18675
18653
  // src/ui/limit-modal.tsx
18676
18654
  import { Box as Box21, Text as Text22 } from "ink";
18677
- import SelectInput7 from "ink-select-input";
18655
+ import SelectInput6 from "ink-select-input";
18678
18656
  import { jsx as jsx23, jsxs as jsxs21 } from "react/jsx-runtime";
18679
18657
  function LimitModal({ limit, onDecide, title, description, items }) {
18680
18658
  const theme = useTheme();
@@ -18687,7 +18665,7 @@ function LimitModal({ limit, onDecide, title, description, items }) {
18687
18665
  /* @__PURE__ */ jsx23(Text22, { color: theme.error, bold: true, children: title ?? `Tool-call limit reached (${limit})` }),
18688
18666
  /* @__PURE__ */ jsx23(Text22, { dimColor: true, children: description ?? `This session has made ${limit} tool calls. What would you like to do?` }),
18689
18667
  /* @__PURE__ */ jsx23(Box21, { marginTop: 1, children: /* @__PURE__ */ jsx23(
18690
- SelectInput7,
18668
+ SelectInput6,
18691
18669
  {
18692
18670
  items: selectItems,
18693
18671
  onSelect: (item) => onDecide(item.value)
@@ -18705,7 +18683,7 @@ var init_limit_modal = __esm({
18705
18683
  // src/ui/command-wizard.tsx
18706
18684
  import { useState as useState15 } from "react";
18707
18685
  import { Box as Box22, Text as Text23, useInput as useInput10, useWindowSize } from "ink";
18708
- import SelectInput8 from "ink-select-input";
18686
+ import SelectInput7 from "ink-select-input";
18709
18687
  import { Fragment as Fragment2, jsx as jsx24, jsxs as jsxs22 } from "react/jsx-runtime";
18710
18688
  function CommandWizard({ mode, initial, existingNames, builtinNames, onDone, onSave }) {
18711
18689
  const theme = useTheme();
@@ -18958,7 +18936,7 @@ ${template}`;
18958
18936
  ")"
18959
18937
  ] }),
18960
18938
  /* @__PURE__ */ jsx24(Box22, { marginTop: 1, children: /* @__PURE__ */ jsx24(
18961
- SelectInput8,
18939
+ SelectInput7,
18962
18940
  {
18963
18941
  items,
18964
18942
  onSelect: (item) => {
@@ -18987,7 +18965,7 @@ ${template}`;
18987
18965
  ] }),
18988
18966
  /* @__PURE__ */ jsx24(Text23, { color: theme.info.color, children: "Saved to file but not yet enforced at runtime" }),
18989
18967
  /* @__PURE__ */ jsx24(Box22, { marginTop: 1, children: /* @__PURE__ */ jsx24(
18990
- SelectInput8,
18968
+ SelectInput7,
18991
18969
  {
18992
18970
  items,
18993
18971
  onSelect: (item) => {
@@ -19015,7 +18993,7 @@ ${template}`;
19015
18993
  ")"
19016
18994
  ] }),
19017
18995
  /* @__PURE__ */ jsx24(Box22, { marginTop: 1, children: /* @__PURE__ */ jsx24(
19018
- SelectInput8,
18996
+ SelectInput7,
19019
18997
  {
19020
18998
  items,
19021
18999
  onSelect: (item) => {
@@ -19061,7 +19039,7 @@ ${template}`;
19061
19039
  ")"
19062
19040
  ] }),
19063
19041
  /* @__PURE__ */ jsx24(Box22, { marginTop: 1, children: /* @__PURE__ */ jsx24(
19064
- SelectInput8,
19042
+ SelectInput7,
19065
19043
  {
19066
19044
  items,
19067
19045
  onSelect: (item) => {
@@ -19094,7 +19072,7 @@ ${template}`;
19094
19072
  ] }),
19095
19073
  /* @__PURE__ */ jsx24(Box22, { marginTop: 1, flexDirection: "column", children: previewContent().split("\n").map((line, i) => /* @__PURE__ */ jsx24(Text23, { color: theme.info.color, children: line || " " }, i)) }),
19096
19074
  /* @__PURE__ */ jsx24(Box22, { marginTop: 1, children: /* @__PURE__ */ jsx24(
19097
- SelectInput8,
19075
+ SelectInput7,
19098
19076
  {
19099
19077
  items,
19100
19078
  onSelect: (item) => handleConfirm(item.value)
@@ -19118,7 +19096,7 @@ var init_command_wizard = __esm({
19118
19096
 
19119
19097
  // src/ui/command-picker.tsx
19120
19098
  import { Box as Box23, Text as Text24 } from "ink";
19121
- import SelectInput9 from "ink-select-input";
19099
+ import SelectInput8 from "ink-select-input";
19122
19100
  import { jsx as jsx25, jsxs as jsxs23 } from "react/jsx-runtime";
19123
19101
  function CommandPicker({ commands, title, onPick }) {
19124
19102
  const theme = useTheme();
@@ -19132,7 +19110,7 @@ function CommandPicker({ commands, title, onPick }) {
19132
19110
  /* @__PURE__ */ jsx25(Text24, { color: theme.accent, bold: true, children: title }),
19133
19111
  /* @__PURE__ */ jsx25(Text24, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select." }),
19134
19112
  /* @__PURE__ */ jsx25(Box23, { marginTop: 1, children: /* @__PURE__ */ jsx25(
19135
- SelectInput9,
19113
+ SelectInput8,
19136
19114
  {
19137
19115
  items,
19138
19116
  onSelect: (item) => {
@@ -19229,7 +19207,7 @@ var init_command_list = __esm({
19229
19207
  // src/ui/lsp-wizard.tsx
19230
19208
  import { useState as useState16 } from "react";
19231
19209
  import { Box as Box25, Text as Text26 } from "ink";
19232
- import SelectInput10 from "ink-select-input";
19210
+ import SelectInput9 from "ink-select-input";
19233
19211
  import { spawn as spawn4 } from "child_process";
19234
19212
  import { jsx as jsx27, jsxs as jsxs25 } from "react/jsx-runtime";
19235
19213
  function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
@@ -19347,7 +19325,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
19347
19325
  /* @__PURE__ */ jsx27(Text26, { color: theme.accent, bold: true, children: "LSP Servers" }),
19348
19326
  /* @__PURE__ */ jsx27(Text26, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select." }),
19349
19327
  /* @__PURE__ */ jsx27(Box25, { marginTop: 1, children: /* @__PURE__ */ jsx27(
19350
- SelectInput10,
19328
+ SelectInput9,
19351
19329
  {
19352
19330
  items: mainItems,
19353
19331
  onSelect: (item) => {
@@ -19378,7 +19356,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
19378
19356
  /* @__PURE__ */ jsx27(Text26, { color: theme.accent, bold: true, children: "Add LSP Server" }),
19379
19357
  /* @__PURE__ */ jsx27(Text26, { color: theme.info.color, dimColor: false, children: "Select a language server to configure." }),
19380
19358
  /* @__PURE__ */ jsx27(Box25, { marginTop: 1, children: /* @__PURE__ */ jsx27(
19381
- SelectInput10,
19359
+ SelectInput9,
19382
19360
  {
19383
19361
  items,
19384
19362
  onSelect: (item) => {
@@ -19417,7 +19395,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
19417
19395
  ] }),
19418
19396
  installState.output && /* @__PURE__ */ jsx27(Box25, { marginTop: 1, flexDirection: "column", children: /* @__PURE__ */ jsx27(Text26, { color: isSuccess ? theme.accent : theme.error, children: installState.output.slice(-500) }) }),
19419
19397
  /* @__PURE__ */ jsx27(Box25, { marginTop: 1, children: /* @__PURE__ */ jsx27(
19420
- SelectInput10,
19398
+ SelectInput9,
19421
19399
  {
19422
19400
  items,
19423
19401
  onSelect: (item) => {
@@ -19458,7 +19436,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
19458
19436
  )
19459
19437
  ] }),
19460
19438
  /* @__PURE__ */ jsx27(Box25, { marginTop: 1, children: /* @__PURE__ */ jsx27(
19461
- SelectInput10,
19439
+ SelectInput9,
19462
19440
  {
19463
19441
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
19464
19442
  onSelect: () => setPage("add")
@@ -19487,7 +19465,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
19487
19465
  )
19488
19466
  ] }),
19489
19467
  /* @__PURE__ */ jsx27(Box25, { marginTop: 1, children: /* @__PURE__ */ jsx27(
19490
- SelectInput10,
19468
+ SelectInput9,
19491
19469
  {
19492
19470
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
19493
19471
  onSelect: () => setPage("custom-name")
@@ -19514,7 +19492,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
19514
19492
  /* @__PURE__ */ jsx27(Text26, { color: theme.accent, bold: true, children: "Save LSP Config" }),
19515
19493
  /* @__PURE__ */ jsx27(Text26, { color: theme.info.color, dimColor: false, children: "Where should this server configuration be saved?" }),
19516
19494
  /* @__PURE__ */ jsx27(Box25, { marginTop: 1, children: /* @__PURE__ */ jsx27(
19517
- SelectInput10,
19495
+ SelectInput9,
19518
19496
  {
19519
19497
  items,
19520
19498
  onSelect: (item) => {
@@ -19536,7 +19514,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
19536
19514
  /* @__PURE__ */ jsx27(Text26, { color: theme.accent, bold: true, children: "Edit LSP Server" }),
19537
19515
  /* @__PURE__ */ jsx27(Text26, { color: theme.info.color, children: "No servers configured." }),
19538
19516
  /* @__PURE__ */ jsx27(Box25, { marginTop: 1, children: /* @__PURE__ */ jsx27(
19539
- SelectInput10,
19517
+ SelectInput9,
19540
19518
  {
19541
19519
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
19542
19520
  onSelect: () => setPage("main")
@@ -19560,7 +19538,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
19560
19538
  /* @__PURE__ */ jsx27(Text26, { color: theme.accent, bold: true, children: "Edit LSP Server" }),
19561
19539
  /* @__PURE__ */ jsx27(Text26, { color: theme.info.color, dimColor: false, children: "Select a server to toggle enabled/disabled." }),
19562
19540
  /* @__PURE__ */ jsx27(Box25, { marginTop: 1, children: /* @__PURE__ */ jsx27(
19563
- SelectInput10,
19541
+ SelectInput9,
19564
19542
  {
19565
19543
  items,
19566
19544
  onSelect: (item) => {
@@ -19581,7 +19559,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
19581
19559
  /* @__PURE__ */ jsx27(Text26, { color: theme.accent, bold: true, children: "Delete LSP Server" }),
19582
19560
  /* @__PURE__ */ jsx27(Text26, { color: theme.info.color, children: "No servers configured." }),
19583
19561
  /* @__PURE__ */ jsx27(Box25, { marginTop: 1, children: /* @__PURE__ */ jsx27(
19584
- SelectInput10,
19562
+ SelectInput9,
19585
19563
  {
19586
19564
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
19587
19565
  onSelect: () => setPage("main")
@@ -19601,7 +19579,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
19601
19579
  /* @__PURE__ */ jsx27(Text26, { color: theme.accent, bold: true, children: "Delete LSP Server" }),
19602
19580
  /* @__PURE__ */ jsx27(Text26, { color: theme.info.color, dimColor: false, children: "Select a server to remove from config." }),
19603
19581
  /* @__PURE__ */ jsx27(Box25, { marginTop: 1, children: /* @__PURE__ */ jsx27(
19604
- SelectInput10,
19582
+ SelectInput9,
19605
19583
  {
19606
19584
  items,
19607
19585
  onSelect: (item) => {
@@ -19625,7 +19603,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
19625
19603
  return /* @__PURE__ */ jsx27(Text26, { color: theme.info.color, children: ` ${k.padEnd(16)} ${status} ${s.command.join(" ")}` }, k);
19626
19604
  }) }),
19627
19605
  /* @__PURE__ */ jsx27(Box25, { marginTop: 1, children: /* @__PURE__ */ jsx27(
19628
- SelectInput10,
19606
+ SelectInput9,
19629
19607
  {
19630
19608
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
19631
19609
  onSelect: () => setPage("main")
@@ -19753,7 +19731,7 @@ var init_lsp_wizard = __esm({
19753
19731
 
19754
19732
  // src/ui/theme-picker.tsx
19755
19733
  import { Box as Box26, Text as Text27 } from "ink";
19756
- import SelectInput11 from "ink-select-input";
19734
+ import SelectInput10 from "ink-select-input";
19757
19735
  import { jsx as jsx28, jsxs as jsxs26 } from "react/jsx-runtime";
19758
19736
  function PaletteSwatches({ palette }) {
19759
19737
  const colors = [
@@ -19773,7 +19751,7 @@ function ThemePicker({ themes, onPick }) {
19773
19751
  return /* @__PURE__ */ jsxs26(Box26, { flexDirection: "column", borderStyle: "round", borderColor: current.accent, paddingX: 1, children: [
19774
19752
  /* @__PURE__ */ jsx28(Text27, { color: current.accent, bold: true, children: "Pick a theme (restart to apply)" }),
19775
19753
  /* @__PURE__ */ jsx28(Box26, { marginTop: 1, children: /* @__PURE__ */ jsx28(
19776
- SelectInput11,
19754
+ SelectInput10,
19777
19755
  {
19778
19756
  items,
19779
19757
  onSelect: (item) => {
@@ -19899,9 +19877,9 @@ var init_worker_client = __esm({
19899
19877
  });
19900
19878
 
19901
19879
  // src/ui/remote-dashboard.tsx
19902
- import { useEffect as useEffect8, useState as useState17 } from "react";
19880
+ import { useEffect as useEffect9, useState as useState17 } from "react";
19903
19881
  import { Box as Box27, Text as Text28, useInput as useInput12 } from "ink";
19904
- import SelectInput12 from "ink-select-input";
19882
+ import SelectInput11 from "ink-select-input";
19905
19883
  import { jsx as jsx29, jsxs as jsxs27 } from "react/jsx-runtime";
19906
19884
  function RemoteDashboard({ onSelect, onCancel }) {
19907
19885
  const theme = useTheme();
@@ -19909,7 +19887,7 @@ function RemoteDashboard({ onSelect, onCancel }) {
19909
19887
  const [loading, setLoading] = useState17(true);
19910
19888
  const [error, setError] = useState17(null);
19911
19889
  const [refreshing, setRefreshing] = useState17(false);
19912
- useEffect8(() => {
19890
+ useEffect9(() => {
19913
19891
  loadSessions();
19914
19892
  }, []);
19915
19893
  async function loadSessions() {
@@ -19982,7 +19960,7 @@ function RemoteDashboard({ onSelect, onCancel }) {
19982
19960
  refreshing ? "(refreshing...)" : ""
19983
19961
  ] }),
19984
19962
  /* @__PURE__ */ jsx29(Box27, { marginTop: 1, children: /* @__PURE__ */ jsx29(
19985
- SelectInput12,
19963
+ SelectInput11,
19986
19964
  {
19987
19965
  items,
19988
19966
  onSelect: (item) => {
@@ -20372,7 +20350,7 @@ var init_recommended = __esm({
20372
20350
  // src/ui/hooks-wizard.tsx
20373
20351
  import { useState as useState19 } from "react";
20374
20352
  import { Box as Box29, Text as Text30, useInput as useInput14 } from "ink";
20375
- import SelectInput13 from "ink-select-input";
20353
+ import SelectInput12 from "ink-select-input";
20376
20354
  import { jsx as jsx31, jsxs as jsxs29 } from "react/jsx-runtime";
20377
20355
  function HooksWizard(props) {
20378
20356
  const theme = useTheme();
@@ -20429,7 +20407,7 @@ function HooksWizard(props) {
20429
20407
  hint: "The lifecycle moment that fires your command.",
20430
20408
  error,
20431
20409
  children: /* @__PURE__ */ jsx31(
20432
- SelectInput13,
20410
+ SelectInput12,
20433
20411
  {
20434
20412
  items,
20435
20413
  onSelect: (it) => {
@@ -20598,7 +20576,7 @@ global \u2014 lives in ~/.config/kimiflare/settings.json (applies to
20598
20576
  every project)`,
20599
20577
  error,
20600
20578
  children: /* @__PURE__ */ jsx31(
20601
- SelectInput13,
20579
+ SelectInput12,
20602
20580
  {
20603
20581
  items: [
20604
20582
  { label: "project (.kimiflare/settings.json)", value: "project", key: "project" },
@@ -20654,7 +20632,7 @@ global \u2014 lives in ~/.config/kimiflare/settings.json (applies to
20654
20632
  ] })
20655
20633
  ] }),
20656
20634
  /* @__PURE__ */ jsx31(Box29, { marginTop: 1, children: /* @__PURE__ */ jsx31(
20657
- SelectInput13,
20635
+ SelectInput12,
20658
20636
  {
20659
20637
  items: [
20660
20638
  { label: "\u2713 Save", value: "save", key: "save" },
@@ -20749,7 +20727,7 @@ var init_hooks_wizard = __esm({
20749
20727
  // src/ui/hooks-dashboard.tsx
20750
20728
  import { useMemo as useMemo5, useState as useState20 } from "react";
20751
20729
  import { Box as Box30, Text as Text31, useInput as useInput15 } from "ink";
20752
- import SelectInput14 from "ink-select-input";
20730
+ import SelectInput13 from "ink-select-input";
20753
20731
  import { jsx as jsx32, jsxs as jsxs30 } from "react/jsx-runtime";
20754
20732
  function tag(event) {
20755
20733
  return `[${event}]`.padEnd(20);
@@ -20920,7 +20898,7 @@ function HooksDashboard(props) {
20920
20898
  ] }),
20921
20899
  configured.length === 0 && /* @__PURE__ */ jsx32(Box30, { marginTop: 1, children: /* @__PURE__ */ jsx32(Text31, { color: theme.info.color, dimColor: true, children: "No hooks configured yet. Pick a recommended one below \u2014 or create your own." }) }),
20922
20900
  /* @__PURE__ */ jsx32(Box30, { marginTop: 1, children: /* @__PURE__ */ jsx32(
20923
- SelectInput14,
20901
+ SelectInput13,
20924
20902
  {
20925
20903
  items,
20926
20904
  itemComponent: ColoredRow,
@@ -20975,7 +20953,7 @@ var init_hooks_dashboard = __esm({
20975
20953
 
20976
20954
  // src/ui/modal-host.tsx
20977
20955
  import { Box as Box31, Text as Text32 } from "ink";
20978
- import SelectInput15 from "ink-select-input";
20956
+ import SelectInput14 from "ink-select-input";
20979
20957
  import { jsx as jsx33, jsxs as jsxs31 } from "react/jsx-runtime";
20980
20958
  function ModalHost(props) {
20981
20959
  const {
@@ -21098,7 +21076,7 @@ function ModalHost(props) {
21098
21076
  ] }),
21099
21077
  /* @__PURE__ */ jsx33(Text32, { color: theme.info.color, children: cmd.filepath }),
21100
21078
  /* @__PURE__ */ jsx33(Box31, { marginTop: 1, children: /* @__PURE__ */ jsx33(
21101
- SelectInput15,
21079
+ SelectInput14,
21102
21080
  {
21103
21081
  items: [
21104
21082
  { label: "Yes, delete", value: "yes", key: "yes" },
@@ -25322,7 +25300,7 @@ var app_exports = {};
25322
25300
  __export(app_exports, {
25323
25301
  renderApp: () => renderApp
25324
25302
  });
25325
- import React19, { useState as useState23, useRef as useRef7, useEffect as useEffect9, useCallback as useCallback8, useMemo as useMemo6 } from "react";
25303
+ import React19, { useState as useState23, useRef as useRef7, useEffect as useEffect10, useCallback as useCallback8, useMemo as useMemo6 } from "react";
25326
25304
  import { Box as Box32, Text as Text33, useApp, useInput as useInput16, render } from "ink";
25327
25305
  import { existsSync as existsSync8 } from "fs";
25328
25306
  import { join as join35 } from "path";
@@ -25358,7 +25336,7 @@ function App({
25358
25336
  const [input, setInput] = useState23("");
25359
25337
  const [usage, setUsage] = useState23(null);
25360
25338
  const [sessionUsage, setSessionUsage] = useState23(null);
25361
- useEffect9(() => {
25339
+ useEffect10(() => {
25362
25340
  const handler = (sid) => {
25363
25341
  if (sessionIdRef.current && sid === sessionIdRef.current) {
25364
25342
  void getCostReport(sid).then((report) => setSessionUsage(report.session));
@@ -25470,10 +25448,10 @@ function App({
25470
25448
  const [kimiMdStale, setKimiMdStale] = useState23(false);
25471
25449
  const [gitBranch, setGitBranch] = useState23(null);
25472
25450
  const [lastSessionTopic, setLastSessionTopic] = useState23(null);
25473
- useEffect9(() => {
25451
+ useEffect10(() => {
25474
25452
  setGitBranch(detectGitBranch());
25475
25453
  }, []);
25476
- useEffect9(() => {
25454
+ useEffect10(() => {
25477
25455
  void Promise.resolve().then(() => (init_sessions(), sessions_exports)).then(
25478
25456
  ({ listSessions: listSessions2 }) => listSessions2(1).then((sessions) => {
25479
25457
  const last = sessions[0];
@@ -25483,7 +25461,7 @@ function App({
25483
25461
  })
25484
25462
  );
25485
25463
  }, []);
25486
- useEffect9(() => {
25464
+ useEffect10(() => {
25487
25465
  const onSigint = () => {
25488
25466
  logger.info("sigint:fired", {
25489
25467
  hasHandler: sigintHandlerRef.current !== null
@@ -25495,7 +25473,7 @@ function App({
25495
25473
  process.off("SIGINT", onSigint);
25496
25474
  };
25497
25475
  }, []);
25498
- useEffect9(() => {
25476
+ useEffect10(() => {
25499
25477
  let cancelled = false;
25500
25478
  loadAndMergeThemes().then(({ errors, wcagWarnings }) => {
25501
25479
  if (cancelled) return;
@@ -25519,7 +25497,7 @@ ${wcagWarnings.join("\n")}` }
25519
25497
  cancelled = true;
25520
25498
  };
25521
25499
  }, []);
25522
- useEffect9(() => {
25500
+ useEffect10(() => {
25523
25501
  if (!cfg?.cloudMode || !initialCloudToken) return;
25524
25502
  let cancelled = false;
25525
25503
  const fetchBudget = async () => {
@@ -25580,7 +25558,7 @@ ${wcagWarnings.join("\n")}` }
25580
25558
  const lspInitRef = useRef7(false);
25581
25559
  const memoryManagerRef = useRef7(null);
25582
25560
  const hooksManagerRef = useRef7(new HooksManager(process.cwd()));
25583
- useEffect9(() => {
25561
+ useEffect10(() => {
25584
25562
  executorRef.current.setHooks(hooksManagerRef.current);
25585
25563
  return () => executorRef.current.setHooks(null);
25586
25564
  }, []);
@@ -25667,7 +25645,7 @@ ${wcagWarnings.join("\n")}` }
25667
25645
  onSlashSelected: (value) => submitRef.current(value),
25668
25646
  getRecentFiles: () => recentFilesRef.current
25669
25647
  });
25670
- useEffect9(() => {
25648
+ useEffect10(() => {
25671
25649
  if (!cfg) return;
25672
25650
  runStartupTasks({
25673
25651
  cfg,
@@ -25684,7 +25662,7 @@ ${wcagWarnings.join("\n")}` }
25684
25662
  initialCloudDeviceId
25685
25663
  });
25686
25664
  }, [cfg, setEvents]);
25687
- useEffect9(() => {
25665
+ useEffect10(() => {
25688
25666
  const id = setInterval(() => {
25689
25667
  try {
25690
25668
  performance.clearMarks();
@@ -25709,7 +25687,7 @@ ${wcagWarnings.join("\n")}` }
25709
25687
  ]);
25710
25688
  }
25711
25689
  }, [setEvents]);
25712
- useEffect9(() => {
25690
+ useEffect10(() => {
25713
25691
  if (!cfg || updateCheckedRef.current) return;
25714
25692
  updateCheckedRef.current = true;
25715
25693
  if (initialUpdateResult) {
@@ -25760,7 +25738,7 @@ ${wcagWarnings.join("\n")}` }
25760
25738
  }
25761
25739
  });
25762
25740
  }, [cfg, initialUpdateResult]);
25763
- useEffect9(() => {
25741
+ useEffect10(() => {
25764
25742
  modeRef.current = mode;
25765
25743
  if (cacheStableRef.current) {
25766
25744
  messagesRef.current[1] = {
@@ -25787,10 +25765,10 @@ ${wcagWarnings.join("\n")}` }
25787
25765
  executorRef.current.clearSessionPermissions();
25788
25766
  }
25789
25767
  }, [mode, cfg?.model]);
25790
- useEffect9(() => {
25768
+ useEffect10(() => {
25791
25769
  effortRef.current = effort;
25792
25770
  }, [effort]);
25793
- useEffect9(() => {
25771
+ useEffect10(() => {
25794
25772
  if (!cfg) return;
25795
25773
  const id = setInterval(() => {
25796
25774
  void checkForUpdate().then((result) => {
@@ -25853,7 +25831,7 @@ ${wcagWarnings.join("\n")}` }
25853
25831
  lspInitRef
25854
25832
  });
25855
25833
  }, [cfg]);
25856
- useEffect9(() => {
25834
+ useEffect10(() => {
25857
25835
  if (cfg && !mcpInitRef.current) {
25858
25836
  void initMcp2();
25859
25837
  }
@@ -27005,7 +26983,7 @@ ${wcagWarnings.join("\n")}` }
27005
26983
  },
27006
26984
  [cfg, handleSlash, updateAssistant, updateTool, saveSessionSafe, updateGatewayMeta]
27007
26985
  );
27008
- useEffect9(() => {
26986
+ useEffect10(() => {
27009
26987
  if (!busy && queue2.length > 0 && supervisorRef.current.phase === "idle") {
27010
26988
  const next = queue2[0];
27011
26989
  setQueue((q) => q.slice(1));
@@ -27035,7 +27013,7 @@ ${wcagWarnings.join("\n")}` }
27035
27013
  [processMessage]
27036
27014
  );
27037
27015
  submitRef.current = submit;
27038
- useEffect9(() => {
27016
+ useEffect10(() => {
27039
27017
  if (compactSuggestedRef.current) return;
27040
27018
  if (usage && usage.prompt_tokens / modelContextLimit >= AUTO_COMPACT_SUGGEST_PCT) {
27041
27019
  compactSuggestedRef.current = true;