kimiflare 0.92.0 → 0.93.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -17338,38 +17338,19 @@ function formatTokens(n) {
17338
17338
  if (n >= 1e3) return `${(n / 1e3).toFixed(1)}K`;
17339
17339
  return String(n);
17340
17340
  }
17341
- function CloudQuotaMessage({ used, limit, expiresAt, onUpgrade }) {
17341
+ function CloudQuotaMessage({ used, limit, onUpgrade }) {
17342
17342
  const theme = useTheme();
17343
- const expires = expiresAt ? new Date(expiresAt) : null;
17344
- const start = expires ? new Date(expires.getTime() - 7 * 24 * 60 * 60 * 1e3) : null;
17345
- const fmt = (d) => d.toLocaleDateString("en-US", { month: "short", day: "numeric" });
17346
- const dateRange = start && expires ? `${fmt(start)} \u2192 ${fmt(expires)}` : "this week";
17347
17343
  return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", marginY: 1, children: [
17348
- /* @__PURE__ */ jsx5(Text4, { bold: true, color: theme.accent, children: "You've used your free allocation for this week." }),
17344
+ /* @__PURE__ */ jsx5(Text4, { bold: true, color: theme.accent, children: "You've run out of free credits." }),
17349
17345
  /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", marginTop: 1, children: [
17350
- /* @__PURE__ */ jsxs4(Text4, { color: theme.info.color, children: [
17351
- "Free tier ran from ",
17352
- dateRange,
17353
- ", courtesy of Cloudflare"
17346
+ /* @__PURE__ */ jsxs4(Text4, { children: [
17347
+ "\u2192 KimiFlare Pro: ",
17348
+ /* @__PURE__ */ jsx5(Text4, { bold: true, children: "$10/month for 50M tokens" }),
17349
+ onUpgrade ? /* @__PURE__ */ jsx5(Text4, { color: theme.info.color, children: " \xB7 type /upgrade" }) : null
17354
17350
  ] }),
17355
- /* @__PURE__ */ jsx5(Text4, { color: theme.info.color, children: "Workers AI credits. Thanks for trying kimiflare." })
17356
- ] }),
17357
- /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", marginTop: 1, children: [
17358
- /* @__PURE__ */ jsx5(Text4, { bold: true, children: "Upgrade to KimiFlare Pro:" }),
17359
- /* @__PURE__ */ jsxs4(Box4, { paddingLeft: 2, flexDirection: "column", children: [
17360
- /* @__PURE__ */ jsx5(Text4, { color: theme.info.color, children: "\u2192 $10/month founding-user price" }),
17361
- /* @__PURE__ */ jsx5(Text4, { color: theme.info.color, children: "\u2192 Includes ~50M tokens/month (usage allowance)" }),
17362
- /* @__PURE__ */ jsx5(Text4, { color: theme.info.color, children: "\u2192 No Cloudflare account needed" })
17363
- ] }),
17364
- onUpgrade ? /* @__PURE__ */ jsx5(Box4, { marginTop: 1, children: /* @__PURE__ */ jsx5(Text4, { bold: true, color: theme.accent, children: "Press Enter or run /upgrade to subscribe" }) }) : null
17365
- ] }),
17366
- /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", marginTop: 1, children: [
17367
- /* @__PURE__ */ jsx5(Text4, { bold: true, children: "Keep going with your own Cloudflare API key:" }),
17368
- /* @__PURE__ */ jsxs4(Box4, { paddingLeft: 2, flexDirection: "column", children: [
17369
- /* @__PURE__ */ jsx5(Text4, { color: theme.info.color, children: "\u2192 Set one: kimiflare config set-key <your-key>" }),
17370
- /* @__PURE__ */ jsx5(Text4, { color: theme.info.color, children: "\u2192 Get one: https://dash.cloudflare.com/profile/api-tokens" }),
17371
- /* @__PURE__ */ jsx5(Text4, { color: theme.info.color, children: "\u2192 Pricing: https://developers.cloudflare.com/workers-ai/platform/pricing/" }),
17372
- /* @__PURE__ */ jsx5(Text4, { color: theme.muted?.color ?? theme.info.color, dimColor: theme.muted?.dim ?? true, children: "(~$0.95/M input tokens, ~$4.00/M output tokens)" })
17351
+ /* @__PURE__ */ jsxs4(Text4, { children: [
17352
+ "\u2192 Or self-host with your own Cloudflare account: ",
17353
+ /* @__PURE__ */ jsx5(Text4, { color: theme.info.color, children: "kimiflare config set-key <your-key>" })
17373
17354
  ] })
17374
17355
  ] }),
17375
17356
  /* @__PURE__ */ jsx5(Box4, { marginTop: 1, children: /* @__PURE__ */ jsxs4(Text4, { color: theme.muted?.color ?? theme.info.color, dimColor: theme.muted?.dim ?? true, children: [
@@ -17377,7 +17358,7 @@ function CloudQuotaMessage({ used, limit, expiresAt, onUpgrade }) {
17377
17358
  formatTokens(used),
17378
17359
  " / ",
17379
17360
  formatTokens(limit),
17380
- " tokens this week."
17361
+ " tokens."
17381
17362
  ] }) })
17382
17363
  ] });
17383
17364
  }
@@ -17390,37 +17371,20 @@ var init_cloud_quota_message = __esm({
17390
17371
 
17391
17372
  // src/ui/api-error-message.tsx
17392
17373
  import { Box as Box5, Text as Text5 } from "ink";
17393
- import SelectInput from "ink-select-input";
17394
17374
  import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
17395
- function isRetryable2(httpStatus, code) {
17396
- return httpStatus === 429 || code === 3040 || httpStatus !== void 0 && httpStatus >= 500;
17397
- }
17398
- function ApiErrorMessage({ httpStatus, code, message: message2, onRetry }) {
17375
+ function ApiErrorMessage({ httpStatus, code, message: message2 }) {
17399
17376
  const theme = useTheme();
17400
17377
  const parts = [];
17401
17378
  if (httpStatus !== void 0) parts.push(`HTTP ${httpStatus}`);
17402
17379
  if (code !== void 0) parts.push(`code: ${code}`);
17403
17380
  const meta = parts.join(" \xB7 ");
17404
- const retryable = isRetryable2(httpStatus, code);
17405
17381
  return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", borderStyle: "round", borderColor: theme.error, paddingX: 1, marginY: 1, children: [
17406
17382
  /* @__PURE__ */ jsxs5(Text5, { bold: true, color: theme.error, children: [
17407
17383
  "\u26A0 ",
17408
17384
  message2
17409
17385
  ] }),
17410
17386
  meta && /* @__PURE__ */ jsx6(Text5, { color: theme.muted?.color ?? theme.info.color, dimColor: theme.muted?.dim ?? true, children: meta }),
17411
- /* @__PURE__ */ jsx6(Text5, { color: theme.muted?.color ?? theme.info.color, dimColor: theme.muted?.dim ?? true, children: "Type /report to send diagnostic info" }),
17412
- retryable && onRetry && /* @__PURE__ */ jsx6(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx6(
17413
- SelectInput,
17414
- {
17415
- items: [
17416
- { label: "Try again", value: "retry" },
17417
- { label: "Dismiss", value: "dismiss" }
17418
- ],
17419
- onSelect: (item) => {
17420
- if (item.value === "retry") onRetry();
17421
- }
17422
- }
17423
- ) })
17387
+ /* @__PURE__ */ jsx6(Text5, { color: theme.muted?.color ?? theme.info.color, dimColor: theme.muted?.dim ?? true, children: "Type /report to send diagnostic info" })
17424
17388
  ] });
17425
17389
  }
