kimiflare 0.73.1 → 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",
1092
- 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",
1095
+ id: "@cf/moonshotai/kimi-k2.5",
1101
1096
  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();
@@ -1211,27 +1124,27 @@ async function* runKimi(opts2) {
1211
1124
  }
1212
1125
  const requestId = opts2.requestId ?? crypto.randomUUID();
1213
1126
  const { url, headers: gatewayHeaders } = buildKimiRequestTarget(opts2);
1214
- const isUniversalEndpoint = url.includes("/compat/chat/completions");
1127
+ const isCloudEndpoint = url.startsWith("https://api.kimiflare.com");
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/");
1132
+ const compatModel = entry.provider === "workers-ai" ? `workers-ai/${opts2.model}` : opts2.model;
1218
1133
  const body = {
1219
1134
  messages: sanitizeMessagesForApi(opts2.messages),
1220
1135
  ...opts2.tools && opts2.tools.length ? { tools: opts2.tools, tool_choice: "auto", parallel_tool_calls: true } : {},
1221
1136
  stream: true,
1222
1137
  ...supportsTemperature ? { temperature: opts2.temperature ?? 0.2 } : {},
1223
1138
  max_completion_tokens: opts2.maxCompletionTokens ?? 16384,
1224
- // Universal Endpoint routes by the `model` body field (e.g. "anthropic/claude-sonnet-4-6").
1225
- // Workers AI endpoints route by URL path and ignore body.model.
1226
- ...isUniversalEndpoint ? { model: opts2.model } : {},
1139
+ ...isCloudEndpoint || isDirectWorkersAi ? {} : { model: compatModel },
1227
1140
  // OpenAI's streaming API omits `usage` by default — you have to explicitly
1228
1141
  // opt in via stream_options. Without this, the status bar's token /
1229
- // context-% / cost columns stay blank for every model that routes through
1230
- // the Universal Endpoint (verified empirically by curling /compat with and
1231
- // without this flag — see PR #468 discussion). CF docs don't mention
1142
+ // context-% / cost columns stay blank. CF docs don't mention
1232
1143
  // stream_options but accept it transparently and forward it upstream;
1233
1144
  // providers that don't recognize the field ignore it.
1234
- ...isUniversalEndpoint ? { 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 } }
1235
1148
  };
1236
1149
  if (opts2.reasoningEffort && supportsReasoning) {
1237
1150
  body.reasoning_effort = opts2.reasoningEffort;
@@ -1271,6 +1184,13 @@ async function* runKimi(opts2) {
1271
1184
  }
1272
1185
  const contentType = res.headers.get("content-type") ?? "";
1273
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
+ }
1274
1194
  const text = await res.text();
1275
1195
  let parsed = null;
