kimiflare 0.35.0 → 0.36.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
@@ -1,5 +1,11 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __getOwnPropNames = Object.getOwnPropertyNames;
3
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
4
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
5
+ }) : x)(function(x) {
6
+ if (typeof require !== "undefined") return require.apply(this, arguments);
7
+ throw Error('Dynamic require of "' + x + '" is not supported');
8
+ });
3
9
  var __esm = (fn, res) => function __init() {
4
10
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
5
11
  };
@@ -321,10 +327,8 @@ async function* readSSE(stream, signal) {
321
327
  const decoder = new TextDecoder("utf-8");
322
328
  let buffer = "";
323
329
  const onAbort = () => {
324
- try {
325
- reader.cancel(new DOMException("aborted", "AbortError"));
326
- } catch {
327
- }
330
+ reader.cancel(new DOMException("aborted", "AbortError")).catch(() => {
331
+ });
328
332
  };
329
333
  signal?.addEventListener("abort", onAbort, { once: true });
330
334
  try {
@@ -1402,6 +1406,11 @@ function stripTypescript(code) {
1402
1406
  return js.trim();
1403
1407
  }
1404
1408
  async function loadTypescript(cwd) {
1409
+ try {
1410
+ const tsPath = await import.meta.resolve("typescript");
1411
+ return await import(tsPath);
1412
+ } catch {
1413
+ }
1405
1414
  let dir = cwd;
1406
1415
  while (dir !== dirname3(dir)) {
1407
1416
  try {
@@ -1669,7 +1678,18 @@ Use console.log() to return results. Only console.log output will be sent back t
1669
1678
  });
1670
1679
  }
1671
1680
  if (iter >= max) {
1672
- if (opts2.continueOnLimit) {
1681
+ if (opts2.callbacks.onToolLimitReached) {
1682
+ const decision = await opts2.callbacks.onToolLimitReached();
1683
+ if (decision === "continue") {
1684
+ opts2.messages.push({
1685
+ role: "system",
1686
+ content: "You have reached the tool-call limit for this session. The counter has been reset so you can continue working. Please proceed with your task."
1687
+ });
1688
+ iter = 0;
1689
+ } else {
1690
+ return;
1691
+ }
1692
+ } else if (opts2.continueOnLimit) {
1673
1693
  opts2.messages.push({
1674
1694
  role: "system",
1675
1695
  content: "You have reached the tool-call limit for this session. The counter has been reset so you can continue working. Please proceed with your task."
@@ -4614,9 +4634,16 @@ var init_cli = __esm({
4614
4634
  // src/cloud/auth.ts
4615
4635
  var auth_exports = {};
4616
4636
  __export(auth_exports, {
4637
+ CLOUD_API_URL: () => CLOUD_API_URL,
4638
+ POLL_INTERVAL_MS: () => POLL_INTERVAL_MS,
4639
+ POLL_TIMEOUT_MS: () => POLL_TIMEOUT_MS,
4617
4640
  authenticateDevice: () => authenticateDevice,
4618
4641
  clearCloudCredentials: () => clearCloudCredentials,
4642
+ fetchCloudUsage: () => fetchCloudUsage,
4643
+ generateDeviceCodes: () => generateDeviceCodes,
4619
4644
  loadCloudCredentials: () => loadCloudCredentials,
4645
+ pollForToken: () => pollForToken,
4646
+ registerDevice: () => registerDevice,
4620
4647
  saveCloudCredentials: () => saveCloudCredentials
4621
4648
  });
4622
4649
  import { readFile as readFile11, writeFile as writeFile7 } from "fs/promises";
@@ -4634,6 +4661,49 @@ function generateCode() {
4634
4661
  }
4635
4662
  return out;
4636
4663
  }
4664
+ function generateDeviceCodes() {
4665
+ const deviceCode = `device-${generateCode()}-${Date.now()}`;
4666
+ const userCode = `${generateCode()}-${generateCode()}`;
4667
+ const authUrl = `${CLOUD_API_URL}/auth/github?code=${encodeURIComponent(userCode)}`;
4668
+ return { deviceCode, userCode, authUrl };
4669
+ }
4670
+ async function registerDevice(codes) {
4671
+ const registerRes = await fetch(`${CLOUD_API_URL}/auth/device`, {
4672
+ method: "POST",
4673
+ headers: { "Content-Type": "application/json" },
4674
+ body: JSON.stringify({ device_code: codes.deviceCode, user_code: codes.userCode })
4675
+ });
4676
+ if (!registerRes.ok) {
4677
+ const err = await registerRes.json().catch(() => ({}));
4678
+ throw new Error(`Failed to register device: ${err.error || registerRes.statusText}`);
4679
+ }
4680
+ }
4681
+ async function pollForToken(deviceCode) {
4682
+ const pollRes = await fetch(`${CLOUD_API_URL}/auth/poll`, {
4683
+ method: "POST",
4684
+ headers: { "Content-Type": "application/json" },
4685
+ body: JSON.stringify({ device_code: deviceCode })
4686
+ });
4687
+ if (!pollRes.ok) return null;
4688
+ const pollData = await pollRes.json();
4689
+ if (pollData.status === "approved" && pollData.access_token) {
4690
+ const creds = {
4691
+ accessToken: pollData.access_token,
4692
+ expiresAt: Math.floor(Date.now() / 1e3) + 7 * 24 * 60 * 60
4693
+ // 7 days
4694
+ };
4695
+ await saveCloudCredentials(creds);
4696
+ return creds;
4697
+ }
4698
+ return null;
4699
+ }
4700
+ async function fetchCloudUsage(token) {
4701
+ const res = await fetch(`${CLOUD_API_URL}/v1/usage`, {
4702
+ headers: { Authorization: `Bearer ${token}` }
4703
+ });
4704
+ if (!res.ok) return null;
4705
+ return await res.json();
4706
+ }
4637
4707
  async function loadCloudCredentials() {
4638
4708
  try {
4639
4709
  const raw = await readFile11(cloudCredPath(), "utf8");
@@ -4657,39 +4727,15 @@ async function clearCloudCredentials() {
4657
4727
  }
4658
4728
  }
4659
4729
  async function authenticateDevice(onStatus) {
4660
- const deviceCode = `device-${generateCode()}-${Date.now()}`;
4661
- const userCode = `${generateCode()}-${generateCode()}`;
4662
- const registerRes = await fetch(`${CLOUD_API_URL}/auth/device`, {
4663
- method: "POST",
4664
- headers: { "Content-Type": "application/json" },
4665
- body: JSON.stringify({ device_code: deviceCode, user_code: userCode })
4666
- });
4667
- if (!registerRes.ok) {
4668
- const err = await registerRes.json().catch(() => ({}));
4669
- throw new Error(`Failed to register device: ${err.error || registerRes.statusText}`);
4670
- }
4671
- const authUrl = `${CLOUD_API_URL}/auth/github?code=${encodeURIComponent(userCode)}`;
4672
- onStatus({ url: authUrl, userCode, polling: false });
4730
+ const codes = generateDeviceCodes();
4731
+ await registerDevice(codes);
4732
+ onStatus({ url: codes.authUrl, userCode: codes.userCode, polling: false });
4673
4733
  const startTime = Date.now();
4674
4734
  while (Date.now() - startTime < POLL_TIMEOUT_MS) {
4675
4735
  await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
4676
- onStatus({ url: authUrl, userCode, polling: true });
4677
- const pollRes = await fetch(`${CLOUD_API_URL}/auth/poll`, {
4678
- method: "POST",
4679
- headers: { "Content-Type": "application/json" },
4680
- body: JSON.stringify({ device_code: deviceCode })
4681
- });
4682
- if (!pollRes.ok) continue;
4683
- const pollData = await pollRes.json();
4684
- if (pollData.status === "approved" && pollData.access_token) {
4685
- const creds = {
4686
- accessToken: pollData.access_token,
4687
- expiresAt: Math.floor(Date.now() / 1e3) + 7 * 24 * 60 * 60
4688
- // 7 days
4689
- };
4690
- await saveCloudCredentials(creds);
4691
- return creds;
4692
- }
4736
+ onStatus({ url: codes.authUrl, userCode: codes.userCode, polling: true });
4737
+ const creds = await pollForToken(codes.deviceCode);
4738
+ if (creds) return creds;
4693
4739
  }
4694
4740
  throw new Error("Authentication timed out. Please try again.");
4695
4741
  }
@@ -4699,7 +4745,7 @@ var init_auth = __esm({
4699
4745
  "use strict";
4700
4746
  CLOUD_API_URL = "https://api.kimiflare.com";
4701
4747
  POLL_INTERVAL_MS = 5e3;
4702
- POLL_TIMEOUT_MS = 10 * 60 * 1e3;
4748
+ POLL_TIMEOUT_MS = 15 * 60 * 1e3;
4703
4749
  }
4704
4750
  });
4705
4751
 
@@ -6754,7 +6800,7 @@ import { useEffect, useState } from "react";
6754
6800
  import { Box as Box5, Text as Text5 } from "ink";
6755
6801
  import Spinner3 from "ink-spinner";
6756
6802
  import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
6757
- function StatusBar({ model, usage, sessionUsage, thinking, turnStartedAt, mode, effort, contextLimit, hasUpdate, latestVersion, gatewayMeta, codeMode, cloudMode }) {
6803
+ function StatusBar({ model, usage, sessionUsage, thinking, turnStartedAt, mode, effort, contextLimit, hasUpdate, latestVersion, gatewayMeta, codeMode, cloudMode, cloudBudget }) {
6758
6804
  const theme = useTheme();
6759
6805
  const [now2, setNow] = useState(Date.now());
6760
6806
  const modeColor = mode === "plan" ? theme.modeBadge.plan : mode === "auto" ? theme.modeBadge.auto : theme.modeBadge.edit;
@@ -6787,7 +6833,7 @@ function StatusBar({ model, usage, sessionUsage, thinking, turnStartedAt, mode,
6787
6833
  ] })
6788
6834
  ] }),
6789
6835
  usage && /* @__PURE__ */ jsxs5(Box5, { children: [
6790
- /* @__PURE__ */ jsx6(Text5, { color: theme.info.color, children: buildRightParts(usage, contextLimit, sessionUsage, gatewayMeta).join(" \xB7 ") }),
6836
+ /* @__PURE__ */ jsx6(Text5, { color: theme.info.color, children: buildRightParts(usage, contextLimit, sessionUsage, gatewayMeta, cloudMode, cloudBudget).join(" \xB7 ") }),
6791
6837
  warn ? /* @__PURE__ */ jsxs5(Text5, { color: theme.warn, bold: true, children: [
6792
6838
  " \xB7 ",
6793
6839
  "/compact recommended"
@@ -6801,7 +6847,7 @@ function StatusBar({ model, usage, sessionUsage, thinking, turnStartedAt, mode,
6801
6847
  ] })
6802
6848
  ] });
6803
6849
  }
6804
- function buildRightParts(usage, contextLimit, sessionUsage, gatewayMeta) {
6850
+ function buildRightParts(usage, contextLimit, sessionUsage, gatewayMeta, cloudMode, cloudBudget) {
6805
6851
  const pct = Math.round(usage.prompt_tokens / contextLimit * 100);
6806
6852
  const parts = [];
6807
6853
  if (sessionUsage) {
@@ -6809,19 +6855,35 @@ function buildRightParts(usage, contextLimit, sessionUsage, gatewayMeta) {
6809
6855
  parts.push(`in ${sessionUsage.promptTokens}${cached ? ` (${cached} cached)` : ""}`);
6810
6856
  parts.push(`out ${sessionUsage.completionTokens}`);
6811
6857
  parts.push(`ctx ${pct}%`);
6812
- parts.push(`$${sessionUsage.cost.toFixed(5)}`);
6858
+ if (cloudMode) {
6859
+ parts.push(`\x1B[9m${sessionUsage.cost.toFixed(5)}\x1B[29m`);
6860
+ } else {
6861
+ parts.push(`${sessionUsage.cost.toFixed(5)}`);
6862
+ }
6813
6863
  } else {
6814
6864
  const cached = usage.prompt_tokens_details?.cached_tokens ?? 0;
6815
6865
  const cost = calculateCost(usage.prompt_tokens, usage.completion_tokens, cached);
6816
6866
  parts.push(`in ${usage.prompt_tokens}${cached ? ` (${cached} cached)` : ""}`);
6817
6867
  parts.push(`out ${usage.completion_tokens}`);
6818
6868
  parts.push(`ctx ${pct}%`);
6819
- parts.push(`$${cost.total.toFixed(5)}`);
6869
+ if (cloudMode) {
6870
+ parts.push(`\x1B[9m${cost.total.toFixed(5)}\x1B[29m`);
6871
+ } else {
6872
+ parts.push(`${cost.total.toFixed(5)}`);
6873
+ }
6874
+ }
6875
+ if (cloudMode && cloudBudget) {
6876
+ parts.push(`${formatTokens(cloudBudget.remaining)}/${formatTokens(cloudBudget.limit)} tokens`);
6820
6877
  }
6821
6878
  const gatewayCache = formatGatewayCacheStatus(gatewayMeta);
6822
6879
  if (gatewayCache) parts.push(gatewayCache);
6823
6880
  return parts;
6824
6881
  }
6882
+ function formatTokens(n) {
6883
+ if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
6884
+ if (n >= 1e3) return `${(n / 1e3).toFixed(1)}K`;
6885
+ return String(n);
6886
+ }
6825
6887
  function formatGatewayCacheStatus(gatewayMeta) {
6826
6888
  const status = gatewayMeta?.cacheStatus?.trim();
6827
6889
  return status ? `AI Gateway \xB7 cache ${status.toLowerCase()}` : null;
@@ -6882,11 +6944,48 @@ var init_permission = __esm({
6882
6944
  }
6883
6945
  });
6884
6946
 
6885
- // src/ui/resume-picker.tsx
6886
- import { useState as useState2 } from "react";
6887
- import { Box as Box7, Text as Text7, useWindowSize } from "ink";
6947
+ // src/ui/limit-modal.tsx
6948
+ import { Box as Box7, Text as Text7 } from "ink";
6888
6949
  import SelectInput2 from "ink-select-input";
6889
6950
  import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
6951
+ function LimitModal({ limit, onDecide }) {
6952
+ const theme = useTheme();
6953
+ const items = [
6954
+ { label: "Continue", value: "continue" },
6955
+ { label: "Stop", value: "stop" }
6956
+ ];
6957
+ return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", borderStyle: "round", borderColor: theme.error, paddingX: 1, children: [
6958
+ /* @__PURE__ */ jsxs7(Text7, { color: theme.error, bold: true, children: [
6959
+ "Tool-call limit reached (",
6960
+ limit,
6961
+ ")"
6962
+ ] }),
6963
+ /* @__PURE__ */ jsxs7(Text7, { dimColor: true, children: [
6964
+ "This session has made ",
6965
+ limit,
6966
+ " tool calls. What would you like to do?"
6967
+ ] }),
6968
+ /* @__PURE__ */ jsx8(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx8(
6969
+ SelectInput2,
6970
+ {
6971
+ items,
6972
+ onSelect: (item) => onDecide(item.value)
6973
+ }
6974
+ ) })
6975
+ ] });
6976
+ }
6977
+ var init_limit_modal = __esm({
6978
+ "src/ui/limit-modal.tsx"() {
6979
+ "use strict";
6980
+ init_theme_context();
6981
+ }
6982
+ });
6983
+
6984
+ // src/ui/resume-picker.tsx
6985
+ import { useState as useState2 } from "react";
6986
+ import { Box as Box8, Text as Text8, useWindowSize } from "ink";
6987
+ import SelectInput3 from "ink-select-input";
6988
+ import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
6890
6989
  function ResumePicker({ sessions, onPick }) {
6891
6990
  const theme = useTheme();
6892
6991
  const { rows } = useWindowSize();
@@ -6895,11 +6994,11 @@ function ResumePicker({ sessions, onPick }) {
6895
6994
  const totalPages = Math.max(1, Math.ceil(sessions.length / pageSize));
6896
6995
  const safePage = Math.min(page, totalPages - 1);
6897
6996
  if (sessions.length === 0) {
6898
- return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
6899
- /* @__PURE__ */ jsx8(Text7, { color: theme.accent, bold: true, children: "Resume a session" }),
6900
- /* @__PURE__ */ jsx8(Text7, { color: theme.info.color, children: "No saved sessions yet. Press Enter to dismiss." }),
6901
- /* @__PURE__ */ jsx8(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx8(
6902
- SelectInput2,
6997
+ return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
6998
+ /* @__PURE__ */ jsx9(Text8, { color: theme.accent, bold: true, children: "Resume a session" }),
6999
+ /* @__PURE__ */ jsx9(Text8, { color: theme.info.color, children: "No saved sessions yet. Press Enter to dismiss." }),
7000
+ /* @__PURE__ */ jsx9(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx9(
7001
+ SelectInput3,
6903
7002
  {
6904
7003
  items: [{ label: "(back)", value: "__cancel__" }],
6905
7004
  onSelect: () => onPick(null)
@@ -6921,9 +7020,9 @@ function ResumePicker({ sessions, onPick }) {
6921
7020
  items.push({ label: "\u2192 next page", value: "__next__" });
6922
7021
  }
6923
7022
  items.push({ label: "(cancel)", value: "__cancel__" });
6924
- return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
6925
- /* @__PURE__ */ jsx8(Text7, { color: theme.accent, bold: true, children: "Resume a session" }),
6926
- /* @__PURE__ */ jsxs7(Text7, { color: theme.info.color, children: [
7023
+ return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
7024
+ /* @__PURE__ */ jsx9(Text8, { color: theme.accent, bold: true, children: "Resume a session" }),
7025
+ /* @__PURE__ */ jsxs8(Text8, { color: theme.info.color, children: [
6927
7026
  "Arrow keys to select, Enter to confirm. Page ",
6928
7027
  safePage + 1,
6929
7028
  " of ",
@@ -6932,8 +7031,8 @@ function ResumePicker({ sessions, onPick }) {
6932
7031
  sessions.length,
6933
7032
  " total)"
6934
7033
  ] }),
6935
- /* @__PURE__ */ jsx8(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx8(
6936
- SelectInput2,
7034
+ /* @__PURE__ */ jsx9(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx9(
7035
+ SelectInput3,
6937
7036
  {
6938
7037
  items,
6939
7038
  onSelect: (item) => {
@@ -6973,9 +7072,9 @@ var init_resume_picker = __esm({
6973
7072
 
6974
7073
  // src/ui/task-list.tsx
6975
7074
  import { useEffect as useEffect2, useRef, useState as useState3 } from "react";
6976
- import { Box as Box8, Text as Text8 } from "ink";
7075
+ import { Box as Box9, Text as Text9 } from "ink";
6977
7076
  import Spinner4 from "ink-spinner";
6978
- import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
7077
+ import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
6979
7078
  function TaskList({ tasks, startedAt, tokensDelta }) {
6980
7079
  const theme = useTheme();
6981
7080
  const [now2, setNow] = useState3(Date.now());
@@ -6999,21 +7098,21 @@ function TaskList({ tasks, startedAt, tokensDelta }) {
6999
7098
  const allDone = done === total;
7000
7099
  const header = active ? active.title : allDone ? `${total} tasks done` : `${done}/${total}`;
7001
7100
  const elapsed = startedAt ? formatElapsed2(now2 - startedAt) : null;
7002
- const headerStats = [elapsed, tokensDelta > 0 ? `\u2191 ${formatTokens(tokensDelta)} tokens` : null].filter(Boolean).join(" \xB7 ");
7101
+ const headerStats = [elapsed, tokensDelta > 0 ? `\u2191 ${formatTokens2(tokensDelta)} tokens` : null].filter(Boolean).join(" \xB7 ");
7003
7102
  const visibleTasks = tasks.slice(0, MAX_VISIBLE);
7004
7103
  const hiddenPending = Math.max(0, tasks.length - visibleTasks.length);
7005
- return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", marginBottom: 1, children: [
7006
- /* @__PURE__ */ jsxs8(Box8, { children: [
7007
- /* @__PURE__ */ jsx9(Text8, { color: allDone ? "green" : theme.accent, bold: true, children: header }),
7008
- headerStats && /* @__PURE__ */ jsxs8(Text8, { color: theme.info.color, children: [
7104
+ return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", marginBottom: 1, children: [
7105
+ /* @__PURE__ */ jsxs9(Box9, { children: [
7106
+ /* @__PURE__ */ jsx10(Text9, { color: allDone ? "green" : theme.accent, bold: true, children: header }),
7107
+ headerStats && /* @__PURE__ */ jsxs9(Text9, { color: theme.info.color, children: [
7009
7108
  " ",
7010
7109
  "(",
7011
7110
  headerStats,
7012
7111
  ")"
7013
7112
  ] })
7014
7113
  ] }),
7015
- visibleTasks.map((t) => /* @__PURE__ */ jsx9(TaskRow, { task: t }, t.id)),
7016
- hiddenPending > 0 && /* @__PURE__ */ jsxs8(Text8, { color: theme.info.color, children: [
7114
+ visibleTasks.map((t) => /* @__PURE__ */ jsx10(TaskRow, { task: t }, t.id)),
7115
+ hiddenPending > 0 && /* @__PURE__ */ jsxs9(Text9, { color: theme.info.color, children: [
7017
7116
  " ",
7018
7117
  "\u2026 +",
7019
7118
  hiddenPending,
@@ -7024,21 +7123,21 @@ function TaskList({ tasks, startedAt, tokensDelta }) {
7024
7123
  function TaskRow({ task }) {
7025
7124
  const theme = useTheme();
7026
7125
  if (task.status === "completed") {
7027
- return /* @__PURE__ */ jsxs8(Text8, { color: theme.info.color, children: [
7126
+ return /* @__PURE__ */ jsxs9(Text9, { color: theme.info.color, children: [
7028
7127
  " ",
7029
7128
  "\u2713 ",
7030
- /* @__PURE__ */ jsx9(Text8, { strikethrough: true, children: task.title })
7129
+ /* @__PURE__ */ jsx10(Text9, { strikethrough: true, children: task.title })
7031
7130
  ] });
7032
7131
  }
7033
7132
  if (task.status === "in_progress") {
7034
- return /* @__PURE__ */ jsxs8(Text8, { color: theme.accent, bold: true, children: [
7133
+ return /* @__PURE__ */ jsxs9(Text9, { color: theme.accent, bold: true, children: [
7035
7134
  " ",
7036
- /* @__PURE__ */ jsx9(Spinner4, { type: "dots" }),
7135
+ /* @__PURE__ */ jsx10(Spinner4, { type: "dots" }),
7037
7136
  " ",
7038
7137
  task.title
7039
7138
  ] });
7040
7139
  }
7041
- return /* @__PURE__ */ jsxs8(Text8, { color: theme.info.color, children: [
7140
+ return /* @__PURE__ */ jsxs9(Text9, { color: theme.info.color, children: [
7042
7141
  " ",
7043
7142
  "\u2610 ",
7044
7143
  task.title
@@ -7051,7 +7150,7 @@ function formatElapsed2(ms) {
7051
7150
  if (m === 0) return `${s}s`;
7052
7151
  return `${m}m ${s}s`;
7053
7152
  }
7054
- function formatTokens(n) {
7153
+ function formatTokens2(n) {
7055
7154
  if (n < 1e3) return String(n);
7056
7155
  return `${(n / 1e3).toFixed(1)}k`;
7057
7156
  }
@@ -7586,8 +7685,8 @@ var init_source = __esm({
7586
7685
 
7587
7686
  // src/ui/text-input.tsx
7588
7687
  import { useState as useState4, useEffect as useEffect3, useRef as useRef2 } from "react";
7589
- import { Text as Text9, useInput } from "ink";
7590
- import { jsx as jsx10 } from "react/jsx-runtime";
7688
+ import { Text as Text10, useInput } from "ink";
7689
+ import { jsx as jsx11 } from "react/jsx-runtime";
7591
7690
  function shouldTreatAsPaste(input) {
7592
7691
  if (input.length >= PASTE_CHAR_THRESHOLD) return true;
7593
7692
  const newlines = (input.match(/\n/g) ?? []).length;
@@ -7797,7 +7896,7 @@ function CustomTextInput({
7797
7896
  } else if (cursorOffset === displayValue.length) {
7798
7897
  renderedValue += source_default.inverse(" ");
7799
7898
  }
7800
- return /* @__PURE__ */ jsx10(Text9, { children: renderedValue });
7899
+ return /* @__PURE__ */ jsx11(Text10, { children: renderedValue });
7801
7900
  }
7802
7901
  function findPasteTokenEndingAt(value, pos, pastes) {
7803
7902
  if (pos <= 0 || value[pos - 1] !== "]") return -1;
@@ -7819,11 +7918,28 @@ var init_text_input = __esm({
7819
7918
  });
7820
7919
 
7821
7920
  // src/ui/onboarding.tsx
7822
- import { useState as useState5 } from "react";
7823
- import { Box as Box9, Text as Text10 } from "ink";
7824
- import SelectInput3 from "ink-select-input";
7825
- import { Fragment, jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
7826
- function Onboarding({ onDone }) {
7921
+ import { useState as useState5, useEffect as useEffect4, useCallback } from "react";
7922
+ import { Box as Box10, Text as Text11, useInput as useInput2 } from "ink";
7923
+ import SelectInput4 from "ink-select-input";
7924
+ import Spinner5 from "ink-spinner";
7925
+ import { exec } from "child_process";
7926
+ import { promisify as promisify2 } from "util";
7927
+ import { Fragment, jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
7928
+ function openBrowser(url) {
7929
+ const platform3 = process.platform;
7930
+ const cmd = platform3 === "darwin" ? `open "${url}"` : platform3 === "win32" ? `start "" "${url}"` : `xdg-open "${url}"`;
7931
+ exec(cmd, (err) => {
7932
+ if (err) {
7933
+ }
7934
+ });
7935
+ }
7936
+ function formatRemaining(ms) {
7937
+ const totalSeconds = Math.ceil(ms / 1e3);
7938
+ const mins = Math.floor(totalSeconds / 60);
7939
+ const secs = totalSeconds % 60;
7940
+ return `${mins}:${secs.toString().padStart(2, "0")}`;
7941
+ }
7942
+ function Onboarding({ onDone, onCancel }) {
7827
7943
  const theme = useTheme();
7828
7944
  const [step, setStep] = useState5("mode");
7829
7945
  const [mode, setMode] = useState5("byok");
@@ -7831,15 +7947,109 @@ function Onboarding({ onDone }) {
7831
7947
  const [apiToken, setApiToken] = useState5("");
7832
7948
  const [model, setModel] = useState5(DEFAULT_MODEL);
7833
7949
  const [savedPath, setSavedPath] = useState5(null);
7950
+ const [cloudAuth, setCloudAuth] = useState5(null);
7951
+ const [pollTick, setPollTick] = useState5(0);
7952
+ useEffect4(() => {
7953
+ if (step !== "cloudAuth" || !cloudAuth) return;
7954
+ if (cloudAuth.phase !== "polling") return;
7955
+ let cancelled = false;
7956
+ const tick = setInterval(() => {
7957
+ setPollTick((t) => t + 1);
7958
+ }, 1e3);
7959
+ const poll = async () => {
7960
+ while (!cancelled) {
7961
+ const elapsed = Date.now() - cloudAuth.startTime;
7962
+ if (elapsed >= POLL_TIMEOUT_MS) {
7963
+ if (!cancelled) {
7964
+ setCloudAuth({ phase: "error", message: "Authentication timed out. Please try again." });
7965
+ }
7966
+ return;
7967
+ }
7968
+ try {
7969
+ const creds = await pollForToken(cloudAuth.codes.deviceCode);
7970
+ if (creds && !cancelled) {
7971
+ const usage = await fetchCloudUsage(creds.accessToken);
7972
+ if (usage && !cancelled) {
7973
+ setCloudAuth({
7974
+ phase: "success",
7975
+ creds,
7976
+ usage
7977
+ });
7978
+ } else if (!cancelled) {
7979
+ setCloudAuth({ phase: "error", message: "Authenticated but failed to fetch usage." });
7980
+ }
7981
+ return;
7982
+ }
7983
+ } catch {
7984
+ }
7985
+ await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
7986
+ }
7987
+ };
7988
+ poll();
7989
+ return () => {
7990
+ cancelled = true;
7991
+ clearInterval(tick);
7992
+ };
7993
+ }, [step, cloudAuth]);
7994
+ useInput2(
7995
+ useCallback(
7996
+ (_input, key) => {
7997
+ if (key.escape && onCancel) {
7998
+ onCancel();
7999
+ }
8000
+ },
8001
+ [onCancel]
8002
+ )
8003
+ );
8004
+ const startCloudAuth = useCallback(async () => {
8005
+ try {
8006
+ const codes = generateDeviceCodes();
8007
+ await registerDevice(codes);
8008
+ setCloudAuth({ phase: "ready", codes });
8009
+ setStep("cloudAuth");
8010
+ } catch (err) {
8011
+ setCloudAuth({
8012
+ phase: "error",
8013
+ message: err instanceof Error ? err.message : "Failed to start authentication"
8014
+ });
8015
+ setStep("cloudAuth");
8016
+ }
8017
+ }, []);
7834
8018
  const handleModeSelect = (item) => {
7835
8019
  if (item.value === "cloud") {
7836
8020
  setMode("cloud");
7837
- setStep("cloudDone");
8021
+ void startCloudAuth();
7838
8022
  } else {
7839
8023
  setMode("byok");
7840
8024
  setStep("accountId");
7841
8025
  }
7842
8026
  };
8027
+ const handleOpenBrowser = () => {
8028
+ if (cloudAuth?.phase === "ready") {
8029
+ openBrowser(cloudAuth.codes.authUrl);
8030
+ setCloudAuth({ phase: "polling", codes: cloudAuth.codes, startTime: Date.now() });
8031
+ }
8032
+ };
8033
+ const handleCloudSuccess = async () => {
8034
+ if (cloudAuth?.phase !== "success") return;
8035
+ const cfg = { accountId: "", apiToken: "", model: DEFAULT_MODEL, cloudMode: true };
8036
+ try {
8037
+ const path = await saveConfig(cfg);
8038
+ setSavedPath(path);
8039
+ onDone(cfg);
8040
+ } catch (e) {
8041
+ setSavedPath(`error: ${e.message}`);
8042
+ }
8043
+ };
8044
+ const handleCloudRetry = () => {
8045
+ setCloudAuth(null);
8046
+ void startCloudAuth();
8047
+ };
8048
+ const handleCloudSwitchToByok = () => {
8049
+ setCloudAuth(null);
8050
+ setMode("byok");
8051
+ setStep("accountId");
8052
+ };
7843
8053
  const handleAccountIdSubmit = (value) => {
7844
8054
  const trimmed = value.trim();
7845
8055
  if (!trimmed) return;
@@ -7858,17 +8068,7 @@ function Onboarding({ onDone }) {
7858
8068
  setStep("confirm");
7859
8069
  };
7860
8070
  const handleConfirm = async () => {
7861
- const cfg = mode === "cloud" ? { accountId: "", apiToken: "", model, cloudMode: true } : { accountId, apiToken, model };
7862
- try {
7863
- const path = await saveConfig(cfg);
7864
- setSavedPath(path);
7865
- onDone(cfg);
7866
- } catch (e) {
7867
- setSavedPath(`error: ${e.message}`);
7868
- }
7869
- };
7870
- const handleCloudSave = async () => {
7871
- const cfg = { accountId: "", apiToken: "", model: DEFAULT_MODEL, cloudMode: true };
8071
+ const cfg = { accountId, apiToken, model };
7872
8072
  try {
7873
8073
  const path = await saveConfig(cfg);
7874
8074
  setSavedPath(path);
@@ -7878,27 +8078,27 @@ function Onboarding({ onDone }) {
7878
8078
  }
7879
8079
  };
7880
8080
  const byokSteps = ["accountId", "apiToken", "model", "confirm"];
7881
- const stepIndex = step === "mode" ? 1 : step === "cloudDone" ? 2 : byokSteps.indexOf(step) + 2;
8081
+ const stepIndex = step === "mode" ? 1 : step === "cloudAuth" ? 2 : byokSteps.indexOf(step) + 2;
7882
8082
  const totalSteps = mode === "cloud" ? 2 : byokSteps.length + 1;
7883
- return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", paddingY: 1, children: [
7884
- /* @__PURE__ */ jsxs9(Box9, { marginBottom: 1, children: [
7885
- /* @__PURE__ */ jsx11(Text10, { bold: true, color: theme.palette.primary, children: "kimiflare" }),
7886
- /* @__PURE__ */ jsxs9(Text10, { color: theme.info.color, children: [
8083
+ return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", paddingY: 1, children: [
8084
+ /* @__PURE__ */ jsxs10(Box10, { marginBottom: 1, children: [
8085
+ /* @__PURE__ */ jsx12(Text11, { bold: true, color: theme.palette.primary, children: "kimiflare" }),
8086
+ /* @__PURE__ */ jsxs10(Text11, { color: theme.info.color, children: [
7887
8087
  " ",
7888
8088
  "Terminal coding agent"
7889
8089
  ] })
7890
8090
  ] }),
7891
- /* @__PURE__ */ jsxs9(Text10, { color: theme.info.color, children: [
8091
+ /* @__PURE__ */ jsxs10(Text11, { color: theme.info.color, children: [
7892
8092
  "Step ",
7893
8093
  stepIndex,
7894
8094
  " of ",
7895
8095
  totalSteps
7896
8096
  ] }),
7897
- /* @__PURE__ */ jsxs9(Box9, { marginTop: 1, flexDirection: "column", children: [
7898
- step === "mode" && /* @__PURE__ */ jsxs9(Fragment, { children: [
7899
- /* @__PURE__ */ jsx11(Text10, { children: "How do you want to connect?" }),
7900
- /* @__PURE__ */ jsx11(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx11(
7901
- SelectInput3,
8097
+ /* @__PURE__ */ jsxs10(Box10, { marginTop: 1, flexDirection: "column", children: [
8098
+ step === "mode" && /* @__PURE__ */ jsxs10(Fragment, { children: [
8099
+ /* @__PURE__ */ jsx12(Text11, { children: "How do you want to connect?" }),
8100
+ /* @__PURE__ */ jsx12(Box10, { marginTop: 1, children: /* @__PURE__ */ jsx12(
8101
+ SelectInput4,
7902
8102
  {
7903
8103
  items: [
7904
8104
  { label: "Cloud (managed) \u2014 no API key needed", value: "cloud" },
@@ -7908,11 +8108,102 @@ function Onboarding({ onDone }) {
7908
8108
  }
7909
8109
  ) })
7910
8110
  ] }),
7911
- step === "accountId" && /* @__PURE__ */ jsxs9(Fragment, { children: [
7912
- /* @__PURE__ */ jsx11(Text10, { children: "Enter your Cloudflare Account ID" }),
7913
- /* @__PURE__ */ jsxs9(Box9, { marginTop: 1, children: [
7914
- /* @__PURE__ */ jsx11(Text10, { color: theme.palette.primary, children: "\u203A " }),
7915
- /* @__PURE__ */ jsx11(
8111
+ step === "cloudAuth" && cloudAuth?.phase === "ready" && /* @__PURE__ */ jsxs10(Fragment, { children: [
8112
+ /* @__PURE__ */ jsx12(Text11, { children: "Authenticating with Kimiflare Cloud..." }),
8113
+ /* @__PURE__ */ jsxs10(Box10, { marginTop: 1, flexDirection: "column", children: [
8114
+ /* @__PURE__ */ jsx12(Text11, { children: "1. Open this URL in your browser:" }),
8115
+ /* @__PURE__ */ jsx12(Text11, { color: theme.palette.primary, children: cloudAuth.codes.authUrl })
8116
+ ] }),
8117
+ /* @__PURE__ */ jsxs10(Box10, { marginTop: 1, children: [
8118
+ /* @__PURE__ */ jsx12(Text11, { children: "2. " }),
8119
+ /* @__PURE__ */ jsx12(Text11, { bold: true, children: "[Press Enter to open browser]" })
8120
+ ] }),
8121
+ /* @__PURE__ */ jsxs10(Box10, { marginTop: 1, children: [
8122
+ /* @__PURE__ */ jsx12(Text11, { color: theme.palette.primary, children: "\u203A " }),
8123
+ /* @__PURE__ */ jsx12(
8124
+ CustomTextInput,
8125
+ {
8126
+ value: "",
8127
+ onChange: () => {
8128
+ },
8129
+ onSubmit: handleOpenBrowser
8130
+ }
8131
+ )
8132
+ ] })
8133
+ ] }),
8134
+ step === "cloudAuth" && cloudAuth?.phase === "polling" && /* @__PURE__ */ jsxs10(Fragment, { children: [
8135
+ /* @__PURE__ */ jsxs10(Text11, { children: [
8136
+ /* @__PURE__ */ jsx12(Text11, { color: theme.spinner, children: /* @__PURE__ */ jsx12(Spinner5, { type: "dots" }) }),
8137
+ " ",
8138
+ "Waiting for authentication..."
8139
+ ] }),
8140
+ /* @__PURE__ */ jsxs10(Text11, { color: theme.info.color, children: [
8141
+ "Expires in ",
8142
+ formatRemaining(POLL_TIMEOUT_MS - (Date.now() - cloudAuth.startTime))
8143
+ ] }),
8144
+ /* @__PURE__ */ jsxs10(Text11, { color: theme.info.color, children: [
8145
+ "URL: ",
8146
+ cloudAuth.codes.authUrl
8147
+ ] })
8148
+ ] }),
8149
+ step === "cloudAuth" && cloudAuth?.phase === "success" && /* @__PURE__ */ jsxs10(Fragment, { children: [
8150
+ /* @__PURE__ */ jsx12(Text11, { color: theme.palette.success, children: "Authenticated!" }),
8151
+ /* @__PURE__ */ jsxs10(Box10, { marginTop: 1, flexDirection: "column", children: [
8152
+ /* @__PURE__ */ jsxs10(Text11, { children: [
8153
+ "Token budget:",
8154
+ " ",
8155
+ /* @__PURE__ */ jsxs10(Text11, { bold: true, children: [
8156
+ cloudAuth.usage.remaining.toLocaleString(),
8157
+ " /",
8158
+ " ",
8159
+ cloudAuth.usage.input_token_limit.toLocaleString()
8160
+ ] }),
8161
+ " ",
8162
+ "remaining"
8163
+ ] }),
8164
+ /* @__PURE__ */ jsxs10(Text11, { color: theme.info.color, children: [
8165
+ "Grant expires: ",
8166
+ cloudAuth.usage.expires_at
8167
+ ] })
8168
+ ] }),
8169
+ /* @__PURE__ */ jsx12(Box10, { marginTop: 1, children: /* @__PURE__ */ jsx12(Text11, { children: "[Press Enter to continue]" }) }),
8170
+ /* @__PURE__ */ jsxs10(Box10, { marginTop: 1, children: [
8171
+ /* @__PURE__ */ jsx12(Text11, { color: theme.palette.primary, children: "\u203A " }),
8172
+ /* @__PURE__ */ jsx12(
8173
+ CustomTextInput,
8174
+ {
8175
+ value: "",
8176
+ onChange: () => {
8177
+ },
8178
+ onSubmit: handleCloudSuccess
8179
+ }
8180
+ )
8181
+ ] })
8182
+ ] }),
8183
+ step === "cloudAuth" && cloudAuth?.phase === "error" && /* @__PURE__ */ jsxs10(Fragment, { children: [
8184
+ /* @__PURE__ */ jsx12(Text11, { color: theme.palette.error, children: "Authentication failed" }),
8185
+ /* @__PURE__ */ jsx12(Text11, { color: theme.info.color, children: cloudAuth.message }),
8186
+ /* @__PURE__ */ jsx12(Box10, { marginTop: 1, children: /* @__PURE__ */ jsx12(
8187
+ SelectInput4,
8188
+ {
8189
+ items: [
8190
+ { label: "Retry", value: "retry" },
8191
+ { label: "Switch to BYOK", value: "byok" },
8192
+ { label: "Cancel", value: "cancel" }
8193
+ ],
8194
+ onSelect: (item) => {
8195
+ if (item.value === "retry") handleCloudRetry();
8196
+ else if (item.value === "byok") handleCloudSwitchToByok();
8197
+ else if (onCancel) onCancel();
8198
+ }
8199
+ }
8200
+ ) })
8201
+ ] }),
8202
+ step === "accountId" && /* @__PURE__ */ jsxs10(Fragment, { children: [
8203
+ /* @__PURE__ */ jsx12(Text11, { children: "Enter your Cloudflare Account ID" }),
8204
+ /* @__PURE__ */ jsxs10(Box10, { marginTop: 1, children: [
8205
+ /* @__PURE__ */ jsx12(Text11, { color: theme.palette.primary, children: "\u203A " }),
8206
+ /* @__PURE__ */ jsx12(
7916
8207
  CustomTextInput,
7917
8208
  {
7918
8209
  value: accountId,
@@ -7922,12 +8213,12 @@ function Onboarding({ onDone }) {
7922
8213
  )
7923
8214
  ] })
7924
8215
  ] }),
7925
- step === "apiToken" && /* @__PURE__ */ jsxs9(Fragment, { children: [
7926
- /* @__PURE__ */ jsx11(Text10, { children: "Enter your Cloudflare API Token" }),
7927
- /* @__PURE__ */ jsx11(Text10, { color: theme.info.color, children: "Create one at https://dash.cloudflare.com/profile/api-tokens" }),
7928
- /* @__PURE__ */ jsxs9(Box9, { marginTop: 1, children: [
7929
- /* @__PURE__ */ jsx11(Text10, { color: theme.palette.primary, children: "\u203A " }),
7930
- /* @__PURE__ */ jsx11(
8216
+ step === "apiToken" && /* @__PURE__ */ jsxs10(Fragment, { children: [
8217
+ /* @__PURE__ */ jsx12(Text11, { children: "Enter your Cloudflare API Token" }),
8218
+ /* @__PURE__ */ jsx12(Text11, { color: theme.info.color, children: "Create one at https://dash.cloudflare.com/profile/api-tokens" }),
8219
+ /* @__PURE__ */ jsxs10(Box10, { marginTop: 1, children: [
8220
+ /* @__PURE__ */ jsx12(Text11, { color: theme.palette.primary, children: "\u203A " }),
8221
+ /* @__PURE__ */ jsx12(
7931
8222
  CustomTextInput,
7932
8223
  {
7933
8224
  value: apiToken,
@@ -7938,15 +8229,15 @@ function Onboarding({ onDone }) {
7938
8229
  )
7939
8230
  ] })
7940
8231
  ] }),
7941
- step === "model" && /* @__PURE__ */ jsxs9(Fragment, { children: [
7942
- /* @__PURE__ */ jsx11(Text10, { children: "Model ID (press Enter for default)" }),
7943
- /* @__PURE__ */ jsxs9(Text10, { color: theme.info.color, children: [
8232
+ step === "model" && /* @__PURE__ */ jsxs10(Fragment, { children: [
8233
+ /* @__PURE__ */ jsx12(Text11, { children: "Model ID (press Enter for default)" }),
8234
+ /* @__PURE__ */ jsxs10(Text11, { color: theme.info.color, children: [
7944
8235
  "default: ",
7945
8236
  DEFAULT_MODEL
7946
8237
  ] }),
7947
- /* @__PURE__ */ jsxs9(Box9, { marginTop: 1, children: [
7948
- /* @__PURE__ */ jsx11(Text10, { color: theme.palette.primary, children: "\u203A " }),
7949
- /* @__PURE__ */ jsx11(
8238
+ /* @__PURE__ */ jsxs10(Box10, { marginTop: 1, children: [
8239
+ /* @__PURE__ */ jsx12(Text11, { color: theme.palette.primary, children: "\u203A " }),
8240
+ /* @__PURE__ */ jsx12(
7950
8241
  CustomTextInput,
7951
8242
  {
7952
8243
  value: model,
@@ -7956,10 +8247,10 @@ function Onboarding({ onDone }) {
7956
8247
  )
7957
8248
  ] })
7958
8249
  ] }),
7959
- step === "confirm" && /* @__PURE__ */ jsxs9(Fragment, { children: [
7960
- /* @__PURE__ */ jsx11(Text10, { children: "Ready to save configuration" }),
7961
- /* @__PURE__ */ jsxs9(
7962
- Box9,
8250
+ step === "confirm" && /* @__PURE__ */ jsxs10(Fragment, { children: [
8251
+ /* @__PURE__ */ jsx12(Text11, { children: "Ready to save configuration" }),
8252
+ /* @__PURE__ */ jsxs10(
8253
+ Box10,
7963
8254
  {
7964
8255
  flexDirection: "column",
7965
8256
  marginTop: 1,
@@ -7968,25 +8259,25 @@ function Onboarding({ onDone }) {
7968
8259
  borderColor: theme.info.color,
7969
8260
  paddingX: 1,
7970
8261
  children: [
7971
- /* @__PURE__ */ jsxs9(Text10, { color: theme.info.color, children: [
8262
+ /* @__PURE__ */ jsxs10(Text11, { color: theme.info.color, children: [
7972
8263
  "Account ID: ",
7973
8264
  accountId
7974
8265
  ] }),
7975
- /* @__PURE__ */ jsxs9(Text10, { color: theme.info.color, children: [
8266
+ /* @__PURE__ */ jsxs10(Text11, { color: theme.info.color, children: [
7976
8267
  "API Token: ",
7977
8268
  "\u2022".repeat(apiToken.length)
7978
8269
  ] }),
7979
- /* @__PURE__ */ jsxs9(Text10, { color: theme.info.color, children: [
8270
+ /* @__PURE__ */ jsxs10(Text11, { color: theme.info.color, children: [
7980
8271
  "Model: ",
7981
8272
  model
7982
8273
  ] })
7983
8274
  ]
7984
8275
  }
7985
8276
  ),
7986
- /* @__PURE__ */ jsx11(Text10, { children: "Press Enter to confirm, or Ctrl+C to cancel" }),
7987
- /* @__PURE__ */ jsxs9(Box9, { marginTop: 1, children: [
7988
- /* @__PURE__ */ jsx11(Text10, { color: theme.palette.primary, children: "\u203A " }),
7989
- /* @__PURE__ */ jsx11(
8277
+ /* @__PURE__ */ jsx12(Text11, { children: "Press Enter to confirm, or Ctrl+C to cancel" }),
8278
+ /* @__PURE__ */ jsxs10(Box10, { marginTop: 1, children: [
8279
+ /* @__PURE__ */ jsx12(Text11, { color: theme.palette.primary, children: "\u203A " }),
8280
+ /* @__PURE__ */ jsx12(
7990
8281
  CustomTextInput,
7991
8282
  {
7992
8283
  value: "",
@@ -7997,68 +8288,54 @@ function Onboarding({ onDone }) {
7997
8288
  )
7998
8289
  ] })
7999
8290
  ] }),
8000
- step === "cloudDone" && /* @__PURE__ */ jsxs9(Fragment, { children: [
8001
- /* @__PURE__ */ jsx11(Text10, { children: "Cloud mode selected" }),
8002
- /* @__PURE__ */ jsx11(Text10, { color: theme.info.color, children: "No API key needed. Run `kimiflare auth cloud` to sign in." }),
8003
- /* @__PURE__ */ jsx11(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx11(Text10, { children: "Press Enter to save, or Ctrl+C to cancel" }) }),
8004
- /* @__PURE__ */ jsxs9(Box9, { marginTop: 1, children: [
8005
- /* @__PURE__ */ jsx11(Text10, { color: theme.palette.primary, children: "\u203A " }),
8006
- /* @__PURE__ */ jsx11(
8007
- CustomTextInput,
8008
- {
8009
- value: "",
8010
- onChange: () => {
8011
- },
8012
- onSubmit: handleCloudSave
8013
- }
8014
- )
8015
- ] })
8016
- ] }),
8017
- savedPath && /* @__PURE__ */ jsxs9(Text10, { color: theme.palette.success, children: [
8291
+ savedPath && /* @__PURE__ */ jsxs10(Text11, { color: theme.palette.success, children: [
8018
8292
  "Config saved to ",
8019
8293
  savedPath
8020
8294
  ] })
8021
8295
  ] })
8022
8296
  ] });
8023
8297
  }
8298
+ var execAsync;
8024
8299
  var init_onboarding = __esm({
8025
8300
  "src/ui/onboarding.tsx"() {
8026
8301
  "use strict";
8027
8302
  init_text_input();
8028
8303
  init_config();
8029
8304
  init_theme_context();
8305
+ init_auth();
8306
+ execAsync = promisify2(exec);
8030
8307
  }
8031
8308
  });
8032
8309
 
8033
8310
  // src/ui/welcome.tsx
8034
- import { Box as Box10, Text as Text11 } from "ink";
8035
- import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
8311
+ import { Box as Box11, Text as Text12 } from "ink";
8312
+ import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
8036
8313
  function Welcome({ accountId }) {
8037
8314
  const theme = useTheme();
8038
- return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", marginBottom: 1, children: [
8039
- /* @__PURE__ */ jsxs10(Box10, { marginBottom: 1, children: [
8040
- /* @__PURE__ */ jsx12(Text11, { bold: true, color: theme.accent, children: "kimiflare" }),
8041
- /* @__PURE__ */ jsxs10(Text11, { color: theme.info.color, children: [
8315
+ return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", marginBottom: 1, children: [
8316
+ /* @__PURE__ */ jsxs11(Box11, { marginBottom: 1, children: [
8317
+ /* @__PURE__ */ jsx13(Text12, { bold: true, color: theme.accent, children: "kimiflare" }),
8318
+ /* @__PURE__ */ jsxs11(Text12, { color: theme.info.color, children: [
8042
8319
  " ",
8043
8320
  "Ready when you are."
8044
8321
  ] })
8045
8322
  ] }),
8046
- accountId && /* @__PURE__ */ jsx12(Box10, { marginBottom: 1, children: /* @__PURE__ */ jsxs10(Text11, { color: theme.info.color, children: [
8323
+ accountId && /* @__PURE__ */ jsx13(Box11, { marginBottom: 1, children: /* @__PURE__ */ jsxs11(Text12, { color: theme.info.color, children: [
8047
8324
  " ",
8048
8325
  "Check your Cloudflare billing: https://dash.cloudflare.com/",
8049
8326
  accountId,
8050
8327
  "/billing/billable-usage"
8051
8328
  ] }) }),
8052
- /* @__PURE__ */ jsx12(Box10, { flexDirection: "column", children: SUGGESTIONS.map((s, i) => /* @__PURE__ */ jsxs10(Box10, { children: [
8053
- /* @__PURE__ */ jsxs10(Text11, { color: theme.info.color, children: [
8329
+ /* @__PURE__ */ jsx13(Box11, { flexDirection: "column", children: SUGGESTIONS.map((s, i) => /* @__PURE__ */ jsxs11(Box11, { children: [
8330
+ /* @__PURE__ */ jsxs11(Text12, { color: theme.info.color, children: [
8054
8331
  " ",
8055
8332
  "\u203A",
8056
8333
  " "
8057
8334
  ] }),
8058
- /* @__PURE__ */ jsx12(Text11, { color: theme.user, children: s })
8335
+ /* @__PURE__ */ jsx13(Text12, { color: theme.user, children: s })
8059
8336
  ] }, i)) }),
8060
- /* @__PURE__ */ jsx12(Box10, { marginTop: 1, children: /* @__PURE__ */ jsx12(Text11, { color: theme.info.color, children: "Type a message or /help for commands \xB7 ctrl-c to exit \xB7 shift+tab to cycle modes" }) }),
8061
- /* @__PURE__ */ jsx12(Box10, { children: /* @__PURE__ */ jsx12(Text11, { color: theme.info.color, children: "Tip: type /hello to send feedback to the creator" }) })
8337
+ /* @__PURE__ */ jsx13(Box11, { marginTop: 1, children: /* @__PURE__ */ jsx13(Text12, { color: theme.info.color, children: "Type a message or /help for commands \xB7 ctrl-c to exit \xB7 shift+tab to cycle modes" }) }),
8338
+ /* @__PURE__ */ jsx13(Box11, { children: /* @__PURE__ */ jsx13(Text12, { color: theme.info.color, children: "Tip: type /hello to send feedback to the creator" }) })
8062
8339
  ] });
8063
8340
  }
8064
8341
  var SUGGESTIONS;
@@ -8076,14 +8353,14 @@ var init_welcome = __esm({
8076
8353
 
8077
8354
  // src/ui/help-menu.tsx
8078
8355
  import { useState as useState6 } from "react";
8079
- import { Box as Box11, Text as Text12, useInput as useInput2 } from "ink";
8080
- import SelectInput4 from "ink-select-input";
8081
- import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
8356
+ import { Box as Box12, Text as Text13, useInput as useInput3 } from "ink";
8357
+ import SelectInput5 from "ink-select-input";
8358
+ import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
8082
8359
  function HelpMenu({ customCommands, costAttributionEnabled, cloudMode, onDone, onCommand }) {
8083
8360
  const theme = useTheme();
8084
8361
  const [page, setPage] = useState6("main");
8085
8362
  const customs = customCommands ?? [];
8086
- useInput2((_input, key) => {
8363
+ useInput3((_input, key) => {
8087
8364
  if (key.escape) {
8088
8365
  if (page !== "main") {
8089
8366
  setPage("main");
@@ -8107,11 +8384,11 @@ function HelpMenu({ customCommands, costAttributionEnabled, cloudMode, onDone, o
8107
8384
  items2.push({ label: "Run custom commands", value: "custom", key: "custom" });
8108
8385
  }
8109
8386
  items2.push({ label: "(close)", value: "__close__", key: "__close__" });
8110
- return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
8111
- /* @__PURE__ */ jsx13(Text12, { color: theme.accent, bold: true, children: "Help" }),
8112
- /* @__PURE__ */ jsx13(Text12, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select, Esc to close." }),
8113
- /* @__PURE__ */ jsx13(Box11, { marginTop: 1, children: /* @__PURE__ */ jsx13(
8114
- SelectInput4,
8387
+ return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
8388
+ /* @__PURE__ */ jsx14(Text13, { color: theme.accent, bold: true, children: "Help" }),
8389
+ /* @__PURE__ */ jsx14(Text13, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select, Esc to close." }),
8390
+ /* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(
8391
+ SelectInput5,
8115
8392
  {
8116
8393
  items: items2,
8117
8394
  onSelect: (item) => {
@@ -8123,8 +8400,8 @@ function HelpMenu({ customCommands, costAttributionEnabled, cloudMode, onDone, o
8123
8400
  }
8124
8401
  }
8125
8402
  ) }),
8126
- /* @__PURE__ */ jsx13(Box11, { marginTop: 1, flexDirection: "column", children: SINGLE_COMMANDS.map((cmd) => /* @__PURE__ */ jsx13(Text12, { color: theme.info.color, dimColor: false, children: ` ${cmd.command.padEnd(20)} ${cmd.description}` }, cmd.command)) }),
8127
- /* @__PURE__ */ jsx13(Box11, { marginTop: 1, children: /* @__PURE__ */ jsx13(Text12, { color: theme.info.color, dimColor: false, children: "keys: ctrl-c interrupt/exit \xB7 ctrl-r toggle reasoning \xB7 ctrl-o verbose \xB7 shift+tab cycle mode \xB7 \u2191/\u2193 history" }) })
8403
+ /* @__PURE__ */ jsx14(Box12, { marginTop: 1, flexDirection: "column", children: SINGLE_COMMANDS.map((cmd) => /* @__PURE__ */ jsx14(Text13, { color: theme.info.color, dimColor: false, children: ` ${cmd.command.padEnd(20)} ${cmd.description}` }, cmd.command)) }),
8404
+ /* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(Text13, { color: theme.info.color, dimColor: false, children: "keys: ctrl-c interrupt/exit \xB7 ctrl-r toggle reasoning \xB7 ctrl-o verbose \xB7 shift+tab cycle mode \xB7 \u2191/\u2193 history" }) })
8128
8405
  ] });
8129
8406
  }
8130
8407
  if (page === "custom") {
@@ -8134,11 +8411,11 @@ function HelpMenu({ customCommands, costAttributionEnabled, cloudMode, onDone, o
8134
8411
  key: c.name
8135
8412
  }));
8136
8413
  items2.push({ label: "\u2190 Back", value: "__back__", key: "__back__" });
8137
- return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
8138
- /* @__PURE__ */ jsx13(Text12, { color: theme.accent, bold: true, children: "Custom commands" }),
8139
- /* @__PURE__ */ jsx13(Text12, { 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." }),
8140
- /* @__PURE__ */ jsx13(Box11, { marginTop: 1, children: /* @__PURE__ */ jsx13(
8141
- SelectInput4,
8414
+ return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
8415
+ /* @__PURE__ */ jsx14(Text13, { color: theme.accent, bold: true, children: "Custom commands" }),
8416
+ /* @__PURE__ */ jsx14(Text13, { 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." }),
8417
+ /* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(
8418
+ SelectInput5,
8142
8419
  {
8143
8420
  items: items2,
8144
8421
  onSelect: (item) => {
@@ -8161,11 +8438,11 @@ function HelpMenu({ customCommands, costAttributionEnabled, cloudMode, onDone, o
8161
8438
  key: cmd.command
8162
8439
  }));
8163
8440
  items.push({ label: "\u2190 Back", value: "__back__", key: "__back__" });
8164
- return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
8165
- /* @__PURE__ */ jsx13(Text12, { color: theme.accent, bold: true, children: category.label }),
8166
- /* @__PURE__ */ jsx13(Text12, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to execute, Esc to go back." }),
8167
- /* @__PURE__ */ jsx13(Box11, { marginTop: 1, children: /* @__PURE__ */ jsx13(
8168
- SelectInput4,
8441
+ return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
8442
+ /* @__PURE__ */ jsx14(Text13, { color: theme.accent, bold: true, children: category.label }),
8443
+ /* @__PURE__ */ jsx14(Text13, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to execute, Esc to go back." }),
8444
+ /* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(
8445
+ SelectInput5,
8169
8446
  {
8170
8447
  items,
8171
8448
  onSelect: (item) => {
@@ -8177,7 +8454,7 @@ function HelpMenu({ customCommands, costAttributionEnabled, cloudMode, onDone, o
8177
8454
  }
8178
8455
  }
8179
8456
  ) }),
8180
- staticCmds.length > 0 && /* @__PURE__ */ jsx13(Box11, { marginTop: 1, flexDirection: "column", children: staticCmds.map((cmd) => /* @__PURE__ */ jsx13(Text12, { color: theme.info.color, children: ` ${cmd.command.padEnd(28)} ${cmd.description}` }, cmd.command)) })
8457
+ staticCmds.length > 0 && /* @__PURE__ */ jsx14(Box12, { marginTop: 1, flexDirection: "column", children: staticCmds.map((cmd) => /* @__PURE__ */ jsx14(Text13, { color: theme.info.color, children: ` ${cmd.command.padEnd(28)} ${cmd.description}` }, cmd.command)) })
8181
8458
  ] });
8182
8459
  }
8183
8460
  var CATEGORIES, SINGLE_COMMANDS;
@@ -8409,17 +8686,17 @@ var init_tui_deploy = __esm({
8409
8686
  });
8410
8687
 
8411
8688
  // src/ui/remote-dashboard.tsx
8412
- import { useEffect as useEffect4, useState as useState7 } from "react";
8413
- import { Box as Box12, Text as Text13, useInput as useInput3 } from "ink";
8414
- import SelectInput5 from "ink-select-input";
8415
- import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
8689
+ import { useEffect as useEffect5, useState as useState7 } from "react";
8690
+ import { Box as Box13, Text as Text14, useInput as useInput4 } from "ink";
8691
+ import SelectInput6 from "ink-select-input";
8692
+ import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
8416
8693
  function RemoteDashboard({ onSelect, onCancel }) {
8417
8694
  const theme = useTheme();
8418
8695
  const [sessions, setSessions] = useState7([]);
8419
8696
  const [loading, setLoading] = useState7(true);
8420
8697
  const [error, setError] = useState7(null);
8421
8698
  const [refreshing, setRefreshing] = useState7(false);
8422
- useEffect4(() => {
8699
+ useEffect5(() => {
8423
8700
  loadSessions();
8424
8701
  }, []);
8425
8702
  async function loadSessions() {
@@ -8455,7 +8732,7 @@ function RemoteDashboard({ onSelect, onCancel }) {
8455
8732
  setRefreshing(false);
8456
8733
  }
8457
8734
  }
8458
- useInput3((input, key) => {
8735
+ useInput4((input, key) => {
8459
8736
  if (input === "r" || input === "R") {
8460
8737
  void loadSessions();
8461
8738
  }
@@ -8468,31 +8745,31 @@ function RemoteDashboard({ onSelect, onCancel }) {
8468
8745
  value: s.sessionId
8469
8746
  }));
8470
8747
  if (loading) {
8471
- return /* @__PURE__ */ jsx14(Box12, { flexDirection: "column", padding: 1, children: /* @__PURE__ */ jsx14(Text13, { color: theme.accent, children: "Loading remote sessions..." }) });
8748
+ return /* @__PURE__ */ jsx15(Box13, { flexDirection: "column", padding: 1, children: /* @__PURE__ */ jsx15(Text14, { color: theme.accent, children: "Loading remote sessions..." }) });
8472
8749
  }
8473
8750
  if (error) {
8474
- return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", padding: 1, children: [
8475
- /* @__PURE__ */ jsxs12(Text13, { color: theme.error, children: [
8751
+ return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", padding: 1, children: [
8752
+ /* @__PURE__ */ jsxs13(Text14, { color: theme.error, children: [
8476
8753
  "Error: ",
8477
8754
  error
8478
8755
  ] }),
8479
- /* @__PURE__ */ jsx14(Text13, { dimColor: true, children: "Press R to retry, Esc to close" })
8756
+ /* @__PURE__ */ jsx15(Text14, { dimColor: true, children: "Press R to retry, Esc to close" })
8480
8757
  ] });
8481
8758
  }
8482
8759
  if (sessions.length === 0) {
8483
- return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", padding: 1, children: [
8484
- /* @__PURE__ */ jsx14(Text13, { color: theme.accent, children: "No remote sessions yet." }),
8485
- /* @__PURE__ */ jsx14(Text13, { dimColor: true, children: "Type /remote <prompt> to start one." }),
8486
- /* @__PURE__ */ jsx14(Text13, { dimColor: true, children: "Press Esc to close" })
8760
+ return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", padding: 1, children: [
8761
+ /* @__PURE__ */ jsx15(Text14, { color: theme.accent, children: "No remote sessions yet." }),
8762
+ /* @__PURE__ */ jsx15(Text14, { dimColor: true, children: "Type /remote <prompt> to start one." }),
8763
+ /* @__PURE__ */ jsx15(Text14, { dimColor: true, children: "Press Esc to close" })
8487
8764
  ] });
8488
8765
  }
8489
- return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", padding: 1, children: [
8490
- /* @__PURE__ */ jsxs12(Text13, { bold: true, color: theme.accent, children: [
8766
+ return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", padding: 1, children: [
8767
+ /* @__PURE__ */ jsxs13(Text14, { bold: true, color: theme.accent, children: [
8491
8768
  "Recent remote tasks ",
8492
8769
  refreshing ? "(refreshing...)" : ""
8493
8770
  ] }),
8494
- /* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(
8495
- SelectInput5,
8771
+ /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
8772
+ SelectInput6,
8496
8773
  {
8497
8774
  items,
8498
8775
  onSelect: (item) => {
@@ -8501,7 +8778,7 @@ function RemoteDashboard({ onSelect, onCancel }) {
8501
8778
  }
8502
8779
  }
8503
8780
  ) }),
8504
- /* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(Text13, { dimColor: true, children: "\u2191\u2193 navigate \u2022 Enter select \u2022 R refresh \u2022 Esc close" }) })
8781
+ /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(Text14, { dimColor: true, children: "\u2191\u2193 navigate \u2022 Enter select \u2022 R refresh \u2022 Esc close" }) })
8505
8782
  ] });
8506
8783
  }
8507
8784
  function formatSessionLine(s) {
@@ -8509,7 +8786,7 @@ function formatSessionLine(s) {
8509
8786
  const ago = formatAgo(new Date(s.updatedAt));
8510
8787
  const prompt = s.prompt.slice(0, 30) + (s.prompt.length > 30 ? "\u2026" : "");
8511
8788
  const outcome = s.prUrl ? `PR ${s.prUrl.split("/").pop()}` : s.status;
8512
- const cost = s.tokensUsed && s.tokensBudget ? ` (${formatTokens2(s.tokensUsed)}/${formatTokens2(s.tokensBudget)})` : s.tokensUsed ? ` (${formatTokens2(s.tokensUsed)})` : "";
8789
+ const cost = s.tokensUsed && s.tokensBudget ? ` (${formatTokens3(s.tokensUsed)}/${formatTokens3(s.tokensBudget)})` : s.tokensUsed ? ` (${formatTokens3(s.tokensUsed)})` : "";
8513
8790
  return `${icon} ${prompt} \u2192 ${outcome} ${ago}${cost}`;
8514
8791
  }
8515
8792
  function formatAgo(date) {
@@ -8522,7 +8799,7 @@ function formatAgo(date) {
8522
8799
  if (minutes > 0) return `${minutes}m ago`;
8523
8800
  return "just now";
8524
8801
  }
8525
- function formatTokens2(n) {
8802
+ function formatTokens3(n) {
8526
8803
  if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
8527
8804
  if (n >= 1e3) return `${(n / 1e3).toFixed(1)}K`;
8528
8805
  return String(n);
@@ -8534,7 +8811,7 @@ function RemoteSessionDetail({
8534
8811
  }) {
8535
8812
  const theme = useTheme();
8536
8813
  const [cancelling, setCancelling] = useState7(false);
8537
- useInput3((input, key) => {
8814
+ useInput4((input, key) => {
8538
8815
  if (key.escape) {
8539
8816
  onBack();
8540
8817
  }
@@ -8554,50 +8831,50 @@ function RemoteSessionDetail({
8554
8831
  }
8555
8832
  }
8556
8833
  const isRunning = session.status === "running" || session.status === "pending";
8557
- return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", padding: 1, children: [
8558
- /* @__PURE__ */ jsx14(Text13, { bold: true, color: theme.accent, children: "Remote Session" }),
8559
- /* @__PURE__ */ jsxs12(Box12, { marginTop: 1, flexDirection: "column", children: [
8560
- /* @__PURE__ */ jsxs12(Text13, { children: [
8834
+ return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", padding: 1, children: [
8835
+ /* @__PURE__ */ jsx15(Text14, { bold: true, color: theme.accent, children: "Remote Session" }),
8836
+ /* @__PURE__ */ jsxs13(Box13, { marginTop: 1, flexDirection: "column", children: [
8837
+ /* @__PURE__ */ jsxs13(Text14, { children: [
8561
8838
  "ID: ",
8562
8839
  session.sessionId
8563
8840
  ] }),
8564
- /* @__PURE__ */ jsxs12(Text13, { children: [
8841
+ /* @__PURE__ */ jsxs13(Text14, { children: [
8565
8842
  "Repo: ",
8566
8843
  session.repo
8567
8844
  ] }),
8568
- /* @__PURE__ */ jsxs12(Text13, { children: [
8845
+ /* @__PURE__ */ jsxs13(Text14, { children: [
8569
8846
  "Status: ",
8570
8847
  session.status
8571
8848
  ] }),
8572
- /* @__PURE__ */ jsxs12(Text13, { children: [
8849
+ /* @__PURE__ */ jsxs13(Text14, { children: [
8573
8850
  "Prompt: ",
8574
8851
  session.prompt
8575
8852
  ] }),
8576
- session.prUrl && /* @__PURE__ */ jsxs12(Text13, { children: [
8853
+ session.prUrl && /* @__PURE__ */ jsxs13(Text14, { children: [
8577
8854
  "PR: ",
8578
8855
  session.prUrl
8579
8856
  ] }),
8580
- session.errorMessage && /* @__PURE__ */ jsxs12(Text13, { color: theme.error, children: [
8857
+ session.errorMessage && /* @__PURE__ */ jsxs13(Text14, { color: theme.error, children: [
8581
8858
  "Error: ",
8582
8859
  session.errorMessage
8583
8860
  ] }),
8584
- session.tokensUsed !== void 0 && /* @__PURE__ */ jsxs12(Text13, { children: [
8861
+ session.tokensUsed !== void 0 && /* @__PURE__ */ jsxs13(Text14, { children: [
8585
8862
  "Tokens: ",
8586
- formatTokens2(session.tokensUsed),
8587
- session.tokensBudget ? ` / ${formatTokens2(session.tokensBudget)}` : ""
8863
+ formatTokens3(session.tokensUsed),
8864
+ session.tokensBudget ? ` / ${formatTokens3(session.tokensBudget)}` : ""
8588
8865
  ] }),
8589
- /* @__PURE__ */ jsxs12(Text13, { children: [
8866
+ /* @__PURE__ */ jsxs13(Text14, { children: [
8590
8867
  "Created: ",
8591
8868
  new Date(session.createdAt).toLocaleString()
8592
8869
  ] }),
8593
- session.finishedAt && /* @__PURE__ */ jsxs12(Text13, { children: [
8870
+ session.finishedAt && /* @__PURE__ */ jsxs13(Text14, { children: [
8594
8871
  "Finished: ",
8595
8872
  new Date(session.finishedAt).toLocaleString()
8596
8873
  ] })
8597
8874
  ] }),
8598
- /* @__PURE__ */ jsxs12(Box12, { marginTop: 1, flexDirection: "row", gap: 2, children: [
8599
- isRunning && onCancel && /* @__PURE__ */ jsx14(Text13, { color: theme.error, children: cancelling ? "Cancelling..." : "[C] Cancel session" }),
8600
- /* @__PURE__ */ jsx14(Text13, { dimColor: true, children: "Esc back" })
8875
+ /* @__PURE__ */ jsxs13(Box13, { marginTop: 1, flexDirection: "row", gap: 2, children: [
8876
+ isRunning && onCancel && /* @__PURE__ */ jsx15(Text14, { color: theme.error, children: cancelling ? "Cancelling..." : "[C] Cancel session" }),
8877
+ /* @__PURE__ */ jsx15(Text14, { dimColor: true, children: "Esc back" })
8601
8878
  ] })
8602
8879
  ] });
8603
8880
  }
@@ -9502,8 +9779,8 @@ function computeExactScore(memory, queryText, cwd) {
9502
9779
  let score = 0;
9503
9780
  const lowerQuery = queryText.toLowerCase();
9504
9781
  for (const file of memory.relatedFiles) {
9505
- const basename4 = file.split("/").pop() ?? file;
9506
- if (lowerQuery.includes(basename4.toLowerCase()) || basename4.toLowerCase().includes(lowerQuery)) {
9782
+ const basename5 = file.split("/").pop() ?? file;
9783
+ if (lowerQuery.includes(basename5.toLowerCase()) || basename5.toLowerCase().includes(lowerQuery)) {
9507
9784
  score += 0.3;
9508
9785
  }
9509
9786
  if (cwd && file.startsWith(cwd)) {
@@ -10281,10 +10558,10 @@ var init_loader = __esm({
10281
10558
  });
10282
10559
 
10283
10560
  // src/commands/renderer.ts
10284
- import { exec } from "child_process";
10561
+ import { exec as exec2 } from "child_process";
10285
10562
  import { open as open2, realpath as realpath2 } from "fs/promises";
10286
10563
  import { isAbsolute as isAbsolute2, relative as relative5, resolve as resolvePathJoin, basename as pathBasename } from "path";
10287
- import { promisify as promisify2 } from "util";
10564
+ import { promisify as promisify3 } from "util";
10288
10565
  function tokenizeArgs(s) {
10289
10566
  return [...s.matchAll(ARG_TOKEN_RE)].map((match) => {
10290
10567
  const token = match[0];
@@ -10351,7 +10628,7 @@ async function replaceShell(prompt, warnings, cmd, shellTimeoutMs) {
10351
10628
  matches.map(async (match) => {
10352
10629
  const command = match[1] ?? "";
10353
10630
  try {
10354
- const { stdout } = await execAsync(command, {
10631
+ const { stdout } = await execAsync2(command, {
10355
10632
  timeout: shellTimeoutMs,
10356
10633
  maxBuffer: 1024 * 1024
10357
10634
  });
@@ -10432,12 +10709,12 @@ async function replaceFiles(prompt, warnings, cmd, cwd, maxFileBytes) {
10432
10709
  function message(error) {
10433
10710
  return error instanceof Error ? error.message : String(error);
10434
10711
  }
10435
- var execAsync, ARG_TOKEN_RE, POSITIONAL_RE, HAS_POSITIONAL, SHELL_RE, FILE_RE, DEFAULT_MAX_FILE_BYTES, DEFAULT_SHELL_TIMEOUT_MS, SECRET_PATTERNS2;
10712
+ var execAsync2, ARG_TOKEN_RE, POSITIONAL_RE, HAS_POSITIONAL, SHELL_RE, FILE_RE, DEFAULT_MAX_FILE_BYTES, DEFAULT_SHELL_TIMEOUT_MS, SECRET_PATTERNS2;
10436
10713
  var init_renderer2 = __esm({
10437
10714
  "src/commands/renderer.ts"() {
10438
10715
  "use strict";
10439
10716
  init_paths();
10440
- execAsync = promisify2(exec);
10717
+ execAsync2 = promisify3(exec2);
10441
10718
  ARG_TOKEN_RE = /(?:"[^"]*"|'[^']*'|[^\s"']+)/g;
10442
10719
  POSITIONAL_RE = /\$(\d+)/g;
10443
10720
  HAS_POSITIONAL = /\$\d+/;
@@ -10535,9 +10812,9 @@ var init_save = __esm({
10535
10812
 
10536
10813
  // src/ui/command-wizard.tsx
10537
10814
  import { useState as useState8 } from "react";
10538
- import { Box as Box13, Text as Text14, useInput as useInput4, useWindowSize as useWindowSize2 } from "ink";
10539
- import SelectInput6 from "ink-select-input";
10540
- import { Fragment as Fragment2, jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
10815
+ import { Box as Box14, Text as Text15, useInput as useInput5, useWindowSize as useWindowSize2 } from "ink";
10816
+ import SelectInput7 from "ink-select-input";
10817
+ import { Fragment as Fragment2, jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
10541
10818
  function CommandWizard({ mode, initial, existingNames, builtinNames, onDone, onSave }) {
10542
10819
  const theme = useTheme();
10543
10820
  const [step, setStep] = useState8("name");
@@ -10561,7 +10838,7 @@ function CommandWizard({ mode, initial, existingNames, builtinNames, onDone, onS
10561
10838
  if (existingNames.includes(trimmed) && !isEditingSelf(trimmed)) return `/${trimmed} already exists`;
10562
10839
  return null;
10563
10840
  };
10564
- useInput4((_input, key) => {
10841
+ useInput5((_input, key) => {
10565
10842
  if (key.escape) {
10566
10843
  onDone();
10567
10844
  }
@@ -10661,8 +10938,8 @@ ${template}`;
10661
10938
  const renderStep = () => {
10662
10939
  switch (step) {
10663
10940
  case "name":
10664
- return /* @__PURE__ */ jsxs13(Fragment2, { children: [
10665
- /* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
10941
+ return /* @__PURE__ */ jsxs14(Fragment2, { children: [
10942
+ /* @__PURE__ */ jsxs14(Text15, { color: theme.accent, bold: true, children: [
10666
10943
  mode === "create" ? "Create" : "Edit",
10667
10944
  " custom command \u2014 Name (",
10668
10945
  stepIndex,
@@ -10670,8 +10947,8 @@ ${template}`;
10670
10947
  totalSteps,
10671
10948
  ")"
10672
10949
  ] }),
10673
- error && /* @__PURE__ */ jsx15(Text14, { color: theme.error, children: error }),
10674
- /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
10950
+ error && /* @__PURE__ */ jsx16(Text15, { color: theme.error, children: error }),
10951
+ /* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(
10675
10952
  CustomTextInput,
10676
10953
  {
10677
10954
  value: name,
@@ -10680,11 +10957,11 @@ ${template}`;
10680
10957
  focus: true
10681
10958
  }
10682
10959
  ) }),
10683
- /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "letters, numbers, _ - / only; must start with a letter" })
10960
+ /* @__PURE__ */ jsx16(Text15, { color: theme.info.color, children: "letters, numbers, _ - / only; must start with a letter" })
10684
10961
  ] });
10685
10962
  case "description":
10686
- return /* @__PURE__ */ jsxs13(Fragment2, { children: [
10687
- /* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
10963
+ return /* @__PURE__ */ jsxs14(Fragment2, { children: [
10964
+ /* @__PURE__ */ jsxs14(Text15, { color: theme.accent, bold: true, children: [
10688
10965
  mode === "create" ? "Create" : "Edit",
10689
10966
  " custom command \u2014 Description (",
10690
10967
  stepIndex,
@@ -10692,7 +10969,7 @@ ${template}`;
10692
10969
  totalSteps,
10693
10970
  ")"
10694
10971
  ] }),
10695
- /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
10972
+ /* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(
10696
10973
  CustomTextInput,
10697
10974
  {
10698
10975
  value: description,
@@ -10701,49 +10978,49 @@ ${template}`;
10701
10978
  focus: true
10702
10979
  }
10703
10980
  ) }),
10704
- /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Press Enter to skip" })
10981
+ /* @__PURE__ */ jsx16(Text15, { color: theme.info.color, children: "Press Enter to skip" })
10705
10982
  ] });
10706
10983
  case "template": {
10707
- const guide = /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", paddingLeft: 1, children: [
10708
- /* @__PURE__ */ jsx15(Text14, { color: theme.accent, bold: true, children: "What is this?" }),
10709
- /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "A prompt template \u2014 instructions to the AI." }),
10710
- /* @__PURE__ */ jsxs13(Text14, { color: theme.info.color, children: [
10984
+ const guide = /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", paddingLeft: 1, children: [
10985
+ /* @__PURE__ */ jsx16(Text15, { color: theme.accent, bold: true, children: "What is this?" }),
10986
+ /* @__PURE__ */ jsx16(Text15, { color: theme.info.color, children: "A prompt template \u2014 instructions to the AI." }),
10987
+ /* @__PURE__ */ jsxs14(Text15, { color: theme.info.color, children: [
10711
10988
  "When you type /",
10712
10989
  name || "yourcommand",
10713
10990
  " later, this gets sent to the model."
10714
10991
  ] }),
10715
- /* @__PURE__ */ jsxs13(Box13, { marginTop: 1, flexDirection: "column", children: [
10716
- /* @__PURE__ */ jsx15(Text14, { color: theme.accent, bold: true, children: "Variables" }),
10717
- /* @__PURE__ */ jsxs13(Text14, { color: theme.info.color, children: [
10992
+ /* @__PURE__ */ jsxs14(Box14, { marginTop: 1, flexDirection: "column", children: [
10993
+ /* @__PURE__ */ jsx16(Text15, { color: theme.accent, bold: true, children: "Variables" }),
10994
+ /* @__PURE__ */ jsxs14(Text15, { color: theme.info.color, children: [
10718
10995
  " ",
10719
10996
  "$1, $2 ... \u2192 arguments you type"
10720
10997
  ] }),
10721
- /* @__PURE__ */ jsxs13(Text14, { color: theme.info.color, children: [
10998
+ /* @__PURE__ */ jsxs14(Text15, { color: theme.info.color, children: [
10722
10999
  " ",
10723
11000
  "$ARGUMENTS \u2192 everything after the command"
10724
11001
  ] })
10725
11002
  ] }),
10726
- /* @__PURE__ */ jsxs13(Box13, { marginTop: 1, flexDirection: "column", children: [
10727
- /* @__PURE__ */ jsx15(Text14, { color: theme.accent, bold: true, children: "Dynamic inlines" }),
10728
- /* @__PURE__ */ jsxs13(Text14, { color: theme.info.color, children: [
11003
+ /* @__PURE__ */ jsxs14(Box14, { marginTop: 1, flexDirection: "column", children: [
11004
+ /* @__PURE__ */ jsx16(Text15, { color: theme.accent, bold: true, children: "Dynamic inlines" }),
11005
+ /* @__PURE__ */ jsxs14(Text15, { color: theme.info.color, children: [
10729
11006
  " ",
10730
11007
  "!`git diff` \u2192 shell output inlined"
10731
11008
  ] }),
10732
- /* @__PURE__ */ jsxs13(Text14, { color: theme.info.color, children: [
11009
+ /* @__PURE__ */ jsxs14(Text15, { color: theme.info.color, children: [
10733
11010
  " ",
10734
11011
  "@README.md \u2192 file contents inlined"
10735
11012
  ] })
10736
11013
  ] }),
10737
- /* @__PURE__ */ jsxs13(Box13, { marginTop: 1, flexDirection: "column", children: [
10738
- /* @__PURE__ */ jsx15(Text14, { color: theme.accent, bold: true, children: "Example" }),
10739
- /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Review this PR diff:" }),
10740
- /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "!`git diff main...HEAD`" }),
10741
- /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Focus on: $1" })
11014
+ /* @__PURE__ */ jsxs14(Box14, { marginTop: 1, flexDirection: "column", children: [
11015
+ /* @__PURE__ */ jsx16(Text15, { color: theme.accent, bold: true, children: "Example" }),
11016
+ /* @__PURE__ */ jsx16(Text15, { color: theme.info.color, children: "Review this PR diff:" }),
11017
+ /* @__PURE__ */ jsx16(Text15, { color: theme.info.color, children: "!`git diff main...HEAD`" }),
11018
+ /* @__PURE__ */ jsx16(Text15, { color: theme.info.color, children: "Focus on: $1" })
10742
11019
  ] })
10743
11020
  ] });
10744
- const inputArea = /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", flexGrow: 1, children: [
10745
- error && /* @__PURE__ */ jsx15(Text14, { color: theme.error, children: error }),
10746
- /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
11021
+ const inputArea = /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", flexGrow: 1, children: [
11022
+ error && /* @__PURE__ */ jsx16(Text15, { color: theme.error, children: error }),
11023
+ /* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(
10747
11024
  CustomTextInput,
10748
11025
  {
10749
11026
  value: template,
@@ -10753,13 +11030,13 @@ ${template}`;
10753
11030
  enablePaste: true
10754
11031
  }
10755
11032
  ) }),
10756
- columns < 100 && /* @__PURE__ */ jsxs13(Fragment2, { children: [
10757
- /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Paste multi-line templates with Ctrl+V." }),
10758
- /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Variables: $1 $2 ... $ARGUMENTS Shell: !`cmd` File: @path" })
11033
+ columns < 100 && /* @__PURE__ */ jsxs14(Fragment2, { children: [
11034
+ /* @__PURE__ */ jsx16(Text15, { color: theme.info.color, children: "Paste multi-line templates with Ctrl+V." }),
11035
+ /* @__PURE__ */ jsx16(Text15, { color: theme.info.color, children: "Variables: $1 $2 ... $ARGUMENTS Shell: !`cmd` File: @path" })
10759
11036
  ] })
10760
11037
  ] });
10761
- return /* @__PURE__ */ jsxs13(Fragment2, { children: [
10762
- /* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
11038
+ return /* @__PURE__ */ jsxs14(Fragment2, { children: [
11039
+ /* @__PURE__ */ jsxs14(Text15, { color: theme.accent, bold: true, children: [
10763
11040
  mode === "create" ? "Create" : "Edit",
10764
11041
  " custom command \u2014 Template (",
10765
11042
  stepIndex,
@@ -10767,10 +11044,10 @@ ${template}`;
10767
11044
  totalSteps,
10768
11045
  ")"
10769
11046
  ] }),
10770
- columns >= 100 ? /* @__PURE__ */ jsxs13(Box13, { flexDirection: "row", marginTop: 1, children: [
10771
- /* @__PURE__ */ jsx15(Box13, { flexDirection: "column", width: "50%", children: inputArea }),
10772
- /* @__PURE__ */ jsx15(Box13, { flexDirection: "column", width: "50%", children: guide })
10773
- ] }) : /* @__PURE__ */ jsx15(Box13, { flexDirection: "column", marginTop: 1, children: inputArea })
11047
+ columns >= 100 ? /* @__PURE__ */ jsxs14(Box14, { flexDirection: "row", marginTop: 1, children: [
11048
+ /* @__PURE__ */ jsx16(Box14, { flexDirection: "column", width: "50%", children: inputArea }),
11049
+ /* @__PURE__ */ jsx16(Box14, { flexDirection: "column", width: "50%", children: guide })
11050
+ ] }) : /* @__PURE__ */ jsx16(Box14, { flexDirection: "column", marginTop: 1, children: inputArea })
10774
11051
  ] });
10775
11052
  }
10776
11053
  case "advanced": {
@@ -10779,8 +11056,8 @@ ${template}`;
10779
11056
  { label: "Skip", value: "skip", key: "skip" },
10780
11057
  { label: "\u2190 Cancel", value: "cancel", key: "cancel" }
10781
11058
  ];
10782
- return /* @__PURE__ */ jsxs13(Fragment2, { children: [
10783
- /* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
11059
+ return /* @__PURE__ */ jsxs14(Fragment2, { children: [
11060
+ /* @__PURE__ */ jsxs14(Text15, { color: theme.accent, bold: true, children: [
10784
11061
  mode === "create" ? "Create" : "Edit",
10785
11062
  " custom command \u2014 Options (",
10786
11063
  stepIndex,
@@ -10788,8 +11065,8 @@ ${template}`;
10788
11065
  totalSteps,
10789
11066
  ")"
10790
11067
  ] }),
10791
- /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
10792
- SelectInput6,
11068
+ /* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(
11069
+ SelectInput7,
10793
11070
  {
10794
11071
  items,
10795
11072
  onSelect: (item) => {
@@ -10808,17 +11085,17 @@ ${template}`;
10808
11085
  { label: cmdMode === "auto" ? "auto \xB7 current" : "auto", value: "auto", key: "auto" },
10809
11086
  { label: "\u2190 Back", value: "__back__", key: "__back__" }
10810
11087
  ];
10811
- return /* @__PURE__ */ jsxs13(Fragment2, { children: [
10812
- /* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
11088
+ return /* @__PURE__ */ jsxs14(Fragment2, { children: [
11089
+ /* @__PURE__ */ jsxs14(Text15, { color: theme.accent, bold: true, children: [
10813
11090
  "Mode override (",
10814
11091
  stepIndex,
10815
11092
  "/",
10816
11093
  totalSteps,
10817
11094
  ")"
10818
11095
  ] }),
10819
- /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Saved to file but not yet enforced at runtime" }),
10820
- /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
10821
- SelectInput6,
11096
+ /* @__PURE__ */ jsx16(Text15, { color: theme.info.color, children: "Saved to file but not yet enforced at runtime" }),
11097
+ /* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(
11098
+ SelectInput7,
10822
11099
  {
10823
11100
  items,
10824
11101
  onSelect: (item) => {
@@ -10837,16 +11114,16 @@ ${template}`;
10837
11114
  { label: cmdEffort === "high" ? "high \xB7 current" : "high", value: "high", key: "high" },
10838
11115
  { label: "\u2190 Back", value: "__back__", key: "__back__" }
10839
11116
  ];
10840
- return /* @__PURE__ */ jsxs13(Fragment2, { children: [
10841
- /* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
11117
+ return /* @__PURE__ */ jsxs14(Fragment2, { children: [
11118
+ /* @__PURE__ */ jsxs14(Text15, { color: theme.accent, bold: true, children: [
10842
11119
  "Reasoning effort (",
10843
11120
  stepIndex,
10844
11121
  "/",
10845
11122
  totalSteps,
10846
11123
  ")"
10847
11124
  ] }),
10848
- /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
10849
- SelectInput6,
11125
+ /* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(
11126
+ SelectInput7,
10850
11127
  {
10851
11128
  items,
10852
11129
  onSelect: (item) => {
@@ -10858,15 +11135,15 @@ ${template}`;
10858
11135
  ] });
10859
11136
  }
10860
11137
  case "model":
10861
- return /* @__PURE__ */ jsxs13(Fragment2, { children: [
10862
- /* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
11138
+ return /* @__PURE__ */ jsxs14(Fragment2, { children: [
11139
+ /* @__PURE__ */ jsxs14(Text15, { color: theme.accent, bold: true, children: [
10863
11140
  "Model override (",
10864
11141
  stepIndex,
10865
11142
  "/",
10866
11143
  totalSteps,
10867
11144
  ")"
10868
11145
  ] }),
10869
- /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
11146
+ /* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(
10870
11147
  CustomTextInput,
10871
11148
  {
10872
11149
  value: cmdModel ?? "",
@@ -10875,7 +11152,7 @@ ${template}`;
10875
11152
  focus: true
10876
11153
  }
10877
11154
  ) }),
10878
- /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Press Enter to skip" })
11155
+ /* @__PURE__ */ jsx16(Text15, { color: theme.info.color, children: "Press Enter to skip" })
10879
11156
  ] });
10880
11157
  case "location": {
10881
11158
  const items = [
@@ -10883,16 +11160,16 @@ ${template}`;
10883
11160
  { label: source === "global" ? "Global \xB7 current" : "Global", value: "global", key: "global" },
10884
11161
  { label: "\u2190 Back", value: "__back__", key: "__back__" }
10885
11162
  ];
10886
- return /* @__PURE__ */ jsxs13(Fragment2, { children: [
10887
- /* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
11163
+ return /* @__PURE__ */ jsxs14(Fragment2, { children: [
11164
+ /* @__PURE__ */ jsxs14(Text15, { color: theme.accent, bold: true, children: [
10888
11165
  "Save location (",
10889
11166
  stepIndex,
10890
11167
  "/",
10891
11168
  totalSteps,
10892
11169
  ")"
10893
11170
  ] }),
10894
- /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
10895
- SelectInput6,
11171
+ /* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(
11172
+ SelectInput7,
10896
11173
  {
10897
11174
  items,
10898
11175
  onSelect: (item) => {
@@ -10901,7 +11178,7 @@ ${template}`;
10901
11178
  }
10902
11179
  }
10903
11180
  ) }),
10904
- /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Project: .kimiflare/commands/ Global: ~/.config/kimiflare/commands/" })
11181
+ /* @__PURE__ */ jsx16(Text15, { color: theme.info.color, children: "Project: .kimiflare/commands/ Global: ~/.config/kimiflare/commands/" })
10905
11182
  ] });
10906
11183
  }
10907
11184
  case "confirm": {
@@ -10909,8 +11186,8 @@ ${template}`;
10909
11186
  { label: "Save", value: "save", key: "save" },
10910
11187
  { label: "Cancel", value: "cancel", key: "cancel" }
10911
11188
  ];
10912
- return /* @__PURE__ */ jsxs13(Fragment2, { children: [
10913
- /* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
11189
+ return /* @__PURE__ */ jsxs14(Fragment2, { children: [
11190
+ /* @__PURE__ */ jsxs14(Text15, { color: theme.accent, bold: true, children: [
10914
11191
  mode === "create" ? "Create" : "Edit",
10915
11192
  " custom command \u2014 Confirm (",
10916
11193
  stepIndex,
@@ -10918,14 +11195,14 @@ ${template}`;
10918
11195
  totalSteps,
10919
11196
  ")"
10920
11197
  ] }),
10921
- /* @__PURE__ */ jsxs13(Text14, { color: theme.info.color, children: [
11198
+ /* @__PURE__ */ jsxs14(Text15, { color: theme.info.color, children: [
10922
11199
  source === "project" ? ".kimiflare/commands/" : "~/.config/kimiflare/commands/",
10923
11200
  name,
10924
11201
  ".md"
10925
11202
  ] }),
10926
- /* @__PURE__ */ jsx15(Box13, { marginTop: 1, flexDirection: "column", children: previewContent().split("\n").map((line, i) => /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: line || " " }, i)) }),
10927
- /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
10928
- SelectInput6,
11203
+ /* @__PURE__ */ jsx16(Box14, { marginTop: 1, flexDirection: "column", children: previewContent().split("\n").map((line, i) => /* @__PURE__ */ jsx16(Text15, { color: theme.info.color, children: line || " " }, i)) }),
11204
+ /* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(
11205
+ SelectInput7,
10929
11206
  {
10930
11207
  items,
10931
11208
  onSelect: (item) => handleConfirm(item.value)
@@ -10935,7 +11212,7 @@ ${template}`;
10935
11212
  }
10936
11213
  }
10937
11214
  };
10938
- return /* @__PURE__ */ jsx15(Box13, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: renderStep() });
11215
+ return /* @__PURE__ */ jsx16(Box14, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: renderStep() });
10939
11216
  }
10940
11217
  var NAME_RE;
10941
11218
  var init_command_wizard = __esm({
@@ -10947,10 +11224,442 @@ var init_command_wizard = __esm({
10947
11224
  }
10948
11225
  });
10949
11226
 
11227
+ // src/init/context-generator.ts
11228
+ import { existsSync as existsSync2, statSync as statSync3 } from "fs";
11229
+ import { join as join20 } from "path";
11230
+ function detectFlavor(cwd) {
11231
+ for (const [flavor, signatures] of Object.entries(FLAVOR_SIGNATURES)) {
11232
+ if (flavor === "generic") continue;
11233
+ for (const sig of signatures) {
11234
+ const path = join20(cwd, sig);
11235
+ if (sig.includes("*")) {
11236
+ try {
11237
+ const parts = sig.split("*");
11238
+ const prefix = parts[0] ?? "";
11239
+ const suffix = parts[1] ?? "";
11240
+ const entries = __require("fs").readdirSync(cwd);
11241
+ if (entries.some((e) => e.startsWith(prefix) && e.endsWith(suffix))) {
11242
+ return flavor;
11243
+ }
11244
+ } catch {
11245
+ }
11246
+ } else if (existsSync2(path)) {
11247
+ return flavor;
11248
+ }
11249
+ }
11250
+ }
11251
+ return "generic";
11252
+ }
11253
+ function findFile(cwd, candidates) {
11254
+ for (const c of candidates) {
11255
+ if (existsSync2(join20(cwd, c))) return c;
11256
+ }
11257
+ return null;
11258
+ }
11259
+ function findSourceRoots(cwd) {
11260
+ const roots = [];
11261
+ for (const r of SOURCE_ROOT_CANDIDATES) {
11262
+ const p = join20(cwd, r);
11263
+ try {
11264
+ const s = statSync3(p);
11265
+ if (s.isDirectory()) roots.push(r);
11266
+ } catch {
11267
+ }
11268
+ }
11269
+ return roots;
11270
+ }
11271
+ function findCiConfig(cwd) {
11272
+ for (const c of CI_PATHS) {
11273
+ if (existsSync2(join20(cwd, c))) {
11274
+ try {
11275
+ const s = statSync3(join20(cwd, c));
11276
+ return s.isDirectory() ? c : c;
11277
+ } catch {
11278
+ }
11279
+ }
11280
+ }
11281
+ return null;
11282
+ }
11283
+ function languageForFlavor(f) {
11284
+ const map = {
11285
+ node: "JavaScript / TypeScript",
11286
+ python: "Python",
11287
+ go: "Go",
11288
+ rust: "Rust",
11289
+ ruby: "Ruby",
11290
+ java: "Java / Kotlin",
11291
+ dotnet: "C# / F#",
11292
+ php: "PHP",
11293
+ elixir: "Elixir",
11294
+ haskell: "Haskell",
11295
+ c: "C",
11296
+ cpp: "C++",
11297
+ zig: "Zig",
11298
+ generic: "Unknown"
11299
+ };
11300
+ return map[f];
11301
+ }
11302
+ function analyzeProject(cwd) {
11303
+ const flavor = detectFlavor(cwd);
11304
+ const packageFiles = {
11305
+ node: ["package.json"],
11306
+ python: ["pyproject.toml", "setup.py", "setup.cfg"],
11307
+ go: ["go.mod"],
11308
+ rust: ["Cargo.toml"],
11309
+ ruby: ["Gemfile"],
11310
+ java: ["pom.xml", "build.gradle", "build.gradle.kts"],
11311
+ dotnet: ["*.csproj"],
11312
+ php: ["composer.json"],
11313
+ elixir: ["mix.exs"],
11314
+ haskell: ["package.yaml", "*.cabal"],
11315
+ c: ["Makefile", "CMakeLists.txt"],
11316
+ cpp: ["Makefile", "CMakeLists.txt"],
11317
+ zig: ["build.zig"],
11318
+ generic: []
11319
+ };
11320
+ const lockFiles = {
11321
+ node: ["package-lock.json", "yarn.lock", "pnpm-lock.yaml", "bun.lockb"],
11322
+ python: ["poetry.lock", "uv.lock", "Pipfile.lock"],
11323
+ go: ["go.sum"],
11324
+ rust: ["Cargo.lock"],
11325
+ ruby: ["Gemfile.lock"],
11326
+ java: [],
11327
+ dotnet: [],
11328
+ php: ["composer.lock"],
11329
+ elixir: ["mix.lock"],
11330
+ haskell: [],
11331
+ c: [],
11332
+ cpp: [],
11333
+ zig: [],
11334
+ generic: []
11335
+ };
11336
+ const buildFiles = {
11337
+ node: ["tsup.config.ts", "vite.config.ts", "webpack.config.js", "rollup.config.js", "esbuild.js", "next.config.js", "nuxt.config.ts", "astro.config.mjs", "svelte.config.js"],
11338
+ python: ["setup.py", "setup.cfg", "pyproject.toml"],
11339
+ go: ["Makefile"],
11340
+ rust: ["Cargo.toml"],
11341
+ ruby: ["Rakefile"],
11342
+ java: ["pom.xml", "build.gradle"],
11343
+ dotnet: ["*.sln"],
11344
+ php: [],
11345
+ elixir: ["mix.exs"],
11346
+ haskell: ["package.yaml", "*.cabal"],
11347
+ c: ["Makefile", "CMakeLists.txt"],
11348
+ cpp: ["Makefile", "CMakeLists.txt"],
11349
+ zig: ["build.zig"],
11350
+ generic: []
11351
+ };
11352
+ const testConfigs = {
11353
+ node: ["vitest.config.ts", "jest.config.js", "playwright.config.ts", "cypress.config.ts", "ava.config.js"],
11354
+ python: ["pytest.ini", "tox.ini", "setup.cfg"],
11355
+ go: [],
11356
+ rust: [],
11357
+ ruby: ["Rakefile", "spec_helper.rb"],
11358
+ java: [],
11359
+ dotnet: [],
11360
+ php: ["phpunit.xml"],
11361
+ elixir: ["test/test_helper.exs"],
11362
+ haskell: [],
11363
+ c: ["Makefile"],
11364
+ cpp: ["Makefile"],
11365
+ zig: [],
11366
+ generic: []
11367
+ };
11368
+ const lintConfigs = {
11369
+ node: [".eslintrc", ".eslintrc.js", ".eslintrc.json", ".prettierrc", "biome.json", "deno.json"],
11370
+ python: [".flake8", "pyproject.toml", "setup.cfg", ".pylintrc", "ruff.toml"],
11371
+ go: [],
11372
+ rust: ["rustfmt.toml", "clippy.toml"],
11373
+ ruby: [".rubocop.yml"],
11374
+ java: [],
11375
+ dotnet: [],
11376
+ php: [],
11377
+ elixir: [".formatter.exs"],
11378
+ haskell: [],
11379
+ c: [".clang-format", ".clang-tidy"],
11380
+ cpp: [".clang-format", ".clang-tidy"],
11381
+ zig: [],
11382
+ generic: []
11383
+ };
11384
+ const typeConfigs = {
11385
+ node: ["tsconfig.json", "jsconfig.json"],
11386
+ python: ["pyproject.toml", "setup.cfg", "mypy.ini"],
11387
+ go: [],
11388
+ rust: [],
11389
+ ruby: [],
11390
+ java: [],
11391
+ dotnet: [],
11392
+ php: [],
11393
+ elixir: [],
11394
+ haskell: [],
11395
+ c: [],
11396
+ cpp: [],
11397
+ zig: [],
11398
+ generic: []
11399
+ };
11400
+ return {
11401
+ flavor,
11402
+ primaryLanguage: languageForFlavor(flavor),
11403
+ packageFile: findFile(cwd, packageFiles[flavor]),
11404
+ lockFile: findFile(cwd, lockFiles[flavor]),
11405
+ buildFile: findFile(cwd, buildFiles[flavor]),
11406
+ testConfig: findFile(cwd, testConfigs[flavor]),
11407
+ lintConfig: findFile(cwd, lintConfigs[flavor]),
11408
+ typeConfig: findFile(cwd, typeConfigs[flavor]),
11409
+ ciConfig: findCiConfig(cwd),
11410
+ readme: findFile(cwd, ["README.md", "README.rst", "README.txt", "Readme.md"]),
11411
+ sourceRoots: findSourceRoots(cwd),
11412
+ hasGit: existsSync2(join20(cwd, ".git"))
11413
+ };
11414
+ }
11415
+ function bashDiscoveryCommands(profile) {
11416
+ const cmds = [];
11417
+ if (profile.hasGit) {
11418
+ cmds.push(
11419
+ "git log --oneline -20",
11420
+ "git branch -a | head -20"
11421
+ );
11422
+ }
11423
+ switch (profile.flavor) {
11424
+ case "node":
11425
+ cmds.push(
11426
+ `cat package.json | jq -r '.scripts | to_entries[] | "\\(.key): \\(.value)"' 2>/dev/null || node -e "const p=require('./package.json'); Object.entries(p.scripts||{}).forEach(([k,v])=>console.log(k+': '+v))"`,
11427
+ "ls -la node_modules/.bin 2>/dev/null | head -30 || true"
11428
+ );
11429
+ break;
11430
+ case "python":
11431
+ cmds.push(
11432
+ `python -c "import tomllib; f=open('pyproject.toml','rb'); d=tomllib.load(f); [print(f'{k}: {v}') for k,v in d.get('project',{}).get('scripts',{}).items()]" 2>/dev/null || true`,
11433
+ "make -p 2>/dev/null | grep -E '^[a-zA-Z_-]+:.*$' | head -20 || true"
11434
+ );
11435
+ break;
11436
+ case "go":
11437
+ cmds.push("go help 2>/dev/null | head -10 || true");
11438
+ break;
11439
+ case "rust":
11440
+ cmds.push("cargo --list 2>/dev/null | head -20 || true");
11441
+ break;
11442
+ case "ruby":
11443
+ cmds.push("bundle exec rake -T 2>/dev/null | head -20 || true");
11444
+ break;
11445
+ case "java":
11446
+ cmds.push("./mvnw help:describe -Dplugin=help 2>/dev/null | head -10 || true");
11447
+ break;
11448
+ }
11449
+ cmds.push("ls -la");
11450
+ return cmds;
11451
+ }
11452
+ function discoveryChecklist(profile) {
11453
+ const lines = [];
11454
+ lines.push("## PHASE 1: Project Identity & Configuration");
11455
+ lines.push("");
11456
+ if (profile.readme) {
11457
+ lines.push(`- [ ] Read \`${profile.readme}\` \u2014 extract project name, description, purpose.`);
11458
+ }
11459
+ if (profile.packageFile) {
11460
+ lines.push(`- [ ] Read \`${profile.packageFile}\` \u2014 extract dependencies, scripts, metadata.`);
11461
+ }
11462
+ if (profile.buildFile) {
11463
+ lines.push(`- [ ] Read \`${profile.buildFile}\` \u2014 understand build system and entry points.`);
11464
+ }
11465
+ if (profile.typeConfig) {
11466
+ lines.push(`- [ ] Read \`${profile.typeConfig}\` \u2014 note strictness, target, module system.`);
11467
+ }
11468
+ if (profile.testConfig) {
11469
+ lines.push(`- [ ] Read \`${profile.testConfig}\` \u2014 understand test runner and conventions.`);
11470
+ }
11471
+ if (profile.lintConfig) {
11472
+ lines.push(`- [ ] Read \`${profile.lintConfig}\` \u2014 note style rules and formatter.`);
11473
+ }
11474
+ if (profile.ciConfig) {
11475
+ lines.push(`- [ ] Inspect CI config in \`${profile.ciConfig}\` \u2014 note checks, matrix, deployment.`);
11476
+ }
11477
+ lines.push("");
11478
+ lines.push("## PHASE 2: Source Structure Discovery");
11479
+ lines.push("");
11480
+ for (const root of profile.sourceRoots) {
11481
+ lines.push(`- [ ] Use \`glob\` to list files in \`${root}/**/*\` (limit to ~50 files).`);
11482
+ lines.push(`- [ ] Read 3-5 representative files from \`${root}\` to understand code patterns.`);
11483
+ }
11484
+ if (profile.sourceRoots.length === 0) {
11485
+ lines.push("- [ ] Use `glob` to find source files (`**/*.{js,ts,py,go,rs,rb,java,cs,php,ex,hs,c,cpp,zig}`) \u2014 list top 50.");
11486
+ lines.push("- [ ] Read 3-5 representative source files to understand code patterns.");
11487
+ }
11488
+ lines.push("- [ ] Use `glob` to find test files and note their location/naming pattern.");
11489
+ lines.push("- [ ] Use `glob` to find config files at root level.");
11490
+ lines.push("");
11491
+ lines.push("## PHASE 3: Convention Extraction");
11492
+ lines.push("");
11493
+ lines.push("- [ ] Use `grep` to find import patterns (e.g., `import .* from` or `require(`).");
11494
+ lines.push("- [ ] Use `grep` to find export patterns (e.g., `export ` or `module.exports`).");
11495
+ lines.push("- [ ] Check for any `.editorconfig`, `.gitignore`, or `CONTRIBUTING.md`.");
11496
+ if (profile.hasGit) {
11497
+ lines.push("- [ ] Run `git log --oneline -20` to understand commit style and recent activity.");
11498
+ lines.push("- [ ] Run `git branch -a | head -20` to understand branching strategy.");
11499
+ }
11500
+ lines.push("");
11501
+ lines.push("## PHASE 4: Build & Development Workflow");
11502
+ lines.push("");
11503
+ const bashCmds = bashDiscoveryCommands(profile);
11504
+ for (const cmd of bashCmds) {
11505
+ lines.push(`- [ ] Run \`bash\` with: \`${cmd}\``);
11506
+ }
11507
+ lines.push("");
11508
+ lines.push("## PHASE 5: Architecture & Patterns (Deep Dive)");
11509
+ lines.push("");
11510
+ lines.push("- [ ] Identify the main entry point(s) of the application.");
11511
+ lines.push("- [ ] Identify the testing framework and how tests are organized.");
11512
+ lines.push("- [ ] Look for any architectural patterns: MVC, hexagonal, actor model, etc.");
11513
+ lines.push("- [ ] Note any code-generation, build-time transforms, or code-mod tools.");
11514
+ lines.push("- [ ] Check for Docker, docker-compose, or deployment configs.");
11515
+ lines.push("- [ ] Note any monorepo patterns (workspaces, turborepo, nx, etc.).");
11516
+ return lines.join("\n");
11517
+ }
11518
+ function sectionTemplate() {
11519
+ return `
11520
+ Generate the context document with these sections. Be concise but comprehensive.
11521
+ Aim for 100\u2013200 lines total. Use markdown tables where they save space.
11522
+
11523
+ ### Required Sections
11524
+
11525
+ 1. **Project** \u2014 One-line description + primary language/runtime + key frameworks.
11526
+
11527
+ 2. **Build / test / run** \u2014 Exact shell commands. Include:
11528
+ - Development server / watch mode
11529
+ - Production build
11530
+ - Test commands (unit, integration, e2e if separate)
11531
+ - Lint / format commands
11532
+ - Type-checking commands
11533
+ - Any setup / install commands
11534
+ Note which commands are slow or require special setup.
11535
+
11536
+ 3. **Layout** \u2014 Table of key directories AND a one-sentence rationale for each.
11537
+ Explain *why* things live where they do, not just *what* is there.
11538
+
11539
+ 4. **Conventions** \u2014 Cover:
11540
+ - Naming conventions (files, variables, types, tests)
11541
+ - Import style and path resolution quirks
11542
+ - File organization patterns
11543
+ - Commit message style (if discernible from git history)
11544
+ - Branching strategy
11545
+ - TypeScript / type system strictness rules
11546
+ - Testing conventions (naming, location, mocks)
11547
+ - Anything surprising or non-obvious
11548
+
11549
+ 5. **Dependencies** \u2014 Rules for adding dependencies:
11550
+ - Package manager commands
11551
+ - Dev vs runtime dependency conventions
11552
+ - Native deps that must stay external (if bundling)
11553
+ - Version pinning policy
11554
+
11555
+ 6. **Do / Don't** \u2014 Numbered list of hard rules:
11556
+ - Security rules (never commit secrets, etc.)
11557
+ - Performance rules (don't bundle X, etc.)
11558
+ - Style rules that aren't caught by linters
11559
+ - Common mistakes to avoid
11560
+ - Anything that would make a maintainer sad
11561
+
11562
+ 7. **Debugging & Troubleshooting** \u2014 Common issues:
11563
+ - How to run in debug mode
11564
+ - Common build failures and fixes
11565
+ - How to reset / clean the project
11566
+ - Where logs live
11567
+
11568
+ 8. **Architecture Notes** (if applicable) \u2014 Brief notes on:
11569
+ - Key abstractions and their responsibilities
11570
+ - Data flow
11571
+ - External integrations
11572
+ - State management approach
11573
+ `.trim();
11574
+ }
11575
+ function buildInitPrompt(cwd) {
11576
+ const existingName = ["KIMI.md", "KIMIFLARE.md", "AGENT.md"].find(
11577
+ (n) => existsSync2(join20(cwd, n))
11578
+ );
11579
+ const isRefresh = existingName !== void 0;
11580
+ const targetFilename = existingName ?? "KIMI.md";
11581
+ const profile = analyzeProject(cwd);
11582
+ const checklist = discoveryChecklist(profile);
11583
+ const sections = sectionTemplate();
11584
+ const promptParts = [
11585
+ isRefresh ? `Regenerate \`${targetFilename}\` at the repository root to refresh project context. The file already exists \u2014 read it first and preserve anything still accurate, updating only what has changed or is missing.` : `Generate a \`${targetFilename}\` at the repository root so future agents have comprehensive project context.`,
11586
+ "",
11587
+ "This is a **structured investigation**. Follow the checklist below systematically. Use the `glob`, `read`, `grep`, and `bash` tools to gather information. Do not skip steps.",
11588
+ "",
11589
+ `**Detected project profile:** ${profile.primaryLanguage} (${profile.flavor})`,
11590
+ profile.packageFile ? `- Package file: ${profile.packageFile}` : null,
11591
+ profile.buildFile ? `- Build file: ${profile.buildFile}` : null,
11592
+ profile.testConfig ? `- Test config: ${profile.testConfig}` : null,
11593
+ profile.typeConfig ? `- Type config: ${profile.typeConfig}` : null,
11594
+ profile.lintConfig ? `- Lint config: ${profile.lintConfig}` : null,
11595
+ profile.ciConfig ? `- CI config: ${profile.ciConfig}` : null,
11596
+ profile.sourceRoots.length > 0 ? `- Source roots: ${profile.sourceRoots.join(", ")}` : null,
11597
+ profile.hasGit ? `- Git repository: yes` : null,
11598
+ "",
11599
+ "---",
11600
+ "",
11601
+ checklist,
11602
+ "",
11603
+ "---",
11604
+ "",
11605
+ sections,
11606
+ "",
11607
+ isRefresh ? `After writing the file, re-read \`${targetFilename}\` and verify it is complete and accurate.` : "After writing the file, re-read it and verify all sections are present and accurate.",
11608
+ "",
11609
+ "Do not call `tasks_set` for this. Just follow the checklist, gather information, then write the file."
11610
+ ];
11611
+ const prompt = promptParts.filter((p) => p !== null).join("\n");
11612
+ return { prompt, targetFilename, isRefresh };
11613
+ }
11614
+ var FLAVOR_SIGNATURES, SOURCE_ROOT_CANDIDATES, CI_PATHS;
11615
+ var init_context_generator = __esm({
11616
+ "src/init/context-generator.ts"() {
11617
+ "use strict";
11618
+ FLAVOR_SIGNATURES = {
11619
+ node: ["package.json", "package-lock.json", "yarn.lock", "pnpm-lock.yaml", "bun.lockb", "node_modules"],
11620
+ python: ["pyproject.toml", "setup.py", "setup.cfg", "requirements.txt", "Pipfile", "poetry.lock", "uv.lock", "tox.ini"],
11621
+ go: ["go.mod", "go.sum"],
11622
+ rust: ["Cargo.toml", "Cargo.lock"],
11623
+ ruby: ["Gemfile", "Gemfile.lock", "*.gemspec"],
11624
+ java: ["pom.xml", "build.gradle", "build.gradle.kts"],
11625
+ dotnet: ["*.csproj", "*.fsproj", "*.sln"],
11626
+ php: ["composer.json", "composer.lock"],
11627
+ elixir: ["mix.exs", "mix.lock"],
11628
+ haskell: ["package.yaml", "*.cabal", "stack.yaml"],
11629
+ c: ["Makefile", "CMakeLists.txt", "configure.ac"],
11630
+ cpp: ["Makefile", "CMakeLists.txt", "configure.ac"],
11631
+ zig: ["build.zig", "build.zig.zon"],
11632
+ generic: []
11633
+ };
11634
+ SOURCE_ROOT_CANDIDATES = [
11635
+ "src",
11636
+ "lib",
11637
+ "app",
11638
+ "source",
11639
+ "Sources",
11640
+ "pkg",
11641
+ "internal",
11642
+ "cmd",
11643
+ "bin",
11644
+ "packages",
11645
+ "projects"
11646
+ ];
11647
+ CI_PATHS = [
11648
+ ".github/workflows",
11649
+ ".gitlab-ci.yml",
11650
+ ".circleci",
11651
+ "azure-pipelines.yml",
11652
+ "Jenkinsfile",
11653
+ ".buildkite",
11654
+ "cloudbuild.yaml"
11655
+ ];
11656
+ }
11657
+ });
11658
+
10950
11659
  // src/ui/command-picker.tsx
10951
- import { Box as Box14, Text as Text15 } from "ink";
10952
- import SelectInput7 from "ink-select-input";
10953
- import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
11660
+ import { Box as Box15, Text as Text16 } from "ink";
11661
+ import SelectInput8 from "ink-select-input";
11662
+ import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
10954
11663
  function CommandPicker({ commands, title, onPick }) {
10955
11664
  const theme = useTheme();
10956
11665
  const items = commands.map((cmd) => ({
@@ -10959,11 +11668,11 @@ function CommandPicker({ commands, title, onPick }) {
10959
11668
  key: cmd.name
10960
11669
  }));
10961
11670
  items.push({ label: "\u2190 Cancel", value: null, key: "__cancel__" });
10962
- return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
10963
- /* @__PURE__ */ jsx16(Text15, { color: theme.accent, bold: true, children: title }),
10964
- /* @__PURE__ */ jsx16(Text15, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select." }),
10965
- /* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(
10966
- SelectInput7,
11671
+ return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
11672
+ /* @__PURE__ */ jsx17(Text16, { color: theme.accent, bold: true, children: title }),
11673
+ /* @__PURE__ */ jsx17(Text16, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select." }),
11674
+ /* @__PURE__ */ jsx17(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx17(
11675
+ SelectInput8,
10967
11676
  {
10968
11677
  items,
10969
11678
  onSelect: (item) => {
@@ -10985,64 +11694,64 @@ var init_command_picker = __esm({
10985
11694
  });
10986
11695
 
10987
11696
  // src/ui/command-list.tsx
10988
- import { Box as Box15, Text as Text16, useInput as useInput5 } from "ink";
10989
- import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
11697
+ import { Box as Box16, Text as Text17, useInput as useInput6 } from "ink";
11698
+ import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
10990
11699
  function CommandList({ commands, onDone }) {
10991
11700
  const theme = useTheme();
10992
- useInput5((_input, key) => {
11701
+ useInput6((_input, key) => {
10993
11702
  if (key.escape) {
10994
11703
  onDone();
10995
11704
  }
10996
11705
  });
10997
- return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
10998
- /* @__PURE__ */ jsx17(Text16, { color: theme.accent, bold: true, children: "Custom commands" }),
10999
- /* @__PURE__ */ jsx17(Text16, { color: theme.info.color, dimColor: false, children: "Esc to close." }),
11000
- /* @__PURE__ */ jsxs15(Box15, { marginTop: 1, flexDirection: "column", children: [
11001
- commands.length === 0 && /* @__PURE__ */ jsx17(Text16, { color: theme.info.color, children: "No custom commands found." }),
11002
- commands.map((cmd) => /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", marginBottom: 1, children: [
11003
- /* @__PURE__ */ jsxs15(Text16, { color: theme.accent, bold: true, children: [
11706
+ return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
11707
+ /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Custom commands" }),
11708
+ /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Esc to close." }),
11709
+ /* @__PURE__ */ jsxs16(Box16, { marginTop: 1, flexDirection: "column", children: [
11710
+ commands.length === 0 && /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, children: "No custom commands found." }),
11711
+ commands.map((cmd) => /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", marginBottom: 1, children: [
11712
+ /* @__PURE__ */ jsxs16(Text17, { color: theme.accent, bold: true, children: [
11004
11713
  "/",
11005
11714
  cmd.name
11006
11715
  ] }),
11007
- /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
11716
+ /* @__PURE__ */ jsxs16(Text17, { color: theme.info.color, children: [
11008
11717
  " ",
11009
11718
  "source: ",
11010
11719
  cmd.source
11011
11720
  ] }),
11012
- /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
11721
+ /* @__PURE__ */ jsxs16(Text17, { color: theme.info.color, children: [
11013
11722
  " ",
11014
11723
  "path: ",
11015
11724
  cmd.filepath
11016
11725
  ] }),
11017
- cmd.description && /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
11726
+ cmd.description && /* @__PURE__ */ jsxs16(Text17, { color: theme.info.color, children: [
11018
11727
  " ",
11019
11728
  "desc: ",
11020
11729
  cmd.description
11021
11730
  ] }),
11022
- cmd.mode && /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
11731
+ cmd.mode && /* @__PURE__ */ jsxs16(Text17, { color: theme.info.color, children: [
11023
11732
  " ",
11024
11733
  "mode: ",
11025
11734
  cmd.mode
11026
11735
  ] }),
11027
- cmd.effort && /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
11736
+ cmd.effort && /* @__PURE__ */ jsxs16(Text17, { color: theme.info.color, children: [
11028
11737
  " ",
11029
11738
  "effort: ",
11030
11739
  cmd.effort
11031
11740
  ] }),
11032
- cmd.model && /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
11741
+ cmd.model && /* @__PURE__ */ jsxs16(Text17, { color: theme.info.color, children: [
11033
11742
  " ",
11034
11743
  "model: ",
11035
11744
  cmd.model
11036
11745
  ] }),
11037
- /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
11746
+ /* @__PURE__ */ jsxs16(Text17, { color: theme.info.color, children: [
11038
11747
  " ",
11039
11748
  "template:"
11040
11749
  ] }),
11041
- cmd.template.split("\n").slice(0, 5).map((line, i) => /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
11750
+ cmd.template.split("\n").slice(0, 5).map((line, i) => /* @__PURE__ */ jsxs16(Text17, { color: theme.info.color, children: [
11042
11751
  " ",
11043
11752
  line || " "
11044
11753
  ] }, i)),
11045
- cmd.template.split("\n").length > 5 && /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
11754
+ cmd.template.split("\n").length > 5 && /* @__PURE__ */ jsxs16(Text17, { color: theme.info.color, children: [
11046
11755
  " ",
11047
11756
  "..."
11048
11757
  ] })
@@ -11059,10 +11768,10 @@ var init_command_list = __esm({
11059
11768
 
11060
11769
  // src/ui/lsp-wizard.tsx
11061
11770
  import { useState as useState9 } from "react";
11062
- import { Box as Box16, Text as Text17 } from "ink";
11063
- import SelectInput8 from "ink-select-input";
11771
+ import { Box as Box17, Text as Text18 } from "ink";
11772
+ import SelectInput9 from "ink-select-input";
11064
11773
  import { spawn as spawn3 } from "child_process";
11065
- import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
11774
+ import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
11066
11775
  function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
11067
11776
  const theme = useTheme();
11068
11777
  const [page, setPage] = useState9("main");
@@ -11173,11 +11882,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
11173
11882
  { label: "(close)", value: "__close__", key: "__close__" }
11174
11883
  ];
11175
11884
  if (page === "main") {
11176
- return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
11177
- /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "LSP Servers" }),
11178
- /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select." }),
11179
- /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
11180
- SelectInput8,
11885
+ return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
11886
+ /* @__PURE__ */ jsx19(Text18, { color: theme.accent, bold: true, children: "LSP Servers" }),
11887
+ /* @__PURE__ */ jsx19(Text18, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select." }),
11888
+ /* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
11889
+ SelectInput9,
11181
11890
  {
11182
11891
  items: mainItems,
11183
11892
  onSelect: (item) => {
@@ -11204,11 +11913,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
11204
11913
  }),
11205
11914
  { label: "\u2190 Back", value: "__back__", key: "__back__" }
11206
11915
  ];
11207
- return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
11208
- /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Add LSP Server" }),
11209
- /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Select a language server to configure." }),
11210
- /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
11211
- SelectInput8,
11916
+ return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
11917
+ /* @__PURE__ */ jsx19(Text18, { color: theme.accent, bold: true, children: "Add LSP Server" }),
11918
+ /* @__PURE__ */ jsx19(Text18, { color: theme.info.color, dimColor: false, children: "Select a language server to configure." }),
11919
+ /* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
11920
+ SelectInput9,
11212
11921
  {
11213
11922
  items,
11214
11923
  onSelect: (item) => {
@@ -11235,19 +11944,19 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
11235
11944
  { label: isSuccess ? "Save to config \u2713" : "Save anyway", value: "save", key: "save" },
11236
11945
  { label: "\u2190 Back", value: "__back__", key: "__back__" }
11237
11946
  ];
11238
- return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
11239
- /* @__PURE__ */ jsxs16(Text17, { color: theme.accent, bold: true, children: [
11947
+ return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
11948
+ /* @__PURE__ */ jsxs17(Text18, { color: theme.accent, bold: true, children: [
11240
11949
  "Install ",
11241
11950
  selectedPreset.name
11242
11951
  ] }),
11243
- /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: selectedPreset.installHint }),
11244
- /* @__PURE__ */ jsxs16(Box16, { marginTop: 1, flexDirection: "column", children: [
11245
- /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Command:" }),
11246
- /* @__PURE__ */ jsx18(Text17, { color: theme.accent, children: selectedPreset.installCommand || "(none required)" })
11952
+ /* @__PURE__ */ jsx19(Text18, { color: theme.info.color, dimColor: false, children: selectedPreset.installHint }),
11953
+ /* @__PURE__ */ jsxs17(Box17, { marginTop: 1, flexDirection: "column", children: [
11954
+ /* @__PURE__ */ jsx19(Text18, { color: theme.info.color, dimColor: false, children: "Command:" }),
11955
+ /* @__PURE__ */ jsx19(Text18, { color: theme.accent, children: selectedPreset.installCommand || "(none required)" })
11247
11956
  ] }),
11248
- installState.output && /* @__PURE__ */ jsx18(Box16, { marginTop: 1, flexDirection: "column", children: /* @__PURE__ */ jsx18(Text17, { color: isSuccess ? theme.accent : theme.error, children: installState.output.slice(-500) }) }),
11249
- /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
11250
- SelectInput8,
11957
+ installState.output && /* @__PURE__ */ jsx19(Box17, { marginTop: 1, flexDirection: "column", children: /* @__PURE__ */ jsx19(Text18, { color: isSuccess ? theme.accent : theme.error, children: installState.output.slice(-500) }) }),
11958
+ /* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
11959
+ SelectInput9,
11251
11960
  {
11252
11961
  items,
11253
11962
  onSelect: (item) => {
@@ -11264,16 +11973,16 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
11264
11973
  }
11265
11974
  }
11266
11975
  ) }),
11267
- isSuccess && /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(Text17, { color: theme.accent, children: "Server saved. Run /lsp reload to start it." }) })
11976
+ isSuccess && /* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(Text18, { color: theme.accent, children: "Server saved. Run /lsp reload to start it." }) })
11268
11977
  ] });
11269
11978
  }
11270
11979
  if (page === "custom-name") {
11271
- return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
11272
- /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Custom LSP Server \u2014 Name" }),
11273
- /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Enter a name for this server (e.g., my-server)." }),
11274
- /* @__PURE__ */ jsxs16(Box16, { marginTop: 1, children: [
11275
- /* @__PURE__ */ jsx18(Text17, { color: theme.accent, children: "\u203A " }),
11276
- /* @__PURE__ */ jsx18(
11980
+ return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
11981
+ /* @__PURE__ */ jsx19(Text18, { color: theme.accent, bold: true, children: "Custom LSP Server \u2014 Name" }),
11982
+ /* @__PURE__ */ jsx19(Text18, { color: theme.info.color, dimColor: false, children: "Enter a name for this server (e.g., my-server)." }),
11983
+ /* @__PURE__ */ jsxs17(Box17, { marginTop: 1, children: [
11984
+ /* @__PURE__ */ jsx19(Text18, { color: theme.accent, children: "\u203A " }),
11985
+ /* @__PURE__ */ jsx19(
11277
11986
  CustomTextInput,
11278
11987
  {
11279
11988
  value: customName,
@@ -11287,8 +11996,8 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
11287
11996
  }
11288
11997
  )
11289
11998
  ] }),
11290
- /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
11291
- SelectInput8,
11999
+ /* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
12000
+ SelectInput9,
11292
12001
  {
11293
12002
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
11294
12003
  onSelect: () => setPage("add")
@@ -11297,12 +12006,12 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
11297
12006
  ] });
11298
12007
  }
11299
12008
  if (page === "custom-command") {
11300
- return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
11301
- /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Custom LSP Server \u2014 Command" }),
11302
- /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Enter the command to start the server (space-separated)." }),
11303
- /* @__PURE__ */ jsxs16(Box16, { marginTop: 1, children: [
11304
- /* @__PURE__ */ jsx18(Text17, { color: theme.accent, children: "\u203A " }),
11305
- /* @__PURE__ */ jsx18(
12009
+ return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
12010
+ /* @__PURE__ */ jsx19(Text18, { color: theme.accent, bold: true, children: "Custom LSP Server \u2014 Command" }),
12011
+ /* @__PURE__ */ jsx19(Text18, { color: theme.info.color, dimColor: false, children: "Enter the command to start the server (space-separated)." }),
12012
+ /* @__PURE__ */ jsxs17(Box17, { marginTop: 1, children: [
12013
+ /* @__PURE__ */ jsx19(Text18, { color: theme.accent, children: "\u203A " }),
12014
+ /* @__PURE__ */ jsx19(
11306
12015
  CustomTextInput,
11307
12016
  {
11308
12017
  value: customCommand,
@@ -11316,8 +12025,8 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
11316
12025
  }
11317
12026
  )
11318
12027
  ] }),
11319
- /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
11320
- SelectInput8,
12028
+ /* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
12029
+ SelectInput9,
11321
12030
  {
11322
12031
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
11323
12032
  onSelect: () => setPage("custom-name")
@@ -11340,11 +12049,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
11340
12049
  },
11341
12050
  { label: "\u2190 Back", value: "__back__", key: "__back__" }
11342
12051
  ];
11343
- return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
11344
- /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Save LSP Config" }),
11345
- /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Where should this server configuration be saved?" }),
11346
- /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
11347
- SelectInput8,
12052
+ return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
12053
+ /* @__PURE__ */ jsx19(Text18, { color: theme.accent, bold: true, children: "Save LSP Config" }),
12054
+ /* @__PURE__ */ jsx19(Text18, { color: theme.info.color, dimColor: false, children: "Where should this server configuration be saved?" }),
12055
+ /* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
12056
+ SelectInput9,
11348
12057
  {
11349
12058
  items,
11350
12059
  onSelect: (item) => {
@@ -11362,11 +12071,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
11362
12071
  if (page === "edit") {
11363
12072
  const keys = Object.keys(servers);
11364
12073
  if (keys.length === 0) {
11365
- return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
11366
- /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Edit LSP Server" }),
11367
- /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, children: "No servers configured." }),
11368
- /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
11369
- SelectInput8,
12074
+ return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
12075
+ /* @__PURE__ */ jsx19(Text18, { color: theme.accent, bold: true, children: "Edit LSP Server" }),
12076
+ /* @__PURE__ */ jsx19(Text18, { color: theme.info.color, children: "No servers configured." }),
12077
+ /* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
12078
+ SelectInput9,
11370
12079
  {
11371
12080
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
11372
12081
  onSelect: () => setPage("main")
@@ -11386,11 +12095,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
11386
12095
  }),
11387
12096
  { label: "\u2190 Back", value: "__back__", key: "__back__" }
11388
12097
  ];
11389
- return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
11390
- /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Edit LSP Server" }),
11391
- /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Select a server to toggle enabled/disabled." }),
11392
- /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
11393
- SelectInput8,
12098
+ return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
12099
+ /* @__PURE__ */ jsx19(Text18, { color: theme.accent, bold: true, children: "Edit LSP Server" }),
12100
+ /* @__PURE__ */ jsx19(Text18, { color: theme.info.color, dimColor: false, children: "Select a server to toggle enabled/disabled." }),
12101
+ /* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
12102
+ SelectInput9,
11394
12103
  {
11395
12104
  items,
11396
12105
  onSelect: (item) => {
@@ -11407,11 +12116,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
11407
12116
  if (page === "delete") {
11408
12117
  const keys = Object.keys(servers);
11409
12118
  if (keys.length === 0) {
11410
- return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
11411
- /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Delete LSP Server" }),
11412
- /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, children: "No servers configured." }),
11413
- /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
11414
- SelectInput8,
12119
+ return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
12120
+ /* @__PURE__ */ jsx19(Text18, { color: theme.accent, bold: true, children: "Delete LSP Server" }),
12121
+ /* @__PURE__ */ jsx19(Text18, { color: theme.info.color, children: "No servers configured." }),
12122
+ /* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
12123
+ SelectInput9,
11415
12124
  {
11416
12125
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
11417
12126
  onSelect: () => setPage("main")
@@ -11427,11 +12136,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
11427
12136
  })),
11428
12137
  { label: "\u2190 Back", value: "__back__", key: "__back__" }
11429
12138
  ];
11430
- return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
11431
- /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Delete LSP Server" }),
11432
- /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Select a server to remove from config." }),
11433
- /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
11434
- SelectInput8,
12139
+ return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
12140
+ /* @__PURE__ */ jsx19(Text18, { color: theme.accent, bold: true, children: "Delete LSP Server" }),
12141
+ /* @__PURE__ */ jsx19(Text18, { color: theme.info.color, dimColor: false, children: "Select a server to remove from config." }),
12142
+ /* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
12143
+ SelectInput9,
11435
12144
  {
11436
12145
  items,
11437
12146
  onSelect: (item) => {
@@ -11447,15 +12156,15 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
11447
12156
  }
11448
12157
  if (page === "list") {
11449
12158
  const keys = Object.keys(servers);
11450
- return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
11451
- /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Configured LSP Servers" }),
11452
- keys.length === 0 ? /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, children: "No servers configured." }) : /* @__PURE__ */ jsx18(Box16, { marginTop: 1, flexDirection: "column", children: keys.map((k) => {
12159
+ return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
12160
+ /* @__PURE__ */ jsx19(Text18, { color: theme.accent, bold: true, children: "Configured LSP Servers" }),
12161
+ keys.length === 0 ? /* @__PURE__ */ jsx19(Text18, { color: theme.info.color, children: "No servers configured." }) : /* @__PURE__ */ jsx19(Box17, { marginTop: 1, flexDirection: "column", children: keys.map((k) => {
11453
12162
  const s = servers[k];
11454
12163
  const status = s.enabled !== false ? "enabled" : "disabled";
11455
- return /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, children: ` ${k.padEnd(16)} ${status} ${s.command.join(" ")}` }, k);
12164
+ return /* @__PURE__ */ jsx19(Text18, { color: theme.info.color, children: ` ${k.padEnd(16)} ${status} ${s.command.join(" ")}` }, k);
11456
12165
  }) }),
11457
- /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
11458
- SelectInput8,
12166
+ /* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
12167
+ SelectInput9,
11459
12168
  {
11460
12169
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
11461
12170
  onSelect: () => setPage("main")
@@ -11581,9 +12290,9 @@ var init_lsp_wizard = __esm({
11581
12290
  });
11582
12291
 
11583
12292
  // src/ui/theme-picker.tsx
11584
- import { Box as Box17, Text as Text18 } from "ink";
11585
- import SelectInput9 from "ink-select-input";
11586
- import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
12293
+ import { Box as Box18, Text as Text19 } from "ink";
12294
+ import SelectInput10 from "ink-select-input";
12295
+ import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
11587
12296
  function PaletteSwatches({ palette }) {
11588
12297
  const colors = [
11589
12298
  palette.primary,
@@ -11591,7 +12300,7 @@ function PaletteSwatches({ palette }) {
11591
12300
  palette.success,
11592
12301
  palette.error
11593
12302
  ];
11594
- return /* @__PURE__ */ jsx19(Box17, { children: colors.map((c, i) => /* @__PURE__ */ jsx19(Text18, { color: c, children: "\u2588" }, i)) });
12303
+ return /* @__PURE__ */ jsx20(Box18, { children: colors.map((c, i) => /* @__PURE__ */ jsx20(Text19, { color: c, children: "\u2588" }, i)) });
11595
12304
  }
11596
12305
  function ThemePicker({ themes, onPick, onPreview }) {
11597
12306
  const current = useTheme();
@@ -11599,10 +12308,10 @@ function ThemePicker({ themes, onPick, onPreview }) {
11599
12308
  ...themes.map((t) => ({ label: t.label, value: t.name })),
11600
12309
  { label: "< Back", value: "__back__" }
11601
12310
  ];
11602
- return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: current.accent, paddingX: 1, children: [
11603
- /* @__PURE__ */ jsx19(Text18, { color: current.accent, bold: true, children: "Pick a theme" }),
11604
- /* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
11605
- SelectInput9,
12311
+ return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", borderStyle: "round", borderColor: current.accent, paddingX: 1, children: [
12312
+ /* @__PURE__ */ jsx20(Text19, { color: current.accent, bold: true, children: "Pick a theme" }),
12313
+ /* @__PURE__ */ jsx20(Box18, { marginTop: 1, children: /* @__PURE__ */ jsx20(
12314
+ SelectInput10,
11606
12315
  {
11607
12316
  items,
11608
12317
  onHighlight: (item) => {
@@ -11621,9 +12330,9 @@ function ThemePicker({ themes, onPick, onPreview }) {
11621
12330
  itemComponent: ({ label, isSelected }) => {
11622
12331
  const t = themes.find((x) => x.label === label);
11623
12332
  const color = t?.accent ?? current.accent;
11624
- return /* @__PURE__ */ jsxs17(Box17, { children: [
11625
- /* @__PURE__ */ jsx19(Text18, { color, bold: isSelected, dimColor: !isSelected, children: label }),
11626
- t && /* @__PURE__ */ jsx19(Box17, { marginLeft: 1, children: /* @__PURE__ */ jsx19(PaletteSwatches, { palette: t.palette }) })
12333
+ return /* @__PURE__ */ jsxs18(Box18, { children: [
12334
+ /* @__PURE__ */ jsx20(Text19, { color, bold: isSelected, dimColor: !isSelected, children: label }),
12335
+ t && /* @__PURE__ */ jsx20(Box18, { marginLeft: 1, children: /* @__PURE__ */ jsx20(PaletteSwatches, { palette: t.palette }) })
11627
12336
  ] });
11628
12337
  }
11629
12338
  }
@@ -11767,8 +12476,8 @@ var init_lsp_nudge = __esm({
11767
12476
  });
11768
12477
 
11769
12478
  // src/ui/file-picker.tsx
11770
- import { Box as Box18, Text as Text19 } from "ink";
11771
- import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
12479
+ import { Box as Box19, Text as Text20 } from "ink";
12480
+ import { jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
11772
12481
  function FilePicker({ items, selectedIndex, query }) {
11773
12482
  const theme = useTheme();
11774
12483
  let startIndex = 0;
@@ -11778,12 +12487,12 @@ function FilePicker({ items, selectedIndex, query }) {
11778
12487
  const visible = items.slice(startIndex, startIndex + VISIBLE_LIMIT);
11779
12488
  const hasMoreAbove = startIndex > 0;
11780
12489
  const hasMoreBelow = items.length > startIndex + VISIBLE_LIMIT;
11781
- return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
11782
- /* @__PURE__ */ jsx20(Text19, { color: theme.accent, bold: true, children: query ? `Files matching "${query}"` : "Mention a file" }),
11783
- /* @__PURE__ */ jsx20(Text19, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select, Esc to cancel." }),
11784
- /* @__PURE__ */ jsxs18(Box18, { marginTop: 1, flexDirection: "column", children: [
11785
- visible.length === 0 && /* @__PURE__ */ jsx20(Text19, { color: theme.info.color, children: "No matches" }),
11786
- hasMoreAbove && /* @__PURE__ */ jsxs18(Text19, { color: theme.info.color, children: [
12490
+ return /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
12491
+ /* @__PURE__ */ jsx21(Text20, { color: theme.accent, bold: true, children: query ? `Files matching "${query}"` : "Mention a file" }),
12492
+ /* @__PURE__ */ jsx21(Text20, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select, Esc to cancel." }),
12493
+ /* @__PURE__ */ jsxs19(Box19, { marginTop: 1, flexDirection: "column", children: [
12494
+ visible.length === 0 && /* @__PURE__ */ jsx21(Text20, { color: theme.info.color, children: "No matches" }),
12495
+ hasMoreAbove && /* @__PURE__ */ jsxs19(Text20, { color: theme.info.color, children: [
11787
12496
  "\u2026 ",
11788
12497
  startIndex,
11789
12498
  " more above"
@@ -11792,12 +12501,12 @@ function FilePicker({ items, selectedIndex, query }) {
11792
12501
  const actualIndex = startIndex + i;
11793
12502
  const isSelected = actualIndex === selectedIndex;
11794
12503
  const label = item.isDirectory ? `${item.name}/` : item.name;
11795
- return /* @__PURE__ */ jsxs18(Text19, { color: isSelected ? theme.accent : void 0, bold: isSelected, children: [
12504
+ return /* @__PURE__ */ jsxs19(Text20, { color: isSelected ? theme.accent : void 0, bold: isSelected, children: [
11796
12505
  isSelected ? "\u203A " : " ",
11797
12506
  label
11798
12507
  ] }, item.name);
11799
12508
  }),
11800
- hasMoreBelow && /* @__PURE__ */ jsxs18(Text19, { color: theme.info.color, children: [
12509
+ hasMoreBelow && /* @__PURE__ */ jsxs19(Text20, { color: theme.info.color, children: [
11801
12510
  "\u2026 ",
11802
12511
  items.length - (startIndex + VISIBLE_LIMIT),
11803
12512
  " more below"
@@ -11815,8 +12524,8 @@ var init_file_picker = __esm({
11815
12524
  });
11816
12525
 
11817
12526
  // src/ui/slash-picker.tsx
11818
- import { Box as Box19, Text as Text20 } from "ink";
11819
- import { jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
12527
+ import { Box as Box20, Text as Text21 } from "ink";
12528
+ import { jsx as jsx22, jsxs as jsxs20 } from "react/jsx-runtime";
11820
12529
  function sourceBadge(source) {
11821
12530
  if (source === "builtin") return "";
11822
12531
  if (source === "project") return "project";
@@ -11836,12 +12545,12 @@ function SlashPicker({ items, selectedIndex, query }) {
11836
12545
  const hasMoreBelow = items.length > startIndex + VISIBLE_LIMIT2;
11837
12546
  const longestLabel = visible.reduce((m, it) => Math.max(m, commandLabel(it).length), 0);
11838
12547
  const nameColWidth = Math.max(NAME_COL_MIN_WIDTH, longestLabel + NAME_DESC_GAP);
11839
- return /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
11840
- /* @__PURE__ */ jsx21(Text20, { color: theme.accent, bold: true, children: query ? `Commands matching "/${query}"` : "Slash commands" }),
11841
- /* @__PURE__ */ jsx21(Text20, { color: theme.info.color, children: "Arrow keys to navigate, Enter to select, Esc to cancel." }),
11842
- /* @__PURE__ */ jsxs19(Box19, { marginTop: 1, flexDirection: "column", children: [
11843
- visible.length === 0 && /* @__PURE__ */ jsx21(Text20, { color: theme.info.color, children: "No matches" }),
11844
- hasMoreAbove && /* @__PURE__ */ jsxs19(Text20, { color: theme.info.color, children: [
12548
+ return /* @__PURE__ */ jsxs20(Box20, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
12549
+ /* @__PURE__ */ jsx22(Text21, { color: theme.accent, bold: true, children: query ? `Commands matching "/${query}"` : "Slash commands" }),
12550
+ /* @__PURE__ */ jsx22(Text21, { color: theme.info.color, children: "Arrow keys to navigate, Enter to select, Esc to cancel." }),
12551
+ /* @__PURE__ */ jsxs20(Box20, { marginTop: 1, flexDirection: "column", children: [
12552
+ visible.length === 0 && /* @__PURE__ */ jsx22(Text21, { color: theme.info.color, children: "No matches" }),
12553
+ hasMoreAbove && /* @__PURE__ */ jsxs20(Text21, { color: theme.info.color, children: [
11845
12554
  "\u2026 ",
11846
12555
  startIndex,
11847
12556
  " more above"
@@ -11851,16 +12560,16 @@ function SlashPicker({ items, selectedIndex, query }) {
11851
12560
  const isSelected = actualIndex === selectedIndex;
11852
12561
  const nameCol = commandLabel(item).padEnd(nameColWidth);
11853
12562
  const badge = sourceBadge(item.source);
11854
- return /* @__PURE__ */ jsxs19(Text20, { color: isSelected ? theme.accent : void 0, bold: isSelected, children: [
12563
+ return /* @__PURE__ */ jsxs20(Text21, { color: isSelected ? theme.accent : void 0, bold: isSelected, children: [
11855
12564
  isSelected ? "\u203A " : " ",
11856
12565
  nameCol,
11857
- /* @__PURE__ */ jsxs19(Text20, { color: theme.info.color, children: [
12566
+ /* @__PURE__ */ jsxs20(Text21, { color: theme.info.color, children: [
11858
12567
  item.description,
11859
12568
  badge && ` [${badge}]`
11860
12569
  ] })
11861
12570
  ] }, item.name);
11862
12571
  }),
11863
- hasMoreBelow && /* @__PURE__ */ jsxs19(Text20, { color: theme.info.color, children: [
12572
+ hasMoreBelow && /* @__PURE__ */ jsxs20(Text21, { color: theme.info.color, children: [
11864
12573
  "\u2026 ",
11865
12574
  items.length - (startIndex + VISIBLE_LIMIT2),
11866
12575
  " more below"
@@ -11941,14 +12650,14 @@ __export(tui_report_exports, {
11941
12650
  getCategoryReportText: () => getCategoryReportText
11942
12651
  });
11943
12652
  import { readFile as readFile16 } from "fs/promises";
11944
- import { join as join20 } from "path";
12653
+ import { join as join21 } from "path";
11945
12654
  import { homedir as homedir14 } from "os";
11946
12655
  function usageDir3() {
11947
- const xdg = process.env.XDG_DATA_HOME || join20(homedir14(), ".local", "share");
11948
- return join20(xdg, "kimiflare");
12656
+ const xdg = process.env.XDG_DATA_HOME || join21(homedir14(), ".local", "share");
12657
+ return join21(xdg, "kimiflare");
11949
12658
  }
11950
12659
  function usagePath3() {
11951
- return join20(usageDir3(), "usage.json");
12660
+ return join21(usageDir3(), "usage.json");
11952
12661
  }
11953
12662
  function today3() {
11954
12663
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
@@ -12026,18 +12735,18 @@ __export(app_exports, {
12026
12735
  shouldOpenMentionPicker: () => shouldOpenMentionPicker,
12027
12736
  shouldOpenSlashPicker: () => shouldOpenSlashPicker
12028
12737
  });
12029
- import React14, { useState as useState10, useRef as useRef3, useEffect as useEffect5, useCallback } from "react";
12030
- import { Box as Box20, Text as Text21, useApp, useInput as useInput6, render } from "ink";
12031
- import SelectInput10 from "ink-select-input";
12032
- import { existsSync as existsSync2, statSync as statSync3 } from "fs";
12033
- import { join as join21 } from "path";
12738
+ import React14, { useState as useState10, useRef as useRef3, useEffect as useEffect6, useCallback as useCallback2 } from "react";
12739
+ import { Box as Box21, Text as Text22, useApp, useInput as useInput7, render } from "ink";
12740
+ import SelectInput11 from "ink-select-input";
12741
+ import { existsSync as existsSync3, statSync as statSync4 } from "fs";
12742
+ import { join as join22 } from "path";
12034
12743
  import { unlink as unlink3 } from "fs/promises";
12035
12744
  import { execSync as execSync2 } from "child_process";
12036
12745
  import { spawn as spawn4 } from "child_process";
12037
12746
  import { platform as platform2 } from "os";
12038
12747
  import fg4 from "fast-glob";
12039
12748
  import { readFileSync as readFileSync3 } from "fs";
12040
- import { jsx as jsx22, jsxs as jsxs20 } from "react/jsx-runtime";
12749
+ import { jsx as jsx23, jsxs as jsxs21 } from "react/jsx-runtime";
12041
12750
  function buildFilePickerIgnoreList(cwd) {
12042
12751
  const hardcoded = [
12043
12752
  // Dependencies
@@ -12108,8 +12817,8 @@ function buildFilePickerIgnoreList(cwd) {
12108
12817
  ];
12109
12818
  const gitignorePatterns = [];
12110
12819
  try {
12111
- const gitignorePath = join21(cwd, ".gitignore");
12112
- const stats = statSync3(gitignorePath);
12820
+ const gitignorePath = join22(cwd, ".gitignore");
12821
+ const stats = statSync4(gitignorePath);
12113
12822
  if (stats.size > MAX_GITIGNORE_SIZE) {
12114
12823
  return hardcoded;
12115
12824
  }
@@ -12177,7 +12886,7 @@ function gatewayUsageLookupFromConfig(cfg, meta) {
12177
12886
  meta
12178
12887
  };
12179
12888
  }
12180
- function openBrowser(url) {
12889
+ function openBrowser2(url) {
12181
12890
  const cmd = platform2() === "darwin" ? "open" : platform2() === "win32" ? "start" : "xdg-open";
12182
12891
  const child = spawn4(cmd, [url], { detached: true, stdio: "ignore" });
12183
12892
  child.unref();
@@ -12197,7 +12906,7 @@ function detectGitHubRepo(cachedRepo) {
12197
12906
  }
12198
12907
  return null;
12199
12908
  }
12200
- function formatTokens3(n) {
12909
+ function formatTokens4(n) {
12201
12910
  if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
12202
12911
  if (n >= 1e3) return `${(n / 1e3).toFixed(1)}K`;
12203
12912
  return String(n);
@@ -12242,7 +12951,7 @@ function findImagePaths(text) {
12242
12951
  let match;
12243
12952
  while ((match = quotedRegex.exec(text)) !== null) {
12244
12953
  const path = match[1] ?? match[2];
12245
- if (path && isImagePath(path) && existsSync2(path)) {
12954
+ if (path && isImagePath(path) && existsSync3(path)) {
12246
12955
  paths.push(path);
12247
12956
  }
12248
12957
  }
@@ -12251,7 +12960,7 @@ function findImagePaths(text) {
12251
12960
  const processed = remaining.replace(/\\ /g, ESCAPED_SPACE);
12252
12961
  for (const token of processed.split(/\s+/)) {
12253
12962
  const clean = token.replace(new RegExp(ESCAPED_SPACE, "g"), " ").replace(/^["']|["',;:!?]$/g, "").replace(/[.,;:!?]$/, "");
12254
- if (clean && isImagePath(clean) && existsSync2(clean) && !paths.includes(clean)) {
12963
+ if (clean && isImagePath(clean) && existsSync3(clean) && !paths.includes(clean)) {
12255
12964
  paths.push(clean);
12256
12965
  }
12257
12966
  }
@@ -12269,7 +12978,7 @@ function App({
12269
12978
  const [lspScope, setLspScope] = useState10(initialLspScope);
12270
12979
  const [lspProjectPath, setLspProjectPath] = useState10(initialLspProjectPath);
12271
12980
  const [events, setRawEvents] = useState10([]);
12272
- const setEvents = useCallback(
12981
+ const setEvents = useCallback2(
12273
12982
  (updater) => {
12274
12983
  setRawEvents((prev) => {
12275
12984
  const next = typeof updater === "function" ? updater(prev) : updater;
@@ -12283,8 +12992,10 @@ function App({
12283
12992
  const [usage, setUsage] = useState10(null);
12284
12993
  const [sessionUsage, setSessionUsage] = useState10(null);
12285
12994
  const [gatewayMeta, setGatewayMeta] = useState10(null);
12995
+ const [cloudBudget, setCloudBudget] = useState10(null);
12286
12996
  const [showReasoning, setShowReasoning] = useState10(false);
12287
12997
  const [perm, setPerm] = useState10(null);
12998
+ const [limitModal, setLimitModal] = useState10(null);
12288
12999
  const [queue, setQueue] = useState10([]);
12289
13000
  const [history, setHistory] = useState10([]);
12290
13001
  const [historyIndex, setHistoryIndex] = useState10(-1);
@@ -12314,6 +13025,21 @@ function App({
12314
13025
  const [theme, setTheme] = useState10(resolveTheme(initialCfg?.theme));
12315
13026
  const [showThemePicker, setShowThemePicker] = useState10(false);
12316
13027
  const [originalTheme, setOriginalTheme] = useState10(null);
13028
+ useEffect6(() => {
13029
+ if (!cfg?.cloudMode || !initialCloudToken) return;
13030
+ let cancelled = false;
13031
+ const fetchBudget = async () => {
13032
+ const { fetchCloudUsage: fetchCloudUsage2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
13033
+ const usage2 = await fetchCloudUsage2(initialCloudToken);
13034
+ if (usage2 && !cancelled) {
13035
+ setCloudBudget({ remaining: usage2.remaining, limit: usage2.input_token_limit });
13036
+ }
13037
+ };
13038
+ fetchBudget();
13039
+ return () => {
13040
+ cancelled = true;
13041
+ };
13042
+ }, [cfg?.cloudMode, initialCloudToken]);
12317
13043
  const [cursorOffset, setCursorOffset] = useState10(0);
12318
13044
  const [activePicker, setActivePicker] = useState10(null);
12319
13045
  const [filePickerItems, setFilePickerItems] = useState10([]);
@@ -12327,6 +13053,7 @@ function App({
12327
13053
  const activeAsstIdRef = useRef3(null);
12328
13054
  const activeControllerRef = useRef3(null);
12329
13055
  const permResolveRef = useRef3(null);
13056
+ const limitResolveRef = useRef3(null);
12330
13057
  const pendingToolCallsRef = useRef3(/* @__PURE__ */ new Map());
12331
13058
  const sessionIdRef = useRef3(null);
12332
13059
  const modeRef = useRef3(mode);
@@ -12348,12 +13075,16 @@ function App({
12348
13075
  const lspManagerRef = useRef3(new LspManager());
12349
13076
  const lspToolsRef = useRef3([]);
12350
13077
  const lspInitRef = useRef3(false);
13078
+ const busyRef = useRef3(busy);
12351
13079
  const memoryManagerRef = useRef3(null);
12352
13080
  const sessionStartRecallRef = useRef3(null);
12353
13081
  const pendingTextRef = useRef3(/* @__PURE__ */ new Map());
12354
13082
  const flushTimeoutRef = useRef3(null);
12355
13083
  const customCommandsRef = useRef3([]);
12356
13084
  const pickerCancelRef = useRef3(null);
13085
+ useEffect6(() => {
13086
+ busyRef.current = busy;
13087
+ }, [busy]);
12357
13088
  const pickerAnchor = activePicker?.anchor ?? null;
12358
13089
  const pickerKind = activePicker?.kind ?? null;
12359
13090
  const pickerQuery = React14.useMemo(() => {
@@ -12376,7 +13107,7 @@ function App({
12376
13107
  if (pickerKind !== "slash" || pickerQuery === null) return [];
12377
13108
  return fuzzyFilter(allSlashCommands, pickerQuery, (c) => c.name).slice(0, 50);
12378
13109
  }, [pickerKind, allSlashCommands, pickerQuery]);
12379
- useEffect5(() => {
13110
+ useEffect6(() => {
12380
13111
  if (activePicker !== null) {
12381
13112
  const trigger = activePicker.kind === "file" ? "@" : "/";
12382
13113
  if (cursorOffset < activePicker.anchor) {
@@ -12433,28 +13164,28 @@ function App({
12433
13164
  return;
12434
13165
  }
12435
13166
  }, [input, cursorOffset, activePicker, filePickerEnabled]);
12436
- useEffect5(() => {
13167
+ useEffect6(() => {
12437
13168
  if (activePicker?.kind !== "file") return;
12438
13169
  const max = Math.max(0, filteredFileItems.length - 1);
12439
13170
  if (activePicker.selected > max) {
12440
13171
  setActivePicker({ ...activePicker, selected: max });
12441
13172
  }
12442
13173
  }, [filteredFileItems.length, activePicker]);
12443
- useEffect5(() => {
13174
+ useEffect6(() => {
12444
13175
  if (activePicker?.kind !== "slash") return;
12445
13176
  const max = Math.max(0, filteredSlashItems.length - 1);
12446
13177
  if (activePicker.selected > max) {
12447
13178
  setActivePicker({ ...activePicker, selected: max });
12448
13179
  }
12449
13180
  }, [filteredSlashItems.length, activePicker]);
12450
- const handlePickerUp = useCallback(() => {
13181
+ const handlePickerUp = useCallback2(() => {
12451
13182
  setActivePicker((p) => {
12452
13183
  if (!p) return null;
12453
13184
  const next = Math.max(0, p.selected - 1);
12454
13185
  return next === p.selected ? p : { ...p, selected: next };
12455
13186
  });
12456
13187
  }, []);
12457
- const handlePickerDown = useCallback(() => {
13188
+ const handlePickerDown = useCallback2(() => {
12458
13189
  setActivePicker((p) => {
12459
13190
  if (!p) return null;
12460
13191
  const max = p.kind === "file" ? Math.max(0, filteredFileItems.length - 1) : Math.max(0, filteredSlashItems.length - 1);
@@ -12462,7 +13193,7 @@ function App({
12462
13193
  return next === p.selected ? p : { ...p, selected: next };
12463
13194
  });
12464
13195
  }, [filteredFileItems.length, filteredSlashItems.length]);
12465
- const handlePickerSelect = useCallback(() => {
13196
+ const handlePickerSelect = useCallback2(() => {
12466
13197
  if (!activePicker) return;
12467
13198
  if (activePicker.kind === "file") {
12468
13199
  const item2 = filteredFileItems[activePicker.selected];
@@ -12480,12 +13211,12 @@ function App({
12480
13211
  setActivePicker(null);
12481
13212
  submitRef.current(value);
12482
13213
  }, [activePicker, filteredFileItems, filteredSlashItems, input, cursorOffset]);
12483
- const handlePickerCancel = useCallback(() => {
13214
+ const handlePickerCancel = useCallback2(() => {
12484
13215
  pickerCancelRef.current = cursorOffset;
12485
13216
  setActivePicker(null);
12486
13217
  }, [cursorOffset]);
12487
- useEffect5(() => {
12488
- const modalActive = showHelpMenu || commandWizard !== null || commandPicker !== null || commandToDelete !== null || showCommandList || showLspWizard || resumeSessions !== null || perm !== null;
13218
+ useEffect6(() => {
13219
+ const modalActive = showHelpMenu || commandWizard !== null || commandPicker !== null || commandToDelete !== null || showCommandList || showLspWizard || resumeSessions !== null || perm !== null || limitModal !== null;
12489
13220
  if (modalActive && activePicker !== null) {
12490
13221
  setActivePicker(null);
12491
13222
  }
@@ -12498,9 +13229,10 @@ function App({
12498
13229
  showLspWizard,
12499
13230
  resumeSessions,
12500
13231
  perm,
13232
+ limitModal,
12501
13233
  activePicker
12502
13234
  ]);
12503
- useEffect5(() => {
13235
+ useEffect6(() => {
12504
13236
  if (!cfg) return;
12505
13237
  void Promise.resolve().then(() => (init_sessions(), sessions_exports)).then(
12506
13238
  ({ pruneSessions: pruneSessions2 }) => pruneSessions2().then((removed) => {
@@ -12526,7 +13258,7 @@ function App({
12526
13258
  }
12527
13259
  });
12528
13260
  if (cfg.memoryEnabled) {
12529
- const dbPath = cfg.memoryDbPath ?? join21(process.cwd(), ".kimiflare", "memory.db");
13261
+ const dbPath = cfg.memoryDbPath ?? join22(process.cwd(), ".kimiflare", "memory.db");
12530
13262
  const manager = new MemoryManager({
12531
13263
  dbPath,
12532
13264
  accountId: cfg.accountId,
@@ -12594,7 +13326,7 @@ function App({
12594
13326
  }
12595
13327
  });
12596
13328
  }, [cfg, setEvents]);
12597
- useEffect5(() => {
13329
+ useEffect6(() => {
12598
13330
  const id = setInterval(() => {
12599
13331
  try {
12600
13332
  performance.clearMarks();
@@ -12604,7 +13336,7 @@ function App({
12604
13336
  }, 3e5);
12605
13337
  return () => clearInterval(id);
12606
13338
  }, []);
12607
- const reloadCustomCommands = useCallback(async () => {
13339
+ const reloadCustomCommands = useCallback2(async () => {
12608
13340
  const { commands, warnings } = await loadCustomCommands(process.cwd());
12609
13341
  customCommandsRef.current = commands;
12610
13342
  setCustomCommandsVersion((v) => v + 1);
@@ -12619,7 +13351,7 @@ function App({
12619
13351
  ]);
12620
13352
  }
12621
13353
  }, [setEvents]);
12622
- useEffect5(() => {
13354
+ useEffect6(() => {
12623
13355
  if (!cfg || updateCheckedRef.current) return;
12624
13356
  updateCheckedRef.current = true;
12625
13357
  if (initialUpdateResult) {
@@ -12670,7 +13402,7 @@ function App({
12670
13402
  }
12671
13403
  });
12672
13404
  }, [cfg, initialUpdateResult]);
12673
- useEffect5(() => {
13405
+ useEffect6(() => {
12674
13406
  modeRef.current = mode;
12675
13407
  if (cacheStableRef.current) {
12676
13408
  messagesRef.current[1] = {
@@ -12697,10 +13429,10 @@ function App({
12697
13429
  executorRef.current.clearSessionPermissions();
12698
13430
  }
12699
13431
  }, [mode, cfg?.model]);
12700
- useEffect5(() => {
13432
+ useEffect6(() => {
12701
13433
  effortRef.current = effort;
12702
13434
  }, [effort]);
12703
- useEffect5(() => {
13435
+ useEffect6(() => {
12704
13436
  if (!cfg) return;
12705
13437
  const id = setInterval(() => {
12706
13438
  void checkForUpdate().then((result) => {
@@ -12731,7 +13463,7 @@ function App({
12731
13463
  }, 30 * 60 * 1e3);
12732
13464
  return () => clearInterval(id);
12733
13465
  }, [cfg]);
12734
- const initMcp = useCallback(async () => {
13466
+ const initMcp = useCallback2(async () => {
12735
13467
  if (!cfg?.mcpServers || mcpInitRef.current) return;
12736
13468
  mcpInitRef.current = true;
12737
13469
  const manager = mcpManagerRef.current;
@@ -12792,7 +13524,7 @@ function App({
12792
13524
  ]);
12793
13525
  }
12794
13526
  }, [cfg]);
12795
- const initLsp = useCallback(async () => {
13527
+ const initLsp = useCallback2(async () => {
12796
13528
  if (!cfg?.lspEnabled || !cfg?.lspServers || lspInitRef.current) {
12797
13529
  if (lspInitRef.current) return;
12798
13530
  if (!cfg?.lspEnabled) {
@@ -12855,7 +13587,7 @@ function App({
12855
13587
  ]);
12856
13588
  }
12857
13589
  }, [cfg]);
12858
- useEffect5(() => {
13590
+ useEffect6(() => {
12859
13591
  if (cfg && !mcpInitRef.current) {
12860
13592
  void initMcp();
12861
13593
  }
@@ -12863,7 +13595,7 @@ function App({
12863
13595
  void initLsp();
12864
13596
  }
12865
13597
  }, [cfg, initMcp, initLsp]);
12866
- const ensureSessionId = useCallback(() => {
13598
+ const ensureSessionId = useCallback2(() => {
12867
13599
  if (sessionIdRef.current) return sessionIdRef.current;
12868
13600
  const firstUser = messagesRef.current.find((m) => m.role === "user");
12869
13601
  let firstText = "session";
@@ -12876,7 +13608,7 @@ function App({
12876
13608
  sessionIdRef.current = makeSessionId(firstText);
12877
13609
  return sessionIdRef.current;
12878
13610
  }, []);
12879
- const saveSessionSafe = useCallback(async () => {
13611
+ const saveSessionSafe = useCallback2(async () => {
12880
13612
  if (!cfg) return;
12881
13613
  ensureSessionId();
12882
13614
  try {
@@ -12893,7 +13625,7 @@ function App({
12893
13625
  } catch {
12894
13626
  }
12895
13627
  }, [cfg, ensureSessionId]);
12896
- const onIterationEnd = useCallback(
13628
+ const onIterationEnd = useCallback2(
12897
13629
  async (messages, signal) => {
12898
13630
  if (signal.aborted) return messages;
12899
13631
  if (!shouldCompact({ messages })) return messages;
@@ -12971,31 +13703,42 @@ function App({
12971
13703
  },
12972
13704
  [cfg]
12973
13705
  );
12974
- useInput6((inputChar, key) => {
13706
+ useInput7((inputChar, key) => {
12975
13707
  if (key.ctrl && inputChar === "c") {
12976
13708
  const hadPerm = permResolveRef.current !== null;
13709
+ const hadLimit = limitResolveRef.current !== null;
12977
13710
  if (hadPerm) {
12978
13711
  permResolveRef.current("deny");
12979
13712
  permResolveRef.current = null;
12980
13713
  setPerm(null);
12981
13714
  }
12982
- if (busy && activeControllerRef.current) {
13715
+ if (hadLimit) {
13716
+ limitResolveRef.current("stop");
13717
+ limitResolveRef.current = null;
13718
+ setLimitModal(null);
13719
+ }
13720
+ if (busyRef.current && activeControllerRef.current) {
12983
13721
  activeControllerRef.current.abort();
12984
13722
  setQueue([]);
12985
13723
  setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "(interrupted)" }]);
12986
- } else if (!hadPerm) {
13724
+ } else if (!hadPerm && !hadLimit) {
12987
13725
  void lspManagerRef.current.stopAll().finally(() => exit());
12988
13726
  }
12989
13727
  return;
12990
13728
  }
12991
13729
  if (key.escape) {
12992
- const modalOpen = perm !== null || showHelpMenu || showLspWizard || showCommandList || commandWizard !== null || commandToDelete !== null || resumeSessions !== null;
12993
- if (!modalOpen && busy && activeControllerRef.current) {
13730
+ const modalOpen = perm !== null || limitModal !== null || showHelpMenu || showLspWizard || showCommandList || commandWizard !== null || commandToDelete !== null || resumeSessions !== null;
13731
+ if (!modalOpen && busyRef.current && activeControllerRef.current) {
12994
13732
  if (permResolveRef.current) {
12995
13733
  permResolveRef.current("deny");
12996
13734
  permResolveRef.current = null;
12997
13735
  setPerm(null);
12998
13736
  }
13737
+ if (limitResolveRef.current) {
13738
+ limitResolveRef.current("stop");
13739
+ limitResolveRef.current = null;
13740
+ setLimitModal(null);
13741
+ }
12999
13742
  activeControllerRef.current.abort();
13000
13743
  setQueue([]);
13001
13744
  setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "(interrupted)" }]);
@@ -13015,7 +13758,7 @@ function App({
13015
13758
  return;
13016
13759
  }
13017
13760
  });
13018
- const flushAssistantUpdates = useCallback(() => {
13761
+ const flushAssistantUpdates = useCallback2(() => {
13019
13762
  flushTimeoutRef.current = null;
13020
13763
  const pending = pendingTextRef.current;
13021
13764
  if (pending.size === 0) return;
@@ -13033,7 +13776,7 @@ function App({
13033
13776
  })
13034
13777
  );
13035
13778
  }, []);
13036
- const updateAssistant = useCallback(
13779
+ const updateAssistant = useCallback2(
13037
13780
  (id, patch) => {
13038
13781
  const result = patch({ text: "", reasoning: "" });
13039
13782
  const assistantResult = result;
@@ -13062,7 +13805,7 @@ function App({
13062
13805
  },
13063
13806
  [flushAssistantUpdates]
13064
13807
  );
13065
- const updateTool = useCallback(
13808
+ const updateTool = useCallback2(
13066
13809
  (id, patch) => {
13067
13810
  setEvents(
13068
13811
  (evts) => evts.map(
@@ -13072,11 +13815,11 @@ function App({
13072
13815
  },
13073
13816
  []
13074
13817
  );
13075
- const updateGatewayMeta = useCallback((meta) => {
13818
+ const updateGatewayMeta = useCallback2((meta) => {
13076
13819
  gatewayMetaRef.current = meta;
13077
13820
  setGatewayMeta(meta);
13078
13821
  }, []);
13079
- const runCompact = useCallback(async () => {
13822
+ const runCompact = useCallback2(async () => {
13080
13823
  if (!cfg) return;
13081
13824
  if (busy) {
13082
13825
  setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "can't compact while model is running" }]);
@@ -13161,40 +13904,23 @@ function App({
13161
13904
  setTurnStartedAt(null);
13162
13905
  activeControllerRef.current = null;
13163
13906
  permResolveRef.current = null;
13907
+ limitResolveRef.current = null;
13164
13908
  pendingToolCallsRef.current.clear();
13165
13909
  }
13166
13910
  }, [cfg, busy, saveSessionSafe]);
13167
- const openResumePicker = useCallback(async () => {
13911
+ const openResumePicker = useCallback2(async () => {
13168
13912
  const sessions = await listSessions(200, process.cwd());
13169
13913
  setResumeSessions(sessions);
13170
13914
  }, []);
13171
- const runInit = useCallback(async () => {
13915
+ const runInit = useCallback2(async () => {
13172
13916
  if (!cfg) return;
13173
13917
  if (busy) {
13174
13918
  setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "can't /init while model is running" }]);
13175
13919
  return;
13176
13920
  }
13177
13921
  const cwd = process.cwd();
13178
- const existingName = ["KIMI.md", "KIMIFLARE.md", "AGENT.md"].find((n) => existsSync2(join21(cwd, n)));
13179
- const isRefresh = existingName !== void 0;
13180
- const promptParts = [
13181
- isRefresh ? `Regenerate ${existingName} at the repository root to refresh project context. If the file already exists, read it first and preserve anything still accurate, updating only what has changed.` : "Generate a KIMI.md at the repository root so future agents have project context.",
13182
- "",
13183
- "First, use the `glob`, `read`, and `grep` tools to understand the project: read `package.json`, the top-level `README.md` if present, the tsconfig / build config, and skim the top-level source directory structure.",
13184
- isRefresh ? `Also read the existing ${existingName} so you know what to keep vs. update.` : null,
13185
- "",
13186
- "Then call the `write` tool to create `KIMI.md` at the repo root with these sections, terse (aim \u2264 100 lines total):",
13187
- "",
13188
- "- **Project** \u2014 one-line description + primary language/runtime.",
13189
- "- **Build / test / run** \u2014 exact shell commands an agent should use.",
13190
- "- **Layout** \u2014 key directories and what lives in each.",
13191
- "- **Conventions** \u2014 naming, import style, file structure, commit style, anything surprising.",
13192
- "- **Do / Don't** \u2014 quirks or rules future agents should know.",
13193
- "",
13194
- "Do not call `tasks_set` for this. Just read what you need, then write the file."
13195
- ];
13196
- const prompt = promptParts.filter((p) => p !== null).join("\n");
13197
- setEvents((e) => [...e, { kind: "user", key: mkKey(), text: isRefresh ? `/init (refreshing ${existingName})` : "/init" }]);
13922
+ const { prompt, targetFilename, isRefresh } = buildInitPrompt(cwd);
13923
+ setEvents((e) => [...e, { kind: "user", key: mkKey(), text: isRefresh ? `/init (refreshing ${targetFilename})` : "/init" }]);
13198
13924
  messagesRef.current.push({ role: "user", content: sanitizeString(prompt) });
13199
13925
  setBusy(true);
13200
13926
  setTurnStartedAt(Date.now());
@@ -13328,7 +14054,7 @@ function App({
13328
14054
  })
13329
14055
  }
13330
14056
  });
13331
- if (existsSync2(join21(cwd, "KIMI.md"))) {
14057
+ if (existsSync3(join22(cwd, "KIMI.md"))) {
13332
14058
  if (cacheStableRef.current) {
13333
14059
  messagesRef.current[1] = {
13334
14060
  role: "system",
@@ -13383,10 +14109,11 @@ function App({
13383
14109
  activeAsstIdRef.current = null;
13384
14110
  activeControllerRef.current = null;
13385
14111
  permResolveRef.current = null;
14112
+ limitResolveRef.current = null;
13386
14113
  pendingToolCallsRef.current.clear();
13387
14114
  }
13388
14115
  }, [cfg, busy, updateAssistant, updateTool, updateGatewayMeta]);
13389
- const handleThemePick = useCallback(
14116
+ const handleThemePick = useCallback2(
13390
14117
  (picked) => {
13391
14118
  setShowThemePicker(false);
13392
14119
  setOriginalTheme(null);
@@ -13405,7 +14132,7 @@ function App({
13405
14132
  },
13406
14133
  [cfg, originalTheme]
13407
14134
  );
13408
- const handleResumePick = useCallback(
14135
+ const handleResumePick = useCallback2(
13409
14136
  async (picked) => {
13410
14137
  setResumeSessions(null);
13411
14138
  if (!picked) return;
@@ -13463,7 +14190,7 @@ function App({
13463
14190
  },
13464
14191
  []
13465
14192
  );
13466
- const handleSlash = useCallback(
14193
+ const handleSlash = useCallback2(
13467
14194
  (cmd) => {
13468
14195
  const raw = cmd.trim();
13469
14196
  const [head, ...rest] = raw.split(/\s+/);
@@ -13949,7 +14676,7 @@ ${lines.join("\n")}` }]);
13949
14676
  if (c === "/hello") {
13950
14677
  const session = crypto.randomUUID();
13951
14678
  const url = `${FEEDBACK_WORKER_URL}/?s=${session}&v=${getAppVersion()}`;
13952
- openBrowser(url);
14679
+ openBrowser2(url);
13953
14680
  setEvents((e) => [
13954
14681
  ...e,
13955
14682
  { kind: "info", key: mkKey(), text: "Opened voice note page in your browser. Record your message there and hit Send when you're done." }
@@ -14074,7 +14801,7 @@ ${lines.join("\n")}` }]);
14074
14801
  setEvents((e) => [
14075
14802
  ...e,
14076
14803
  { kind: "info", key: mkKey(), text: `Starting remote session for ${repo.owner}/${repo.name}...` },
14077
- { kind: "info", key: mkKey(), text: `Budget: ${formatTokens3(budget)} tokens. TTL: ${ttl} min.` }
14804
+ { kind: "info", key: mkKey(), text: `Budget: ${formatTokens4(budget)} tokens. TTL: ${ttl} min.` }
14078
14805
  ]);
14079
14806
  try {
14080
14807
  const data = await startRemoteSession({
@@ -14162,7 +14889,7 @@ ${lines.join("\n")}` }]);
14162
14889
  },
14163
14890
  [cfg, exit, usage, effort, theme, mode, openResumePicker, runCompact, runInit, initMcp, setCfg, setShowRemoteDashboard, setSelectedRemoteSession]
14164
14891
  );
14165
- const handleHelpCommand = useCallback(
14892
+ const handleHelpCommand = useCallback2(
14166
14893
  (command) => {
14167
14894
  setShowHelpMenu(false);
14168
14895
  const executed = handleSlash(command);
@@ -14172,7 +14899,7 @@ ${lines.join("\n")}` }]);
14172
14899
  },
14173
14900
  [handleSlash]
14174
14901
  );
14175
- const handleCommandSave = useCallback(
14902
+ const handleCommandSave = useCallback2(
14176
14903
  async (opts2) => {
14177
14904
  setCommandWizard(null);
14178
14905
  try {
@@ -14194,7 +14921,7 @@ ${lines.join("\n")}` }]);
14194
14921
  },
14195
14922
  [commandWizard, reloadCustomCommands, setEvents]
14196
14923
  );
14197
- const handleCommandDelete = useCallback(
14924
+ const handleCommandDelete = useCallback2(
14198
14925
  async (cmd) => {
14199
14926
  setCommandToDelete(null);
14200
14927
  try {
@@ -14213,7 +14940,7 @@ ${lines.join("\n")}` }]);
14213
14940
  },
14214
14941
  [reloadCustomCommands, setEvents]
14215
14942
  );
14216
- const processMessage = useCallback(
14943
+ const processMessage = useCallback2(
14217
14944
  async (text, displayText) => {
14218
14945
  if (!cfg) return;
14219
14946
  let trimmed = text.trim();
@@ -14412,6 +15139,10 @@ ${lines.join("\n")}` }]);
14412
15139
  }
14413
15140
  permResolveRef.current = resolve2;
14414
15141
  setPerm({ tool: req.tool, args: req.args, resolve: resolve2 });
15142
+ }),
15143
+ onToolLimitReached: () => new Promise((resolve2) => {
15144
+ limitResolveRef.current = resolve2;
15145
+ setLimitModal({ limit: 50, resolve: resolve2 });
14415
15146
  })
14416
15147
  };
14417
15148
  try {
@@ -14501,6 +15232,8 @@ ${lines.join("\n")}` }]);
14501
15232
  text: `auto-compact failed: ${compactErr.message ?? String(compactErr)}`
14502
15233
  }
14503
15234
  ]);
15235
+ } else {
15236
+ throw compactErr;
14504
15237
  }
14505
15238
  }
14506
15239
  }
@@ -14570,19 +15303,20 @@ ${lines.join("\n")}` }]);
14570
15303
  activeAsstIdRef.current = null;
14571
15304
  activeControllerRef.current = null;
14572
15305
  permResolveRef.current = null;
15306
+ limitResolveRef.current = null;
14573
15307
  pendingToolCallsRef.current.clear();
14574
15308
  }
14575
15309
  },
14576
15310
  [cfg, handleSlash, updateAssistant, updateTool, saveSessionSafe, updateGatewayMeta]
14577
15311
  );
14578
- useEffect5(() => {
15312
+ useEffect6(() => {
14579
15313
  if (!busy && queue.length > 0) {
14580
15314
  const next = queue[0];
14581
15315
  setQueue((q) => q.slice(1));
14582
15316
  processMessage(next.full, next.display);
14583
15317
  }
14584
15318
  }, [busy, queue, processMessage]);
14585
- const submit = useCallback(
15319
+ const submit = useCallback2(
14586
15320
  (full, display) => {
14587
15321
  const trimmedFull = full.trim();
14588
15322
  if (!trimmedFull) return;
@@ -14603,7 +15337,7 @@ ${lines.join("\n")}` }]);
14603
15337
  [busy, processMessage]
14604
15338
  );
14605
15339
  submitRef.current = submit;
14606
- useEffect5(() => {
15340
+ useEffect6(() => {
14607
15341
  if (compactSuggestedRef.current) return;
14608
15342
  if (usage && usage.prompt_tokens / CONTEXT_LIMIT >= AUTO_COMPACT_SUGGEST_PCT) {
14609
15343
  compactSuggestedRef.current = true;
@@ -14618,9 +15352,10 @@ ${lines.join("\n")}` }]);
14618
15352
  }
14619
15353
  }, [usage]);
14620
15354
  if (!cfg) {
14621
- return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(
15355
+ return /* @__PURE__ */ jsx23(ThemeProvider, { theme, children: /* @__PURE__ */ jsx23(
14622
15356
  Onboarding,
14623
15357
  {
15358
+ onCancel: () => exit(),
14624
15359
  onDone: async (newCfg) => {
14625
15360
  setCfg(newCfg);
14626
15361
  if (newCfg.cloudMode) {
@@ -14648,10 +15383,10 @@ ${lines.join("\n")}` }]);
14648
15383
  ) });
14649
15384
  }
14650
15385
  if (resumeSessions !== null) {
14651
- return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", children: /* @__PURE__ */ jsx22(ResumePicker, { sessions: resumeSessions, onPick: handleResumePick }) }) });
15386
+ return /* @__PURE__ */ jsx23(ThemeProvider, { theme, children: /* @__PURE__ */ jsx23(Box21, { flexDirection: "column", children: /* @__PURE__ */ jsx23(ResumePicker, { sessions: resumeSessions, onPick: handleResumePick }) }) });
14652
15387
  }
14653
15388
  if (showRemoteDashboard) {
14654
- return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", children: selectedRemoteSession ? /* @__PURE__ */ jsx22(
15389
+ return /* @__PURE__ */ jsx23(ThemeProvider, { theme, children: /* @__PURE__ */ jsx23(Box21, { flexDirection: "column", children: selectedRemoteSession ? /* @__PURE__ */ jsx23(
14655
15390
  RemoteSessionDetail,
14656
15391
  {
14657
15392
  session: selectedRemoteSession,
@@ -14674,7 +15409,7 @@ ${lines.join("\n")}` }]);
14674
15409
  setShowRemoteDashboard(false);
14675
15410
  }
14676
15411
  }
14677
- ) : /* @__PURE__ */ jsx22(
15412
+ ) : /* @__PURE__ */ jsx23(
14678
15413
  RemoteDashboard,
14679
15414
  {
14680
15415
  onSelect: (session) => setSelectedRemoteSession(session),
@@ -14683,7 +15418,7 @@ ${lines.join("\n")}` }]);
14683
15418
  ) }) });
14684
15419
  }
14685
15420
  if (showHelpMenu) {
14686
- return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", children: /* @__PURE__ */ jsx22(
15421
+ return /* @__PURE__ */ jsx23(ThemeProvider, { theme, children: /* @__PURE__ */ jsx23(Box21, { flexDirection: "column", children: /* @__PURE__ */ jsx23(
14687
15422
  HelpMenu,
14688
15423
  {
14689
15424
  customCommands: customCommandsRef.current.filter((c) => !BUILTIN_COMMAND_NAMES.has(c.name.toLowerCase())).map((c) => ({ name: c.name, description: c.description })),
@@ -14695,12 +15430,12 @@ ${lines.join("\n")}` }]);
14695
15430
  ) }) });
14696
15431
  }
14697
15432
  if (showLspWizard) {
14698
- return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", children: /* @__PURE__ */ jsx22(
15433
+ return /* @__PURE__ */ jsx23(ThemeProvider, { theme, children: /* @__PURE__ */ jsx23(Box21, { flexDirection: "column", children: /* @__PURE__ */ jsx23(
14699
15434
  LspWizard,
14700
15435
  {
14701
15436
  servers: cfg?.lspServers ?? {},
14702
15437
  currentScope: lspScope,
14703
- hasProjectDir: existsSync2(join21(process.cwd(), ".kimiflare")),
15438
+ hasProjectDir: existsSync3(join22(process.cwd(), ".kimiflare")),
14704
15439
  onDone: () => setShowLspWizard(false),
14705
15440
  onSave: (servers, enabled, scope) => {
14706
15441
  setCfg((c) => c ? { ...c, lspEnabled: enabled, lspServers: servers } : c);
@@ -14732,7 +15467,7 @@ ${lines.join("\n")}` }]);
14732
15467
  ) }) });
14733
15468
  }
14734
15469
  if (commandWizard) {
14735
- return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", children: /* @__PURE__ */ jsx22(
15470
+ return /* @__PURE__ */ jsx23(ThemeProvider, { theme, children: /* @__PURE__ */ jsx23(Box21, { flexDirection: "column", children: /* @__PURE__ */ jsx23(
14736
15471
  CommandWizard,
14737
15472
  {
14738
15473
  mode: commandWizard.mode,
@@ -14745,7 +15480,7 @@ ${lines.join("\n")}` }]);
14745
15480
  ) }) });
14746
15481
  }
14747
15482
  if (commandPicker) {
14748
- return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", children: /* @__PURE__ */ jsx22(
15483
+ return /* @__PURE__ */ jsx23(ThemeProvider, { theme, children: /* @__PURE__ */ jsx23(Box21, { flexDirection: "column", children: /* @__PURE__ */ jsx23(
14749
15484
  CommandPicker,
14750
15485
  {
14751
15486
  commands: customCommandsRef.current,
@@ -14763,15 +15498,15 @@ ${lines.join("\n")}` }]);
14763
15498
  ) }) });
14764
15499
  }
14765
15500
  if (commandToDelete) {
14766
- return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsxs20(Box20, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
14767
- /* @__PURE__ */ jsxs20(Text21, { color: theme.accent, bold: true, children: [
15501
+ return /* @__PURE__ */ jsx23(ThemeProvider, { theme, children: /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
15502
+ /* @__PURE__ */ jsxs21(Text22, { color: theme.accent, bold: true, children: [
14768
15503
  "Delete /",
14769
15504
  commandToDelete.name,
14770
15505
  "?"
14771
15506
  ] }),
14772
- /* @__PURE__ */ jsx22(Text21, { color: theme.info.color, children: commandToDelete.filepath }),
14773
- /* @__PURE__ */ jsx22(Box20, { marginTop: 1, children: /* @__PURE__ */ jsx22(
14774
- SelectInput10,
15507
+ /* @__PURE__ */ jsx23(Text22, { color: theme.info.color, children: commandToDelete.filepath }),
15508
+ /* @__PURE__ */ jsx23(Box21, { marginTop: 1, children: /* @__PURE__ */ jsx23(
15509
+ SelectInput11,
14775
15510
  {
14776
15511
  items: [
14777
15512
  { label: "Yes, delete", value: "yes", key: "yes" },
@@ -14789,7 +15524,7 @@ ${lines.join("\n")}` }]);
14789
15524
  ] }) });
14790
15525
  }
14791
15526
  if (showCommandList) {
14792
- return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", children: /* @__PURE__ */ jsx22(
15527
+ return /* @__PURE__ */ jsx23(ThemeProvider, { theme, children: /* @__PURE__ */ jsx23(Box21, { flexDirection: "column", children: /* @__PURE__ */ jsx23(
14793
15528
  CommandList,
14794
15529
  {
14795
15530
  commands: customCommandsRef.current,
@@ -14798,12 +15533,12 @@ ${lines.join("\n")}` }]);
14798
15533
  ) }) });
14799
15534
  }
14800
15535
  if (showThemePicker) {
14801
- return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", children: /* @__PURE__ */ jsx22(ThemePicker, { themes: themeList(), onPick: handleThemePick, onPreview: (t) => setTheme(t) }) }) });
15536
+ return /* @__PURE__ */ jsx23(ThemeProvider, { theme, children: /* @__PURE__ */ jsx23(Box21, { flexDirection: "column", children: /* @__PURE__ */ jsx23(ThemePicker, { themes: themeList(), onPick: handleThemePick, onPreview: (t) => setTheme(t) }) }) });
14802
15537
  }
14803
15538
  const hasConversation = events.some((e) => e.kind === "user" || e.kind === "assistant");
14804
- return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsxs20(Box20, { flexDirection: "column", children: [
14805
- !hasConversation && events.length === 0 ? /* @__PURE__ */ jsx22(Welcome, { accountId: cfg.accountId }) : /* @__PURE__ */ jsx22(ChatView, { events, showReasoning, verbose }),
14806
- perm ? /* @__PURE__ */ jsx22(
15539
+ return /* @__PURE__ */ jsx23(ThemeProvider, { theme, children: /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", children: [
15540
+ !hasConversation && events.length === 0 ? /* @__PURE__ */ jsx23(Welcome, { accountId: cfg.accountId }) : /* @__PURE__ */ jsx23(ChatView, { events, showReasoning, verbose }),
15541
+ perm ? /* @__PURE__ */ jsx23(
14807
15542
  PermissionModal,
14808
15543
  {
14809
15544
  tool: perm.tool,
@@ -14814,8 +15549,18 @@ ${lines.join("\n")}` }]);
14814
15549
  setPerm(null);
14815
15550
  }
14816
15551
  }
14817
- ) : /* @__PURE__ */ jsxs20(Box20, { flexDirection: "column", marginTop: 1, children: [
14818
- tasks.length > 0 && /* @__PURE__ */ jsx22(
15552
+ ) : limitModal ? /* @__PURE__ */ jsx23(
15553
+ LimitModal,
15554
+ {
15555
+ limit: limitModal.limit,
15556
+ onDecide: (d) => {
15557
+ limitModal.resolve(d);
15558
+ limitResolveRef.current = null;
15559
+ setLimitModal(null);
15560
+ }
15561
+ }
15562
+ ) : /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", marginTop: 1, children: [
15563
+ tasks.length > 0 && /* @__PURE__ */ jsx23(
14819
15564
  TaskList,
14820
15565
  {
14821
15566
  tasks,
@@ -14823,11 +15568,11 @@ ${lines.join("\n")}` }]);
14823
15568
  tokensDelta: Math.max(0, (usage?.prompt_tokens ?? 0) - tasksStartTokens)
14824
15569
  }
14825
15570
  ),
14826
- queue.length > 0 && /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", marginBottom: 1, children: queue.map((q, i) => /* @__PURE__ */ jsxs20(Text21, { color: theme.info.color, children: [
15571
+ queue.length > 0 && /* @__PURE__ */ jsx23(Box21, { flexDirection: "column", marginBottom: 1, children: queue.map((q, i) => /* @__PURE__ */ jsxs21(Text22, { color: theme.info.color, children: [
14827
15572
  "\u23F3 ",
14828
15573
  q.display
14829
15574
  ] }, `queue_${i}`)) }),
14830
- /* @__PURE__ */ jsx22(
15575
+ /* @__PURE__ */ jsx23(
14831
15576
  StatusBar,
14832
15577
  {
14833
15578
  model: cfg.model,
@@ -14842,10 +15587,11 @@ ${lines.join("\n")}` }]);
14842
15587
  latestVersion,
14843
15588
  gatewayMeta,
14844
15589
  codeMode,
14845
- cloudMode: cfg.cloudMode
15590
+ cloudMode: cfg.cloudMode,
15591
+ cloudBudget
14846
15592
  }
14847
15593
  ),
14848
- activePicker?.kind === "file" && /* @__PURE__ */ jsx22(
15594
+ activePicker?.kind === "file" && /* @__PURE__ */ jsx23(
14849
15595
  FilePicker,
14850
15596
  {
14851
15597
  items: filteredFileItems,
@@ -14853,7 +15599,7 @@ ${lines.join("\n")}` }]);
14853
15599
  query: pickerQuery ?? ""
14854
15600
  }
14855
15601
  ),
14856
- activePicker?.kind === "slash" && /* @__PURE__ */ jsx22(
15602
+ activePicker?.kind === "slash" && /* @__PURE__ */ jsx23(
14857
15603
  SlashPicker,
14858
15604
  {
14859
15605
  items: filteredSlashItems,
@@ -14861,9 +15607,9 @@ ${lines.join("\n")}` }]);
14861
15607
  query: pickerQuery ?? ""
14862
15608
  }
14863
15609
  ),
14864
- /* @__PURE__ */ jsxs20(Box20, { marginTop: 1, children: [
14865
- /* @__PURE__ */ jsx22(Text21, { color: "#d699b6", children: "\u203A " }),
14866
- /* @__PURE__ */ jsx22(
15610
+ /* @__PURE__ */ jsxs21(Box21, { marginTop: 1, children: [
15611
+ /* @__PURE__ */ jsx23(Text22, { color: "#d699b6", children: "\u203A " }),
15612
+ /* @__PURE__ */ jsx23(
14867
15613
  CustomTextInput,
14868
15614
  {
14869
15615
  value: input,
@@ -14920,7 +15666,7 @@ ${lines.join("\n")}` }]);
14920
15666
  }
14921
15667
  async function renderApp(cfg, updateResult, lspScope = "global", lspProjectPath = null, cloudToken) {
14922
15668
  const instance = render(
14923
- /* @__PURE__ */ jsx22(
15669
+ /* @__PURE__ */ jsx23(
14924
15670
  App,
14925
15671
  {
14926
15672
  initialCfg: cfg,
@@ -14954,6 +15700,7 @@ var init_app = __esm({
14954
15700
  init_chat();
14955
15701
  init_status();
14956
15702
  init_permission();
15703
+ init_limit_modal();
14957
15704
  init_resume_picker();
14958
15705
  init_task_list();
14959
15706
  init_text_input();
@@ -14981,6 +15728,7 @@ var init_app = __esm({
14981
15728
  init_builtins();
14982
15729
  init_save();
14983
15730
  init_command_wizard();
15731
+ init_context_generator();
14984
15732
  init_command_picker();
14985
15733
  init_command_list();
14986
15734
  init_lsp_wizard();