kimiflare 0.51.0 → 0.53.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
@@ -915,6 +915,21 @@ function toOpenAIToolDefs(tools) {
915
915
  }
916
916
  }));
917
917
  }
918
+ function isValidStatus(s) {
919
+ return s === "pending" || s === "in_progress" || s === "completed";
920
+ }
921
+ function validateTasks(input) {
922
+ if (!Array.isArray(input)) throw new Error("tasks must be an array");
923
+ return input.map((t, i) => {
924
+ if (!t || typeof t !== "object") throw new Error(`tasks[${i}] must be an object`);
925
+ const rec = t;
926
+ const id = typeof rec.id === "string" && rec.id.length > 0 ? rec.id : String(i + 1);
927
+ const title = typeof rec.title === "string" ? rec.title.trim() : "";
928
+ if (!title) throw new Error(`tasks[${i}].title is required`);
929
+ const status = isValidStatus(rec.status) ? rec.status : "pending";
930
+ return { id, title, status };
931
+ });
932
+ }
918
933
  var init_registry = __esm({
919
934
  "src/tools/registry.ts"() {
920
935
  "use strict";
@@ -1556,8 +1571,8 @@ var require_node_gyp_build = __commonJS({
1556
1571
  var abi = process.versions.modules;
1557
1572
  var runtime = isElectron() ? "electron" : isNwjs() ? "node-webkit" : "node";
1558
1573
  var arch = process.env.npm_config_arch || os2.arch();
1559
- var platform3 = process.env.npm_config_platform || os2.platform();
1560
- var libc = process.env.LIBC || (isAlpine(platform3) ? "musl" : "glibc");
1574
+ var platform4 = process.env.npm_config_platform || os2.platform();
1575
+ var libc = process.env.LIBC || (isAlpine(platform4) ? "musl" : "glibc");
1561
1576
  var armv = process.env.ARM_VERSION || (arch === "arm64" ? "8" : vars.arm_version) || "";
1562
1577
  var uv = (process.versions.uv || "").split(".")[0];
1563
1578
  module.exports = load;
@@ -1582,7 +1597,7 @@ var require_node_gyp_build = __commonJS({
1582
1597
  var nearby = resolve3(path.dirname(process.execPath));
1583
1598
  if (nearby) return nearby;
1584
1599
  var target = [
1585
- "platform=" + platform3,
1600
+ "platform=" + platform4,
1586
1601
  "arch=" + arch,
1587
1602
  "runtime=" + runtime,
1588
1603
  "abi=" + abi,
@@ -1597,7 +1612,7 @@ var require_node_gyp_build = __commonJS({
1597
1612
  throw new Error("No native build was found for " + target + "\n loaded from: " + dir + "\n");
1598
1613
  function resolve3(dir2) {
1599
1614
  var tuples = readdirSync(path.join(dir2, "prebuilds")).map(parseTuple);
1600
- var tuple = tuples.filter(matchTuple(platform3, arch)).sort(compareTuples)[0];
1615
+ var tuple = tuples.filter(matchTuple(platform4, arch)).sort(compareTuples)[0];
1601
1616
  if (!tuple) return;
1602
1617
  var prebuilds = path.join(dir2, "prebuilds", tuple.name);
1603
1618
  var parsed = readdirSync(prebuilds).map(parseTags);
@@ -1623,17 +1638,17 @@ var require_node_gyp_build = __commonJS({
1623
1638
  function parseTuple(name) {
1624
1639
  var arr = name.split("-");
1625
1640
  if (arr.length !== 2) return;
1626
- var platform4 = arr[0];
1641
+ var platform5 = arr[0];
1627
1642
  var architectures = arr[1].split("+");
1628
- if (!platform4) return;
1643
+ if (!platform5) return;
1629
1644
  if (!architectures.length) return;
1630
1645
  if (!architectures.every(Boolean)) return;
1631
- return { name, platform: platform4, architectures };
1646
+ return { name, platform: platform5, architectures };
1632
1647
  }
1633
- function matchTuple(platform4, arch2) {
1648
+ function matchTuple(platform5, arch2) {
1634
1649
  return function(tuple) {
1635
1650
  if (tuple == null) return false;
1636
- if (tuple.platform !== platform4) return false;
1651
+ if (tuple.platform !== platform5) return false;
1637
1652
  return tuple.architectures.includes(arch2);
1638
1653
  };
1639
1654
  }
@@ -1701,8 +1716,8 @@ var require_node_gyp_build = __commonJS({
1701
1716
  if (process.env.ELECTRON_RUN_AS_NODE) return true;
1702
1717
  return typeof window !== "undefined" && window.process && window.process.type === "renderer";
1703
1718
  }
1704
- function isAlpine(platform4) {
1705
- return platform4 === "linux" && fs.existsSync("/etc/alpine-release");
1719
+ function isAlpine(platform5) {
1720
+ return platform5 === "linux" && fs.existsSync("/etc/alpine-release");
1706
1721
  }
1707
1722
  load.parseTags = parseTags;
1708
1723
  load.matchTags = matchTags;
@@ -2114,7 +2129,7 @@ var init_session_state = __esm({
2114
2129
  }
2115
2130
  });
2116
2131
 
2117
- // src/agent/compaction.ts
2132
+ // src/agent/artifact-compaction.ts
2118
2133
  function approxTokens2(n) {
2119
2134
  return Math.round(n / 4);
2120
2135
  }
@@ -2313,7 +2328,7 @@ function shouldCompact(opts2) {
2313
2328
  const { turns } = groupIntoTurns(opts2.messages);
2314
2329
  return tokens > tokenThreshold || turns.length > turnThreshold;
2315
2330
  }
2316
- function compactMessages(opts2) {
2331
+ function compactMessagesViaArtifacts(opts2) {
2317
2332
  const keepLastTurns = opts2.keepLastTurns ?? 4;
2318
2333
  const { prefix, turns } = groupIntoTurns(opts2.messages);
2319
2334
  const tokensBefore = estimatePromptTokens(opts2.messages);
@@ -2397,8 +2412,8 @@ function recallArtifacts(messages, store, state) {
2397
2412
  const recalled = store.recall(uniqueIds);
2398
2413
  return { ids: uniqueIds, recalled };
2399
2414
  }
2400
- var init_compaction = __esm({
2401
- "src/agent/compaction.ts"() {
2415
+ var init_artifact_compaction = __esm({
2416
+ "src/agent/artifact-compaction.ts"() {
2402
2417
  "use strict";
2403
2418
  init_session_state();
2404
2419
  }
@@ -2788,6 +2803,7 @@ ${sandboxResult.output}` : `${warningPrefix}${sandboxResult.output}`;
2788
2803
  recentToolCalls.push(loopSignature);
2789
2804
  if (recentToolCalls.length > LOOP_WINDOW) recentToolCalls.shift();
2790
2805
  } else {
2806
+ opts2.callbacks.onToolWillExecute?.(tc.id, tc.function.name);
2791
2807
  logger.debug("turn:tool_start", { sessionId: opts2.sessionId, tool: tc.function.name, toolCallId: tc.id });
2792
2808
  const result = await opts2.executor.run(
2793
2809
  { id: tc.id, name: tc.function.name, arguments: tc.function.arguments },
@@ -2922,7 +2938,7 @@ var init_loop = __esm({
2922
2938
  init_extractors();
2923
2939
  init_strip_reasoning();
2924
2940
  init_code_mode();
2925
- init_compaction();
2941
+ init_artifact_compaction();
2926
2942
  init_logger();
2927
2943
  BudgetExhaustedError = class extends Error {
2928
2944
  constructor(message2 = "Cumulative input token budget exhausted") {
@@ -4182,34 +4198,12 @@ var init_browser = __esm({
4182
4198
  }
4183
4199
  });
4184
4200
 
4185
- // src/tasks-state.ts
4186
- function isValidStatus(s) {
4187
- return s === "pending" || s === "in_progress" || s === "completed";
4188
- }
4189
- function validateTasks(input) {
4190
- if (!Array.isArray(input)) throw new Error("tasks must be an array");
4191
- return input.map((t, i) => {
4192
- if (!t || typeof t !== "object") throw new Error(`tasks[${i}] must be an object`);
4193
- const rec = t;
4194
- const id = typeof rec.id === "string" && rec.id.length > 0 ? rec.id : String(i + 1);
4195
- const title = typeof rec.title === "string" ? rec.title.trim() : "";
4196
- if (!title) throw new Error(`tasks[${i}].title is required`);
4197
- const status = isValidStatus(rec.status) ? rec.status : "pending";
4198
- return { id, title, status };
4199
- });
4200
- }
4201
- var init_tasks_state = __esm({
4202
- "src/tasks-state.ts"() {
4203
- "use strict";
4204
- }
4205
- });
4206
-
4207
4201
  // src/tools/tasks.ts
4208
4202
  var tasksSetTool;
4209
4203
  var init_tasks = __esm({
4210
4204
  "src/tools/tasks.ts"() {
4211
4205
  "use strict";
4212
- init_tasks_state();
4206
+ init_registry();
4213
4207
  tasksSetTool = {
4214
4208
  name: "tasks_set",
4215
4209
  description: [
@@ -9486,7 +9480,7 @@ var init_supervisor = __esm({
9486
9480
  }
9487
9481
  });
9488
9482
 
9489
- // src/agent/compact.ts
9483
+ // src/agent/llm-summarize.ts
9490
9484
  function indexOfNthUserFromEnd(messages, n) {
9491
9485
  let seen = 0;
9492
9486
  for (let i = messages.length - 1; i >= 0; i--) {
@@ -9497,7 +9491,7 @@ function indexOfNthUserFromEnd(messages, n) {
9497
9491
  }
9498
9492
  return -1;
9499
9493
  }
9500
- async function compactMessages2(opts2) {
9494
+ async function summarizeMessagesViaLlm(opts2) {
9501
9495
  const keep = opts2.keepLastTurns ?? 4;
9502
9496
  const messages = opts2.messages;
9503
9497
  let prefixEnd = 0;
@@ -9559,8 +9553,8 @@ ${summary.trim()}`
9559
9553
  };
9560
9554
  }
9561
9555
  var SUMMARY_SYSTEM;
9562
- var init_compact = __esm({
9563
- "src/agent/compact.ts"() {
9556
+ var init_llm_summarize = __esm({
9557
+ "src/agent/llm-summarize.ts"() {
9564
9558
  "use strict";
9565
9559
  init_client();
9566
9560
  SUMMARY_SYSTEM = `You are summarizing a terminal coding session so it can fit back into a short context window. Produce a dense summary that captures:
@@ -10180,12 +10174,14 @@ var init_tool_view = __esm({
10180
10174
  const id = setInterval(() => setNow(Date.now()), 1e3);
10181
10175
  return () => clearInterval(id);
10182
10176
  }, [evt.status, evt.startedAt]);
10183
- const statusIcon = evt.status === "running" ? /* @__PURE__ */ jsx3(Text2, { color: theme.info.color, children: /* @__PURE__ */ jsx3(Spinner, { type: "dots" }) }) : evt.status === "error" ? /* @__PURE__ */ jsx3(Text2, { color: theme.palette.error, children: "\u2717" }) : /* @__PURE__ */ jsx3(Text2, { color: theme.palette.success, children: "\u2713" });
10177
+ const statusIcon = evt.status === "queued" ? /* @__PURE__ */ jsx3(Text2, { color: theme.muted?.color ?? theme.info.color, children: "[ ]" }) : evt.status === "running" ? /* @__PURE__ */ jsx3(Text2, { color: theme.info.color, children: /* @__PURE__ */ jsx3(Spinner, { type: "dots" }) }) : evt.status === "error" ? /* @__PURE__ */ jsx3(Text2, { color: theme.palette.error, children: "[err]" }) : evt.status === "cancelled" ? /* @__PURE__ */ jsx3(Text2, { color: theme.info.color, children: "[x]" }) : evt.status === "rejected" ? /* @__PURE__ */ jsx3(Text2, { color: theme.palette.error, children: "[!]" }) : /* @__PURE__ */ jsx3(Text2, { color: theme.palette.success, children: "[ok]" });
10184
10178
  const rawTitle = evt.render?.title ?? `${evt.name}(${compactArgs(evt.args)})`;
10185
10179
  let title = humanizeToolTitle(evt.name, rawTitle, intentTier);
10186
- if (evt.startedAt !== void 0) {
10180
+ if (evt.startedAt !== void 0 && (evt.status === "running" || evt.status === "done" || evt.status === "error")) {
10187
10181
  title += ` \xB7 ${formatElapsed(now2 - evt.startedAt)}`;
10188
10182
  }
10183
+ const statusLabel = evt.status === "rejected" ? /* @__PURE__ */ jsx3(Text2, { color: theme.palette.error, children: " rejected" }) : evt.status === "cancelled" ? /* @__PURE__ */ jsx3(Text2, { color: theme.info.color, children: " cancelled" }) : null;
10184
+ const showItalic = evt.status === "queued" || evt.status === "cancelled" || evt.status === "rejected";
10189
10185
  const expand = Boolean(evt.expanded || verbose);
10190
10186
  const lines = evt.result ? evt.result.split("\n") : [];
10191
10187
  const showLimit = verbose ? 200 : 20;
@@ -10193,8 +10189,9 @@ var init_tool_view = __esm({
10193
10189
  /* @__PURE__ */ jsxs2(Text2, { children: [
10194
10190
  statusIcon,
10195
10191
  " ",
10196
- /* @__PURE__ */ jsx3(Text2, { color: theme.info.color, children: title }),
10197
- isRepeated ? /* @__PURE__ */ jsx3(Text2, { color: theme.warn, children: " \u26A0 repeated" }) : null
10192
+ /* @__PURE__ */ jsx3(Text2, { color: theme.info.color, italic: showItalic, children: title }),
10193
+ statusLabel,
10194
+ isRepeated ? /* @__PURE__ */ jsx3(Text2, { color: theme.warn, children: " [warn] repeated" }) : null
10198
10195
  ] }),
10199
10196
  evt.render?.diff ? /* @__PURE__ */ jsx3(Box2, { marginLeft: 2, children: /* @__PURE__ */ jsx3(DiffView, { ...evt.render.diff }) }) : null,
10200
10197
  evt.result && expand ? /* @__PURE__ */ jsxs2(
@@ -10216,7 +10213,7 @@ var init_tool_view = __esm({
10216
10213
  ]
10217
10214
  }
10218
10215
  ) : null,
10219
- evt.result && !expand && evt.status !== "running" ? /* @__PURE__ */ jsxs2(Text2, { color: theme.info.color, children: [
10216
+ evt.result && !expand && evt.status !== "running" && evt.status !== "queued" && evt.status !== "cancelled" && evt.status !== "rejected" ? /* @__PURE__ */ jsxs2(Text2, { color: theme.info.color, children: [
10220
10217
  " ",
10221
10218
  firstLine(evt.result)
10222
10219
  ] }) : null
@@ -10801,1214 +10798,1354 @@ var init_status = __esm({
10801
10798
  }
10802
10799
  });
10803
10800
 
10804
- // src/ui/permission.tsx
10805
- import { Box as Box7, Text as Text7 } from "ink";
10806
- import SelectInput from "ink-select-input";
10807
- import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
10808
- function PermissionModal({ tool, args, onDecide }) {
10809
- const theme = useTheme();
10810
- let render2;
10811
- try {
10812
- render2 = tool.render?.(args);
10813
- } catch {
10801
+ // node_modules/chalk/source/vendor/ansi-styles/index.js
10802
+ function assembleStyles() {
10803
+ const codes = /* @__PURE__ */ new Map();
10804
+ for (const [groupName, group] of Object.entries(styles)) {
10805
+ for (const [styleName, style] of Object.entries(group)) {
10806
+ styles[styleName] = {
10807
+ open: `\x1B[${style[0]}m`,
10808
+ close: `\x1B[${style[1]}m`
10809
+ };
10810
+ group[styleName] = styles[styleName];
10811
+ codes.set(style[0], style[1]);
10812
+ }
10813
+ Object.defineProperty(styles, groupName, {
10814
+ value: group,
10815
+ enumerable: false
10816
+ });
10814
10817
  }
10815
- const items = [
10816
- { label: "Allow once", value: "allow" },
10817
- { label: "Allow for this session", value: "allow_session" },
10818
- { label: "Deny", value: "deny" }
10819
- ];
10820
- return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", borderStyle: "round", borderColor: theme.permission, paddingX: 1, children: [
10821
- /* @__PURE__ */ jsx8(Text7, { color: theme.permission, bold: true, children: "Permission requested" }),
10822
- /* @__PURE__ */ jsxs7(Text7, { children: [
10823
- "tool: ",
10824
- /* @__PURE__ */ jsx8(Text7, { color: theme.tool, children: tool.name })
10825
- ] }),
10826
- render2?.title ? /* @__PURE__ */ jsxs7(Text7, { children: [
10827
- "action: ",
10828
- render2.title
10829
- ] }) : null,
10830
- render2?.diff ? /* @__PURE__ */ jsx8(Box7, { marginTop: 1, flexDirection: "column", children: /* @__PURE__ */ jsx8(DiffView, { ...render2.diff }) }) : /* @__PURE__ */ jsxs7(Text7, { color: theme.info.color, children: [
10831
- "args: ",
10832
- JSON.stringify(args)
10833
- ] }),
10834
- /* @__PURE__ */ jsx8(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx8(SelectInput, { items, onSelect: (item) => onDecide(item.value) }) })
10835
- ] });
10818
+ Object.defineProperty(styles, "codes", {
10819
+ value: codes,
10820
+ enumerable: false
10821
+ });
10822
+ styles.color.close = "\x1B[39m";
10823
+ styles.bgColor.close = "\x1B[49m";
10824
+ styles.color.ansi = wrapAnsi16();
10825
+ styles.color.ansi256 = wrapAnsi256();
10826
+ styles.color.ansi16m = wrapAnsi16m();
10827
+ styles.bgColor.ansi = wrapAnsi16(ANSI_BACKGROUND_OFFSET);
10828
+ styles.bgColor.ansi256 = wrapAnsi256(ANSI_BACKGROUND_OFFSET);
10829
+ styles.bgColor.ansi16m = wrapAnsi16m(ANSI_BACKGROUND_OFFSET);
10830
+ Object.defineProperties(styles, {
10831
+ rgbToAnsi256: {
10832
+ value(red, green, blue) {
10833
+ if (red === green && green === blue) {
10834
+ if (red < 8) {
10835
+ return 16;
10836
+ }
10837
+ if (red > 248) {
10838
+ return 231;
10839
+ }
10840
+ return Math.round((red - 8) / 247 * 24) + 232;
10841
+ }
10842
+ return 16 + 36 * Math.round(red / 255 * 5) + 6 * Math.round(green / 255 * 5) + Math.round(blue / 255 * 5);
10843
+ },
10844
+ enumerable: false
10845
+ },
10846
+ hexToRgb: {
10847
+ value(hex) {
10848
+ const matches = /[a-f\d]{6}|[a-f\d]{3}/i.exec(hex.toString(16));
10849
+ if (!matches) {
10850
+ return [0, 0, 0];
10851
+ }
10852
+ let [colorString] = matches;
10853
+ if (colorString.length === 3) {
10854
+ colorString = [...colorString].map((character) => character + character).join("");
10855
+ }
10856
+ const integer = Number.parseInt(colorString, 16);
10857
+ return [
10858
+ /* eslint-disable no-bitwise */
10859
+ integer >> 16 & 255,
10860
+ integer >> 8 & 255,
10861
+ integer & 255
10862
+ /* eslint-enable no-bitwise */
10863
+ ];
10864
+ },
10865
+ enumerable: false
10866
+ },
10867
+ hexToAnsi256: {
10868
+ value: (hex) => styles.rgbToAnsi256(...styles.hexToRgb(hex)),
10869
+ enumerable: false
10870
+ },
10871
+ ansi256ToAnsi: {
10872
+ value(code) {
10873
+ if (code < 8) {
10874
+ return 30 + code;
10875
+ }
10876
+ if (code < 16) {
10877
+ return 90 + (code - 8);
10878
+ }
10879
+ let red;
10880
+ let green;
10881
+ let blue;
10882
+ if (code >= 232) {
10883
+ red = ((code - 232) * 10 + 8) / 255;
10884
+ green = red;
10885
+ blue = red;
10886
+ } else {
10887
+ code -= 16;
10888
+ const remainder = code % 36;
10889
+ red = Math.floor(code / 36) / 5;
10890
+ green = Math.floor(remainder / 6) / 5;
10891
+ blue = remainder % 6 / 5;
10892
+ }
10893
+ const value = Math.max(red, green, blue) * 2;
10894
+ if (value === 0) {
10895
+ return 30;
10896
+ }
10897
+ let result = 30 + (Math.round(blue) << 2 | Math.round(green) << 1 | Math.round(red));
10898
+ if (value === 2) {
10899
+ result += 60;
10900
+ }
10901
+ return result;
10902
+ },
10903
+ enumerable: false
10904
+ },
10905
+ rgbToAnsi: {
10906
+ value: (red, green, blue) => styles.ansi256ToAnsi(styles.rgbToAnsi256(red, green, blue)),
10907
+ enumerable: false
10908
+ },
10909
+ hexToAnsi: {
10910
+ value: (hex) => styles.ansi256ToAnsi(styles.hexToAnsi256(hex)),
10911
+ enumerable: false
10912
+ }
10913
+ });
10914
+ return styles;
10836
10915
  }
10837
- var init_permission = __esm({
10838
- "src/ui/permission.tsx"() {
10916
+ var ANSI_BACKGROUND_OFFSET, wrapAnsi16, wrapAnsi256, wrapAnsi16m, styles, modifierNames, foregroundColorNames, backgroundColorNames, colorNames, ansiStyles, ansi_styles_default;
10917
+ var init_ansi_styles = __esm({
10918
+ "node_modules/chalk/source/vendor/ansi-styles/index.js"() {
10839
10919
  "use strict";
10840
- init_diff_view();
10841
- init_theme_context();
10920
+ ANSI_BACKGROUND_OFFSET = 10;
10921
+ wrapAnsi16 = (offset = 0) => (code) => `\x1B[${code + offset}m`;
10922
+ wrapAnsi256 = (offset = 0) => (code) => `\x1B[${38 + offset};5;${code}m`;
10923
+ wrapAnsi16m = (offset = 0) => (red, green, blue) => `\x1B[${38 + offset};2;${red};${green};${blue}m`;
10924
+ styles = {
10925
+ modifier: {
10926
+ reset: [0, 0],
10927
+ // 21 isn't widely supported and 22 does the same thing
10928
+ bold: [1, 22],
10929
+ dim: [2, 22],
10930
+ italic: [3, 23],
10931
+ underline: [4, 24],
10932
+ overline: [53, 55],
10933
+ inverse: [7, 27],
10934
+ hidden: [8, 28],
10935
+ strikethrough: [9, 29]
10936
+ },
10937
+ color: {
10938
+ black: [30, 39],
10939
+ red: [31, 39],
10940
+ green: [32, 39],
10941
+ yellow: [33, 39],
10942
+ blue: [34, 39],
10943
+ magenta: [35, 39],
10944
+ cyan: [36, 39],
10945
+ white: [37, 39],
10946
+ // Bright color
10947
+ blackBright: [90, 39],
10948
+ gray: [90, 39],
10949
+ // Alias of `blackBright`
10950
+ grey: [90, 39],
10951
+ // Alias of `blackBright`
10952
+ redBright: [91, 39],
10953
+ greenBright: [92, 39],
10954
+ yellowBright: [93, 39],
10955
+ blueBright: [94, 39],
10956
+ magentaBright: [95, 39],
10957
+ cyanBright: [96, 39],
10958
+ whiteBright: [97, 39]
10959
+ },
10960
+ bgColor: {
10961
+ bgBlack: [40, 49],
10962
+ bgRed: [41, 49],
10963
+ bgGreen: [42, 49],
10964
+ bgYellow: [43, 49],
10965
+ bgBlue: [44, 49],
10966
+ bgMagenta: [45, 49],
10967
+ bgCyan: [46, 49],
10968
+ bgWhite: [47, 49],
10969
+ // Bright color
10970
+ bgBlackBright: [100, 49],
10971
+ bgGray: [100, 49],
10972
+ // Alias of `bgBlackBright`
10973
+ bgGrey: [100, 49],
10974
+ // Alias of `bgBlackBright`
10975
+ bgRedBright: [101, 49],
10976
+ bgGreenBright: [102, 49],
10977
+ bgYellowBright: [103, 49],
10978
+ bgBlueBright: [104, 49],
10979
+ bgMagentaBright: [105, 49],
10980
+ bgCyanBright: [106, 49],
10981
+ bgWhiteBright: [107, 49]
10982
+ }
10983
+ };
10984
+ modifierNames = Object.keys(styles.modifier);
10985
+ foregroundColorNames = Object.keys(styles.color);
10986
+ backgroundColorNames = Object.keys(styles.bgColor);
10987
+ colorNames = [...foregroundColorNames, ...backgroundColorNames];
10988
+ ansiStyles = assembleStyles();
10989
+ ansi_styles_default = ansiStyles;
10842
10990
  }
10843
10991
  });
10844
10992
 
10845
- // src/ui/limit-modal.tsx
10846
- import { Box as Box8, Text as Text8 } from "ink";
10847
- import SelectInput2 from "ink-select-input";
10848
- import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
10849
- function LimitModal({ limit, onDecide }) {
10850
- const theme = useTheme();
10851
- const items = [
10852
- { label: "Continue", value: "continue" },
10853
- { label: "Stop", value: "stop" }
10854
- ];
10855
- return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", borderStyle: "round", borderColor: theme.error, paddingX: 1, children: [
10856
- /* @__PURE__ */ jsxs8(Text8, { color: theme.error, bold: true, children: [
10857
- "Tool-call limit reached (",
10858
- limit,
10859
- ")"
10860
- ] }),
10861
- /* @__PURE__ */ jsxs8(Text8, { dimColor: true, children: [
10862
- "This session has made ",
10863
- limit,
10864
- " tool calls. What would you like to do?"
10865
- ] }),
10866
- /* @__PURE__ */ jsx9(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx9(
10867
- SelectInput2,
10868
- {
10869
- items,
10870
- onSelect: (item) => onDecide(item.value)
10871
- }
10872
- ) })
10873
- ] });
10993
+ // node_modules/chalk/source/vendor/supports-color/index.js
10994
+ import process2 from "process";
10995
+ import os from "os";
10996
+ import tty from "tty";
10997
+ function hasFlag(flag, argv = globalThis.Deno ? globalThis.Deno.args : process2.argv) {
10998
+ const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
10999
+ const position = argv.indexOf(prefix + flag);
11000
+ const terminatorPosition = argv.indexOf("--");
11001
+ return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
10874
11002
  }
10875
- var init_limit_modal = __esm({
10876
- "src/ui/limit-modal.tsx"() {
10877
- "use strict";
10878
- init_theme_context();
10879
- }
10880
- });
10881
-
10882
- // src/util/fuzzy.ts
10883
- function fuzzyMatch(query, text) {
10884
- const queryLower = query.toLowerCase();
10885
- const textLower = text.toLowerCase();
10886
- const matchQuery = (normalizedQuery) => {
10887
- if (normalizedQuery.length === 0) return { matches: true, score: 0 };
10888
- if (normalizedQuery.length > textLower.length) return { matches: false, score: 0 };
10889
- let queryIndex = 0;
10890
- let score = 0;
10891
- let lastMatchIndex = -1;
10892
- let consecutiveMatches = 0;
10893
- for (let i = 0; i < textLower.length && queryIndex < normalizedQuery.length; i++) {
10894
- if (textLower[i] !== normalizedQuery[queryIndex]) continue;
10895
- const isWordBoundary = i === 0 || /[\s\-_./:]/.test(textLower[i - 1]);
10896
- if (lastMatchIndex === i - 1) {
10897
- consecutiveMatches++;
10898
- score -= consecutiveMatches * 5;
10899
- } else {
10900
- consecutiveMatches = 0;
10901
- if (lastMatchIndex >= 0) score += (i - lastMatchIndex - 1) * 2;
10902
- }
10903
- if (isWordBoundary) score -= 10;
10904
- score += i * 0.1;
10905
- lastMatchIndex = i;
10906
- queryIndex++;
11003
+ function envForceColor() {
11004
+ if ("FORCE_COLOR" in env) {
11005
+ if (env.FORCE_COLOR === "true") {
11006
+ return 1;
10907
11007
  }
10908
- if (queryIndex < normalizedQuery.length) return { matches: false, score: 0 };
10909
- if (normalizedQuery === textLower) score -= 100;
10910
- return { matches: true, score };
10911
- };
10912
- const primaryMatch = matchQuery(queryLower);
10913
- if (primaryMatch.matches) return primaryMatch;
10914
- const alphaNumericMatch = queryLower.match(/^(?<letters>[a-z]+)(?<digits>[0-9]+)$/);
10915
- const numericAlphaMatch = queryLower.match(/^(?<digits>[0-9]+)(?<letters>[a-z]+)$/);
10916
- const swappedQuery = alphaNumericMatch ? `${alphaNumericMatch.groups?.digits ?? ""}${alphaNumericMatch.groups?.letters ?? ""}` : numericAlphaMatch ? `${numericAlphaMatch.groups?.letters ?? ""}${numericAlphaMatch.groups?.digits ?? ""}` : "";
10917
- if (!swappedQuery) return primaryMatch;
10918
- const swappedMatch = matchQuery(swappedQuery);
10919
- if (!swappedMatch.matches) return primaryMatch;
10920
- return { matches: true, score: swappedMatch.score + 5 };
10921
- }
10922
- function fuzzyFilter(items, query, getText) {
10923
- const trimmed = query.trim();
10924
- if (trimmed.length === 0) return items;
10925
- const tokens = trimmed.split(/\s+/).filter((t) => t.length > 0);
10926
- if (tokens.length === 0) return items;
10927
- const scored = [];
10928
- for (const item of items) {
10929
- const text = getText(item);
10930
- let total = 0;
10931
- let allMatch = true;
10932
- for (const token of tokens) {
10933
- const m = fuzzyMatch(token, text);
10934
- if (!m.matches) {
10935
- allMatch = false;
10936
- break;
10937
- }
10938
- total += m.score;
11008
+ if (env.FORCE_COLOR === "false") {
11009
+ return 0;
10939
11010
  }
10940
- if (allMatch) scored.push({ item, score: total });
11011
+ return env.FORCE_COLOR.length === 0 ? 1 : Math.min(Number.parseInt(env.FORCE_COLOR, 10), 3);
10941
11012
  }
10942
- scored.sort((a, b) => a.score - b.score);
10943
- return scored.map((s) => s.item);
10944
11013
  }
10945
- var init_fuzzy = __esm({
10946
- "src/util/fuzzy.ts"() {
10947
- "use strict";
11014
+ function translateLevel(level) {
11015
+ if (level === 0) {
11016
+ return false;
10948
11017
  }
10949
- });
10950
-
10951
- // src/ui/resume-picker.tsx
10952
- import { useState as useState3 } from "react";
10953
- import { Box as Box9, Text as Text9, useInput } from "ink";
10954
- import SelectInput3 from "ink-select-input";
10955
- import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
10956
- function ResumePicker({ sessions, onPick }) {
10957
- const theme = useTheme();
10958
- const [page, setPage] = useState3(0);
10959
- const [selectedIndex, setSelectedIndex] = useState3(0);
10960
- const [query, setQuery] = useState3("");
10961
- const filtered = query.trim() ? fuzzyFilter(sessions, query, (s) => `${s.title ?? s.firstPrompt} ${s.id}`) : sessions;
10962
- const totalPages = Math.max(1, Math.ceil(filtered.length / PAGE_SIZE));
10963
- const safePage = Math.min(page, totalPages - 1);
10964
- const start = safePage * PAGE_SIZE;
10965
- const end = Math.min(start + PAGE_SIZE, filtered.length);
10966
- const pageSessions = filtered.slice(start, end);
10967
- useInput((input, key) => {
10968
- if (key.leftArrow && safePage > 0) {
10969
- setPage((p) => p - 1);
10970
- setSelectedIndex(0);
10971
- return;
11018
+ return {
11019
+ level,
11020
+ hasBasic: true,
11021
+ has256: level >= 2,
11022
+ has16m: level >= 3
11023
+ };
11024
+ }
11025
+ function _supportsColor(haveStream, { streamIsTTY, sniffFlags = true } = {}) {
11026
+ const noFlagForceColor = envForceColor();
11027
+ if (noFlagForceColor !== void 0) {
11028
+ flagForceColor = noFlagForceColor;
11029
+ }
11030
+ const forceColor = sniffFlags ? flagForceColor : noFlagForceColor;
11031
+ if (forceColor === 0) {
11032
+ return 0;
11033
+ }
11034
+ if (sniffFlags) {
11035
+ if (hasFlag("color=16m") || hasFlag("color=full") || hasFlag("color=truecolor")) {
11036
+ return 3;
10972
11037
  }
10973
- if (key.rightArrow && safePage < totalPages - 1) {
10974
- setPage((p) => p + 1);
10975
- setSelectedIndex(0);
10976
- return;
11038
+ if (hasFlag("color=256")) {
11039
+ return 2;
10977
11040
  }
10978
- if (key.backspace || key.delete) {
10979
- setQuery((q) => q.slice(0, -1));
10980
- setPage(0);
10981
- setSelectedIndex(0);
10982
- return;
11041
+ }
11042
+ if ("TF_BUILD" in env && "AGENT_NAME" in env) {
11043
+ return 1;
11044
+ }
11045
+ if (haveStream && !streamIsTTY && forceColor === void 0) {
11046
+ return 0;
11047
+ }
11048
+ const min = forceColor || 0;
11049
+ if (env.TERM === "dumb") {
11050
+ return min;
11051
+ }
11052
+ if (process2.platform === "win32") {
11053
+ const osRelease = os.release().split(".");
11054
+ if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
11055
+ return Number(osRelease[2]) >= 14931 ? 3 : 2;
10983
11056
  }
10984
- if (input.length === 1 && !key.ctrl && !key.meta && !key.return && !key.escape) {
10985
- setQuery((q) => q + input);
10986
- setPage(0);
10987
- setSelectedIndex(0);
10988
- return;
11057
+ return 1;
11058
+ }
11059
+ if ("CI" in env) {
11060
+ if (["GITHUB_ACTIONS", "GITEA_ACTIONS", "CIRCLECI"].some((key) => key in env)) {
11061
+ return 3;
10989
11062
  }
10990
- if (input === "q" || key.escape) {
10991
- onPick(null);
10992
- return;
11063
+ if (["TRAVIS", "APPVEYOR", "GITLAB_CI", "BUILDKITE", "DRONE"].some((sign) => sign in env) || env.CI_NAME === "codeship") {
11064
+ return 1;
10993
11065
  }
10994
- });
10995
- if (sessions.length === 0) {
10996
- return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
10997
- /* @__PURE__ */ jsx10(Text9, { color: theme.accent, bold: true, children: "Resume a session" }),
10998
- /* @__PURE__ */ jsx10(Text9, { color: theme.info.color, children: "No saved sessions yet. Press Enter to dismiss." }),
10999
- /* @__PURE__ */ jsx10(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx10(
11000
- SelectInput3,
11001
- {
11002
- items: [{ label: "(back)", value: "__cancel__" }],
11003
- onSelect: () => onPick(null)
11004
- }
11005
- ) })
11006
- ] });
11066
+ return min;
11007
11067
  }
11008
- const items = pageSessions.map((s) => ({
11009
- label: `${formatDate(s.updatedAt)} \xB7 ${s.messageCount} msgs \xB7 ${s.title ?? s.firstPrompt}`,
11010
- value: s.id
11011
- }));
11012
- return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
11013
- /* @__PURE__ */ jsx10(Text9, { color: theme.accent, bold: true, children: "Resume a session" }),
11014
- /* @__PURE__ */ jsxs9(Text9, { color: theme.info.color, children: [
11015
- query ? `Search: ${query}\u258C` : "Type to search\u2026",
11016
- " \xB7 Page ",
11017
- safePage + 1,
11018
- " of ",
11019
- totalPages,
11020
- " (",
11021
- filtered.length,
11022
- " total)"
11023
- ] }),
11024
- /* @__PURE__ */ jsx10(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx10(
11025
- SelectInput3,
11026
- {
11027
- items,
11028
- initialIndex: selectedIndex,
11029
- onHighlight: (item) => {
11030
- const idx = items.findIndex((i) => i.value === item.value);
11031
- if (idx >= 0) setSelectedIndex(idx);
11032
- },
11033
- onSelect: (item) => {
11034
- const picked = sessions.find((s) => s.id === item.value) ?? null;
11035
- onPick(picked);
11036
- }
11037
- }
11038
- ) }),
11039
- /* @__PURE__ */ jsx10(Box9, { marginTop: 1, children: /* @__PURE__ */ jsxs9(Text9, { color: theme.info.color, children: [
11040
- safePage > 0 ? "\u2190 prev " : "",
11041
- safePage < totalPages - 1 ? "\u2192 next " : "",
11042
- "q: cancel"
11043
- ] }) })
11044
- ] });
11045
- }
11046
- function formatDate(iso) {
11047
- try {
11048
- const d = new Date(iso);
11049
- return d.toLocaleString(void 0, {
11050
- month: "short",
11051
- day: "numeric",
11052
- hour: "2-digit",
11053
- minute: "2-digit"
11054
- });
11055
- } catch {
11056
- return iso;
11068
+ if ("TEAMCITY_VERSION" in env) {
11069
+ return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
11057
11070
  }
11058
- }
11059
- var PAGE_SIZE;
11060
- var init_resume_picker = __esm({
11061
- "src/ui/resume-picker.tsx"() {
11062
- "use strict";
11063
- init_fuzzy();
11064
- init_theme_context();
11065
- PAGE_SIZE = 5;
11071
+ if (env.COLORTERM === "truecolor") {
11072
+ return 3;
11066
11073
  }
11067
- });
11068
-
11069
- // src/ui/checkpoint-picker.tsx
11070
- import { useState as useState4 } from "react";
11071
- import { Box as Box10, Text as Text10, useInput as useInput2 } from "ink";
11072
- import SelectInput4 from "ink-select-input";
11073
- import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
11074
- function CheckpointPicker({ session, checkpoints, onPick }) {
11075
- const theme = useTheme();
11076
- const [selectedIndex, setSelectedIndex] = useState4(0);
11077
- useInput2((input, key) => {
11078
- if (input === "q" || key.escape) {
11079
- onPick(null);
11080
- return;
11081
- }
11082
- });
11083
- const items = [
11084
- {
11085
- label: `Resume from beginning (${session.messageCount} msgs)`,
11086
- value: "__start__"
11087
- },
11088
- ...checkpoints.map((cp) => ({
11089
- label: `Resume from: "${cp.label}" \u2014 turn ${cp.turnIndex} \xB7 ${formatDate2(cp.timestamp)}`,
11090
- value: cp.id
11091
- }))
11092
- ];
11093
- return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
11094
- /* @__PURE__ */ jsx11(Text10, { color: theme.accent, bold: true, children: session.firstPrompt.slice(0, 50) }),
11095
- /* @__PURE__ */ jsxs10(Text10, { color: theme.info.color, children: [
11096
- session.messageCount,
11097
- " turns \xB7 ",
11098
- checkpoints.length,
11099
- " checkpoint",
11100
- checkpoints.length === 1 ? "" : "s"
11101
- ] }),
11102
- /* @__PURE__ */ jsx11(Box10, { marginTop: 1, children: /* @__PURE__ */ jsx11(
11103
- SelectInput4,
11104
- {
11105
- items,
11106
- initialIndex: selectedIndex,
11107
- onHighlight: (item) => {
11108
- const idx = items.findIndex((i) => i.value === item.value);
11109
- if (idx >= 0) setSelectedIndex(idx);
11110
- },
11111
- onSelect: (item) => {
11112
- if (item.value === "__start__") {
11113
- onPick("__start__");
11114
- } else {
11115
- onPick(item.value);
11116
- }
11117
- }
11074
+ if (env.TERM === "xterm-kitty") {
11075
+ return 3;
11076
+ }
11077
+ if (env.TERM === "xterm-ghostty") {
11078
+ return 3;
11079
+ }
11080
+ if (env.TERM === "wezterm") {
11081
+ return 3;
11082
+ }
11083
+ if ("TERM_PROGRAM" in env) {
11084
+ const version = Number.parseInt((env.TERM_PROGRAM_VERSION || "").split(".")[0], 10);
11085
+ switch (env.TERM_PROGRAM) {
11086
+ case "iTerm.app": {
11087
+ return version >= 3 ? 3 : 2;
11118
11088
  }
11119
- ) }),
11120
- /* @__PURE__ */ jsx11(Box10, { marginTop: 1, children: /* @__PURE__ */ jsx11(Text10, { color: theme.info.color, children: "q: cancel / go back" }) })
11121
- ] });
11122
- }
11123
- function formatDate2(iso) {
11124
- try {
11125
- const d = new Date(iso);
11126
- return d.toLocaleString(void 0, {
11127
- month: "short",
11128
- day: "numeric",
11129
- hour: "2-digit",
11130
- minute: "2-digit"
11131
- });
11132
- } catch {
11133
- return iso;
11089
+ case "Apple_Terminal": {
11090
+ return 2;
11091
+ }
11092
+ }
11093
+ }
11094
+ if (/-256(color)?$/i.test(env.TERM)) {
11095
+ return 2;
11096
+ }
11097
+ if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
11098
+ return 1;
11134
11099
  }
11100
+ if ("COLORTERM" in env) {
11101
+ return 1;
11102
+ }
11103
+ return min;
11135
11104
  }
11136
- var init_checkpoint_picker = __esm({
11137
- "src/ui/checkpoint-picker.tsx"() {
11105
+ function createSupportsColor(stream, options = {}) {
11106
+ const level = _supportsColor(stream, {
11107
+ streamIsTTY: stream && stream.isTTY,
11108
+ ...options
11109
+ });
11110
+ return translateLevel(level);
11111
+ }
11112
+ var env, flagForceColor, supportsColor, supports_color_default;
11113
+ var init_supports_color = __esm({
11114
+ "node_modules/chalk/source/vendor/supports-color/index.js"() {
11138
11115
  "use strict";
11139
- init_theme_context();
11116
+ ({ env } = process2);
11117
+ if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false") || hasFlag("color=never")) {
11118
+ flagForceColor = 0;
11119
+ } else if (hasFlag("color") || hasFlag("colors") || hasFlag("color=true") || hasFlag("color=always")) {
11120
+ flagForceColor = 1;
11121
+ }
11122
+ supportsColor = {
11123
+ stdout: createSupportsColor({ isTTY: tty.isatty(1) }),
11124
+ stderr: createSupportsColor({ isTTY: tty.isatty(2) })
11125
+ };
11126
+ supports_color_default = supportsColor;
11140
11127
  }
11141
11128
  });
11142
11129
 
11143
- // src/ui/task-list.tsx
11144
- import { useEffect as useEffect3, useRef, useState as useState5 } from "react";
11145
- import { Box as Box11, Text as Text11 } from "ink";
11146
- import Spinner4 from "ink-spinner";
11147
- import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
11148
- function TaskList({ tasks, startedAt, tokensDelta }) {
11149
- const theme = useTheme();
11150
- const [now2, setNow] = useState5(Date.now());
11151
- const [celebrating, setCelebrating] = useState5(false);
11152
- const tasksRef = useRef(tasks);
11153
- const prevAllDoneRef = useRef(false);
11154
- tasksRef.current = tasks;
11155
- useEffect3(() => {
11156
- if (startedAt === null) return;
11157
- const id = setInterval(() => {
11158
- setNow(Date.now());
11159
- const current = tasksRef.current;
11160
- if (current.length > 0 && current.every((t) => t.status === "completed")) {
11161
- clearInterval(id);
11162
- }
11163
- }, 1e3);
11164
- return () => clearInterval(id);
11165
- }, [startedAt]);
11166
- useEffect3(() => {
11167
- const allDone2 = tasks.length > 0 && tasks.every((t) => t.status === "completed");
11168
- if (allDone2 && !prevAllDoneRef.current) {
11169
- setCelebrating(true);
11170
- const id = setTimeout(() => setCelebrating(false), 1500);
11171
- return () => clearTimeout(id);
11172
- }
11173
- prevAllDoneRef.current = allDone2;
11174
- }, [tasks]);
11175
- if (tasks.length === 0) return null;
11176
- const active = tasks.find((t) => t.status === "in_progress");
11177
- const done = tasks.filter((t) => t.status === "completed").length;
11178
- const total = tasks.length;
11179
- const allDone = done === total;
11180
- const header = active ? active.title : allDone ? `${total} tasks done` : `${done}/${total}`;
11181
- const elapsed = startedAt ? formatElapsed3(now2 - startedAt) : null;
11182
- const headerStats = [elapsed, tokensDelta > 0 ? `\u2191 ${formatTokens3(tokensDelta)} tokens` : null].filter(Boolean).join(" \xB7 ");
11183
- const visibleTasks = tasks.slice(0, MAX_VISIBLE);
11184
- const hiddenPending = Math.max(0, tasks.length - visibleTasks.length);
11185
- return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", marginBottom: 1, children: [
11186
- /* @__PURE__ */ jsxs11(Box11, { children: [
11187
- /* @__PURE__ */ jsx12(Text11, { color: celebrating ? theme.palette.success : allDone ? "green" : theme.accent, bold: true, children: celebrating ? `\u2728 ${header}` : header }),
11188
- headerStats && /* @__PURE__ */ jsxs11(Text11, { color: theme.info.color, children: [
11189
- " ",
11190
- "(",
11191
- headerStats,
11192
- ")"
11193
- ] })
11194
- ] }),
11195
- visibleTasks.map((t) => /* @__PURE__ */ jsx12(TaskRow, { task: t }, t.id)),
11196
- hiddenPending > 0 && /* @__PURE__ */ jsxs11(Text11, { color: theme.info.color, children: [
11197
- " ",
11198
- "\u2026 +",
11199
- hiddenPending,
11200
- " more"
11201
- ] })
11202
- ] });
11203
- }
11204
- function TaskRow({ task }) {
11205
- const theme = useTheme();
11206
- if (task.status === "completed") {
11207
- return /* @__PURE__ */ jsxs11(Text11, { color: theme.info.color, children: [
11208
- " ",
11209
- "\u2713 ",
11210
- /* @__PURE__ */ jsx12(Text11, { strikethrough: true, children: task.title })
11211
- ] });
11212
- }
11213
- if (task.status === "in_progress") {
11214
- return /* @__PURE__ */ jsxs11(Text11, { color: theme.accent, bold: true, children: [
11215
- " ",
11216
- /* @__PURE__ */ jsx12(Spinner4, { type: "line" }),
11217
- " ",
11218
- task.title
11219
- ] });
11130
+ // node_modules/chalk/source/utilities.js
11131
+ function stringReplaceAll(string, substring, replacer) {
11132
+ let index = string.indexOf(substring);
11133
+ if (index === -1) {
11134
+ return string;
11220
11135
  }
11221
- return /* @__PURE__ */ jsxs11(Text11, { color: theme.info.color, children: [
11222
- " ",
11223
- "\u2610 ",
11224
- task.title
11225
- ] });
11226
- }
11227
- function formatElapsed3(ms) {
11228
- const total = Math.floor(ms / 1e3);
11229
- const m = Math.floor(total / 60);
11230
- const s = total % 60;
11231
- if (m === 0) return `${s}s`;
11232
- return `${m}m ${s}s`;
11136
+ const substringLength = substring.length;
11137
+ let endIndex = 0;
11138
+ let returnValue = "";
11139
+ do {
11140
+ returnValue += string.slice(endIndex, index) + substring + replacer;
11141
+ endIndex = index + substringLength;
11142
+ index = string.indexOf(substring, endIndex);
11143
+ } while (index !== -1);
11144
+ returnValue += string.slice(endIndex);
11145
+ return returnValue;
11233
11146
  }
11234
- function formatTokens3(n) {
11235
- if (n < 1e3) return String(n);
11236
- return `${(n / 1e3).toFixed(1)}k`;
11147
+ function stringEncaseCRLFWithFirstIndex(string, prefix, postfix, index) {
11148
+ let endIndex = 0;
11149
+ let returnValue = "";
11150
+ do {
11151
+ const gotCR = string[index - 1] === "\r";
11152
+ returnValue += string.slice(endIndex, gotCR ? index - 1 : index) + prefix + (gotCR ? "\r\n" : "\n") + postfix;
11153
+ endIndex = index + 1;
11154
+ index = string.indexOf("\n", endIndex);
11155
+ } while (index !== -1);
11156
+ returnValue += string.slice(endIndex);
11157
+ return returnValue;
11237
11158
  }
11238
- var MAX_VISIBLE;
11239
- var init_task_list = __esm({
11240
- "src/ui/task-list.tsx"() {
11159
+ var init_utilities = __esm({
11160
+ "node_modules/chalk/source/utilities.js"() {
11241
11161
  "use strict";
11242
- init_theme_context();
11243
- MAX_VISIBLE = 6;
11244
11162
  }
11245
11163
  });
11246
11164
 
11247
- // node_modules/chalk/source/vendor/ansi-styles/index.js
11248
- function assembleStyles() {
11249
- const codes = /* @__PURE__ */ new Map();
11250
- for (const [groupName, group] of Object.entries(styles)) {
11251
- for (const [styleName, style] of Object.entries(group)) {
11252
- styles[styleName] = {
11253
- open: `\x1B[${style[0]}m`,
11254
- close: `\x1B[${style[1]}m`
11165
+ // node_modules/chalk/source/index.js
11166
+ function createChalk(options) {
11167
+ return chalkFactory(options);
11168
+ }
11169
+ var stdoutColor, stderrColor, GENERATOR, STYLER, IS_EMPTY, levelMapping, styles2, applyOptions, chalkFactory, getModelAnsi, usedModels, proto, createStyler, createBuilder, applyStyle, chalk, chalkStderr, source_default;
11170
+ var init_source = __esm({
11171
+ "node_modules/chalk/source/index.js"() {
11172
+ "use strict";
11173
+ init_ansi_styles();
11174
+ init_supports_color();
11175
+ init_utilities();
11176
+ ({ stdout: stdoutColor, stderr: stderrColor } = supports_color_default);
11177
+ GENERATOR = /* @__PURE__ */ Symbol("GENERATOR");
11178
+ STYLER = /* @__PURE__ */ Symbol("STYLER");
11179
+ IS_EMPTY = /* @__PURE__ */ Symbol("IS_EMPTY");
11180
+ levelMapping = [
11181
+ "ansi",
11182
+ "ansi",
11183
+ "ansi256",
11184
+ "ansi16m"
11185
+ ];
11186
+ styles2 = /* @__PURE__ */ Object.create(null);
11187
+ applyOptions = (object, options = {}) => {
11188
+ if (options.level && !(Number.isInteger(options.level) && options.level >= 0 && options.level <= 3)) {
11189
+ throw new Error("The `level` option should be an integer from 0 to 3");
11190
+ }
11191
+ const colorLevel = stdoutColor ? stdoutColor.level : 0;
11192
+ object.level = options.level === void 0 ? colorLevel : options.level;
11193
+ };
11194
+ chalkFactory = (options) => {
11195
+ const chalk2 = (...strings) => strings.join(" ");
11196
+ applyOptions(chalk2, options);
11197
+ Object.setPrototypeOf(chalk2, createChalk.prototype);
11198
+ return chalk2;
11199
+ };
11200
+ Object.setPrototypeOf(createChalk.prototype, Function.prototype);
11201
+ for (const [styleName, style] of Object.entries(ansi_styles_default)) {
11202
+ styles2[styleName] = {
11203
+ get() {
11204
+ const builder = createBuilder(this, createStyler(style.open, style.close, this[STYLER]), this[IS_EMPTY]);
11205
+ Object.defineProperty(this, styleName, { value: builder });
11206
+ return builder;
11207
+ }
11255
11208
  };
11256
- group[styleName] = styles[styleName];
11257
- codes.set(style[0], style[1]);
11258
11209
  }
11259
- Object.defineProperty(styles, groupName, {
11260
- value: group,
11261
- enumerable: false
11262
- });
11263
- }
11264
- Object.defineProperty(styles, "codes", {
11265
- value: codes,
11266
- enumerable: false
11267
- });
11268
- styles.color.close = "\x1B[39m";
11269
- styles.bgColor.close = "\x1B[49m";
11270
- styles.color.ansi = wrapAnsi16();
11271
- styles.color.ansi256 = wrapAnsi256();
11272
- styles.color.ansi16m = wrapAnsi16m();
11273
- styles.bgColor.ansi = wrapAnsi16(ANSI_BACKGROUND_OFFSET);
11274
- styles.bgColor.ansi256 = wrapAnsi256(ANSI_BACKGROUND_OFFSET);
11275
- styles.bgColor.ansi16m = wrapAnsi16m(ANSI_BACKGROUND_OFFSET);
11276
- Object.defineProperties(styles, {
11277
- rgbToAnsi256: {
11278
- value(red, green, blue) {
11279
- if (red === green && green === blue) {
11280
- if (red < 8) {
11281
- return 16;
11282
- }
11283
- if (red > 248) {
11284
- return 231;
11285
- }
11286
- return Math.round((red - 8) / 247 * 24) + 232;
11210
+ styles2.visible = {
11211
+ get() {
11212
+ const builder = createBuilder(this, this[STYLER], true);
11213
+ Object.defineProperty(this, "visible", { value: builder });
11214
+ return builder;
11215
+ }
11216
+ };
11217
+ getModelAnsi = (model, level, type, ...arguments_) => {
11218
+ if (model === "rgb") {
11219
+ if (level === "ansi16m") {
11220
+ return ansi_styles_default[type].ansi16m(...arguments_);
11287
11221
  }
11288
- return 16 + 36 * Math.round(red / 255 * 5) + 6 * Math.round(green / 255 * 5) + Math.round(blue / 255 * 5);
11289
- },
11290
- enumerable: false
11291
- },
11292
- hexToRgb: {
11293
- value(hex) {
11294
- const matches = /[a-f\d]{6}|[a-f\d]{3}/i.exec(hex.toString(16));
11295
- if (!matches) {
11296
- return [0, 0, 0];
11222
+ if (level === "ansi256") {
11223
+ return ansi_styles_default[type].ansi256(ansi_styles_default.rgbToAnsi256(...arguments_));
11297
11224
  }
11298
- let [colorString] = matches;
11299
- if (colorString.length === 3) {
11300
- colorString = [...colorString].map((character) => character + character).join("");
11225
+ return ansi_styles_default[type].ansi(ansi_styles_default.rgbToAnsi(...arguments_));
11226
+ }
11227
+ if (model === "hex") {
11228
+ return getModelAnsi("rgb", level, type, ...ansi_styles_default.hexToRgb(...arguments_));
11229
+ }
11230
+ return ansi_styles_default[type][model](...arguments_);
11231
+ };
11232
+ usedModels = ["rgb", "hex", "ansi256"];
11233
+ for (const model of usedModels) {
11234
+ styles2[model] = {
11235
+ get() {
11236
+ const { level } = this;
11237
+ return function(...arguments_) {
11238
+ const styler = createStyler(getModelAnsi(model, levelMapping[level], "color", ...arguments_), ansi_styles_default.color.close, this[STYLER]);
11239
+ return createBuilder(this, styler, this[IS_EMPTY]);
11240
+ };
11301
11241
  }
11302
- const integer = Number.parseInt(colorString, 16);
11303
- return [
11304
- /* eslint-disable no-bitwise */
11305
- integer >> 16 & 255,
11306
- integer >> 8 & 255,
11307
- integer & 255
11308
- /* eslint-enable no-bitwise */
11309
- ];
11310
- },
11311
- enumerable: false
11312
- },
11313
- hexToAnsi256: {
11314
- value: (hex) => styles.rgbToAnsi256(...styles.hexToRgb(hex)),
11315
- enumerable: false
11316
- },
11317
- ansi256ToAnsi: {
11318
- value(code) {
11319
- if (code < 8) {
11320
- return 30 + code;
11242
+ };
11243
+ const bgModel = "bg" + model[0].toUpperCase() + model.slice(1);
11244
+ styles2[bgModel] = {
11245
+ get() {
11246
+ const { level } = this;
11247
+ return function(...arguments_) {
11248
+ const styler = createStyler(getModelAnsi(model, levelMapping[level], "bgColor", ...arguments_), ansi_styles_default.bgColor.close, this[STYLER]);
11249
+ return createBuilder(this, styler, this[IS_EMPTY]);
11250
+ };
11321
11251
  }
11322
- if (code < 16) {
11323
- return 90 + (code - 8);
11252
+ };
11253
+ }
11254
+ proto = Object.defineProperties(() => {
11255
+ }, {
11256
+ ...styles2,
11257
+ level: {
11258
+ enumerable: true,
11259
+ get() {
11260
+ return this[GENERATOR].level;
11261
+ },
11262
+ set(level) {
11263
+ this[GENERATOR].level = level;
11324
11264
  }
11325
- let red;
11326
- let green;
11327
- let blue;
11328
- if (code >= 232) {
11329
- red = ((code - 232) * 10 + 8) / 255;
11330
- green = red;
11331
- blue = red;
11332
- } else {
11333
- code -= 16;
11334
- const remainder = code % 36;
11335
- red = Math.floor(code / 36) / 5;
11336
- green = Math.floor(remainder / 6) / 5;
11337
- blue = remainder % 6 / 5;
11265
+ }
11266
+ });
11267
+ createStyler = (open3, close, parent) => {
11268
+ let openAll;
11269
+ let closeAll;
11270
+ if (parent === void 0) {
11271
+ openAll = open3;
11272
+ closeAll = close;
11273
+ } else {
11274
+ openAll = parent.openAll + open3;
11275
+ closeAll = close + parent.closeAll;
11276
+ }
11277
+ return {
11278
+ open: open3,
11279
+ close,
11280
+ openAll,
11281
+ closeAll,
11282
+ parent
11283
+ };
11284
+ };
11285
+ createBuilder = (self, _styler, _isEmpty) => {
11286
+ const builder = (...arguments_) => applyStyle(builder, arguments_.length === 1 ? "" + arguments_[0] : arguments_.join(" "));
11287
+ Object.setPrototypeOf(builder, proto);
11288
+ builder[GENERATOR] = self;
11289
+ builder[STYLER] = _styler;
11290
+ builder[IS_EMPTY] = _isEmpty;
11291
+ return builder;
11292
+ };
11293
+ applyStyle = (self, string) => {
11294
+ if (self.level <= 0 || !string) {
11295
+ return self[IS_EMPTY] ? "" : string;
11296
+ }
11297
+ let styler = self[STYLER];
11298
+ if (styler === void 0) {
11299
+ return string;
11300
+ }
11301
+ const { openAll, closeAll } = styler;
11302
+ if (string.includes("\x1B")) {
11303
+ while (styler !== void 0) {
11304
+ string = stringReplaceAll(string, styler.close, styler.open);
11305
+ styler = styler.parent;
11338
11306
  }
11339
- const value = Math.max(red, green, blue) * 2;
11340
- if (value === 0) {
11341
- return 30;
11307
+ }
11308
+ const lfIndex = string.indexOf("\n");
11309
+ if (lfIndex !== -1) {
11310
+ string = stringEncaseCRLFWithFirstIndex(string, closeAll, openAll, lfIndex);
11311
+ }
11312
+ return openAll + string + closeAll;
11313
+ };
11314
+ Object.defineProperties(createChalk.prototype, styles2);
11315
+ chalk = createChalk();
11316
+ chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
11317
+ source_default = chalk;
11318
+ }
11319
+ });
11320
+
11321
+ // src/ui/text-input.tsx
11322
+ import { useState as useState3, useEffect as useEffect3, useRef } from "react";
11323
+ import { Text as Text7, useInput } from "ink";
11324
+ import { jsx as jsx8 } from "react/jsx-runtime";
11325
+ function shouldTreatAsPaste(input) {
11326
+ if (input.length >= PASTE_CHAR_THRESHOLD) return true;
11327
+ const newlines = (input.match(/\n/g) ?? []).length;
11328
+ return newlines >= PASTE_NEWLINE_THRESHOLD;
11329
+ }
11330
+ function makePastePreview(input, lines, id) {
11331
+ const firstLine2 = input.split("\n")[0] ?? "";
11332
+ const cleaned = firstLine2.trim().replace(/\s+/g, " ");
11333
+ const preview = cleaned.length > 20 ? cleaned.slice(0, 20) + "\u2026" : cleaned;
11334
+ const text = preview || "(empty)";
11335
+ return `\u2997"${text}" (${lines} line${lines === 1 ? "" : "s"}) #${id}\u2998`;
11336
+ }
11337
+ function countLines(s) {
11338
+ return s.split("\n").length;
11339
+ }
11340
+ function findWordBoundaryForward(text, pos) {
11341
+ while (pos < text.length && /\w/.test(text[pos])) pos++;
11342
+ while (pos < text.length && !/\w/.test(text[pos])) pos++;
11343
+ return pos;
11344
+ }
11345
+ function findWordBoundaryBackward(text, pos) {
11346
+ while (pos > 0 && !/\w/.test(text[pos - 1])) pos--;
11347
+ while (pos > 0 && /\w/.test(text[pos - 1])) pos--;
11348
+ return pos;
11349
+ }
11350
+ function CustomTextInput({
11351
+ value,
11352
+ onChange,
11353
+ onSubmit,
11354
+ onHistoryUp,
11355
+ onHistoryDown,
11356
+ onClearQueueItem,
11357
+ focus = true,
11358
+ mask,
11359
+ enablePaste = false,
11360
+ cursorOffset: controlledCursor,
11361
+ onCursorChange,
11362
+ pickerActive = false,
11363
+ onPickerUp,
11364
+ onPickerDown,
11365
+ onPickerSelect,
11366
+ onPickerCancel,
11367
+ onCancel
11368
+ }) {
11369
+ const [internalCursor, setInternalCursor] = useState3(value.length);
11370
+ const cursorOffset = controlledCursor ?? internalCursor;
11371
+ const setCursorOffset = (offset) => {
11372
+ setInternalCursor(offset);
11373
+ onCursorChange?.(offset);
11374
+ };
11375
+ const pastesRef = useRef(/* @__PURE__ */ new Map());
11376
+ const pasteCounterRef = useRef(0);
11377
+ useEffect3(() => {
11378
+ if (!focus) return;
11379
+ const next = cursorOffset > value.length ? value.length : cursorOffset;
11380
+ if (next !== cursorOffset) {
11381
+ setCursorOffset(next);
11382
+ }
11383
+ }, [value, focus, cursorOffset]);
11384
+ useInput(
11385
+ (input, key) => {
11386
+ if (!focus) return;
11387
+ if (key.ctrl && input === "c") return;
11388
+ if (key.ctrl && input === "r") return;
11389
+ if (key.ctrl && input === "o") return;
11390
+ if (key.tab) return;
11391
+ if (pickerActive) {
11392
+ if (key.upArrow) {
11393
+ onPickerUp?.();
11394
+ return;
11342
11395
  }
11343
- let result = 30 + (Math.round(blue) << 2 | Math.round(green) << 1 | Math.round(red));
11344
- if (value === 2) {
11345
- result += 60;
11396
+ if (key.downArrow) {
11397
+ onPickerDown?.();
11398
+ return;
11346
11399
  }
11347
- return result;
11348
- },
11349
- enumerable: false
11350
- },
11351
- rgbToAnsi: {
11352
- value: (red, green, blue) => styles.ansi256ToAnsi(styles.rgbToAnsi256(red, green, blue)),
11353
- enumerable: false
11400
+ if (key.return) {
11401
+ onPickerSelect?.();
11402
+ return;
11403
+ }
11404
+ if (key.escape) {
11405
+ onPickerCancel?.();
11406
+ return;
11407
+ }
11408
+ }
11409
+ if (key.escape) {
11410
+ onCancel?.();
11411
+ setCursorOffset(0);
11412
+ return;
11413
+ }
11414
+ if (key.return) {
11415
+ let full = value;
11416
+ let hasPastes = false;
11417
+ if (enablePaste && pastesRef.current.size > 0) {
11418
+ for (const [placeholder, fullText] of pastesRef.current) {
11419
+ if (full.includes(placeholder)) {
11420
+ full = full.split(placeholder).join(fullText);
11421
+ hasPastes = true;
11422
+ }
11423
+ }
11424
+ }
11425
+ onSubmit(full, hasPastes ? value : void 0);
11426
+ pastesRef.current.clear();
11427
+ setCursorOffset(0);
11428
+ return;
11429
+ }
11430
+ if (key.upArrow) {
11431
+ onHistoryUp?.();
11432
+ return;
11433
+ }
11434
+ if (key.downArrow) {
11435
+ onHistoryDown?.();
11436
+ return;
11437
+ }
11438
+ let nextCursor = cursorOffset;
11439
+ let nextValue = value;
11440
+ let didDelete = false;
11441
+ if (key.leftArrow) {
11442
+ if (key.meta) {
11443
+ nextCursor = findWordBoundaryBackward(value, cursorOffset);
11444
+ } else {
11445
+ nextCursor = cursorOffset - 1;
11446
+ }
11447
+ } else if (key.rightArrow) {
11448
+ if (key.meta) {
11449
+ nextCursor = findWordBoundaryForward(value, cursorOffset);
11450
+ } else {
11451
+ nextCursor = cursorOffset + 1;
11452
+ }
11453
+ } else if (key.meta && input === "b") {
11454
+ nextCursor = findWordBoundaryBackward(value, cursorOffset);
11455
+ } else if (key.meta && input === "f") {
11456
+ nextCursor = findWordBoundaryForward(value, cursorOffset);
11457
+ } else if (key.meta && input === "d") {
11458
+ didDelete = true;
11459
+ const boundary = findWordBoundaryForward(value, cursorOffset);
11460
+ nextValue = value.slice(0, cursorOffset) + value.slice(boundary);
11461
+ } else if (key.home || key.ctrl && input === "a") {
11462
+ nextCursor = 0;
11463
+ } else if (key.end || key.ctrl && input === "e") {
11464
+ nextCursor = value.length;
11465
+ } else if (key.backspace) {
11466
+ didDelete = true;
11467
+ const tokenBoundary = enablePaste ? findPasteTokenEndingAt(value, cursorOffset, pastesRef.current) : -1;
11468
+ if (tokenBoundary >= 0) {
11469
+ const token = value.slice(tokenBoundary, cursorOffset);
11470
+ pastesRef.current.delete(token);
11471
+ nextValue = value.slice(0, tokenBoundary) + value.slice(cursorOffset);
11472
+ nextCursor = tokenBoundary;
11473
+ } else if (key.meta || key.ctrl && input === "w") {
11474
+ const boundary = findWordBoundaryBackward(value, cursorOffset);
11475
+ nextValue = value.slice(0, boundary) + value.slice(cursorOffset);
11476
+ nextCursor = boundary;
11477
+ } else if (key.ctrl) {
11478
+ const boundary = findWordBoundaryBackward(value, cursorOffset);
11479
+ nextValue = value.slice(0, boundary) + value.slice(cursorOffset);
11480
+ nextCursor = boundary;
11481
+ } else {
11482
+ if (cursorOffset > 0) {
11483
+ nextValue = value.slice(0, cursorOffset - 1) + value.slice(cursorOffset);
11484
+ nextCursor = cursorOffset - 1;
11485
+ }
11486
+ }
11487
+ } else if (key.delete) {
11488
+ didDelete = true;
11489
+ if (key.meta || key.ctrl) {
11490
+ const boundary = findWordBoundaryForward(value, cursorOffset);
11491
+ nextValue = value.slice(0, cursorOffset) + value.slice(boundary);
11492
+ } else {
11493
+ nextValue = value.slice(0, cursorOffset) + value.slice(cursorOffset + 1);
11494
+ }
11495
+ } else if (key.ctrl && input === "w") {
11496
+ didDelete = true;
11497
+ const boundary = findWordBoundaryBackward(value, cursorOffset);
11498
+ nextValue = value.slice(0, boundary) + value.slice(cursorOffset);
11499
+ nextCursor = boundary;
11500
+ } else if (key.ctrl && input === "u") {
11501
+ didDelete = true;
11502
+ nextValue = value.slice(cursorOffset);
11503
+ nextCursor = 0;
11504
+ } else if (key.ctrl && input === "k") {
11505
+ didDelete = true;
11506
+ nextValue = value.slice(0, cursorOffset);
11507
+ } else if (input.length > 0 && !key.ctrl && !key.meta) {
11508
+ let toInsert = input;
11509
+ if (enablePaste && shouldTreatAsPaste(input)) {
11510
+ const lines = countLines(input);
11511
+ const id = ++pasteCounterRef.current;
11512
+ const placeholder = makePastePreview(input, lines, id);
11513
+ pastesRef.current.set(placeholder, input);
11514
+ toInsert = placeholder;
11515
+ }
11516
+ nextValue = value.slice(0, cursorOffset) + toInsert + value.slice(cursorOffset);
11517
+ nextCursor = cursorOffset + toInsert.length;
11518
+ }
11519
+ if (nextCursor < 0) nextCursor = 0;
11520
+ if (nextCursor > nextValue.length) nextCursor = nextValue.length;
11521
+ if (didDelete && nextValue === "" && value !== "") {
11522
+ onClearQueueItem?.(value);
11523
+ }
11524
+ if (nextCursor !== cursorOffset) {
11525
+ setCursorOffset(nextCursor);
11526
+ }
11527
+ if (nextValue !== value) {
11528
+ onChange(nextValue);
11529
+ }
11354
11530
  },
11355
- hexToAnsi: {
11356
- value: (hex) => styles.ansi256ToAnsi(styles.hexToAnsi256(hex)),
11357
- enumerable: false
11358
- }
11359
- });
11360
- return styles;
11531
+ { isActive: focus }
11532
+ );
11533
+ const displayValue = mask ? mask.repeat(value.length) : value;
11534
+ let renderedValue = "";
11535
+ let i = 0;
11536
+ for (const char of displayValue) {
11537
+ renderedValue += i === cursorOffset ? source_default.inverse(char) : char;
11538
+ i++;
11539
+ }
11540
+ if (displayValue.length === 0) {
11541
+ renderedValue = source_default.inverse(" ");
11542
+ } else if (cursorOffset === displayValue.length) {
11543
+ renderedValue += source_default.inverse(" ");
11544
+ }
11545
+ return /* @__PURE__ */ jsx8(Text7, { children: renderedValue });
11361
11546
  }
11362
- var ANSI_BACKGROUND_OFFSET, wrapAnsi16, wrapAnsi256, wrapAnsi16m, styles, modifierNames, foregroundColorNames, backgroundColorNames, colorNames, ansiStyles, ansi_styles_default;
11363
- var init_ansi_styles = __esm({
11364
- "node_modules/chalk/source/vendor/ansi-styles/index.js"() {
11547
+ function findPasteTokenEndingAt(value, pos, pastes) {
11548
+ if (pos <= 0 || value[pos - 1] !== "\u2998") return -1;
11549
+ for (const placeholder of pastes.keys()) {
11550
+ if (placeholder.length > pos) continue;
11551
+ const start = pos - placeholder.length;
11552
+ if (value.slice(start, pos) === placeholder) return start;
11553
+ }
11554
+ return -1;
11555
+ }
11556
+ var PASTE_CHAR_THRESHOLD, PASTE_NEWLINE_THRESHOLD;
11557
+ var init_text_input = __esm({
11558
+ "src/ui/text-input.tsx"() {
11365
11559
  "use strict";
11366
- ANSI_BACKGROUND_OFFSET = 10;
11367
- wrapAnsi16 = (offset = 0) => (code) => `\x1B[${code + offset}m`;
11368
- wrapAnsi256 = (offset = 0) => (code) => `\x1B[${38 + offset};5;${code}m`;
11369
- wrapAnsi16m = (offset = 0) => (red, green, blue) => `\x1B[${38 + offset};2;${red};${green};${blue}m`;
11370
- styles = {
11371
- modifier: {
11372
- reset: [0, 0],
11373
- // 21 isn't widely supported and 22 does the same thing
11374
- bold: [1, 22],
11375
- dim: [2, 22],
11376
- italic: [3, 23],
11377
- underline: [4, 24],
11378
- overline: [53, 55],
11379
- inverse: [7, 27],
11380
- hidden: [8, 28],
11381
- strikethrough: [9, 29]
11382
- },
11383
- color: {
11384
- black: [30, 39],
11385
- red: [31, 39],
11386
- green: [32, 39],
11387
- yellow: [33, 39],
11388
- blue: [34, 39],
11389
- magenta: [35, 39],
11390
- cyan: [36, 39],
11391
- white: [37, 39],
11392
- // Bright color
11393
- blackBright: [90, 39],
11394
- gray: [90, 39],
11395
- // Alias of `blackBright`
11396
- grey: [90, 39],
11397
- // Alias of `blackBright`
11398
- redBright: [91, 39],
11399
- greenBright: [92, 39],
11400
- yellowBright: [93, 39],
11401
- blueBright: [94, 39],
11402
- magentaBright: [95, 39],
11403
- cyanBright: [96, 39],
11404
- whiteBright: [97, 39]
11405
- },
11406
- bgColor: {
11407
- bgBlack: [40, 49],
11408
- bgRed: [41, 49],
11409
- bgGreen: [42, 49],
11410
- bgYellow: [43, 49],
11411
- bgBlue: [44, 49],
11412
- bgMagenta: [45, 49],
11413
- bgCyan: [46, 49],
11414
- bgWhite: [47, 49],
11415
- // Bright color
11416
- bgBlackBright: [100, 49],
11417
- bgGray: [100, 49],
11418
- // Alias of `bgBlackBright`
11419
- bgGrey: [100, 49],
11420
- // Alias of `bgBlackBright`
11421
- bgRedBright: [101, 49],
11422
- bgGreenBright: [102, 49],
11423
- bgYellowBright: [103, 49],
11424
- bgBlueBright: [104, 49],
11425
- bgMagentaBright: [105, 49],
11426
- bgCyanBright: [106, 49],
11427
- bgWhiteBright: [107, 49]
11428
- }
11429
- };
11430
- modifierNames = Object.keys(styles.modifier);
11431
- foregroundColorNames = Object.keys(styles.color);
11432
- backgroundColorNames = Object.keys(styles.bgColor);
11433
- colorNames = [...foregroundColorNames, ...backgroundColorNames];
11434
- ansiStyles = assembleStyles();
11435
- ansi_styles_default = ansiStyles;
11560
+ init_source();
11561
+ PASTE_CHAR_THRESHOLD = 200;
11562
+ PASTE_NEWLINE_THRESHOLD = 1;
11436
11563
  }
11437
11564
  });
11438
11565
 
11439
- // node_modules/chalk/source/vendor/supports-color/index.js
11440
- import process2 from "process";
11441
- import os from "os";
11442
- import tty from "tty";
11443
- function hasFlag(flag, argv = globalThis.Deno ? globalThis.Deno.args : process2.argv) {
11444
- const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
11445
- const position = argv.indexOf(prefix + flag);
11446
- const terminatorPosition = argv.indexOf("--");
11447
- return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
11448
- }
11449
- function envForceColor() {
11450
- if ("FORCE_COLOR" in env) {
11451
- if (env.FORCE_COLOR === "true") {
11452
- return 1;
11453
- }
11454
- if (env.FORCE_COLOR === "false") {
11455
- return 0;
11456
- }
11457
- return env.FORCE_COLOR.length === 0 ? 1 : Math.min(Number.parseInt(env.FORCE_COLOR, 10), 3);
11458
- }
11566
+ // src/ui/permission.tsx
11567
+ import { useState as useState4, useCallback } from "react";
11568
+ import { Box as Box7, Text as Text8, useInput as useInput2 } from "ink";
11569
+ import { platform as platform2 } from "os";
11570
+ import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
11571
+ function formatSelection(label, shortcut) {
11572
+ return `${label} [${MOD_KEY}+${shortcut}]`;
11459
11573
  }
11460
- function translateLevel(level) {
11461
- if (level === 0) {
11462
- return false;
11463
- }
11464
- return {
11465
- level,
11466
- hasBasic: true,
11467
- has256: level >= 2,
11468
- has16m: level >= 3
11469
- };
11470
- }
11471
- function _supportsColor(haveStream, { streamIsTTY, sniffFlags = true } = {}) {
11472
- const noFlagForceColor = envForceColor();
11473
- if (noFlagForceColor !== void 0) {
11474
- flagForceColor = noFlagForceColor;
11475
- }
11476
- const forceColor = sniffFlags ? flagForceColor : noFlagForceColor;
11477
- if (forceColor === 0) {
11478
- return 0;
11479
- }
11480
- if (sniffFlags) {
11481
- if (hasFlag("color=16m") || hasFlag("color=full") || hasFlag("color=truecolor")) {
11482
- return 3;
11483
- }
11484
- if (hasFlag("color=256")) {
11485
- return 2;
11486
- }
11487
- }
11488
- if ("TF_BUILD" in env && "AGENT_NAME" in env) {
11489
- return 1;
11490
- }
11491
- if (haveStream && !streamIsTTY && forceColor === void 0) {
11492
- return 0;
11493
- }
11494
- const min = forceColor || 0;
11495
- if (env.TERM === "dumb") {
11496
- return min;
11497
- }
11498
- if (process2.platform === "win32") {
11499
- const osRelease = os.release().split(".");
11500
- if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
11501
- return Number(osRelease[2]) >= 14931 ? 3 : 2;
11502
- }
11503
- return 1;
11504
- }
11505
- if ("CI" in env) {
11506
- if (["GITHUB_ACTIONS", "GITEA_ACTIONS", "CIRCLECI"].some((key) => key in env)) {
11507
- return 3;
11508
- }
11509
- if (["TRAVIS", "APPVEYOR", "GITLAB_CI", "BUILDKITE", "DRONE"].some((sign) => sign in env) || env.CI_NAME === "codeship") {
11510
- return 1;
11511
- }
11512
- return min;
11513
- }
11514
- if ("TEAMCITY_VERSION" in env) {
11515
- return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
11516
- }
11517
- if (env.COLORTERM === "truecolor") {
11518
- return 3;
11519
- }
11520
- if (env.TERM === "xterm-kitty") {
11521
- return 3;
11522
- }
11523
- if (env.TERM === "xterm-ghostty") {
11524
- return 3;
11525
- }
11526
- if (env.TERM === "wezterm") {
11527
- return 3;
11574
+ function PermissionModal({ tool, args, onDecide, onFeedback }) {
11575
+ const theme = useTheme();
11576
+ const [selectedIndex, setSelectedIndex] = useState4(0);
11577
+ const [showHelp, setShowHelp] = useState4(false);
11578
+ const [feedbackActive, setFeedbackActive] = useState4(false);
11579
+ const [feedbackValue, setFeedbackValue] = useState4("");
11580
+ let render2;
11581
+ try {
11582
+ render2 = tool.render?.(args);
11583
+ } catch {
11528
11584
  }
11529
- if ("TERM_PROGRAM" in env) {
11530
- const version = Number.parseInt((env.TERM_PROGRAM_VERSION || "").split(".")[0], 10);
11531
- switch (env.TERM_PROGRAM) {
11532
- case "iTerm.app": {
11533
- return version >= 3 ? 3 : 2;
11585
+ const handleSelect = useCallback(
11586
+ (index) => {
11587
+ const opt = OPTIONS[index];
11588
+ if (!opt) return;
11589
+ if (opt.value === "deny") {
11590
+ if (onFeedback) {
11591
+ setFeedbackActive(true);
11592
+ } else {
11593
+ onDecide("deny");
11594
+ }
11595
+ } else {
11596
+ onDecide(opt.value);
11534
11597
  }
11535
- case "Apple_Terminal": {
11536
- return 2;
11598
+ },
11599
+ [onDecide, onFeedback]
11600
+ );
11601
+ const handleFeedbackSubmit = useCallback(
11602
+ (text) => {
11603
+ onDecide("deny");
11604
+ if (text.trim()) {
11605
+ onFeedback?.(text);
11606
+ }
11607
+ setFeedbackActive(false);
11608
+ setFeedbackValue("");
11609
+ },
11610
+ [onDecide, onFeedback]
11611
+ );
11612
+ const handleFeedbackCancel = useCallback(() => {
11613
+ onDecide("deny");
11614
+ setFeedbackActive(false);
11615
+ setFeedbackValue("");
11616
+ }, [onDecide]);
11617
+ useInput2(
11618
+ (inputChar, key) => {
11619
+ if (showHelp) {
11620
+ setShowHelp(false);
11621
+ return;
11537
11622
  }
11538
- }
11539
- }
11540
- if (/-256(color)?$/i.test(env.TERM)) {
11541
- return 2;
11542
- }
11543
- if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
11544
- return 1;
11545
- }
11546
- if ("COLORTERM" in env) {
11547
- return 1;
11623
+ if (key.meta && inputChar === "1") {
11624
+ handleSelect(0);
11625
+ return;
11626
+ }
11627
+ if (key.meta && inputChar === "2") {
11628
+ handleSelect(1);
11629
+ return;
11630
+ }
11631
+ if (key.meta && inputChar === "3") {
11632
+ handleSelect(2);
11633
+ return;
11634
+ }
11635
+ if (key.upArrow || inputChar === "k") {
11636
+ setSelectedIndex((i) => Math.max(0, i - 1));
11637
+ return;
11638
+ }
11639
+ if (key.downArrow || inputChar === "j") {
11640
+ setSelectedIndex((i) => Math.min(OPTIONS.length - 1, i + 1));
11641
+ return;
11642
+ }
11643
+ if (key.return) {
11644
+ handleSelect(selectedIndex);
11645
+ return;
11646
+ }
11647
+ if (inputChar === "?") {
11648
+ setShowHelp(true);
11649
+ return;
11650
+ }
11651
+ if (key.escape) {
11652
+ onDecide("deny");
11653
+ }
11654
+ },
11655
+ { isActive: !feedbackActive }
11656
+ );
11657
+ if (showHelp) {
11658
+ return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", borderStyle: "round", borderColor: theme.permission, paddingX: 1, children: [
11659
+ /* @__PURE__ */ jsx9(Text8, { color: theme.permission, bold: true, children: "Permission modal \u2014 keyboard shortcuts" }),
11660
+ /* @__PURE__ */ jsx9(Text8, { color: theme.info.color, children: "\u2191 / \u2193 or j / k \u2014 navigate options" }),
11661
+ /* @__PURE__ */ jsxs7(Text8, { color: theme.info.color, children: [
11662
+ MOD_KEY,
11663
+ "+1 / ",
11664
+ MOD_KEY,
11665
+ "+2 / ",
11666
+ MOD_KEY,
11667
+ "+3 \u2014 select option directly"
11668
+ ] }),
11669
+ /* @__PURE__ */ jsx9(Text8, { color: theme.info.color, children: "Enter \u2014 confirm selection" }),
11670
+ /* @__PURE__ */ jsx9(Text8, { color: theme.info.color, children: "Esc \u2014 deny and close" }),
11671
+ /* @__PURE__ */ jsx9(Text8, { color: theme.info.color, children: "? \u2014 toggle this help" }),
11672
+ /* @__PURE__ */ jsx9(Text8, { color: theme.info.color, children: "When feedback input is open:" }),
11673
+ /* @__PURE__ */ jsx9(Text8, { color: theme.info.color, children: " Enter \u2014 submit feedback and deny" }),
11674
+ /* @__PURE__ */ jsx9(Text8, { color: theme.info.color, children: " Esc \u2014 deny without feedback" }),
11675
+ /* @__PURE__ */ jsx9(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx9(Text8, { color: theme.accent, children: "Press any key to close" }) })
11676
+ ] });
11548
11677
  }
11549
- return min;
11550
- }
11551
- function createSupportsColor(stream, options = {}) {
11552
- const level = _supportsColor(stream, {
11553
- streamIsTTY: stream && stream.isTTY,
11554
- ...options
11555
- });
11556
- return translateLevel(level);
11678
+ return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", borderStyle: "round", borderColor: theme.permission, paddingX: 1, children: [
11679
+ /* @__PURE__ */ jsx9(Text8, { color: theme.permission, bold: true, children: "Permission requested" }),
11680
+ /* @__PURE__ */ jsxs7(Text8, { children: [
11681
+ "tool: ",
11682
+ /* @__PURE__ */ jsx9(Text8, { color: theme.tool, children: tool.name })
11683
+ ] }),
11684
+ render2?.title ? /* @__PURE__ */ jsxs7(Text8, { children: [
11685
+ "action: ",
11686
+ render2.title
11687
+ ] }) : null,
11688
+ render2?.diff ? /* @__PURE__ */ jsx9(Box7, { marginTop: 1, flexDirection: "column", children: /* @__PURE__ */ jsx9(DiffView, { ...render2.diff }) }) : /* @__PURE__ */ jsxs7(Text8, { color: theme.info.color, children: [
11689
+ "args: ",
11690
+ JSON.stringify(args)
11691
+ ] }),
11692
+ /* @__PURE__ */ jsx9(Box7, { marginTop: 1, flexDirection: "column", children: OPTIONS.map((opt, i) => /* @__PURE__ */ jsxs7(
11693
+ Text8,
11694
+ {
11695
+ color: i === selectedIndex ? theme.accent : void 0,
11696
+ bold: i === selectedIndex,
11697
+ children: [
11698
+ i === selectedIndex ? "\u203A " : " ",
11699
+ formatSelection(opt.label, opt.key)
11700
+ ]
11701
+ },
11702
+ opt.value
11703
+ )) }),
11704
+ feedbackActive && /* @__PURE__ */ jsxs7(Box7, { marginTop: 1, flexDirection: "column", children: [
11705
+ /* @__PURE__ */ jsx9(Text8, { color: theme.palette.error, children: "Tell me what to do instead" }),
11706
+ /* @__PURE__ */ jsx9(Text8, { color: theme.info.color, dimColor: true, children: "Press Esc to deny without feedback" }),
11707
+ /* @__PURE__ */ jsx9(
11708
+ CustomTextInput,
11709
+ {
11710
+ value: feedbackValue,
11711
+ onChange: setFeedbackValue,
11712
+ onSubmit: handleFeedbackSubmit,
11713
+ onCancel: handleFeedbackCancel,
11714
+ focus: true
11715
+ }
11716
+ )
11717
+ ] })
11718
+ ] });
11557
11719
  }
11558
- var env, flagForceColor, supportsColor, supports_color_default;
11559
- var init_supports_color = __esm({
11560
- "node_modules/chalk/source/vendor/supports-color/index.js"() {
11720
+ var OPTIONS, MOD_KEY;
11721
+ var init_permission = __esm({
11722
+ "src/ui/permission.tsx"() {
11561
11723
  "use strict";
11562
- ({ env } = process2);
11563
- if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false") || hasFlag("color=never")) {
11564
- flagForceColor = 0;
11565
- } else if (hasFlag("color") || hasFlag("colors") || hasFlag("color=true") || hasFlag("color=always")) {
11566
- flagForceColor = 1;
11567
- }
11568
- supportsColor = {
11569
- stdout: createSupportsColor({ isTTY: tty.isatty(1) }),
11570
- stderr: createSupportsColor({ isTTY: tty.isatty(2) })
11571
- };
11572
- supports_color_default = supportsColor;
11724
+ init_diff_view();
11725
+ init_text_input();
11726
+ init_theme_context();
11727
+ OPTIONS = [
11728
+ { value: "allow", label: "Allow once", key: 1 },
11729
+ { value: "allow_session", label: "Allow for this session", key: 2 },
11730
+ { value: "deny", label: "Something else", key: 3 }
11731
+ ];
11732
+ MOD_KEY = platform2() === "darwin" ? "\u2325" : "Alt";
11573
11733
  }
11574
11734
  });
11575
11735
 
11576
- // node_modules/chalk/source/utilities.js
11577
- function stringReplaceAll(string, substring, replacer) {
11578
- let index = string.indexOf(substring);
11579
- if (index === -1) {
11580
- return string;
11581
- }
11582
- const substringLength = substring.length;
11583
- let endIndex = 0;
11584
- let returnValue = "";
11585
- do {
11586
- returnValue += string.slice(endIndex, index) + substring + replacer;
11587
- endIndex = index + substringLength;
11588
- index = string.indexOf(substring, endIndex);
11589
- } while (index !== -1);
11590
- returnValue += string.slice(endIndex);
11591
- return returnValue;
11592
- }
11593
- function stringEncaseCRLFWithFirstIndex(string, prefix, postfix, index) {
11594
- let endIndex = 0;
11595
- let returnValue = "";
11596
- do {
11597
- const gotCR = string[index - 1] === "\r";
11598
- returnValue += string.slice(endIndex, gotCR ? index - 1 : index) + prefix + (gotCR ? "\r\n" : "\n") + postfix;
11599
- endIndex = index + 1;
11600
- index = string.indexOf("\n", endIndex);
11601
- } while (index !== -1);
11602
- returnValue += string.slice(endIndex);
11603
- return returnValue;
11736
+ // src/ui/limit-modal.tsx
11737
+ import { Box as Box8, Text as Text9 } from "ink";
11738
+ import SelectInput from "ink-select-input";
11739
+ import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
11740
+ function LimitModal({ limit, onDecide }) {
11741
+ const theme = useTheme();
11742
+ const items = [
11743
+ { label: "Continue", value: "continue" },
11744
+ { label: "Stop", value: "stop" }
11745
+ ];
11746
+ return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", borderStyle: "round", borderColor: theme.error, paddingX: 1, children: [
11747
+ /* @__PURE__ */ jsxs8(Text9, { color: theme.error, bold: true, children: [
11748
+ "Tool-call limit reached (",
11749
+ limit,
11750
+ ")"
11751
+ ] }),
11752
+ /* @__PURE__ */ jsxs8(Text9, { dimColor: true, children: [
11753
+ "This session has made ",
11754
+ limit,
11755
+ " tool calls. What would you like to do?"
11756
+ ] }),
11757
+ /* @__PURE__ */ jsx10(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx10(
11758
+ SelectInput,
11759
+ {
11760
+ items,
11761
+ onSelect: (item) => onDecide(item.value)
11762
+ }
11763
+ ) })
11764
+ ] });
11604
11765
  }
11605
- var init_utilities = __esm({
11606
- "node_modules/chalk/source/utilities.js"() {
11766
+ var init_limit_modal = __esm({
11767
+ "src/ui/limit-modal.tsx"() {
11607
11768
  "use strict";
11769
+ init_theme_context();
11608
11770
  }
11609
11771
  });
11610
11772
 
11611
- // node_modules/chalk/source/index.js
11612
- function createChalk(options) {
11613
- return chalkFactory(options);
11614
- }
11615
- var stdoutColor, stderrColor, GENERATOR, STYLER, IS_EMPTY, levelMapping, styles2, applyOptions, chalkFactory, getModelAnsi, usedModels, proto, createStyler, createBuilder, applyStyle, chalk, chalkStderr, source_default;
11616
- var init_source = __esm({
11617
- "node_modules/chalk/source/index.js"() {
11618
- "use strict";
11619
- init_ansi_styles();
11620
- init_supports_color();
11621
- init_utilities();
11622
- ({ stdout: stdoutColor, stderr: stderrColor } = supports_color_default);
11623
- GENERATOR = /* @__PURE__ */ Symbol("GENERATOR");
11624
- STYLER = /* @__PURE__ */ Symbol("STYLER");
11625
- IS_EMPTY = /* @__PURE__ */ Symbol("IS_EMPTY");
11626
- levelMapping = [
11627
- "ansi",
11628
- "ansi",
11629
- "ansi256",
11630
- "ansi16m"
11631
- ];
11632
- styles2 = /* @__PURE__ */ Object.create(null);
11633
- applyOptions = (object, options = {}) => {
11634
- if (options.level && !(Number.isInteger(options.level) && options.level >= 0 && options.level <= 3)) {
11635
- throw new Error("The `level` option should be an integer from 0 to 3");
11636
- }
11637
- const colorLevel = stdoutColor ? stdoutColor.level : 0;
11638
- object.level = options.level === void 0 ? colorLevel : options.level;
11639
- };
11640
- chalkFactory = (options) => {
11641
- const chalk2 = (...strings) => strings.join(" ");
11642
- applyOptions(chalk2, options);
11643
- Object.setPrototypeOf(chalk2, createChalk.prototype);
11644
- return chalk2;
11645
- };
11646
- Object.setPrototypeOf(createChalk.prototype, Function.prototype);
11647
- for (const [styleName, style] of Object.entries(ansi_styles_default)) {
11648
- styles2[styleName] = {
11649
- get() {
11650
- const builder = createBuilder(this, createStyler(style.open, style.close, this[STYLER]), this[IS_EMPTY]);
11651
- Object.defineProperty(this, styleName, { value: builder });
11652
- return builder;
11653
- }
11654
- };
11655
- }
11656
- styles2.visible = {
11657
- get() {
11658
- const builder = createBuilder(this, this[STYLER], true);
11659
- Object.defineProperty(this, "visible", { value: builder });
11660
- return builder;
11661
- }
11662
- };
11663
- getModelAnsi = (model, level, type, ...arguments_) => {
11664
- if (model === "rgb") {
11665
- if (level === "ansi16m") {
11666
- return ansi_styles_default[type].ansi16m(...arguments_);
11667
- }
11668
- if (level === "ansi256") {
11669
- return ansi_styles_default[type].ansi256(ansi_styles_default.rgbToAnsi256(...arguments_));
11670
- }
11671
- return ansi_styles_default[type].ansi(ansi_styles_default.rgbToAnsi(...arguments_));
11672
- }
11673
- if (model === "hex") {
11674
- return getModelAnsi("rgb", level, type, ...ansi_styles_default.hexToRgb(...arguments_));
11675
- }
11676
- return ansi_styles_default[type][model](...arguments_);
11677
- };
11678
- usedModels = ["rgb", "hex", "ansi256"];
11679
- for (const model of usedModels) {
11680
- styles2[model] = {
11681
- get() {
11682
- const { level } = this;
11683
- return function(...arguments_) {
11684
- const styler = createStyler(getModelAnsi(model, levelMapping[level], "color", ...arguments_), ansi_styles_default.color.close, this[STYLER]);
11685
- return createBuilder(this, styler, this[IS_EMPTY]);
11686
- };
11687
- }
11688
- };
11689
- const bgModel = "bg" + model[0].toUpperCase() + model.slice(1);
11690
- styles2[bgModel] = {
11691
- get() {
11692
- const { level } = this;
11693
- return function(...arguments_) {
11694
- const styler = createStyler(getModelAnsi(model, levelMapping[level], "bgColor", ...arguments_), ansi_styles_default.bgColor.close, this[STYLER]);
11695
- return createBuilder(this, styler, this[IS_EMPTY]);
11696
- };
11697
- }
11698
- };
11699
- }
11700
- proto = Object.defineProperties(() => {
11701
- }, {
11702
- ...styles2,
11703
- level: {
11704
- enumerable: true,
11705
- get() {
11706
- return this[GENERATOR].level;
11707
- },
11708
- set(level) {
11709
- this[GENERATOR].level = level;
11710
- }
11711
- }
11712
- });
11713
- createStyler = (open3, close, parent) => {
11714
- let openAll;
11715
- let closeAll;
11716
- if (parent === void 0) {
11717
- openAll = open3;
11718
- closeAll = close;
11773
+ // src/util/fuzzy.ts
11774
+ function fuzzyMatch(query, text) {
11775
+ const queryLower = query.toLowerCase();
11776
+ const textLower = text.toLowerCase();
11777
+ const matchQuery = (normalizedQuery) => {
11778
+ if (normalizedQuery.length === 0) return { matches: true, score: 0 };
11779
+ if (normalizedQuery.length > textLower.length) return { matches: false, score: 0 };
11780
+ let queryIndex = 0;
11781
+ let score = 0;
11782
+ let lastMatchIndex = -1;
11783
+ let consecutiveMatches = 0;
11784
+ for (let i = 0; i < textLower.length && queryIndex < normalizedQuery.length; i++) {
11785
+ if (textLower[i] !== normalizedQuery[queryIndex]) continue;
11786
+ const isWordBoundary = i === 0 || /[\s\-_./:]/.test(textLower[i - 1]);
11787
+ if (lastMatchIndex === i - 1) {
11788
+ consecutiveMatches++;
11789
+ score -= consecutiveMatches * 5;
11719
11790
  } else {
11720
- openAll = parent.openAll + open3;
11721
- closeAll = close + parent.closeAll;
11722
- }
11723
- return {
11724
- open: open3,
11725
- close,
11726
- openAll,
11727
- closeAll,
11728
- parent
11729
- };
11730
- };
11731
- createBuilder = (self, _styler, _isEmpty) => {
11732
- const builder = (...arguments_) => applyStyle(builder, arguments_.length === 1 ? "" + arguments_[0] : arguments_.join(" "));
11733
- Object.setPrototypeOf(builder, proto);
11734
- builder[GENERATOR] = self;
11735
- builder[STYLER] = _styler;
11736
- builder[IS_EMPTY] = _isEmpty;
11737
- return builder;
11738
- };
11739
- applyStyle = (self, string) => {
11740
- if (self.level <= 0 || !string) {
11741
- return self[IS_EMPTY] ? "" : string;
11742
- }
11743
- let styler = self[STYLER];
11744
- if (styler === void 0) {
11745
- return string;
11746
- }
11747
- const { openAll, closeAll } = styler;
11748
- if (string.includes("\x1B")) {
11749
- while (styler !== void 0) {
11750
- string = stringReplaceAll(string, styler.close, styler.open);
11751
- styler = styler.parent;
11752
- }
11791
+ consecutiveMatches = 0;
11792
+ if (lastMatchIndex >= 0) score += (i - lastMatchIndex - 1) * 2;
11753
11793
  }
11754
- const lfIndex = string.indexOf("\n");
11755
- if (lfIndex !== -1) {
11756
- string = stringEncaseCRLFWithFirstIndex(string, closeAll, openAll, lfIndex);
11794
+ if (isWordBoundary) score -= 10;
11795
+ score += i * 0.1;
11796
+ lastMatchIndex = i;
11797
+ queryIndex++;
11798
+ }
11799
+ if (queryIndex < normalizedQuery.length) return { matches: false, score: 0 };
11800
+ if (normalizedQuery === textLower) score -= 100;
11801
+ return { matches: true, score };
11802
+ };
11803
+ const primaryMatch = matchQuery(queryLower);
11804
+ if (primaryMatch.matches) return primaryMatch;
11805
+ const alphaNumericMatch = queryLower.match(/^(?<letters>[a-z]+)(?<digits>[0-9]+)$/);
11806
+ const numericAlphaMatch = queryLower.match(/^(?<digits>[0-9]+)(?<letters>[a-z]+)$/);
11807
+ const swappedQuery = alphaNumericMatch ? `${alphaNumericMatch.groups?.digits ?? ""}${alphaNumericMatch.groups?.letters ?? ""}` : numericAlphaMatch ? `${numericAlphaMatch.groups?.letters ?? ""}${numericAlphaMatch.groups?.digits ?? ""}` : "";
11808
+ if (!swappedQuery) return primaryMatch;
11809
+ const swappedMatch = matchQuery(swappedQuery);
11810
+ if (!swappedMatch.matches) return primaryMatch;
11811
+ return { matches: true, score: swappedMatch.score + 5 };
11812
+ }
11813
+ function fuzzyFilter(items, query, getText) {
11814
+ const trimmed = query.trim();
11815
+ if (trimmed.length === 0) return items;
11816
+ const tokens = trimmed.split(/\s+/).filter((t) => t.length > 0);
11817
+ if (tokens.length === 0) return items;
11818
+ const scored = [];
11819
+ for (const item of items) {
11820
+ const text = getText(item);
11821
+ let total = 0;
11822
+ let allMatch = true;
11823
+ for (const token of tokens) {
11824
+ const m = fuzzyMatch(token, text);
11825
+ if (!m.matches) {
11826
+ allMatch = false;
11827
+ break;
11757
11828
  }
11758
- return openAll + string + closeAll;
11759
- };
11760
- Object.defineProperties(createChalk.prototype, styles2);
11761
- chalk = createChalk();
11762
- chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
11763
- source_default = chalk;
11829
+ total += m.score;
11830
+ }
11831
+ if (allMatch) scored.push({ item, score: total });
11832
+ }
11833
+ scored.sort((a, b) => a.score - b.score);
11834
+ return scored.map((s) => s.item);
11835
+ }
11836
+ var init_fuzzy = __esm({
11837
+ "src/util/fuzzy.ts"() {
11838
+ "use strict";
11764
11839
  }
11765
11840
  });
11766
11841
 
11767
- // src/ui/text-input.tsx
11768
- import { useState as useState6, useEffect as useEffect4, useRef as useRef2 } from "react";
11769
- import { Text as Text12, useInput as useInput3 } from "ink";
11770
- import { jsx as jsx13 } from "react/jsx-runtime";
11771
- function shouldTreatAsPaste(input) {
11772
- if (input.length >= PASTE_CHAR_THRESHOLD) return true;
11773
- const newlines = (input.match(/\n/g) ?? []).length;
11774
- return newlines >= PASTE_NEWLINE_THRESHOLD;
11775
- }
11776
- function newPasteId() {
11777
- return Math.random().toString(36).slice(2, 7);
11778
- }
11779
- function countLines(s) {
11780
- return s.split("\n").length;
11781
- }
11782
- function findWordBoundaryForward(text, pos) {
11783
- while (pos < text.length && /\w/.test(text[pos])) pos++;
11784
- while (pos < text.length && !/\w/.test(text[pos])) pos++;
11785
- return pos;
11786
- }
11787
- function findWordBoundaryBackward(text, pos) {
11788
- while (pos > 0 && !/\w/.test(text[pos - 1])) pos--;
11789
- while (pos > 0 && /\w/.test(text[pos - 1])) pos--;
11790
- return pos;
11791
- }
11792
- function CustomTextInput({
11793
- value,
11794
- onChange,
11795
- onSubmit,
11796
- onHistoryUp,
11797
- onHistoryDown,
11798
- onClearQueueItem,
11799
- focus = true,
11800
- mask,
11801
- enablePaste = false,
11802
- cursorOffset: controlledCursor,
11803
- onCursorChange,
11804
- pickerActive = false,
11805
- onPickerUp,
11806
- onPickerDown,
11807
- onPickerSelect,
11808
- onPickerCancel
11809
- }) {
11810
- const [internalCursor, setInternalCursor] = useState6(value.length);
11811
- const cursorOffset = controlledCursor ?? internalCursor;
11812
- const setCursorOffset = (offset) => {
11813
- setInternalCursor(offset);
11814
- onCursorChange?.(offset);
11815
- };
11816
- const pastesRef = useRef2(/* @__PURE__ */ new Map());
11817
- useEffect4(() => {
11818
- if (!focus) return;
11819
- const next = cursorOffset > value.length ? value.length : cursorOffset;
11820
- if (next !== cursorOffset) {
11821
- setCursorOffset(next);
11842
+ // src/ui/resume-picker.tsx
11843
+ import { useState as useState5 } from "react";
11844
+ import { Box as Box9, Text as Text10, useInput as useInput3 } from "ink";
11845
+ import SelectInput2 from "ink-select-input";
11846
+ import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
11847
+ function ResumePicker({ sessions, onPick }) {
11848
+ const theme = useTheme();
11849
+ const [page, setPage] = useState5(0);
11850
+ const [selectedIndex, setSelectedIndex] = useState5(0);
11851
+ const [query, setQuery] = useState5("");
11852
+ const filtered = query.trim() ? fuzzyFilter(sessions, query, (s) => `${s.title ?? s.firstPrompt} ${s.id}`) : sessions;
11853
+ const totalPages = Math.max(1, Math.ceil(filtered.length / PAGE_SIZE));
11854
+ const safePage = Math.min(page, totalPages - 1);
11855
+ const start = safePage * PAGE_SIZE;
11856
+ const end = Math.min(start + PAGE_SIZE, filtered.length);
11857
+ const pageSessions = filtered.slice(start, end);
11858
+ useInput3((input, key) => {
11859
+ if (key.leftArrow && safePage > 0) {
11860
+ setPage((p) => p - 1);
11861
+ setSelectedIndex(0);
11862
+ return;
11822
11863
  }
11823
- }, [value, focus, cursorOffset]);
11824
- useInput3(
11825
- (input, key) => {
11826
- if (!focus) return;
11827
- if (key.ctrl && input === "c") return;
11828
- if (key.ctrl && input === "r") return;
11829
- if (key.ctrl && input === "o") return;
11830
- if (key.tab) return;
11831
- if (pickerActive) {
11832
- if (key.upArrow) {
11833
- onPickerUp?.();
11834
- return;
11835
- }
11836
- if (key.downArrow) {
11837
- onPickerDown?.();
11838
- return;
11839
- }
11840
- if (key.return) {
11841
- onPickerSelect?.();
11842
- return;
11843
- }
11844
- if (key.escape) {
11845
- onPickerCancel?.();
11846
- return;
11847
- }
11848
- }
11849
- if (key.return) {
11850
- let full = value;
11851
- let hasPastes = false;
11852
- if (enablePaste && pastesRef.current.size > 0) {
11853
- for (const [placeholder, fullText] of pastesRef.current) {
11854
- if (full.includes(placeholder)) {
11855
- full = full.split(placeholder).join(fullText);
11856
- hasPastes = true;
11857
- }
11858
- }
11859
- }
11860
- onSubmit(full, hasPastes ? value : void 0);
11861
- pastesRef.current.clear();
11862
- setCursorOffset(0);
11863
- return;
11864
- }
11865
- if (key.upArrow) {
11866
- onHistoryUp?.();
11867
- return;
11868
- }
11869
- if (key.downArrow) {
11870
- onHistoryDown?.();
11871
- return;
11872
- }
11873
- let nextCursor = cursorOffset;
11874
- let nextValue = value;
11875
- let didDelete = false;
11876
- if (key.leftArrow) {
11877
- if (key.meta) {
11878
- nextCursor = findWordBoundaryBackward(value, cursorOffset);
11879
- } else {
11880
- nextCursor = cursorOffset - 1;
11881
- }
11882
- } else if (key.rightArrow) {
11883
- if (key.meta) {
11884
- nextCursor = findWordBoundaryForward(value, cursorOffset);
11885
- } else {
11886
- nextCursor = cursorOffset + 1;
11887
- }
11888
- } else if (key.meta && input === "b") {
11889
- nextCursor = findWordBoundaryBackward(value, cursorOffset);
11890
- } else if (key.meta && input === "f") {
11891
- nextCursor = findWordBoundaryForward(value, cursorOffset);
11892
- } else if (key.meta && input === "d") {
11893
- didDelete = true;
11894
- const boundary = findWordBoundaryForward(value, cursorOffset);
11895
- nextValue = value.slice(0, cursorOffset) + value.slice(boundary);
11896
- } else if (key.home || key.ctrl && input === "a") {
11897
- nextCursor = 0;
11898
- } else if (key.end || key.ctrl && input === "e") {
11899
- nextCursor = value.length;
11900
- } else if (key.backspace) {
11901
- didDelete = true;
11902
- const tokenBoundary = enablePaste ? findPasteTokenEndingAt(value, cursorOffset, pastesRef.current) : -1;
11903
- if (tokenBoundary >= 0) {
11904
- const token = value.slice(tokenBoundary, cursorOffset);
11905
- pastesRef.current.delete(token);
11906
- nextValue = value.slice(0, tokenBoundary) + value.slice(cursorOffset);
11907
- nextCursor = tokenBoundary;
11908
- } else if (key.meta || key.ctrl && input === "w") {
11909
- const boundary = findWordBoundaryBackward(value, cursorOffset);
11910
- nextValue = value.slice(0, boundary) + value.slice(cursorOffset);
11911
- nextCursor = boundary;
11912
- } else if (key.ctrl) {
11913
- const boundary = findWordBoundaryBackward(value, cursorOffset);
11914
- nextValue = value.slice(0, boundary) + value.slice(cursorOffset);
11915
- nextCursor = boundary;
11916
- } else {
11917
- if (cursorOffset > 0) {
11918
- nextValue = value.slice(0, cursorOffset - 1) + value.slice(cursorOffset);
11919
- nextCursor = cursorOffset - 1;
11920
- }
11921
- }
11922
- } else if (key.delete) {
11923
- didDelete = true;
11924
- if (key.meta || key.ctrl) {
11925
- const boundary = findWordBoundaryForward(value, cursorOffset);
11926
- nextValue = value.slice(0, cursorOffset) + value.slice(boundary);
11927
- } else {
11928
- nextValue = value.slice(0, cursorOffset) + value.slice(cursorOffset + 1);
11864
+ if (key.rightArrow && safePage < totalPages - 1) {
11865
+ setPage((p) => p + 1);
11866
+ setSelectedIndex(0);
11867
+ return;
11868
+ }
11869
+ if (key.backspace || key.delete) {
11870
+ setQuery((q) => q.slice(0, -1));
11871
+ setPage(0);
11872
+ setSelectedIndex(0);
11873
+ return;
11874
+ }
11875
+ if (input.length === 1 && !key.ctrl && !key.meta && !key.return && !key.escape) {
11876
+ setQuery((q) => q + input);
11877
+ setPage(0);
11878
+ setSelectedIndex(0);
11879
+ return;
11880
+ }
11881
+ if (input === "q" || key.escape) {
11882
+ onPick(null);
11883
+ return;
11884
+ }
11885
+ });
11886
+ if (sessions.length === 0) {
11887
+ return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
11888
+ /* @__PURE__ */ jsx11(Text10, { color: theme.accent, bold: true, children: "Resume a session" }),
11889
+ /* @__PURE__ */ jsx11(Text10, { color: theme.info.color, children: "No saved sessions yet. Press Enter to dismiss." }),
11890
+ /* @__PURE__ */ jsx11(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx11(
11891
+ SelectInput2,
11892
+ {
11893
+ items: [{ label: "(back)", value: "__cancel__" }],
11894
+ onSelect: () => onPick(null)
11929
11895
  }
11930
- } else if (key.ctrl && input === "w") {
11931
- didDelete = true;
11932
- const boundary = findWordBoundaryBackward(value, cursorOffset);
11933
- nextValue = value.slice(0, boundary) + value.slice(cursorOffset);
11934
- nextCursor = boundary;
11935
- } else if (key.ctrl && input === "u") {
11936
- didDelete = true;
11937
- nextValue = value.slice(cursorOffset);
11938
- nextCursor = 0;
11939
- } else if (key.ctrl && input === "k") {
11940
- didDelete = true;
11941
- nextValue = value.slice(0, cursorOffset);
11942
- } else if (input.length > 0 && !key.ctrl && !key.meta) {
11943
- let toInsert = input;
11944
- if (enablePaste && shouldTreatAsPaste(input)) {
11945
- const lines = countLines(input);
11946
- const id = newPasteId();
11947
- const placeholder = `[pasted ${lines} line${lines === 1 ? "" : "s"} #${id}]`;
11948
- pastesRef.current.set(placeholder, input);
11949
- toInsert = placeholder;
11896
+ ) })
11897
+ ] });
11898
+ }
11899
+ const items = pageSessions.map((s) => ({
11900
+ label: `${formatDate(s.updatedAt)} \xB7 ${s.messageCount} msgs \xB7 ${s.title ?? s.firstPrompt}`,
11901
+ value: s.id
11902
+ }));
11903
+ return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
11904
+ /* @__PURE__ */ jsx11(Text10, { color: theme.accent, bold: true, children: "Resume a session" }),
11905
+ /* @__PURE__ */ jsxs9(Text10, { color: theme.info.color, children: [
11906
+ query ? `Search: ${query}\u258C` : "Type to search\u2026",
11907
+ " \xB7 Page ",
11908
+ safePage + 1,
11909
+ " of ",
11910
+ totalPages,
11911
+ " (",
11912
+ filtered.length,
11913
+ " total)"
11914
+ ] }),
11915
+ /* @__PURE__ */ jsx11(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx11(
11916
+ SelectInput2,
11917
+ {
11918
+ items,
11919
+ initialIndex: selectedIndex,
11920
+ onHighlight: (item) => {
11921
+ const idx = items.findIndex((i) => i.value === item.value);
11922
+ if (idx >= 0) setSelectedIndex(idx);
11923
+ },
11924
+ onSelect: (item) => {
11925
+ const picked = sessions.find((s) => s.id === item.value) ?? null;
11926
+ onPick(picked);
11950
11927
  }
11951
- nextValue = value.slice(0, cursorOffset) + toInsert + value.slice(cursorOffset);
11952
- nextCursor = cursorOffset + toInsert.length;
11953
- }
11954
- if (nextCursor < 0) nextCursor = 0;
11955
- if (nextCursor > nextValue.length) nextCursor = nextValue.length;
11956
- if (didDelete && nextValue === "" && value !== "") {
11957
- onClearQueueItem?.(value);
11958
- }
11959
- if (nextCursor !== cursorOffset) {
11960
- setCursorOffset(nextCursor);
11961
- }
11962
- if (nextValue !== value) {
11963
- onChange(nextValue);
11964
11928
  }
11929
+ ) }),
11930
+ /* @__PURE__ */ jsx11(Box9, { marginTop: 1, children: /* @__PURE__ */ jsxs9(Text10, { color: theme.info.color, children: [
11931
+ safePage > 0 ? "\u2190 prev " : "",
11932
+ safePage < totalPages - 1 ? "\u2192 next " : "",
11933
+ "q: cancel"
11934
+ ] }) })
11935
+ ] });
11936
+ }
11937
+ function formatDate(iso) {
11938
+ try {
11939
+ const d = new Date(iso);
11940
+ return d.toLocaleString(void 0, {
11941
+ month: "short",
11942
+ day: "numeric",
11943
+ hour: "2-digit",
11944
+ minute: "2-digit"
11945
+ });
11946
+ } catch {
11947
+ return iso;
11948
+ }
11949
+ }
11950
+ var PAGE_SIZE;
11951
+ var init_resume_picker = __esm({
11952
+ "src/ui/resume-picker.tsx"() {
11953
+ "use strict";
11954
+ init_fuzzy();
11955
+ init_theme_context();
11956
+ PAGE_SIZE = 5;
11957
+ }
11958
+ });
11959
+
11960
+ // src/ui/checkpoint-picker.tsx
11961
+ import { useState as useState6 } from "react";
11962
+ import { Box as Box10, Text as Text11, useInput as useInput4 } from "ink";
11963
+ import SelectInput3 from "ink-select-input";
11964
+ import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
11965
+ function CheckpointPicker({ session, checkpoints, onPick }) {
11966
+ const theme = useTheme();
11967
+ const [selectedIndex, setSelectedIndex] = useState6(0);
11968
+ useInput4((input, key) => {
11969
+ if (input === "q" || key.escape) {
11970
+ onPick(null);
11971
+ return;
11972
+ }
11973
+ });
11974
+ const items = [
11975
+ {
11976
+ label: `Resume from beginning (${session.messageCount} msgs)`,
11977
+ value: "__start__"
11965
11978
  },
11966
- { isActive: focus }
11967
- );
11968
- const displayValue = mask ? mask.repeat(value.length) : value;
11969
- let renderedValue = "";
11970
- let i = 0;
11971
- for (const char of displayValue) {
11972
- renderedValue += i === cursorOffset ? source_default.inverse(char) : char;
11973
- i++;
11979
+ ...checkpoints.map((cp) => ({
11980
+ label: `Resume from: "${cp.label}" \u2014 turn ${cp.turnIndex} \xB7 ${formatDate2(cp.timestamp)}`,
11981
+ value: cp.id
11982
+ }))
11983
+ ];
11984
+ return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
11985
+ /* @__PURE__ */ jsx12(Text11, { color: theme.accent, bold: true, children: session.firstPrompt.slice(0, 50) }),
11986
+ /* @__PURE__ */ jsxs10(Text11, { color: theme.info.color, children: [
11987
+ session.messageCount,
11988
+ " turns \xB7 ",
11989
+ checkpoints.length,
11990
+ " checkpoint",
11991
+ checkpoints.length === 1 ? "" : "s"
11992
+ ] }),
11993
+ /* @__PURE__ */ jsx12(Box10, { marginTop: 1, children: /* @__PURE__ */ jsx12(
11994
+ SelectInput3,
11995
+ {
11996
+ items,
11997
+ initialIndex: selectedIndex,
11998
+ onHighlight: (item) => {
11999
+ const idx = items.findIndex((i) => i.value === item.value);
12000
+ if (idx >= 0) setSelectedIndex(idx);
12001
+ },
12002
+ onSelect: (item) => {
12003
+ if (item.value === "__start__") {
12004
+ onPick("__start__");
12005
+ } else {
12006
+ onPick(item.value);
12007
+ }
12008
+ }
12009
+ }
12010
+ ) }),
12011
+ /* @__PURE__ */ jsx12(Box10, { marginTop: 1, children: /* @__PURE__ */ jsx12(Text11, { color: theme.info.color, children: "q: cancel / go back" }) })
12012
+ ] });
12013
+ }
12014
+ function formatDate2(iso) {
12015
+ try {
12016
+ const d = new Date(iso);
12017
+ return d.toLocaleString(void 0, {
12018
+ month: "short",
12019
+ day: "numeric",
12020
+ hour: "2-digit",
12021
+ minute: "2-digit"
12022
+ });
12023
+ } catch {
12024
+ return iso;
11974
12025
  }
11975
- if (displayValue.length === 0) {
11976
- renderedValue = source_default.inverse(" ");
11977
- } else if (cursorOffset === displayValue.length) {
11978
- renderedValue += source_default.inverse(" ");
12026
+ }
12027
+ var init_checkpoint_picker = __esm({
12028
+ "src/ui/checkpoint-picker.tsx"() {
12029
+ "use strict";
12030
+ init_theme_context();
11979
12031
  }
11980
- return /* @__PURE__ */ jsx13(Text12, { children: renderedValue });
12032
+ });
12033
+
12034
+ // src/ui/task-list.tsx
12035
+ import { useEffect as useEffect4, useRef as useRef2, useState as useState7 } from "react";
12036
+ import { Box as Box11, Text as Text12 } from "ink";
12037
+ import Spinner4 from "ink-spinner";
12038
+ import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
12039
+ function TaskList({ tasks, startedAt, tokensDelta }) {
12040
+ const theme = useTheme();
12041
+ const [now2, setNow] = useState7(Date.now());
12042
+ const [celebrating, setCelebrating] = useState7(false);
12043
+ const tasksRef = useRef2(tasks);
12044
+ const prevAllDoneRef = useRef2(false);
12045
+ tasksRef.current = tasks;
12046
+ useEffect4(() => {
12047
+ if (startedAt === null) return;
12048
+ const id = setInterval(() => {
12049
+ setNow(Date.now());
12050
+ const current = tasksRef.current;
12051
+ if (current.length > 0 && current.every((t) => t.status === "completed")) {
12052
+ clearInterval(id);
12053
+ }
12054
+ }, 1e3);
12055
+ return () => clearInterval(id);
12056
+ }, [startedAt]);
12057
+ useEffect4(() => {
12058
+ const allDone2 = tasks.length > 0 && tasks.every((t) => t.status === "completed");
12059
+ if (allDone2 && !prevAllDoneRef.current) {
12060
+ setCelebrating(true);
12061
+ const id = setTimeout(() => setCelebrating(false), 1500);
12062
+ return () => clearTimeout(id);
12063
+ }
12064
+ prevAllDoneRef.current = allDone2;
12065
+ }, [tasks]);
12066
+ if (tasks.length === 0) return null;
12067
+ const active = tasks.find((t) => t.status === "in_progress");
12068
+ const done = tasks.filter((t) => t.status === "completed").length;
12069
+ const total = tasks.length;
12070
+ const allDone = done === total;
12071
+ const header = active ? active.title : allDone ? `${total} tasks done` : `${done}/${total}`;
12072
+ const elapsed = startedAt ? formatElapsed3(now2 - startedAt) : null;
12073
+ const headerStats = [elapsed, tokensDelta > 0 ? `\u2191 ${formatTokens3(tokensDelta)} tokens` : null].filter(Boolean).join(" \xB7 ");
12074
+ const visibleTasks = tasks.slice(0, MAX_VISIBLE);
12075
+ const hiddenPending = Math.max(0, tasks.length - visibleTasks.length);
12076
+ return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", marginBottom: 1, children: [
12077
+ /* @__PURE__ */ jsxs11(Box11, { children: [
12078
+ /* @__PURE__ */ jsx13(Text12, { color: celebrating ? theme.palette.success : allDone ? "green" : theme.accent, bold: true, children: celebrating ? `\u2728 ${header}` : header }),
12079
+ headerStats && /* @__PURE__ */ jsxs11(Text12, { color: theme.info.color, children: [
12080
+ " ",
12081
+ "(",
12082
+ headerStats,
12083
+ ")"
12084
+ ] })
12085
+ ] }),
12086
+ visibleTasks.map((t) => /* @__PURE__ */ jsx13(TaskRow, { task: t }, t.id)),
12087
+ hiddenPending > 0 && /* @__PURE__ */ jsxs11(Text12, { color: theme.info.color, children: [
12088
+ " ",
12089
+ "\u2026 +",
12090
+ hiddenPending,
12091
+ " more"
12092
+ ] })
12093
+ ] });
11981
12094
  }
11982
- function findPasteTokenEndingAt(value, pos, pastes) {
11983
- if (pos <= 0 || value[pos - 1] !== "]") return -1;
11984
- for (const placeholder of pastes.keys()) {
11985
- if (placeholder.length > pos) continue;
11986
- const start = pos - placeholder.length;
11987
- if (value.slice(start, pos) === placeholder) return start;
12095
+ function TaskRow({ task }) {
12096
+ const theme = useTheme();
12097
+ if (task.status === "completed") {
12098
+ return /* @__PURE__ */ jsxs11(Text12, { color: theme.info.color, children: [
12099
+ " ",
12100
+ "\u2713 ",
12101
+ /* @__PURE__ */ jsx13(Text12, { strikethrough: true, children: task.title })
12102
+ ] });
11988
12103
  }
11989
- return -1;
12104
+ if (task.status === "in_progress") {
12105
+ return /* @__PURE__ */ jsxs11(Text12, { color: theme.accent, bold: true, children: [
12106
+ " ",
12107
+ /* @__PURE__ */ jsx13(Spinner4, { type: "line" }),
12108
+ " ",
12109
+ task.title
12110
+ ] });
12111
+ }
12112
+ return /* @__PURE__ */ jsxs11(Text12, { color: theme.info.color, children: [
12113
+ " ",
12114
+ "\u2610 ",
12115
+ task.title
12116
+ ] });
11990
12117
  }
11991
- var PASTE_CHAR_THRESHOLD, PASTE_NEWLINE_THRESHOLD;
11992
- var init_text_input = __esm({
11993
- "src/ui/text-input.tsx"() {
12118
+ function formatElapsed3(ms) {
12119
+ const total = Math.floor(ms / 1e3);
12120
+ const m = Math.floor(total / 60);
12121
+ const s = total % 60;
12122
+ if (m === 0) return `${s}s`;
12123
+ return `${m}m ${s}s`;
12124
+ }
12125
+ function formatTokens3(n) {
12126
+ if (n < 1e3) return String(n);
12127
+ return `${(n / 1e3).toFixed(1)}k`;
12128
+ }
12129
+ var MAX_VISIBLE;
12130
+ var init_task_list = __esm({
12131
+ "src/ui/task-list.tsx"() {
11994
12132
  "use strict";
11995
- init_source();
11996
- PASTE_CHAR_THRESHOLD = 200;
11997
- PASTE_NEWLINE_THRESHOLD = 1;
12133
+ init_theme_context();
12134
+ MAX_VISIBLE = 6;
11998
12135
  }
11999
12136
  });
12000
12137
 
12001
12138
  // src/ui/onboarding.tsx
12002
- import { useState as useState7, useEffect as useEffect5, useCallback } from "react";
12003
- import { Box as Box12, Text as Text13, useInput as useInput4 } from "ink";
12004
- import SelectInput5 from "ink-select-input";
12139
+ import { useState as useState8, useEffect as useEffect5, useCallback as useCallback2 } from "react";
12140
+ import { Box as Box12, Text as Text13, useInput as useInput5 } from "ink";
12141
+ import SelectInput4 from "ink-select-input";
12005
12142
  import Spinner5 from "ink-spinner";
12006
12143
  import { exec } from "child_process";
12007
12144
  import { promisify as promisify2 } from "util";
12008
12145
  import { Fragment, jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
12009
12146
  function openBrowser(url) {
12010
- const platform3 = process.platform;
12011
- const cmd = platform3 === "darwin" ? `open "${url}"` : platform3 === "win32" ? `start "" "${url}"` : `xdg-open "${url}"`;
12147
+ const platform4 = process.platform;
12148
+ const cmd = platform4 === "darwin" ? `open "${url}"` : platform4 === "win32" ? `start "" "${url}"` : `xdg-open "${url}"`;
12012
12149
  exec(cmd, (err) => {
12013
12150
  if (err) {
12014
12151
  }
@@ -12022,14 +12159,14 @@ function formatRemaining(ms) {
12022
12159
  }
12023
12160
  function Onboarding({ onDone, onCancel }) {
12024
12161
  const theme = useTheme();
12025
- const [step, setStep] = useState7("mode");
12026
- const [mode, setMode] = useState7("byok");
12027
- const [accountId, setAccountId] = useState7("");
12028
- const [apiToken, setApiToken] = useState7("");
12029
- const [model, setModel] = useState7(DEFAULT_MODEL);
12030
- const [savedPath, setSavedPath] = useState7(null);
12031
- const [cloudAuth, setCloudAuth] = useState7(null);
12032
- const [pollTick, setPollTick] = useState7(0);
12162
+ const [step, setStep] = useState8("mode");
12163
+ const [mode, setMode] = useState8("byok");
12164
+ const [accountId, setAccountId] = useState8("");
12165
+ const [apiToken, setApiToken] = useState8("");
12166
+ const [model, setModel] = useState8(DEFAULT_MODEL);
12167
+ const [savedPath, setSavedPath] = useState8(null);
12168
+ const [cloudAuth, setCloudAuth] = useState8(null);
12169
+ const [pollTick, setPollTick] = useState8(0);
12033
12170
  useEffect5(() => {
12034
12171
  if (step !== "cloudAuth" || !cloudAuth) return;
12035
12172
  if (cloudAuth.phase !== "polling") return;
@@ -12072,8 +12209,8 @@ function Onboarding({ onDone, onCancel }) {
12072
12209
  clearInterval(tick);
12073
12210
  };
12074
12211
  }, [step, cloudAuth]);
12075
- useInput4(
12076
- useCallback(
12212
+ useInput5(
12213
+ useCallback2(
12077
12214
  (_input, key) => {
12078
12215
  if (key.escape && onCancel) {
12079
12216
  onCancel();
@@ -12082,7 +12219,7 @@ function Onboarding({ onDone, onCancel }) {
12082
12219
  [onCancel]
12083
12220
  )
12084
12221
  );
12085
- const startCloudAuth = useCallback(async () => {
12222
+ const startCloudAuth = useCallback2(async () => {
12086
12223
  try {
12087
12224
  const codes = await generateDeviceCodes();
12088
12225
  await registerDevice(codes);
@@ -12179,7 +12316,7 @@ function Onboarding({ onDone, onCancel }) {
12179
12316
  step === "mode" && /* @__PURE__ */ jsxs12(Fragment, { children: [
12180
12317
  /* @__PURE__ */ jsx14(Text13, { children: "How do you want to connect?" }),
12181
12318
  /* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(
12182
- SelectInput5,
12319
+ SelectInput4,
12183
12320
  {
12184
12321
  items: [
12185
12322
  { label: "Cloud (managed) \u2014 no API key needed", value: "cloud" },
@@ -12265,7 +12402,7 @@ function Onboarding({ onDone, onCancel }) {
12265
12402
  /* @__PURE__ */ jsx14(Text13, { color: theme.palette.error, children: "Authentication failed" }),
12266
12403
  /* @__PURE__ */ jsx14(Text13, { color: theme.info.color, children: cloudAuth.message }),
12267
12404
  /* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(
12268
- SelectInput5,
12405
+ SelectInput4,
12269
12406
  {
12270
12407
  items: [
12271
12408
  { label: "Retry", value: "retry" },
@@ -12544,25 +12681,17 @@ var init_worker_client = __esm({
12544
12681
  }
12545
12682
  });
12546
12683
 
12547
- // src/remote/tui-deploy.ts
12548
- var init_tui_deploy = __esm({
12549
- "src/remote/tui-deploy.ts"() {
12550
- "use strict";
12551
- init_deploy();
12552
- }
12553
- });
12554
-
12555
12684
  // src/ui/remote-dashboard.tsx
12556
- import { useEffect as useEffect6, useState as useState8 } from "react";
12557
- import { Box as Box14, Text as Text15, useInput as useInput5 } from "ink";
12558
- import SelectInput6 from "ink-select-input";
12685
+ import { useEffect as useEffect6, useState as useState9 } from "react";
12686
+ import { Box as Box14, Text as Text15, useInput as useInput6 } from "ink";
12687
+ import SelectInput5 from "ink-select-input";
12559
12688
  import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
12560
12689
  function RemoteDashboard({ onSelect, onCancel }) {
12561
12690
  const theme = useTheme();
12562
- const [sessions, setSessions] = useState8([]);
12563
- const [loading, setLoading] = useState8(true);
12564
- const [error, setError] = useState8(null);
12565
- const [refreshing, setRefreshing] = useState8(false);
12691
+ const [sessions, setSessions] = useState9([]);
12692
+ const [loading, setLoading] = useState9(true);
12693
+ const [error, setError] = useState9(null);
12694
+ const [refreshing, setRefreshing] = useState9(false);
12566
12695
  useEffect6(() => {
12567
12696
  loadSessions();
12568
12697
  }, []);
@@ -12599,7 +12728,7 @@ function RemoteDashboard({ onSelect, onCancel }) {
12599
12728
  setRefreshing(false);
12600
12729
  }
12601
12730
  }
12602
- useInput5((input, key) => {
12731
+ useInput6((input, key) => {
12603
12732
  if (input === "r" || input === "R") {
12604
12733
  void loadSessions();
12605
12734
  }
@@ -12636,7 +12765,7 @@ function RemoteDashboard({ onSelect, onCancel }) {
12636
12765
  refreshing ? "(refreshing...)" : ""
12637
12766
  ] }),
12638
12767
  /* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(
12639
- SelectInput6,
12768
+ SelectInput5,
12640
12769
  {
12641
12770
  items,
12642
12771
  onSelect: (item) => {
@@ -12677,8 +12806,8 @@ function RemoteSessionDetail({
12677
12806
  onCancel
12678
12807
  }) {
12679
12808
  const theme = useTheme();
12680
- const [cancelling, setCancelling] = useState8(false);
12681
- useInput5((input, key) => {
12809
+ const [cancelling, setCancelling] = useState9(false);
12810
+ useInput6((input, key) => {
12682
12811
  if (key.escape) {
12683
12812
  onBack();
12684
12813
  }
@@ -13575,21 +13704,21 @@ var init_save = __esm({
13575
13704
  });
13576
13705
 
13577
13706
  // src/ui/command-wizard.tsx
13578
- import { useState as useState9 } from "react";
13579
- import { Box as Box15, Text as Text16, useInput as useInput6, useWindowSize } from "ink";
13580
- import SelectInput7 from "ink-select-input";
13707
+ import { useState as useState10 } from "react";
13708
+ import { Box as Box15, Text as Text16, useInput as useInput7, useWindowSize } from "ink";
13709
+ import SelectInput6 from "ink-select-input";
13581
13710
  import { Fragment as Fragment2, jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
13582
13711
  function CommandWizard({ mode, initial, existingNames, builtinNames, onDone, onSave }) {
13583
13712
  const theme = useTheme();
13584
- const [step, setStep] = useState9("name");
13585
- const [name, setName] = useState9(initial?.name ?? "");
13586
- const [description, setDescription] = useState9(initial?.description ?? "");
13587
- const [template, setTemplate] = useState9(initial?.template ?? "");
13588
- const [cmdMode, setCmdMode] = useState9(initial?.mode);
13589
- const [cmdEffort, setCmdEffort] = useState9(initial?.effort);
13590
- const [cmdModel, setCmdModel] = useState9(initial?.model);
13591
- const [source, setSource] = useState9(initial?.source ?? "project");
13592
- const [error, setError] = useState9(null);
13713
+ const [step, setStep] = useState10("name");
13714
+ const [name, setName] = useState10(initial?.name ?? "");
13715
+ const [description, setDescription] = useState10(initial?.description ?? "");
13716
+ const [template, setTemplate] = useState10(initial?.template ?? "");
13717
+ const [cmdMode, setCmdMode] = useState10(initial?.mode);
13718
+ const [cmdEffort, setCmdEffort] = useState10(initial?.effort);
13719
+ const [cmdModel, setCmdModel] = useState10(initial?.model);
13720
+ const [source, setSource] = useState10(initial?.source ?? "project");
13721
+ const [error, setError] = useState10(null);
13593
13722
  const { columns } = useWindowSize();
13594
13723
  const totalSteps = 5;
13595
13724
  const stepIndex = step === "name" ? 1 : step === "description" ? 2 : step === "template" ? 3 : step === "advanced" || step === "mode" || step === "effort" || step === "model" ? 4 : step === "location" ? 4 : 5;
@@ -13602,7 +13731,7 @@ function CommandWizard({ mode, initial, existingNames, builtinNames, onDone, onS
13602
13731
  if (existingNames.includes(trimmed) && !isEditingSelf(trimmed)) return `/${trimmed} already exists`;
13603
13732
  return null;
13604
13733
  };
13605
- useInput6((_input, key) => {
13734
+ useInput7((_input, key) => {
13606
13735
  if (key.escape) {
13607
13736
  onDone();
13608
13737
  }
@@ -13830,7 +13959,7 @@ ${template}`;
13830
13959
  ")"
13831
13960
  ] }),
13832
13961
  /* @__PURE__ */ jsx17(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx17(
13833
- SelectInput7,
13962
+ SelectInput6,
13834
13963
  {
13835
13964
  items,
13836
13965
  onSelect: (item) => {
@@ -13859,7 +13988,7 @@ ${template}`;
13859
13988
  ] }),
13860
13989
  /* @__PURE__ */ jsx17(Text16, { color: theme.info.color, children: "Saved to file but not yet enforced at runtime" }),
13861
13990
  /* @__PURE__ */ jsx17(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx17(
13862
- SelectInput7,
13991
+ SelectInput6,
13863
13992
  {
13864
13993
  items,
13865
13994
  onSelect: (item) => {
@@ -13887,7 +14016,7 @@ ${template}`;
13887
14016
  ")"
13888
14017
  ] }),
13889
14018
  /* @__PURE__ */ jsx17(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx17(
13890
- SelectInput7,
14019
+ SelectInput6,
13891
14020
  {
13892
14021
  items,
13893
14022
  onSelect: (item) => {
@@ -13933,7 +14062,7 @@ ${template}`;
13933
14062
  ")"
13934
14063
  ] }),
13935
14064
  /* @__PURE__ */ jsx17(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx17(
13936
- SelectInput7,
14065
+ SelectInput6,
13937
14066
  {
13938
14067
  items,
13939
14068
  onSelect: (item) => {
@@ -13966,7 +14095,7 @@ ${template}`;
13966
14095
  ] }),
13967
14096
  /* @__PURE__ */ jsx17(Box15, { marginTop: 1, flexDirection: "column", children: previewContent().split("\n").map((line, i) => /* @__PURE__ */ jsx17(Text16, { color: theme.info.color, children: line || " " }, i)) }),
13968
14097
  /* @__PURE__ */ jsx17(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx17(
13969
- SelectInput7,
14098
+ SelectInput6,
13970
14099
  {
13971
14100
  items,
13972
14101
  onSelect: (item) => handleConfirm(item.value)
@@ -14422,7 +14551,7 @@ var init_context_generator = __esm({
14422
14551
 
14423
14552
  // src/ui/command-picker.tsx
14424
14553
  import { Box as Box16, Text as Text17 } from "ink";
14425
- import SelectInput8 from "ink-select-input";
14554
+ import SelectInput7 from "ink-select-input";
14426
14555
  import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
14427
14556
  function CommandPicker({ commands, title, onPick }) {
14428
14557
  const theme = useTheme();
@@ -14436,7 +14565,7 @@ function CommandPicker({ commands, title, onPick }) {
14436
14565
  /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: title }),
14437
14566
  /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select." }),
14438
14567
  /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
14439
- SelectInput8,
14568
+ SelectInput7,
14440
14569
  {
14441
14570
  items,
14442
14571
  onSelect: (item) => {
@@ -14458,11 +14587,11 @@ var init_command_picker = __esm({
14458
14587
  });
14459
14588
 
14460
14589
  // src/ui/command-list.tsx
14461
- import { Box as Box17, Text as Text18, useInput as useInput7 } from "ink";
14590
+ import { Box as Box17, Text as Text18, useInput as useInput8 } from "ink";
14462
14591
  import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
14463
14592
  function CommandList({ commands, onDone }) {
14464
14593
  const theme = useTheme();
14465
- useInput7((_input, key) => {
14594
+ useInput8((_input, key) => {
14466
14595
  if (key.escape) {
14467
14596
  onDone();
14468
14597
  }
@@ -14531,20 +14660,20 @@ var init_command_list = __esm({
14531
14660
  });
14532
14661
 
14533
14662
  // src/ui/lsp-wizard.tsx
14534
- import { useState as useState10 } from "react";
14663
+ import { useState as useState11 } from "react";
14535
14664
  import { Box as Box18, Text as Text19 } from "ink";
14536
- import SelectInput9 from "ink-select-input";
14665
+ import SelectInput8 from "ink-select-input";
14537
14666
  import { spawn as spawn3 } from "child_process";
14538
14667
  import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
14539
14668
  function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
14540
14669
  const theme = useTheme();
14541
- const [page, setPage] = useState10("main");
14542
- const [selectedPreset, setSelectedPreset] = useState10(null);
14543
- const [customName, setCustomName] = useState10("");
14544
- const [customCommand, setCustomCommand] = useState10("");
14545
- const [installState, setInstallState] = useState10({ status: "idle", output: "" });
14546
- const [pendingServers, setPendingServers] = useState10(null);
14547
- const [pendingEnabled, setPendingEnabled] = useState10(true);
14670
+ const [page, setPage] = useState11("main");
14671
+ const [selectedPreset, setSelectedPreset] = useState11(null);
14672
+ const [customName, setCustomName] = useState11("");
14673
+ const [customCommand, setCustomCommand] = useState11("");
14674
+ const [installState, setInstallState] = useState11({ status: "idle", output: "" });
14675
+ const [pendingServers, setPendingServers] = useState11(null);
14676
+ const [pendingEnabled, setPendingEnabled] = useState11(true);
14548
14677
  const runInstall = (command) => {
14549
14678
  setInstallState({ status: "running", output: "Installing..." });
14550
14679
  const child = spawn3("bash", ["-lc", command], {
@@ -14650,7 +14779,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
14650
14779
  /* @__PURE__ */ jsx20(Text19, { color: theme.accent, bold: true, children: "LSP Servers" }),
14651
14780
  /* @__PURE__ */ jsx20(Text19, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select." }),
14652
14781
  /* @__PURE__ */ jsx20(Box18, { marginTop: 1, children: /* @__PURE__ */ jsx20(
14653
- SelectInput9,
14782
+ SelectInput8,
14654
14783
  {
14655
14784
  items: mainItems,
14656
14785
  onSelect: (item) => {
@@ -14681,7 +14810,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
14681
14810
  /* @__PURE__ */ jsx20(Text19, { color: theme.accent, bold: true, children: "Add LSP Server" }),
14682
14811
  /* @__PURE__ */ jsx20(Text19, { color: theme.info.color, dimColor: false, children: "Select a language server to configure." }),
14683
14812
  /* @__PURE__ */ jsx20(Box18, { marginTop: 1, children: /* @__PURE__ */ jsx20(
14684
- SelectInput9,
14813
+ SelectInput8,
14685
14814
  {
14686
14815
  items,
14687
14816
  onSelect: (item) => {
@@ -14720,7 +14849,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
14720
14849
  ] }),
14721
14850
  installState.output && /* @__PURE__ */ jsx20(Box18, { marginTop: 1, flexDirection: "column", children: /* @__PURE__ */ jsx20(Text19, { color: isSuccess ? theme.accent : theme.error, children: installState.output.slice(-500) }) }),
14722
14851
  /* @__PURE__ */ jsx20(Box18, { marginTop: 1, children: /* @__PURE__ */ jsx20(
14723
- SelectInput9,
14852
+ SelectInput8,
14724
14853
  {
14725
14854
  items,
14726
14855
  onSelect: (item) => {
@@ -14761,7 +14890,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
14761
14890
  )
14762
14891
  ] }),
14763
14892
  /* @__PURE__ */ jsx20(Box18, { marginTop: 1, children: /* @__PURE__ */ jsx20(
14764
- SelectInput9,
14893
+ SelectInput8,
14765
14894
  {
14766
14895
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
14767
14896
  onSelect: () => setPage("add")
@@ -14790,7 +14919,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
14790
14919
  )
14791
14920
  ] }),
14792
14921
  /* @__PURE__ */ jsx20(Box18, { marginTop: 1, children: /* @__PURE__ */ jsx20(
14793
- SelectInput9,
14922
+ SelectInput8,
14794
14923
  {
14795
14924
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
14796
14925
  onSelect: () => setPage("custom-name")
@@ -14817,7 +14946,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
14817
14946
  /* @__PURE__ */ jsx20(Text19, { color: theme.accent, bold: true, children: "Save LSP Config" }),
14818
14947
  /* @__PURE__ */ jsx20(Text19, { color: theme.info.color, dimColor: false, children: "Where should this server configuration be saved?" }),
14819
14948
  /* @__PURE__ */ jsx20(Box18, { marginTop: 1, children: /* @__PURE__ */ jsx20(
14820
- SelectInput9,
14949
+ SelectInput8,
14821
14950
  {
14822
14951
  items,
14823
14952
  onSelect: (item) => {
@@ -14839,7 +14968,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
14839
14968
  /* @__PURE__ */ jsx20(Text19, { color: theme.accent, bold: true, children: "Edit LSP Server" }),
14840
14969
  /* @__PURE__ */ jsx20(Text19, { color: theme.info.color, children: "No servers configured." }),
14841
14970
  /* @__PURE__ */ jsx20(Box18, { marginTop: 1, children: /* @__PURE__ */ jsx20(
14842
- SelectInput9,
14971
+ SelectInput8,
14843
14972
  {
14844
14973
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
14845
14974
  onSelect: () => setPage("main")
@@ -14863,7 +14992,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
14863
14992
  /* @__PURE__ */ jsx20(Text19, { color: theme.accent, bold: true, children: "Edit LSP Server" }),
14864
14993
  /* @__PURE__ */ jsx20(Text19, { color: theme.info.color, dimColor: false, children: "Select a server to toggle enabled/disabled." }),
14865
14994
  /* @__PURE__ */ jsx20(Box18, { marginTop: 1, children: /* @__PURE__ */ jsx20(
14866
- SelectInput9,
14995
+ SelectInput8,
14867
14996
  {
14868
14997
  items,
14869
14998
  onSelect: (item) => {
@@ -14884,7 +15013,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
14884
15013
  /* @__PURE__ */ jsx20(Text19, { color: theme.accent, bold: true, children: "Delete LSP Server" }),
14885
15014
  /* @__PURE__ */ jsx20(Text19, { color: theme.info.color, children: "No servers configured." }),
14886
15015
  /* @__PURE__ */ jsx20(Box18, { marginTop: 1, children: /* @__PURE__ */ jsx20(
14887
- SelectInput9,
15016
+ SelectInput8,
14888
15017
  {
14889
15018
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
14890
15019
  onSelect: () => setPage("main")
@@ -14904,7 +15033,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
14904
15033
  /* @__PURE__ */ jsx20(Text19, { color: theme.accent, bold: true, children: "Delete LSP Server" }),
14905
15034
  /* @__PURE__ */ jsx20(Text19, { color: theme.info.color, dimColor: false, children: "Select a server to remove from config." }),
14906
15035
  /* @__PURE__ */ jsx20(Box18, { marginTop: 1, children: /* @__PURE__ */ jsx20(
14907
- SelectInput9,
15036
+ SelectInput8,
14908
15037
  {
14909
15038
  items,
14910
15039
  onSelect: (item) => {
@@ -14928,7 +15057,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
14928
15057
  return /* @__PURE__ */ jsx20(Text19, { color: theme.info.color, children: ` ${k.padEnd(16)} ${status} ${s.command.join(" ")}` }, k);
14929
15058
  }) }),
14930
15059
  /* @__PURE__ */ jsx20(Box18, { marginTop: 1, children: /* @__PURE__ */ jsx20(
14931
- SelectInput9,
15060
+ SelectInput8,
14932
15061
  {
14933
15062
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
14934
15063
  onSelect: () => setPage("main")
@@ -15055,7 +15184,7 @@ var init_lsp_wizard = __esm({
15055
15184
 
15056
15185
  // src/ui/theme-picker.tsx
15057
15186
  import { Box as Box19, Text as Text20 } from "ink";
15058
- import SelectInput10 from "ink-select-input";
15187
+ import SelectInput9 from "ink-select-input";
15059
15188
  import { jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
15060
15189
  function PaletteSwatches({ palette }) {
15061
15190
  const colors = [
@@ -15075,7 +15204,7 @@ function ThemePicker({ themes, onPick }) {
15075
15204
  return /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", borderStyle: "round", borderColor: current.accent, paddingX: 1, children: [
15076
15205
  /* @__PURE__ */ jsx21(Text20, { color: current.accent, bold: true, children: "Pick a theme (restart to apply)" }),
15077
15206
  /* @__PURE__ */ jsx21(Box19, { marginTop: 1, children: /* @__PURE__ */ jsx21(
15078
- SelectInput10,
15207
+ SelectInput9,
15079
15208
  {
15080
15209
  items,
15081
15210
  onSelect: (item) => {
@@ -16498,15 +16627,15 @@ __export(app_exports, {
16498
16627
  shouldOpenMentionPicker: () => shouldOpenMentionPicker,
16499
16628
  shouldOpenSlashPicker: () => shouldOpenSlashPicker
16500
16629
  });
16501
- import React14, { useState as useState11, useRef as useRef3, useEffect as useEffect7, useCallback as useCallback2 } from "react";
16502
- import { Box as Box22, Text as Text23, useApp, useInput as useInput8, render } from "ink";
16503
- import SelectInput11 from "ink-select-input";
16630
+ import React15, { useState as useState12, useRef as useRef3, useEffect as useEffect7, useCallback as useCallback3 } from "react";
16631
+ import { Box as Box22, Text as Text23, useApp, useInput as useInput9, render } from "ink";
16632
+ import SelectInput10 from "ink-select-input";
16504
16633
  import { existsSync as existsSync4, statSync as statSync4 } from "fs";
16505
16634
  import { join as join27 } from "path";
16506
16635
  import { unlink as unlink4 } from "fs/promises";
16507
16636
  import { execSync as execSync2 } from "child_process";
16508
16637
  import { spawn as spawn4 } from "child_process";
16509
- import { platform as platform2 } from "os";
16638
+ import { platform as platform3 } from "os";
16510
16639
  import fg4 from "fast-glob";
16511
16640
  import { readFileSync as readFileSync3 } from "fs";
16512
16641
  import { jsx as jsx24, jsxs as jsxs22 } from "react/jsx-runtime";
@@ -16649,7 +16778,7 @@ function gatewayUsageLookupFromConfig(cfg, meta) {
16649
16778
  };
16650
16779
  }
16651
16780
  function openBrowser2(url) {
16652
- const cmd = platform2() === "darwin" ? "open" : platform2() === "win32" ? "start" : "xdg-open";
16781
+ const cmd = platform3() === "darwin" ? "open" : platform3() === "win32" ? "start" : "xdg-open";
16653
16782
  const child = spawn4(cmd, [url], { detached: true, stdio: "ignore" });
16654
16783
  child.unref();
16655
16784
  }
@@ -16758,13 +16887,13 @@ function App({
16758
16887
  initialCloudDeviceId
16759
16888
  }) {
16760
16889
  const { exit } = useApp();
16761
- const [cfg, setCfg] = useState11(initialCfg);
16762
- const [lspScope, setLspScope] = useState11(initialLspScope);
16763
- const [lspProjectPath, setLspProjectPath] = useState11(initialLspProjectPath);
16764
- const [cloudToken, setCloudToken] = useState11(initialCloudToken);
16765
- const [cloudDeviceId, setCloudDeviceId] = useState11(initialCloudDeviceId);
16766
- const [events, setRawEvents] = useState11([]);
16767
- const setEvents = useCallback2(
16890
+ const [cfg, setCfg] = useState12(initialCfg);
16891
+ const [lspScope, setLspScope] = useState12(initialLspScope);
16892
+ const [lspProjectPath, setLspProjectPath] = useState12(initialLspProjectPath);
16893
+ const [cloudToken, setCloudToken] = useState12(initialCloudToken);
16894
+ const [cloudDeviceId, setCloudDeviceId] = useState12(initialCloudDeviceId);
16895
+ const [events, setRawEvents] = useState12([]);
16896
+ const setEvents = useCallback3(
16768
16897
  (updater) => {
16769
16898
  setRawEvents((prev) => {
16770
16899
  const next = typeof updater === "function" ? updater(prev) : updater;
@@ -16773,55 +16902,55 @@ function App({
16773
16902
  },
16774
16903
  []
16775
16904
  );
16776
- const [input, setInput] = useState11("");
16777
- const [busy, setBusy] = useState11(false);
16778
- const [usage, setUsage] = useState11(null);
16779
- const [sessionUsage, setSessionUsage] = useState11(null);
16780
- const [gatewayMeta, setGatewayMeta] = useState11(null);
16781
- const [cloudBudget, setCloudBudget] = useState11(null);
16782
- const [showReasoning, setShowReasoning] = useState11(false);
16783
- const [perm, setPerm] = useState11(null);
16784
- const [limitModal, setLimitModal] = useState11(null);
16785
- const [queue, setQueue] = useState11([]);
16786
- const [history, setHistory] = useState11([]);
16787
- const [historyIndex, setHistoryIndex] = useState11(-1);
16788
- const [draftInput, setDraftInput] = useState11("");
16789
- const [mode, setMode] = useState11("edit");
16790
- const [codeMode, setCodeMode] = useState11(false);
16905
+ const [input, setInput] = useState12("");
16906
+ const [busy, setBusy] = useState12(false);
16907
+ const [usage, setUsage] = useState12(null);
16908
+ const [sessionUsage, setSessionUsage] = useState12(null);
16909
+ const [gatewayMeta, setGatewayMeta] = useState12(null);
16910
+ const [cloudBudget, setCloudBudget] = useState12(null);
16911
+ const [showReasoning, setShowReasoning] = useState12(false);
16912
+ const [perm, setPerm] = useState12(null);
16913
+ const [limitModal, setLimitModal] = useState12(null);
16914
+ const [queue, setQueue] = useState12([]);
16915
+ const [history, setHistory] = useState12([]);
16916
+ const [historyIndex, setHistoryIndex] = useState12(-1);
16917
+ const [draftInput, setDraftInput] = useState12("");
16918
+ const [mode, setMode] = useState12("edit");
16919
+ const [codeMode, setCodeMode] = useState12(false);
16791
16920
  const filePickerEnabled = initialCfg?.filePicker ?? true;
16792
- const [effort, setEffort] = useState11(
16921
+ const [effort, setEffort] = useState12(
16793
16922
  initialCfg?.reasoningEffort ?? DEFAULT_REASONING_EFFORT
16794
16923
  );
16795
- const [resumeSessions, setResumeSessions] = useState11(null);
16796
- const [checkpointSession, setCheckpointSession] = useState11(null);
16797
- const [checkpointList, setCheckpointList] = useState11([]);
16798
- const [commandWizard, setCommandWizard] = useState11(null);
16799
- const [commandPicker, setCommandPicker] = useState11(null);
16800
- const [commandToDelete, setCommandToDelete] = useState11(null);
16801
- const [showCommandList, setShowCommandList] = useState11(false);
16802
- const [showLspWizard, setShowLspWizard] = useState11(false);
16803
- const [showRemoteDashboard, setShowRemoteDashboard] = useState11(false);
16804
- const [selectedRemoteSession, setSelectedRemoteSession] = useState11(null);
16805
- const [tasks, setTasks] = useState11([]);
16806
- const [tasksStartedAt, setTasksStartedAt] = useState11(null);
16807
- const [tasksStartTokens, setTasksStartTokens] = useState11(0);
16808
- const [turnStartedAt, setTurnStartedAt] = useState11(null);
16809
- const [turnPhase, setTurnPhase] = useState11("waiting");
16810
- const [currentToolName, setCurrentToolName] = useState11(null);
16811
- const [lastActivityAt, setLastActivityAt] = useState11(null);
16812
- const [verbose, setVerbose] = useState11(false);
16813
- const [hasUpdate, setHasUpdate] = useState11(initialUpdateResult?.hasUpdate ?? false);
16814
- const [latestVersion, setLatestVersion] = useState11(initialUpdateResult?.latestVersion ?? null);
16815
- const [theme, setTheme] = useState11(resolveTheme(initialCfg?.theme));
16816
- const [showThemePicker, setShowThemePicker] = useState11(false);
16817
- const [originalTheme, setOriginalTheme] = useState11(null);
16818
- const [skillsActive, setSkillsActive] = useState11(0);
16819
- const [memoryRecalled, setMemoryRecalled] = useState11(false);
16820
- const [intentTier, setIntentTier] = useState11(null);
16924
+ const [resumeSessions, setResumeSessions] = useState12(null);
16925
+ const [checkpointSession, setCheckpointSession] = useState12(null);
16926
+ const [checkpointList, setCheckpointList] = useState12([]);
16927
+ const [commandWizard, setCommandWizard] = useState12(null);
16928
+ const [commandPicker, setCommandPicker] = useState12(null);
16929
+ const [commandToDelete, setCommandToDelete] = useState12(null);
16930
+ const [showCommandList, setShowCommandList] = useState12(false);
16931
+ const [showLspWizard, setShowLspWizard] = useState12(false);
16932
+ const [showRemoteDashboard, setShowRemoteDashboard] = useState12(false);
16933
+ const [selectedRemoteSession, setSelectedRemoteSession] = useState12(null);
16934
+ const [tasks, setTasks] = useState12([]);
16935
+ const [tasksStartedAt, setTasksStartedAt] = useState12(null);
16936
+ const [tasksStartTokens, setTasksStartTokens] = useState12(0);
16937
+ const [turnStartedAt, setTurnStartedAt] = useState12(null);
16938
+ const [turnPhase, setTurnPhase] = useState12("waiting");
16939
+ const [currentToolName, setCurrentToolName] = useState12(null);
16940
+ const [lastActivityAt, setLastActivityAt] = useState12(null);
16941
+ const [verbose, setVerbose] = useState12(false);
16942
+ const [hasUpdate, setHasUpdate] = useState12(initialUpdateResult?.hasUpdate ?? false);
16943
+ const [latestVersion, setLatestVersion] = useState12(initialUpdateResult?.latestVersion ?? null);
16944
+ const [theme, setTheme] = useState12(resolveTheme(initialCfg?.theme));
16945
+ const [showThemePicker, setShowThemePicker] = useState12(false);
16946
+ const [originalTheme, setOriginalTheme] = useState12(null);
16947
+ const [skillsActive, setSkillsActive] = useState12(0);
16948
+ const [memoryRecalled, setMemoryRecalled] = useState12(false);
16949
+ const [intentTier, setIntentTier] = useState12(null);
16821
16950
  const skillsDirRef = useRef3(join27(process.cwd(), ".kimiflare", "skills"));
16822
- const [kimiMdStale, setKimiMdStale] = useState11(false);
16823
- const [gitBranch, setGitBranch] = useState11(null);
16824
- const [lastSessionTopic, setLastSessionTopic] = useState11(null);
16951
+ const [kimiMdStale, setKimiMdStale] = useState12(false);
16952
+ const [gitBranch, setGitBranch] = useState12(null);
16953
+ const [lastSessionTopic, setLastSessionTopic] = useState12(null);
16825
16954
  useEffect7(() => {
16826
16955
  setGitBranch(detectGitBranch());
16827
16956
  }, []);
@@ -16886,11 +17015,11 @@ ${wcagWarnings.join("\n")}` }
16886
17015
  cancelled = true;
16887
17016
  };
16888
17017
  }, [cfg?.cloudMode, initialCloudToken]);
16889
- const [cursorOffset, setCursorOffset] = useState11(0);
16890
- const [activePicker, setActivePicker] = useState11(null);
16891
- const [filePickerItems, setFilePickerItems] = useState11([]);
17018
+ const [cursorOffset, setCursorOffset] = useState12(0);
17019
+ const [activePicker, setActivePicker] = useState12(null);
17020
+ const [filePickerItems, setFilePickerItems] = useState12([]);
16892
17021
  const filePickerLoadedRef = useRef3(false);
16893
- const [customCommandsVersion, setCustomCommandsVersion] = useState11(0);
17022
+ const [customCommandsVersion, setCustomCommandsVersion] = useState12(0);
16894
17023
  const cacheStableRef = useRef3(initialCfg?.cacheStablePrompts !== false);
16895
17024
  const messagesRef = useRef3(
16896
17025
  makePrefixMessages(cacheStableRef.current, cfg?.model ?? DEFAULT_MODEL, "edit", ALL_TOOLS)
@@ -16941,11 +17070,11 @@ ${wcagWarnings.join("\n")}` }
16941
17070
  const MAX_RECENT_FILES = 10;
16942
17071
  const pickerAnchor = activePicker?.anchor ?? null;
16943
17072
  const pickerKind = activePicker?.kind ?? null;
16944
- const pickerQuery = React14.useMemo(() => {
17073
+ const pickerQuery = React15.useMemo(() => {
16945
17074
  if (pickerAnchor === null) return null;
16946
17075
  return input.slice(pickerAnchor + 1, cursorOffset);
16947
17076
  }, [input, cursorOffset, pickerAnchor]);
16948
- const filteredFileItems = React14.useMemo(() => {
17077
+ const filteredFileItems = React15.useMemo(() => {
16949
17078
  if (pickerKind !== "file" || pickerQuery === null) return [];
16950
17079
  const items = filterPickerItems(filePickerItems, pickerQuery).slice();
16951
17080
  const now2 = Date.now();
@@ -16960,7 +17089,7 @@ ${wcagWarnings.join("\n")}` }
16960
17089
  return a.name.localeCompare(b.name);
16961
17090
  });
16962
17091
  }, [pickerKind, filePickerItems, pickerQuery]);
16963
- const allSlashCommands = React14.useMemo(() => {
17092
+ const allSlashCommands = React15.useMemo(() => {
16964
17093
  const customs = customCommandsRef.current.filter((c) => !BUILTIN_COMMAND_NAMES.has(c.name.toLowerCase())).map((c) => ({
16965
17094
  name: c.name,
16966
17095
  description: c.description ?? "",
@@ -16968,7 +17097,7 @@ ${wcagWarnings.join("\n")}` }
16968
17097
  }));
16969
17098
  return [...BUILTIN_COMMANDS, ...customs];
16970
17099
  }, [customCommandsVersion]);
16971
- const filteredSlashItems = React14.useMemo(() => {
17100
+ const filteredSlashItems = React15.useMemo(() => {
16972
17101
  if (pickerKind !== "slash" || pickerQuery === null) return [];
16973
17102
  return fuzzyFilter(allSlashCommands, pickerQuery, (c) => c.name).slice(0, 50);
16974
17103
  }, [pickerKind, allSlashCommands, pickerQuery]);
@@ -17043,14 +17172,14 @@ ${wcagWarnings.join("\n")}` }
17043
17172
  setActivePicker({ ...activePicker, selected: max });
17044
17173
  }
17045
17174
  }, [filteredSlashItems.length, activePicker]);
17046
- const handlePickerUp = useCallback2(() => {
17175
+ const handlePickerUp = useCallback3(() => {
17047
17176
  setActivePicker((p) => {
17048
17177
  if (!p) return null;
17049
17178
  const next = Math.max(0, p.selected - 1);
17050
17179
  return next === p.selected ? p : { ...p, selected: next };
17051
17180
  });
17052
17181
  }, []);
17053
- const handlePickerDown = useCallback2(() => {
17182
+ const handlePickerDown = useCallback3(() => {
17054
17183
  setActivePicker((p) => {
17055
17184
  if (!p) return null;
17056
17185
  const max = p.kind === "file" ? Math.max(0, filteredFileItems.length - 1) : Math.max(0, filteredSlashItems.length - 1);
@@ -17058,7 +17187,7 @@ ${wcagWarnings.join("\n")}` }
17058
17187
  return next === p.selected ? p : { ...p, selected: next };
17059
17188
  });
17060
17189
  }, [filteredFileItems.length, filteredSlashItems.length]);
17061
- const handlePickerSelect = useCallback2(() => {
17190
+ const handlePickerSelect = useCallback3(() => {
17062
17191
  if (!activePicker) return;
17063
17192
  if (activePicker.kind === "file") {
17064
17193
  const item2 = filteredFileItems[activePicker.selected];
@@ -17077,7 +17206,7 @@ ${wcagWarnings.join("\n")}` }
17077
17206
  setActivePicker(null);
17078
17207
  submitRef.current(value);
17079
17208
  }, [activePicker, filteredFileItems, filteredSlashItems, input, cursorOffset]);
17080
- const handlePickerCancel = useCallback2(() => {
17209
+ const handlePickerCancel = useCallback3(() => {
17081
17210
  pickerCancelRef.current = cursorOffset;
17082
17211
  setActivePicker(null);
17083
17212
  }, [cursorOffset]);
@@ -17208,7 +17337,7 @@ ${wcagWarnings.join("\n")}` }
17208
17337
  }, 3e5);
17209
17338
  return () => clearInterval(id);
17210
17339
  }, []);
17211
- const reloadCustomCommands = useCallback2(async () => {
17340
+ const reloadCustomCommands = useCallback3(async () => {
17212
17341
  const { commands, warnings } = await loadCustomCommands(process.cwd());
17213
17342
  customCommandsRef.current = commands;
17214
17343
  setCustomCommandsVersion((v) => v + 1);
@@ -17335,7 +17464,7 @@ ${wcagWarnings.join("\n")}` }
17335
17464
  }, 30 * 60 * 1e3);
17336
17465
  return () => clearInterval(id);
17337
17466
  }, [cfg]);
17338
- const initMcp = useCallback2(async () => {
17467
+ const initMcp = useCallback3(async () => {
17339
17468
  if (!cfg?.mcpServers || mcpInitRef.current) return;
17340
17469
  mcpInitRef.current = true;
17341
17470
  const manager = mcpManagerRef.current;
@@ -17396,7 +17525,7 @@ ${wcagWarnings.join("\n")}` }
17396
17525
  ]);
17397
17526
  }
17398
17527
  }, [cfg]);
17399
- const initLsp = useCallback2(async () => {
17528
+ const initLsp = useCallback3(async () => {
17400
17529
  if (!cfg?.lspEnabled || !cfg?.lspServers || lspInitRef.current) {
17401
17530
  if (lspInitRef.current) return;
17402
17531
  if (!cfg?.lspEnabled) {
@@ -17467,7 +17596,7 @@ ${wcagWarnings.join("\n")}` }
17467
17596
  void initLsp();
17468
17597
  }
17469
17598
  }, [cfg, initMcp, initLsp]);
17470
- const ensureSessionId = useCallback2(() => {
17599
+ const ensureSessionId = useCallback3(() => {
17471
17600
  if (sessionIdRef.current) return sessionIdRef.current;
17472
17601
  const firstUser = messagesRef.current.find((m) => m.role === "user");
17473
17602
  let firstText = "session";
@@ -17480,7 +17609,7 @@ ${wcagWarnings.join("\n")}` }
17480
17609
  sessionIdRef.current = makeSessionId(firstText);
17481
17610
  return sessionIdRef.current;
17482
17611
  }, []);
17483
- const saveSessionSafe = useCallback2(async () => {
17612
+ const saveSessionSafe = useCallback3(async () => {
17484
17613
  if (!cfg) return;
17485
17614
  ensureSessionId();
17486
17615
  const now2 = (/* @__PURE__ */ new Date()).toISOString();
@@ -17506,13 +17635,13 @@ ${wcagWarnings.join("\n")}` }
17506
17635
  ]);
17507
17636
  }
17508
17637
  }, [cfg, ensureSessionId]);
17509
- const onIterationEnd = useCallback2(
17638
+ const onIterationEnd = useCallback3(
17510
17639
  async (messages, signal) => {
17511
17640
  if (signal.aborted) return messages;
17512
17641
  if (!shouldCompact({ messages })) return messages;
17513
17642
  if (compiledContextRef.current) {
17514
17643
  const store = artifactStoreRef.current;
17515
- const result = compactMessages({
17644
+ const result = compactMessagesViaArtifacts({
17516
17645
  messages,
17517
17646
  state: sessionStateRef.current,
17518
17647
  store
@@ -17557,7 +17686,7 @@ ${wcagWarnings.join("\n")}` }
17557
17686
  }
17558
17687
  if (cfg && !signal.aborted) {
17559
17688
  try {
17560
- const result = await compactMessages2({
17689
+ const result = await summarizeMessagesViaLlm({
17561
17690
  accountId: cfg.accountId,
17562
17691
  apiToken: cfg.apiToken,
17563
17692
  model: cfg.model,
@@ -17584,7 +17713,7 @@ ${wcagWarnings.join("\n")}` }
17584
17713
  },
17585
17714
  [cfg]
17586
17715
  );
17587
- useInput8((inputChar, key) => {
17716
+ useInput9((inputChar, key) => {
17588
17717
  if (key.ctrl && inputChar === "c") {
17589
17718
  logger.info("input:ctrl+c", {
17590
17719
  busy: busyRef.current,
@@ -17609,8 +17738,11 @@ ${wcagWarnings.join("\n")}` }
17609
17738
  isAbortingRef.current = true;
17610
17739
  supervisorRef.current.killTurn();
17611
17740
  activeScopeRef.current.abort("user_stopped");
17612
- setQueue([]);
17613
17741
  setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "(interrupted)" }]);
17742
+ for (const [toolId] of pendingToolCallsRef.current) {
17743
+ updateTool(toolId, { status: "cancelled" });
17744
+ }
17745
+ pendingToolCallsRef.current.clear();
17614
17746
  void saveSessionSafe();
17615
17747
  setTasks([]);
17616
17748
  setTasksStartedAt(null);
@@ -17640,8 +17772,11 @@ ${wcagWarnings.join("\n")}` }
17640
17772
  setLimitModal(null);
17641
17773
  }
17642
17774
  activeScopeRef.current.abort("user_stopped");
17643
- setQueue([]);
17644
17775
  setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "(interrupted)" }]);
17776
+ for (const [toolId] of pendingToolCallsRef.current) {
17777
+ updateTool(toolId, { status: "cancelled" });
17778
+ }
17779
+ pendingToolCallsRef.current.clear();
17645
17780
  setTasks([]);
17646
17781
  setTasksStartedAt(null);
17647
17782
  setTasksStartTokens(0);
@@ -17686,7 +17821,6 @@ ${wcagWarnings.join("\n")}` }
17686
17821
  isAbortingRef.current = true;
17687
17822
  supervisorRef.current.killTurn();
17688
17823
  activeScopeRef.current.abort("user_stopped");
17689
- setQueue([]);
17690
17824
  setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "(interrupted)" }]);
17691
17825
  void saveSessionSafe();
17692
17826
  setTasks([]);
@@ -17698,7 +17832,7 @@ ${wcagWarnings.join("\n")}` }
17698
17832
  void lspManagerRef.current.stopAll().finally(() => exit());
17699
17833
  }
17700
17834
  };
17701
- const flushAssistantUpdates = useCallback2(() => {
17835
+ const flushAssistantUpdates = useCallback3(() => {
17702
17836
  flushTimeoutRef.current = null;
17703
17837
  const pending = pendingTextRef.current;
17704
17838
  if (pending.size === 0) return;
@@ -17716,7 +17850,7 @@ ${wcagWarnings.join("\n")}` }
17716
17850
  })
17717
17851
  );
17718
17852
  }, []);
17719
- const updateAssistant = useCallback2(
17853
+ const updateAssistant = useCallback3(
17720
17854
  (id, patch) => {
17721
17855
  const result = patch({ text: "", reasoning: "" });
17722
17856
  const assistantResult = result;
@@ -17745,7 +17879,7 @@ ${wcagWarnings.join("\n")}` }
17745
17879
  },
17746
17880
  [flushAssistantUpdates]
17747
17881
  );
17748
- const updateTool = useCallback2(
17882
+ const updateTool = useCallback3(
17749
17883
  (id, patch) => {
17750
17884
  setEvents(
17751
17885
  (evts) => evts.map(
@@ -17755,11 +17889,11 @@ ${wcagWarnings.join("\n")}` }
17755
17889
  },
17756
17890
  []
17757
17891
  );
17758
- const updateGatewayMeta = useCallback2((meta) => {
17892
+ const updateGatewayMeta = useCallback3((meta) => {
17759
17893
  gatewayMetaRef.current = meta;
17760
17894
  setGatewayMeta(meta);
17761
17895
  }, []);
17762
- const runCompact = useCallback2(async () => {
17896
+ const runCompact = useCallback3(async () => {
17763
17897
  if (!cfg) return;
17764
17898
  if (busy) {
17765
17899
  setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "can't compact while model is running" }]);
@@ -17773,7 +17907,7 @@ ${wcagWarnings.join("\n")}` }
17773
17907
  try {
17774
17908
  if (compiledContextRef.current) {
17775
17909
  const store = artifactStoreRef.current;
17776
- const result = compactMessages({
17910
+ const result = compactMessagesViaArtifacts({
17777
17911
  messages: messagesRef.current,
17778
17912
  state: sessionStateRef.current,
17779
17913
  store
@@ -17802,7 +17936,7 @@ ${wcagWarnings.join("\n")}` }
17802
17936
  await saveSessionSafe();
17803
17937
  }
17804
17938
  } else {
17805
- const result = await compactMessages2({
17939
+ const result = await summarizeMessagesViaLlm({
17806
17940
  accountId: cfg.accountId,
17807
17941
  apiToken: cfg.apiToken,
17808
17942
  model: cfg.model,
@@ -17855,11 +17989,11 @@ ${wcagWarnings.join("\n")}` }
17855
17989
  pendingToolCallsRef.current.clear();
17856
17990
  }
17857
17991
  }, [cfg, busy, saveSessionSafe]);
17858
- const openResumePicker = useCallback2(async () => {
17992
+ const openResumePicker = useCallback3(async () => {
17859
17993
  const sessions = await listSessions(200, process.cwd());
17860
17994
  setResumeSessions(sessions);
17861
17995
  }, []);
17862
- const runInit = useCallback2(async () => {
17996
+ const runInit = useCallback3(async () => {
17863
17997
  if (!cfg) return;
17864
17998
  if (busy) {
17865
17999
  setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "can't /init while model is running" }]);
@@ -17957,15 +18091,27 @@ ${wcagWarnings.join("\n")}` }
17957
18091
  id: call.id,
17958
18092
  name: call.function.name,
17959
18093
  args: call.function.arguments,
17960
- status: "running",
18094
+ status: "queued",
17961
18095
  render: renderMeta,
17962
18096
  expanded: false
17963
18097
  }
17964
18098
  ]);
17965
18099
  },
18100
+ onToolWillExecute: (id) => {
18101
+ setTurnPhase("executing");
18102
+ setCurrentToolName(pendingToolCallsRef.current.get(id) ?? null);
18103
+ setLastActivityAt(Date.now());
18104
+ updateTool(id, { status: "running", startedAt: Date.now() });
18105
+ },
17966
18106
  onToolResult: (r) => {
17967
18107
  pendingToolCallsRef.current.delete(r.tool_call_id);
17968
- updateTool(r.tool_call_id, { status: r.ok ? "done" : "error", result: r.content });
18108
+ setLastActivityAt(Date.now());
18109
+ if (pendingToolCallsRef.current.size === 0) {
18110
+ setTurnPhase("waiting");
18111
+ setCurrentToolName(null);
18112
+ }
18113
+ const isDenied = typeof r.content === "string" && r.content.startsWith("Permission denied");
18114
+ updateTool(r.tool_call_id, { status: isDenied ? "rejected" : r.ok ? "done" : "error", result: r.content });
17969
18115
  },
17970
18116
  onUsage: (u) => {
17971
18117
  usageRef.current = u;
@@ -18132,7 +18278,7 @@ ${wcagWarnings.join("\n")}` }
18132
18278
  pendingToolCallsRef.current.clear();
18133
18279
  }
18134
18280
  }, [cfg, busy, updateAssistant, updateTool, updateGatewayMeta]);
18135
- const handleThemePick = useCallback2(
18281
+ const handleThemePick = useCallback3(
18136
18282
  (picked) => {
18137
18283
  setShowThemePicker(false);
18138
18284
  if (!picked) return;
@@ -18150,7 +18296,7 @@ ${wcagWarnings.join("\n")}` }
18150
18296
  },
18151
18297
  []
18152
18298
  );
18153
- const doResumeSession = useCallback2(
18299
+ const doResumeSession = useCallback3(
18154
18300
  async (filePath, checkpointId) => {
18155
18301
  try {
18156
18302
  const file = checkpointId ? (await loadSessionFromCheckpoint(filePath, checkpointId)).file : await loadSession(filePath);
@@ -18202,7 +18348,7 @@ ${wcagWarnings.join("\n")}` }
18202
18348
  },
18203
18349
  []
18204
18350
  );
18205
- const handleResumePick = useCallback2(
18351
+ const handleResumePick = useCallback3(
18206
18352
  async (picked) => {
18207
18353
  setResumeSessions(null);
18208
18354
  if (!picked) return;
@@ -18224,7 +18370,7 @@ ${wcagWarnings.join("\n")}` }
18224
18370
  },
18225
18371
  [doResumeSession]
18226
18372
  );
18227
- const handleCheckpointPick = useCallback2(
18373
+ const handleCheckpointPick = useCallback3(
18228
18374
  async (checkpointId) => {
18229
18375
  const session = checkpointSession;
18230
18376
  setCheckpointSession(null);
@@ -18243,7 +18389,7 @@ ${wcagWarnings.join("\n")}` }
18243
18389
  },
18244
18390
  [checkpointSession, doResumeSession]
18245
18391
  );
18246
- const handleSlash = useCallback2(
18392
+ const handleSlash = useCallback3(
18247
18393
  (cmd) => {
18248
18394
  const raw = cmd.trim();
18249
18395
  const [head, ...rest] = raw.split(/\s+/);
@@ -19110,7 +19256,7 @@ ${lines.join("\n")}` }]);
19110
19256
  },
19111
19257
  [cfg, exit, usage, theme, mode, openResumePicker, runCompact, runInit, initMcp, setCfg, setShowRemoteDashboard, setSelectedRemoteSession]
19112
19258
  );
19113
- const handleCommandSave = useCallback2(
19259
+ const handleCommandSave = useCallback3(
19114
19260
  async (opts2) => {
19115
19261
  setCommandWizard(null);
19116
19262
  try {
@@ -19132,7 +19278,7 @@ ${lines.join("\n")}` }]);
19132
19278
  },
19133
19279
  [commandWizard, reloadCustomCommands, setEvents]
19134
19280
  );
19135
- const handleCommandDelete = useCallback2(
19281
+ const handleCommandDelete = useCallback3(
19136
19282
  async (cmd) => {
19137
19283
  setCommandToDelete(null);
19138
19284
  try {
@@ -19151,7 +19297,7 @@ ${lines.join("\n")}` }]);
19151
19297
  },
19152
19298
  [reloadCustomCommands, setEvents]
19153
19299
  );
19154
- const processMessage = useCallback2(
19300
+ const processMessage = useCallback3(
19155
19301
  async (text, displayText, opts2) => {
19156
19302
  if (!cfg) return;
19157
19303
  let trimmed = text.trim();
@@ -19373,13 +19519,18 @@ ${lines.join("\n")}` }]);
19373
19519
  id: call.id,
19374
19520
  name: call.function.name,
19375
19521
  args: call.function.arguments,
19376
- status: "running",
19522
+ status: "queued",
19377
19523
  render: renderMeta,
19378
- expanded: false,
19379
- startedAt: Date.now()
19524
+ expanded: false
19380
19525
  }
19381
19526
  ]);
19382
19527
  },
19528
+ onToolWillExecute: (id, name) => {
19529
+ setTurnPhase("executing");
19530
+ setCurrentToolName(name);
19531
+ setLastActivityAt(Date.now());
19532
+ updateTool(id, { status: "running", startedAt: Date.now() });
19533
+ },
19383
19534
  onToolResult: (r) => {
19384
19535
  pendingToolCallsRef.current.delete(r.tool_call_id);
19385
19536
  setLastActivityAt(Date.now());
@@ -19388,7 +19539,7 @@ ${lines.join("\n")}` }]);
19388
19539
  setCurrentToolName(null);
19389
19540
  }
19390
19541
  updateTool(r.tool_call_id, {
19391
- status: r.ok ? "done" : "error",
19542
+ status: !r.ok && typeof r.content === "string" && r.content.startsWith("Permission denied") ? "rejected" : r.ok ? "done" : "error",
19392
19543
  result: r.content
19393
19544
  });
19394
19545
  },
@@ -19537,7 +19688,7 @@ ${lines.join("\n")}` }]);
19537
19688
  if (shouldCompact({ messages: messagesRef.current })) {
19538
19689
  if (compiledContextRef.current) {
19539
19690
  const store = artifactStoreRef.current;
19540
- const result = compactMessages({
19691
+ const result = compactMessagesViaArtifacts({
19541
19692
  messages: messagesRef.current,
19542
19693
  state: sessionStateRef.current,
19543
19694
  store
@@ -19557,7 +19708,7 @@ ${lines.join("\n")}` }]);
19557
19708
  }
19558
19709
  } else {
19559
19710
  try {
19560
- const result = await compactMessages2({
19711
+ const result = await summarizeMessagesViaLlm({
19561
19712
  accountId: cfg.accountId,
19562
19713
  apiToken: cfg.apiToken,
19563
19714
  model: cfg.model,
@@ -19680,23 +19831,13 @@ ${lines.join("\n")}` }]);
19680
19831
  processMessage(next.full, next.display, { queuedKey: next.key });
19681
19832
  }
19682
19833
  }, [busy, queue, processMessage]);
19683
- const submit = useCallback2(
19834
+ const submit = useCallback3(
19684
19835
  (full, display) => {
19685
19836
  const trimmedFull = full.trim();
19686
19837
  if (!trimmedFull) return;
19687
19838
  const trimmedDisplay = (display ?? full).trim() || trimmedFull;
19688
19839
  const historyEntry = trimmedDisplay;
19689
19840
  if (busyRef.current) {
19690
- if (activeScopeRef.current && !isAbortingRef.current) {
19691
- isAbortingRef.current = true;
19692
- supervisorRef.current.killTurn();
19693
- activeScopeRef.current.abort("new_message");
19694
- setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "(preempted)" }]);
19695
- setTasks([]);
19696
- setTasksStartedAt(null);
19697
- setTasksStartTokens(0);
19698
- tasksRef.current = [];
19699
- }
19700
19841
  const key = mkKey();
19701
19842
  setEvents((e) => [...e, { kind: "user", key, text: trimmedDisplay, queued: true }]);
19702
19843
  setQueue((q) => [...q, { full: trimmedFull, display: trimmedDisplay, key }]);
@@ -19881,7 +20022,7 @@ ${lines.join("\n")}` }]);
19881
20022
  ] }),
19882
20023
  /* @__PURE__ */ jsx24(Text23, { color: theme.info.color, children: commandToDelete.filepath }),
19883
20024
  /* @__PURE__ */ jsx24(Box22, { marginTop: 1, children: /* @__PURE__ */ jsx24(
19884
- SelectInput11,
20025
+ SelectInput10,
19885
20026
  {
19886
20027
  items: [
19887
20028
  { label: "Yes, delete", value: "yes", key: "yes" },
@@ -19922,6 +20063,9 @@ ${lines.join("\n")}` }]);
19922
20063
  perm.resolve(d);
19923
20064
  permResolveRef.current = null;
19924
20065
  setPerm(null);
20066
+ },
20067
+ onFeedback: (text) => {
20068
+ submitRef.current(text);
19925
20069
  }
19926
20070
  }
19927
20071
  ) : limitModal ? /* @__PURE__ */ jsx24(
@@ -20070,8 +20214,8 @@ var init_app = __esm({
20070
20214
  init_loop();
20071
20215
  init_supervisor();
20072
20216
  init_system_prompt();
20073
- init_compact();
20074
- init_compaction();
20217
+ init_llm_summarize();
20218
+ init_artifact_compaction();
20075
20219
  init_session_state();
20076
20220
  init_executor();
20077
20221
  init_manager3();
@@ -20095,7 +20239,7 @@ var init_app = __esm({
20095
20239
  init_config();
20096
20240
  init_worker_client();
20097
20241
  init_session_store();
20098
- init_tui_deploy();
20242
+ init_deploy();
20099
20243
  init_tui_auth();
20100
20244
  init_remote_dashboard();
20101
20245
  init_mode();