1276
1196
  try {
@@ -1381,25 +1301,35 @@ function gatewayHeadersFor(opts2) {
1381
1301
  function buildKimiRequestTarget(opts2) {
1382
1302
  validateModelId(opts2.model);
1383
1303
  if (opts2.cloudMode) {
1384
- const headers = opts2.cloudToken ? { Authorization: `Bearer ${opts2.cloudToken}` } : {};
1385
- if (opts2.cloudDeviceId) headers["X-Device-ID"] = opts2.cloudDeviceId;
1386
- return { url: "https://api.kimiflare.com/v1/chat", headers };
1304
+ const headers2 = opts2.cloudToken ? { Authorization: `Bearer ${opts2.cloudToken}` } : {};
1305
+ if (opts2.cloudDeviceId) headers2["X-Device-ID"] = opts2.cloudDeviceId;
1306
+ return { url: "https://api.kimiflare.com/v1/chat", headers: headers2 };
1387
1307
  }
1388
1308
  const entry = getModelOrInfer(opts2.model);
1389
- if (entry.provider !== "workers-ai") {
1390
- if (!opts2.gateway?.id) {
1391
- throw new KimiApiError(
1392
- [
1393
- `kimiflare: ${opts2.model} (${entry.provider}) is routed through Cloudflare AI Gateway, but no gateway is configured.`,
1394
- ``,
1395
- `To fix: run /gateway <your-gateway-id> (create one at https://dash.cloudflare.com/?to=/:account/ai-gateway),`,
1396
- `or switch back to a Workers AI model: /model @cf/moonshotai/kimi-k2.6`
1397
- ].join("\n"),
1398
- void 0,
1399
- 400
1400
- );
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
+ };
1401
1320
  }
1402
- const headers = gatewayHeadersFor(opts2);
1321
+ throw new KimiApiError(
1322
+ [
1323
+ `kimiflare: ${opts2.model} requires Cloudflare AI Gateway, but no gateway is configured.`,
1324
+ ``,
1325
+ `To fix: run /gateway <your-gateway-id> (create one at https://dash.cloudflare.com/?to=/:account/ai-gateway).`
1326
+ ].join("\n"),
1327
+ void 0,
1328
+ 400
1329
+ );
1330
+ }
1331
+ const headers = gatewayHeadersFor(opts2);
1332
+ if (entry.provider !== "workers-ai") {
1403
1333
  const useUnified = !!opts2.unifiedBilling;
1404
1334
  const alias = opts2.providerKeyAliases?.[entry.provider];
1405
1335
  const providerKey = opts2.providerKeys?.[entry.provider];
@@ -1415,24 +1345,12 @@ function buildKimiRequestTarget(opts2) {
1415
1345
  401
1416
1346
  );
1417
1347
  }
1418
- return {
1419
- url: `https://gateway.ai.cloudflare.com/v1/${encodeURIComponent(opts2.accountId)}/${encodeURIComponent(
1420
- opts2.gateway.id
1421
- )}/compat/chat/completions`,
1422
- headers
1423
- };
1424
- }
1425
- if (!opts2.gateway?.id) {
1426
- return {
1427
- url: `https://api.cloudflare.com/client/v4/accounts/${encodeURIComponent(opts2.accountId)}/ai/run/${opts2.model}`,
1428
- headers: {}
1429
- };
1430
1348
  }
1431
1349
  return {
1432
1350
  url: `https://gateway.ai.cloudflare.com/v1/${encodeURIComponent(opts2.accountId)}/${encodeURIComponent(
1433
1351
  opts2.gateway.id
1434
- )}/workers-ai/${opts2.model}`,
1435
- headers: gatewayHeadersFor(opts2)
1352
+ )}/compat/chat/completions`,
1353
+ headers
1436
1354
  };
1437
1355
  }
1438
1356
  function readGatewayMeta(headers) {
@@ -3205,23 +3123,24 @@ async function fetchEmbeddings(opts2) {
3205
3123
  url = "https://api.kimiflare.com/v1/embeddings";
3206
3124
  if (opts2.cloudToken) headers.Authorization = `Bearer ${opts2.cloudToken}`;
3207
3125
  if (opts2.cloudDeviceId) headers["X-Device-ID"] = opts2.cloudDeviceId;
3208
- } else {
3209
- url = opts2.gateway ? `https://gateway.ai.cloudflare.com/v1/${opts2.accountId}/${opts2.gateway.id}/workers-ai/${model}` : `https://api.cloudflare.com/client/v4/accounts/${opts2.accountId}/ai/run/${model}`;
3126
+ } else if (opts2.gateway) {
3127
+ url = `https://gateway.ai.cloudflare.com/v1/${opts2.accountId}/${opts2.gateway.id}/workers-ai/${model}`;
3210
3128
  headers.Authorization = `Bearer ${opts2.apiToken}`;
3211
- if (opts2.gateway) {
3212
- const merged = {
3213
- ...opts2.gateway.metadata ?? {},
3214
- feature: "embedding"
3215
- };
3216
- const entries = Object.entries(merged).slice(0, 5);
3217
- headers["cf-aig-metadata"] = JSON.stringify(Object.fromEntries(entries));
3218
- }
3219
- if (opts2.gateway?.cacheTtl !== void 0) {
3129
+ const merged = {
3130
+ ...opts2.gateway.metadata ?? {},
3131
+ feature: "embedding"
3132
+ };
3133
+ const entries = Object.entries(merged).slice(0, 5);
3134
+ headers["cf-aig-metadata"] = JSON.stringify(Object.fromEntries(entries));
3135
+ if (opts2.gateway.cacheTtl !== void 0) {
3220
3136
  headers["cf-aig-cache-ttl"] = String(opts2.gateway.cacheTtl);
3221
3137
  }
3222
- if (opts2.gateway?.skipCache !== void 0) {
3138
+ if (opts2.gateway.skipCache !== void 0) {
3223
3139
  headers["cf-aig-skip-cache"] = String(opts2.gateway.skipCache);
3224
3140
  }
3141
+ } else {
3142
+ url = `https://api.cloudflare.com/client/v4/accounts/${opts2.accountId}/ai/run/${model}`;
3143
+ headers.Authorization = `Bearer ${opts2.apiToken}`;
3225
3144
  }
3226
3145
  const results = [];
3227
3146
  for (const text of opts2.texts) {
@@ -9067,7 +8986,7 @@ Return a JSON array of strings. Example:
9067
8986
  return {
9068
8987
  accountId: this.opts.accountId,
9069
8988
  apiToken: this.opts.apiToken,
9070
- model: this.opts.plumbingModel ?? "@cf/meta/llama-4-scout-17b-16e-instruct",
8989
+ model: this.opts.plumbingModel ?? "@cf/moonshotai/kimi-k2.5",
9071
8990
  gateway: this.opts.gateway
9072
8991
  };
9073
8992
  }
@@ -9075,7 +8994,7 @@ Return a JSON array of strings. Example:
9075
8994
  return {
9076
8995
  accountId: this.opts.accountId,
9077
8996
  apiToken: this.opts.apiToken,
9078
- model: this.opts.extractionModel ?? "@cf/meta/llama-3.2-3b-instruct",
8997
+ model: this.opts.extractionModel ?? "@cf/moonshotai/kimi-k2.5",
9079
8998
  gateway: this.opts.gateway
9080
8999
  };
9081
9000
  }
@@ -15023,9 +14942,8 @@ var init_task_list = __esm({
15023
14942
  });
15024
14943
 
15025
14944
  // src/ui/model-picker.tsx
15026
- import { useMemo as useMemo2, useState as useState9 } from "react";
14945
+ import { useEffect as useEffect5, useMemo as useMemo2, useState as useState9 } from "react";
15027
14946
  import { Box as Box13, Text as Text14, useInput as useInput5 } from "ink";
15028
- import SelectInput3 from "ink-select-input";
15029
14947
  import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
15030
14948
  function formatContext(n) {
15031
14949
  if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
@@ -15152,6 +15070,10 @@ function ModelPicker({ current, onPick }) {
15152
15070
  const totalPages = pages.length;
15153
15071
  const safePage = Math.min(page, totalPages - 1);
15154
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]);
15155
15077
  useInput5((input, key) => {
15156
15078
  if (key.escape || input === "q") {
15157
15079
  onPick(null);
@@ -15167,6 +15089,25 @@ function ModelPicker({ current, onPick }) {
15167
15089
  setSelectedIndex(0);
15168
15090
  return;
15169
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
+ }
15170
15111
  if (key.backspace || key.delete) {
15171
15112
  setQuery((q) => q.slice(0, -1));
15172
15113
  setPage(0);
@@ -15181,17 +15122,6 @@ function ModelPicker({ current, onPick }) {
15181
15122
  }
15182
15123
  });
15183
15124
  const maxIdRender = Math.min(idColWidth, 48);
15184
- const items = pageRows.map((row, i) => {
15185
- if (row.kind === "header") {
15186
- return { label: `__hdr__::${row.label}`, value: row.key };
15187
- }
15188
- const id = truncateMiddle(row.displayId, maxIdRender);
15189
- const marker = row.isCurrent ? "\u25CF " : " ";
15190
- const idCell = padRight(`${marker}${id}`, maxIdRender + 2);
15191
- const ctxCell = padRight(row.context, ctxColWidth);
15192
- const label = `${idCell} ${ctxCell} ${row.price}`;
15193
- return { label, value: `model::${row.model.id}::${i}` };
15194
- });
15195
15125
  const headerIdCell = padRight("", maxIdRender + 2);
15196
15126
  const headerCtxCell = padRight("context", ctxColWidth);
15197
15127
  const headerLine = `${headerIdCell} ${headerCtxCell} in / out / cached`;
@@ -15206,31 +15136,21 @@ function ModelPicker({ current, onPick }) {
15206
15136
  ` \xB7 ${modelRows.length} model${modelRows.length === 1 ? "" : "s"}`
15207
15137
  ] }),
15208
15138
  /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(Text14, { color: theme.muted?.color ?? theme.info.color, dimColor: true, children: headerLine }) }),