17426
17390
  var init_api_error_message = __esm({
@@ -17472,9 +17436,6 @@ import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
17472
17436
  function toolSignature(name, args) {
17473
17437
  return `${name}:${args}`;
17474
17438
  }
17475
- function isRetryableApiError(evt) {
17476
- return evt.kind === "api_error" && (evt.httpStatus === 429 || evt.code === 3040 || evt.httpStatus !== void 0 && evt.httpStatus >= 500);
17477
- }
17478
17439
  var ChatView, EventView;
17479
17440
  var init_chat = __esm({
17480
17441
  "src/ui/chat.tsx"() {
@@ -17486,7 +17447,7 @@ var init_chat = __esm({
17486
17447
  init_cloud_quota_message();
17487
17448
  init_api_error_message();
17488
17449
  init_service_ended_message();
17489
- ChatView = React4.memo(function ChatView2({ events, showReasoning, verbose, intentTier, onUpgrade, onRetry }) {
17450
+ ChatView = React4.memo(function ChatView2({ events, showReasoning, verbose, intentTier, onUpgrade }) {
17490
17451
  const theme = useTheme();
17491
17452
  const toolCounts = /* @__PURE__ */ new Map();
17492
17453
  for (const e of events) {
@@ -17506,32 +17467,12 @@ var init_chat = __esm({
17506
17467
  break;
17507
17468
  }
17508
17469
  }
17509
- let latestRetryableErrorKey;
17510
- for (let i = events.length - 1; i >= 0; i--) {
17511
- const e = events[i];
17512
- if (isRetryableApiError(e)) {
17513
- latestRetryableErrorKey = e.key;
17514
- break;
17515
- }
17516
- }
17517
17470
  return /* @__PURE__ */ jsx8(Box7, { flexDirection: "column", children: events.map((e, i) => {
17518
17471
  const prev = events[i - 1];
17519
17472
  const showSeparator = !!(prev && (e.kind === "user" && prev.kind !== "user" || e.kind === "assistant" && prev.kind !== "assistant" && prev.kind !== "tool"));
17520
17473
  return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
17521
17474
  showSeparator && /* @__PURE__ */ jsx8(Box7, { marginY: 1, children: /* @__PURE__ */ jsx8(Text7, { color: theme.info.color, children: "\u2500".repeat(40) }) }),
17522
- /* @__PURE__ */ jsx8(
17523
- EventView,
17524
- {
17525
- evt: e,
17526
- showReasoning,
17527
- verbose,
17528
- repeatedSigs,
17529
- intentTier,
17530
- isLastAssistant: i === lastAssistantIndex,
17531
- onUpgrade,
17532
- onRetry: e.key === latestRetryableErrorKey ? onRetry : void 0
17533
- }
17534
- )
17475
+ /* @__PURE__ */ jsx8(EventView, { evt: e, showReasoning, verbose, repeatedSigs, intentTier, isLastAssistant: i === lastAssistantIndex, onUpgrade })
17535
17476
  ] }, e.key);
17536
17477
  }) });
17537
17478
  });
@@ -17542,8 +17483,7 @@ var init_chat = __esm({
17542
17483
  repeatedSigs,
17543
17484
  intentTier,
17544
17485
  isLastAssistant,
17545
- onUpgrade,
17546
- onRetry
17486
+ onUpgrade
17547
17487
  }) {
17548
17488
  const theme = useTheme();
17549
17489
  if (evt.kind === "user") {
@@ -17637,8 +17577,7 @@ var init_chat = __esm({
17637
17577
  {
17638
17578
  httpStatus: evt.httpStatus,
17639
17579
  code: evt.code,
17640
- message: evt.message,
17641
- onRetry: onRetry ? () => onRetry(evt.key) : void 0
17580
+ message: evt.message
17642
17581
  }
17643
17582
  );
17644
17583
  }
@@ -18930,7 +18869,7 @@ var init_fuzzy = __esm({
18930
18869
  // src/ui/resume-picker.tsx
18931
18870
  import { useState as useState6 } from "react";
18932
18871
  import { Box as Box11, Text as Text11, useInput as useInput3 } from "ink";
18933
- import SelectInput2 from "ink-select-input";
18872
+ import SelectInput from "ink-select-input";
18934
18873
  import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
18935
18874
  function ResumePicker({ sessions, onPick }) {
18936
18875
  const theme = useTheme();
@@ -18976,7 +18915,7 @@ function ResumePicker({ sessions, onPick }) {
18976
18915
  /* @__PURE__ */ jsx12(Text11, { color: theme.accent, bold: true, children: "Resume a session" }),
18977
18916
  /* @__PURE__ */ jsx12(Text11, { color: theme.info.color, children: "No saved sessions yet. Press Enter to dismiss." }),
18978
18917
  /* @__PURE__ */ jsx12(Box11, { marginTop: 1, children: /* @__PURE__ */ jsx12(
18979
- SelectInput2,
18918
+ SelectInput,
18980
18919
  {
18981
18920
  items: [{ label: "(back)", value: "__cancel__" }],
18982
18921
  onSelect: () => onPick(null)
@@ -19001,7 +18940,7 @@ function ResumePicker({ sessions, onPick }) {
19001
18940
  " total)"
19002
18941
  ] }),
19003
18942
  /* @__PURE__ */ jsx12(Box11, { marginTop: 1, children: /* @__PURE__ */ jsx12(
19004
- SelectInput2,
18943
+ SelectInput,
19005
18944
  {
19006
18945
  items,
19007
18946
  initialIndex: selectedIndex,
@@ -19048,7 +18987,7 @@ var init_resume_picker = __esm({
19048
18987
  // src/ui/checkpoint-picker.tsx
19049
18988
  import { useState as useState7 } from "react";
19050
18989
  import { Box as Box12, Text as Text12, useInput as useInput4 } from "ink";
19051
- import SelectInput3 from "ink-select-input";
18990
+ import SelectInput2 from "ink-select-input";
19052
18991
  import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
19053
18992
  function CheckpointPicker({ session, checkpoints, onPick }) {
19054
18993
  const theme = useTheme();
@@ -19079,7 +19018,7 @@ function CheckpointPicker({ session, checkpoints, onPick }) {
19079
19018
  checkpoints.length === 1 ? "" : "s"
19080
19019
  ] }),
19081
19020
  /* @__PURE__ */ jsx13(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx13(
19082
- SelectInput3,
19021
+ SelectInput2,
19083
19022
  {
19084
19023
  items,
19085
19024
  initialIndex: selectedIndex,
@@ -19122,7 +19061,7 @@ var init_checkpoint_picker = __esm({
19122
19061
  // src/ui/plan-options-picker.tsx
19123
19062
  import { useState as useState8 } from "react";
19124
19063
  import { Box as Box13, Text as Text13, useInput as useInput5 } from "ink";
19125
- import SelectInput4 from "ink-select-input";
19064
+ import SelectInput3 from "ink-select-input";
19126
19065
  import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
19127
19066
  function PlanOptionsPicker({ options, onPick }) {
19128
19067
  const theme = useTheme();
@@ -19152,7 +19091,7 @@ function PlanOptionsPicker({ options, onPick }) {
19152
19091
  " available"
19153
19092
  ] }),
19154
19093
  /* @__PURE__ */ jsx14(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx14(
19155
- SelectInput4,
19094
+ SelectInput3,
19156
19095
  {
19157
19096
  items,
19158
19097
  initialIndex: selectedIndex,
@@ -19678,7 +19617,7 @@ var init_model_picker = __esm({
19678
19617
 
19679
19618
  // src/ui/billing-chooser.tsx
19680
19619
  import { Box as Box17, Text as Text17, useInput as useInput7 } from "ink";
19681
- import SelectInput5 from "ink-select-input";
19620
+ import SelectInput4 from "ink-select-input";
19682
19621
  import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
19683
19622
  function BillingChooser({ model, onPick }) {
19684
19623
  const theme = useTheme();
@@ -19709,7 +19648,7 @@ function BillingChooser({ model, onPick }) {
19709
19648
  /* @__PURE__ */ jsx18(Text17, { bold: true, children: model.id }),
19710
19649
  ". How would you like to pay for it?"
19711
19650
  ] }) }),
19712
- /* @__PURE__ */ jsx18(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx18(SelectInput5, { items, onSelect: (item) => onPick(item.value) }) }),
19651
+ /* @__PURE__ */ jsx18(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx18(SelectInput4, { items, onSelect: (item) => onPick(item.value) }) }),
19713
19652
  /* @__PURE__ */ jsx18(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx18(Text17, { color: theme.muted?.color ?? theme.info.color, dimColor: true, children: "\u2191/\u2193 select \xB7 Enter \xB7 Esc cancel" }) })
19714
19653
  ]
19715
19654
  }
@@ -19947,7 +19886,7 @@ var init_ai_gateway_api = __esm({
19947
19886
  // src/ui/unified-billing-status.tsx
19948
19887
  import { useEffect as useEffect7, useState as useState12 } from "react";
19949
19888
  import { Box as Box18, Text as Text18, useInput as useInput8 } from "ink";
19950
- import SelectInput6 from "ink-select-input";
19889
+ import SelectInput5 from "ink-select-input";
19951
19890
  import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
19952
19891
  function UnifiedBillingStatus({
19953
19892
  model,
@@ -20061,7 +20000,7 @@ function UnifiedBillingStatus({
20061
20000
  ] }) : null
20062
20001
  ] }),
20063
20002
  /* @__PURE__ */ jsx19(Box18, { marginTop: 1, children: /* @__PURE__ */ jsx19(
20064
- SelectInput6,
20003
+ SelectInput5,
20065
20004
  {
20066
20005
  items: items2,
20067
20006
  onSelect: (item) => {
@@ -20111,7 +20050,7 @@ function UnifiedBillingStatus({
20111
20050
  /* @__PURE__ */ jsx19(Text18, { color: theme.accent, underline: true, children: ` https://dash.cloudflare.com/${accountId}/ai/ai-gateway/gateways/${gatewayId}/logs` })
20112
20051
  ] }) : null,
20113
20052
  /* @__PURE__ */ jsx19(Box18, { marginTop: 1, children: /* @__PURE__ */ jsx19(
20114
- SelectInput6,
20053
+ SelectInput5,
20115
20054
  {
20116
20055
  items,
20117
20056
  onSelect: (item) => {
@@ -20227,7 +20166,7 @@ var init_secrets_store = __esm({
20227
20166
  // src/ui/key-entry-modal.tsx
20228
20167
  import { useState as useState13 } from "react";
20229
20168
  import { Box as Box19, Text as Text19, useInput as useInput9 } from "ink";
20230
- import SelectInput7 from "ink-select-input";
20169
+ import SelectInput6 from "ink-select-input";
20231
20170
  import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
20232
20171
  function maskPreview(value) {
20233
20172
  if (!value) return "";
@@ -20335,7 +20274,7 @@ function KeyEntryModal({
20335
20274
  /* @__PURE__ */ jsx20(Text19, { color: theme.accent, underline: true, children: "https://dash.cloudflare.com/profile/api-tokens" })
20336
20275
  ] }),
20337
20276
  /* @__PURE__ */ jsx20(Box19, { marginTop: 1, children: /* @__PURE__ */ jsx20(
20338
- SelectInput7,
20277
+ SelectInput6,
20339
20278
  {
20340
20279
  items: fallbackItems,
20341
20280
  onSelect: (item) => {
@@ -20367,7 +20306,7 @@ function KeyEntryModal({
20367
20306
  /* @__PURE__ */ jsx20(Text19, { color: theme.accent, bold: true, children: "Couldn't store the key." }),
20368
20307
  /* @__PURE__ */ jsx20(Box19, { marginTop: 1, children: /* @__PURE__ */ jsx20(Text19, { color: theme.info.color, children: phase.message }) }),
20369
20308
  /* @__PURE__ */ jsx20(Box19, { marginTop: 1, children: /* @__PURE__ */ jsx20(
20370
- SelectInput7,
20309
+ SelectInput6,
20371
20310
  {
20372
20311
  items: [
20373
20312
  { label: "Try again", value: "retry" },
@@ -20472,7 +20411,8 @@ import { Box as Box20, Text as Text20, useInput as useInput10 } from "ink";
20472
20411
  import { Fragment, jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
20473
20412
  function Onboarding({ onDone, onCancel }) {
20474
20413
  const theme = useTheme();
20475
- const [step, setStep] = useState14("accountId");
20414
+ const [step, setStep] = useState14("mode");
20415
+ const [modePickIdx, setModePickIdx] = useState14(0);
20476
20416
  const [accountId, setAccountId] = useState14("");
20477
20417
  const [apiToken, setApiToken] = useState14("");
20478
20418
  const [model, setModel] = useState14(DEFAULT_MODEL);
@@ -20504,6 +20444,23 @@ function Onboarding({ onDone, onCancel }) {
20504
20444
  [onCancel]
20505
20445
  )
20506
20446
  );
20447
+ useInput10(
20448
+ (_input, key) => {
20449
+ if (step !== "mode") return;
20450
+ const total = 2;
20451
+ if (key.upArrow) {
20452
+ setModePickIdx((i) => (i - 1 + total) % total);
20453
+ } else if (key.downArrow) {
20454
+ setModePickIdx((i) => (i + 1) % total);
20455
+ } else if (key.return) {
20456
+ if (modePickIdx === 0) {
20457
+ startCloudAuth();
20458
+ } else {
20459
+ setStep("accountId");
20460
+ }
20461
+ }
20462
+ }
20463
+ );
20507
20464
  useInput10(
20508
20465
  (_input, key) => {
20509
20466
  if (step !== "routingMode") return;
@@ -20619,6 +20576,22 @@ function Onboarding({ onDone, onCancel }) {
20619
20576
  if (!trimmed) return;
20620
20577
  void runProbe(trimmed);
20621
20578
  };
20579
+ const startCloudAuth = () => {
20580
+ setStep("cloudAuth");
20581
+ setCloudAuthError(null);
20582
+ void Promise.resolve().then(() => (init_auth(), auth_exports)).then(({ authenticateDevice: authenticateDevice2 }) => {
20583
+ authenticateDevice2((status) => {
20584
+ setCloudAuthStatus(status);
20585
+ }).then(() => {
20586
+ setCloudMode(true);
20587
+ setAccountId("");
20588
+ setApiToken("");
20589
+ setStep("confirm");
20590
+ }).catch((err) => {
20591
+ setCloudAuthError(err instanceof Error ? err.message : String(err));
20592
+ });
20593
+ });
20594
+ };
20622
20595
  const handleModelPick = (picked) => {
20623
20596
  if (!picked) {
20624
20597
  setStep("confirm");
@@ -20626,7 +20599,9 @@ function Onboarding({ onDone, onCancel }) {
20626
20599
  }
20627
20600
  setModel(picked.id);
20628
20601
  setPickedEntry(picked);
20629
- if (picked.provider === "workers-ai" || isUnifiedEligible(picked)) {
20602
+ if (picked.provider === "workers-ai") {
20603
+ setStep("confirm");
20604
+ } else if (isUnifiedEligible(picked)) {
20630
20605
  setStep("billingChoice");
20631
20606
  } else {
20632
20607
  setStep("keyEntry");
@@ -20634,24 +20609,7 @@ function Onboarding({ onDone, onCancel }) {
20634
20609
  };
20635
20610
  const handleBillingChoice = (choice) => {
20636
20611
  if (!choice) {
20637
- setStep("keyEntry");
20638
- return;
20639
- }
20640
- if (choice === "cloud") {
20641
- setStep("cloudAuth");
20642
- setCloudAuthError(null);
20643
- void Promise.resolve().then(() => (init_auth(), auth_exports)).then(({ authenticateDevice: authenticateDevice2 }) => {
20644
- authenticateDevice2((status) => {
20645
- setCloudAuthStatus(status);
20646
- }).then(() => {
20647
- setCloudMode(true);
20648
- setAccountId("");
20649
- setApiToken("");
20650
- setStep("confirm");
20651
- }).catch((err) => {
20652
- setCloudAuthError(err instanceof Error ? err.message : String(err));
20653
- });
20654
- });
20612
+ setStep("model");
20655
20613
  return;
20656
20614
  }
20657
20615
  setStep(choice === "unified" ? "unifiedProbe" : "keyEntry");
@@ -20704,7 +20662,7 @@ function Onboarding({ onDone, onCancel }) {
20704
20662
  setSavedPath(`error: ${e.message}`);
20705
20663
  }
20706
20664
  };
20707
- const visibleSteps = ["accountId", "apiToken", "routingMode", "model", "confirm"];
20665
+ const visibleSteps = ["mode", "accountId", "apiToken", "routingMode", "model", "confirm"];
20708
20666
  const stepIndex = Math.max(1, visibleSteps.indexOf(step) === -1 ? 3 : visibleSteps.indexOf(step) + 1);
20709
20667
  const totalSteps = visibleSteps.length;
20710
20668
  return /* @__PURE__ */ jsxs19(Box20, { flexDirection: "column", paddingY: 1, children: [
@@ -20722,6 +20680,29 @@ function Onboarding({ onDone, onCancel }) {
20722
20680
  totalSteps
20723
20681
  ] }),
20724
20682
  /* @__PURE__ */ jsxs19(Box20, { marginTop: 1, flexDirection: "column", children: [
20683
+ step === "mode" && /* @__PURE__ */ jsxs19(Fragment, { children: [
20684
+ /* @__PURE__ */ jsx21(Text20, { children: "How do you want to run kimiflare?" }),
20685
+ /* @__PURE__ */ jsx21(Text20, { color: theme.info.color, children: "Use \u2191/\u2193 to navigate, Enter to select." }),
20686
+ /* @__PURE__ */ jsxs19(Box20, { flexDirection: "column", marginTop: 1, children: [
20687
+ /* @__PURE__ */ jsxs19(Text20, { color: modePickIdx === 0 ? theme.palette.primary : void 0, children: [
20688
+ modePickIdx === 0 ? "\u203A " : " ",
20689
+ "KimiFlare Cloud \u2014 5,000,000 tokens free"
20690
+ ] }),
20691
+ /* @__PURE__ */ jsxs19(Text20, { color: theme.info.color, dimColor: true, children: [
20692
+ " ",
20693
+ "Sign in with GitHub or email. No Cloudflare account needed. Upgrade to Pro when you run out."
20694
+ ] }),
20695
+ /* @__PURE__ */ jsx21(Text20, { children: " " }),
20696
+ /* @__PURE__ */ jsxs19(Text20, { color: modePickIdx === 1 ? theme.palette.primary : void 0, children: [
20697
+ modePickIdx === 1 ? "\u203A " : " ",
20698
+ "Self-hosted \u2014 bring your own Cloudflare account"
20699
+ ] }),
20700
+ /* @__PURE__ */ jsxs19(Text20, { color: theme.info.color, dimColor: true, children: [
20701
+ " ",
20702
+ "Use your Cloudflare Account ID + API token, then pick Workers AI (direct) or AI Gateway."
20703
+ ] })
20704
+ ] })
20705
+ ] }),
20725
20706
  step === "accountId" && /* @__PURE__ */ jsxs19(Fragment, { children: [
20726
20707
  /* @__PURE__ */ jsx21(Text20, { children: "Enter your Cloudflare Account ID" }),
20727
20708
  /* @__PURE__ */ jsxs19(Box20, { marginTop: 1, children: [
@@ -20909,22 +20890,24 @@ function Onboarding({ onDone, onCancel }) {
20909
20890
  borderColor: theme.info.color,
20910
20891
  paddingX: 1,
20911
20892
  children: [
20912
- /* @__PURE__ */ jsxs19(Text20, { color: theme.info.color, children: [
20913
- "Account ID: ",
20914
- accountId
20915
- ] }),
20916
- /* @__PURE__ */ jsxs19(Text20, { color: theme.info.color, children: [
20917
- "API Token: ",
20918
- "\u2022".repeat(apiToken.length)
20893
+ !cloudMode && /* @__PURE__ */ jsxs19(Fragment, { children: [
20894
+ /* @__PURE__ */ jsxs19(Text20, { color: theme.info.color, children: [
20895
+ "Account ID: ",
20896
+ accountId
20897
+ ] }),
20898
+ /* @__PURE__ */ jsxs19(Text20, { color: theme.info.color, children: [
20899
+ "API Token: ",
20900
+ "\u2022".repeat(apiToken.length)
20901
+ ] })
20919
20902
  ] }),
20920
20903
  /* @__PURE__ */ jsxs19(Text20, { color: theme.info.color, children: [
20921
20904
  "Model: ",
20922
20905
  model
20923
20906
  ] }),
20924
- aiGatewayId ? /* @__PURE__ */ jsxs19(Text20, { color: theme.info.color, children: [
20907
+ !cloudMode && (aiGatewayId ? /* @__PURE__ */ jsxs19(Text20, { color: theme.info.color, children: [
20925
20908
  "AI Gateway: ",
20926
20909
  aiGatewayId
20927
- ] }) : /* @__PURE__ */ jsx21(Text20, { color: theme.info.color, children: "Routing: Workers AI (direct)" }),
20910
+ ] }) : /* @__PURE__ */ jsx21(Text20, { color: theme.info.color, children: "Routing: Workers AI (direct)" })),
20928
20911
  cloudMode && /* @__PURE__ */ jsx21(Text20, { color: theme.info.color, children: "Billing: KimiFlare Cloud (free 5M tokens, then $10/mo Pro)" }),
20929
20912
  unifiedBilling && /* @__PURE__ */ jsx21(Text20, { color: theme.info.color, children: "Billing: Cloudflare credits (Unified Billing)" }),
20930
20913
  Object.keys(providerKeyAliases).length > 0 && /* @__PURE__ */ jsxs19(Text20, { color: theme.info.color, children: [
@@ -23134,7 +23117,7 @@ var init_use_modal_host = __esm({
23134
23117
 
23135
23118
  // src/ui/limit-modal.tsx
23136
23119
  import { Box as Box24, Text as Text24 } from "ink";
23137
- import SelectInput8 from "ink-select-input";
23120
+ import SelectInput7 from "ink-select-input";
23138
23121
  import { jsx as jsx25, jsxs as jsxs23 } from "react/jsx-runtime";
23139
23122
  function LimitModal({ limit, onDecide, title, description, items }) {
23140
23123
  const theme = useTheme();
@@ -23147,7 +23130,7 @@ function LimitModal({ limit, onDecide, title, description, items }) {
23147
23130
  /* @__PURE__ */ jsx25(Text24, { color: theme.error, bold: true, children: title ?? `Tool-call limit reached (${limit})` }),
23148
23131
  /* @__PURE__ */ jsx25(Text24, { dimColor: true, children: description ?? `This session has made ${limit} tool calls. What would you like to do?` }),
23149
23132
  /* @__PURE__ */ jsx25(Box24, { marginTop: 1, children: /* @__PURE__ */ jsx25(
23150
- SelectInput8,
23133
+ SelectInput7,
23151
23134
  {
23152
23135
  items: selectItems,
23153
23136
  onSelect: (item) => onDecide(item.value)
@@ -23165,7 +23148,7 @@ var init_limit_modal = __esm({
23165
23148
  // src/ui/command-wizard.tsx
23166
23149
  import { useState as useState17 } from "react";
23167
23150
  import { Box as Box25, Text as Text25, useInput as useInput11, useWindowSize } from "ink";
23168
- import SelectInput9 from "ink-select-input";
23151
+ import SelectInput8 from "ink-select-input";
23169
23152
  import { Fragment as Fragment2, jsx as jsx26, jsxs as jsxs24 } from "react/jsx-runtime";
23170
23153
  function CommandWizard({ mode, initial, existingNames, builtinNames, onDone, onSave }) {
23171
23154
  const theme = useTheme();
@@ -23418,7 +23401,7 @@ ${template}`;
23418
23401
  ")"
23419
23402
  ] }),
23420
23403
  /* @__PURE__ */ jsx26(Box25, { marginTop: 1, children: /* @__PURE__ */ jsx26(
23421
- SelectInput9,
23404
+ SelectInput8,
23422
23405
  {
23423
23406
  items,
23424
23407
  onSelect: (item) => {
@@ -23447,7 +23430,7 @@ ${template}`;
23447
23430
  ] }),
23448
23431
  /* @__PURE__ */ jsx26(Text25, { color: theme.info.color, children: "Saved to file but not yet enforced at runtime" }),
23449
23432
  /* @__PURE__ */ jsx26(Box25, { marginTop: 1, children: /* @__PURE__ */ jsx26(
23450
- SelectInput9,
23433
+ SelectInput8,
23451
23434
  {
23452
23435
  items,
23453
23436
  onSelect: (item) => {
@@ -23475,7 +23458,7 @@ ${template}`;
23475
23458
  ")"
23476
23459
  ] }),
23477
23460
  /* @__PURE__ */ jsx26(Box25, { marginTop: 1, children: /* @__PURE__ */ jsx26(
23478
- SelectInput9,
23461
+ SelectInput8,
23479
23462
  {
23480
23463
  items,
23481
23464
  onSelect: (item) => {
@@ -23521,7 +23504,7 @@ ${template}`;
23521
23504
  ")"
23522
23505
  ] }),
23523
23506
  /* @__PURE__ */ jsx26(Box25, { marginTop: 1, children: /* @__PURE__ */ jsx26(
23524
- SelectInput9,
23507
+ SelectInput8,
23525
23508
  {
23526
23509
  items,
23527
23510
  onSelect: (item) => {
@@ -23554,7 +23537,7 @@ ${template}`;
23554
23537
  ] }),
23555
23538
  /* @__PURE__ */ jsx26(Box25, { marginTop: 1, flexDirection: "column", children: previewContent().split("\n").map((line, i) => /* @__PURE__ */ jsx26(Text25, { color: theme.info.color, children: line || " " }, i)) }),
23556
23539
  /* @__PURE__ */ jsx26(Box25, { marginTop: 1, children: /* @__PURE__ */ jsx26(
23557
- SelectInput9,
23540
+ SelectInput8,
23558
23541
  {
23559
23542
  items,
23560
23543
  onSelect: (item) => handleConfirm(item.value)
@@ -23578,7 +23561,7 @@ var init_command_wizard = __esm({
23578
23561
 
23579
23562
  // src/ui/command-picker.tsx
23580
23563
  import { Box as Box26, Text as Text26 } from "ink";
23581
- import SelectInput10 from "ink-select-input";
23564
+ import SelectInput9 from "ink-select-input";
23582
23565
  import { jsx as jsx27, jsxs as jsxs25 } from "react/jsx-runtime";
23583
23566
  function CommandPicker({ commands, title, onPick }) {
23584
23567
  const theme = useTheme();
@@ -23592,7 +23575,7 @@ function CommandPicker({ commands, title, onPick }) {
23592
23575
  /* @__PURE__ */ jsx27(Text26, { color: theme.accent, bold: true, children: title }),
23593
23576
  /* @__PURE__ */ jsx27(Text26, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select." }),
23594
23577
  /* @__PURE__ */ jsx27(Box26, { marginTop: 1, children: /* @__PURE__ */ jsx27(
23595
- SelectInput10,
23578
+ SelectInput9,
23596
23579
  {
23597
23580
  items,
23598
23581
  onSelect: (item) => {
@@ -23689,7 +23672,7 @@ var init_command_list = __esm({
23689
23672
  // src/ui/lsp-wizard.tsx
23690
23673
  import { useState as useState18 } from "react";
23691
23674
  import { Box as Box28, Text as Text28 } from "ink";
23692
- import SelectInput11 from "ink-select-input";
23675
+ import SelectInput10 from "ink-select-input";
23693
23676
  import { spawn as spawn4 } from "child_process";
23694
23677
  import { jsx as jsx29, jsxs as jsxs27 } from "react/jsx-runtime";
23695
23678
  function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
@@ -23807,7 +23790,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
23807
23790
  /* @__PURE__ */ jsx29(Text28, { color: theme.accent, bold: true, children: "LSP Servers" }),
23808
23791
  /* @__PURE__ */ jsx29(Text28, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select." }),
23809
23792
  /* @__PURE__ */ jsx29(Box28, { marginTop: 1, children: /* @__PURE__ */ jsx29(
23810
- SelectInput11,
23793
+ SelectInput10,
23811
23794
  {
23812
23795
  items: mainItems,
23813
23796
  onSelect: (item) => {
@@ -23838,7 +23821,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
23838
23821
  /* @__PURE__ */ jsx29(Text28, { color: theme.accent, bold: true, children: "Add LSP Server" }),
23839
23822
  /* @__PURE__ */ jsx29(Text28, { color: theme.info.color, dimColor: false, children: "Select a language server to configure." }),
23840
23823
  /* @__PURE__ */ jsx29(Box28, { marginTop: 1, children: /* @__PURE__ */ jsx29(
23841
- SelectInput11,
23824
+ SelectInput10,
23842
23825
  {
23843
23826
  items,
23844
23827
  onSelect: (item) => {
@@ -23877,7 +23860,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
23877
23860
  ] }),
23878
23861
  installState.output && /* @__PURE__ */ jsx29(Box28, { marginTop: 1, flexDirection: "column", children: /* @__PURE__ */ jsx29(Text28, { color: isSuccess ? theme.accent : theme.error, children: installState.output.slice(-500) }) }),
23879
23862
  /* @__PURE__ */ jsx29(Box28, { marginTop: 1, children: /* @__PURE__ */ jsx29(
23880
- SelectInput11,
23863
+ SelectInput10,
23881
23864
  {
23882
23865
  items,
23883
23866
  onSelect: (item) => {
@@ -23918,7 +23901,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
23918
23901
  )
23919
23902
  ] }),
23920
23903
  /* @__PURE__ */ jsx29(Box28, { marginTop: 1, children: /* @__PURE__ */ jsx29(
23921
- SelectInput11,
23904
+ SelectInput10,
23922
23905
  {
23923
23906
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
23924
23907
  onSelect: () => setPage("add")
@@ -23947,7 +23930,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
23947
23930
  )
23948
23931
  ] }),
23949
23932
  /* @__PURE__ */ jsx29(Box28, { marginTop: 1, children: /* @__PURE__ */ jsx29(
23950
- SelectInput11,
23933
+ SelectInput10,
23951
23934
  {
23952
23935
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
23953
23936
  onSelect: () => setPage("custom-name")
@@ -23974,7 +23957,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
23974
23957
  /* @__PURE__ */ jsx29(Text28, { color: theme.accent, bold: true, children: "Save LSP Config" }),
23975
23958
  /* @__PURE__ */ jsx29(Text28, { color: theme.info.color, dimColor: false, children: "Where should this server configuration be saved?" }),
23976
23959
  /* @__PURE__ */ jsx29(Box28, { marginTop: 1, children: /* @__PURE__ */ jsx29(
23977
- SelectInput11,
23960
+ SelectInput10,
23978
23961
  {
23979
23962
  items,
23980
23963
  onSelect: (item) => {
@@ -23996,7 +23979,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
23996
23979
  /* @__PURE__ */ jsx29(Text28, { color: theme.accent, bold: true, children: "Edit LSP Server" }),
23997
23980
  /* @__PURE__ */ jsx29(Text28, { color: theme.info.color, children: "No servers configured." }),
23998
23981
  /* @__PURE__ */ jsx29(Box28, { marginTop: 1, children: /* @__PURE__ */ jsx29(
23999
- SelectInput11,
23982
+ SelectInput10,
24000
23983
  {
24001
23984
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
24002
23985
  onSelect: () => setPage("main")
@@ -24020,7 +24003,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
24020
24003
  /* @__PURE__ */ jsx29(Text28, { color: theme.accent, bold: true, children: "Edit LSP Server" }),
24021
24004
  /* @__PURE__ */ jsx29(Text28, { color: theme.info.color, dimColor: false, children: "Select a server to toggle enabled/disabled." }),
24022
24005
  /* @__PURE__ */ jsx29(Box28, { marginTop: 1, children: /* @__PURE__ */ jsx29(
24023
- SelectInput11,
24006
+ SelectInput10,
24024
24007
  {
24025
24008
  items,
24026
24009
  onSelect: (item) => {
@@ -24041,7 +24024,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
24041
24024
  /* @__PURE__ */ jsx29(Text28, { color: theme.accent, bold: true, children: "Delete LSP Server" }),
24042
24025
  /* @__PURE__ */ jsx29(Text28, { color: theme.info.color, children: "No servers configured." }),
24043
24026
  /* @__PURE__ */ jsx29(Box28, { marginTop: 1, children: /* @__PURE__ */ jsx29(
24044
- SelectInput11,
24027
+ SelectInput10,
24045
24028
  {
24046
24029
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
24047
24030
  onSelect: () => setPage("main")
@@ -24061,7 +24044,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
24061
24044
  /* @__PURE__ */ jsx29(Text28, { color: theme.accent, bold: true, children: "Delete LSP Server" }),
24062
24045
  /* @__PURE__ */ jsx29(Text28, { color: theme.info.color, dimColor: false, children: "Select a server to remove from config." }),
24063
24046
  /* @__PURE__ */ jsx29(Box28, { marginTop: 1, children: /* @__PURE__ */ jsx29(
24064
- SelectInput11,
24047
+ SelectInput10,
24065
24048
  {
24066
24049
  items,
24067
24050
  onSelect: (item) => {
@@ -24085,7 +24068,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
24085
24068
  return /* @__PURE__ */ jsx29(Text28, { color: theme.info.color, children: ` ${k.padEnd(16)} ${status} ${s.command.join(" ")}` }, k);
24086
24069
  }) }),
24087
24070
  /* @__PURE__ */ jsx29(Box28, { marginTop: 1, children: /* @__PURE__ */ jsx29(
24088
- SelectInput11,
24071
+ SelectInput10,
24089
24072
  {
24090
24073
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
24091
24074
  onSelect: () => setPage("main")
@@ -24213,7 +24196,7 @@ var init_lsp_wizard = __esm({
24213
24196
 
24214
24197
  // src/ui/theme-picker.tsx
24215
24198
  import { Box as Box29, Text as Text29 } from "ink";
24216
- import SelectInput12 from "ink-select-input";
24199
+ import SelectInput11 from "ink-select-input";
24217
24200
  import { jsx as jsx30, jsxs as jsxs28 } from "react/jsx-runtime";
24218
24201
  function PaletteSwatches({ palette }) {
24219
24202
  const colors = [
@@ -24233,7 +24216,7 @@ function ThemePicker({ themes, onPick }) {
24233
24216
  return /* @__PURE__ */ jsxs28(Box29, { flexDirection: "column", borderStyle: "round", borderColor: current.accent, paddingX: 1, children: [
24234
24217
  /* @__PURE__ */ jsx30(Text29, { color: current.accent, bold: true, children: "Pick a theme (restart to apply)" }),
24235
24218
  /* @__PURE__ */ jsx30(Box29, { marginTop: 1, children: /* @__PURE__ */ jsx30(
24236
- SelectInput12,
24219
+ SelectInput11,
24237
24220
  {
24238
24221
  items,
24239
24222
  onSelect: (item) => {
@@ -24265,7 +24248,7 @@ var init_theme_picker = __esm({
24265
24248
 
24266
24249
  // src/ui/ui-picker.tsx
24267
24250
  import { Box as Box30, Text as Text30 } from "ink";
24268
- import SelectInput13 from "ink-select-input";
24251
+ import SelectInput12 from "ink-select-input";
24269
24252
  import { jsx as jsx31, jsxs as jsxs29 } from "react/jsx-runtime";
24270
24253
  function UiPicker({ current, onPick }) {
24271
24254
  const theme = useTheme();
@@ -24280,7 +24263,7 @@ function UiPicker({ current, onPick }) {
24280
24263
  return /* @__PURE__ */ jsxs29(Box30, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
24281
24264
  /* @__PURE__ */ jsx31(Text30, { color: theme.accent, bold: true, children: "Pick UI engine (takes effect on next launch)" }),
24282
24265
  /* @__PURE__ */ jsx31(Box30, { marginTop: 1, children: /* @__PURE__ */ jsx31(
24283
- SelectInput13,
24266
+ SelectInput12,
24284
24267
  {
24285
24268
  items,
24286
24269
  initialIndex: items.findIndex((i) => i.value === current),
@@ -24312,7 +24295,7 @@ var init_ui_picker = __esm({
24312
24295
 
24313
24296
  // src/ui/mode-picker.tsx
24314
24297
  import { Box as Box31, Text as Text31 } from "ink";
24315
- import SelectInput14 from "ink-select-input";
24298
+ import SelectInput13 from "ink-select-input";
24316
24299
  import { jsx as jsx32, jsxs as jsxs30 } from "react/jsx-runtime";
24317
24300
  function ModePicker({ current, onPick }) {
24318
24301
  const theme = useTheme();
@@ -24326,7 +24309,7 @@ function ModePicker({ current, onPick }) {
24326
24309
  /* @__PURE__ */ jsx32(Text31, { color: theme.accent, bold: true, children: "Select mode" }),
24327
24310
  /* @__PURE__ */ jsx32(Text31, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select, Esc to cancel." }),
24328
24311
  /* @__PURE__ */ jsx32(Box31, { marginTop: 1, children: /* @__PURE__ */ jsx32(
24329
- SelectInput14,
24312
+ SelectInput13,
24330
24313
  {
24331
24314
  items,
24332
24315
  onSelect: (item) => onPick(item.value)
@@ -24344,7 +24327,7 @@ var init_mode_picker = __esm({
24344
24327
 
24345
24328
  // src/ui/shell-picker.tsx
24346
24329
  import { Box as Box32, Text as Text32 } from "ink";
24347
- import SelectInput15 from "ink-select-input";
24330
+ import SelectInput14 from "ink-select-input";
24348
24331
  import { jsx as jsx33, jsxs as jsxs31 } from "react/jsx-runtime";
24349
24332
  function ShellPicker({ current, onPick }) {
24350
24333
  const theme = useTheme();
@@ -24356,7 +24339,7 @@ function ShellPicker({ current, onPick }) {
24356
24339
  return /* @__PURE__ */ jsxs31(Box32, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
24357
24340
  /* @__PURE__ */ jsx33(Text32, { color: theme.accent, bold: true, children: "Select shell" }),
24358
24341
  /* @__PURE__ */ jsx33(Text32, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select, Esc to cancel." }),
24359
- /* @__PURE__ */ jsx33(Box32, { marginTop: 1, children: /* @__PURE__ */ jsx33(SelectInput15, { items, onSelect: (item) => onPick(item.value) }) })
24342
+ /* @__PURE__ */ jsx33(Box32, { marginTop: 1, children: /* @__PURE__ */ jsx33(SelectInput14, { items, onSelect: (item) => onPick(item.value) }) })
24360
24343
  ] });
24361
24344
  }
24362
24345
  var SHELLS;
@@ -24376,7 +24359,7 @@ var init_shell_picker = __esm({
24376
24359
  // src/ui/memory-picker.tsx
24377
24360
  import { useState as useState19, useCallback as useCallback5 } from "react";
24378
24361
  import { Box as Box33, Text as Text33, useInput as useInput13 } from "ink";
24379
- import SelectInput16 from "ink-select-input";
24362
+ import SelectInput15 from "ink-select-input";
24380
24363
  import { jsx as jsx34, jsxs as jsxs32 } from "react/jsx-runtime";
24381
24364
  function MemoryPicker({ enabled, memoryManager, onAction, onDone }) {
24382
24365
  const theme = useTheme();
@@ -24418,7 +24401,7 @@ function MemoryPicker({ enabled, memoryManager, onAction, onDone }) {
24418
24401
  /* @__PURE__ */ jsx34(Text33, { color: theme.accent, bold: true, children: "\u26A0\uFE0F Clear All Memories" }),
24419
24402
  /* @__PURE__ */ jsx34(Text33, { color: theme.info.color, children: "This will permanently delete every stored memory. This cannot be undone." }),
24420
24403
  /* @__PURE__ */ jsx34(Box33, { marginTop: 1, children: /* @__PURE__ */ jsx34(
24421
- SelectInput16,
24404
+ SelectInput15,
24422
24405
  {
24423
24406
  items: [
24424
24407
  { label: "Yes, clear everything", value: "yes", key: "yes" },
@@ -24486,7 +24469,7 @@ function MemoryPicker({ enabled, memoryManager, onAction, onDone }) {
24486
24469
  /* @__PURE__ */ jsx34(Text33, { color: theme.accent, bold: true, children: "Memory" }),
24487
24470
  /* @__PURE__ */ jsx34(Text33, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select, Esc to close." }),
24488
24471
  /* @__PURE__ */ jsx34(Box33, { marginTop: 1, children: /* @__PURE__ */ jsx34(
24489
- SelectInput16,
24472
+ SelectInput15,
24490
24473
  {
24491
24474
  items,
24492
24475
  onSelect: (item) => {
@@ -24518,7 +24501,7 @@ var init_memory_picker = __esm({
24518
24501
 
24519
24502
  // src/ui/gateway-picker.tsx
24520
24503
  import { Box as Box34, Text as Text34 } from "ink";
24521
- import SelectInput17 from "ink-select-input";
24504
+ import SelectInput16 from "ink-select-input";
24522
24505
  import { jsx as jsx35, jsxs as jsxs33 } from "react/jsx-runtime";
24523
24506
  function GatewayPicker({ gatewayId, skipCache, collectLogs, metadataCount, onAction, onDone }) {
24524
24507
  const theme = useTheme();
@@ -24563,7 +24546,7 @@ function GatewayPicker({ gatewayId, skipCache, collectLogs, metadataCount, onAct
24563
24546
  /* @__PURE__ */ jsx35(Text34, { color: theme.accent, bold: true, children: "AI Gateway" }),
24564
24547
  /* @__PURE__ */ jsx35(Text34, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select, Esc to close." }),
24565
24548
  /* @__PURE__ */ jsx35(Box34, { marginTop: 1, children: /* @__PURE__ */ jsx35(
24566
- SelectInput17,
24549
+ SelectInput16,
24567
24550
  {
24568
24551
  items: selectable,
24569
24552
  onSelect: (item) => {
@@ -24586,7 +24569,7 @@ var init_gateway_picker = __esm({
24586
24569
 
24587
24570
  // src/ui/skills-picker.tsx
24588
24571
  import { Box as Box35, Text as Text35 } from "ink";
24589
- import SelectInput18 from "ink-select-input";
24572
+ import SelectInput17 from "ink-select-input";
24590
24573
  import { jsx as jsx36, jsxs as jsxs34 } from "react/jsx-runtime";
24591
24574
  function SkillsPicker({ onAction, onDone }) {
24592
24575
  const theme = useTheme();
@@ -24603,7 +24586,7 @@ function SkillsPicker({ onAction, onDone }) {
24603
24586
  /* @__PURE__ */ jsx36(Text35, { color: theme.accent, bold: true, children: "Skills" }),
24604
24587
  /* @__PURE__ */ jsx36(Text35, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select, Esc to close." }),
24605
24588
  /* @__PURE__ */ jsx36(Box35, { marginTop: 1, children: /* @__PURE__ */ jsx36(
24606
- SelectInput18,
24589
+ SelectInput17,
24607
24590
  {
24608
24591
  items,
24609
24592
  onSelect: (item) => {
@@ -24722,7 +24705,7 @@ var init_worker_client = __esm({
24722
24705
  // src/ui/remote-dashboard.tsx
24723
24706
  import { useEffect as useEffect10, useState as useState20 } from "react";
24724
24707
  import { Box as Box36, Text as Text36, useInput as useInput14 } from "ink";
24725
- import SelectInput19 from "ink-select-input";
24708
+ import SelectInput18 from "ink-select-input";
24726
24709
  import { jsx as jsx37, jsxs as jsxs35 } from "react/jsx-runtime";
24727
24710
  function RemoteDashboard({ onSelect, onCancel }) {
24728
24711
  const theme = useTheme();
@@ -24803,7 +24786,7 @@ function RemoteDashboard({ onSelect, onCancel }) {
24803
24786
  refreshing ? "(refreshing...)" : ""
24804
24787
  ] }),
24805
24788
  /* @__PURE__ */ jsx37(Box36, { marginTop: 1, children: /* @__PURE__ */ jsx37(
24806
- SelectInput19,
24789
+ SelectInput18,
24807
24790
  {
24808
24791
  items,
24809
24792
  onSelect: (item) => {
@@ -26376,7 +26359,7 @@ var init_recommended = __esm({
26376
26359
  // src/ui/hooks-wizard.tsx
26377
26360
  import { useState as useState23 } from "react";
26378
26361
  import { Box as Box39, Text as Text39, useInput as useInput17 } from "ink";
26379
- import SelectInput20 from "ink-select-input";
26362
+ import SelectInput19 from "ink-select-input";
26380
26363
  import { jsx as jsx40, jsxs as jsxs38 } from "react/jsx-runtime";
26381
26364
  function HooksWizard(props) {
26382
26365
  const theme = useTheme();
@@ -26433,7 +26416,7 @@ function HooksWizard(props) {
26433
26416
  hint: "The lifecycle moment that fires your command.",
26434
26417
  error,
26435
26418
  children: /* @__PURE__ */ jsx40(
26436
- SelectInput20,
26419
+ SelectInput19,
26437
26420
  {
26438
26421
  items,
26439
26422
  onSelect: (it) => {
@@ -26602,7 +26585,7 @@ global \u2014 lives in ~/.config/kimiflare/settings.json (applies to
26602
26585
  every project)`,
26603
26586
  error,
26604
26587
  children: /* @__PURE__ */ jsx40(
26605
- SelectInput20,
26588
+ SelectInput19,
26606
26589
  {
26607
26590
  items: [
26608
26591
  { label: "project (.kimiflare/settings.json)", value: "project", key: "project" },
@@ -26658,7 +26641,7 @@ global \u2014 lives in ~/.config/kimiflare/settings.json (applies to
26658
26641
  ] })
26659
26642
  ] }),
26660
26643
  /* @__PURE__ */ jsx40(Box39, { marginTop: 1, children: /* @__PURE__ */ jsx40(
26661
- SelectInput20,
26644
+ SelectInput19,
26662
26645
  {
26663
26646
  items: [
26664
26647
  { label: "\u2713 Save", value: "save", key: "save" },
@@ -26753,7 +26736,7 @@ var init_hooks_wizard = __esm({
26753
26736
  // src/ui/hooks-dashboard.tsx
26754
26737
  import { useMemo as useMemo5, useState as useState24 } from "react";
26755
26738
  import { Box as Box40, Text as Text40, useInput as useInput18 } from "ink";
26756
- import SelectInput21 from "ink-select-input";
26739
+ import SelectInput20 from "ink-select-input";
26757
26740
  import { jsx as jsx41, jsxs as jsxs39 } from "react/jsx-runtime";
26758
26741
  function tag(event) {
26759
26742
  return `[${event}]`.padEnd(20);
@@ -26924,7 +26907,7 @@ function HooksDashboard(props) {
26924
26907
  ] }),
26925
26908
  configured.length === 0 && /* @__PURE__ */ jsx41(Box40, { marginTop: 1, children: /* @__PURE__ */ jsx41(Text40, { color: theme.info.color, dimColor: true, children: "No hooks configured yet. Pick a recommended one below \u2014 or create your own." }) }),
26926
26909
  /* @__PURE__ */ jsx41(Box40, { marginTop: 1, children: /* @__PURE__ */ jsx41(
26927
- SelectInput21,
26910
+ SelectInput20,
26928
26911
  {
26929
26912
  items,
26930
26913
  itemComponent: ColoredRow,
@@ -26980,7 +26963,7 @@ var init_hooks_dashboard = __esm({
26980
26963
  // src/ui/help-menu.tsx
26981
26964
  import { useState as useState25 } from "react";
26982
26965
  import { Box as Box41, Text as Text41, useInput as useInput19 } from "ink";
26983
- import SelectInput22 from "ink-select-input";
26966
+ import SelectInput21 from "ink-select-input";
26984
26967
  import { jsx as jsx42, jsxs as jsxs40 } from "react/jsx-runtime";
26985
26968
  function HelpMenu({ customCommands, costAttributionEnabled, cloudMode, onDone, onCommand }) {
26986
26969
  const theme = useTheme();
@@ -27014,7 +26997,7 @@ function HelpMenu({ customCommands, costAttributionEnabled, cloudMode, onDone, o
27014
26997
  /* @__PURE__ */ jsx42(Text41, { color: theme.accent, bold: true, children: "Help" }),
27015
26998
  /* @__PURE__ */ jsx42(Text41, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select, Esc to close." }),
27016
26999
  /* @__PURE__ */ jsx42(Box41, { marginTop: 1, children: /* @__PURE__ */ jsx42(
27017
- SelectInput22,
27000
+ SelectInput21,
27018
27001
  {
27019
27002
  items: items2,
27020
27003
  onSelect: (item) => {
@@ -27041,7 +27024,7 @@ function HelpMenu({ customCommands, costAttributionEnabled, cloudMode, onDone, o
27041
27024
  /* @__PURE__ */ jsx42(Text41, { color: theme.accent, bold: true, children: "Custom commands" }),
27042
27025
  /* @__PURE__ */ jsx42(Text41, { color: theme.info.color, dimColor: false, children: customs.length === 0 ? "no custom commands found in .kimiflare/commands/" : "Arrow keys to navigate, Enter to run, Esc to go back." }),
27043
27026
  /* @__PURE__ */ jsx42(Box41, { marginTop: 1, children: /* @__PURE__ */ jsx42(
27044
- SelectInput22,
27027
+ SelectInput21,
27045
27028
  {
27046
27029
  items: items2,
27047
27030
  onSelect: (item) => {
@@ -27068,7 +27051,7 @@ function HelpMenu({ customCommands, costAttributionEnabled, cloudMode, onDone, o
27068
27051
  /* @__PURE__ */ jsx42(Text41, { color: theme.accent, bold: true, children: category.label }),
27069
27052
  /* @__PURE__ */ jsx42(Text41, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to execute, Esc to go back." }),
27070
27053
  /* @__PURE__ */ jsx42(Box41, { marginTop: 1, children: /* @__PURE__ */ jsx42(
27071
- SelectInput22,
27054
+ SelectInput21,
27072
27055
  {
27073
27056
  items,
27074
27057
  onSelect: (item) => {
@@ -27281,7 +27264,7 @@ var init_changelog_image_picker = __esm({
27281
27264
 
27282
27265
  // src/ui/modal-host.tsx
27283
27266
  import { Box as Box43, Text as Text43 } from "ink";
27284
- import SelectInput23 from "ink-select-input";
27267
+ import SelectInput22 from "ink-select-input";
27285
27268
  import { jsx as jsx44, jsxs as jsxs42 } from "react/jsx-runtime";
27286
27269
  function ModalHost(props) {
27287
27270
  const {
@@ -27464,7 +27447,7 @@ function ModalHost(props) {
27464
27447
  ] }),
27465
27448
  /* @__PURE__ */ jsx44(Text43, { color: theme.info.color, children: cmd.filepath }),
27466
27449
  /* @__PURE__ */ jsx44(Box43, { marginTop: 1, children: /* @__PURE__ */ jsx44(
27467
- SelectInput23,
27450
+ SelectInput22,
27468
27451
  {
27469
27452
  items: [
27470
27453
  { label: "Yes, delete", value: "yes", key: "yes" },
@@ -27618,7 +27601,7 @@ var init_modal_host = __esm({
27618
27601
 
27619
27602
  // src/ui/plan-complete-picker.tsx
27620
27603
  import { Box as Box44, Text as Text44 } from "ink";
27621
- import SelectInput24 from "ink-select-input";
27604
+ import SelectInput23 from "ink-select-input";
27622
27605
  import { jsx as jsx45, jsxs as jsxs43 } from "react/jsx-runtime";
27623
27606
  function PlanCompletePicker({ onPick }) {
27624
27607
  const theme = useTheme();
@@ -27631,7 +27614,7 @@ function PlanCompletePicker({ onPick }) {
27631
27614
  /* @__PURE__ */ jsx45(Text44, { color: theme.accent, bold: true, children: "Plan complete \u2014 what next?" }),
27632
27615
  /* @__PURE__ */ jsx45(Text44, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select, Esc to cancel." }),
27633
27616
  /* @__PURE__ */ jsx45(Box44, { marginTop: 1, children: /* @__PURE__ */ jsx45(
27634
- SelectInput24,
27617
+ SelectInput23,
27635
27618
  {
27636
27619
  items,
27637
27620
  onSelect: (item) => onPick(item.value),
@@ -32321,9 +32304,15 @@ ${wcagWarnings.join("\n")}` }
32321
32304
  if (!cfg?.cloudMode || !initialCloudToken) return;
32322
32305
  let cancelled = false;
32323
32306
  const fetchBudget = async () => {
32307
+ const did = cloudDeviceId ?? initialCloudDeviceId;
32308
+ try {
32309
+ const { fetchBillingStatus: fetchBillingStatus2 } = await Promise.resolve().then(() => (init_billing(), billing_exports));
32310
+ await fetchBillingStatus2(initialCloudToken, did);
32311
+ } catch {
32312
+ }
32324
32313
  try {
32325
32314
  const { fetchCloudUsage: fetchCloudUsage2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
32326
- const usage2 = await fetchCloudUsage2(initialCloudToken, cloudDeviceId ?? initialCloudDeviceId);
32315
+ const usage2 = await fetchCloudUsage2(initialCloudToken, did);
32327
32316
  if (usage2 && !cancelled) {
32328
32317
  setCloudBudget({ remaining: usage2.remaining, limit: usage2.input_token_limit });
32329
32318
  }
@@ -32362,7 +32351,6 @@ ${wcagWarnings.join("\n")}` }
32362
32351
  const usageRef = useRef7(null);
32363
32352
  const gatewayMetaRef = useRef7(null);
32364
32353
  const lastApiErrorRef = useRef7(null);
32365
- const pendingRetryRef = useRef7(null);
32366
32354
  const updateCheckedRef = useRef7(false);
32367
32355
  const sessionStateRef = useRef7(emptySessionState());
32368
32356
  const artifactStoreRef = useRef7(new ArtifactStore());
@@ -32436,8 +32424,9 @@ ${wcagWarnings.join("\n")}` }
32436
32424
  description: c.description ?? "",
32437
32425
  source: c.source
32438
32426
  }));
32439
- return [...BUILTIN_COMMANDS, ...customs];
32440
- }, [customCommandsVersion]);
32427
+ const cloudCommands = cfg?.cloudMode ? [{ name: "upgrade", description: "Upgrade to KimiFlare Pro", source: "builtin" }] : [];
32428
+ return [...BUILTIN_COMMANDS, ...cloudCommands, ...customs];
32429
+ }, [customCommandsVersion, cfg?.cloudMode]);
32441
32430
  const modalActive = commandWizard !== null || commandPicker !== null || commandToDelete !== null || showCommandList || showLspWizard || resumeSessions !== null || checkpointSession !== null || resuming || perm !== null || limitModal !== null || loopModal !== null || showInboxModal || showHelpMenu || showModePicker || showMemoryPicker || showGatewayPicker || showSkillsPicker || showShellPicker;
32442
32431
  const loadFilePickerItems = useCallback10(async () => {
32443
32432
  const cwd = process.cwd();
@@ -33141,6 +33130,31 @@ ${wcagWarnings.join("\n")}` }
33141
33130
  ...e,
33142
33131
  { kind: "info", key: mkKey(), text: "Complete payment in your browser. Your session will activate automatically." }
33143
33132
  ]);
33133
+ void (async () => {
33134
+ const { fetchBillingStatus: fetchBillingStatus2 } = await Promise.resolve().then(() => (init_billing(), billing_exports));
33135
+ const { fetchCloudUsage: fetchCloudUsage2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
33136
+ for (let i = 0; i < 40; i++) {
33137
+ await new Promise((r) => setTimeout(r, 5e3));
33138
+ let status;
33139
+ try {
33140
+ status = await fetchBillingStatus2(token, did);
33141
+ } catch {
33142
+ continue;
33143
+ }
33144
+ if (status && (status.status === "active" || status.status === "past_due")) {
33145
+ try {
33146
+ const usage2 = await fetchCloudUsage2(token, did);
33147
+ if (usage2) setCloudBudget({ remaining: usage2.remaining, limit: usage2.input_token_limit });
33148
+ } catch {
33149
+ }
33150
+ setEvents((e) => [
33151
+ ...e,
33152
+ { kind: "info", key: mkKey(), text: "\u2713 KimiFlare Pro is active \u2014 your token limit has been upgraded. Thank you!" }
33153
+ ]);
33154
+ return;
33155
+ }
33156
+ }
33157
+ })();
33144
33158
  } else {
33145
33159
  setEvents((e) => [...e, { kind: "error", key: mkKey(), text: "Checkout unavailable. Please try again later." }]);
33146
33160
  }
@@ -33150,7 +33164,7 @@ ${wcagWarnings.join("\n")}` }
33150
33164
  { kind: "error", key: mkKey(), text: `Upgrade failed: ${err instanceof Error ? err.message : String(err)}` }
33151
33165
  ]);
33152
33166
  }
33153
- }, [cloudToken, cloudDeviceId, initialCloudToken, initialCloudDeviceId, mkKey, setEvents]);
33167
+ }, [cloudToken, cloudDeviceId, initialCloudToken, initialCloudDeviceId, mkKey, setEvents, setCloudBudget]);
33154
33168
  const handleSaveProviderKey = useCallback10(
33155
33169
  (model, result) => {
33156
33170
  setKeyEntryFor(null);
@@ -33412,7 +33426,7 @@ ${wcagWarnings.join("\n")}` }
33412
33426
  let overrideModel;
33413
33427
  let overrideEffort;
33414
33428
  let display = displayText?.trim() || trimmed;
33415
- if (!opts2?.isRetry && trimmed.startsWith("/")) {
33429
+ if (trimmed.startsWith("/")) {
33416
33430
  const head = trimmed.split(/\s+/)[0].toLowerCase();
33417
33431
  const selfManaged = ["/compact", "/init"].includes(head);
33418
33432
  if (await handleSlash(trimmed)) {
@@ -33484,111 +33498,44 @@ ${wcagWarnings.join("\n")}` }
33484
33498
  content = parts;
33485
33499
  }
33486
33500
  }
33487
- if (!opts2?.isRetry) {
33488
- if (opts2?.queuedKey) {
33489
- setEvents(
33490
- (evts) => evts.map(
33491
- (e) => e.kind === "user" && e.key === opts2.queuedKey ? { ...e, text: display, images: images.length > 0 ? images : void 0, queued: false } : e
33492
- )
33493
- );
33494
- } else {
33495
- setEvents((e) => [...e, { kind: "user", key: mkKey(), text: display, images: images.length > 0 ? images : void 0 }]);
33496
- }
33497
- const nudge = maybeLspNudge(display, cfg?.lspEnabled ?? false, cfg?.lspServers ?? {});
33498
- if (nudge) {
33499
- setEvents((e) => [...e, { kind: "info", key: mkKey(), text: nudge }]);
33500
- }
33501
+ if (opts2?.queuedKey) {
33502
+ setEvents(
33503
+ (evts) => evts.map(
33504
+ (e) => e.kind === "user" && e.key === opts2.queuedKey ? { ...e, text: display, images: images.length > 0 ? images : void 0, queued: false } : e
33505
+ )
33506
+ );
33507
+ } else {
33508
+ setEvents((e) => [...e, { kind: "user", key: mkKey(), text: display, images: images.length > 0 ? images : void 0 }]);
33509
+ }
33510
+ const nudge = maybeLspNudge(display, cfg?.lspEnabled ?? false, cfg?.lspServers ?? {});
33511
+ if (nudge) {
33512
+ setEvents((e) => [...e, { kind: "info", key: mkKey(), text: nudge }]);
33501
33513
  }
33502
33514
  const classification = classifyIntent(trimmed);
33503
- if (!opts2?.isRetry) {
33504
- if (hooksManagerRef.current.hasEnabledHooks("UserPromptSubmit")) {
33505
- const promptOutcome = await hooksManagerRef.current.fire(
33506
- "UserPromptSubmit",
33507
- {
33508
- event: "UserPromptSubmit",
33509
- session_id: sessionIdRef.current,
33510
- cwd: process.cwd(),
33511
- prompt: display,
33512
- tier: classification.tier
33513
- },
33514
- null
33515
- );
33516
- if (promptOutcome.vetoed) {
33517
- const reason = promptOutcome.vetoReason || "UserPromptSubmit hook blocked the prompt";
33518
- setEvents((e) => [
33519
- ...e,
33520
- { kind: "info", key: mkKey(), text: `hook blocked the prompt: ${reason}` }
33521
- ]);
33522
- endTurn();
33523
- return;
33524
- }
33525
- }
33526
- messagesRef.current.push({ role: "user", content });
33527
- await saveSessionSafe();
33528
- turnCounterRef.current += 1;
33529
- if (turnCounterRef.current % 15 === 0 && existsSync8(join38(process.cwd(), "KIMI.md")) && !kimiMdStale) {
33515
+ if (hooksManagerRef.current.hasEnabledHooks("UserPromptSubmit")) {
33516
+ const promptOutcome = await hooksManagerRef.current.fire(
33517
+ "UserPromptSubmit",
33518
+ {
33519
+ event: "UserPromptSubmit",
33520
+ session_id: sessionIdRef.current,
33521
+ cwd: process.cwd(),
33522
+ prompt: display,
33523
+ tier: classification.tier
33524
+ },
33525
+ null
33526
+ );
33527
+ if (promptOutcome.vetoed) {
33528
+ const reason = promptOutcome.vetoReason || "UserPromptSubmit hook blocked the prompt";
33530
33529
  setEvents((e) => [
33531
33530
  ...e,
33532
- { kind: "info", key: mkKey(), text: "Tip: Rerunning /init occasionally helps KimiFlare stay accurate as your project evolves." }
33531
+ { kind: "info", key: mkKey(), text: `hook blocked the prompt: ${reason}` }
33533
33532
  ]);
33534
- }
33535
- const autoFreshThreshold = cfg?.autoFreshSuggestionTurns ?? DEFAULT_AUTO_FRESH_SUGGESTION_TURNS;
33536
- if (autoFreshThreshold > 0 && turnCounterRef.current >= autoFreshThreshold && (modeRef.current === "auto" || modeRef.current === "edit" || modeRef.current === "multi-agent-experimental") && !freshSuggestedRef.current) {
33537
- freshSuggestedRef.current = true;
33538
- if (cfg?.autoFreshEnabled) {
33539
- void (async () => {
33540
- try {
33541
- const turnIndex = messagesRef.current.length;
33542
- if (turnIndex > 0) {
33543
- const cp = {
33544
- id: `cp_prefresh_${Date.now()}`,
33545
- label: "pre-fresh auto-save",
33546
- turnIndex,
33547
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
33548
- sessionState: compiledContextRef.current ? sessionStateRef.current : void 0,
33549
- artifactStore: serializeArtifactStore(artifactStoreRef.current)
33550
- };
33551
- ensureSessionId();
33552
- const { sessionsDir: sessionsDir3 } = await Promise.resolve().then(() => (init_sessions(), sessions_exports));
33553
- const filePath = join38(sessionsDir3(), `${sessionIdRef.current}.json`);
33554
- await addCheckpoint(filePath, cp);
33555
- }
33556
- const summary = await generateContinuationSummary({
33557
- messages: messagesRef.current,
33558
- mode: modeRef.current,
33559
- accountId: cfg.accountId,
33560
- apiToken: cfg.apiToken,
33561
- model: cfg.plumbingModel ?? "@cf/moonshotai/kimi-k2.5",
33562
- gateway: gatewayFromConfig(cfg),
33563
- memoryManager: memoryManagerRef.current,
33564
- memoryEnabled: cfg.memoryEnabled
33565
- });
33566
- if (summary) {
33567
- executeFreshStart(buildSlashContext(), summary);
33568
- setEvents((e) => [
33569
- ...e,
33570
- { kind: "info", key: mkKey(), text: "Auto-fresh triggered: starting new session with continuation context\u2026" }
33571
- ]);
33572
- }
33573
- } catch (e) {
33574
- setEvents((es) => [
33575
- ...es,
33576
- { kind: "error", key: mkKey(), text: `Auto-fresh failed: ${e.message}` }
33577
- ]);
33578
- }
33579
- })();
33580
- } else {
33581
- setEvents((e) => [
33582
- ...e,
33583
- {
33584
- kind: "info",
33585
- key: mkKey(),
33586
- text: `Session has run for ${turnCounterRef.current} turns. The model may slow down with accumulated context. Run /fresh to continue with a summarized state, or /compact to compress history.`
33587
- }
33588
- ]);
33589
- }
33533
+ endTurn();
33534
+ return;
33590
33535
  }
33591
33536
  }
33537
+ messagesRef.current.push({ role: "user", content });
33538
+ await saveSessionSafe();
33592
33539
  if (compiledContextRef.current) {
33593
33540
  const { ids, recalled } = recallArtifacts(messagesRef.current, artifactStoreRef.current, sessionStateRef.current);
33594
33541
  if (recalled.length > 0) {
@@ -33600,6 +33547,69 @@ ${wcagWarnings.join("\n")}` }
33600
33547
  };
33601
33548
  }
33602
33549
  }
33550
+ turnCounterRef.current += 1;
33551
+ if (turnCounterRef.current % 15 === 0 && existsSync8(join38(process.cwd(), "KIMI.md")) && !kimiMdStale) {
33552
+ setEvents((e) => [
33553
+ ...e,
33554
+ { kind: "info", key: mkKey(), text: "Tip: Rerunning /init occasionally helps KimiFlare stay accurate as your project evolves." }
33555
+ ]);
33556
+ }
33557
+ const autoFreshThreshold = cfg?.autoFreshSuggestionTurns ?? DEFAULT_AUTO_FRESH_SUGGESTION_TURNS;
33558
+ if (autoFreshThreshold > 0 && turnCounterRef.current >= autoFreshThreshold && (modeRef.current === "auto" || modeRef.current === "edit" || modeRef.current === "multi-agent-experimental") && !freshSuggestedRef.current) {
33559
+ freshSuggestedRef.current = true;
33560
+ if (cfg?.autoFreshEnabled) {
33561
+ void (async () => {
33562
+ try {
33563
+ const turnIndex = messagesRef.current.length;
33564
+ if (turnIndex > 0) {
33565
+ const cp = {
33566
+ id: `cp_prefresh_${Date.now()}`,
33567
+ label: "pre-fresh auto-save",
33568
+ turnIndex,
33569
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
33570
+ sessionState: compiledContextRef.current ? sessionStateRef.current : void 0,
33571
+ artifactStore: serializeArtifactStore(artifactStoreRef.current)
33572
+ };
33573
+ ensureSessionId();
33574
+ const { sessionsDir: sessionsDir3 } = await Promise.resolve().then(() => (init_sessions(), sessions_exports));
33575
+ const filePath = join38(sessionsDir3(), `${sessionIdRef.current}.json`);
33576
+ await addCheckpoint(filePath, cp);
33577
+ }
33578
+ const summary = await generateContinuationSummary({
33579
+ messages: messagesRef.current,
33580
+ mode: modeRef.current,
33581
+ accountId: cfg.accountId,
33582
+ apiToken: cfg.apiToken,
33583
+ model: cfg.plumbingModel ?? "@cf/moonshotai/kimi-k2.5",
33584
+ gateway: gatewayFromConfig(cfg),
33585
+ memoryManager: memoryManagerRef.current,
33586
+ memoryEnabled: cfg.memoryEnabled
33587
+ });
33588
+ if (summary) {
33589
+ executeFreshStart(buildSlashContext(), summary);
33590
+ setEvents((e) => [
33591
+ ...e,
33592
+ { kind: "info", key: mkKey(), text: "Auto-fresh triggered: starting new session with continuation context\u2026" }
33593
+ ]);
33594
+ }
33595
+ } catch (e) {
33596
+ setEvents((es) => [
33597
+ ...es,
33598
+ { kind: "error", key: mkKey(), text: `Auto-fresh failed: ${e.message}` }
33599
+ ]);
33600
+ }
33601
+ })();
33602
+ } else {
33603
+ setEvents((e) => [
33604
+ ...e,
33605
+ {
33606
+ kind: "info",
33607
+ key: mkKey(),
33608
+ text: `Session has run for ${turnCounterRef.current} turns. The model may slow down with accumulated context. Run /fresh to continue with a summarized state, or /compact to compress history.`
33609
+ }
33610
+ ]);
33611
+ }
33612
+ }
33603
33613
  gatewayMetaRef.current = null;
33604
33614
  setGatewayMeta(null);
33605
33615
  setIntentTier(classification.tier);
@@ -33963,7 +33973,6 @@ ${conflicts.join("\n")}` }
33963
33973
  },
33964
33974
  {
33965
33975
  onDone: () => {
33966
- pendingRetryRef.current = null;
33967
33976
  void (async () => {
33968
33977
  await saveSessionSafe();
33969
33978
  if (turnScope.signal.aborted) {
@@ -34066,6 +34075,117 @@ ${conflicts.join("\n")}` }
34066
34075
  }
34067
34076
  }
34068
34077
  }
34078
+ const autoCompactTokenThreshold = cfg?.autoCompactTokenThreshold ?? 5e5;
34079
+ const autoFreshTokenThreshold = cfg?.autoFreshTokenThreshold ?? 2e6;
34080
+ const estimatedTokens = estimatePromptTokens(messagesRef.current);
34081
+ if (estimatedTokens > autoCompactTokenThreshold) {
34082
+ let didAggressiveCompact = false;
34083
+ if (compiledContextRef.current) {
34084
+ const store = artifactStoreRef.current;
34085
+ const result = compactMessagesViaArtifacts({
34086
+ messages: messagesRef.current,
34087
+ state: sessionStateRef.current,
34088
+ store,
34089
+ keepLastTurns: 1
34090
+ });
34091
+ if (result.metrics.rawTurnsRemoved > 0) {
34092
+ messagesRef.current = result.newMessages;
34093
+ sessionStateRef.current = result.newState;
34094
+ setEvents((e) => [
34095
+ ...e,
34096
+ {
34097
+ kind: "info",
34098
+ key: mkKey(),
34099
+ text: `auto-compacted (aggressive): ${result.metrics.estimatedTokensBefore.toLocaleString()} \u2192 ${result.metrics.estimatedTokensAfter.toLocaleString()} tokens (${result.metrics.archivedArtifacts} artifacts)`
34100
+ }
34101
+ ]);
34102
+ await saveSessionSafe();
34103
+ didAggressiveCompact = true;
34104
+ }
34105
+ } else {
34106
+ try {
34107
+ const result = await summarizeMessagesViaLlm({
34108
+ accountId: cfg.accountId,
34109
+ apiToken: cfg.apiToken,
34110
+ model: cfg.model,
34111
+ messages: messagesRef.current,
34112
+ keepLastTurns: 1,
34113
+ signal: turnScope.signal,
34114
+ gateway: gatewayFromConfig(cfg)
34115
+ });
34116
+ if (result.replacedCount > 0) {
34117
+ messagesRef.current = result.newMessages;
34118
+ setEvents((e) => [
34119
+ ...e,
34120
+ {
34121
+ kind: "info",
34122
+ key: mkKey(),
34123
+ text: `auto-compacted (aggressive): ${result.replacedCount} messages summarized`
34124
+ }
34125
+ ]);
34126
+ await saveSessionSafe();
34127
+ didAggressiveCompact = true;
34128
+ }
34129
+ } catch (compactErr) {
34130
+ if (compactErr.name !== "AbortError") {
34131
+ setEvents((es) => [
34132
+ ...es,
34133
+ {
34134
+ kind: "info",
34135
+ key: mkKey(),
34136
+ text: `aggressive auto-compact failed: ${compactErr.message ?? String(compactErr)}`
34137
+ }
34138
+ ]);
34139
+ }
34140
+ }
34141
+ }
34142
+ const tokensAfterCompact = estimatePromptTokens(messagesRef.current);
34143
+ if (tokensAfterCompact > autoFreshTokenThreshold) {
34144
+ try {
34145
+ const turnIndex = messagesRef.current.length;
34146
+ if (turnIndex > 0) {
34147
+ const cp = {
34148
+ id: `cp_prefresh_${Date.now()}`,
34149
+ label: "pre-fresh auto-save",
34150
+ turnIndex,
34151
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
34152
+ sessionState: compiledContextRef.current ? sessionStateRef.current : void 0,
34153
+ artifactStore: serializeArtifactStore(artifactStoreRef.current)
34154
+ };
34155
+ ensureSessionId();
34156
+ const { sessionsDir: sessionsDir3 } = await Promise.resolve().then(() => (init_sessions(), sessions_exports));
34157
+ const filePath = join38(sessionsDir3(), `${sessionIdRef.current}.json`);
34158
+ await addCheckpoint(filePath, cp);
34159
+ }
34160
+ const summary = await generateContinuationSummary({
34161
+ messages: messagesRef.current,
34162
+ mode: modeRef.current,
34163
+ accountId: cfg.accountId,
34164
+ apiToken: cfg.apiToken,
34165
+ model: cfg.plumbingModel ?? "@cf/moonshotai/kimi-k2.5",
34166
+ gateway: gatewayFromConfig(cfg),
34167
+ memoryManager: memoryManagerRef.current,
34168
+ memoryEnabled: cfg.memoryEnabled
34169
+ });
34170
+ if (summary) {
34171
+ executeFreshStart(buildSlashContext(), summary);
34172
+ setEvents((e) => [
34173
+ ...e,
34174
+ {
34175
+ kind: "info",
34176
+ key: mkKey(),
34177
+ text: `Auto-fresh triggered at ~${tokensAfterCompact.toLocaleString()} tokens: starting new session with continuation context\u2026`
34178
+ }
34179
+ ]);
34180
+ }
34181
+ } catch (e) {
34182
+ setEvents((es) => [
34183
+ ...es,
34184
+ { kind: "error", key: mkKey(), text: `Auto-fresh failed: ${e.message}` }
34185
+ ]);
34186
+ }
34187
+ }
34188
+ }
34069
34189
  })();
34070
34190
  cleanupTurn();
34071
34191
  if (modeRef.current === "plan") {
@@ -34108,7 +34228,6 @@ ${conflicts.join("\n")}` }
34108
34228
  const did = cloudDeviceId ?? initialCloudDeviceId;
34109
34229
  let used = 0;
34110
34230
  let limit = 0;
34111
- let expiresAt = "";
34112
34231
  if (token) {
34113
34232
  try {
34114
34233
  const { fetchCloudUsage: fetchCloudUsage2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
@@ -34116,7 +34235,6 @@ ${conflicts.join("\n")}` }
34116
34235
  if (usage2) {
34117
34236
  used = usage2.input_tokens_used;
34118
34237
  limit = usage2.input_token_limit;
34119
- expiresAt = usage2.expires_at;
34120
34238
  }
34121
34239
  } catch {
34122
34240
  }
@@ -34130,12 +34248,11 @@ ${conflicts.join("\n")}` }
34130
34248
  }
34131
34249
  setEvents((es) => [
34132
34250
  ...es,
34133
- { kind: "cloud_quota_exhausted", key: mkKey(), used, limit, expiresAt }
34251
+ { kind: "cloud_quota_exhausted", key: mkKey(), used, limit }
34134
34252
  ]);
34135
34253
  } else if (e instanceof KimiApiError && (e.httpStatus === 429 || e.code === 3040 || e.httpStatus !== void 0 && e.httpStatus >= 500)) {
34136
34254
  const err = { httpStatus: e.httpStatus, code: e.code, message: humanizeCloudflareError(e) };
34137
34255
  lastApiErrorRef.current = err;
34138
- pendingRetryRef.current = { text: trimmed, display };
34139
34256
  setEvents((es) => [
34140
34257
  ...es,
34141
34258
  { kind: "api_error", key: mkKey(), ...err }
@@ -34483,19 +34600,9 @@ ${conflicts.join("\n")}` }
34483
34600
  }
34484
34601
  );
34485
34602
  }
34486
- const handleRetry = useCallback10(
34487
- (eventKey) => {
34488
- const pending = pendingRetryRef.current;
34489
- if (!pending) return;
34490
- pendingRetryRef.current = null;
34491
- setEvents((es) => es.filter((e) => e.key !== eventKey));
34492
- void processMessage(pending.text, pending.display, { isRetry: true });
34493
- },
34494
- [processMessage]
34495
- );
34496
34603
  const hasConversation = events.some((e) => e.kind === "user" || e.kind === "assistant");
34497
34604
  return /* @__PURE__ */ jsx47(ThemeProvider, { theme, children: /* @__PURE__ */ jsxs45(Box46, { flexDirection: "column", children: [
34498
- !hasConversation && events.length === 0 ? /* @__PURE__ */ jsx47(Welcome, {}) : /* @__PURE__ */ jsx47(ChatView, { events, showReasoning, verbose, intentTier: intentTier ?? void 0, onUpgrade: handleUpgrade2, onRetry: handleRetry }),
34605
+ !hasConversation && events.length === 0 ? /* @__PURE__ */ jsx47(Welcome, {}) : /* @__PURE__ */ jsx47(ChatView, { events, showReasoning, verbose, intentTier: intentTier ?? void 0, onUpgrade: handleUpgrade2 }),
34499
34606
  perm ? /* @__PURE__ */ jsx47(
34500
34607
  PermissionModal,
34501
34608
  {