kimiflare 0.41.0 → 0.43.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
@@ -204,7 +204,8 @@ async function loadConfig() {
204
204
  plumbingModel: envPlumbingModel ?? parsed.plumbingModel,
205
205
  codeMode: envCodeMode ?? parsed.codeMode,
206
206
  costAttribution: envCostAttribution ?? parsed.costAttribution ?? false,
207
- filePicker: envFilePicker ?? parsed.filePicker ?? true
207
+ filePicker: envFilePicker ?? parsed.filePicker ?? true,
208
+ theme: parsed.theme
208
209
  };
209
210
  }
210
211
  if (parsed.accountId && parsed.apiToken) {
@@ -235,7 +236,8 @@ async function loadConfig() {
235
236
  codeMode: envCodeMode ?? parsed.codeMode ?? true,
236
237
  costAttribution: envCostAttribution ?? parsed.costAttribution ?? true,
237
238
  filePicker: envFilePicker ?? parsed.filePicker ?? true,
238
- cloudMode: envCloudMode ?? parsed.cloudMode
239
+ cloudMode: envCloudMode ?? parsed.cloudMode,
240
+ theme: parsed.theme
239
241
  };
240
242
  }
241
243
  } catch {
@@ -345,10 +347,11 @@ var init_lsp_config = __esm({
345
347
  });
346
348
 
347
349
  // src/util/sse.ts
348
- async function* readSSE(stream, signal) {
350
+ async function* readSSE(stream, signal, idleTimeoutMs) {
349
351
  const reader = stream.getReader();
350
352
  const decoder = new TextDecoder("utf-8");
351
353
  let buffer = "";
354
+ let lastDataAt = Date.now();
352
355
  const onAbort = () => {
353
356
  reader.cancel(new DOMException("aborted", "AbortError")).catch(() => {
354
357
  });
@@ -357,8 +360,15 @@ async function* readSSE(stream, signal) {
357
360
  try {
358
361
  while (true) {
359
362
  if (signal?.aborted) throw new DOMException("aborted", "AbortError");
363
+ if (idleTimeoutMs !== void 0 && Date.now() - lastDataAt > idleTimeoutMs) {
364
+ throw new DOMException(
365
+ `kimiflare: stream idle for ${idleTimeoutMs}ms \u2014 no data received from API`,
366
+ "TimeoutError"
367
+ );
368
+ }
360
369
  const { done, value } = await reader.read();
361
370
  if (done) break;
371
+ lastDataAt = Date.now();
362
372
  buffer += decoder.decode(value, { stream: true });
363
373
  buffer = buffer.replace(/\r\n/g, "\n");
364
374
  let sep3;
@@ -573,7 +583,7 @@ async function* runKimi(opts2) {
573
583
  const meta = readGatewayMeta(res.headers);
574
584
  if (meta) yield { type: "gateway_meta", meta };
575
585
  let lastUsage = null;
576
- for await (const ev of parseStream(res.body, opts2.signal)) {
586
+ for await (const ev of parseStream(res.body, opts2.signal, opts2.idleTimeoutMs)) {
577
587
  if (ev.type === "usage") lastUsage = ev.usage;
578
588
  yield ev;
579
589
  }
@@ -654,11 +664,12 @@ function readGatewayMeta(headers) {
654
664
  if (model) meta.model = model;
655
665
  return Object.keys(meta).length > 0 ? meta : null;
656
666
  }
657
- async function* parseStream(body, signal) {
667
+ async function* parseStream(body, signal, idleTimeoutMs = DEFAULT_IDLE_TIMEOUT_MS) {
658
668
  const toolCalls = /* @__PURE__ */ new Map();
659
669
  let lastUsage = null;
660
670
  let finishReason = null;
661
- for await (const dataStr of readSSE(body, signal)) {
671
+ let lastDataAt = Date.now();
672
+ for await (const dataStr of readSSE(body, signal, idleTimeoutMs)) {
662
673
  if (dataStr === "[DONE]") break;
663
674
  let chunk = null;
664
675
  try {
@@ -789,7 +800,7 @@ function sleep(ms, signal) {
789
800
  signal?.addEventListener("abort", onAbort, { once: true });
790
801
  });
791
802
  }
792
- var RETRYABLE_CODES, MAX_ATTEMPTS;
803
+ var RETRYABLE_CODES, MAX_ATTEMPTS, DEFAULT_IDLE_TIMEOUT_MS;
793
804
  var init_client = __esm({
794
805
  "src/agent/client.ts"() {
795
806
  "use strict";
@@ -799,6 +810,7 @@ var init_client = __esm({
799
810
  init_messages();
800
811
  RETRYABLE_CODES = /* @__PURE__ */ new Set([3040]);
801
812
  MAX_ATTEMPTS = 5;
813
+ DEFAULT_IDLE_TIMEOUT_MS = 6e4;
802
814
  }
803
815
  });
804
816
 
@@ -1070,7 +1082,8 @@ async function logTurnDebug(ctx) {
1070
1082
  shadowStrip: ctx.shadowStrip,
1071
1083
  durationMs: ctx.durationMs,
1072
1084
  intentClassification: ctx.intentClassification,
1073
- codeMode: ctx.codeMode
1085
+ codeMode: ctx.codeMode,
1086
+ selectedSkills: ctx.selectedSkills?.map((s) => s.name)
1074
1087
  });
1075
1088
  }
1076
1089
  var LOG_VERSION;
@@ -2304,7 +2317,8 @@ ${sandboxResult.output}` : `${warningPrefix}${sandboxResult.output}`;
2304
2317
  shadowStrip: shadowStripMetrics,
2305
2318
  durationMs: Math.round(performance.now() - turnStart),
2306
2319
  intentClassification: opts2.intentClassification,
2307
- codeMode: opts2.codeMode
2320
+ codeMode: opts2.codeMode,
2321
+ selectedSkills: opts2.selectedSkills
2308
2322
  });
2309
2323
  }
2310
2324
  if (budgetExhausted) {
@@ -2624,7 +2638,12 @@ ${toolsBlock}`;
2624
2638
  Project context from ${ctx.name} (${ctx.lineCount} lines, treat as authoritative):
2625
2639
  ${ctx.content.trim()}` : "";
2626
2640
  const modeBlock = opts2.mode ? systemPromptForMode(opts2.mode) : "";
2627
- return env2 + "\n\n" + tools + lspBlock + contextBlock + modeBlock;
2641
+ const skillsBlock = opts2.selectedSkills && opts2.selectedSkills.length > 0 ? `
2642
+
2643
+ Active skills for this turn:
2644
+ ${opts2.selectedSkills.map((s) => `--- ${s.name} ---
2645
+ ${s.body}`).join("\n\n")}` : "";
2646
+ return env2 + "\n\n" + tools + lspBlock + contextBlock + modeBlock + skillsBlock;
2628
2647
  }
2629
2648
  function buildSystemPrompt(opts2) {
2630
2649
  return buildStaticPrefix(opts2) + "\n\n" + buildSessionPrefix(opts2);
@@ -5004,8 +5023,8 @@ async function saveCloudCredentials(creds) {
5004
5023
  }
5005
5024
  async function clearCloudCredentials() {
5006
5025
  try {
5007
- const { unlink: unlink4 } = await import("fs/promises");
5008
- await unlink4(cloudCredPath());
5026
+ const { unlink: unlink5 } = await import("fs/promises");
5027
+ await unlink5(cloudCredPath());
5009
5028
  } catch {
5010
5029
  }
5011
5030
  }
@@ -6917,10 +6936,18 @@ var init_narrative = __esm({
6917
6936
  });
6918
6937
 
6919
6938
  // src/ui/tool-view.tsx
6920
- import React2 from "react";
6939
+ import React2, { useEffect, useState } from "react";
6921
6940
  import { Box as Box2, Text as Text2 } from "ink";
6922
6941
  import Spinner from "ink-spinner";
6923
6942
  import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
6943
+ function formatElapsed(ms) {
6944
+ const total = Math.floor(ms / 1e3);
6945
+ if (total < 1) return "<1s";
6946
+ const m = Math.floor(total / 60);
6947
+ const s = total % 60;
6948
+ if (m === 0) return `${s}s`;
6949
+ return `${m}m ${s}s`;
6950
+ }
6924
6951
  function firstLine(s) {
6925
6952
  const line = s.split("\n").find((l) => l.trim().length > 0) ?? "";
6926
6953
  return line.length <= 120 ? line : line.slice(0, 120) + "\u2026";
@@ -6933,10 +6960,20 @@ var init_tool_view = __esm({
6933
6960
  init_paths();
6934
6961
  init_theme_context();
6935
6962
  init_narrative();
6936
- ToolView = React2.memo(function ToolView2({ evt, verbose }) {
6963
+ ToolView = React2.memo(function ToolView2({ evt, verbose, isRepeated }) {
6937
6964
  const theme = useTheme();
6965
+ const [now2, setNow] = useState(Date.now());
6966
+ useEffect(() => {
6967
+ if (evt.startedAt === void 0) return;
6968
+ if (evt.status !== "running") {
6969
+ setNow(Date.now());
6970
+ return;
6971
+ }
6972
+ const id = setInterval(() => setNow(Date.now()), 1e3);
6973
+ return () => clearInterval(id);
6974
+ }, [evt.status, evt.startedAt]);
6938
6975
  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" });
6939
- const title = evt.render?.title ?? (() => {
6976
+ let title = evt.render?.title ?? (() => {
6940
6977
  try {
6941
6978
  const args = evt.args ? JSON.parse(evt.args) : {};
6942
6979
  return humanizeToolTitle(evt.name, args);
@@ -6944,6 +6981,9 @@ var init_tool_view = __esm({
6944
6981
  return humanizeToolTitle(evt.name);
6945
6982
  }
6946
6983
  })();
6984
+ if (evt.startedAt !== void 0) {
6985
+ title += ` \xB7 ${formatElapsed(now2 - evt.startedAt)}`;
6986
+ }
6947
6987
  const expand = Boolean(evt.expanded || verbose);
6948
6988
  const lines = evt.result ? evt.result.split("\n") : [];
6949
6989
  const showLimit = verbose ? 200 : 20;
@@ -6951,7 +6991,8 @@ var init_tool_view = __esm({
6951
6991
  /* @__PURE__ */ jsxs2(Text2, { children: [
6952
6992
  statusIcon,
6953
6993
  " ",
6954
- /* @__PURE__ */ jsx3(Text2, { color: theme.info.color, children: title })
6994
+ /* @__PURE__ */ jsx3(Text2, { color: theme.info.color, children: title }),
6995
+ isRepeated ? /* @__PURE__ */ jsx3(Text2, { color: theme.warn, children: " \u26A0 repeated" }) : null
6955
6996
  ] }),
6956
6997
  evt.render?.diff ? /* @__PURE__ */ jsx3(Box2, { marginLeft: 2, children: /* @__PURE__ */ jsx3(DiffView, { ...evt.render.diff }) }) : null,
6957
6998
  evt.result && expand ? /* @__PURE__ */ jsxs2(
@@ -7027,6 +7068,15 @@ function parseBlocks(src) {
7027
7068
  out.push({ kind: "quote", text: quoteLines.join("\n") });
7028
7069
  continue;
7029
7070
  }
7071
+ if (/^\s*\d+\.\s+/.test(line)) {
7072
+ const items = [];
7073
+ while (i < lines.length && /^\s*\d+\.\s+/.test(lines[i])) {
7074
+ items.push(lines[i].replace(/^\s*\d+\.\s+/, ""));
7075
+ i++;
7076
+ }
7077
+ out.push({ kind: "numbered", items });
7078
+ continue;
7079
+ }
7030
7080
  if (/^\s*[-*]\s+/.test(line)) {
7031
7081
  const items = [];
7032
7082
  while (i < lines.length && /^\s*[-*]\s+/.test(lines[i])) {
@@ -7036,9 +7086,23 @@ function parseBlocks(src) {
7036
7086
  out.push({ kind: "bullet", items });
7037
7087
  continue;
7038
7088
  }
7089
+ if (i + 1 < lines.length && /^\|/.test(line) && /^\|[\s\-:|]+\|$/.test(lines[i + 1])) {
7090
+ const headerLine = line;
7091
+ const headers = headerLine.split("|").slice(1, -1).map((h) => h.trim());
7092
+ i += 2;
7093
+ const rows = [];
7094
+ while (i < lines.length && /^\|/.test(lines[i])) {
7095
+ rows.push(
7096
+ lines[i].split("|").slice(1, -1).map((c) => c.trim())
7097
+ );
7098
+ i++;
7099
+ }
7100
+ out.push({ kind: "table", headers, rows });
7101
+ continue;
7102
+ }
7039
7103
  const paraLines = [line];
7040
7104
  i++;
7041
- while (i < lines.length && lines[i].trim() !== "" && !/^(#{1,3})\s+/.test(lines[i]) && !/^\s*[-*]\s+/.test(lines[i]) && !/^\s*>\s?/.test(lines[i]) && !/^```/.test(lines[i])) {
7105
+ while (i < lines.length && lines[i].trim() !== "" && !/^(#{1,3})\s+/.test(lines[i]) && !/^\s*[-*]\s+/.test(lines[i]) && !/^\s*\d+\.\s+/.test(lines[i]) && !/^\s*>\s?/.test(lines[i]) && !/^```/.test(lines[i]) && !/^\|/.test(lines[i])) {
7042
7106
  paraLines.push(lines[i]);
7043
7107
  i++;
7044
7108
  }
@@ -7051,7 +7115,18 @@ function renderInline(src, theme) {
7051
7115
  return segments.map((seg, i) => {
7052
7116
  if (seg.kind === "bold") return /* @__PURE__ */ jsx4(Text3, { bold: true, children: seg.text }, i);
7053
7117
  if (seg.kind === "italic") return /* @__PURE__ */ jsx4(Text3, { italic: true, children: seg.text }, i);
7054
- if (seg.kind === "code") return /* @__PURE__ */ jsx4(Text3, { color: theme.tool, children: seg.text }, i);
7118
+ if (seg.kind === "code") {
7119
+ const color = theme.codeInline ?? theme.tool;
7120
+ return /* @__PURE__ */ jsx4(Text3, { color, children: seg.text }, i);
7121
+ }
7122
+ if (seg.kind === "strikethrough") {
7123
+ const color = theme.strikethrough ?? theme.muted?.color ?? theme.palette.secondary;
7124
+ return /* @__PURE__ */ jsx4(Text3, { strikethrough: true, color, children: seg.text }, i);
7125
+ }
7126
+ if (seg.kind === "link") {
7127
+ const color = theme.link ?? theme.accent;
7128
+ return /* @__PURE__ */ jsx4(Text3, { underline: true, color, children: seg.text }, i);
7129
+ }
7055
7130
  return /* @__PURE__ */ jsx4(Text3, { children: seg.text }, i);
7056
7131
  });
7057
7132
  }
@@ -7076,6 +7151,30 @@ function parseInline(src) {
7076
7151
  continue;
7077
7152
  }
7078
7153
  }
7154
+ if (ch === "~" && src[i + 1] === "~") {
7155
+ const end = src.indexOf("~~", i + 2);
7156
+ if (end > i + 1) {
7157
+ flush();
7158
+ out.push({ kind: "strikethrough", text: src.slice(i + 2, end) });
7159
+ i = end + 2;
7160
+ continue;
7161
+ }
7162
+ }
7163
+ if (ch === "[") {
7164
+ const closeBracket = src.indexOf("]", i + 1);
7165
+ const openParen = closeBracket >= 0 ? src.indexOf("(", closeBracket) : -1;
7166
+ const closeParen = openParen >= 0 ? src.indexOf(")", openParen) : -1;
7167
+ if (closeParen > openParen && openParen === closeBracket + 1) {
7168
+ flush();
7169
+ out.push({
7170
+ kind: "link",
7171
+ text: src.slice(i + 1, closeBracket),
7172
+ url: src.slice(openParen + 1, closeParen)
7173
+ });
7174
+ i = closeParen + 1;
7175
+ continue;
7176
+ }
7177
+ }
7079
7178
  if (ch === "*" && src[i + 1] === "*") {
7080
7179
  const end = src.indexOf("**", i + 2);
7081
7180
  if (end > i + 1) {
@@ -7135,11 +7234,53 @@ var init_markdown = __esm({
7135
7234
  /* @__PURE__ */ jsx4(Text3, { children: renderInline(item, theme) })
7136
7235
  ] }, i)) });
7137
7236
  }
7237
+ if (block.kind === "numbered") {
7238
+ return /* @__PURE__ */ jsx4(Box3, { flexDirection: "column", children: block.items.map((item, idx) => /* @__PURE__ */ jsxs3(Box3, { children: [
7239
+ /* @__PURE__ */ jsxs3(Text3, { color: theme.accent, children: [
7240
+ " ",
7241
+ idx + 1,
7242
+ ". "
7243
+ ] }),
7244
+ /* @__PURE__ */ jsx4(Text3, { children: renderInline(item, theme) })
7245
+ ] }, idx)) });
7246
+ }
7138
7247
  if (block.kind === "quote") {
7139
- return /* @__PURE__ */ jsx4(Box3, { marginLeft: 2, children: /* @__PURE__ */ jsx4(Text3, { color: theme.info.color, italic: true, children: renderInline(block.text, theme) }) });
7248
+ const quoteColor = theme.blockquote?.color ?? theme.info.color;
7249
+ const dim = theme.blockquote?.dim ?? false;
7250
+ return /* @__PURE__ */ jsx4(Box3, { marginLeft: 2, children: /* @__PURE__ */ jsx4(Text3, { color: quoteColor, dimColor: dim, italic: true, children: renderInline(block.text, theme) }) });
7140
7251
  }
7141
7252
  if (block.kind === "code") {
7142
- return /* @__PURE__ */ jsx4(Box3, { flexDirection: "column", marginLeft: 2, children: block.text.split("\n").map((l, i) => /* @__PURE__ */ jsx4(Text3, { color: theme.tool, children: l }, i)) });
7253
+ const codeColor = theme.codeBlock ?? theme.tool;
7254
+ return /* @__PURE__ */ jsx4(Box3, { flexDirection: "column", marginLeft: 2, children: block.text.split("\n").map((l, i) => /* @__PURE__ */ jsx4(Text3, { color: codeColor, children: l }, i)) });
7255
+ }
7256
+ if (block.kind === "table") {
7257
+ const borderColor = theme.tableBorder ?? theme.accent;
7258
+ const headerColor = theme.tableHeader ?? theme.accent;
7259
+ const cellColor = theme.tableCell ?? theme.palette.foreground;
7260
+ const colCount = block.headers.length;
7261
+ return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", marginLeft: 2, children: [
7262
+ /* @__PURE__ */ jsxs3(Box3, { children: [
7263
+ /* @__PURE__ */ jsx4(Text3, { color: borderColor, children: "\u2502 " }),
7264
+ block.headers.map((h, ci) => /* @__PURE__ */ jsxs3(React3.Fragment, { children: [
7265
+ /* @__PURE__ */ jsx4(Text3, { bold: true, color: headerColor, children: h }),
7266
+ ci < colCount - 1 && /* @__PURE__ */ jsx4(Text3, { color: borderColor, children: " \u2502 " })
7267
+ ] }, ci)),
7268
+ /* @__PURE__ */ jsx4(Text3, { color: borderColor, children: " \u2502" })
7269
+ ] }),
7270
+ /* @__PURE__ */ jsx4(Box3, { children: /* @__PURE__ */ jsxs3(Text3, { color: borderColor, children: [
7271
+ "\u251C",
7272
+ Array(colCount).fill("\u2500".repeat(8)).join("\u253C"),
7273
+ "\u2524"
7274
+ ] }) }),
7275
+ block.rows.map((row, ri) => /* @__PURE__ */ jsxs3(Box3, { children: [
7276
+ /* @__PURE__ */ jsx4(Text3, { color: borderColor, children: "\u2502 " }),
7277
+ row.map((cell, ci) => /* @__PURE__ */ jsxs3(React3.Fragment, { children: [
7278
+ /* @__PURE__ */ jsx4(Text3, { color: cellColor, children: cell }),
7279
+ ci < colCount - 1 && /* @__PURE__ */ jsx4(Text3, { color: borderColor, children: " \u2502 " })
7280
+ ] }, ci)),
7281
+ /* @__PURE__ */ jsx4(Text3, { color: borderColor, children: " \u2502" })
7282
+ ] }, ri))
7283
+ ] });
7143
7284
  }
7144
7285
  return /* @__PURE__ */ jsx4(Text3, { children: renderInline(block.text, theme) });
7145
7286
  });
@@ -7151,6 +7292,9 @@ import React4 from "react";
7151
7292
  import { Box as Box4, Text as Text4, Static } from "ink";
7152
7293
  import Spinner2 from "ink-spinner";
7153
7294
  import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
7295
+ function toolSignature(name, args) {
7296
+ return `${name}:${args}`;
7297
+ }
7154
7298
  var ChatView, EventView;
7155
7299
  var init_chat = __esm({
7156
7300
  "src/ui/chat.tsx"() {
@@ -7162,6 +7306,17 @@ var init_chat = __esm({
7162
7306
  const theme = useTheme();
7163
7307
  const finalized = [];
7164
7308
  const active = [];
7309
+ const toolCounts = /* @__PURE__ */ new Map();
7310
+ for (const e of events) {
7311
+ if (e.kind === "tool") {
7312
+ const sig = toolSignature(e.name, e.args);
7313
+ toolCounts.set(sig, (toolCounts.get(sig) ?? 0) + 1);
7314
+ }
7315
+ }
7316
+ const repeatedSigs = /* @__PURE__ */ new Set();
7317
+ for (const [sig, count] of toolCounts) {
7318
+ if (count >= 3) repeatedSigs.add(sig);
7319
+ }
7165
7320
  for (let i = 0; i < events.length; i++) {
7166
7321
  const e = events[i];
7167
7322
  if (suppressTools && e.kind === "tool") continue;
@@ -7177,14 +7332,14 @@ var init_chat = __esm({
7177
7332
  return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
7178
7333
  /* @__PURE__ */ jsx5(Static, { items: finalized, children: (item) => /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
7179
7334
  item.showSeparator && /* @__PURE__ */ jsx5(Box4, { marginY: 1, children: /* @__PURE__ */ jsx5(Text4, { color: theme.info.color, children: "\u2500".repeat(40) }) }),
7180
- /* @__PURE__ */ jsx5(EventView, { evt: item.evt, showReasoning, verbose })
7335
+ /* @__PURE__ */ jsx5(EventView, { evt: item.evt, showReasoning, verbose, repeatedSigs })
7181
7336
  ] }, item.id) }),
7182
7337
  active.map((e, i) => {
7183
7338
  const prevEvt = i > 0 ? active[i - 1] : finalized[finalized.length - 1]?.evt;
7184
7339
  const showSeparator = e.kind === "user" && prevEvt && (prevEvt.kind === "assistant" || prevEvt.kind === "tool");
7185
7340
  return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
7186
7341
  showSeparator && /* @__PURE__ */ jsx5(Box4, { marginY: 1, children: /* @__PURE__ */ jsx5(Text4, { color: theme.info.color, children: "\u2500".repeat(40) }) }),
7187
- /* @__PURE__ */ jsx5(EventView, { evt: e, showReasoning, verbose })
7342
+ /* @__PURE__ */ jsx5(EventView, { evt: e, showReasoning, verbose, repeatedSigs })
7188
7343
  ] }, e.key);
7189
7344
  })
7190
7345
  ] });
@@ -7192,7 +7347,8 @@ var init_chat = __esm({
7192
7347
  EventView = React4.memo(function EventView2({
7193
7348
  evt,
7194
7349
  showReasoning,
7195
- verbose
7350
+ verbose,
7351
+ repeatedSigs
7196
7352
  }) {
7197
7353
  const theme = useTheme();
7198
7354
  if (evt.kind === "user") {
@@ -7222,7 +7378,8 @@ var init_chat = __esm({
7222
7378
  ] });
7223
7379
  }
7224
7380
  if (evt.kind === "tool") {
7225
- return /* @__PURE__ */ jsx5(ToolView, { evt, verbose });
7381
+ const isRepeated = repeatedSigs?.has(toolSignature(evt.name, evt.args)) ?? false;
7382
+ return /* @__PURE__ */ jsx5(ToolView, { evt, verbose, isRepeated });
7226
7383
  }
7227
7384
  if (evt.kind === "info") {
7228
7385
  return /* @__PURE__ */ jsxs4(Text4, { color: theme.info.color, children: [
@@ -7236,6 +7393,22 @@ var init_chat = __esm({
7236
7393
  evt.text
7237
7394
  ] });
7238
7395
  }
7396
+ if (evt.kind === "meta") {
7397
+ const parts = [];
7398
+ if (evt.intentTier) {
7399
+ parts.push(
7400
+ evt.intentTier === "light" ? "Quick thought" : evt.intentTier === "medium" ? "Deep dive" : "Heavy lifting"
7401
+ );
7402
+ }
7403
+ if (evt.skillsActive !== void 0 && evt.skillsActive > 0) {
7404
+ parts.push(`${evt.skillsActive} skill${evt.skillsActive === 1 ? "" : "s"} on deck`);
7405
+ }
7406
+ if (evt.memoryRecalled) {
7407
+ parts.push("Memory recalled");
7408
+ }
7409
+ if (parts.length === 0) return null;
7410
+ return /* @__PURE__ */ jsx5(Text4, { color: theme.info.color, dimColor: true, children: parts.join(" \xB7 ") });
7411
+ }
7239
7412
  if (evt.kind === "activity") {
7240
7413
  return /* @__PURE__ */ jsxs4(Text4, { italic: true, color: theme.info.dim ? theme.info.color : theme.palette.secondary, children: [
7241
7414
  "~ ",
@@ -7269,24 +7442,34 @@ var init_pricing = __esm({
7269
7442
  });
7270
7443
 
7271
7444
  // src/ui/status.tsx
7272
- import { useEffect, useState } from "react";
7445
+ import { useEffect as useEffect2, useState as useState2 } from "react";
7273
7446
  import { Box as Box5, Text as Text5 } from "ink";
7274
7447
  import Spinner3 from "ink-spinner";
7275
7448
  import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
7276
- function StatusBar({ model, usage, sessionUsage, thinking, turnStartedAt, mode, effort, contextLimit, hasUpdate, latestVersion, gatewayMeta, codeMode, cloudMode, cloudBudget, kimiMdStale }) {
7449
+ function StatusBar({ model, usage, sessionUsage, thinking, turnStartedAt, mode, effort, contextLimit, hasUpdate, latestVersion, gatewayMeta, codeMode, cloudMode, cloudBudget, skillsActive, memoryRecalled, phase, currentTool, lastActivityAt, kimiMdStale }) {
7277
7450
  const theme = useTheme();
7278
- const [now2, setNow] = useState(Date.now());
7451
+ const [now2, setNow] = useState2(Date.now());
7279
7452
  const modeColor = mode === "plan" ? theme.modeBadge.plan : mode === "auto" ? theme.modeBadge.auto : theme.modeBadge.edit;
7280
7453
  const warn = usage && usage.prompt_tokens / contextLimit >= 0.8;
7281
- useEffect(() => {
7454
+ useEffect2(() => {
7282
7455
  if (!thinking || turnStartedAt === null) return;
7283
7456
  const id = setInterval(() => setNow(Date.now()), 1e3);
7284
7457
  return () => clearInterval(id);
7285
7458
  }, [thinking, turnStartedAt]);
7286
- const elapsed = turnStartedAt !== null ? formatElapsed(now2 - turnStartedAt) : null;
7459
+ const elapsed = turnStartedAt !== null ? formatElapsed2(now2 - turnStartedAt) : null;
7287
7460
  const leftParts = [`${shortModel(model)}`, effort];
7288
7461
  if (cloudMode) leftParts.push("CLOUD");
7289
7462
  if (codeMode) leftParts.push("CODE");
7463
+ const labelParts = [];
7464
+ if (skillsActive !== void 0 && skillsActive > 0) {
7465
+ labelParts.push(`${skillsActive} skill${skillsActive === 1 ? "" : "s"} on deck`);
7466
+ }
7467
+ if (memoryRecalled) {
7468
+ labelParts.push("Memory recalled");
7469
+ }
7470
+ const phaseLabel = phase === "generating" ? "generating" : phase === "executing" ? `executing ${currentTool ?? ""}` : phase === "waiting" ? "waiting" : "thinking";
7471
+ const idleMs = lastActivityAt && thinking ? now2 - lastActivityAt : 0;
7472
+ const idleLabel = idleMs > 3e4 ? ` (idle ${formatElapsed2(Math.floor(idleMs / 1e3))})` : "";
7290
7473
  return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
7291
7474
  /* @__PURE__ */ jsxs5(Box5, { children: [
7292
7475
  /* @__PURE__ */ jsxs5(Text5, { color: modeColor, bold: true, children: [
@@ -7298,13 +7481,15 @@ function StatusBar({ model, usage, sessionUsage, thinking, turnStartedAt, mode,
7298
7481
  thinking ? /* @__PURE__ */ jsxs5(Text5, { color: theme.spinner, children: [
7299
7482
  /* @__PURE__ */ jsx6(Spinner3, { type: "dots" }),
7300
7483
  " ",
7301
- "thinking",
7302
- elapsed ? ` \xB7 ${elapsed}` : ""
7484
+ phaseLabel,
7485
+ elapsed ? ` \xB7 ${elapsed}` : "",
7486
+ idleLabel
7303
7487
  ] }) : /* @__PURE__ */ jsxs5(Text5, { color: theme.info.color, children: [
7304
7488
  leftParts.join(" \xB7 "),
7305
7489
  " \xB7 ready"
7306
7490
  ] })
7307
7491
  ] }),
7492
+ labelParts.length > 0 && /* @__PURE__ */ jsx6(Box5, { children: /* @__PURE__ */ jsx6(Text5, { color: theme.info.color, dimColor: true, children: labelParts.join(" \xB7 ") }) }),
7308
7493
  usage && /* @__PURE__ */ jsxs5(Box5, { children: [
7309
7494
  /* @__PURE__ */ jsx6(Text5, { color: theme.info.color, children: buildRightParts(usage, contextLimit, sessionUsage, gatewayMeta, cloudMode, cloudBudget).join(" \xB7 ") }),
7310
7495
  warn ? /* @__PURE__ */ jsxs5(Text5, { color: theme.warn, bold: true, children: [
@@ -7370,7 +7555,7 @@ function shortModel(m) {
7370
7555
  const last = m.split("/").at(-1) ?? m;
7371
7556
  return last;
7372
7557
  }
7373
- function formatElapsed(ms) {
7558
+ function formatElapsed2(ms) {
7374
7559
  const total = Math.floor(ms / 1e3);
7375
7560
  const m = Math.floor(total / 60);
7376
7561
  const s = total % 60;
@@ -7460,14 +7645,14 @@ var init_limit_modal = __esm({
7460
7645
  });
7461
7646
 
7462
7647
  // src/ui/resume-picker.tsx
7463
- import { useState as useState2 } from "react";
7648
+ import { useState as useState3 } from "react";
7464
7649
  import { Box as Box8, Text as Text8, useWindowSize } from "ink";
7465
7650
  import SelectInput3 from "ink-select-input";
7466
7651
  import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
7467
7652
  function ResumePicker({ sessions, onPick }) {
7468
7653
  const theme = useTheme();
7469
7654
  const { rows } = useWindowSize();
7470
- const [page, setPage] = useState2(0);
7655
+ const [page, setPage] = useState3(0);
7471
7656
  const pageSize = Math.max(MIN_PAGE_SIZE, rows - HEADER_ROWS - FOOTER_ROWS);
7472
7657
  const totalPages = Math.max(1, Math.ceil(sessions.length / pageSize));
7473
7658
  const safePage = Math.min(page, totalPages - 1);
@@ -7549,16 +7734,16 @@ var init_resume_picker = __esm({
7549
7734
  });
7550
7735
 
7551
7736
  // src/ui/task-list.tsx
7552
- import { useEffect as useEffect2, useRef, useState as useState3 } from "react";
7737
+ import { useEffect as useEffect3, useRef, useState as useState4 } from "react";
7553
7738
  import { Box as Box9, Text as Text9 } from "ink";
7554
7739
  import Spinner4 from "ink-spinner";
7555
7740
  import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
7556
7741
  function TaskList({ tasks, startedAt, tokensDelta }) {
7557
7742
  const theme = useTheme();
7558
- const [now2, setNow] = useState3(Date.now());
7743
+ const [now2, setNow] = useState4(Date.now());
7559
7744
  const tasksRef = useRef(tasks);
7560
7745
  tasksRef.current = tasks;
7561
- useEffect2(() => {
7746
+ useEffect3(() => {
7562
7747
  if (startedAt === null) return;
7563
7748
  const id = setInterval(() => {
7564
7749
  setNow(Date.now());
@@ -7575,7 +7760,7 @@ function TaskList({ tasks, startedAt, tokensDelta }) {
7575
7760
  const total = tasks.length;
7576
7761
  const allDone = done === total;
7577
7762
  const header = active ? active.title : allDone ? `${total} tasks done` : `${done}/${total}`;
7578
- const elapsed = startedAt ? formatElapsed2(now2 - startedAt) : null;
7763
+ const elapsed = startedAt ? formatElapsed3(now2 - startedAt) : null;
7579
7764
  const headerStats = [elapsed, tokensDelta > 0 ? `\u2191 ${formatTokens2(tokensDelta)} tokens` : null].filter(Boolean).join(" \xB7 ");
7580
7765
  const visibleTasks = tasks.slice(0, MAX_VISIBLE);
7581
7766
  const hiddenPending = Math.max(0, tasks.length - visibleTasks.length);
@@ -7621,7 +7806,7 @@ function TaskRow({ task }) {
7621
7806
  task.title
7622
7807
  ] });
7623
7808
  }
7624
- function formatElapsed2(ms) {
7809
+ function formatElapsed3(ms) {
7625
7810
  const total = Math.floor(ms / 1e3);
7626
7811
  const m = Math.floor(total / 60);
7627
7812
  const s = total % 60;
@@ -8162,7 +8347,7 @@ var init_source = __esm({
8162
8347
  });
8163
8348
 
8164
8349
  // src/ui/text-input.tsx
8165
- import { useState as useState4, useEffect as useEffect3, useRef as useRef2 } from "react";
8350
+ import { useState as useState5, useEffect as useEffect4, useRef as useRef2 } from "react";
8166
8351
  import { Text as Text10, useInput } from "ink";
8167
8352
  import { jsx as jsx11 } from "react/jsx-runtime";
8168
8353
  function shouldTreatAsPaste(input) {
@@ -8204,14 +8389,14 @@ function CustomTextInput({
8204
8389
  onPickerSelect,
8205
8390
  onPickerCancel
8206
8391
  }) {
8207
- const [internalCursor, setInternalCursor] = useState4(value.length);
8392
+ const [internalCursor, setInternalCursor] = useState5(value.length);
8208
8393
  const cursorOffset = controlledCursor ?? internalCursor;
8209
8394
  const setCursorOffset = (offset) => {
8210
8395
  setInternalCursor(offset);
8211
8396
  onCursorChange?.(offset);
8212
8397
  };
8213
8398
  const pastesRef = useRef2(/* @__PURE__ */ new Map());
8214
- useEffect3(() => {
8399
+ useEffect4(() => {
8215
8400
  if (!focus) return;
8216
8401
  const next = cursorOffset > value.length ? value.length : cursorOffset;
8217
8402
  if (next !== cursorOffset) {
@@ -8396,7 +8581,7 @@ var init_text_input = __esm({
8396
8581
  });
8397
8582
 
8398
8583
  // src/ui/onboarding.tsx
8399
- import { useState as useState5, useEffect as useEffect4, useCallback } from "react";
8584
+ import { useState as useState6, useEffect as useEffect5, useCallback } from "react";
8400
8585
  import { Box as Box10, Text as Text11, useInput as useInput2 } from "ink";
8401
8586
  import SelectInput4 from "ink-select-input";
8402
8587
  import Spinner5 from "ink-spinner";
@@ -8419,15 +8604,15 @@ function formatRemaining(ms) {
8419
8604
  }
8420
8605
  function Onboarding({ onDone, onCancel }) {
8421
8606
  const theme = useTheme();
8422
- const [step, setStep] = useState5("mode");
8423
- const [mode, setMode] = useState5("byok");
8424
- const [accountId, setAccountId] = useState5("");
8425
- const [apiToken, setApiToken] = useState5("");
8426
- const [model, setModel] = useState5(DEFAULT_MODEL);
8427
- const [savedPath, setSavedPath] = useState5(null);
8428
- const [cloudAuth, setCloudAuth] = useState5(null);
8429
- const [pollTick, setPollTick] = useState5(0);
8430
- useEffect4(() => {
8607
+ const [step, setStep] = useState6("mode");
8608
+ const [mode, setMode] = useState6("byok");
8609
+ const [accountId, setAccountId] = useState6("");
8610
+ const [apiToken, setApiToken] = useState6("");
8611
+ const [model, setModel] = useState6(DEFAULT_MODEL);
8612
+ const [savedPath, setSavedPath] = useState6(null);
8613
+ const [cloudAuth, setCloudAuth] = useState6(null);
8614
+ const [pollTick, setPollTick] = useState6(0);
8615
+ useEffect5(() => {
8431
8616
  if (step !== "cloudAuth" || !cloudAuth) return;
8432
8617
  if (cloudAuth.phase !== "polling") return;
8433
8618
  let cancelled = false;
@@ -8788,7 +8973,7 @@ var init_onboarding = __esm({
8788
8973
  // src/ui/welcome.tsx
8789
8974
  import { Box as Box11, Text as Text12 } from "ink";
8790
8975
  import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
8791
- function Welcome({ accountId }) {
8976
+ function Welcome({ accountId, cloudMode }) {
8792
8977
  const theme = useTheme();
8793
8978
  return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", marginBottom: 1, children: [
8794
8979
  /* @__PURE__ */ jsxs11(Box11, { marginBottom: 1, children: [
@@ -8798,7 +8983,7 @@ function Welcome({ accountId }) {
8798
8983
  "Ready when you are."
8799
8984
  ] })
8800
8985
  ] }),
8801
- accountId && /* @__PURE__ */ jsx13(Box11, { marginBottom: 1, children: /* @__PURE__ */ jsxs11(Text12, { color: theme.info.color, children: [
8986
+ accountId && !cloudMode && /* @__PURE__ */ jsx13(Box11, { marginBottom: 1, children: /* @__PURE__ */ jsxs11(Text12, { color: theme.info.color, children: [
8802
8987
  " ",
8803
8988
  "Check your Cloudflare billing: https://dash.cloudflare.com/",
8804
8989
  accountId,
@@ -8829,237 +9014,6 @@ var init_welcome = __esm({
8829
9014
  }
8830
9015
  });
8831
9016
 
8832
- // src/ui/help-menu.tsx
8833
- import { useState as useState6 } from "react";
8834
- import { Box as Box12, Text as Text13, useInput as useInput3 } from "ink";
8835
- import SelectInput5 from "ink-select-input";
8836
- import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
8837
- function HelpMenu({ customCommands, costAttributionEnabled, cloudMode, onDone, onCommand }) {
8838
- const theme = useTheme();
8839
- const [page, setPage] = useState6("main");
8840
- const customs = customCommands ?? [];
8841
- useInput3((_input, key) => {
8842
- if (key.escape) {
8843
- if (page !== "main") {
8844
- setPage("main");
8845
- } else {
8846
- onDone();
8847
- }
8848
- }
8849
- });
8850
- const handleSelect = (command) => {
8851
- onCommand(command);
8852
- onDone();
8853
- };
8854
- const categories = cloudMode ? CATEGORIES.filter((c) => c.key !== "gateway") : CATEGORIES;
8855
- if (page === "main") {
8856
- const items2 = categories.map((cat) => ({
8857
- label: cat.label,
8858
- value: cat.key,
8859
- key: cat.key
8860
- }));
8861
- if (customs.length > 0) {
8862
- items2.push({ label: "Run custom commands", value: "custom", key: "custom" });
8863
- }
8864
- items2.push({ label: "(close)", value: "__close__", key: "__close__" });
8865
- return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
8866
- /* @__PURE__ */ jsx14(Text13, { color: theme.accent, bold: true, children: "Help" }),
8867
- /* @__PURE__ */ jsx14(Text13, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select, Esc to close." }),
8868
- /* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(
8869
- SelectInput5,
8870
- {
8871
- items: items2,
8872
- onSelect: (item) => {
8873
- if (item.value === "__close__") {
8874
- onDone();
8875
- } else {
8876
- setPage(item.value);
8877
- }
8878
- }
8879
- }
8880
- ) }),
8881
- /* @__PURE__ */ jsx14(Box12, { marginTop: 1, flexDirection: "column", children: SINGLE_COMMANDS.map((cmd) => /* @__PURE__ */ jsx14(Text13, { color: theme.info.color, dimColor: false, children: ` ${cmd.command.padEnd(20)} ${cmd.description}` }, cmd.command)) }),
8882
- /* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(Text13, { color: theme.info.color, dimColor: false, children: "keys: ctrl-c interrupt/exit \xB7 ctrl-r toggle reasoning \xB7 ctrl-o verbose \xB7 shift+tab cycle mode \xB7 \u2191/\u2193 history" }) })
8883
- ] });
8884
- }
8885
- if (page === "custom") {
8886
- const items2 = customs.map((c) => ({
8887
- label: `${`/${c.name}`.padEnd(28)} ${c.description ?? ""}`.trimEnd(),
8888
- value: `/${c.name}`,
8889
- key: c.name
8890
- }));
8891
- items2.push({ label: "\u2190 Back", value: "__back__", key: "__back__" });
8892
- return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
8893
- /* @__PURE__ */ jsx14(Text13, { color: theme.accent, bold: true, children: "Custom commands" }),
8894
- /* @__PURE__ */ jsx14(Text13, { color: theme.info.color, dimColor: false, children: customs.length === 0 ? "no custom commands found in .kimiflare/commands/" : "Arrow keys to navigate, Enter to run, Esc to go back." }),
8895
- /* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(
8896
- SelectInput5,
8897
- {
8898
- items: items2,
8899
- onSelect: (item) => {
8900
- if (item.value === "__back__") {
8901
- setPage("main");
8902
- } else {
8903
- handleSelect(item.value);
8904
- }
8905
- }
8906
- }
8907
- ) })
8908
- ] });
8909
- }
8910
- const category = categories.find((c) => c.key === page);
8911
- const selectable = category.commands.filter((cmd) => cmd.selectable !== false);
8912
- const staticCmds = category.commands.filter((cmd) => cmd.selectable === false);
8913
- const items = selectable.map((cmd) => ({
8914
- label: `${cmd.command.padEnd(28)} ${cmd.description}`,
8915
- value: cmd.command,
8916
- key: cmd.command
8917
- }));
8918
- items.push({ label: "\u2190 Back", value: "__back__", key: "__back__" });
8919
- return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
8920
- /* @__PURE__ */ jsx14(Text13, { color: theme.accent, bold: true, children: category.label }),
8921
- /* @__PURE__ */ jsx14(Text13, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to execute, Esc to go back." }),
8922
- /* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(
8923
- SelectInput5,
8924
- {
8925
- items,
8926
- onSelect: (item) => {
8927
- if (item.value === "__back__") {
8928
- setPage("main");
8929
- } else {
8930
- handleSelect(item.value);
8931
- }
8932
- }
8933
- }
8934
- ) }),
8935
- staticCmds.length > 0 && /* @__PURE__ */ jsx14(Box12, { marginTop: 1, flexDirection: "column", children: staticCmds.map((cmd) => /* @__PURE__ */ jsx14(Text13, { color: theme.info.color, children: ` ${cmd.command.padEnd(28)} ${cmd.description}` }, cmd.command)) })
8936
- ] });
8937
- }
8938
- var CATEGORIES, SINGLE_COMMANDS;
8939
- var init_help_menu = __esm({
8940
- "src/ui/help-menu.tsx"() {
8941
- "use strict";
8942
- init_theme_context();
8943
- CATEGORIES = [
8944
- {
8945
- key: "mode",
8946
- label: "Mode",
8947
- commands: [
8948
- { command: "/mode edit", description: "switch to edit mode" },
8949
- { command: "/mode plan", description: "switch to plan mode" },
8950
- { command: "/mode auto", description: "switch to auto mode" }
8951
- ]
8952
- },
8953
- {
8954
- key: "thinking",
8955
- label: "Thinking",
8956
- commands: [
8957
- { command: "/thinking low", description: "fast, lower quality" },
8958
- { command: "/thinking medium", description: "balanced" },
8959
- { command: "/thinking high", description: "slow, higher quality" }
8960
- ]
8961
- },
8962
- {
8963
- key: "session",
8964
- label: "Session",
8965
- commands: [
8966
- { command: "/resume", description: "pick a past conversation" },
8967
- { command: "/compact", description: "summarize old turns to free context" },
8968
- { command: "/clear", description: "clear current conversation" }
8969
- ]
8970
- },
8971
- {
8972
- key: "memory",
8973
- label: "Memory",
8974
- commands: [
8975
- { command: "/memory", description: "show memory stats" },
8976
- { command: "/memory on", description: "enable memory" },
8977
- { command: "/memory off", description: "disable memory" },
8978
- { command: "/memory clear", description: "wipe memories for this repo" },
8979
- { command: "/memory search <query>", description: "search stored memories", selectable: false }
8980
- ]
8981
- },
8982
- {
8983
- key: "cost",
8984
- label: "Cost",
8985
- commands: [
8986
- { command: "/cost", description: "show cost report" },
8987
- { command: "/cost on", description: "enable cost attribution by task type" },
8988
- { command: "/cost off", description: "disable cost attribution by task type" }
8989
- ]
8990
- },
8991
- {
8992
- key: "mcp",
8993
- label: "MCP",
8994
- commands: [
8995
- { command: "/mcp list", description: "list connected MCP servers and tools" },
8996
- { command: "/mcp reload", description: "reconnect all configured MCP servers" }
8997
- ]
8998
- },
8999
- {
9000
- key: "lsp",
9001
- label: "LSP",
9002
- commands: [
9003
- { command: "/lsp config", description: "add, edit, or remove language servers" },
9004
- { command: "/lsp list", description: "list active LSP servers" },
9005
- { command: "/lsp reload", description: "restart all configured LSP servers" },
9006
- { command: "/lsp scope", description: "show whether LSP config is project or global" }
9007
- ]
9008
- },
9009
- {
9010
- key: "gateway",
9011
- label: "Gateway",
9012
- commands: [
9013
- { command: "/gateway", description: "show gateway status" },
9014
- { command: "/gateway off", description: "disable AI Gateway (direct Workers AI)" },
9015
- { command: "/gateway skip-cache true", description: "enable skip-cache" },
9016
- { command: "/gateway skip-cache false", description: "disable skip-cache" },
9017
- { command: "/gateway collect-logs true", description: "enable log collection" },
9018
- { command: "/gateway collect-logs false", description: "disable log collection" },
9019
- { command: "/gateway metadata clear", description: "remove all metadata" },
9020
- { command: "/gateway <id>", description: "enable AI Gateway", selectable: false },
9021
- { command: "/gateway cache-ttl <seconds>", description: "set cache TTL", selectable: false },
9022
- { command: "/gateway metadata <key>=<value>", description: "add metadata", selectable: false }
9023
- ]
9024
- },
9025
- {
9026
- key: "info",
9027
- label: "Info",
9028
- commands: [
9029
- { command: "/cost", description: "show cost report" },
9030
- { command: "/model", description: "show current model" },
9031
- { command: "/update", description: "check for updates" },
9032
- { command: "/hello", description: "send a voice note to the creator" }
9033
- ]
9034
- },
9035
- {
9036
- key: "commands",
9037
- label: "Commands",
9038
- commands: [
9039
- { command: "/command create", description: "create a new custom slash command" },
9040
- { command: "/command edit", description: "edit an existing custom command" },
9041
- { command: "/command delete", description: "delete a custom command" },
9042
- { command: "/command list", description: "list all custom commands" }
9043
- ]
9044
- },
9045
- {
9046
- key: "config",
9047
- label: "Config",
9048
- commands: [
9049
- { command: "/init", description: "scan this repo and write a KIMI.md" },
9050
- { command: "/logout", description: "clear credentials" },
9051
- { command: "filePicker", description: "enabled by default; disable with KIMIFLARE_FILE_PICKER=0 or filePicker: false in config", selectable: false }
9052
- ]
9053
- }
9054
- ];
9055
- SINGLE_COMMANDS = [
9056
- { command: "/reasoning", description: "toggle show/hide model reasoning" },
9057
- { command: "/help", description: "show this menu" },
9058
- { command: "/exit", description: "exit kimiflare" }
9059
- ];
9060
- }
9061
- });
9062
-
9063
9017
  // src/remote/worker-client.ts
9064
9018
  var worker_client_exports = {};
9065
9019
  __export(worker_client_exports, {
@@ -9164,17 +9118,17 @@ var init_tui_deploy = __esm({
9164
9118
  });
9165
9119
 
9166
9120
  // src/ui/remote-dashboard.tsx
9167
- import { useEffect as useEffect5, useState as useState7 } from "react";
9168
- import { Box as Box13, Text as Text14, useInput as useInput4 } from "ink";
9169
- import SelectInput6 from "ink-select-input";
9170
- import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
9121
+ import { useEffect as useEffect6, useState as useState7 } from "react";
9122
+ import { Box as Box12, Text as Text13, useInput as useInput3 } from "ink";
9123
+ import SelectInput5 from "ink-select-input";
9124
+ import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
9171
9125
  function RemoteDashboard({ onSelect, onCancel }) {
9172
9126
  const theme = useTheme();
9173
9127
  const [sessions, setSessions] = useState7([]);
9174
9128
  const [loading, setLoading] = useState7(true);
9175
9129
  const [error, setError] = useState7(null);
9176
9130
  const [refreshing, setRefreshing] = useState7(false);
9177
- useEffect5(() => {
9131
+ useEffect6(() => {
9178
9132
  loadSessions();
9179
9133
  }, []);
9180
9134
  async function loadSessions() {
@@ -9210,7 +9164,7 @@ function RemoteDashboard({ onSelect, onCancel }) {
9210
9164
  setRefreshing(false);
9211
9165
  }
9212
9166
  }
9213
- useInput4((input, key) => {
9167
+ useInput3((input, key) => {
9214
9168
  if (input === "r" || input === "R") {
9215
9169
  void loadSessions();
9216
9170
  }
@@ -9223,31 +9177,31 @@ function RemoteDashboard({ onSelect, onCancel }) {
9223
9177
  value: s.sessionId
9224
9178
  }));
9225
9179
  if (loading) {
9226
- return /* @__PURE__ */ jsx15(Box13, { flexDirection: "column", padding: 1, children: /* @__PURE__ */ jsx15(Text14, { color: theme.accent, children: "Loading remote sessions..." }) });
9180
+ return /* @__PURE__ */ jsx14(Box12, { flexDirection: "column", padding: 1, children: /* @__PURE__ */ jsx14(Text13, { color: theme.accent, children: "Loading remote sessions..." }) });
9227
9181
  }
9228
9182
  if (error) {
9229
- return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", padding: 1, children: [
9230
- /* @__PURE__ */ jsxs13(Text14, { color: theme.error, children: [
9183
+ return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", padding: 1, children: [
9184
+ /* @__PURE__ */ jsxs12(Text13, { color: theme.error, children: [
9231
9185
  "Error: ",
9232
9186
  error
9233
9187
  ] }),
9234
- /* @__PURE__ */ jsx15(Text14, { dimColor: true, children: "Press R to retry, Esc to close" })
9188
+ /* @__PURE__ */ jsx14(Text13, { dimColor: true, children: "Press R to retry, Esc to close" })
9235
9189
  ] });
9236
9190
  }
9237
9191
  if (sessions.length === 0) {
9238
- return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", padding: 1, children: [
9239
- /* @__PURE__ */ jsx15(Text14, { color: theme.accent, children: "No remote sessions yet." }),
9240
- /* @__PURE__ */ jsx15(Text14, { dimColor: true, children: "Type /remote <prompt> to start one." }),
9241
- /* @__PURE__ */ jsx15(Text14, { dimColor: true, children: "Press Esc to close" })
9192
+ return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", padding: 1, children: [
9193
+ /* @__PURE__ */ jsx14(Text13, { color: theme.accent, children: "No remote sessions yet." }),
9194
+ /* @__PURE__ */ jsx14(Text13, { dimColor: true, children: "Type /remote <prompt> to start one." }),
9195
+ /* @__PURE__ */ jsx14(Text13, { dimColor: true, children: "Press Esc to close" })
9242
9196
  ] });
9243
9197
  }
9244
- return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", padding: 1, children: [
9245
- /* @__PURE__ */ jsxs13(Text14, { bold: true, color: theme.accent, children: [
9198
+ return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", padding: 1, children: [
9199
+ /* @__PURE__ */ jsxs12(Text13, { bold: true, color: theme.accent, children: [
9246
9200
  "Recent remote tasks ",
9247
9201
  refreshing ? "(refreshing...)" : ""
9248
9202
  ] }),
9249
- /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
9250
- SelectInput6,
9203
+ /* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(
9204
+ SelectInput5,
9251
9205
  {
9252
9206
  items,
9253
9207
  onSelect: (item) => {
@@ -9256,7 +9210,7 @@ function RemoteDashboard({ onSelect, onCancel }) {
9256
9210
  }
9257
9211
  }
9258
9212
  ) }),
9259
- /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(Text14, { dimColor: true, children: "\u2191\u2193 navigate \u2022 Enter select \u2022 R refresh \u2022 Esc close" }) })
9213
+ /* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(Text13, { dimColor: true, children: "\u2191\u2193 navigate \u2022 Enter select \u2022 R refresh \u2022 Esc close" }) })
9260
9214
  ] });
9261
9215
  }
9262
9216
  function formatSessionLine(s) {
@@ -9289,7 +9243,7 @@ function RemoteSessionDetail({
9289
9243
  }) {
9290
9244
  const theme = useTheme();
9291
9245
  const [cancelling, setCancelling] = useState7(false);
9292
- useInput4((input, key) => {
9246
+ useInput3((input, key) => {
9293
9247
  if (key.escape) {
9294
9248
  onBack();
9295
9249
  }
@@ -9309,50 +9263,50 @@ function RemoteSessionDetail({
9309
9263
  }
9310
9264
  }
9311
9265
  const isRunning = session.status === "running" || session.status === "pending";
9312
- return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", padding: 1, children: [
9313
- /* @__PURE__ */ jsx15(Text14, { bold: true, color: theme.accent, children: "Remote Session" }),
9314
- /* @__PURE__ */ jsxs13(Box13, { marginTop: 1, flexDirection: "column", children: [
9315
- /* @__PURE__ */ jsxs13(Text14, { children: [
9266
+ return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", padding: 1, children: [
9267
+ /* @__PURE__ */ jsx14(Text13, { bold: true, color: theme.accent, children: "Remote Session" }),
9268
+ /* @__PURE__ */ jsxs12(Box12, { marginTop: 1, flexDirection: "column", children: [
9269
+ /* @__PURE__ */ jsxs12(Text13, { children: [
9316
9270
  "ID: ",
9317
9271
  session.sessionId
9318
9272
  ] }),
9319
- /* @__PURE__ */ jsxs13(Text14, { children: [
9273
+ /* @__PURE__ */ jsxs12(Text13, { children: [
9320
9274
  "Repo: ",
9321
9275
  session.repo
9322
9276
  ] }),
9323
- /* @__PURE__ */ jsxs13(Text14, { children: [
9277
+ /* @__PURE__ */ jsxs12(Text13, { children: [
9324
9278
  "Status: ",
9325
9279
  session.status
9326
9280
  ] }),
9327
- /* @__PURE__ */ jsxs13(Text14, { children: [
9281
+ /* @__PURE__ */ jsxs12(Text13, { children: [
9328
9282
  "Prompt: ",
9329
9283
  session.prompt
9330
9284
  ] }),
9331
- session.prUrl && /* @__PURE__ */ jsxs13(Text14, { children: [
9285
+ session.prUrl && /* @__PURE__ */ jsxs12(Text13, { children: [
9332
9286
  "PR: ",
9333
9287
  session.prUrl
9334
9288
  ] }),
9335
- session.errorMessage && /* @__PURE__ */ jsxs13(Text14, { color: theme.error, children: [
9289
+ session.errorMessage && /* @__PURE__ */ jsxs12(Text13, { color: theme.error, children: [
9336
9290
  "Error: ",
9337
9291
  session.errorMessage
9338
9292
  ] }),
9339
- session.tokensUsed !== void 0 && /* @__PURE__ */ jsxs13(Text14, { children: [
9293
+ session.tokensUsed !== void 0 && /* @__PURE__ */ jsxs12(Text13, { children: [
9340
9294
  "Tokens: ",
9341
9295
  formatTokens3(session.tokensUsed),
9342
9296
  session.tokensBudget ? ` / ${formatTokens3(session.tokensBudget)}` : ""
9343
9297
  ] }),
9344
- /* @__PURE__ */ jsxs13(Text14, { children: [
9298
+ /* @__PURE__ */ jsxs12(Text13, { children: [
9345
9299
  "Created: ",
9346
9300
  new Date(session.createdAt).toLocaleString()
9347
9301
  ] }),
9348
- session.finishedAt && /* @__PURE__ */ jsxs13(Text14, { children: [
9302
+ session.finishedAt && /* @__PURE__ */ jsxs12(Text13, { children: [
9349
9303
  "Finished: ",
9350
9304
  new Date(session.finishedAt).toLocaleString()
9351
9305
  ] })
9352
9306
  ] }),
9353
- /* @__PURE__ */ jsxs13(Box13, { marginTop: 1, flexDirection: "row", gap: 2, children: [
9354
- isRunning && onCancel && /* @__PURE__ */ jsx15(Text14, { color: theme.error, children: cancelling ? "Cancelling..." : "[C] Cancel session" }),
9355
- /* @__PURE__ */ jsx15(Text14, { dimColor: true, children: "Esc back" })
9307
+ /* @__PURE__ */ jsxs12(Box12, { marginTop: 1, flexDirection: "row", gap: 2, children: [
9308
+ isRunning && onCancel && /* @__PURE__ */ jsx14(Text13, { color: theme.error, children: cancelling ? "Cancelling..." : "[C] Cancel session" }),
9309
+ /* @__PURE__ */ jsx14(Text13, { dimColor: true, children: "Esc back" })
9356
9310
  ] })
9357
9311
  ] });
9358
9312
  }
@@ -9409,6 +9363,240 @@ var init_classify = __esm({
9409
9363
  }
9410
9364
  });
9411
9365
 
9366
+ // src/skills/loader.ts
9367
+ import { readFile as readFile12, readdir as readdir3, stat as stat4 } from "fs/promises";
9368
+ import { join as join15, extname } from "path";
9369
+ import matter from "gray-matter";
9370
+ function normalizeManifest(raw, filePath) {
9371
+ const name = typeof raw.name === "string" ? raw.name : "";
9372
+ const description = typeof raw.description === "string" ? raw.description : "";
9373
+ const match = Array.isArray(raw.match) ? raw.match.filter((m) => typeof m === "string") : DEFAULTS.match;
9374
+ const scope = raw.scope === "project" ? "project" : DEFAULTS.scope;
9375
+ const priority = typeof raw.priority === "number" ? raw.priority : DEFAULTS.priority;
9376
+ const enabled = typeof raw.enabled === "boolean" ? raw.enabled : DEFAULTS.enabled;
9377
+ if (!name) {
9378
+ throw new Error(`Skill file missing required 'name' field: ${filePath}`);
9379
+ }
9380
+ return { name, description, match, scope, priority, enabled };
9381
+ }
9382
+ async function loadSkillFile(filePath) {
9383
+ const raw = await readFile12(filePath, "utf-8");
9384
+ const parsed = matter(raw);
9385
+ const manifest = normalizeManifest(parsed.data, filePath);
9386
+ const body = parsed.content.trim();
9387
+ const estimatedTokens = Math.ceil(body.length / 4);
9388
+ return {
9389
+ name: manifest.name,
9390
+ description: manifest.description,
9391
+ match: manifest.match ?? DEFAULTS.match,
9392
+ scope: manifest.scope ?? DEFAULTS.scope,
9393
+ priority: manifest.priority ?? DEFAULTS.priority,
9394
+ enabled: manifest.enabled ?? DEFAULTS.enabled,
9395
+ body,
9396
+ filePath,
9397
+ estimatedTokens
9398
+ };
9399
+ }
9400
+ async function loadSkillsFromDir(dirPath) {
9401
+ try {
9402
+ const entries = await readdir3(dirPath);
9403
+ const files = [];
9404
+ for (const entry of entries) {
9405
+ const full = join15(dirPath, entry);
9406
+ const s = await stat4(full);
9407
+ if (s.isFile() && extname(entry) === ".md") {
9408
+ files.push(full);
9409
+ }
9410
+ }
9411
+ const skills = await Promise.all(files.map(loadSkillFile));
9412
+ skills.sort((a, b) => a.priority - b.priority);
9413
+ return skills;
9414
+ } catch {
9415
+ return [];
9416
+ }
9417
+ }
9418
+ var DEFAULTS;
9419
+ var init_loader = __esm({
9420
+ "src/skills/loader.ts"() {
9421
+ "use strict";
9422
+ DEFAULTS = {
9423
+ scope: "global",
9424
+ priority: 0,
9425
+ enabled: true,
9426
+ match: []
9427
+ };
9428
+ }
9429
+ });
9430
+
9431
+ // src/skills/router.ts
9432
+ import { minimatch } from "minimatch";
9433
+ function matchSkill(skill, prompt, cwd) {
9434
+ if (!skill.enabled) return false;
9435
+ if (skill.match.length === 0) return true;
9436
+ for (const pattern of skill.match) {
9437
+ if (pattern.includes("/") || pattern.includes("*")) {
9438
+ if (minimatch(cwd, pattern) || minimatch(cwd, `**/${pattern}`)) {
9439
+ return true;
9440
+ }
9441
+ }
9442
+ if (prompt.toLowerCase().includes(pattern.toLowerCase())) {
9443
+ return true;
9444
+ }
9445
+ }
9446
+ return false;
9447
+ }
9448
+ function findConflicts(skill, memorySnippets) {
9449
+ const conflicts = [];
9450
+ for (const mem of memorySnippets) {
9451
+ const memLower = mem.toLowerCase();
9452
+ const skillLower = skill.name.toLowerCase();
9453
+ if (memLower.includes(skillLower) || skillLower.includes(memLower)) {
9454
+ conflicts.push({
9455
+ skillName: skill.name,
9456
+ memoryContent: mem.slice(0, 200),
9457
+ memoryId: ""
9458
+ // populated by caller if available
9459
+ });
9460
+ }
9461
+ }
9462
+ return conflicts;
9463
+ }
9464
+ function selectSkills(skills, options) {
9465
+ const tierBudget = TIER_BUDGETS[options.tier];
9466
+ const effectiveBudget = Math.min(tierBudget, options.maxSkillTokens);
9467
+ const matched = skills.filter((s) => matchSkill(s, options.prompt, options.cwd));
9468
+ const selected = [];
9469
+ const dropped = [];
9470
+ const allConflicts = [];
9471
+ let runningTotal = 0;
9472
+ for (const skill of matched) {
9473
+ const conflicts = findConflicts(skill, options.memorySnippets);
9474
+ allConflicts.push(...conflicts);
9475
+ if (runningTotal + skill.estimatedTokens <= effectiveBudget) {
9476
+ selected.push(skill);
9477
+ runningTotal += skill.estimatedTokens;
9478
+ } else {
9479
+ dropped.push(skill);
9480
+ }
9481
+ }
9482
+ const budgetUsed = effectiveBudget > 0 ? Math.round(runningTotal / effectiveBudget * 100) : 0;
9483
+ return {
9484
+ selectedSkills: selected,
9485
+ droppedSkills: dropped,
9486
+ totalSkillTokens: runningTotal,
9487
+ budgetUsed,
9488
+ memoryConflicts: allConflicts
9489
+ };
9490
+ }
9491
+ var TIER_BUDGETS;
9492
+ var init_router = __esm({
9493
+ "src/skills/router.ts"() {
9494
+ "use strict";
9495
+ TIER_BUDGETS = {
9496
+ light: 2e3,
9497
+ medium: 8e3,
9498
+ heavy: 24e3
9499
+ };
9500
+ }
9501
+ });
9502
+
9503
+ // src/skills/index.ts
9504
+ async function routeSkills(skillDir, opts2) {
9505
+ const skills = await loadSkillsFromDir(skillDir);
9506
+ return selectSkills(skills, opts2);
9507
+ }
9508
+ var init_skills = __esm({
9509
+ "src/skills/index.ts"() {
9510
+ "use strict";
9511
+ init_loader();
9512
+ init_router();
9513
+ }
9514
+ });
9515
+
9516
+ // src/skills/manager.ts
9517
+ import { mkdir as mkdir7, writeFile as writeFile8, unlink as unlink2, readFile as readFile13 } from "fs/promises";
9518
+ import { join as join16 } from "path";
9519
+ import matter2 from "gray-matter";
9520
+ function getSkillDirs(cwd) {
9521
+ return {
9522
+ projectDir: join16(cwd, ".kimiflare", "skills"),
9523
+ globalDir: join16(process.env.HOME ?? "", ".config", "kimiflare", "skills")
9524
+ };
9525
+ }
9526
+ async function listAllSkills(cwd) {
9527
+ const dirs = getSkillDirs(cwd);
9528
+ const [project, global] = await Promise.all([
9529
+ loadSkillsFromDir(dirs.projectDir).catch(() => []),
9530
+ loadSkillsFromDir(dirs.globalDir).catch(() => [])
9531
+ ]);
9532
+ return { project, global };
9533
+ }
9534
+ async function createSkill(opts2) {
9535
+ const dirs = getSkillDirs(opts2.cwd);
9536
+ const dir = opts2.scope === "project" ? dirs.projectDir : dirs.globalDir;
9537
+ const filepath = join16(dir, `${opts2.name}.md`);
9538
+ const frontmatter = {
9539
+ name: opts2.name,
9540
+ enabled: true,
9541
+ priority: 0
9542
+ };
9543
+ if (opts2.description) frontmatter.description = opts2.description;
9544
+ if (opts2.match && opts2.match.length > 0) frontmatter.match = opts2.match;
9545
+ const yaml = Object.entries(frontmatter).map(([k, v]) => {
9546
+ if (Array.isArray(v)) return `${k}:
9547
+ ${v.map((item) => ` - ${item}`).join("\n")}`;
9548
+ return `${k}: ${v}`;
9549
+ }).join("\n");
9550
+ const content = `---
9551
+ ${yaml}
9552
+ ---
9553
+
9554
+ # ${opts2.name}
9555
+
9556
+ Add your instructions here.
9557
+ `;
9558
+ await mkdir7(dir, { recursive: true });
9559
+ await writeFile8(filepath, content, "utf8");
9560
+ return { filepath };
9561
+ }
9562
+ async function deleteSkill(name, cwd) {
9563
+ const all = await listAllSkills(cwd);
9564
+ const skill = all.project.find((s) => s.name === name) ?? all.global.find((s) => s.name === name);
9565
+ if (!skill) throw new Error(`skill "${name}" not found`);
9566
+ await unlink2(skill.filePath);
9567
+ return { filepath: skill.filePath };
9568
+ }
9569
+ async function setSkillEnabled(name, enabled, cwd) {
9570
+ const all = await listAllSkills(cwd);
9571
+ const skill = all.project.find((s) => s.name === name) ?? all.global.find((s) => s.name === name);
9572
+ if (!skill) throw new Error(`skill "${name}" not found`);
9573
+ const raw = await readFile13(skill.filePath, "utf-8");
9574
+ const parsed = matter2(raw);
9575
+ parsed.data.enabled = enabled;
9576
+ const yaml = Object.entries(parsed.data).map(([k, v]) => {
9577
+ if (Array.isArray(v)) return `${k}:
9578
+ ${v.map((item) => ` - ${item}`).join("\n")}`;
9579
+ return `${k}: ${v}`;
9580
+ }).join("\n");
9581
+ const content = `---
9582
+ ${yaml}
9583
+ ---
9584
+ ${parsed.content}`;
9585
+ await writeFile8(skill.filePath, content, "utf8");
9586
+ return { filepath: skill.filePath };
9587
+ }
9588
+ async function findSkillFile(name, cwd) {
9589
+ const all = await listAllSkills(cwd);
9590
+ const skill = all.project.find((s) => s.name === name) ?? all.global.find((s) => s.name === name);
9591
+ return skill?.filePath ?? null;
9592
+ }
9593
+ var init_manager3 = __esm({
9594
+ "src/skills/manager.ts"() {
9595
+ "use strict";
9596
+ init_loader();
9597
+ }
9598
+ });
9599
+
9412
9600
  // src/sessions.ts
9413
9601
  var sessions_exports = {};
9414
9602
  __export(sessions_exports, {
@@ -9418,12 +9606,12 @@ __export(sessions_exports, {
9418
9606
  pruneSessions: () => pruneSessions,
9419
9607
  saveSession: () => saveSession
9420
9608
  });
9421
- import { readFile as readFile12, writeFile as writeFile8, mkdir as mkdir7, readdir as readdir3, stat as stat4 } from "fs/promises";
9609
+ import { readFile as readFile14, writeFile as writeFile9, mkdir as mkdir8, readdir as readdir4, stat as stat5 } from "fs/promises";
9422
9610
  import { homedir as homedir10 } from "os";
9423
- import { join as join15 } from "path";
9611
+ import { join as join17 } from "path";
9424
9612
  function sessionsDir2() {
9425
- const xdg = process.env.XDG_DATA_HOME || join15(homedir10(), ".local", "share");
9426
- return join15(xdg, "kimiflare", "sessions");
9613
+ const xdg = process.env.XDG_DATA_HOME || join17(homedir10(), ".local", "share");
9614
+ return join17(xdg, "kimiflare", "sessions");
9427
9615
  }
9428
9616
  function sanitize(text) {
9429
9617
  return text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40);
@@ -9435,9 +9623,9 @@ function makeSessionId(firstPrompt) {
9435
9623
  }
9436
9624
  async function saveSession(file) {
9437
9625
  const dir = sessionsDir2();
9438
- await mkdir7(dir, { recursive: true });
9439
- const path = join15(dir, `${file.id}.json`);
9440
- await writeFile8(path, JSON.stringify(file, null, 2), "utf8");
9626
+ await mkdir8(dir, { recursive: true });
9627
+ const path = join17(dir, `${file.id}.json`);
9628
+ await writeFile9(path, JSON.stringify(file, null, 2), "utf8");
9441
9629
  return path;
9442
9630
  }
9443
9631
  async function pruneSessions() {
@@ -9449,16 +9637,16 @@ async function listSessions(limit = 30, cwd) {
9449
9637
  const dir = sessionsDir2();
9450
9638
  let entries;
9451
9639
  try {
9452
- entries = await readdir3(dir);
9640
+ entries = await readdir4(dir);
9453
9641
  } catch {
9454
9642
  return [];
9455
9643
  }
9456
9644
  const summaries = [];
9457
9645
  for (const name of entries) {
9458
9646
  if (!name.endsWith(".json")) continue;
9459
- const path = join15(dir, name);
9647
+ const path = join17(dir, name);
9460
9648
  try {
9461
- const [s, raw] = await Promise.all([stat4(path), readFile12(path, "utf8")]);
9649
+ const [s, raw] = await Promise.all([stat5(path), readFile14(path, "utf8")]);
9462
9650
  const parsed = JSON.parse(raw);
9463
9651
  if (cwd && parsed.cwd !== cwd) continue;
9464
9652
  const firstUser = parsed.messages.find((m) => m.role === "user");
@@ -9478,7 +9666,7 @@ async function listSessions(limit = 30, cwd) {
9478
9666
  return summaries.slice(0, limit);
9479
9667
  }
9480
9668
  async function loadSession(filePath) {
9481
- const raw = await readFile12(filePath, "utf8");
9669
+ const raw = await readFile14(filePath, "utf8");
9482
9670
  return JSON.parse(raw);
9483
9671
  }
9484
9672
  var init_sessions = __esm({
@@ -9489,10 +9677,10 @@ var init_sessions = __esm({
9489
9677
  });
9490
9678
 
9491
9679
  // src/util/image.ts
9492
- import { readFile as readFile13 } from "fs/promises";
9680
+ import { readFile as readFile15 } from "fs/promises";
9493
9681
  import { basename as basename3 } from "path";
9494
9682
  async function encodeImageFile(filePath) {
9495
- const buf = await readFile13(filePath);
9683
+ const buf = await readFile15(filePath);
9496
9684
  if (buf.byteLength > MAX_IMAGE_BYTES) {
9497
9685
  throw new Error(
9498
9686
  `image too large (${(buf.byteLength / 1024 / 1024).toFixed(1)} MB); max is ${MAX_IMAGE_BYTES / 1024 / 1024} MB`
@@ -9528,15 +9716,15 @@ var init_image = __esm({
9528
9716
  });
9529
9717
 
9530
9718
  // src/usage-tracker.ts
9531
- import { readFile as readFile14, writeFile as writeFile9, mkdir as mkdir8 } from "fs/promises";
9719
+ import { readFile as readFile16, writeFile as writeFile10, mkdir as mkdir9 } from "fs/promises";
9532
9720
  import { homedir as homedir11 } from "os";
9533
- import { join as join16 } from "path";
9721
+ import { join as join18 } from "path";
9534
9722
  function usageDir2() {
9535
- const xdg = process.env.XDG_DATA_HOME || join16(homedir11(), ".local", "share");
9536
- return join16(xdg, "kimiflare");
9723
+ const xdg = process.env.XDG_DATA_HOME || join18(homedir11(), ".local", "share");
9724
+ return join18(xdg, "kimiflare");
9537
9725
  }
9538
9726
  function usagePath2() {
9539
- return join16(usageDir2(), "usage.json");
9727
+ return join18(usageDir2(), "usage.json");
9540
9728
  }
9541
9729
  function today2() {
9542
9730
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
@@ -9547,7 +9735,7 @@ function cutoffDate(daysBack) {
9547
9735
  }
9548
9736
  async function loadLog2() {
9549
9737
  try {
9550
- const raw = await readFile14(usagePath2(), "utf8");
9738
+ const raw = await readFile16(usagePath2(), "utf8");
9551
9739
  const parsed = JSON.parse(raw);
9552
9740
  if (parsed.version === LOG_VERSION2) return parsed;
9553
9741
  } catch {
@@ -9555,8 +9743,8 @@ async function loadLog2() {
9555
9743
  return { version: LOG_VERSION2, days: [], sessions: [] };
9556
9744
  }
9557
9745
  async function saveLog(log) {
9558
- await mkdir8(usageDir2(), { recursive: true });
9559
- await writeFile9(usagePath2(), JSON.stringify(log, null, 2), "utf8");
9746
+ await mkdir9(usageDir2(), { recursive: true });
9747
+ await writeFile10(usagePath2(), JSON.stringify(log, null, 2), "utf8");
9560
9748
  }
9561
9749
  function getOrCreateDay(log, date) {
9562
9750
  let day = log.days.find((d) => d.date === date);
@@ -9772,7 +9960,7 @@ __export(db_exports, {
9772
9960
  updateMemoryEmbedding: () => updateMemoryEmbedding
9773
9961
  });
9774
9962
  import Database from "better-sqlite3";
9775
- import { dirname as dirname7 } from "path";
9963
+ import { dirname as dirname8 } from "path";
9776
9964
  import { mkdirSync, statSync as statSync2 } from "fs";
9777
9965
  function initSchema(db) {
9778
9966
  db.exec(`
@@ -9857,7 +10045,7 @@ function openMemoryDb(dbPath) {
9857
10045
  if (dbInstance) {
9858
10046
  dbInstance.close();
9859
10047
  }
9860
- mkdirSync(dirname7(dbPath), { recursive: true });
10048
+ mkdirSync(dirname8(dbPath), { recursive: true });
9861
10049
  dbInstance = new Database(dbPath);
9862
10050
  dbInstance.pragma("journal_mode = WAL");
9863
10051
  dbInstance.pragma("foreign_keys = ON");
@@ -10507,7 +10695,7 @@ function pickTopicKey(content, existingKeys) {
10507
10695
  return normalized;
10508
10696
  }
10509
10697
  var SECRET_PATTERNS, VERIFY_SYSTEM, HYPOTHETICAL_QUERIES_SYSTEM, MemoryManager;
10510
- var init_manager3 = __esm({
10698
+ var init_manager4 = __esm({
10511
10699
  "src/memory/manager.ts"() {
10512
10700
  "use strict";
10513
10701
  init_client();
@@ -10852,16 +11040,16 @@ Context: This memory was explicitly provided by the user during a conversation.`
10852
11040
  });
10853
11041
 
10854
11042
  // src/util/state.ts
10855
- import { readFile as readFile15, writeFile as writeFile10, mkdir as mkdir9 } from "fs/promises";
11043
+ import { readFile as readFile17, writeFile as writeFile11, mkdir as mkdir10 } from "fs/promises";
10856
11044
  import { homedir as homedir12 } from "os";
10857
- import { join as join18 } from "path";
11045
+ import { join as join20 } from "path";
10858
11046
  function statePath() {
10859
- const xdg = process.env.XDG_CONFIG_HOME || join18(homedir12(), ".config");
10860
- return join18(xdg, "kimiflare", "state.json");
11047
+ const xdg = process.env.XDG_CONFIG_HOME || join20(homedir12(), ".config");
11048
+ return join20(xdg, "kimiflare", "state.json");
10861
11049
  }
10862
11050
  async function readState() {
10863
11051
  try {
10864
- const raw = await readFile15(statePath(), "utf8");
11052
+ const raw = await readFile17(statePath(), "utf8");
10865
11053
  return JSON.parse(raw);
10866
11054
  } catch {
10867
11055
  return {};
@@ -10869,8 +11057,8 @@ async function readState() {
10869
11057
  }
10870
11058
  async function writeState(state) {
10871
11059
  const path = statePath();
10872
- await mkdir9(join18(path, ".."), { recursive: true });
10873
- await writeFile10(path, JSON.stringify(state, null, 2) + "\n", "utf8");
11060
+ await mkdir10(join20(path, ".."), { recursive: true });
11061
+ await writeFile11(path, JSON.stringify(state, null, 2) + "\n", "utf8");
10874
11062
  }
10875
11063
  async function markCreatorMessageSeen(version) {
10876
11064
  const state = await readState();
@@ -10944,14 +11132,14 @@ var init_frontmatter = __esm({
10944
11132
  // src/commands/loader.ts
10945
11133
  import { open, realpath } from "fs/promises";
10946
11134
  import { homedir as homedir13 } from "os";
10947
- import { join as join19, relative as relative4, sep as sep2 } from "path";
11135
+ import { join as join21, relative as relative4, sep as sep2 } from "path";
10948
11136
  import fg3 from "fast-glob";
10949
11137
  function projectCommandsDir(cwd = process.cwd()) {
10950
- return join19(cwd, ".kimiflare", "commands");
11138
+ return join21(cwd, ".kimiflare", "commands");
10951
11139
  }
10952
11140
  function globalCommandsDir() {
10953
- const xdg = process.env.XDG_CONFIG_HOME || join19(homedir13(), ".config");
10954
- return join19(xdg, "kimiflare", "commands");
11141
+ const xdg = process.env.XDG_CONFIG_HOME || join21(homedir13(), ".config");
11142
+ return join21(xdg, "kimiflare", "commands");
10955
11143
  }
10956
11144
  async function loadCustomCommands(cwd = process.cwd()) {
10957
11145
  const warnings = [];
@@ -11090,7 +11278,7 @@ function filenameToCommandName(file, rootDir) {
11090
11278
  return parts.join("/");
11091
11279
  }
11092
11280
  var MAX_COMMAND_FILE_BYTES;
11093
- var init_loader = __esm({
11281
+ var init_loader2 = __esm({
11094
11282
  "src/commands/loader.ts"() {
11095
11283
  "use strict";
11096
11284
  init_mode();
@@ -11308,6 +11496,7 @@ var init_builtins = __esm({
11308
11496
  { name: "gateway", argHint: "[status|off|<id>|cache-ttl|skip-cache|...]", description: "Manage AI Gateway", source: "builtin" },
11309
11497
  { name: "mcp", argHint: "[list|reload]", description: "Manage MCP servers", source: "builtin" },
11310
11498
  { name: "lsp", argHint: "[config|list|reload|scope]", description: "Manage language servers", source: "builtin" },
11499
+ { name: "skills", argHint: "[list|add|edit|delete|enable|disable]", description: "Manage skills", source: "builtin" },
11311
11500
  { name: "command", argHint: "[create|edit|delete|list]", description: "Manage custom slash commands", source: "builtin" },
11312
11501
  { name: "resume", description: "Pick a past conversation to resume", source: "builtin" },
11313
11502
  { name: "compact", description: "Summarize old turns to free context", source: "builtin" },
@@ -11327,8 +11516,8 @@ var init_builtins = __esm({
11327
11516
  });
11328
11517
 
11329
11518
  // src/commands/save.ts
11330
- import { mkdir as mkdir10, writeFile as writeFile11, unlink as unlink2 } from "fs/promises";
11331
- import { dirname as dirname8 } from "path";
11519
+ import { mkdir as mkdir11, writeFile as writeFile12, unlink as unlink3 } from "fs/promises";
11520
+ import { dirname as dirname9 } from "path";
11332
11521
  async function saveCustomCommand(opts2) {
11333
11522
  const dir = opts2.source === "project" ? projectCommandsDir(opts2.cwd) : globalCommandsDir();
11334
11523
  const filepath = `${dir}/${opts2.name}.md`;
@@ -11339,26 +11528,26 @@ async function saveCustomCommand(opts2) {
11339
11528
  if (opts2.effort) data.effort = opts2.effort;
11340
11529
  const frontmatter = serializeFrontmatter(data);
11341
11530
  const content = frontmatter + opts2.template;
11342
- await mkdir10(dirname8(filepath), { recursive: true });
11343
- await writeFile11(filepath, content, "utf8");
11531
+ await mkdir11(dirname9(filepath), { recursive: true });
11532
+ await writeFile12(filepath, content, "utf8");
11344
11533
  return { filepath };
11345
11534
  }
11346
11535
  async function deleteCustomCommand(cmd) {
11347
- await unlink2(cmd.filepath);
11536
+ await unlink3(cmd.filepath);
11348
11537
  }
11349
11538
  var init_save = __esm({
11350
11539
  "src/commands/save.ts"() {
11351
11540
  "use strict";
11352
11541
  init_frontmatter();
11353
- init_loader();
11542
+ init_loader2();
11354
11543
  }
11355
11544
  });
11356
11545
 
11357
11546
  // src/ui/command-wizard.tsx
11358
11547
  import { useState as useState8 } from "react";
11359
- import { Box as Box14, Text as Text15, useInput as useInput5, useWindowSize as useWindowSize2 } from "ink";
11360
- import SelectInput7 from "ink-select-input";
11361
- import { Fragment as Fragment2, jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
11548
+ import { Box as Box13, Text as Text14, useInput as useInput4, useWindowSize as useWindowSize2 } from "ink";
11549
+ import SelectInput6 from "ink-select-input";
11550
+ import { Fragment as Fragment2, jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
11362
11551
  function CommandWizard({ mode, initial, existingNames, builtinNames, onDone, onSave }) {
11363
11552
  const theme = useTheme();
11364
11553
  const [step, setStep] = useState8("name");
@@ -11382,7 +11571,7 @@ function CommandWizard({ mode, initial, existingNames, builtinNames, onDone, onS
11382
11571
  if (existingNames.includes(trimmed) && !isEditingSelf(trimmed)) return `/${trimmed} already exists`;
11383
11572
  return null;
11384
11573
  };
11385
- useInput5((_input, key) => {
11574
+ useInput4((_input, key) => {
11386
11575
  if (key.escape) {
11387
11576
  onDone();
11388
11577
  }
@@ -11482,8 +11671,8 @@ ${template}`;
11482
11671
  const renderStep = () => {
11483
11672
  switch (step) {
11484
11673
  case "name":
11485
- return /* @__PURE__ */ jsxs14(Fragment2, { children: [
11486
- /* @__PURE__ */ jsxs14(Text15, { color: theme.accent, bold: true, children: [
11674
+ return /* @__PURE__ */ jsxs13(Fragment2, { children: [
11675
+ /* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
11487
11676
  mode === "create" ? "Create" : "Edit",
11488
11677
  " custom command \u2014 Name (",
11489
11678
  stepIndex,
@@ -11491,8 +11680,8 @@ ${template}`;
11491
11680
  totalSteps,
11492
11681
  ")"
11493
11682
  ] }),
11494
- error && /* @__PURE__ */ jsx16(Text15, { color: theme.error, children: error }),
11495
- /* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(
11683
+ error && /* @__PURE__ */ jsx15(Text14, { color: theme.error, children: error }),
11684
+ /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
11496
11685
  CustomTextInput,
11497
11686
  {
11498
11687
  value: name,
@@ -11501,11 +11690,11 @@ ${template}`;
11501
11690
  focus: true
11502
11691
  }
11503
11692
  ) }),
11504
- /* @__PURE__ */ jsx16(Text15, { color: theme.info.color, children: "letters, numbers, _ - / only; must start with a letter" })
11693
+ /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "letters, numbers, _ - / only; must start with a letter" })
11505
11694
  ] });
11506
11695
  case "description":
11507
- return /* @__PURE__ */ jsxs14(Fragment2, { children: [
11508
- /* @__PURE__ */ jsxs14(Text15, { color: theme.accent, bold: true, children: [
11696
+ return /* @__PURE__ */ jsxs13(Fragment2, { children: [
11697
+ /* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
11509
11698
  mode === "create" ? "Create" : "Edit",
11510
11699
  " custom command \u2014 Description (",
11511
11700
  stepIndex,
@@ -11513,7 +11702,7 @@ ${template}`;
11513
11702
  totalSteps,
11514
11703
  ")"
11515
11704
  ] }),
11516
- /* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(
11705
+ /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
11517
11706
  CustomTextInput,
11518
11707
  {
11519
11708
  value: description,
@@ -11522,49 +11711,49 @@ ${template}`;
11522
11711
  focus: true
11523
11712
  }
11524
11713
  ) }),
11525
- /* @__PURE__ */ jsx16(Text15, { color: theme.info.color, children: "Press Enter to skip" })
11714
+ /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Press Enter to skip" })
11526
11715
  ] });
11527
11716
  case "template": {
11528
- const guide = /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", paddingLeft: 1, children: [
11529
- /* @__PURE__ */ jsx16(Text15, { color: theme.accent, bold: true, children: "What is this?" }),
11530
- /* @__PURE__ */ jsx16(Text15, { color: theme.info.color, children: "A prompt template \u2014 instructions to the AI." }),
11531
- /* @__PURE__ */ jsxs14(Text15, { color: theme.info.color, children: [
11717
+ const guide = /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", paddingLeft: 1, children: [
11718
+ /* @__PURE__ */ jsx15(Text14, { color: theme.accent, bold: true, children: "What is this?" }),
11719
+ /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "A prompt template \u2014 instructions to the AI." }),
11720
+ /* @__PURE__ */ jsxs13(Text14, { color: theme.info.color, children: [
11532
11721
  "When you type /",
11533
11722
  name || "yourcommand",
11534
11723
  " later, this gets sent to the model."
11535
11724
  ] }),
11536
- /* @__PURE__ */ jsxs14(Box14, { marginTop: 1, flexDirection: "column", children: [
11537
- /* @__PURE__ */ jsx16(Text15, { color: theme.accent, bold: true, children: "Variables" }),
11538
- /* @__PURE__ */ jsxs14(Text15, { color: theme.info.color, children: [
11725
+ /* @__PURE__ */ jsxs13(Box13, { marginTop: 1, flexDirection: "column", children: [
11726
+ /* @__PURE__ */ jsx15(Text14, { color: theme.accent, bold: true, children: "Variables" }),
11727
+ /* @__PURE__ */ jsxs13(Text14, { color: theme.info.color, children: [
11539
11728
  " ",
11540
11729
  "$1, $2 ... \u2192 arguments you type"
11541
11730
  ] }),
11542
- /* @__PURE__ */ jsxs14(Text15, { color: theme.info.color, children: [
11731
+ /* @__PURE__ */ jsxs13(Text14, { color: theme.info.color, children: [
11543
11732
  " ",
11544
11733
  "$ARGUMENTS \u2192 everything after the command"
11545
11734
  ] })
11546
11735
  ] }),
11547
- /* @__PURE__ */ jsxs14(Box14, { marginTop: 1, flexDirection: "column", children: [
11548
- /* @__PURE__ */ jsx16(Text15, { color: theme.accent, bold: true, children: "Dynamic inlines" }),
11549
- /* @__PURE__ */ jsxs14(Text15, { color: theme.info.color, children: [
11736
+ /* @__PURE__ */ jsxs13(Box13, { marginTop: 1, flexDirection: "column", children: [
11737
+ /* @__PURE__ */ jsx15(Text14, { color: theme.accent, bold: true, children: "Dynamic inlines" }),
11738
+ /* @__PURE__ */ jsxs13(Text14, { color: theme.info.color, children: [
11550
11739
  " ",
11551
11740
  "!`git diff` \u2192 shell output inlined"
11552
11741
  ] }),
11553
- /* @__PURE__ */ jsxs14(Text15, { color: theme.info.color, children: [
11742
+ /* @__PURE__ */ jsxs13(Text14, { color: theme.info.color, children: [
11554
11743
  " ",
11555
11744
  "@README.md \u2192 file contents inlined"
11556
11745
  ] })
11557
11746
  ] }),
11558
- /* @__PURE__ */ jsxs14(Box14, { marginTop: 1, flexDirection: "column", children: [
11559
- /* @__PURE__ */ jsx16(Text15, { color: theme.accent, bold: true, children: "Example" }),
11560
- /* @__PURE__ */ jsx16(Text15, { color: theme.info.color, children: "Review this PR diff:" }),
11561
- /* @__PURE__ */ jsx16(Text15, { color: theme.info.color, children: "!`git diff main...HEAD`" }),
11562
- /* @__PURE__ */ jsx16(Text15, { color: theme.info.color, children: "Focus on: $1" })
11747
+ /* @__PURE__ */ jsxs13(Box13, { marginTop: 1, flexDirection: "column", children: [
11748
+ /* @__PURE__ */ jsx15(Text14, { color: theme.accent, bold: true, children: "Example" }),
11749
+ /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Review this PR diff:" }),
11750
+ /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "!`git diff main...HEAD`" }),
11751
+ /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Focus on: $1" })
11563
11752
  ] })
11564
11753
  ] });
11565
- const inputArea = /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", flexGrow: 1, children: [
11566
- error && /* @__PURE__ */ jsx16(Text15, { color: theme.error, children: error }),
11567
- /* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(
11754
+ const inputArea = /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", flexGrow: 1, children: [
11755
+ error && /* @__PURE__ */ jsx15(Text14, { color: theme.error, children: error }),
11756
+ /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
11568
11757
  CustomTextInput,
11569
11758
  {
11570
11759
  value: template,
@@ -11574,13 +11763,13 @@ ${template}`;
11574
11763
  enablePaste: true
11575
11764
  }
11576
11765
  ) }),
11577
- columns < 100 && /* @__PURE__ */ jsxs14(Fragment2, { children: [
11578
- /* @__PURE__ */ jsx16(Text15, { color: theme.info.color, children: "Paste multi-line templates with Ctrl+V." }),
11579
- /* @__PURE__ */ jsx16(Text15, { color: theme.info.color, children: "Variables: $1 $2 ... $ARGUMENTS Shell: !`cmd` File: @path" })
11766
+ columns < 100 && /* @__PURE__ */ jsxs13(Fragment2, { children: [
11767
+ /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Paste multi-line templates with Ctrl+V." }),
11768
+ /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Variables: $1 $2 ... $ARGUMENTS Shell: !`cmd` File: @path" })
11580
11769
  ] })
11581
11770
  ] });
11582
- return /* @__PURE__ */ jsxs14(Fragment2, { children: [
11583
- /* @__PURE__ */ jsxs14(Text15, { color: theme.accent, bold: true, children: [
11771
+ return /* @__PURE__ */ jsxs13(Fragment2, { children: [
11772
+ /* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
11584
11773
  mode === "create" ? "Create" : "Edit",
11585
11774
  " custom command \u2014 Template (",
11586
11775
  stepIndex,
@@ -11588,10 +11777,10 @@ ${template}`;
11588
11777
  totalSteps,
11589
11778
  ")"
11590
11779
  ] }),
11591
- columns >= 100 ? /* @__PURE__ */ jsxs14(Box14, { flexDirection: "row", marginTop: 1, children: [
11592
- /* @__PURE__ */ jsx16(Box14, { flexDirection: "column", width: "50%", children: inputArea }),
11593
- /* @__PURE__ */ jsx16(Box14, { flexDirection: "column", width: "50%", children: guide })
11594
- ] }) : /* @__PURE__ */ jsx16(Box14, { flexDirection: "column", marginTop: 1, children: inputArea })
11780
+ columns >= 100 ? /* @__PURE__ */ jsxs13(Box13, { flexDirection: "row", marginTop: 1, children: [
11781
+ /* @__PURE__ */ jsx15(Box13, { flexDirection: "column", width: "50%", children: inputArea }),
11782
+ /* @__PURE__ */ jsx15(Box13, { flexDirection: "column", width: "50%", children: guide })
11783
+ ] }) : /* @__PURE__ */ jsx15(Box13, { flexDirection: "column", marginTop: 1, children: inputArea })
11595
11784
  ] });
11596
11785
  }
11597
11786
  case "advanced": {
@@ -11600,8 +11789,8 @@ ${template}`;
11600
11789
  { label: "Skip", value: "skip", key: "skip" },
11601
11790
  { label: "\u2190 Cancel", value: "cancel", key: "cancel" }
11602
11791
  ];
11603
- return /* @__PURE__ */ jsxs14(Fragment2, { children: [
11604
- /* @__PURE__ */ jsxs14(Text15, { color: theme.accent, bold: true, children: [
11792
+ return /* @__PURE__ */ jsxs13(Fragment2, { children: [
11793
+ /* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
11605
11794
  mode === "create" ? "Create" : "Edit",
11606
11795
  " custom command \u2014 Options (",
11607
11796
  stepIndex,
@@ -11609,8 +11798,8 @@ ${template}`;
11609
11798
  totalSteps,
11610
11799
  ")"
11611
11800
  ] }),
11612
- /* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(
11613
- SelectInput7,
11801
+ /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
11802
+ SelectInput6,
11614
11803
  {
11615
11804
  items,
11616
11805
  onSelect: (item) => {
@@ -11629,17 +11818,17 @@ ${template}`;
11629
11818
  { label: cmdMode === "auto" ? "auto \xB7 current" : "auto", value: "auto", key: "auto" },
11630
11819
  { label: "\u2190 Back", value: "__back__", key: "__back__" }
11631
11820
  ];
11632
- return /* @__PURE__ */ jsxs14(Fragment2, { children: [
11633
- /* @__PURE__ */ jsxs14(Text15, { color: theme.accent, bold: true, children: [
11821
+ return /* @__PURE__ */ jsxs13(Fragment2, { children: [
11822
+ /* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
11634
11823
  "Mode override (",
11635
11824
  stepIndex,
11636
11825
  "/",
11637
11826
  totalSteps,
11638
11827
  ")"
11639
11828
  ] }),
11640
- /* @__PURE__ */ jsx16(Text15, { color: theme.info.color, children: "Saved to file but not yet enforced at runtime" }),
11641
- /* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(
11642
- SelectInput7,
11829
+ /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Saved to file but not yet enforced at runtime" }),
11830
+ /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
11831
+ SelectInput6,
11643
11832
  {
11644
11833
  items,
11645
11834
  onSelect: (item) => {
@@ -11658,16 +11847,16 @@ ${template}`;
11658
11847
  { label: cmdEffort === "high" ? "high \xB7 current" : "high", value: "high", key: "high" },
11659
11848
  { label: "\u2190 Back", value: "__back__", key: "__back__" }
11660
11849
  ];
11661
- return /* @__PURE__ */ jsxs14(Fragment2, { children: [
11662
- /* @__PURE__ */ jsxs14(Text15, { color: theme.accent, bold: true, children: [
11850
+ return /* @__PURE__ */ jsxs13(Fragment2, { children: [
11851
+ /* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
11663
11852
  "Reasoning effort (",
11664
11853
  stepIndex,
11665
11854
  "/",
11666
11855
  totalSteps,
11667
11856
  ")"
11668
11857
  ] }),
11669
- /* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(
11670
- SelectInput7,
11858
+ /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
11859
+ SelectInput6,
11671
11860
  {
11672
11861
  items,
11673
11862
  onSelect: (item) => {
@@ -11679,15 +11868,15 @@ ${template}`;
11679
11868
  ] });
11680
11869
  }
11681
11870
  case "model":
11682
- return /* @__PURE__ */ jsxs14(Fragment2, { children: [
11683
- /* @__PURE__ */ jsxs14(Text15, { color: theme.accent, bold: true, children: [
11871
+ return /* @__PURE__ */ jsxs13(Fragment2, { children: [
11872
+ /* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
11684
11873
  "Model override (",
11685
11874
  stepIndex,
11686
11875
  "/",
11687
11876
  totalSteps,
11688
11877
  ")"
11689
11878
  ] }),
11690
- /* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(
11879
+ /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
11691
11880
  CustomTextInput,
11692
11881
  {
11693
11882
  value: cmdModel ?? "",
@@ -11696,7 +11885,7 @@ ${template}`;
11696
11885
  focus: true
11697
11886
  }
11698
11887
  ) }),
11699
- /* @__PURE__ */ jsx16(Text15, { color: theme.info.color, children: "Press Enter to skip" })
11888
+ /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Press Enter to skip" })
11700
11889
  ] });
11701
11890
  case "location": {
11702
11891
  const items = [
@@ -11704,16 +11893,16 @@ ${template}`;
11704
11893
  { label: source === "global" ? "Global \xB7 current" : "Global", value: "global", key: "global" },
11705
11894
  { label: "\u2190 Back", value: "__back__", key: "__back__" }
11706
11895
  ];
11707
- return /* @__PURE__ */ jsxs14(Fragment2, { children: [
11708
- /* @__PURE__ */ jsxs14(Text15, { color: theme.accent, bold: true, children: [
11896
+ return /* @__PURE__ */ jsxs13(Fragment2, { children: [
11897
+ /* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
11709
11898
  "Save location (",
11710
11899
  stepIndex,
11711
11900
  "/",
11712
11901
  totalSteps,
11713
11902
  ")"
11714
11903
  ] }),
11715
- /* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(
11716
- SelectInput7,
11904
+ /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
11905
+ SelectInput6,
11717
11906
  {
11718
11907
  items,
11719
11908
  onSelect: (item) => {
@@ -11722,7 +11911,7 @@ ${template}`;
11722
11911
  }
11723
11912
  }
11724
11913
  ) }),
11725
- /* @__PURE__ */ jsx16(Text15, { color: theme.info.color, children: "Project: .kimiflare/commands/ Global: ~/.config/kimiflare/commands/" })
11914
+ /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Project: .kimiflare/commands/ Global: ~/.config/kimiflare/commands/" })
11726
11915
  ] });
11727
11916
  }
11728
11917
  case "confirm": {
@@ -11730,8 +11919,8 @@ ${template}`;
11730
11919
  { label: "Save", value: "save", key: "save" },
11731
11920
  { label: "Cancel", value: "cancel", key: "cancel" }
11732
11921
  ];
11733
- return /* @__PURE__ */ jsxs14(Fragment2, { children: [
11734
- /* @__PURE__ */ jsxs14(Text15, { color: theme.accent, bold: true, children: [
11922
+ return /* @__PURE__ */ jsxs13(Fragment2, { children: [
11923
+ /* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
11735
11924
  mode === "create" ? "Create" : "Edit",
11736
11925
  " custom command \u2014 Confirm (",
11737
11926
  stepIndex,
@@ -11739,14 +11928,14 @@ ${template}`;
11739
11928
  totalSteps,
11740
11929
  ")"
11741
11930
  ] }),
11742
- /* @__PURE__ */ jsxs14(Text15, { color: theme.info.color, children: [
11931
+ /* @__PURE__ */ jsxs13(Text14, { color: theme.info.color, children: [
11743
11932
  source === "project" ? ".kimiflare/commands/" : "~/.config/kimiflare/commands/",
11744
11933
  name,
11745
11934
  ".md"
11746
11935
  ] }),
11747
- /* @__PURE__ */ jsx16(Box14, { marginTop: 1, flexDirection: "column", children: previewContent().split("\n").map((line, i) => /* @__PURE__ */ jsx16(Text15, { color: theme.info.color, children: line || " " }, i)) }),
11748
- /* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(
11749
- SelectInput7,
11936
+ /* @__PURE__ */ jsx15(Box13, { marginTop: 1, flexDirection: "column", children: previewContent().split("\n").map((line, i) => /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: line || " " }, i)) }),
11937
+ /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
11938
+ SelectInput6,
11750
11939
  {
11751
11940
  items,
11752
11941
  onSelect: (item) => handleConfirm(item.value)
@@ -11756,7 +11945,7 @@ ${template}`;
11756
11945
  }
11757
11946
  }
11758
11947
  };
11759
- return /* @__PURE__ */ jsx16(Box14, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: renderStep() });
11948
+ return /* @__PURE__ */ jsx15(Box13, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: renderStep() });
11760
11949
  }
11761
11950
  var NAME_RE;
11762
11951
  var init_command_wizard = __esm({
@@ -11770,12 +11959,12 @@ var init_command_wizard = __esm({
11770
11959
 
11771
11960
  // src/init/context-generator.ts
11772
11961
  import { existsSync as existsSync2, statSync as statSync3 } from "fs";
11773
- import { join as join20 } from "path";
11962
+ import { join as join22 } from "path";
11774
11963
  function detectFlavor(cwd) {
11775
11964
  for (const [flavor, signatures] of Object.entries(FLAVOR_SIGNATURES)) {
11776
11965
  if (flavor === "generic") continue;
11777
11966
  for (const sig of signatures) {
11778
- const path = join20(cwd, sig);
11967
+ const path = join22(cwd, sig);
11779
11968
  if (sig.includes("*")) {
11780
11969
  try {
11781
11970
  const parts = sig.split("*");
@@ -11796,14 +11985,14 @@ function detectFlavor(cwd) {
11796
11985
  }
11797
11986
  function findFile(cwd, candidates) {
11798
11987
  for (const c of candidates) {
11799
- if (existsSync2(join20(cwd, c))) return c;
11988
+ if (existsSync2(join22(cwd, c))) return c;
11800
11989
  }
11801
11990
  return null;
11802
11991
  }
11803
11992
  function findSourceRoots(cwd) {
11804
11993
  const roots = [];
11805
11994
  for (const r of SOURCE_ROOT_CANDIDATES) {
11806
- const p = join20(cwd, r);
11995
+ const p = join22(cwd, r);
11807
11996
  try {
11808
11997
  const s = statSync3(p);
11809
11998
  if (s.isDirectory()) roots.push(r);
@@ -11814,9 +12003,9 @@ function findSourceRoots(cwd) {
11814
12003
  }
11815
12004
  function findCiConfig(cwd) {
11816
12005
  for (const c of CI_PATHS) {
11817
- if (existsSync2(join20(cwd, c))) {
12006
+ if (existsSync2(join22(cwd, c))) {
11818
12007
  try {
11819
- const s = statSync3(join20(cwd, c));
12008
+ const s = statSync3(join22(cwd, c));
11820
12009
  return s.isDirectory() ? c : c;
11821
12010
  } catch {
11822
12011
  }
@@ -11953,7 +12142,7 @@ function analyzeProject(cwd) {
11953
12142
  ciConfig: findCiConfig(cwd),
11954
12143
  readme: findFile(cwd, ["README.md", "README.rst", "README.txt", "Readme.md"]),
11955
12144
  sourceRoots: findSourceRoots(cwd),
11956
- hasGit: existsSync2(join20(cwd, ".git"))
12145
+ hasGit: existsSync2(join22(cwd, ".git"))
11957
12146
  };
11958
12147
  }
11959
12148
  function bashDiscoveryCommands(profile) {
@@ -12118,7 +12307,7 @@ Aim for 100\u2013200 lines total. Use markdown tables where they save space.
12118
12307
  }
12119
12308
  function buildInitPrompt(cwd) {
12120
12309
  const existingName = ["KIMI.md", "KIMIFLARE.md", "AGENT.md"].find(
12121
- (n) => existsSync2(join20(cwd, n))
12310
+ (n) => existsSync2(join22(cwd, n))
12122
12311
  );
12123
12312
  const isRefresh = existingName !== void 0;
12124
12313
  const targetFilename = existingName ?? "KIMI.md";
@@ -12201,9 +12390,9 @@ var init_context_generator = __esm({
12201
12390
  });
12202
12391
 
12203
12392
  // src/ui/command-picker.tsx
12204
- import { Box as Box15, Text as Text16 } from "ink";
12205
- import SelectInput8 from "ink-select-input";
12206
- import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
12393
+ import { Box as Box14, Text as Text15 } from "ink";
12394
+ import SelectInput7 from "ink-select-input";
12395
+ import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
12207
12396
  function CommandPicker({ commands, title, onPick }) {
12208
12397
  const theme = useTheme();
12209
12398
  const items = commands.map((cmd) => ({
@@ -12212,11 +12401,11 @@ function CommandPicker({ commands, title, onPick }) {
12212
12401
  key: cmd.name
12213
12402
  }));
12214
12403
  items.push({ label: "\u2190 Cancel", value: null, key: "__cancel__" });
12215
- return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
12216
- /* @__PURE__ */ jsx17(Text16, { color: theme.accent, bold: true, children: title }),
12217
- /* @__PURE__ */ jsx17(Text16, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select." }),
12218
- /* @__PURE__ */ jsx17(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx17(
12219
- SelectInput8,
12404
+ return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
12405
+ /* @__PURE__ */ jsx16(Text15, { color: theme.accent, bold: true, children: title }),
12406
+ /* @__PURE__ */ jsx16(Text15, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select." }),
12407
+ /* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(
12408
+ SelectInput7,
12220
12409
  {
12221
12410
  items,
12222
12411
  onSelect: (item) => {
@@ -12238,64 +12427,64 @@ var init_command_picker = __esm({
12238
12427
  });
12239
12428
 
12240
12429
  // src/ui/command-list.tsx
12241
- import { Box as Box16, Text as Text17, useInput as useInput6 } from "ink";
12242
- import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
12430
+ import { Box as Box15, Text as Text16, useInput as useInput5 } from "ink";
12431
+ import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
12243
12432
  function CommandList({ commands, onDone }) {
12244
12433
  const theme = useTheme();
12245
- useInput6((_input, key) => {
12434
+ useInput5((_input, key) => {
12246
12435
  if (key.escape) {
12247
12436
  onDone();
12248
12437
  }
12249
12438
  });
12250
- return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
12251
- /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Custom commands" }),
12252
- /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Esc to close." }),
12253
- /* @__PURE__ */ jsxs16(Box16, { marginTop: 1, flexDirection: "column", children: [
12254
- commands.length === 0 && /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, children: "No custom commands found." }),
12255
- commands.map((cmd) => /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", marginBottom: 1, children: [
12256
- /* @__PURE__ */ jsxs16(Text17, { color: theme.accent, bold: true, children: [
12439
+ return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
12440
+ /* @__PURE__ */ jsx17(Text16, { color: theme.accent, bold: true, children: "Custom commands" }),
12441
+ /* @__PURE__ */ jsx17(Text16, { color: theme.info.color, dimColor: false, children: "Esc to close." }),
12442
+ /* @__PURE__ */ jsxs15(Box15, { marginTop: 1, flexDirection: "column", children: [
12443
+ commands.length === 0 && /* @__PURE__ */ jsx17(Text16, { color: theme.info.color, children: "No custom commands found." }),
12444
+ commands.map((cmd) => /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", marginBottom: 1, children: [
12445
+ /* @__PURE__ */ jsxs15(Text16, { color: theme.accent, bold: true, children: [
12257
12446
  "/",
12258
12447
  cmd.name
12259
12448
  ] }),
12260
- /* @__PURE__ */ jsxs16(Text17, { color: theme.info.color, children: [
12449
+ /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
12261
12450
  " ",
12262
12451
  "source: ",
12263
12452
  cmd.source
12264
12453
  ] }),
12265
- /* @__PURE__ */ jsxs16(Text17, { color: theme.info.color, children: [
12454
+ /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
12266
12455
  " ",
12267
12456
  "path: ",
12268
12457
  cmd.filepath
12269
12458
  ] }),
12270
- cmd.description && /* @__PURE__ */ jsxs16(Text17, { color: theme.info.color, children: [
12459
+ cmd.description && /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
12271
12460
  " ",
12272
12461
  "desc: ",
12273
12462
  cmd.description
12274
12463
  ] }),
12275
- cmd.mode && /* @__PURE__ */ jsxs16(Text17, { color: theme.info.color, children: [
12464
+ cmd.mode && /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
12276
12465
  " ",
12277
12466
  "mode: ",
12278
12467
  cmd.mode
12279
12468
  ] }),
12280
- cmd.effort && /* @__PURE__ */ jsxs16(Text17, { color: theme.info.color, children: [
12469
+ cmd.effort && /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
12281
12470
  " ",
12282
12471
  "effort: ",
12283
12472
  cmd.effort
12284
12473
  ] }),
12285
- cmd.model && /* @__PURE__ */ jsxs16(Text17, { color: theme.info.color, children: [
12474
+ cmd.model && /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
12286
12475
  " ",
12287
12476
  "model: ",
12288
12477
  cmd.model
12289
12478
  ] }),
12290
- /* @__PURE__ */ jsxs16(Text17, { color: theme.info.color, children: [
12479
+ /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
12291
12480
  " ",
12292
12481
  "template:"
12293
12482
  ] }),
12294
- cmd.template.split("\n").slice(0, 5).map((line, i) => /* @__PURE__ */ jsxs16(Text17, { color: theme.info.color, children: [
12483
+ cmd.template.split("\n").slice(0, 5).map((line, i) => /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
12295
12484
  " ",
12296
12485
  line || " "
12297
12486
  ] }, i)),
12298
- cmd.template.split("\n").length > 5 && /* @__PURE__ */ jsxs16(Text17, { color: theme.info.color, children: [
12487
+ cmd.template.split("\n").length > 5 && /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
12299
12488
  " ",
12300
12489
  "..."
12301
12490
  ] })
@@ -12312,10 +12501,10 @@ var init_command_list = __esm({
12312
12501
 
12313
12502
  // src/ui/lsp-wizard.tsx
12314
12503
  import { useState as useState9 } from "react";
12315
- import { Box as Box17, Text as Text18 } from "ink";
12316
- import SelectInput9 from "ink-select-input";
12504
+ import { Box as Box16, Text as Text17 } from "ink";
12505
+ import SelectInput8 from "ink-select-input";
12317
12506
  import { spawn as spawn3 } from "child_process";
12318
- import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
12507
+ import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
12319
12508
  function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
12320
12509
  const theme = useTheme();
12321
12510
  const [page, setPage] = useState9("main");
@@ -12426,11 +12615,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
12426
12615
  { label: "(close)", value: "__close__", key: "__close__" }
12427
12616
  ];
12428
12617
  if (page === "main") {
12429
- return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
12430
- /* @__PURE__ */ jsx19(Text18, { color: theme.accent, bold: true, children: "LSP Servers" }),
12431
- /* @__PURE__ */ jsx19(Text18, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select." }),
12432
- /* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
12433
- SelectInput9,
12618
+ return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
12619
+ /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "LSP Servers" }),
12620
+ /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select." }),
12621
+ /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
12622
+ SelectInput8,
12434
12623
  {
12435
12624
  items: mainItems,
12436
12625
  onSelect: (item) => {
@@ -12457,11 +12646,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
12457
12646
  }),
12458
12647
  { label: "\u2190 Back", value: "__back__", key: "__back__" }
12459
12648
  ];
12460
- return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
12461
- /* @__PURE__ */ jsx19(Text18, { color: theme.accent, bold: true, children: "Add LSP Server" }),
12462
- /* @__PURE__ */ jsx19(Text18, { color: theme.info.color, dimColor: false, children: "Select a language server to configure." }),
12463
- /* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
12464
- SelectInput9,
12649
+ return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
12650
+ /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Add LSP Server" }),
12651
+ /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Select a language server to configure." }),
12652
+ /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
12653
+ SelectInput8,
12465
12654
  {
12466
12655
  items,
12467
12656
  onSelect: (item) => {
@@ -12488,19 +12677,19 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
12488
12677
  { label: isSuccess ? "Save to config \u2713" : "Save anyway", value: "save", key: "save" },
12489
12678
  { label: "\u2190 Back", value: "__back__", key: "__back__" }
12490
12679
  ];
12491
- return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
12492
- /* @__PURE__ */ jsxs17(Text18, { color: theme.accent, bold: true, children: [
12680
+ return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
12681
+ /* @__PURE__ */ jsxs16(Text17, { color: theme.accent, bold: true, children: [
12493
12682
  "Install ",
12494
12683
  selectedPreset.name
12495
12684
  ] }),
12496
- /* @__PURE__ */ jsx19(Text18, { color: theme.info.color, dimColor: false, children: selectedPreset.installHint }),
12497
- /* @__PURE__ */ jsxs17(Box17, { marginTop: 1, flexDirection: "column", children: [
12498
- /* @__PURE__ */ jsx19(Text18, { color: theme.info.color, dimColor: false, children: "Command:" }),
12499
- /* @__PURE__ */ jsx19(Text18, { color: theme.accent, children: selectedPreset.installCommand || "(none required)" })
12685
+ /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: selectedPreset.installHint }),
12686
+ /* @__PURE__ */ jsxs16(Box16, { marginTop: 1, flexDirection: "column", children: [
12687
+ /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Command:" }),
12688
+ /* @__PURE__ */ jsx18(Text17, { color: theme.accent, children: selectedPreset.installCommand || "(none required)" })
12500
12689
  ] }),
12501
- installState.output && /* @__PURE__ */ jsx19(Box17, { marginTop: 1, flexDirection: "column", children: /* @__PURE__ */ jsx19(Text18, { color: isSuccess ? theme.accent : theme.error, children: installState.output.slice(-500) }) }),
12502
- /* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
12503
- SelectInput9,
12690
+ installState.output && /* @__PURE__ */ jsx18(Box16, { marginTop: 1, flexDirection: "column", children: /* @__PURE__ */ jsx18(Text17, { color: isSuccess ? theme.accent : theme.error, children: installState.output.slice(-500) }) }),
12691
+ /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
12692
+ SelectInput8,
12504
12693
  {
12505
12694
  items,
12506
12695
  onSelect: (item) => {
@@ -12517,16 +12706,16 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
12517
12706
  }
12518
12707
  }
12519
12708
  ) }),
12520
- isSuccess && /* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(Text18, { color: theme.accent, children: "Server saved. Run /lsp reload to start it." }) })
12709
+ isSuccess && /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(Text17, { color: theme.accent, children: "Server saved. Run /lsp reload to start it." }) })
12521
12710
  ] });
12522
12711
  }
12523
12712
  if (page === "custom-name") {
12524
- return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
12525
- /* @__PURE__ */ jsx19(Text18, { color: theme.accent, bold: true, children: "Custom LSP Server \u2014 Name" }),
12526
- /* @__PURE__ */ jsx19(Text18, { color: theme.info.color, dimColor: false, children: "Enter a name for this server (e.g., my-server)." }),
12527
- /* @__PURE__ */ jsxs17(Box17, { marginTop: 1, children: [
12528
- /* @__PURE__ */ jsx19(Text18, { color: theme.accent, children: "\u203A " }),
12529
- /* @__PURE__ */ jsx19(
12713
+ return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
12714
+ /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Custom LSP Server \u2014 Name" }),
12715
+ /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Enter a name for this server (e.g., my-server)." }),
12716
+ /* @__PURE__ */ jsxs16(Box16, { marginTop: 1, children: [
12717
+ /* @__PURE__ */ jsx18(Text17, { color: theme.accent, children: "\u203A " }),
12718
+ /* @__PURE__ */ jsx18(
12530
12719
  CustomTextInput,
12531
12720
  {
12532
12721
  value: customName,
@@ -12540,8 +12729,8 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
12540
12729
  }
12541
12730
  )
12542
12731
  ] }),
12543
- /* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
12544
- SelectInput9,
12732
+ /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
12733
+ SelectInput8,
12545
12734
  {
12546
12735
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
12547
12736
  onSelect: () => setPage("add")
@@ -12550,12 +12739,12 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
12550
12739
  ] });
12551
12740
  }
12552
12741
  if (page === "custom-command") {
12553
- return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
12554
- /* @__PURE__ */ jsx19(Text18, { color: theme.accent, bold: true, children: "Custom LSP Server \u2014 Command" }),
12555
- /* @__PURE__ */ jsx19(Text18, { color: theme.info.color, dimColor: false, children: "Enter the command to start the server (space-separated)." }),
12556
- /* @__PURE__ */ jsxs17(Box17, { marginTop: 1, children: [
12557
- /* @__PURE__ */ jsx19(Text18, { color: theme.accent, children: "\u203A " }),
12558
- /* @__PURE__ */ jsx19(
12742
+ return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
12743
+ /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Custom LSP Server \u2014 Command" }),
12744
+ /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Enter the command to start the server (space-separated)." }),
12745
+ /* @__PURE__ */ jsxs16(Box16, { marginTop: 1, children: [
12746
+ /* @__PURE__ */ jsx18(Text17, { color: theme.accent, children: "\u203A " }),
12747
+ /* @__PURE__ */ jsx18(
12559
12748
  CustomTextInput,
12560
12749
  {
12561
12750
  value: customCommand,
@@ -12569,8 +12758,8 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
12569
12758
  }
12570
12759
  )
12571
12760
  ] }),
12572
- /* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
12573
- SelectInput9,
12761
+ /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
12762
+ SelectInput8,
12574
12763
  {
12575
12764
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
12576
12765
  onSelect: () => setPage("custom-name")
@@ -12593,11 +12782,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
12593
12782
  },
12594
12783
  { label: "\u2190 Back", value: "__back__", key: "__back__" }
12595
12784
  ];
12596
- return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
12597
- /* @__PURE__ */ jsx19(Text18, { color: theme.accent, bold: true, children: "Save LSP Config" }),
12598
- /* @__PURE__ */ jsx19(Text18, { color: theme.info.color, dimColor: false, children: "Where should this server configuration be saved?" }),
12599
- /* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
12600
- SelectInput9,
12785
+ return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
12786
+ /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Save LSP Config" }),
12787
+ /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Where should this server configuration be saved?" }),
12788
+ /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
12789
+ SelectInput8,
12601
12790
  {
12602
12791
  items,
12603
12792
  onSelect: (item) => {
@@ -12615,11 +12804,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
12615
12804
  if (page === "edit") {
12616
12805
  const keys = Object.keys(servers);
12617
12806
  if (keys.length === 0) {
12618
- return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
12619
- /* @__PURE__ */ jsx19(Text18, { color: theme.accent, bold: true, children: "Edit LSP Server" }),
12620
- /* @__PURE__ */ jsx19(Text18, { color: theme.info.color, children: "No servers configured." }),
12621
- /* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
12622
- SelectInput9,
12807
+ return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
12808
+ /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Edit LSP Server" }),
12809
+ /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, children: "No servers configured." }),
12810
+ /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
12811
+ SelectInput8,
12623
12812
  {
12624
12813
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
12625
12814
  onSelect: () => setPage("main")
@@ -12639,11 +12828,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
12639
12828
  }),
12640
12829
  { label: "\u2190 Back", value: "__back__", key: "__back__" }
12641
12830
  ];
12642
- return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
12643
- /* @__PURE__ */ jsx19(Text18, { color: theme.accent, bold: true, children: "Edit LSP Server" }),
12644
- /* @__PURE__ */ jsx19(Text18, { color: theme.info.color, dimColor: false, children: "Select a server to toggle enabled/disabled." }),
12645
- /* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
12646
- SelectInput9,
12831
+ return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
12832
+ /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Edit LSP Server" }),
12833
+ /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Select a server to toggle enabled/disabled." }),
12834
+ /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
12835
+ SelectInput8,
12647
12836
  {
12648
12837
  items,
12649
12838
  onSelect: (item) => {
@@ -12660,11 +12849,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
12660
12849
  if (page === "delete") {
12661
12850
  const keys = Object.keys(servers);
12662
12851
  if (keys.length === 0) {
12663
- return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
12664
- /* @__PURE__ */ jsx19(Text18, { color: theme.accent, bold: true, children: "Delete LSP Server" }),
12665
- /* @__PURE__ */ jsx19(Text18, { color: theme.info.color, children: "No servers configured." }),
12666
- /* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
12667
- SelectInput9,
12852
+ return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
12853
+ /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Delete LSP Server" }),
12854
+ /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, children: "No servers configured." }),
12855
+ /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
12856
+ SelectInput8,
12668
12857
  {
12669
12858
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
12670
12859
  onSelect: () => setPage("main")
@@ -12680,11 +12869,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
12680
12869
  })),
12681
12870
  { label: "\u2190 Back", value: "__back__", key: "__back__" }
12682
12871
  ];
12683
- return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
12684
- /* @__PURE__ */ jsx19(Text18, { color: theme.accent, bold: true, children: "Delete LSP Server" }),
12685
- /* @__PURE__ */ jsx19(Text18, { color: theme.info.color, dimColor: false, children: "Select a server to remove from config." }),
12686
- /* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
12687
- SelectInput9,
12872
+ return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
12873
+ /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Delete LSP Server" }),
12874
+ /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Select a server to remove from config." }),
12875
+ /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
12876
+ SelectInput8,
12688
12877
  {
12689
12878
  items,
12690
12879
  onSelect: (item) => {
@@ -12700,15 +12889,15 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
12700
12889
  }
12701
12890
  if (page === "list") {
12702
12891
  const keys = Object.keys(servers);
12703
- return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
12704
- /* @__PURE__ */ jsx19(Text18, { color: theme.accent, bold: true, children: "Configured LSP Servers" }),
12705
- keys.length === 0 ? /* @__PURE__ */ jsx19(Text18, { color: theme.info.color, children: "No servers configured." }) : /* @__PURE__ */ jsx19(Box17, { marginTop: 1, flexDirection: "column", children: keys.map((k) => {
12892
+ return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
12893
+ /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Configured LSP Servers" }),
12894
+ keys.length === 0 ? /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, children: "No servers configured." }) : /* @__PURE__ */ jsx18(Box16, { marginTop: 1, flexDirection: "column", children: keys.map((k) => {
12706
12895
  const s = servers[k];
12707
12896
  const status = s.enabled !== false ? "enabled" : "disabled";
12708
- return /* @__PURE__ */ jsx19(Text18, { color: theme.info.color, children: ` ${k.padEnd(16)} ${status} ${s.command.join(" ")}` }, k);
12897
+ return /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, children: ` ${k.padEnd(16)} ${status} ${s.command.join(" ")}` }, k);
12709
12898
  }) }),
12710
- /* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
12711
- SelectInput9,
12899
+ /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
12900
+ SelectInput8,
12712
12901
  {
12713
12902
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
12714
12903
  onSelect: () => setPage("main")
@@ -12834,9 +13023,9 @@ var init_lsp_wizard = __esm({
12834
13023
  });
12835
13024
 
12836
13025
  // src/ui/theme-picker.tsx
12837
- import { Box as Box18, Text as Text19 } from "ink";
12838
- import SelectInput10 from "ink-select-input";
12839
- import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
13026
+ import { Box as Box17, Text as Text18 } from "ink";
13027
+ import SelectInput9 from "ink-select-input";
13028
+ import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
12840
13029
  function PaletteSwatches({ palette }) {
12841
13030
  const colors = [
12842
13031
  palette.primary,
@@ -12844,7 +13033,7 @@ function PaletteSwatches({ palette }) {
12844
13033
  palette.success,
12845
13034
  palette.error
12846
13035
  ];
12847
- return /* @__PURE__ */ jsx20(Box18, { children: colors.map((c, i) => /* @__PURE__ */ jsx20(Text19, { color: c, children: "\u2588" }, i)) });
13036
+ return /* @__PURE__ */ jsx19(Box17, { children: colors.map((c, i) => /* @__PURE__ */ jsx19(Text18, { color: c, children: "\u2588" }, i)) });
12848
13037
  }
12849
13038
  function ThemePicker({ themes, onPick }) {
12850
13039
  const current = useTheme();
@@ -12852,10 +13041,10 @@ function ThemePicker({ themes, onPick }) {
12852
13041
  ...themes.map((t) => ({ label: t.label, value: t.name })),
12853
13042
  { label: "< Back", value: "__back__" }
12854
13043
  ];
12855
- return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", borderStyle: "round", borderColor: current.accent, paddingX: 1, children: [
12856
- /* @__PURE__ */ jsx20(Text19, { color: current.accent, bold: true, children: "Pick a theme (restart to apply)" }),
12857
- /* @__PURE__ */ jsx20(Box18, { marginTop: 1, children: /* @__PURE__ */ jsx20(
12858
- SelectInput10,
13044
+ return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: current.accent, paddingX: 1, children: [
13045
+ /* @__PURE__ */ jsx19(Text18, { color: current.accent, bold: true, children: "Pick a theme (restart to apply)" }),
13046
+ /* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
13047
+ SelectInput9,
12859
13048
  {
12860
13049
  items,
12861
13050
  onSelect: (item) => {
@@ -12869,9 +13058,9 @@ function ThemePicker({ themes, onPick }) {
12869
13058
  itemComponent: ({ label, isSelected }) => {
12870
13059
  const t = themes.find((x) => x.label === label);
12871
13060
  const color = t?.accent ?? current.accent;
12872
- return /* @__PURE__ */ jsxs18(Box18, { children: [
12873
- /* @__PURE__ */ jsx20(Text19, { color, bold: isSelected, dimColor: !isSelected, children: label }),
12874
- t && /* @__PURE__ */ jsx20(Box18, { marginLeft: 1, children: /* @__PURE__ */ jsx20(PaletteSwatches, { palette: t.palette }) })
13061
+ return /* @__PURE__ */ jsxs17(Box17, { children: [
13062
+ /* @__PURE__ */ jsx19(Text18, { color, bold: isSelected, dimColor: !isSelected, children: label }),
13063
+ t && /* @__PURE__ */ jsx19(Box17, { marginLeft: 1, children: /* @__PURE__ */ jsx19(PaletteSwatches, { palette: t.palette }) })
12875
13064
  ] });
12876
13065
  }
12877
13066
  }
@@ -12885,39 +13074,628 @@ var init_theme_picker = __esm({
12885
13074
  }
12886
13075
  });
12887
13076
 
12888
- // src/ui/theme.ts
12889
- function buildTheme(name, label, palette, overrides) {
12890
- const base = {
12891
- name,
12892
- label,
13077
+ // src/ui/themes/everforest-dark.json
13078
+ var everforest_dark_default;
13079
+ var init_everforest_dark = __esm({
13080
+ "src/ui/themes/everforest-dark.json"() {
13081
+ everforest_dark_default = {
13082
+ name: "everforest-dark",
13083
+ label: "Everforest Dark",
13084
+ palette: {
13085
+ background: "#2b3339",
13086
+ foreground: "#d3c6aa",
13087
+ primary: "#a7c080",
13088
+ secondary: "#7a8478",
13089
+ success: "#a7c080",
13090
+ error: "#e67e80"
13091
+ },
13092
+ user: "#a7c080",
13093
+ assistant: null,
13094
+ reasoning: { color: "#7a8478", dim: true },
13095
+ info: { color: "#d3c6aa", dim: false },
13096
+ error: "#e67e80",
13097
+ warn: "#dbbc7f",
13098
+ tool: "#7fbbb3",
13099
+ spinner: "#a7c080",
13100
+ permission: "#e67e80",
13101
+ queue: { color: "#7a8478", dim: true },
13102
+ accent: "#a7c080",
13103
+ modeBadge: {
13104
+ plan: "#a7c080",
13105
+ auto: "#a7c080",
13106
+ edit: "#e67e80"
13107
+ },
13108
+ blockquote: { color: "#7a8478", dim: true },
13109
+ codeInline: "#7fbbb3",
13110
+ codeBlock: "#7fbbb3",
13111
+ link: "#a7c080",
13112
+ strikethrough: "#7a8478",
13113
+ tableBorder: "#4b565c",
13114
+ tableHeader: "#d3c6aa",
13115
+ tableCell: "#d3c6aa",
13116
+ muted: { color: "#7a8478", dim: true }
13117
+ };
13118
+ }
13119
+ });
13120
+
13121
+ // src/ui/themes/everforest-light.json
13122
+ var everforest_light_default;
13123
+ var init_everforest_light = __esm({
13124
+ "src/ui/themes/everforest-light.json"() {
13125
+ everforest_light_default = {
13126
+ name: "everforest-light",
13127
+ label: "Everforest Light",
13128
+ palette: {
13129
+ background: "#fdf6e3",
13130
+ foreground: "#5c6a72",
13131
+ primary: "#8da101",
13132
+ secondary: "#939f91",
13133
+ success: "#8da101",
13134
+ error: "#f85552"
13135
+ },
13136
+ user: "#8da101",
13137
+ assistant: null,
13138
+ reasoning: { color: "#939f91", dim: true },
13139
+ info: { color: "#5c6a72", dim: false },
13140
+ error: "#f85552",
13141
+ warn: "#dfa000",
13142
+ tool: "#3a94c5",
13143
+ spinner: "#8da101",
13144
+ permission: "#f85552",
13145
+ queue: { color: "#939f91", dim: true },
13146
+ accent: "#8da101",
13147
+ modeBadge: {
13148
+ plan: "#8da101",
13149
+ auto: "#8da101",
13150
+ edit: "#f85552"
13151
+ },
13152
+ blockquote: { color: "#939f91", dim: true },
13153
+ codeInline: "#3a94c5",
13154
+ codeBlock: "#3a94c5",
13155
+ link: "#8da101",
13156
+ strikethrough: "#939f91",
13157
+ tableBorder: "#bdc3af",
13158
+ tableHeader: "#5c6a72",
13159
+ tableCell: "#5c6a72",
13160
+ muted: { color: "#939f91", dim: true }
13161
+ };
13162
+ }
13163
+ });
13164
+
13165
+ // src/ui/themes/kanagawa-dark.json
13166
+ var kanagawa_dark_default;
13167
+ var init_kanagawa_dark = __esm({
13168
+ "src/ui/themes/kanagawa-dark.json"() {
13169
+ kanagawa_dark_default = {
13170
+ name: "kanagawa-dark",
13171
+ label: "Kanagawa Dark",
13172
+ palette: {
13173
+ background: "#1f1f28",
13174
+ foreground: "#dcd7ba",
13175
+ primary: "#7e9cd8",
13176
+ secondary: "#727169",
13177
+ success: "#98bb6c",
13178
+ error: "#ff5d62"
13179
+ },
13180
+ user: "#7e9cd8",
13181
+ assistant: null,
13182
+ reasoning: { color: "#727169", dim: true },
13183
+ info: { color: "#dcd7ba", dim: false },
13184
+ error: "#ff5d62",
13185
+ warn: "#e6c384",
13186
+ tool: "#7fb4ca",
13187
+ spinner: "#7e9cd8",
13188
+ permission: "#ff5d62",
13189
+ queue: { color: "#727169", dim: true },
13190
+ accent: "#7e9cd8",
13191
+ modeBadge: {
13192
+ plan: "#7e9cd8",
13193
+ auto: "#98bb6c",
13194
+ edit: "#ff5d62"
13195
+ },
13196
+ blockquote: { color: "#727169", dim: true },
13197
+ codeInline: "#7fb4ca",
13198
+ codeBlock: "#7fb4ca",
13199
+ link: "#7e9cd8",
13200
+ strikethrough: "#727169",
13201
+ tableBorder: "#54546d",
13202
+ tableHeader: "#dcd7ba",
13203
+ tableCell: "#dcd7ba",
13204
+ muted: { color: "#727169", dim: true }
13205
+ };
13206
+ }
13207
+ });
13208
+
13209
+ // src/ui/themes/dracula-dark.json
13210
+ var dracula_dark_default;
13211
+ var init_dracula_dark = __esm({
13212
+ "src/ui/themes/dracula-dark.json"() {
13213
+ dracula_dark_default = {
13214
+ name: "dracula-dark",
13215
+ label: "Dracula Dark",
13216
+ palette: {
13217
+ background: "#282a36",
13218
+ foreground: "#f8f8f2",
13219
+ primary: "#ff79c6",
13220
+ secondary: "#6272a4",
13221
+ success: "#50fa7b",
13222
+ error: "#ff5555"
13223
+ },
13224
+ user: "#ff79c6",
13225
+ assistant: null,
13226
+ reasoning: { color: "#6272a4", dim: true },
13227
+ info: { color: "#f8f8f2", dim: false },
13228
+ error: "#ff5555",
13229
+ warn: "#f1fa8c",
13230
+ tool: "#8be9fd",
13231
+ spinner: "#ff79c6",
13232
+ permission: "#ff5555",
13233
+ queue: { color: "#6272a4", dim: true },
13234
+ accent: "#ff79c6",
13235
+ modeBadge: {
13236
+ plan: "#ff79c6",
13237
+ auto: "#50fa7b",
13238
+ edit: "#ff5555"
13239
+ },
13240
+ blockquote: { color: "#6272a4", dim: true },
13241
+ codeInline: "#8be9fd",
13242
+ codeBlock: "#8be9fd",
13243
+ link: "#ff79c6",
13244
+ strikethrough: "#6272a4",
13245
+ tableBorder: "#44475a",
13246
+ tableHeader: "#f8f8f2",
13247
+ tableCell: "#f8f8f2",
13248
+ muted: { color: "#6272a4", dim: true }
13249
+ };
13250
+ }
13251
+ });
13252
+
13253
+ // src/ui/themes/tokyo-night.json
13254
+ var tokyo_night_default;
13255
+ var init_tokyo_night = __esm({
13256
+ "src/ui/themes/tokyo-night.json"() {
13257
+ tokyo_night_default = {
13258
+ name: "tokyo-night",
13259
+ label: "Tokyo Night",
13260
+ palette: {
13261
+ background: "#1a1b26",
13262
+ foreground: "#a9b1d6",
13263
+ primary: "#7aa2f7",
13264
+ secondary: "#565f89",
13265
+ success: "#9ece6a",
13266
+ error: "#f7768e"
13267
+ },
13268
+ user: "#7aa2f7",
13269
+ assistant: null,
13270
+ reasoning: { color: "#565f89", dim: true },
13271
+ info: { color: "#a9b1d6", dim: false },
13272
+ error: "#f7768e",
13273
+ warn: "#e0af68",
13274
+ tool: "#bb9af7",
13275
+ spinner: "#7aa2f7",
13276
+ permission: "#f7768e",
13277
+ queue: { color: "#565f89", dim: true },
13278
+ accent: "#7aa2f7",
13279
+ modeBadge: {
13280
+ plan: "#7aa2f7",
13281
+ auto: "#9ece6a",
13282
+ edit: "#f7768e"
13283
+ },
13284
+ blockquote: { color: "#565f89", dim: true },
13285
+ codeInline: "#bb9af7",
13286
+ codeBlock: "#bb9af7",
13287
+ link: "#7aa2f7",
13288
+ strikethrough: "#565f89",
13289
+ tableBorder: "#414868",
13290
+ tableHeader: "#c0caf5",
13291
+ tableCell: "#a9b1d6",
13292
+ muted: { color: "#565f89", dim: true }
13293
+ };
13294
+ }
13295
+ });
13296
+
13297
+ // src/ui/themes/catppuccin-mocha.json
13298
+ var catppuccin_mocha_default;
13299
+ var init_catppuccin_mocha = __esm({
13300
+ "src/ui/themes/catppuccin-mocha.json"() {
13301
+ catppuccin_mocha_default = {
13302
+ name: "catppuccin-mocha",
13303
+ label: "Catppuccin Mocha",
13304
+ palette: {
13305
+ background: "#1e1e2e",
13306
+ foreground: "#cdd6f4",
13307
+ primary: "#89b4fa",
13308
+ secondary: "#6c7086",
13309
+ success: "#a6e3a1",
13310
+ error: "#f38ba8"
13311
+ },
13312
+ user: "#89b4fa",
13313
+ assistant: null,
13314
+ reasoning: { color: "#6c7086", dim: true },
13315
+ info: { color: "#cdd6f4", dim: false },
13316
+ error: "#f38ba8",
13317
+ warn: "#f9e2af",
13318
+ tool: "#cba6f7",
13319
+ spinner: "#89b4fa",
13320
+ permission: "#f38ba8",
13321
+ queue: { color: "#6c7086", dim: true },
13322
+ accent: "#89b4fa",
13323
+ modeBadge: {
13324
+ plan: "#89b4fa",
13325
+ auto: "#a6e3a1",
13326
+ edit: "#f38ba8"
13327
+ },
13328
+ blockquote: { color: "#6c7086", dim: true },
13329
+ codeInline: "#cba6f7",
13330
+ codeBlock: "#cba6f7",
13331
+ link: "#89b4fa",
13332
+ strikethrough: "#6c7086",
13333
+ tableBorder: "#45475a",
13334
+ tableHeader: "#cdd6f4",
13335
+ tableCell: "#cdd6f4",
13336
+ muted: { color: "#6c7086", dim: true }
13337
+ };
13338
+ }
13339
+ });
13340
+
13341
+ // src/ui/themes/catppuccin-latte.json
13342
+ var catppuccin_latte_default;
13343
+ var init_catppuccin_latte = __esm({
13344
+ "src/ui/themes/catppuccin-latte.json"() {
13345
+ catppuccin_latte_default = {
13346
+ name: "catppuccin-latte",
13347
+ label: "Catppuccin Latte",
13348
+ palette: {
13349
+ background: "#eff1f5",
13350
+ foreground: "#4c4f69",
13351
+ primary: "#1e66f5",
13352
+ secondary: "#8c8fa1",
13353
+ success: "#40a02b",
13354
+ error: "#d20f39"
13355
+ },
13356
+ user: "#1e66f5",
13357
+ assistant: null,
13358
+ reasoning: { color: "#8c8fa1", dim: true },
13359
+ info: { color: "#4c4f69", dim: false },
13360
+ error: "#d20f39",
13361
+ warn: "#df8e1d",
13362
+ tool: "#8839ef",
13363
+ spinner: "#1e66f5",
13364
+ permission: "#d20f39",
13365
+ queue: { color: "#8c8fa1", dim: true },
13366
+ accent: "#1e66f5",
13367
+ modeBadge: {
13368
+ plan: "#1e66f5",
13369
+ auto: "#40a02b",
13370
+ edit: "#d20f39"
13371
+ },
13372
+ blockquote: { color: "#8c8fa1", dim: true },
13373
+ codeInline: "#8839ef",
13374
+ codeBlock: "#8839ef",
13375
+ link: "#1e66f5",
13376
+ strikethrough: "#8c8fa1",
13377
+ tableBorder: "#bcc0cc",
13378
+ tableHeader: "#4c4f69",
13379
+ tableCell: "#4c4f69",
13380
+ muted: { color: "#8c8fa1", dim: true }
13381
+ };
13382
+ }
13383
+ });
13384
+
13385
+ // src/ui/themes/solarized-dark.json
13386
+ var solarized_dark_default;
13387
+ var init_solarized_dark = __esm({
13388
+ "src/ui/themes/solarized-dark.json"() {
13389
+ solarized_dark_default = {
13390
+ name: "solarized-dark",
13391
+ label: "Solarized Dark",
13392
+ palette: {
13393
+ background: "#002b36",
13394
+ foreground: "#839496",
13395
+ primary: "#268bd2",
13396
+ secondary: "#586e75",
13397
+ success: "#859900",
13398
+ error: "#dc322f"
13399
+ },
13400
+ user: "#268bd2",
13401
+ assistant: null,
13402
+ reasoning: { color: "#586e75", dim: true },
13403
+ info: { color: "#839496", dim: false },
13404
+ error: "#dc322f",
13405
+ warn: "#b58900",
13406
+ tool: "#2aa198",
13407
+ spinner: "#268bd2",
13408
+ permission: "#dc322f",
13409
+ queue: { color: "#586e75", dim: true },
13410
+ accent: "#268bd2",
13411
+ modeBadge: {
13412
+ plan: "#268bd2",
13413
+ auto: "#859900",
13414
+ edit: "#dc322f"
13415
+ },
13416
+ blockquote: { color: "#586e75", dim: true },
13417
+ codeInline: "#2aa198",
13418
+ codeBlock: "#2aa198",
13419
+ link: "#268bd2",
13420
+ strikethrough: "#586e75",
13421
+ tableBorder: "#073642",
13422
+ tableHeader: "#93a1a1",
13423
+ tableCell: "#839496",
13424
+ muted: { color: "#586e75", dim: true }
13425
+ };
13426
+ }
13427
+ });
13428
+
13429
+ // src/ui/themes/solarized-light.json
13430
+ var solarized_light_default;
13431
+ var init_solarized_light = __esm({
13432
+ "src/ui/themes/solarized-light.json"() {
13433
+ solarized_light_default = {
13434
+ name: "solarized-light",
13435
+ label: "Solarized Light",
13436
+ palette: {
13437
+ background: "#fdf6e3",
13438
+ foreground: "#657b83",
13439
+ primary: "#268bd2",
13440
+ secondary: "#93a1a1",
13441
+ success: "#859900",
13442
+ error: "#dc322f"
13443
+ },
13444
+ user: "#268bd2",
13445
+ assistant: null,
13446
+ reasoning: { color: "#93a1a1", dim: true },
13447
+ info: { color: "#657b83", dim: false },
13448
+ error: "#dc322f",
13449
+ warn: "#b58900",
13450
+ tool: "#2aa198",
13451
+ spinner: "#268bd2",
13452
+ permission: "#dc322f",
13453
+ queue: { color: "#93a1a1", dim: true },
13454
+ accent: "#268bd2",
13455
+ modeBadge: {
13456
+ plan: "#268bd2",
13457
+ auto: "#859900",
13458
+ edit: "#dc322f"
13459
+ },
13460
+ blockquote: { color: "#93a1a1", dim: true },
13461
+ codeInline: "#2aa198",
13462
+ codeBlock: "#2aa198",
13463
+ link: "#268bd2",
13464
+ strikethrough: "#93a1a1",
13465
+ tableBorder: "#eee8d5",
13466
+ tableHeader: "#586e75",
13467
+ tableCell: "#657b83",
13468
+ muted: { color: "#93a1a1", dim: true }
13469
+ };
13470
+ }
13471
+ });
13472
+
13473
+ // src/ui/themes/nord.json
13474
+ var nord_default;
13475
+ var init_nord = __esm({
13476
+ "src/ui/themes/nord.json"() {
13477
+ nord_default = {
13478
+ name: "nord",
13479
+ label: "Nord",
13480
+ palette: {
13481
+ background: "#2e3440",
13482
+ foreground: "#d8dee9",
13483
+ primary: "#88c0d0",
13484
+ secondary: "#4c566a",
13485
+ success: "#a3be8c",
13486
+ error: "#bf616a"
13487
+ },
13488
+ user: "#88c0d0",
13489
+ assistant: null,
13490
+ reasoning: { color: "#4c566a", dim: true },
13491
+ info: { color: "#d8dee9", dim: false },
13492
+ error: "#bf616a",
13493
+ warn: "#ebcb8b",
13494
+ tool: "#81a1c1",
13495
+ spinner: "#88c0d0",
13496
+ permission: "#bf616a",
13497
+ queue: { color: "#4c566a", dim: true },
13498
+ accent: "#88c0d0",
13499
+ modeBadge: {
13500
+ plan: "#88c0d0",
13501
+ auto: "#a3be8c",
13502
+ edit: "#bf616a"
13503
+ },
13504
+ blockquote: { color: "#4c566a", dim: true },
13505
+ codeInline: "#81a1c1",
13506
+ codeBlock: "#81a1c1",
13507
+ link: "#88c0d0",
13508
+ strikethrough: "#4c566a",
13509
+ tableBorder: "#434c5e",
13510
+ tableHeader: "#eceff4",
13511
+ tableCell: "#d8dee9",
13512
+ muted: { color: "#4c566a", dim: true }
13513
+ };
13514
+ }
13515
+ });
13516
+
13517
+ // src/ui/themes/gruvbox-dark.json
13518
+ var gruvbox_dark_default;
13519
+ var init_gruvbox_dark = __esm({
13520
+ "src/ui/themes/gruvbox-dark.json"() {
13521
+ gruvbox_dark_default = {
13522
+ name: "gruvbox-dark",
13523
+ label: "Gruvbox Dark",
13524
+ palette: {
13525
+ background: "#282828",
13526
+ foreground: "#ebdbb2",
13527
+ primary: "#b8bb26",
13528
+ secondary: "#928374",
13529
+ success: "#b8bb26",
13530
+ error: "#fb4934"
13531
+ },
13532
+ user: "#b8bb26",
13533
+ assistant: null,
13534
+ reasoning: { color: "#928374", dim: true },
13535
+ info: { color: "#ebdbb2", dim: false },
13536
+ error: "#fb4934",
13537
+ warn: "#fabd2f",
13538
+ tool: "#83a598",
13539
+ spinner: "#b8bb26",
13540
+ permission: "#fb4934",
13541
+ queue: { color: "#928374", dim: true },
13542
+ accent: "#b8bb26",
13543
+ modeBadge: {
13544
+ plan: "#b8bb26",
13545
+ auto: "#b8bb26",
13546
+ edit: "#fb4934"
13547
+ },
13548
+ blockquote: { color: "#928374", dim: true },
13549
+ codeInline: "#83a598",
13550
+ codeBlock: "#83a598",
13551
+ link: "#b8bb26",
13552
+ strikethrough: "#928374",
13553
+ tableBorder: "#504945",
13554
+ tableHeader: "#ebdbb2",
13555
+ tableCell: "#ebdbb2",
13556
+ muted: { color: "#928374", dim: true }
13557
+ };
13558
+ }
13559
+ });
13560
+
13561
+ // src/ui/themes/gruvbox-light.json
13562
+ var gruvbox_light_default;
13563
+ var init_gruvbox_light = __esm({
13564
+ "src/ui/themes/gruvbox-light.json"() {
13565
+ gruvbox_light_default = {
13566
+ name: "gruvbox-light",
13567
+ label: "Gruvbox Light",
13568
+ palette: {
13569
+ background: "#fbf1c7",
13570
+ foreground: "#3c3836",
13571
+ primary: "#79740e",
13572
+ secondary: "#928374",
13573
+ success: "#79740e",
13574
+ error: "#9d0006"
13575
+ },
13576
+ user: "#79740e",
13577
+ assistant: null,
13578
+ reasoning: { color: "#928374", dim: true },
13579
+ info: { color: "#3c3836", dim: false },
13580
+ error: "#9d0006",
13581
+ warn: "#b57614",
13582
+ tool: "#076678",
13583
+ spinner: "#79740e",
13584
+ permission: "#9d0006",
13585
+ queue: { color: "#928374", dim: true },
13586
+ accent: "#79740e",
13587
+ modeBadge: {
13588
+ plan: "#79740e",
13589
+ auto: "#79740e",
13590
+ edit: "#9d0006"
13591
+ },
13592
+ blockquote: { color: "#928374", dim: true },
13593
+ codeInline: "#076678",
13594
+ codeBlock: "#076678",
13595
+ link: "#79740e",
13596
+ strikethrough: "#928374",
13597
+ tableBorder: "#d5c4a1",
13598
+ tableHeader: "#3c3836",
13599
+ tableCell: "#3c3836",
13600
+ muted: { color: "#928374", dim: true }
13601
+ };
13602
+ }
13603
+ });
13604
+
13605
+ // src/ui/themes/one-dark.json
13606
+ var one_dark_default;
13607
+ var init_one_dark = __esm({
13608
+ "src/ui/themes/one-dark.json"() {
13609
+ one_dark_default = {
13610
+ name: "one-dark",
13611
+ label: "One Dark",
13612
+ palette: {
13613
+ background: "#282c34",
13614
+ foreground: "#abb2bf",
13615
+ primary: "#61afef",
13616
+ secondary: "#5c6370",
13617
+ success: "#98c379",
13618
+ error: "#e06c75"
13619
+ },
13620
+ user: "#61afef",
13621
+ assistant: null,
13622
+ reasoning: { color: "#5c6370", dim: true },
13623
+ info: { color: "#abb2bf", dim: false },
13624
+ error: "#e06c75",
13625
+ warn: "#e5c07b",
13626
+ tool: "#c678dd",
13627
+ spinner: "#61afef",
13628
+ permission: "#e06c75",
13629
+ queue: { color: "#5c6370", dim: true },
13630
+ accent: "#61afef",
13631
+ modeBadge: {
13632
+ plan: "#61afef",
13633
+ auto: "#98c379",
13634
+ edit: "#e06c75"
13635
+ },
13636
+ blockquote: { color: "#5c6370", dim: true },
13637
+ codeInline: "#c678dd",
13638
+ codeBlock: "#c678dd",
13639
+ link: "#61afef",
13640
+ strikethrough: "#5c6370",
13641
+ tableBorder: "#3e4451",
13642
+ tableHeader: "#abb2bf",
13643
+ tableCell: "#abb2bf",
13644
+ muted: { color: "#5c6370", dim: true }
13645
+ };
13646
+ }
13647
+ });
13648
+
13649
+ // src/ui/theme.ts
13650
+ function normalizeTheme(json) {
13651
+ const obj = json;
13652
+ const palette = obj.palette;
13653
+ const normalizeDim = (v) => {
13654
+ if (v === void 0) return void 0;
13655
+ if (typeof v === "string") return { color: v, dim: false };
13656
+ const d = v;
13657
+ return { color: String(d.color), dim: d.dim === true };
13658
+ };
13659
+ const normalizeColor2 = (v) => {
13660
+ if (v === void 0) return void 0;
13661
+ if (typeof v === "string") return v;
13662
+ const d = v;
13663
+ return String(d.color);
13664
+ };
13665
+ return {
13666
+ name: String(obj.name),
13667
+ label: String(obj.label),
12893
13668
  palette,
12894
- user: palette.primary,
12895
- tool: palette.secondary,
12896
- spinner: palette.primary,
12897
- accent: palette.primary,
12898
- error: palette.error,
12899
- warn: palette.error,
12900
- info: { color: palette.secondary, dim: false },
12901
- reasoning: { color: palette.secondary, dim: false },
12902
- permission: palette.error,
12903
- queue: { color: palette.secondary, dim: false },
12904
- assistant: void 0,
12905
- modeBadge: {
13669
+ user: String(obj.user ?? palette.primary),
13670
+ assistant: obj.assistant === null ? void 0 : typeof obj.assistant === "string" ? obj.assistant : void 0,
13671
+ reasoning: normalizeDim(obj.reasoning) ?? { color: palette.secondary, dim: false },
13672
+ info: normalizeDim(obj.info) ?? { color: palette.secondary, dim: false },
13673
+ error: String(obj.error ?? palette.error),
13674
+ warn: String(obj.warn ?? palette.error),
13675
+ tool: String(obj.tool ?? palette.secondary),
13676
+ spinner: String(obj.spinner ?? palette.primary),
13677
+ permission: String(obj.permission ?? palette.error),
13678
+ queue: normalizeDim(obj.queue) ?? { color: palette.secondary, dim: false },
13679
+ accent: String(obj.accent ?? palette.primary),
13680
+ modeBadge: obj.modeBadge ?? {
12906
13681
  plan: palette.primary,
12907
13682
  auto: palette.success,
12908
13683
  edit: palette.error
12909
- }
12910
- };
12911
- if (!overrides) return base;
12912
- return {
12913
- ...base,
12914
- ...overrides,
12915
- modeBadge: overrides.modeBadge ?? base.modeBadge,
12916
- info: overrides.info ?? base.info,
12917
- reasoning: overrides.reasoning ?? base.reasoning,
12918
- queue: overrides.queue ?? base.queue
13684
+ },
13685
+ blockquote: normalizeDim(obj.blockquote),
13686
+ codeInline: normalizeColor2(obj.codeInline),
13687
+ codeBlock: normalizeColor2(obj.codeBlock),
13688
+ link: normalizeColor2(obj.link),
13689
+ strikethrough: normalizeColor2(obj.strikethrough),
13690
+ tableBorder: normalizeColor2(obj.tableBorder),
13691
+ tableHeader: normalizeColor2(obj.tableHeader),
13692
+ tableCell: normalizeColor2(obj.tableCell),
13693
+ muted: normalizeDim(obj.muted)
12919
13694
  };
12920
13695
  }
13696
+ function setThemes(themes) {
13697
+ THEMES = themes;
13698
+ }
12921
13699
  function resolveTheme(name) {
12922
13700
  if (!name) return THEMES[DEFAULT_THEME_NAME];
12923
13701
  return THEMES[name] ?? THEMES[DEFAULT_THEME_NAME];
@@ -12928,44 +13706,341 @@ function themeNames() {
12928
13706
  function themeList() {
12929
13707
  return Object.values(THEMES);
12930
13708
  }
12931
- var everforestDark, everforestLight, kanagawaDark, draculaDark, THEMES, DEFAULT_THEME_NAME;
13709
+ var BUILT_IN_THEMES, THEMES, DEFAULT_THEME_NAME;
12932
13710
  var init_theme = __esm({
12933
13711
  "src/ui/theme.ts"() {
12934
13712
  "use strict";
12935
- everforestDark = buildTheme("everforest-dark", "everforest-dark", {
12936
- primary: "#a7c080",
12937
- secondary: "#d3c6aa",
12938
- success: "#a7c080",
12939
- error: "#e67e80"
12940
- });
12941
- everforestLight = buildTheme("everforest-light", "everforest-light", {
12942
- primary: "#c5e49a",
12943
- secondary: "#f0e6c8",
12944
- success: "#c5e49a",
12945
- error: "#e07070"
12946
- });
12947
- kanagawaDark = buildTheme("kanagawa-dark", "kanagawa-dark", {
12948
- primary: "#8aadf4",
12949
- secondary: "#f0e6c8",
12950
- success: "#a6e3a1",
12951
- error: "#f38ba8"
12952
- });
12953
- draculaDark = buildTheme("dracula-dark", "dracula-dark", {
12954
- primary: "#ff79c6",
12955
- secondary: "#f8f8f2",
12956
- success: "#50fa7b",
12957
- error: "#ff5555"
12958
- });
12959
- THEMES = {
12960
- "everforest-dark": everforestDark,
12961
- "everforest-light": everforestLight,
12962
- "kanagawa-dark": kanagawaDark,
12963
- "dracula-dark": draculaDark
13713
+ init_everforest_dark();
13714
+ init_everforest_light();
13715
+ init_kanagawa_dark();
13716
+ init_dracula_dark();
13717
+ init_tokyo_night();
13718
+ init_catppuccin_mocha();
13719
+ init_catppuccin_latte();
13720
+ init_solarized_dark();
13721
+ init_solarized_light();
13722
+ init_nord();
13723
+ init_gruvbox_dark();
13724
+ init_gruvbox_light();
13725
+ init_one_dark();
13726
+ BUILT_IN_THEMES = {
13727
+ "everforest-dark": normalizeTheme(everforest_dark_default),
13728
+ "everforest-light": normalizeTheme(everforest_light_default),
13729
+ "kanagawa-dark": normalizeTheme(kanagawa_dark_default),
13730
+ "dracula-dark": normalizeTheme(dracula_dark_default),
13731
+ "tokyo-night": normalizeTheme(tokyo_night_default),
13732
+ "catppuccin-mocha": normalizeTheme(catppuccin_mocha_default),
13733
+ "catppuccin-latte": normalizeTheme(catppuccin_latte_default),
13734
+ "solarized-dark": normalizeTheme(solarized_dark_default),
13735
+ "solarized-light": normalizeTheme(solarized_light_default),
13736
+ "nord": normalizeTheme(nord_default),
13737
+ "gruvbox-dark": normalizeTheme(gruvbox_dark_default),
13738
+ "gruvbox-light": normalizeTheme(gruvbox_light_default),
13739
+ "one-dark": normalizeTheme(one_dark_default)
12964
13740
  };
13741
+ THEMES = { ...BUILT_IN_THEMES };
12965
13742
  DEFAULT_THEME_NAME = "everforest-dark";
12966
13743
  }
12967
13744
  });
12968
13745
 
13746
+ // src/ui/wcag.ts
13747
+ function hexToRgb(hex) {
13748
+ const m = hex.match(/^#([0-9a-fA-F]{6})$/);
13749
+ if (!m) return null;
13750
+ const v = parseInt(m[1], 16);
13751
+ return {
13752
+ r: v >> 16 & 255,
13753
+ g: v >> 8 & 255,
13754
+ b: v & 255
13755
+ };
13756
+ }
13757
+ function relativeLuminance({ r, g, b }) {
13758
+ const toLinear = (c) => {
13759
+ const s = c / 255;
13760
+ return s <= 0.03928 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4);
13761
+ };
13762
+ return 0.2126 * toLinear(r) + 0.7152 * toLinear(g) + 0.0722 * toLinear(b);
13763
+ }
13764
+ function contrastRatio(a, b) {
13765
+ const rgbA = hexToRgb(a);
13766
+ const rgbB = hexToRgb(b);
13767
+ if (!rgbA || !rgbB) return null;
13768
+ const l1 = relativeLuminance(rgbA);
13769
+ const l2 = relativeLuminance(rgbB);
13770
+ const lighter = Math.max(l1, l2);
13771
+ const darker = Math.min(l1, l2);
13772
+ return (lighter + 0.05) / (darker + 0.05);
13773
+ }
13774
+ function checkContrast(foreground, background, required = 4.5) {
13775
+ const ratio = contrastRatio(foreground, background);
13776
+ if (ratio === null) return null;
13777
+ if (ratio >= required) return null;
13778
+ return {
13779
+ pair: `${foreground} on ${background}`,
13780
+ foreground,
13781
+ background,
13782
+ ratio: Math.round(ratio * 100) / 100,
13783
+ required
13784
+ };
13785
+ }
13786
+ var init_wcag = __esm({
13787
+ "src/ui/wcag.ts"() {
13788
+ "use strict";
13789
+ }
13790
+ });
13791
+
13792
+ // src/ui/theme-loader.ts
13793
+ import { readFile as readFile18, readdir as readdir5 } from "fs/promises";
13794
+ import { join as join23 } from "path";
13795
+ import { homedir as homedir14 } from "os";
13796
+ function projectThemesDir(cwd = process.cwd()) {
13797
+ return join23(cwd, ".kimiflare", "themes");
13798
+ }
13799
+ function isHexColor(c) {
13800
+ return /^#[0-9a-fA-F]{6}$/.test(c);
13801
+ }
13802
+ function validateHex(field, value, errors) {
13803
+ if (value === void 0) return;
13804
+ if (!isHexColor(value)) {
13805
+ errors.push(`${field}: "${value}" is not a valid #RRGGBB hex color`);
13806
+ }
13807
+ }
13808
+ function validatePalette(p, errors) {
13809
+ if (!p || typeof p !== "object") {
13810
+ errors.push("palette must be an object");
13811
+ return null;
13812
+ }
13813
+ const palette = p;
13814
+ const required = ["background", "foreground", "primary", "secondary", "success", "error"];
13815
+ for (const key of required) {
13816
+ if (typeof palette[key] !== "string") {
13817
+ errors.push(`palette.${key} is required and must be a string`);
13818
+ } else {
13819
+ validateHex(`palette.${key}`, palette[key], errors);
13820
+ }
13821
+ }
13822
+ if (errors.length > 0) return null;
13823
+ return {
13824
+ background: palette.background,
13825
+ foreground: palette.foreground,
13826
+ primary: palette.primary,
13827
+ secondary: palette.secondary,
13828
+ success: palette.success,
13829
+ error: palette.error
13830
+ };
13831
+ }
13832
+ function validateDimColor(field, value, errors) {
13833
+ if (value === void 0) return void 0;
13834
+ if (typeof value === "string") {
13835
+ validateHex(field, value, errors);
13836
+ return { color: value, dim: false };
13837
+ }
13838
+ if (!value || typeof value !== "object") {
13839
+ errors.push(`${field} must be a string or { color, dim } object`);
13840
+ return void 0;
13841
+ }
13842
+ const obj = value;
13843
+ if (typeof obj.color !== "string") {
13844
+ errors.push(`${field}.color is required`);
13845
+ return void 0;
13846
+ }
13847
+ validateHex(`${field}.color`, obj.color, errors);
13848
+ return {
13849
+ color: obj.color,
13850
+ dim: obj.dim === true
13851
+ };
13852
+ }
13853
+ function validateModeBadge(value, errors) {
13854
+ if (value === void 0) return void 0;
13855
+ if (!value || typeof value !== "object") {
13856
+ errors.push("modeBadge must be an object");
13857
+ return void 0;
13858
+ }
13859
+ const obj = value;
13860
+ const result = {};
13861
+ for (const key of ["plan", "auto", "edit"]) {
13862
+ if (typeof obj[key] !== "string") {
13863
+ errors.push(`modeBadge.${key} is required`);
13864
+ } else {
13865
+ validateHex(`modeBadge.${key}`, obj[key], errors);
13866
+ result[key] = obj[key];
13867
+ }
13868
+ }
13869
+ return result;
13870
+ }
13871
+ function normalizeColor(v) {
13872
+ if (v === void 0) return void 0;
13873
+ if (typeof v === "string") return v;
13874
+ const d = v;
13875
+ return typeof d.color === "string" ? d.color : void 0;
13876
+ }
13877
+ async function loadThemesFromDir(dir, source) {
13878
+ const themes = [];
13879
+ const errors = [];
13880
+ let files;
13881
+ try {
13882
+ files = await readdir5(dir);
13883
+ } catch {
13884
+ return { themes, errors };
13885
+ }
13886
+ for (const file of files.filter((f) => f.endsWith(".json"))) {
13887
+ const path = join23(dir, file);
13888
+ let raw;
13889
+ try {
13890
+ raw = await readFile18(path, "utf-8");
13891
+ } catch (e) {
13892
+ errors.push(`${path}: ${e instanceof Error ? e.message : String(e)}`);
13893
+ continue;
13894
+ }
13895
+ let json;
13896
+ try {
13897
+ json = JSON.parse(raw);
13898
+ } catch (e) {
13899
+ errors.push(`${path}: invalid JSON \u2014 ${e instanceof Error ? e.message : String(e)}`);
13900
+ continue;
13901
+ }
13902
+ if (!json || typeof json !== "object") {
13903
+ errors.push(`${path}: root must be an object`);
13904
+ continue;
13905
+ }
13906
+ const obj = json;
13907
+ const fileErrors = [];
13908
+ if (typeof obj.name !== "string" || obj.name.length === 0) {
13909
+ fileErrors.push("name is required");
13910
+ }
13911
+ if (typeof obj.label !== "string" || obj.label.length === 0) {
13912
+ fileErrors.push("label is required");
13913
+ }
13914
+ const palette = validatePalette(obj.palette, fileErrors);
13915
+ if (fileErrors.length > 0) {
13916
+ errors.push(...fileErrors.map((e) => `${path}: ${e}`));
13917
+ continue;
13918
+ }
13919
+ if (!palette) continue;
13920
+ const theme = {
13921
+ name: obj.name,
13922
+ label: obj.label,
13923
+ palette,
13924
+ user: typeof obj.user === "string" ? obj.user : palette.primary,
13925
+ assistant: obj.assistant === null ? void 0 : typeof obj.assistant === "string" ? obj.assistant : void 0,
13926
+ reasoning: validateDimColor("reasoning", obj.reasoning, fileErrors) ?? { color: palette.secondary, dim: false },
13927
+ info: validateDimColor("info", obj.info, fileErrors) ?? { color: palette.secondary, dim: false },
13928
+ error: typeof obj.error === "string" ? obj.error : palette.error,
13929
+ warn: typeof obj.warn === "string" ? obj.warn : palette.error,
13930
+ tool: typeof obj.tool === "string" ? obj.tool : palette.secondary,
13931
+ spinner: typeof obj.spinner === "string" ? obj.spinner : palette.primary,
13932
+ permission: typeof obj.permission === "string" ? obj.permission : palette.error,
13933
+ queue: validateDimColor("queue", obj.queue, fileErrors) ?? { color: palette.secondary, dim: false },
13934
+ accent: typeof obj.accent === "string" ? obj.accent : palette.primary,
13935
+ modeBadge: validateModeBadge(obj.modeBadge, fileErrors) ?? {
13936
+ plan: palette.primary,
13937
+ auto: palette.success,
13938
+ edit: palette.error
13939
+ },
13940
+ blockquote: validateDimColor("blockquote", obj.blockquote, fileErrors),
13941
+ codeInline: normalizeColor(obj.codeInline),
13942
+ codeBlock: normalizeColor(obj.codeBlock),
13943
+ link: normalizeColor(obj.link),
13944
+ strikethrough: normalizeColor(obj.strikethrough),
13945
+ tableBorder: normalizeColor(obj.tableBorder),
13946
+ tableHeader: normalizeColor(obj.tableHeader),
13947
+ tableCell: normalizeColor(obj.tableCell),
13948
+ muted: validateDimColor("muted", obj.muted, fileErrors)
13949
+ };
13950
+ if (fileErrors.length > 0) {
13951
+ errors.push(...fileErrors.map((e) => `${path}: ${e}`));
13952
+ continue;
13953
+ }
13954
+ const wcagIssues = [];
13955
+ const bg = palette.background;
13956
+ const check = (label, color) => {
13957
+ if (!color) return;
13958
+ const issue = checkContrast(color, bg);
13959
+ if (issue) wcagIssues.push({ ...issue, pair: `${label} (${issue.pair})` });
13960
+ };
13961
+ check("foreground", palette.foreground);
13962
+ check("user", theme.user);
13963
+ check("assistant", theme.assistant);
13964
+ check("reasoning", theme.reasoning.color);
13965
+ check("info", theme.info.color);
13966
+ check("error", theme.error);
13967
+ check("warn", theme.warn);
13968
+ check("tool", theme.tool);
13969
+ check("accent", theme.accent);
13970
+ check("link", theme.link);
13971
+ check("codeInline", theme.codeInline);
13972
+ check("codeBlock", theme.codeBlock);
13973
+ check("tableHeader", theme.tableHeader);
13974
+ check("tableCell", theme.tableCell);
13975
+ themes.push({ theme, source, path, wcagIssues });
13976
+ }
13977
+ return { themes, errors };
13978
+ }
13979
+ async function loadAllThemes(cwd = process.cwd()) {
13980
+ if (cachedResult) return cachedResult;
13981
+ const themes = {};
13982
+ const errors = [];
13983
+ for (const [name, theme] of Object.entries(THEMES)) {
13984
+ themes[name] = {
13985
+ theme,
13986
+ source: "built-in",
13987
+ path: "<built-in>",
13988
+ wcagIssues: []
13989
+ };
13990
+ }
13991
+ const user = await loadThemesFromDir(USER_THEMES_DIR, "user");
13992
+ for (const t of user.themes) {
13993
+ themes[t.theme.name] = t;
13994
+ }
13995
+ errors.push(...user.errors);
13996
+ const project = await loadThemesFromDir(projectThemesDir(cwd), "project");
13997
+ for (const t of project.themes) {
13998
+ themes[t.theme.name] = t;
13999
+ }
14000
+ errors.push(...project.errors);
14001
+ cachedResult = { themes, errors };
14002
+ return cachedResult;
14003
+ }
14004
+ function clearThemeCache() {
14005
+ cachedResult = null;
14006
+ }
14007
+ async function loadAndMergeThemes(cwd = process.cwd()) {
14008
+ clearThemeCache();
14009
+ const { themes, errors } = await loadAllThemes(cwd);
14010
+ const merged = {};
14011
+ for (const [name, t] of Object.entries(THEMES)) {
14012
+ merged[name] = t;
14013
+ }
14014
+ for (const t of Object.values(themes)) {
14015
+ merged[t.theme.name] = t.theme;
14016
+ }
14017
+ setThemes(merged);
14018
+ const wcagWarnings = [];
14019
+ for (const t of Object.values(themes)) {
14020
+ if (t.wcagIssues.length > 0 && t.source !== "built-in") {
14021
+ wcagWarnings.push(
14022
+ `Theme "${t.theme.label}" has WCAG contrast issues:
14023
+ ` + t.wcagIssues.map((i) => ` ${i.pair}: ${i.ratio}:1 (needs ${i.required}:1)`).join("\n")
14024
+ );
14025
+ }
14026
+ }
14027
+ return { errors, wcagWarnings };
14028
+ }
14029
+ var USER_THEMES_DIR, cachedResult;
14030
+ var init_theme_loader = __esm({
14031
+ "src/ui/theme-loader.ts"() {
14032
+ "use strict";
14033
+ init_wcag();
14034
+ init_theme();
14035
+ USER_THEMES_DIR = join23(
14036
+ process.env.XDG_CONFIG_HOME || join23(homedir14(), ".config"),
14037
+ "kimiflare",
14038
+ "themes"
14039
+ );
14040
+ cachedResult = null;
14041
+ }
14042
+ });
14043
+
12969
14044
  // src/util/lsp-nudge.ts
12970
14045
  function maybeLspNudge(userText, lspEnabled, lspServers) {
12971
14046
  if (lspEnabled && Object.keys(lspServers).length > 0) {
@@ -13015,8 +14090,8 @@ var init_lsp_nudge = __esm({
13015
14090
  });
13016
14091
 
13017
14092
  // src/ui/file-picker.tsx
13018
- import { Box as Box19, Text as Text20 } from "ink";
13019
- import { jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
14093
+ import { Box as Box18, Text as Text19 } from "ink";
14094
+ import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
13020
14095
  function FilePicker({ items, selectedIndex, query }) {
13021
14096
  const theme = useTheme();
13022
14097
  let startIndex = 0;
@@ -13026,12 +14101,12 @@ function FilePicker({ items, selectedIndex, query }) {
13026
14101
  const visible = items.slice(startIndex, startIndex + VISIBLE_LIMIT);
13027
14102
  const hasMoreAbove = startIndex > 0;
13028
14103
  const hasMoreBelow = items.length > startIndex + VISIBLE_LIMIT;
13029
- return /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
13030
- /* @__PURE__ */ jsx21(Text20, { color: theme.accent, bold: true, children: query ? `Files matching "${query}"` : "Mention a file" }),
13031
- /* @__PURE__ */ jsx21(Text20, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select, Esc to cancel." }),
13032
- /* @__PURE__ */ jsxs19(Box19, { marginTop: 1, flexDirection: "column", children: [
13033
- visible.length === 0 && /* @__PURE__ */ jsx21(Text20, { color: theme.info.color, children: "No matches" }),
13034
- hasMoreAbove && /* @__PURE__ */ jsxs19(Text20, { color: theme.info.color, children: [
14104
+ return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
14105
+ /* @__PURE__ */ jsx20(Text19, { color: theme.accent, bold: true, children: query ? `Files matching "${query}"` : "Mention a file" }),
14106
+ /* @__PURE__ */ jsx20(Text19, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select, Esc to cancel." }),
14107
+ /* @__PURE__ */ jsxs18(Box18, { marginTop: 1, flexDirection: "column", children: [
14108
+ visible.length === 0 && /* @__PURE__ */ jsx20(Text19, { color: theme.info.color, children: "No matches" }),
14109
+ hasMoreAbove && /* @__PURE__ */ jsxs18(Text19, { color: theme.info.color, children: [
13035
14110
  "\u2026 ",
13036
14111
  startIndex,
13037
14112
  " more above"
@@ -13040,12 +14115,12 @@ function FilePicker({ items, selectedIndex, query }) {
13040
14115
  const actualIndex = startIndex + i;
13041
14116
  const isSelected = actualIndex === selectedIndex;
13042
14117
  const label = item.isDirectory ? `${item.name}/` : item.name;
13043
- return /* @__PURE__ */ jsxs19(Text20, { color: isSelected ? theme.accent : void 0, bold: isSelected, children: [
14118
+ return /* @__PURE__ */ jsxs18(Text19, { color: isSelected ? theme.accent : void 0, bold: isSelected, children: [
13044
14119
  isSelected ? "\u203A " : " ",
13045
14120
  label
13046
14121
  ] }, item.name);
13047
14122
  }),
13048
- hasMoreBelow && /* @__PURE__ */ jsxs19(Text20, { color: theme.info.color, children: [
14123
+ hasMoreBelow && /* @__PURE__ */ jsxs18(Text19, { color: theme.info.color, children: [
13049
14124
  "\u2026 ",
13050
14125
  items.length - (startIndex + VISIBLE_LIMIT),
13051
14126
  " more below"
@@ -13063,8 +14138,8 @@ var init_file_picker = __esm({
13063
14138
  });
13064
14139
 
13065
14140
  // src/ui/slash-picker.tsx
13066
- import { Box as Box20, Text as Text21 } from "ink";
13067
- import { jsx as jsx22, jsxs as jsxs20 } from "react/jsx-runtime";
14141
+ import { Box as Box19, Text as Text20 } from "ink";
14142
+ import { jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
13068
14143
  function sourceBadge(source) {
13069
14144
  if (source === "builtin") return "";
13070
14145
  if (source === "project") return "project";
@@ -13084,12 +14159,12 @@ function SlashPicker({ items, selectedIndex, query }) {
13084
14159
  const hasMoreBelow = items.length > startIndex + VISIBLE_LIMIT2;
13085
14160
  const longestLabel = visible.reduce((m, it) => Math.max(m, commandLabel(it).length), 0);
13086
14161
  const nameColWidth = Math.max(NAME_COL_MIN_WIDTH, longestLabel + NAME_DESC_GAP);
13087
- return /* @__PURE__ */ jsxs20(Box20, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
13088
- /* @__PURE__ */ jsx22(Text21, { color: theme.accent, bold: true, children: query ? `Commands matching "/${query}"` : "Slash commands" }),
13089
- /* @__PURE__ */ jsx22(Text21, { color: theme.info.color, children: "Arrow keys to navigate, Enter to select, Esc to cancel." }),
13090
- /* @__PURE__ */ jsxs20(Box20, { marginTop: 1, flexDirection: "column", children: [
13091
- visible.length === 0 && /* @__PURE__ */ jsx22(Text21, { color: theme.info.color, children: "No matches" }),
13092
- hasMoreAbove && /* @__PURE__ */ jsxs20(Text21, { color: theme.info.color, children: [
14162
+ return /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
14163
+ /* @__PURE__ */ jsx21(Text20, { color: theme.accent, bold: true, children: query ? `Commands matching "/${query}"` : "Slash commands" }),
14164
+ /* @__PURE__ */ jsx21(Text20, { color: theme.info.color, children: "Arrow keys to navigate, Enter to select, Esc to cancel." }),
14165
+ /* @__PURE__ */ jsxs19(Box19, { marginTop: 1, flexDirection: "column", children: [
14166
+ visible.length === 0 && /* @__PURE__ */ jsx21(Text20, { color: theme.info.color, children: "No matches" }),
14167
+ hasMoreAbove && /* @__PURE__ */ jsxs19(Text20, { color: theme.info.color, children: [
13093
14168
  "\u2026 ",
13094
14169
  startIndex,
13095
14170
  " more above"
@@ -13099,16 +14174,16 @@ function SlashPicker({ items, selectedIndex, query }) {
13099
14174
  const isSelected = actualIndex === selectedIndex;
13100
14175
  const nameCol = commandLabel(item).padEnd(nameColWidth);
13101
14176
  const badge = sourceBadge(item.source);
13102
- return /* @__PURE__ */ jsxs20(Text21, { color: isSelected ? theme.accent : void 0, bold: isSelected, children: [
14177
+ return /* @__PURE__ */ jsxs19(Text20, { color: isSelected ? theme.accent : void 0, bold: isSelected, children: [
13103
14178
  isSelected ? "\u203A " : " ",
13104
14179
  nameCol,
13105
- /* @__PURE__ */ jsxs20(Text21, { color: theme.info.color, children: [
14180
+ /* @__PURE__ */ jsxs19(Text20, { color: theme.info.color, children: [
13106
14181
  item.description,
13107
14182
  badge && ` [${badge}]`
13108
14183
  ] })
13109
14184
  ] }, item.name);
13110
14185
  }),
13111
- hasMoreBelow && /* @__PURE__ */ jsxs20(Text21, { color: theme.info.color, children: [
14186
+ hasMoreBelow && /* @__PURE__ */ jsxs19(Text20, { color: theme.info.color, children: [
13112
14187
  "\u2026 ",
13113
14188
  items.length - (startIndex + VISIBLE_LIMIT2),
13114
14189
  " more below"
@@ -13188,15 +14263,15 @@ var tui_report_exports = {};
13188
14263
  __export(tui_report_exports, {
13189
14264
  getCategoryReportText: () => getCategoryReportText
13190
14265
  });
13191
- import { readFile as readFile16 } from "fs/promises";
13192
- import { join as join21 } from "path";
13193
- import { homedir as homedir14 } from "os";
14266
+ import { readFile as readFile19 } from "fs/promises";
14267
+ import { join as join24 } from "path";
14268
+ import { homedir as homedir15 } from "os";
13194
14269
  function usageDir3() {
13195
- const xdg = process.env.XDG_DATA_HOME || join21(homedir14(), ".local", "share");
13196
- return join21(xdg, "kimiflare");
14270
+ const xdg = process.env.XDG_DATA_HOME || join24(homedir15(), ".local", "share");
14271
+ return join24(xdg, "kimiflare");
13197
14272
  }
13198
14273
  function usagePath3() {
13199
- return join21(usageDir3(), "usage.json");
14274
+ return join24(usageDir3(), "usage.json");
13200
14275
  }
13201
14276
  function today3() {
13202
14277
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
@@ -13208,7 +14283,7 @@ function daysAgo2(n) {
13208
14283
  }
13209
14284
  async function loadLog3() {
13210
14285
  try {
13211
- const raw = await readFile16(usagePath3(), "utf8");
14286
+ const raw = await readFile19(usagePath3(), "utf8");
13212
14287
  return JSON.parse(raw);
13213
14288
  } catch {
13214
14289
  return { version: 1, days: [], sessions: [] };
@@ -13274,18 +14349,18 @@ __export(app_exports, {
13274
14349
  shouldOpenMentionPicker: () => shouldOpenMentionPicker,
13275
14350
  shouldOpenSlashPicker: () => shouldOpenSlashPicker
13276
14351
  });
13277
- import React14, { useState as useState10, useRef as useRef3, useEffect as useEffect6, useCallback as useCallback2 } from "react";
13278
- import { Box as Box21, Text as Text22, useApp, useInput as useInput7, render } from "ink";
13279
- import SelectInput11 from "ink-select-input";
14352
+ import React13, { useState as useState10, useRef as useRef3, useEffect as useEffect7, useCallback as useCallback2 } from "react";
14353
+ import { Box as Box20, Text as Text21, useApp, useInput as useInput6, render } from "ink";
14354
+ import SelectInput10 from "ink-select-input";
13280
14355
  import { existsSync as existsSync3, statSync as statSync4 } from "fs";
13281
- import { join as join22 } from "path";
13282
- import { unlink as unlink3 } from "fs/promises";
14356
+ import { join as join25 } from "path";
14357
+ import { unlink as unlink4 } from "fs/promises";
13283
14358
  import { execSync as execSync2 } from "child_process";
13284
14359
  import { spawn as spawn4 } from "child_process";
13285
14360
  import { platform as platform2 } from "os";
13286
14361
  import fg4 from "fast-glob";
13287
14362
  import { readFileSync as readFileSync3 } from "fs";
13288
- import { jsx as jsx23, jsxs as jsxs21 } from "react/jsx-runtime";
14363
+ import { jsx as jsx22, jsxs as jsxs20 } from "react/jsx-runtime";
13289
14364
  function buildFilePickerIgnoreList(cwd) {
13290
14365
  const hardcoded = [
13291
14366
  // Dependencies
@@ -13356,7 +14431,7 @@ function buildFilePickerIgnoreList(cwd) {
13356
14431
  ];
13357
14432
  const gitignorePatterns = [];
13358
14433
  try {
13359
- const gitignorePath = join22(cwd, ".gitignore");
14434
+ const gitignorePath = join25(cwd, ".gitignore");
13360
14435
  const stats = statSync4(gitignorePath);
13361
14436
  if (stats.size > MAX_GITIGNORE_SIZE) {
13362
14437
  return hardcoded;
@@ -13549,7 +14624,6 @@ function App({
13549
14624
  initialCfg?.reasoningEffort ?? DEFAULT_REASONING_EFFORT
13550
14625
  );
13551
14626
  const [resumeSessions, setResumeSessions] = useState10(null);
13552
- const [showHelpMenu, setShowHelpMenu] = useState10(false);
13553
14627
  const [commandWizard, setCommandWizard] = useState10(null);
13554
14628
  const [commandPicker, setCommandPicker] = useState10(null);
13555
14629
  const [commandToDelete, setCommandToDelete] = useState10(null);
@@ -13561,13 +14635,45 @@ function App({
13561
14635
  const [tasksStartedAt, setTasksStartedAt] = useState10(null);
13562
14636
  const [tasksStartTokens, setTasksStartTokens] = useState10(0);
13563
14637
  const [turnStartedAt, setTurnStartedAt] = useState10(null);
14638
+ const [turnPhase, setTurnPhase] = useState10("waiting");
14639
+ const [currentToolName, setCurrentToolName] = useState10(null);
14640
+ const [lastActivityAt, setLastActivityAt] = useState10(null);
13564
14641
  const [verbose, setVerbose] = useState10(false);
13565
14642
  const [hasUpdate, setHasUpdate] = useState10(initialUpdateResult?.hasUpdate ?? false);
13566
14643
  const [latestVersion, setLatestVersion] = useState10(initialUpdateResult?.latestVersion ?? null);
13567
14644
  const [theme, setTheme] = useState10(resolveTheme(initialCfg?.theme));
13568
14645
  const [showThemePicker, setShowThemePicker] = useState10(false);
14646
+ const [originalTheme, setOriginalTheme] = useState10(null);
14647
+ const [skillsActive, setSkillsActive] = useState10(0);
14648
+ const [memoryRecalled, setMemoryRecalled] = useState10(false);
14649
+ const [intentTier, setIntentTier] = useState10(null);
14650
+ const skillsDirRef = useRef3(join25(process.cwd(), ".kimiflare", "skills"));
13569
14651
  const [kimiMdStale, setKimiMdStale] = useState10(false);
13570
- useEffect6(() => {
14652
+ useEffect7(() => {
14653
+ let cancelled = false;
14654
+ loadAndMergeThemes().then(({ errors, wcagWarnings }) => {
14655
+ if (cancelled) return;
14656
+ if (errors.length > 0) {
14657
+ setEvents((e) => [
14658
+ ...e,
14659
+ { kind: "error", key: mkKey(), text: `theme load errors:
14660
+ ${errors.join("\n")}` }
14661
+ ]);
14662
+ }
14663
+ if (wcagWarnings.length > 0) {
14664
+ setEvents((e) => [
14665
+ ...e,
14666
+ { kind: "info", key: mkKey(), text: `theme WCAG warnings:
14667
+ ${wcagWarnings.join("\n")}` }
14668
+ ]);
14669
+ }
14670
+ setTheme(resolveTheme(initialCfg?.theme));
14671
+ });
14672
+ return () => {
14673
+ cancelled = true;
14674
+ };
14675
+ }, []);
14676
+ useEffect7(() => {
13571
14677
  if (!cfg?.cloudMode || !initialCloudToken) return;
13572
14678
  let cancelled = false;
13573
14679
  const fetchBudget = async () => {
@@ -13628,20 +14734,20 @@ function App({
13628
14734
  const flushTimeoutRef = useRef3(null);
13629
14735
  const customCommandsRef = useRef3([]);
13630
14736
  const pickerCancelRef = useRef3(null);
13631
- useEffect6(() => {
14737
+ useEffect7(() => {
13632
14738
  busyRef.current = busy;
13633
14739
  }, [busy]);
13634
14740
  const pickerAnchor = activePicker?.anchor ?? null;
13635
14741
  const pickerKind = activePicker?.kind ?? null;
13636
- const pickerQuery = React14.useMemo(() => {
14742
+ const pickerQuery = React13.useMemo(() => {
13637
14743
  if (pickerAnchor === null) return null;
13638
14744
  return input.slice(pickerAnchor + 1, cursorOffset);
13639
14745
  }, [input, cursorOffset, pickerAnchor]);
13640
- const filteredFileItems = React14.useMemo(() => {
14746
+ const filteredFileItems = React13.useMemo(() => {
13641
14747
  if (pickerKind !== "file" || pickerQuery === null) return [];
13642
14748
  return filterPickerItems(filePickerItems, pickerQuery);
13643
14749
  }, [pickerKind, filePickerItems, pickerQuery]);
13644
- const allSlashCommands = React14.useMemo(() => {
14750
+ const allSlashCommands = React13.useMemo(() => {
13645
14751
  const customs = customCommandsRef.current.filter((c) => !BUILTIN_COMMAND_NAMES.has(c.name.toLowerCase())).map((c) => ({
13646
14752
  name: c.name,
13647
14753
  description: c.description ?? "",
@@ -13649,11 +14755,11 @@ function App({
13649
14755
  }));
13650
14756
  return [...BUILTIN_COMMANDS, ...customs];
13651
14757
  }, [customCommandsVersion]);
13652
- const filteredSlashItems = React14.useMemo(() => {
14758
+ const filteredSlashItems = React13.useMemo(() => {
13653
14759
  if (pickerKind !== "slash" || pickerQuery === null) return [];
13654
14760
  return fuzzyFilter(allSlashCommands, pickerQuery, (c) => c.name).slice(0, 50);
13655
14761
  }, [pickerKind, allSlashCommands, pickerQuery]);
13656
- useEffect6(() => {
14762
+ useEffect7(() => {
13657
14763
  if (activePicker !== null) {
13658
14764
  const trigger = activePicker.kind === "file" ? "@" : "/";
13659
14765
  if (cursorOffset < activePicker.anchor) {
@@ -13710,14 +14816,14 @@ function App({
13710
14816
  return;
13711
14817
  }
13712
14818
  }, [input, cursorOffset, activePicker, filePickerEnabled]);
13713
- useEffect6(() => {
14819
+ useEffect7(() => {
13714
14820
  if (activePicker?.kind !== "file") return;
13715
14821
  const max = Math.max(0, filteredFileItems.length - 1);
13716
14822
  if (activePicker.selected > max) {
13717
14823
  setActivePicker({ ...activePicker, selected: max });
13718
14824
  }
13719
14825
  }, [filteredFileItems.length, activePicker]);
13720
- useEffect6(() => {
14826
+ useEffect7(() => {
13721
14827
  if (activePicker?.kind !== "slash") return;
13722
14828
  const max = Math.max(0, filteredSlashItems.length - 1);
13723
14829
  if (activePicker.selected > max) {
@@ -13761,13 +14867,12 @@ function App({
13761
14867
  pickerCancelRef.current = cursorOffset;
13762
14868
  setActivePicker(null);
13763
14869
  }, [cursorOffset]);
13764
- useEffect6(() => {
13765
- const modalActive = showHelpMenu || commandWizard !== null || commandPicker !== null || commandToDelete !== null || showCommandList || showLspWizard || resumeSessions !== null || perm !== null || limitModal !== null;
14870
+ useEffect7(() => {
14871
+ const modalActive = commandWizard !== null || commandPicker !== null || commandToDelete !== null || showCommandList || showLspWizard || resumeSessions !== null || perm !== null || limitModal !== null;
13766
14872
  if (modalActive && activePicker !== null) {
13767
14873
  setActivePicker(null);
13768
14874
  }
13769
14875
  }, [
13770
- showHelpMenu,
13771
14876
  commandWizard,
13772
14877
  commandPicker,
13773
14878
  commandToDelete,
@@ -13778,7 +14883,7 @@ function App({
13778
14883
  limitModal,
13779
14884
  activePicker
13780
14885
  ]);
13781
- useEffect6(() => {
14886
+ useEffect7(() => {
13782
14887
  if (!cfg) return;
13783
14888
  void Promise.resolve().then(() => (init_sessions(), sessions_exports)).then(
13784
14889
  ({ pruneSessions: pruneSessions2 }) => pruneSessions2().then((removed) => {
@@ -13804,7 +14909,7 @@ function App({
13804
14909
  }
13805
14910
  });
13806
14911
  if (cfg.memoryEnabled) {
13807
- const dbPath = cfg.memoryDbPath ?? join22(process.cwd(), ".kimiflare", "memory.db");
14912
+ const dbPath = cfg.memoryDbPath ?? join25(process.cwd(), ".kimiflare", "memory.db");
13808
14913
  const manager = new MemoryManager({
13809
14914
  dbPath,
13810
14915
  accountId: cfg.accountId,
@@ -13853,7 +14958,7 @@ function App({
13853
14958
  } catch {
13854
14959
  }
13855
14960
  })();
13856
- if (existsSync3(join22(cwd, "KIMI.md"))) {
14961
+ if (existsSync3(join25(cwd, "KIMI.md"))) {
13857
14962
  const lastRefresh = manager.getLastKimiMdRefreshTime(cwd);
13858
14963
  const driftCount = manager.countHighSignalMemoriesSince(cwd, lastRefresh);
13859
14964
  if (driftCount >= 5) {
@@ -13879,7 +14984,7 @@ function App({
13879
14984
  }
13880
14985
  });
13881
14986
  }, [cfg, setEvents]);
13882
- useEffect6(() => {
14987
+ useEffect7(() => {
13883
14988
  const id = setInterval(() => {
13884
14989
  try {
13885
14990
  performance.clearMarks();
@@ -13904,7 +15009,7 @@ function App({
13904
15009
  ]);
13905
15010
  }
13906
15011
  }, [setEvents]);
13907
- useEffect6(() => {
15012
+ useEffect7(() => {
13908
15013
  if (!cfg || updateCheckedRef.current) return;
13909
15014
  updateCheckedRef.current = true;
13910
15015
  if (initialUpdateResult) {
@@ -13955,7 +15060,7 @@ function App({
13955
15060
  }
13956
15061
  });
13957
15062
  }, [cfg, initialUpdateResult]);
13958
- useEffect6(() => {
15063
+ useEffect7(() => {
13959
15064
  modeRef.current = mode;
13960
15065
  if (cacheStableRef.current) {
13961
15066
  messagesRef.current[1] = {
@@ -13982,10 +15087,10 @@ function App({
13982
15087
  executorRef.current.clearSessionPermissions();
13983
15088
  }
13984
15089
  }, [mode, cfg?.model]);
13985
- useEffect6(() => {
15090
+ useEffect7(() => {
13986
15091
  effortRef.current = effort;
13987
15092
  }, [effort]);
13988
- useEffect6(() => {
15093
+ useEffect7(() => {
13989
15094
  if (!cfg) return;
13990
15095
  const id = setInterval(() => {
13991
15096
  void checkForUpdate().then((result) => {
@@ -14140,7 +15245,7 @@ function App({
14140
15245
  ]);
14141
15246
  }
14142
15247
  }, [cfg]);
14143
- useEffect6(() => {
15248
+ useEffect7(() => {
14144
15249
  if (cfg && !mcpInitRef.current) {
14145
15250
  void initMcp();
14146
15251
  }
@@ -14256,7 +15361,7 @@ function App({
14256
15361
  },
14257
15362
  [cfg]
14258
15363
  );
14259
- useInput7((inputChar, key) => {
15364
+ useInput6((inputChar, key) => {
14260
15365
  if (key.ctrl && inputChar === "c") {
14261
15366
  const hadPerm = permResolveRef.current !== null;
14262
15367
  const hadLimit = limitResolveRef.current !== null;
@@ -14280,7 +15385,7 @@ function App({
14280
15385
  return;
14281
15386
  }
14282
15387
  if (key.escape) {
14283
- const modalOpen = perm !== null || limitModal !== null || showHelpMenu || showLspWizard || showCommandList || commandWizard !== null || commandToDelete !== null || resumeSessions !== null || showThemePicker;
15388
+ const modalOpen = perm !== null || limitModal !== null || showLspWizard || showCommandList || commandWizard !== null || commandToDelete !== null || resumeSessions !== null || showThemePicker;
14284
15389
  if (!modalOpen && busyRef.current && activeControllerRef.current) {
14285
15390
  if (permResolveRef.current) {
14286
15391
  permResolveRef.current("deny");
@@ -14465,6 +15570,9 @@ function App({
14465
15570
  } finally {
14466
15571
  setBusy(false);
14467
15572
  setTurnStartedAt(null);
15573
+ setTurnPhase("waiting");
15574
+ setCurrentToolName(null);
15575
+ setLastActivityAt(null);
14468
15576
  activeControllerRef.current = null;
14469
15577
  permResolveRef.current = null;
14470
15578
  limitResolveRef.current = null;
@@ -14524,7 +15632,7 @@ function App({
14524
15632
  lspManagerRef.current.notifyChange(path, content);
14525
15633
  } else {
14526
15634
  void import("fs/promises").then(
14527
- ({ readFile: readFile17 }) => readFile17(path, "utf8").then((c) => lspManagerRef.current.notifyChange(path, c)).catch(() => {
15635
+ ({ readFile: readFile20 }) => readFile20(path, "utf8").then((c) => lspManagerRef.current.notifyChange(path, c)).catch(() => {
14528
15636
  })
14529
15637
  );
14530
15638
  }
@@ -14644,7 +15752,7 @@ function App({
14644
15752
  }
14645
15753
  }
14646
15754
  });
14647
- if (existsSync3(join22(cwd, "KIMI.md"))) {
15755
+ if (existsSync3(join25(cwd, "KIMI.md"))) {
14648
15756
  if (cacheStableRef.current) {
14649
15757
  messagesRef.current[1] = {
14650
15758
  role: "system",
@@ -14699,6 +15807,9 @@ function App({
14699
15807
  if (asstId !== null) updateAssistant(asstId, () => ({ streaming: false }));
14700
15808
  setBusy(false);
14701
15809
  setTurnStartedAt(null);
15810
+ setTurnPhase("waiting");
15811
+ setCurrentToolName(null);
15812
+ setLastActivityAt(null);
14702
15813
  activeAsstIdRef.current = null;
14703
15814
  activeControllerRef.current = null;
14704
15815
  permResolveRef.current = null;
@@ -14717,15 +15828,19 @@ function App({
14717
15828
  (picked) => {
14718
15829
  setShowThemePicker(false);
14719
15830
  if (!picked) return;
14720
- setCfg((c) => c ? { ...c, theme: picked.name } : c);
14721
- if (cfg) void saveConfig({ ...cfg, theme: picked.name }).catch(() => {
15831
+ setCfg((c) => {
15832
+ if (!c) return c;
15833
+ const updated = { ...c, theme: picked.name };
15834
+ void saveConfig(updated).catch(() => {
15835
+ });
15836
+ return updated;
14722
15837
  });
14723
15838
  setEvents((e) => [
14724
15839
  ...e,
14725
15840
  { kind: "info", key: mkKey(), text: `theme: ${picked.label} \u2014 restart to apply` }
14726
15841
  ]);
14727
15842
  },
14728
- [cfg]
15843
+ []
14729
15844
  );
14730
15845
  const handleResumePick = useCallback2(
14731
15846
  async (picked) => {
@@ -15049,8 +16164,12 @@ use: /thinking low | medium | high`
15049
16164
  ]);
15050
16165
  return true;
15051
16166
  }
15052
- setCfg((c2) => c2 ? { ...c2, theme: next.name } : c2);
15053
- if (cfg) void saveConfig({ ...cfg, theme: next.name }).catch(() => {
16167
+ setCfg((prev) => {
16168
+ if (!prev) return prev;
16169
+ const updated = { ...prev, theme: next.name };
16170
+ void saveConfig(updated).catch(() => {
16171
+ });
16172
+ return updated;
15054
16173
  });
15055
16174
  setEvents((e) => [
15056
16175
  ...e,
@@ -15073,6 +16192,118 @@ use: /thinking low | medium | high`
15073
16192
  setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "mode: edit" }]);
15074
16193
  return true;
15075
16194
  }
16195
+ if (c === "/skills") {
16196
+ const sub = rest[0]?.toLowerCase() ?? "";
16197
+ const subRest = rest.slice(1).join(" ").trim();
16198
+ if (sub === "list" || sub === "") {
16199
+ void listAllSkills(process.cwd()).then((all) => {
16200
+ const lines = [];
16201
+ if (all.project.length > 0) {
16202
+ lines.push("project skills:");
16203
+ for (const s of all.project) {
16204
+ const status = s.enabled ? "\u2713" : "\u2717";
16205
+ lines.push(` ${status} ${s.name} \u2014 ${s.description || "no description"} (${s.estimatedTokens} tokens)`);
16206
+ }
16207
+ }
16208
+ if (all.global.length > 0) {
16209
+ lines.push("global skills:");
16210
+ for (const s of all.global) {
16211
+ const status = s.enabled ? "\u2713" : "\u2717";
16212
+ lines.push(` ${status} ${s.name} \u2014 ${s.description || "no description"} (${s.estimatedTokens} tokens)`);
16213
+ }
16214
+ }
16215
+ if (lines.length === 0) {
16216
+ lines.push("no skills found. create one with /skills add <name>");
16217
+ }
16218
+ setEvents((e) => [...e, { kind: "info", key: mkKey(), text: lines.join("\n") }]);
16219
+ }).catch((err) => {
16220
+ setEvents((e) => [...e, { kind: "error", key: mkKey(), text: `failed to list skills: ${err.message}` }]);
16221
+ });
16222
+ return true;
16223
+ }
16224
+ if (sub === "add") {
16225
+ const name = subRest.trim();
16226
+ if (!name) {
16227
+ setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "usage: /skills add <name>" }]);
16228
+ return true;
16229
+ }
16230
+ void createSkill({ name, scope: "project", cwd: process.cwd() }).then((result) => {
16231
+ setEvents((e) => [
16232
+ ...e,
16233
+ { kind: "info", key: mkKey(), text: `created skill '${name}' \u2192 ${result.filepath}` },
16234
+ { kind: "info", key: mkKey(), text: `edit the file to add your instructions` }
16235
+ ]);
16236
+ }).catch((err) => {
16237
+ setEvents((e) => [...e, { kind: "error", key: mkKey(), text: `failed to create skill: ${err.message}` }]);
16238
+ });
16239
+ return true;
16240
+ }
16241
+ if (sub === "edit") {
16242
+ const name = subRest.trim();
16243
+ if (!name) {
16244
+ setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "usage: /skills edit <name>" }]);
16245
+ return true;
16246
+ }
16247
+ void findSkillFile(name, process.cwd()).then((filepath) => {
16248
+ if (!filepath) {
16249
+ setEvents((e) => [...e, { kind: "error", key: mkKey(), text: `skill '${name}' not found` }]);
16250
+ return;
16251
+ }
16252
+ setEvents((e) => [
16253
+ ...e,
16254
+ { kind: "info", key: mkKey(), text: `skill '${name}' \u2192 ${filepath}` },
16255
+ { kind: "info", key: mkKey(), text: `open it in your editor to make changes` }
16256
+ ]);
16257
+ }).catch((err) => {
16258
+ setEvents((e) => [...e, { kind: "error", key: mkKey(), text: `failed to find skill: ${err.message}` }]);
16259
+ });
16260
+ return true;
16261
+ }
16262
+ if (sub === "delete") {
16263
+ const name = subRest.trim();
16264
+ if (!name) {
16265
+ setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "usage: /skills delete <name>" }]);
16266
+ return true;
16267
+ }
16268
+ void deleteSkill(name, process.cwd()).then((result) => {
16269
+ setEvents((e) => [...e, { kind: "info", key: mkKey(), text: `deleted skill '${name}' (${result.filepath})` }]);
16270
+ }).catch((err) => {
16271
+ setEvents((e) => [...e, { kind: "error", key: mkKey(), text: `failed to delete skill: ${err.message}` }]);
16272
+ });
16273
+ return true;
16274
+ }
16275
+ if (sub === "enable") {
16276
+ const name = subRest.trim();
16277
+ if (!name) {
16278
+ setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "usage: /skills enable <name>" }]);
16279
+ return true;
16280
+ }
16281
+ void setSkillEnabled(name, true, process.cwd()).then((result) => {
16282
+ setEvents((e) => [...e, { kind: "info", key: mkKey(), text: `enabled skill '${name}' (${result.filepath})` }]);
16283
+ }).catch((err) => {
16284
+ setEvents((e) => [...e, { kind: "error", key: mkKey(), text: `failed to enable skill: ${err.message}` }]);
16285
+ });
16286
+ return true;
16287
+ }
16288
+ if (sub === "disable") {
16289
+ const name = subRest.trim();
16290
+ if (!name) {
16291
+ setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "usage: /skills disable <name>" }]);
16292
+ return true;
16293
+ }
16294
+ void setSkillEnabled(name, false, process.cwd()).then((result) => {
16295
+ setEvents((e) => [...e, { kind: "info", key: mkKey(), text: `disabled skill '${name}' (${result.filepath})` }]);
16296
+ }).catch((err) => {
16297
+ setEvents((e) => [...e, { kind: "error", key: mkKey(), text: `failed to disable skill: ${err.message}` }]);
16298
+ });
16299
+ return true;
16300
+ }
16301
+ setEvents((e) => [
16302
+ ...e,
16303
+ { kind: "info", key: mkKey(), text: "usage: /skills list | add <name> | edit <name> | delete <name> | enable <name> | disable <name>" }
16304
+ ]);
16305
+ return true;
16306
+ }
15076
16307
  if (c === "/memory") {
15077
16308
  if (!cfg) return true;
15078
16309
  if (arg === "on") {
@@ -15277,7 +16508,7 @@ ${lines.join("\n")}` }]);
15277
16508
  return true;
15278
16509
  }
15279
16510
  if (c === "/logout") {
15280
- unlink3(configPath()).catch(() => {
16511
+ unlink4(configPath()).catch(() => {
15281
16512
  });
15282
16513
  setEvents((e) => [
15283
16514
  ...e,
@@ -15475,23 +16706,27 @@ ${lines.join("\n")}` }]);
15475
16706
  return true;
15476
16707
  }
15477
16708
  if (c === "/help") {
15478
- setShowHelpMenu(true);
16709
+ const lines = [
16710
+ "commands:",
16711
+ " /mode edit|plan|auto switch agent mode",
16712
+ " /thinking low|medium|high set reasoning effort",
16713
+ " /skills list|add|edit|... manage skills",
16714
+ " /memory on|off|clear manage memory",
16715
+ " /cost show cost report",
16716
+ " /compact summarize old turns",
16717
+ " /resume pick a past session",
16718
+ " /clear clear conversation",
16719
+ " /init scan repo and write KIMI.md",
16720
+ " /update check for updates",
16721
+ " /exit exit kimiflare"
16722
+ ];
16723
+ setEvents((e) => [...e, { kind: "info", key: mkKey(), text: lines.join("\n") }]);
15479
16724
  return true;
15480
16725
  }
15481
16726
  return false;
15482
16727
  },
15483
16728
  [cfg, exit, usage, effort, theme, mode, openResumePicker, runCompact, runInit, initMcp, setCfg, setShowRemoteDashboard, setSelectedRemoteSession]
15484
16729
  );
15485
- const handleHelpCommand = useCallback2(
15486
- (command) => {
15487
- setShowHelpMenu(false);
15488
- const executed = handleSlash(command);
15489
- if (!executed) {
15490
- setEvents((e) => [...e, { kind: "error", key: mkKey(), text: `unknown command: ${command}` }]);
15491
- }
15492
- },
15493
- [handleSlash]
15494
- );
15495
16730
  const handleCommandSave = useCallback2(
15496
16731
  async (opts2) => {
15497
16732
  setCommandWizard(null);
@@ -15620,7 +16855,7 @@ ${lines.join("\n")}` }]);
15620
16855
  }
15621
16856
  }
15622
16857
  turnCounterRef.current += 1;
15623
- if (turnCounterRef.current % 15 === 0 && existsSync3(join22(process.cwd(), "KIMI.md")) && !kimiMdStale) {
16858
+ if (turnCounterRef.current % 15 === 0 && existsSync3(join25(process.cwd(), "KIMI.md")) && !kimiMdStale) {
15624
16859
  setEvents((e) => [
15625
16860
  ...e,
15626
16861
  { kind: "info", key: mkKey(), text: "Tip: Rerunning /init occasionally helps KimiFlare stay accurate as your project evolves." }
@@ -15631,6 +16866,22 @@ ${lines.join("\n")}` }]);
15631
16866
  setGatewayMeta(null);
15632
16867
  setTurnStartedAt(Date.now());
15633
16868
  const classification = classifyIntent(trimmed);
16869
+ setIntentTier(classification.tier);
16870
+ let skillResult;
16871
+ try {
16872
+ skillResult = await routeSkills(skillsDirRef.current, {
16873
+ cwd: process.cwd(),
16874
+ prompt: trimmed,
16875
+ memorySnippets: [],
16876
+ // TODO: wire memory snippets when available
16877
+ tier: classification.tier,
16878
+ maxSkillTokens: CONTEXT_LIMIT - 1e4
16879
+ // leave headroom
16880
+ });
16881
+ setSkillsActive(skillResult.selectedSkills.length);
16882
+ } catch {
16883
+ setSkillsActive(0);
16884
+ }
15634
16885
  const effortForTier = {
15635
16886
  light: "low",
15636
16887
  medium: "medium",
@@ -15639,6 +16890,40 @@ ${lines.join("\n")}` }]);
15639
16890
  const turnReasoningEffort = overrideEffort ?? effortForTier[classification.tier] ?? effortRef.current;
15640
16891
  const effectiveCodeMode = classification.tier === "heavy";
15641
16892
  setCodeMode(effectiveCodeMode);
16893
+ const selectedSkills = skillResult?.selectedSkills.map((s) => ({ name: s.name, body: s.body }));
16894
+ if (cacheStableRef.current) {
16895
+ messagesRef.current[1] = {
16896
+ role: "system",
16897
+ content: buildSessionPrefix({
16898
+ cwd: process.cwd(),
16899
+ tools: [...ALL_TOOLS, ...mcpToolsRef.current, ...lspToolsRef.current],
16900
+ model: cfg.model,
16901
+ mode: modeRef.current,
16902
+ selectedSkills
16903
+ })
16904
+ };
16905
+ } else {
16906
+ messagesRef.current[0] = {
16907
+ role: "system",
16908
+ content: buildSystemPrompt({
16909
+ cwd: process.cwd(),
16910
+ tools: [...ALL_TOOLS, ...mcpToolsRef.current, ...lspToolsRef.current],
16911
+ model: cfg.model,
16912
+ mode: modeRef.current,
16913
+ selectedSkills
16914
+ })
16915
+ };
16916
+ }
16917
+ setEvents((e) => [
16918
+ ...e,
16919
+ {
16920
+ kind: "meta",
16921
+ key: mkKey(),
16922
+ intentTier: classification.tier,
16923
+ skillsActive: skillResult?.selectedSkills.length ?? 0,
16924
+ memoryRecalled: false
16925
+ }
16926
+ ]);
15642
16927
  const triageActivity = narrativizeInfo("", { tier: classification.tier, codeMode: effectiveCodeMode });
15643
16928
  if (triageActivity) {
15644
16929
  setEvents((e) => [...e, { kind: "activity", key: mkKey(), text: triageActivity.text, feature: triageActivity.feature }]);
@@ -15649,6 +16934,8 @@ ${lines.join("\n")}` }]);
15649
16934
  onAssistantStart: () => {
15650
16935
  const id = nextAssistantId++;
15651
16936
  activeAsstIdRef.current = id;
16937
+ setTurnPhase("generating");
16938
+ setLastActivityAt(Date.now());
15652
16939
  setEvents((e) => [
15653
16940
  ...e,
15654
16941
  { kind: "assistant", key: `asst_${id}`, id, text: "", reasoning: "", streaming: true }
@@ -15657,17 +16944,23 @@ ${lines.join("\n")}` }]);
15657
16944
  onReasoningDelta: (d) => {
15658
16945
  const id = activeAsstIdRef.current;
15659
16946
  if (id !== null) updateAssistant(id, (e) => ({ reasoning: e.reasoning + d }));
16947
+ setLastActivityAt(Date.now());
15660
16948
  },
15661
16949
  onTextDelta: (d) => {
15662
16950
  const id = activeAsstIdRef.current;
15663
16951
  if (id !== null) updateAssistant(id, (e) => ({ text: e.text + d }));
16952
+ setLastActivityAt(Date.now());
15664
16953
  },
15665
16954
  onAssistantFinal: () => {
15666
16955
  const id = activeAsstIdRef.current;
15667
16956
  if (id !== null) updateAssistant(id, () => ({ streaming: false }));
16957
+ setTurnPhase("waiting");
15668
16958
  },
15669
16959
  onToolCallFinalized: (call) => {
15670
16960
  pendingToolCallsRef.current.set(call.id, call.function.name);
16961
+ setTurnPhase("executing");
16962
+ setCurrentToolName(call.function.name);
16963
+ setLastActivityAt(Date.now());
15671
16964
  const spec = executorRef.current.list().find((t) => t.name === call.function.name);
15672
16965
  let renderMeta;
15673
16966
  let argsParsed = {};
@@ -15690,12 +16983,18 @@ ${lines.join("\n")}` }]);
15690
16983
  args: call.function.arguments,
15691
16984
  status: "running",
15692
16985
  render: renderMeta,
15693
- expanded: false
16986
+ expanded: false,
16987
+ startedAt: Date.now()
15694
16988
  }
15695
16989
  ]);
15696
16990
  },
15697
16991
  onToolResult: (r) => {
15698
16992
  pendingToolCallsRef.current.delete(r.tool_call_id);
16993
+ setLastActivityAt(Date.now());
16994
+ if (pendingToolCallsRef.current.size === 0) {
16995
+ setTurnPhase("waiting");
16996
+ setCurrentToolName(null);
16997
+ }
15699
16998
  updateTool(r.tool_call_id, {
15700
16999
  status: r.ok ? "done" : "error",
15701
17000
  result: r.content
@@ -15797,12 +17096,13 @@ ${lines.join("\n")}` }]);
15797
17096
  cloudDeviceId: cloudDeviceId ?? initialCloudDeviceId,
15798
17097
  onIterationEnd,
15799
17098
  intentClassification: classification,
17099
+ selectedSkills,
15800
17100
  onFileChange: (path, content2) => {
15801
17101
  if (content2) {
15802
17102
  lspManagerRef.current.notifyChange(path, content2);
15803
17103
  } else {
15804
17104
  void import("fs/promises").then(
15805
- ({ readFile: readFile17 }) => readFile17(path, "utf8").then((c) => lspManagerRef.current.notifyChange(path, c)).catch(() => {
17105
+ ({ readFile: readFile20 }) => readFile20(path, "utf8").then((c) => lspManagerRef.current.notifyChange(path, c)).catch(() => {
15806
17106
  })
15807
17107
  );
15808
17108
  }
@@ -15934,6 +17234,9 @@ ${lines.join("\n")}` }]);
15934
17234
  if (asstId !== null) updateAssistant(asstId, () => ({ streaming: false }));
15935
17235
  setBusy(false);
15936
17236
  setTurnStartedAt(null);
17237
+ setTurnPhase("waiting");
17238
+ setCurrentToolName(null);
17239
+ setLastActivityAt(null);
15937
17240
  activeAsstIdRef.current = null;
15938
17241
  activeControllerRef.current = null;
15939
17242
  permResolveRef.current = null;
@@ -15950,7 +17253,7 @@ ${lines.join("\n")}` }]);
15950
17253
  },
15951
17254
  [cfg, handleSlash, updateAssistant, updateTool, saveSessionSafe, updateGatewayMeta, flushToolBatch]
15952
17255
  );
15953
- useEffect6(() => {
17256
+ useEffect7(() => {
15954
17257
  if (!busy && queue.length > 0) {
15955
17258
  const next = queue[0];
15956
17259
  setQueue((q) => q.slice(1));
@@ -15978,7 +17281,7 @@ ${lines.join("\n")}` }]);
15978
17281
  [busy, processMessage]
15979
17282
  );
15980
17283
  submitRef.current = submit;
15981
- useEffect6(() => {
17284
+ useEffect7(() => {
15982
17285
  if (compactSuggestedRef.current) return;
15983
17286
  if (usage && usage.prompt_tokens / CONTEXT_LIMIT >= AUTO_COMPACT_SUGGEST_PCT) {
15984
17287
  compactSuggestedRef.current = true;
@@ -15993,7 +17296,7 @@ ${lines.join("\n")}` }]);
15993
17296
  }
15994
17297
  }, [usage]);
15995
17298
  if (!cfg) {
15996
- return /* @__PURE__ */ jsx23(ThemeProvider, { theme, children: /* @__PURE__ */ jsx23(
17299
+ return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(
15997
17300
  Onboarding,
15998
17301
  {
15999
17302
  onCancel: () => exit(),
@@ -16025,10 +17328,10 @@ ${lines.join("\n")}` }]);
16025
17328
  ) });
16026
17329
  }
16027
17330
  if (resumeSessions !== null) {
16028
- return /* @__PURE__ */ jsx23(ThemeProvider, { theme, children: /* @__PURE__ */ jsx23(Box21, { flexDirection: "column", children: /* @__PURE__ */ jsx23(ResumePicker, { sessions: resumeSessions, onPick: handleResumePick }) }) });
17331
+ return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", children: /* @__PURE__ */ jsx22(ResumePicker, { sessions: resumeSessions, onPick: handleResumePick }) }) });
16029
17332
  }
16030
17333
  if (showRemoteDashboard) {
16031
- return /* @__PURE__ */ jsx23(ThemeProvider, { theme, children: /* @__PURE__ */ jsx23(Box21, { flexDirection: "column", children: selectedRemoteSession ? /* @__PURE__ */ jsx23(
17334
+ return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", children: selectedRemoteSession ? /* @__PURE__ */ jsx22(
16032
17335
  RemoteSessionDetail,
16033
17336
  {
16034
17337
  session: selectedRemoteSession,
@@ -16051,7 +17354,7 @@ ${lines.join("\n")}` }]);
16051
17354
  setShowRemoteDashboard(false);
16052
17355
  }
16053
17356
  }
16054
- ) : /* @__PURE__ */ jsx23(
17357
+ ) : /* @__PURE__ */ jsx22(
16055
17358
  RemoteDashboard,
16056
17359
  {
16057
17360
  onSelect: (session) => setSelectedRemoteSession(session),
@@ -16059,25 +17362,13 @@ ${lines.join("\n")}` }]);
16059
17362
  }
16060
17363
  ) }) });
16061
17364
  }
16062
- if (showHelpMenu) {
16063
- return /* @__PURE__ */ jsx23(ThemeProvider, { theme, children: /* @__PURE__ */ jsx23(Box21, { flexDirection: "column", children: /* @__PURE__ */ jsx23(
16064
- HelpMenu,
16065
- {
16066
- customCommands: customCommandsRef.current.filter((c) => !BUILTIN_COMMAND_NAMES.has(c.name.toLowerCase())).map((c) => ({ name: c.name, description: c.description })),
16067
- costAttributionEnabled: cfg?.costAttribution,
16068
- cloudMode: cfg?.cloudMode,
16069
- onDone: () => setShowHelpMenu(false),
16070
- onCommand: handleHelpCommand
16071
- }
16072
- ) }) });
16073
- }
16074
17365
  if (showLspWizard) {
16075
- return /* @__PURE__ */ jsx23(ThemeProvider, { theme, children: /* @__PURE__ */ jsx23(Box21, { flexDirection: "column", children: /* @__PURE__ */ jsx23(
17366
+ return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", children: /* @__PURE__ */ jsx22(
16076
17367
  LspWizard,
16077
17368
  {
16078
17369
  servers: cfg?.lspServers ?? {},
16079
17370
  currentScope: lspScope,
16080
- hasProjectDir: existsSync3(join22(process.cwd(), ".kimiflare")),
17371
+ hasProjectDir: existsSync3(join25(process.cwd(), ".kimiflare")),
16081
17372
  onDone: () => setShowLspWizard(false),
16082
17373
  onSave: (servers, enabled, scope) => {
16083
17374
  setCfg((c) => c ? { ...c, lspEnabled: enabled, lspServers: servers } : c);
@@ -16109,7 +17400,7 @@ ${lines.join("\n")}` }]);
16109
17400
  ) }) });
16110
17401
  }
16111
17402
  if (commandWizard) {
16112
- return /* @__PURE__ */ jsx23(ThemeProvider, { theme, children: /* @__PURE__ */ jsx23(Box21, { flexDirection: "column", children: /* @__PURE__ */ jsx23(
17403
+ return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", children: /* @__PURE__ */ jsx22(
16113
17404
  CommandWizard,
16114
17405
  {
16115
17406
  mode: commandWizard.mode,
@@ -16122,7 +17413,7 @@ ${lines.join("\n")}` }]);
16122
17413
  ) }) });
16123
17414
  }
16124
17415
  if (commandPicker) {
16125
- return /* @__PURE__ */ jsx23(ThemeProvider, { theme, children: /* @__PURE__ */ jsx23(Box21, { flexDirection: "column", children: /* @__PURE__ */ jsx23(
17416
+ return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", children: /* @__PURE__ */ jsx22(
16126
17417
  CommandPicker,
16127
17418
  {
16128
17419
  commands: customCommandsRef.current,
@@ -16140,15 +17431,15 @@ ${lines.join("\n")}` }]);
16140
17431
  ) }) });
16141
17432
  }
16142
17433
  if (commandToDelete) {
16143
- return /* @__PURE__ */ jsx23(ThemeProvider, { theme, children: /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
16144
- /* @__PURE__ */ jsxs21(Text22, { color: theme.accent, bold: true, children: [
17434
+ return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsxs20(Box20, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
17435
+ /* @__PURE__ */ jsxs20(Text21, { color: theme.accent, bold: true, children: [
16145
17436
  "Delete /",
16146
17437
  commandToDelete.name,
16147
17438
  "?"
16148
17439
  ] }),
16149
- /* @__PURE__ */ jsx23(Text22, { color: theme.info.color, children: commandToDelete.filepath }),
16150
- /* @__PURE__ */ jsx23(Box21, { marginTop: 1, children: /* @__PURE__ */ jsx23(
16151
- SelectInput11,
17440
+ /* @__PURE__ */ jsx22(Text21, { color: theme.info.color, children: commandToDelete.filepath }),
17441
+ /* @__PURE__ */ jsx22(Box20, { marginTop: 1, children: /* @__PURE__ */ jsx22(
17442
+ SelectInput10,
16152
17443
  {
16153
17444
  items: [
16154
17445
  { label: "Yes, delete", value: "yes", key: "yes" },
@@ -16166,7 +17457,7 @@ ${lines.join("\n")}` }]);
16166
17457
  ] }) });
16167
17458
  }
16168
17459
  if (showCommandList) {
16169
- return /* @__PURE__ */ jsx23(ThemeProvider, { theme, children: /* @__PURE__ */ jsx23(Box21, { flexDirection: "column", children: /* @__PURE__ */ jsx23(
17460
+ return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", children: /* @__PURE__ */ jsx22(
16170
17461
  CommandList,
16171
17462
  {
16172
17463
  commands: customCommandsRef.current,
@@ -16175,12 +17466,12 @@ ${lines.join("\n")}` }]);
16175
17466
  ) }) });
16176
17467
  }
16177
17468
  if (showThemePicker) {
16178
- return /* @__PURE__ */ jsx23(ThemeProvider, { theme, children: /* @__PURE__ */ jsx23(Box21, { flexDirection: "column", children: /* @__PURE__ */ jsx23(ThemePicker, { themes: themeList(), onPick: handleThemePick }) }) });
17469
+ return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", children: /* @__PURE__ */ jsx22(ThemePicker, { themes: themeList(), onPick: handleThemePick }) }) });
16179
17470
  }
16180
17471
  const hasConversation = events.some((e) => e.kind === "user" || e.kind === "assistant");
16181
- return /* @__PURE__ */ jsx23(ThemeProvider, { theme, children: /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", children: [
16182
- !hasConversation && events.length === 0 ? /* @__PURE__ */ jsx23(Welcome, { accountId: cfg.accountId }) : /* @__PURE__ */ jsx23(ChatView, { events, showReasoning, verbose, suppressTools: mode === "plan" }),
16183
- perm ? /* @__PURE__ */ jsx23(
17472
+ return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsxs20(Box20, { flexDirection: "column", children: [
17473
+ !hasConversation && events.length === 0 ? /* @__PURE__ */ jsx22(Welcome, { accountId: cfg.accountId, cloudMode: cfg.cloudMode }) : /* @__PURE__ */ jsx22(ChatView, { events, showReasoning, verbose, suppressTools: mode === "plan" }),
17474
+ perm ? /* @__PURE__ */ jsx22(
16184
17475
  PermissionModal,
16185
17476
  {
16186
17477
  tool: perm.tool,
@@ -16191,7 +17482,7 @@ ${lines.join("\n")}` }]);
16191
17482
  setPerm(null);
16192
17483
  }
16193
17484
  }
16194
- ) : limitModal ? /* @__PURE__ */ jsx23(
17485
+ ) : limitModal ? /* @__PURE__ */ jsx22(
16195
17486
  LimitModal,
16196
17487
  {
16197
17488
  limit: limitModal.limit,
@@ -16201,8 +17492,8 @@ ${lines.join("\n")}` }]);
16201
17492
  setLimitModal(null);
16202
17493
  }
16203
17494
  }
16204
- ) : /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", marginTop: 1, children: [
16205
- tasks.length > 0 && /* @__PURE__ */ jsx23(
17495
+ ) : /* @__PURE__ */ jsxs20(Box20, { flexDirection: "column", marginTop: 1, children: [
17496
+ tasks.length > 0 && /* @__PURE__ */ jsx22(
16206
17497
  TaskList,
16207
17498
  {
16208
17499
  tasks,
@@ -16210,11 +17501,11 @@ ${lines.join("\n")}` }]);
16210
17501
  tokensDelta: Math.max(0, (usage?.prompt_tokens ?? 0) - tasksStartTokens)
16211
17502
  }
16212
17503
  ),
16213
- queue.length > 0 && /* @__PURE__ */ jsx23(Box21, { flexDirection: "column", marginBottom: 1, children: queue.map((q, i) => /* @__PURE__ */ jsxs21(Text22, { color: theme.info.color, children: [
17504
+ queue.length > 0 && /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", marginBottom: 1, children: queue.map((q, i) => /* @__PURE__ */ jsxs20(Text21, { color: theme.info.color, children: [
16214
17505
  "\u23F3 ",
16215
17506
  q.display
16216
17507
  ] }, `queue_${i}`)) }),
16217
- /* @__PURE__ */ jsx23(
17508
+ /* @__PURE__ */ jsx22(
16218
17509
  StatusBar,
16219
17510
  {
16220
17511
  model: cfg.model,
@@ -16231,10 +17522,15 @@ ${lines.join("\n")}` }]);
16231
17522
  codeMode,
16232
17523
  cloudMode: cfg.cloudMode,
16233
17524
  cloudBudget,
17525
+ skillsActive,
17526
+ memoryRecalled,
17527
+ phase: turnPhase,
17528
+ currentTool: currentToolName,
17529
+ lastActivityAt,
16234
17530
  kimiMdStale
16235
17531
  }
16236
17532
  ),
16237
- activePicker?.kind === "file" && /* @__PURE__ */ jsx23(
17533
+ activePicker?.kind === "file" && /* @__PURE__ */ jsx22(
16238
17534
  FilePicker,
16239
17535
  {
16240
17536
  items: filteredFileItems,
@@ -16242,7 +17538,7 @@ ${lines.join("\n")}` }]);
16242
17538
  query: pickerQuery ?? ""
16243
17539
  }
16244
17540
  ),
16245
- activePicker?.kind === "slash" && /* @__PURE__ */ jsx23(
17541
+ activePicker?.kind === "slash" && /* @__PURE__ */ jsx22(
16246
17542
  SlashPicker,
16247
17543
  {
16248
17544
  items: filteredSlashItems,
@@ -16250,9 +17546,9 @@ ${lines.join("\n")}` }]);
16250
17546
  query: pickerQuery ?? ""
16251
17547
  }
16252
17548
  ),
16253
- /* @__PURE__ */ jsxs21(Box21, { marginTop: 1, children: [
16254
- /* @__PURE__ */ jsx23(Text22, { color: "#d699b6", children: "\u203A " }),
16255
- /* @__PURE__ */ jsx23(
17549
+ /* @__PURE__ */ jsxs20(Box20, { marginTop: 1, children: [
17550
+ /* @__PURE__ */ jsx22(Text21, { color: "#d699b6", children: "\u203A " }),
17551
+ /* @__PURE__ */ jsx22(
16256
17552
  CustomTextInput,
16257
17553
  {
16258
17554
  value: input,
@@ -16309,7 +17605,7 @@ ${lines.join("\n")}` }]);
16309
17605
  }
16310
17606
  async function renderApp(cfg, updateResult, lspScope = "global", lspProjectPath = null, cloudToken, cloudDeviceId) {
16311
17607
  const instance = render(
16312
- /* @__PURE__ */ jsx23(
17608
+ /* @__PURE__ */ jsx22(
16313
17609
  App,
16314
17610
  {
16315
17611
  initialCfg: cfg,
@@ -16352,7 +17648,6 @@ var init_app = __esm({
16352
17648
  init_update_check();
16353
17649
  init_onboarding();
16354
17650
  init_welcome();
16355
- init_help_menu();
16356
17651
  init_config();
16357
17652
  init_worker_client();
16358
17653
  init_session_store();
@@ -16361,14 +17656,16 @@ var init_app = __esm({
16361
17656
  init_remote_dashboard();
16362
17657
  init_mode();
16363
17658
  init_classify();
17659
+ init_skills();
17660
+ init_manager3();
16364
17661
  init_sessions();
16365
17662
  init_image();
16366
17663
  init_usage_tracker();
16367
- init_manager3();
17664
+ init_manager4();
16368
17665
  init_storage_limits();
16369
17666
  init_state();
16370
17667
  init_version();
16371
- init_loader();
17668
+ init_loader2();
16372
17669
  init_renderer2();
16373
17670
  init_builtins();
16374
17671
  init_save();
@@ -16380,6 +17677,7 @@ var init_app = __esm({
16380
17677
  init_theme_context();
16381
17678
  init_theme_picker();
16382
17679
  init_theme();
17680
+ init_theme_loader();
16383
17681
  init_lsp_config();
16384
17682
  init_lsp_nudge();
16385
17683
  init_file_picker();