15209
- /* @__PURE__ */ jsx15(Box13, { children: /* @__PURE__ */ jsx15(
15210
- SelectInput3,
15211
- {
15212
- items,
15213
- initialIndex: selectedIndex,
15214
- onHighlight: (item) => {
15215
- const idx = items.findIndex((i) => i.value === item.value);
15216
- if (idx >= 0) setSelectedIndex(idx);
15217
- },
15218
- onSelect: (item) => {
15219
- if (item.value.startsWith("__hdr_")) return;
15220
- if (!item.value.startsWith("model::")) return;
15221
- const modelId = item.value.slice("model::".length).split("::")[0];
15222
- const picked = allModels.find((m) => m.id === modelId) ?? null;
15223
- onPick(picked);
15224
- },
15225
- itemComponent: ({ label, isSelected }) => {
15226
- if (label.startsWith("__hdr__::")) {
15227
- const name = label.slice("__hdr__::".length);
15228
- return /* @__PURE__ */ jsx15(Text14, { color: theme.muted?.color ?? theme.info.color, dimColor: true, children: name });
15229
- }
15230
- return /* @__PURE__ */ jsx15(Text14, { color: isSelected ? theme.accent : theme.info.color, bold: isSelected, children: label });
15231
- }
15232
- }
15233
- ) }),
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
+ }) }),
15234
15154
  /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsxs13(Text14, { color: theme.muted?.color ?? theme.info.color, dimColor: true, children: [
15235
15155
  safePage > 0 ? "\u2190 prev " : "",
15236
15156
  safePage < totalPages - 1 ? "\u2192 next " : "",
@@ -15266,7 +15186,7 @@ var init_model_picker = __esm({
15266
15186
 
15267
15187
  // src/ui/billing-chooser.tsx
15268
15188
  import { Box as Box14, Text as Text15, useInput as useInput6 } from "ink";
15269
- import SelectInput4 from "ink-select-input";
15189
+ import SelectInput3 from "ink-select-input";
15270
15190
  import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
15271
15191
  function BillingChooser({ model, onPick }) {
15272
15192
  const theme = useTheme();
@@ -15296,7 +15216,7 @@ function BillingChooser({ model, onPick }) {
15296
15216
  /* @__PURE__ */ jsx16(Text15, { bold: true, children: model.id }),
15297
15217
  ". How would you like to pay for it?"
15298
15218
  ] }) }),
15299
- /* @__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) }) }),
15300
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" }) })
15301
15221
  ]
15302
15222
  }
@@ -15532,9 +15452,9 @@ var init_ai_gateway_api = __esm({
15532
15452
  });
15533
15453
 
15534
15454
  // src/ui/unified-billing-status.tsx
15535
- import { useEffect as useEffect5, useState as useState10 } from "react";
15455
+ import { useEffect as useEffect6, useState as useState10 } from "react";
15536
15456
  import { Box as Box15, Text as Text16, useInput as useInput7 } from "ink";
15537
- import SelectInput5 from "ink-select-input";
15457
+ import SelectInput4 from "ink-select-input";
15538
15458
  import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
15539
15459
  function UnifiedBillingStatus({
15540
15460
  model,
@@ -15547,7 +15467,7 @@ function UnifiedBillingStatus({
15547
15467
  const [phase, setPhase] = useState10({ kind: "probing" });
15548
15468
  const [attempt, setAttempt] = useState10(0);
15549
15469
  const name = PROVIDER_NAME2[model.provider];
15550
- useEffect5(() => {
15470
+ useEffect6(() => {
15551
15471
  let cancelled = false;
15552
15472
  (async () => {
15553
15473
  const r = await probeUnifiedBilling({
@@ -15648,7 +15568,7 @@ function UnifiedBillingStatus({
15648
15568
  ] }) : null
15649
15569
  ] }),
15650
15570
  /* @__PURE__ */ jsx17(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx17(
15651
- SelectInput5,
15571
+ SelectInput4,
15652
15572
  {
15653
15573
  items: items2,
15654
15574
  onSelect: (item) => {
@@ -15698,7 +15618,7 @@ function UnifiedBillingStatus({
15698
15618
  /* @__PURE__ */ jsx17(Text16, { color: theme.accent, underline: true, children: ` https://dash.cloudflare.com/${accountId}/ai/ai-gateway/gateways/${gatewayId}/logs` })
15699
15619
  ] }) : null,
15700
15620
  /* @__PURE__ */ jsx17(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx17(
15701
- SelectInput5,
15621
+ SelectInput4,
15702
15622
  {
15703
15623
  items,
15704
15624
  onSelect: (item) => {
@@ -15814,7 +15734,7 @@ var init_secrets_store = __esm({
15814
15734
  // src/ui/key-entry-modal.tsx
15815
15735
  import { useState as useState11 } from "react";
15816
15736
  import { Box as Box16, Text as Text17, useInput as useInput8 } from "ink";
15817
- import SelectInput6 from "ink-select-input";
15737
+ import SelectInput5 from "ink-select-input";
15818
15738
  import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
15819
15739
  function maskPreview(value) {
15820
15740
  if (!value) return "";
@@ -15922,7 +15842,7 @@ function KeyEntryModal({
15922
15842
  /* @__PURE__ */ jsx18(Text17, { color: theme.accent, underline: true, children: "https://dash.cloudflare.com/profile/api-tokens" })
15923
15843
  ] }),
15924
15844
  /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
15925
- SelectInput6,
15845
+ SelectInput5,
15926
15846
  {
15927
15847
  items: fallbackItems,
15928
15848
  onSelect: (item) => {
@@ -15954,7 +15874,7 @@ function KeyEntryModal({
15954
15874
  /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Couldn't store the key." }),
15955
15875
  /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, children: phase.message }) }),
15956
15876
  /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
15957
- SelectInput6,
15877
+ SelectInput5,
15958
15878
  {
15959
15879
  items: [
15960
15880
  { label: "Try again", value: "retry" },
@@ -16054,7 +15974,7 @@ var init_key_entry_modal = __esm({
16054
15974
  });
16055
15975
 
16056
15976
  // src/ui/onboarding.tsx
16057
- 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";
16058
15978
  import { Box as Box17, Text as Text18, useInput as useInput9 } from "ink";
16059
15979
  import { Fragment, jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
16060
15980
  function Onboarding({ onDone, onCancel }) {
@@ -16064,6 +15984,8 @@ function Onboarding({ onDone, onCancel }) {
16064
15984
  const [apiToken, setApiToken] = useState12("");
16065
15985
  const [model, setModel] = useState12(DEFAULT_MODEL);
16066
15986
  const [savedPath, setSavedPath] = useState12(null);
15987
+ const [useGateway, setUseGateway] = useState12(null);
15988
+ const [routingPickIdx, setRoutingPickIdx] = useState12(0);
16067
15989
  const [gateways, setGateways] = useState12([]);
16068
15990
  const [gatewayPickIdx, setGatewayPickIdx] = useState12(0);
16069
15991
  const [aiGatewayId, setAiGatewayId] = useState12("");
@@ -16086,6 +16008,25 @@ function Onboarding({ onDone, onCancel }) {
16086
16008
  [onCancel]
16087
16009
  )
16088
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
+ );
16089
16030
  useInput9(
16090
16031
  (_input, key) => {
16091
16032
  if (step !== "gatewayPick") return;
@@ -16107,7 +16048,7 @@ function Onboarding({ onDone, onCancel }) {
16107
16048
  }
16108
16049
  }
16109
16050
  );
16110
- useEffect6(() => {
16051
+ useEffect7(() => {
16111
16052
  if (step !== "gatewayLoading") return;
16112
16053
  let cancelled = false;
16113
16054
  (async () => {
@@ -16159,7 +16100,7 @@ function Onboarding({ onDone, onCancel }) {
16159
16100
  const trimmed = value.trim();
16160
16101
  if (!trimmed) return;
16161
16102
  setApiToken(trimmed);
16162
- setStep("gatewayLoading");
16103
+ setStep("routingMode");
16163
16104
  };
16164
16105
  const handleGatewayCreateSubmit = async (value) => {
16165
16106
  const name = (value.trim() || "kimiflare").toLowerCase().replace(/[^a-z0-9_-]/g, "-");
@@ -16251,7 +16192,7 @@ function Onboarding({ onDone, onCancel }) {
16251
16192
  setSavedPath(`error: ${e.message}`);
16252
16193
  }
16253
16194
  };
16254
- const visibleSteps = ["accountId", "apiToken", "gatewayLoading", "model", "confirm"];
16195
+ const visibleSteps = ["accountId", "apiToken", "routingMode", "model", "confirm"];
16255
16196
  const stepIndex = Math.max(1, visibleSteps.indexOf(step) === -1 ? 3 : visibleSteps.indexOf(step) + 1);
16256
16197
  const totalSteps = visibleSteps.length;
16257
16198
  return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", paddingY: 1, children: [
@@ -16300,6 +16241,29 @@ function Onboarding({ onDone, onCancel }) {
16300
16241
  )
16301
16242
  ] })
16302
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
+ ] }),
16303
16267
  step === "gatewayLoading" && /* @__PURE__ */ jsx19(Text18, { color: theme.info.color, children: "Looking up your AI Gateways\u2026" }),
16304
16268
  step === "gatewayPick" && /* @__PURE__ */ jsxs17(Fragment, { children: [
16305
16269
  /* @__PURE__ */ jsx19(Text18, { children: "Pick an AI Gateway to route requests through" }),
@@ -16377,6 +16341,7 @@ function Onboarding({ onDone, onCancel }) {
16377
16341
  aiGatewayId,
16378
16342
  " \u2713"
16379
16343
  ] }),
16344
+ !aiGatewayId && useGateway === false && /* @__PURE__ */ jsx19(Text18, { color: theme.palette.success, children: "Routing: Workers AI (direct) \u2713" }),
16380
16345
  /* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(ModelPicker, { current: model, onPick: handleModelPick }) }),
16381
16346
  /* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsxs17(Text18, { color: theme.info.color, dimColor: true, children: [
16382
16347
  "Tip: Esc keeps the default (",
@@ -16430,10 +16395,10 @@ function Onboarding({ onDone, onCancel }) {
16430
16395
  "Model: ",
16431
16396
  model
16432
16397
  ] }),
16433
- aiGatewayId && /* @__PURE__ */ jsxs17(Text18, { color: theme.info.color, children: [
16398
+ aiGatewayId ? /* @__PURE__ */ jsxs17(Text18, { color: theme.info.color, children: [
16434
16399
  "AI Gateway: ",
16435
16400
  aiGatewayId
16436
- ] }),
16401
+ ] }) : /* @__PURE__ */ jsx19(Text18, { color: theme.info.color, children: "Routing: Workers AI (direct)" }),
16437
16402
  unifiedBilling && /* @__PURE__ */ jsx19(Text18, { color: theme.info.color, children: "Billing: Cloudflare credits (Unified Billing)" }),
16438
16403
  Object.keys(providerKeyAliases).length > 0 && /* @__PURE__ */ jsxs17(Text18, { color: theme.info.color, children: [
16439
16404
  "Provider keys: ",
@@ -18399,7 +18364,7 @@ var init_slash_picker = __esm({
18399
18364
  });
18400
18365
 
18401
18366
  // src/ui/use-picker-controller.ts
18402
- 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";
18403
18368
  function filterPickerItems(items, query) {
18404
18369
  return fuzzyFilter(items, query, (item) => item.name).slice(0, 50);
18405
18370
  }
@@ -18502,7 +18467,7 @@ function usePickerController(opts2) {
18502
18467
  if (activeKind !== "slash") return [];
18503
18468
  return fuzzyFilter(allSlashCommands, query, (c) => c.name).slice(0, 50);
18504
18469
  }, [activeKind, allSlashCommands, query]);
18505
- useEffect7(() => {
18470
+ useEffect8(() => {
18506
18471
  const t = decidePickerTransition(
18507
18472
  active,
18508
18473
  input,
@@ -18526,21 +18491,21 @@ function usePickerController(opts2) {
18526
18491
  }
18527
18492
  }
18528
18493
  }, [input, cursorOffset, active, filePickerEnabled]);
18529
- useEffect7(() => {
18494
+ useEffect8(() => {
18530
18495
  if (active?.kind !== "file") return;
18531
18496
  const max = Math.max(0, fileItems.length - 1);
18532
18497
  if (active.selected > max) {
18533
18498
  setActive({ ...active, selected: max });
18534
18499
  }
18535
18500
  }, [fileItems.length, active]);
18536
- useEffect7(() => {
18501
+ useEffect8(() => {
18537
18502
  if (active?.kind !== "slash") return;
18538
18503
  const max = Math.max(0, slashItems.length - 1);
18539
18504
  if (active.selected > max) {
18540
18505
  setActive({ ...active, selected: max });
18541
18506
  }
18542
18507
  }, [slashItems.length, active]);
18543
- useEffect7(() => {
18508
+ useEffect8(() => {
18544
18509
  if (modalActive && active !== null) {
18545
18510
  setActive(null);
18546
18511
  }
@@ -18687,7 +18652,7 @@ var init_use_modal_host = __esm({
18687
18652
 
18688
18653
  // src/ui/limit-modal.tsx
18689
18654
  import { Box as Box21, Text as Text22 } from "ink";
18690
- import SelectInput7 from "ink-select-input";
18655
+ import SelectInput6 from "ink-select-input";
18691
18656
  import { jsx as jsx23, jsxs as jsxs21 } from "react/jsx-runtime";
18692
18657
  function LimitModal({ limit, onDecide, title, description, items }) {
18693
18658
  const theme = useTheme();
@@ -18700,7 +18665,7 @@ function LimitModal({ limit, onDecide, title, description, items }) {
18700
18665
  /* @__PURE__ */ jsx23(Text22, { color: theme.error, bold: true, children: title ?? `Tool-call limit reached (${limit})` }),
18701
18666
  /* @__PURE__ */ jsx23(Text22, { dimColor: true, children: description ?? `This session has made ${limit} tool calls. What would you like to do?` }),
18702
18667
  /* @__PURE__ */ jsx23(Box21, { marginTop: 1, children: /* @__PURE__ */ jsx23(
18703
- SelectInput7,
18668
+ SelectInput6,
18704
18669
  {
18705
18670
  items: selectItems,
18706
18671
  onSelect: (item) => onDecide(item.value)
@@ -18718,7 +18683,7 @@ var init_limit_modal = __esm({
18718
18683
  // src/ui/command-wizard.tsx
18719
18684
  import { useState as useState15 } from "react";
18720
18685
  import { Box as Box22, Text as Text23, useInput as useInput10, useWindowSize } from "ink";
18721
- import SelectInput8 from "ink-select-input";
18686
+ import SelectInput7 from "ink-select-input";
18722
18687
  import { Fragment as Fragment2, jsx as jsx24, jsxs as jsxs22 } from "react/jsx-runtime";
18723
18688
  function CommandWizard({ mode, initial, existingNames, builtinNames, onDone, onSave }) {
18724
18689
  const theme = useTheme();
@@ -18971,7 +18936,7 @@ ${template}`;
18971
18936
  ")"
18972
18937
  ] }),
18973
18938
  /* @__PURE__ */ jsx24(Box22, { marginTop: 1, children: /* @__PURE__ */ jsx24(
18974
- SelectInput8,
18939
+ SelectInput7,
18975
18940
  {
18976
18941
  items,
18977
18942
  onSelect: (item) => {
@@ -19000,7 +18965,7 @@ ${template}`;
19000
18965
  ] }),
19001
18966
  /* @__PURE__ */ jsx24(Text23, { color: theme.info.color, children: "Saved to file but not yet enforced at runtime" }),
19002
18967
  /* @__PURE__ */ jsx24(Box22, { marginTop: 1, children: /* @__PURE__ */ jsx24(
19003
- SelectInput8,
18968
+ SelectInput7,
19004
18969
  {
19005
18970
  items,
19006
18971
  onSelect: (item) => {
@@ -19028,7 +18993,7 @@ ${template}`;
19028
18993
  ")"
19029
18994
  ] }),
19030
18995
  /* @__PURE__ */ jsx24(Box22, { marginTop: 1, children: /* @__PURE__ */ jsx24(
19031
- SelectInput8,
18996
+ SelectInput7,
19032
18997
  {
19033
18998
  items,
19034
18999
  onSelect: (item) => {
@@ -19074,7 +19039,7 @@ ${template}`;
19074
19039
  ")"
19075
19040
  ] }),
19076
19041
  /* @__PURE__ */ jsx24(Box22, { marginTop: 1, children: /* @__PURE__ */ jsx24(
19077
- SelectInput8,
19042
+ SelectInput7,
19078
19043
  {
19079
19044
  items,
19080
19045
  onSelect: (item) => {
@@ -19107,7 +19072,7 @@ ${template}`;
19107
19072
  ] }),
19108
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)) }),
19109
19074
  /* @__PURE__ */ jsx24(Box22, { marginTop: 1, children: /* @__PURE__ */ jsx24(
19110
- SelectInput8,
19075
+ SelectInput7,
19111
19076
  {
19112
19077
  items,
19113
19078
  onSelect: (item) => handleConfirm(item.value)
@@ -19131,7 +19096,7 @@ var init_command_wizard = __esm({
19131
19096
 
19132
19097
  // src/ui/command-picker.tsx
19133
19098
  import { Box as Box23, Text as Text24 } from "ink";
19134
- import SelectInput9 from "ink-select-input";
19099
+ import SelectInput8 from "ink-select-input";
19135
19100
  import { jsx as jsx25, jsxs as jsxs23 } from "react/jsx-runtime";
19136
19101
  function CommandPicker({ commands, title, onPick }) {
19137
19102
  const theme = useTheme();
@@ -19145,7 +19110,7 @@ function CommandPicker({ commands, title, onPick }) {
19145
19110
  /* @__PURE__ */ jsx25(Text24, { color: theme.accent, bold: true, children: title }),
19146
19111
  /* @__PURE__ */ jsx25(Text24, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select." }),
19147
19112
  /* @__PURE__ */ jsx25(Box23, { marginTop: 1, children: /* @__PURE__ */ jsx25(
19148
- SelectInput9,
19113
+ SelectInput8,
19149
19114
  {
19150
19115
  items,
19151
19116
  onSelect: (item) => {
@@ -19242,7 +19207,7 @@ var init_command_list = __esm({
19242
19207
  // src/ui/lsp-wizard.tsx
19243
19208
  import { useState as useState16 } from "react";
19244
19209
  import { Box as Box25, Text as Text26 } from "ink";
19245
- import SelectInput10 from "ink-select-input";
19210
+ import SelectInput9 from "ink-select-input";
19246
19211
  import { spawn as spawn4 } from "child_process";
19247
19212
  import { jsx as jsx27, jsxs as jsxs25 } from "react/jsx-runtime";
19248
19213
  function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
@@ -19360,7 +19325,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
19360
19325
  /* @__PURE__ */ jsx27(Text26, { color: theme.accent, bold: true, children: "LSP Servers" }),
19361
19326
  /* @__PURE__ */ jsx27(Text26, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select." }),
19362
19327
  /* @__PURE__ */ jsx27(Box25, { marginTop: 1, children: /* @__PURE__ */ jsx27(
19363
- SelectInput10,
19328
+ SelectInput9,
19364
19329
  {
19365
19330
  items: mainItems,
19366
19331
  onSelect: (item) => {
@@ -19391,7 +19356,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
19391
19356
  /* @__PURE__ */ jsx27(Text26, { color: theme.accent, bold: true, children: "Add LSP Server" }),
19392
19357
  /* @__PURE__ */ jsx27(Text26, { color: theme.info.color, dimColor: false, children: "Select a language server to configure." }),
19393
19358
  /* @__PURE__ */ jsx27(Box25, { marginTop: 1, children: /* @__PURE__ */ jsx27(
19394
- SelectInput10,
19359
+ SelectInput9,
19395
19360
  {
19396
19361
  items,
19397
19362
  onSelect: (item) => {
@@ -19430,7 +19395,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
19430
19395
  ] }),
19431
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) }) }),
19432
19397
  /* @__PURE__ */ jsx27(Box25, { marginTop: 1, children: /* @__PURE__ */ jsx27(
19433
- SelectInput10,
19398
+ SelectInput9,
19434
19399
  {
19435
19400
  items,
19436
19401
  onSelect: (item) => {
@@ -19471,7 +19436,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
19471
19436
  )
19472
19437
  ] }),
19473
19438
  /* @__PURE__ */ jsx27(Box25, { marginTop: 1, children: /* @__PURE__ */ jsx27(
19474
- SelectInput10,
19439
+ SelectInput9,
19475
19440
  {
19476
19441
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
19477
19442
  onSelect: () => setPage("add")
@@ -19500,7 +19465,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
19500
19465
  )
19501
19466
  ] }),
19502
19467
  /* @__PURE__ */ jsx27(Box25, { marginTop: 1, children: /* @__PURE__ */ jsx27(
19503
- SelectInput10,
19468
+ SelectInput9,
19504
19469
  {
19505
19470
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
19506
19471
  onSelect: () => setPage("custom-name")
@@ -19527,7 +19492,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
19527
19492
  /* @__PURE__ */ jsx27(Text26, { color: theme.accent, bold: true, children: "Save LSP Config" }),
19528
19493
  /* @__PURE__ */ jsx27(Text26, { color: theme.info.color, dimColor: false, children: "Where should this server configuration be saved?" }),
19529
19494
  /* @__PURE__ */ jsx27(Box25, { marginTop: 1, children: /* @__PURE__ */ jsx27(
19530
- SelectInput10,
19495
+ SelectInput9,
19531
19496
  {
19532
19497
  items,
19533
19498
  onSelect: (item) => {
@@ -19549,7 +19514,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
19549
19514
  /* @__PURE__ */ jsx27(Text26, { color: theme.accent, bold: true, children: "Edit LSP Server" }),
19550
19515
  /* @__PURE__ */ jsx27(Text26, { color: theme.info.color, children: "No servers configured." }),
19551
19516
  /* @__PURE__ */ jsx27(Box25, { marginTop: 1, children: /* @__PURE__ */ jsx27(
19552
- SelectInput10,
19517
+ SelectInput9,
19553
19518
  {
19554
19519
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
19555
19520
  onSelect: () => setPage("main")
@@ -19573,7 +19538,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
19573
19538
  /* @__PURE__ */ jsx27(Text26, { color: theme.accent, bold: true, children: "Edit LSP Server" }),
19574
19539
  /* @__PURE__ */ jsx27(Text26, { color: theme.info.color, dimColor: false, children: "Select a server to toggle enabled/disabled." }),
19575
19540
  /* @__PURE__ */ jsx27(Box25, { marginTop: 1, children: /* @__PURE__ */ jsx27(
19576
- SelectInput10,
19541
+ SelectInput9,
19577
19542
  {
19578
19543
  items,
19579
19544
  onSelect: (item) => {
@@ -19594,7 +19559,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
19594
19559
  /* @__PURE__ */ jsx27(Text26, { color: theme.accent, bold: true, children: "Delete LSP Server" }),
19595
19560
  /* @__PURE__ */ jsx27(Text26, { color: theme.info.color, children: "No servers configured." }),
19596
19561
  /* @__PURE__ */ jsx27(Box25, { marginTop: 1, children: /* @__PURE__ */ jsx27(
19597
- SelectInput10,
19562
+ SelectInput9,
19598
19563
  {
19599
19564
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
19600
19565
  onSelect: () => setPage("main")
@@ -19614,7 +19579,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
19614
19579
  /* @__PURE__ */ jsx27(Text26, { color: theme.accent, bold: true, children: "Delete LSP Server" }),
19615
19580
  /* @__PURE__ */ jsx27(Text26, { color: theme.info.color, dimColor: false, children: "Select a server to remove from config." }),
19616
19581
  /* @__PURE__ */ jsx27(Box25, { marginTop: 1, children: /* @__PURE__ */ jsx27(
19617
- SelectInput10,
19582
+ SelectInput9,
19618
19583
  {
19619
19584
  items,
19620
19585
  onSelect: (item) => {
@@ -19638,7 +19603,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
19638
19603
  return /* @__PURE__ */ jsx27(Text26, { color: theme.info.color, children: ` ${k.padEnd(16)} ${status} ${s.command.join(" ")}` }, k);
19639
19604
  }) }),
19640
19605
  /* @__PURE__ */ jsx27(Box25, { marginTop: 1, children: /* @__PURE__ */ jsx27(
19641
- SelectInput10,
19606
+ SelectInput9,
19642
19607
  {
19643
19608
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
19644
19609
  onSelect: () => setPage("main")
@@ -19766,7 +19731,7 @@ var init_lsp_wizard = __esm({
19766
19731
 
19767
19732
  // src/ui/theme-picker.tsx
19768
19733
  import { Box as Box26, Text as Text27 } from "ink";
19769
- import SelectInput11 from "ink-select-input";
19734
+ import SelectInput10 from "ink-select-input";
19770
19735
  import { jsx as jsx28, jsxs as jsxs26 } from "react/jsx-runtime";
19771
19736
  function PaletteSwatches({ palette }) {
19772
19737
  const colors = [
@@ -19786,7 +19751,7 @@ function ThemePicker({ themes, onPick }) {
19786
19751
  return /* @__PURE__ */ jsxs26(Box26, { flexDirection: "column", borderStyle: "round", borderColor: current.accent, paddingX: 1, children: [
19787
19752
  /* @__PURE__ */ jsx28(Text27, { color: current.accent, bold: true, children: "Pick a theme (restart to apply)" }),
19788
19753
  /* @__PURE__ */ jsx28(Box26, { marginTop: 1, children: /* @__PURE__ */ jsx28(
19789
- SelectInput11,
19754
+ SelectInput10,
19790
19755
  {
19791
19756
  items,
19792
19757
  onSelect: (item) => {
@@ -19912,9 +19877,9 @@ var init_worker_client = __esm({
19912
19877
  });
19913
19878
 
19914
19879
  // src/ui/remote-dashboard.tsx
19915
- import { useEffect as useEffect8, useState as useState17 } from "react";
19880
+ import { useEffect as useEffect9, useState as useState17 } from "react";
19916
19881
  import { Box as Box27, Text as Text28, useInput as useInput12 } from "ink";
19917
- import SelectInput12 from "ink-select-input";
19882
+ import SelectInput11 from "ink-select-input";
19918
19883
  import { jsx as jsx29, jsxs as jsxs27 } from "react/jsx-runtime";
19919
19884
  function RemoteDashboard({ onSelect, onCancel }) {
19920
19885
  const theme = useTheme();
@@ -19922,7 +19887,7 @@ function RemoteDashboard({ onSelect, onCancel }) {
19922
19887
  const [loading, setLoading] = useState17(true);
19923
19888
  const [error, setError] = useState17(null);
19924
19889
  const [refreshing, setRefreshing] = useState17(false);
19925
- useEffect8(() => {
19890
+ useEffect9(() => {
19926
19891
  loadSessions();
19927
19892
  }, []);
19928
19893
  async function loadSessions() {
@@ -19995,7 +19960,7 @@ function RemoteDashboard({ onSelect, onCancel }) {
19995
19960
  refreshing ? "(refreshing...)" : ""
19996
19961
  ] }),
19997
19962
  /* @__PURE__ */ jsx29(Box27, { marginTop: 1, children: /* @__PURE__ */ jsx29(
19998
- SelectInput12,
19963
+ SelectInput11,
19999
19964
  {
20000
19965
  items,
20001
19966
  onSelect: (item) => {
@@ -20385,7 +20350,7 @@ var init_recommended = __esm({
20385
20350
  // src/ui/hooks-wizard.tsx
20386
20351
  import { useState as useState19 } from "react";
20387
20352
  import { Box as Box29, Text as Text30, useInput as useInput14 } from "ink";
20388
- import SelectInput13 from "ink-select-input";
20353
+ import SelectInput12 from "ink-select-input";
20389
20354
  import { jsx as jsx31, jsxs as jsxs29 } from "react/jsx-runtime";
20390
20355
  function HooksWizard(props) {
20391
20356
  const theme = useTheme();
@@ -20442,7 +20407,7 @@ function HooksWizard(props) {
20442
20407
  hint: "The lifecycle moment that fires your command.",
20443
20408
  error,
20444
20409
  children: /* @__PURE__ */ jsx31(
20445
- SelectInput13,
20410
+ SelectInput12,
20446
20411
  {
20447
20412
  items,
20448
20413
  onSelect: (it) => {
@@ -20611,7 +20576,7 @@ global \u2014 lives in ~/.config/kimiflare/settings.json (applies to
20611
20576
  every project)`,
20612
20577
  error,
20613
20578
  children: /* @__PURE__ */ jsx31(
20614
- SelectInput13,
20579
+ SelectInput12,
20615
20580
  {
20616
20581
  items: [
20617
20582
  { label: "project (.kimiflare/settings.json)", value: "project", key: "project" },
@@ -20667,7 +20632,7 @@ global \u2014 lives in ~/.config/kimiflare/settings.json (applies to
20667
20632
  ] })
20668
20633
  ] }),
20669
20634
  /* @__PURE__ */ jsx31(Box29, { marginTop: 1, children: /* @__PURE__ */ jsx31(
20670
- SelectInput13,
20635
+ SelectInput12,
20671
20636
  {
20672
20637
  items: [
20673
20638
  { label: "\u2713 Save", value: "save", key: "save" },
@@ -20762,7 +20727,7 @@ var init_hooks_wizard = __esm({
20762
20727
  // src/ui/hooks-dashboard.tsx
20763
20728
  import { useMemo as useMemo5, useState as useState20 } from "react";
20764
20729
  import { Box as Box30, Text as Text31, useInput as useInput15 } from "ink";
20765
- import SelectInput14 from "ink-select-input";
20730
+ import SelectInput13 from "ink-select-input";
20766
20731
  import { jsx as jsx32, jsxs as jsxs30 } from "react/jsx-runtime";
20767
20732
  function tag(event) {
20768
20733
  return `[${event}]`.padEnd(20);
@@ -20933,7 +20898,7 @@ function HooksDashboard(props) {
20933
20898
  ] }),
20934
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." }) }),
20935
20900
  /* @__PURE__ */ jsx32(Box30, { marginTop: 1, children: /* @__PURE__ */ jsx32(
20936
- SelectInput14,
20901
+ SelectInput13,
20937
20902
  {
20938
20903
  items,
20939
20904
  itemComponent: ColoredRow,
@@ -20988,7 +20953,7 @@ var init_hooks_dashboard = __esm({
20988
20953
 
20989
20954
  // src/ui/modal-host.tsx
20990
20955
  import { Box as Box31, Text as Text32 } from "ink";
20991
- import SelectInput15 from "ink-select-input";
20956
+ import SelectInput14 from "ink-select-input";
20992
20957
  import { jsx as jsx33, jsxs as jsxs31 } from "react/jsx-runtime";
20993
20958
  function ModalHost(props) {
20994
20959
  const {
@@ -21111,7 +21076,7 @@ function ModalHost(props) {
21111
21076
  ] }),
21112
21077
  /* @__PURE__ */ jsx33(Text32, { color: theme.info.color, children: cmd.filepath }),
21113
21078
  /* @__PURE__ */ jsx33(Box31, { marginTop: 1, children: /* @__PURE__ */ jsx33(
21114
- SelectInput15,
21079
+ SelectInput14,
21115
21080
  {
21116
21081
  items: [
21117
21082
  { label: "Yes, delete", value: "yes", key: "yes" },
@@ -25335,7 +25300,7 @@ var app_exports = {};
25335
25300
  __export(app_exports, {
25336
25301
  renderApp: () => renderApp
25337
25302
  });
25338
- 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";
25339
25304
  import { Box as Box32, Text as Text33, useApp, useInput as useInput16, render } from "ink";
25340
25305
  import { existsSync as existsSync8 } from "fs";
25341
25306
  import { join as join35 } from "path";
@@ -25371,7 +25336,7 @@ function App({
25371
25336
  const [input, setInput] = useState23("");
25372
25337
  const [usage, setUsage] = useState23(null);
25373
25338
  const [sessionUsage, setSessionUsage] = useState23(null);
25374
- useEffect9(() => {
25339
+ useEffect10(() => {
25375
25340
  const handler = (sid) => {
25376
25341
  if (sessionIdRef.current && sid === sessionIdRef.current) {
25377
25342
  void getCostReport(sid).then((report) => setSessionUsage(report.session));
@@ -25483,10 +25448,10 @@ function App({
25483
25448
  const [kimiMdStale, setKimiMdStale] = useState23(false);
25484
25449
  const [gitBranch, setGitBranch] = useState23(null);
25485
25450
  const [lastSessionTopic, setLastSessionTopic] = useState23(null);
25486
- useEffect9(() => {
25451
+ useEffect10(() => {
25487
25452
  setGitBranch(detectGitBranch());
25488
25453
  }, []);
25489
- useEffect9(() => {
25454
+ useEffect10(() => {
25490
25455
  void Promise.resolve().then(() => (init_sessions(), sessions_exports)).then(
25491
25456
  ({ listSessions: listSessions2 }) => listSessions2(1).then((sessions) => {
25492
25457
  const last = sessions[0];
@@ -25496,7 +25461,7 @@ function App({
25496
25461
  })
25497
25462
  );
25498
25463
  }, []);
25499
- useEffect9(() => {
25464
+ useEffect10(() => {
25500
25465
  const onSigint = () => {
25501
25466
  logger.info("sigint:fired", {
25502
25467
  hasHandler: sigintHandlerRef.current !== null
@@ -25508,7 +25473,7 @@ function App({
25508
25473
  process.off("SIGINT", onSigint);
25509
25474
  };
25510
25475
  }, []);
25511
- useEffect9(() => {
25476
+ useEffect10(() => {
25512
25477
  let cancelled = false;
25513
25478
  loadAndMergeThemes().then(({ errors, wcagWarnings }) => {
25514
25479
  if (cancelled) return;
@@ -25532,7 +25497,7 @@ ${wcagWarnings.join("\n")}` }
25532
25497
  cancelled = true;
25533
25498
  };
25534
25499
  }, []);
25535
- useEffect9(() => {
25500
+ useEffect10(() => {
25536
25501
  if (!cfg?.cloudMode || !initialCloudToken) return;
25537
25502
  let cancelled = false;
25538
25503
  const fetchBudget = async () => {
@@ -25593,7 +25558,7 @@ ${wcagWarnings.join("\n")}` }
25593
25558
  const lspInitRef = useRef7(false);
25594
25559
  const memoryManagerRef = useRef7(null);
25595
25560
  const hooksManagerRef = useRef7(new HooksManager(process.cwd()));
25596
- useEffect9(() => {
25561
+ useEffect10(() => {
25597
25562
  executorRef.current.setHooks(hooksManagerRef.current);
25598
25563
  return () => executorRef.current.setHooks(null);
25599
25564
  }, []);
@@ -25680,7 +25645,7 @@ ${wcagWarnings.join("\n")}` }
25680
25645
  onSlashSelected: (value) => submitRef.current(value),
25681
25646
  getRecentFiles: () => recentFilesRef.current
25682
25647
  });
25683
- useEffect9(() => {
25648
+ useEffect10(() => {
25684
25649
  if (!cfg) return;
25685
25650
  runStartupTasks({
25686
25651
  cfg,
@@ -25697,7 +25662,7 @@ ${wcagWarnings.join("\n")}` }
25697
25662
  initialCloudDeviceId
25698
25663
  });
25699
25664
  }, [cfg, setEvents]);
25700
- useEffect9(() => {
25665
+ useEffect10(() => {
25701
25666
  const id = setInterval(() => {
25702
25667
  try {
25703
25668
  performance.clearMarks();
@@ -25722,7 +25687,7 @@ ${wcagWarnings.join("\n")}` }
25722
25687
  ]);
25723
25688
  }
25724
25689
  }, [setEvents]);
25725
- useEffect9(() => {
25690
+ useEffect10(() => {
25726
25691
  if (!cfg || updateCheckedRef.current) return;
25727
25692
  updateCheckedRef.current = true;
25728
25693
  if (initialUpdateResult) {
@@ -25773,7 +25738,7 @@ ${wcagWarnings.join("\n")}` }
25773
25738
  }
25774
25739
  });
25775
25740
  }, [cfg, initialUpdateResult]);
25776
- useEffect9(() => {
25741
+ useEffect10(() => {
25777
25742
  modeRef.current = mode;
25778
25743
  if (cacheStableRef.current) {
25779
25744
  messagesRef.current[1] = {
@@ -25800,10 +25765,10 @@ ${wcagWarnings.join("\n")}` }
25800
25765
  executorRef.current.clearSessionPermissions();
25801
25766
  }
25802
25767
  }, [mode, cfg?.model]);
25803
- useEffect9(() => {
25768
+ useEffect10(() => {
25804
25769
  effortRef.current = effort;
25805
25770
  }, [effort]);
25806
- useEffect9(() => {
25771
+ useEffect10(() => {
25807
25772
  if (!cfg) return;
25808
25773
  const id = setInterval(() => {
25809
25774
  void checkForUpdate().then((result) => {
@@ -25866,7 +25831,7 @@ ${wcagWarnings.join("\n")}` }
25866
25831
  lspInitRef
25867
25832
  });
25868
25833
  }, [cfg]);
25869
- useEffect9(() => {
25834
+ useEffect10(() => {
25870
25835
  if (cfg && !mcpInitRef.current) {
25871
25836
  void initMcp2();
25872
25837
  }
@@ -27018,7 +26983,7 @@ ${wcagWarnings.join("\n")}` }
27018
26983
  },
27019
26984
  [cfg, handleSlash, updateAssistant, updateTool, saveSessionSafe, updateGatewayMeta]
27020
26985
  );
27021
- useEffect9(() => {
26986
+ useEffect10(() => {
27022
26987
  if (!busy && queue2.length > 0 && supervisorRef.current.phase === "idle") {
27023
26988
  const next = queue2[0];
27024
26989
  setQueue((q) => q.slice(1));
@@ -27048,7 +27013,7 @@ ${wcagWarnings.join("\n")}` }
27048
27013
  [processMessage]
27049
27014
  );
27050
27015
  submitRef.current = submit;
27051
- useEffect9(() => {
27016
+ useEffect10(() => {
27052
27017
  if (compactSuggestedRef.current) return;
27053
27018
  if (usage && usage.prompt_tokens / modelContextLimit >= AUTO_COMPACT_SUGGEST_PCT) {
27054
27019
  compactSuggestedRef.current = true;