kimiflare 0.3.1 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1222,7 +1222,7 @@ import { Box as Box2, Text as Text2 } from "ink";
1222
1222
  import Spinner from "ink-spinner";
1223
1223
  import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
1224
1224
  function ToolView({ evt, verbose }) {
1225
- const statusIcon = evt.status === "running" ? /* @__PURE__ */ jsx2(Spinner, { type: "dots" }) : evt.status === "error" ? /* @__PURE__ */ jsx2(Text2, { color: "red", children: "\u2717" }) : /* @__PURE__ */ jsx2(Text2, { color: "green", children: "\u2713" });
1225
+ const statusIcon = evt.status === "running" ? /* @__PURE__ */ jsx2(Text2, { color: "gray", children: /* @__PURE__ */ jsx2(Spinner, { type: "dots" }) }) : evt.status === "error" ? /* @__PURE__ */ jsx2(Text2, { color: "red", children: "\u2717" }) : /* @__PURE__ */ jsx2(Text2, { color: "green", children: "\u2713" });
1226
1226
  const title = evt.render?.title ?? `${evt.name}(${compactArgs(evt.args)})`;
1227
1227
  const expand = Boolean(evt.expanded || verbose);
1228
1228
  const lines = evt.result ? evt.result.split("\n") : [];
@@ -1231,18 +1231,29 @@ function ToolView({ evt, verbose }) {
1231
1231
  /* @__PURE__ */ jsxs2(Text2, { children: [
1232
1232
  statusIcon,
1233
1233
  " ",
1234
- /* @__PURE__ */ jsx2(Text2, { color: "magenta", children: title })
1234
+ /* @__PURE__ */ jsx2(Text2, { color: "gray", children: title })
1235
1235
  ] }),
1236
1236
  evt.render?.diff ? /* @__PURE__ */ jsx2(Box2, { marginLeft: 2, children: /* @__PURE__ */ jsx2(DiffView, { ...evt.render.diff }) }) : null,
1237
- evt.result && expand ? /* @__PURE__ */ jsxs2(Box2, { marginLeft: 2, flexDirection: "column", children: [
1238
- lines.slice(0, showLimit).map((l, i) => /* @__PURE__ */ jsx2(Text2, { color: "gray", children: l }, i)),
1239
- lines.length > showLimit && /* @__PURE__ */ jsxs2(Text2, { color: "gray", children: [
1240
- "... (",
1241
- lines.length - showLimit,
1242
- " more lines)"
1243
- ] })
1244
- ] }) : null,
1245
- evt.result && !expand && evt.status !== "running" ? /* @__PURE__ */ jsxs2(Text2, { color: "gray", children: [
1237
+ evt.result && expand ? /* @__PURE__ */ jsxs2(
1238
+ Box2,
1239
+ {
1240
+ marginLeft: 2,
1241
+ marginTop: 1,
1242
+ flexDirection: "column",
1243
+ borderStyle: "single",
1244
+ borderColor: "gray",
1245
+ paddingX: 1,
1246
+ children: [
1247
+ lines.slice(0, showLimit).map((l, i) => /* @__PURE__ */ jsx2(Text2, { color: "gray", dimColor: true, children: l }, i)),
1248
+ lines.length > showLimit && /* @__PURE__ */ jsxs2(Text2, { color: "gray", dimColor: true, children: [
1249
+ "\u2026 (",
1250
+ lines.length - showLimit,
1251
+ " more lines)"
1252
+ ] })
1253
+ ]
1254
+ }
1255
+ ) : null,
1256
+ evt.result && !expand && evt.status !== "running" ? /* @__PURE__ */ jsxs2(Text2, { color: "gray", dimColor: true, children: [
1246
1257
  " ",
1247
1258
  firstLine(evt.result)
1248
1259
  ] }) : null
@@ -1428,19 +1439,35 @@ var init_markdown = __esm({
1428
1439
  import { Box as Box4, Text as Text4 } from "ink";
1429
1440
  import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
1430
1441
  function ChatView({ events, showReasoning, theme, verbose }) {
1431
- return /* @__PURE__ */ jsx4(Box4, { flexDirection: "column", children: events.map((e) => /* @__PURE__ */ jsx4(EventView, { evt: e, showReasoning, theme, verbose }, e.key)) });
1432
- }
1433
- function EventView({ evt, showReasoning, theme, verbose }) {
1442
+ return /* @__PURE__ */ jsx4(Box4, { flexDirection: "column", children: events.map((e, i) => {
1443
+ const prev = events[i - 1];
1444
+ const showSeparator = e.kind === "user" && prev && (prev.kind === "assistant" || prev.kind === "tool");
1445
+ return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
1446
+ showSeparator && /* @__PURE__ */ jsx4(Box4, { marginY: 1, children: /* @__PURE__ */ jsx4(Text4, { color: theme.info.color, dimColor: theme.info.dim, children: "\u2500".repeat(40) }) }),
1447
+ /* @__PURE__ */ jsx4(EventView, { evt: e, showReasoning, theme, verbose })
1448
+ ] }, e.key);
1449
+ }) });
1450
+ }
1451
+ function EventView({
1452
+ evt,
1453
+ showReasoning,
1454
+ theme,
1455
+ verbose
1456
+ }) {
1434
1457
  if (evt.kind === "user") {
1435
- return /* @__PURE__ */ jsxs4(Box4, { marginTop: 1, children: [
1436
- /* @__PURE__ */ jsx4(Text4, { color: theme.user, children: "\u203A " }),
1437
- /* @__PURE__ */ jsx4(Text4, { children: evt.text })
1458
+ return /* @__PURE__ */ jsxs4(Box4, { children: [
1459
+ /* @__PURE__ */ jsxs4(Text4, { bold: true, color: theme.user, children: [
1460
+ "\u203A",
1461
+ " "
1462
+ ] }),
1463
+ /* @__PURE__ */ jsx4(Text4, { bold: true, children: evt.text })
1438
1464
  ] });
1439
1465
  }
1440
1466
  if (evt.kind === "assistant") {
1441
- return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", marginTop: 1, paddingLeft: 1, children: [
1442
- showReasoning && evt.reasoning ? /* @__PURE__ */ jsx4(Box4, { flexDirection: "column", marginLeft: 2, children: /* @__PURE__ */ jsxs4(Text4, { color: theme.reasoning.color, dimColor: theme.reasoning.dim, children: [
1443
- "\u2727 thinking: ",
1467
+ return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", paddingLeft: 2, children: [
1468
+ showReasoning && evt.reasoning ? /* @__PURE__ */ jsx4(Box4, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsxs4(Text4, { color: theme.reasoning.color, dimColor: theme.reasoning.dim, children: [
1469
+ "thinking\u2026",
1470
+ " ",
1444
1471
  evt.reasoning.length > 400 ? evt.reasoning.slice(0, 400) + "\u2026" : evt.reasoning
1445
1472
  ] }) }) : null,
1446
1473
  evt.text ? /* @__PURE__ */ jsx4(MD, { text: evt.text, theme }) : null
@@ -1450,7 +1477,10 @@ function EventView({ evt, showReasoning, theme, verbose }) {
1450
1477
  return /* @__PURE__ */ jsx4(ToolView, { evt, verbose });
1451
1478
  }
1452
1479
  if (evt.kind === "info") {
1453
- return /* @__PURE__ */ jsx4(Text4, { color: theme.info.color, dimColor: theme.info.dim, children: evt.text });
1480
+ return /* @__PURE__ */ jsxs4(Text4, { color: theme.info.color, dimColor: theme.info.dim, children: [
1481
+ "\xB7 ",
1482
+ evt.text
1483
+ ] });
1454
1484
  }
1455
1485
  return /* @__PURE__ */ jsxs4(Text4, { color: theme.error, children: [
1456
1486
  "! ",
@@ -1468,36 +1498,41 @@ var init_chat = __esm({
1468
1498
  // src/ui/status.tsx
1469
1499
  import { Box as Box5, Text as Text5 } from "ink";
1470
1500
  import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1471
- function StatusBar({ model, usage, thinking, hint, theme, mode, effort, contextLimit }) {
1472
- const parts = [`model: ${shortModel(model)}`, `effort: ${effort}`];
1501
+ function StatusBar({ model, usage, thinking, theme, mode, effort, contextLimit }) {
1502
+ const modeColor = mode === "plan" ? theme.modeBadge.plan : mode === "auto" ? theme.modeBadge.auto : theme.modeBadge.edit;
1503
+ const warn = usage && usage.prompt_tokens / contextLimit >= 0.8;
1504
+ const leftParts = [`${shortModel(model)}`, effort];
1505
+ if (thinking) leftParts.push("thinking\u2026");
1506
+ const rightParts = [];
1473
1507
  if (usage) {
1474
1508
  const cached = usage.prompt_tokens_details?.cached_tokens ?? 0;
1475
1509
  const uncachedIn = usage.prompt_tokens - cached;
1476
1510
  const cost = uncachedIn * PRICE_IN_PER_M / 1e6 + cached * PRICE_IN_CACHED_PER_M / 1e6 + usage.completion_tokens * PRICE_OUT_PER_M / 1e6;
1477
1511
  const pct = Math.round(usage.prompt_tokens / contextLimit * 100);
1478
- parts.push(
1479
- `in: ${usage.prompt_tokens}${cached ? ` (${cached} cached)` : ""}`,
1480
- `out: ${usage.completion_tokens}`,
1481
- `ctx: ${pct}%`,
1482
- `$${cost.toFixed(5)}`
1512
+ rightParts.push(
1513
+ `in ${usage.prompt_tokens}${cached ? ` (${cached} cached)` : ""}`,
1514
+ `out ${usage.completion_tokens}`,
1515
+ `ctx ${pct}%`,
1516
+ `${cost.toFixed(5)}`
1483
1517
  );
1484
1518
  }
1485
- if (thinking) parts.push("thinking\u2026");
1486
- if (hint) parts.push(hint);
1487
- const modeColor = mode === "plan" ? theme.modeBadge.plan : mode === "auto" ? theme.modeBadge.auto : theme.modeBadge.edit;
1488
- const warn = usage && usage.prompt_tokens / contextLimit >= 0.8;
1489
- return /* @__PURE__ */ jsxs5(Box5, { children: [
1490
- /* @__PURE__ */ jsxs5(Text5, { color: modeColor, bold: true, children: [
1491
- "[",
1492
- mode,
1493
- "]"
1519
+ return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
1520
+ /* @__PURE__ */ jsxs5(Box5, { children: [
1521
+ /* @__PURE__ */ jsxs5(Text5, { color: modeColor, bold: true, children: [
1522
+ "[",
1523
+ mode,
1524
+ "]"
1525
+ ] }),
1526
+ /* @__PURE__ */ jsx5(Text5, { children: " " }),
1527
+ /* @__PURE__ */ jsx5(Text5, { color: theme.info.color, dimColor: theme.info.dim, children: leftParts.join(" \xB7 ") })
1494
1528
  ] }),
1495
- /* @__PURE__ */ jsx5(Text5, { children: " " }),
1496
- /* @__PURE__ */ jsx5(Text5, { color: theme.info.color, dimColor: theme.info.dim, children: parts.join(" \xB7 ") }),
1497
- warn ? /* @__PURE__ */ jsxs5(Text5, { color: theme.warn, bold: true, children: [
1498
- " \xB7 ",
1499
- "/compact recommended"
1500
- ] }) : null
1529
+ rightParts.length > 0 && /* @__PURE__ */ jsxs5(Box5, { children: [
1530
+ /* @__PURE__ */ jsx5(Text5, { color: theme.info.color, dimColor: theme.info.dim, children: rightParts.join(" \xB7 ") }),
1531
+ warn ? /* @__PURE__ */ jsxs5(Text5, { color: theme.warn, bold: true, children: [
1532
+ " \xB7 ",
1533
+ "/compact recommended"
1534
+ ] }) : null
1535
+ ] })
1501
1536
  ] });
1502
1537
  }
1503
1538
  function shortModel(m) {
@@ -1625,18 +1660,14 @@ function TaskList({ tasks, theme, startedAt, tokensDelta }) {
1625
1660
  const done = tasks.filter((t) => t.status === "completed").length;
1626
1661
  const total = tasks.length;
1627
1662
  const allDone = done === total;
1628
- const header = active ? active.title : allDone ? `Done (${total} tasks)` : `Tasks (${done}/${total})`;
1663
+ const header = active ? active.title : allDone ? `${total} tasks done` : `${done}/${total}`;
1629
1664
  const elapsed = startedAt ? formatElapsed(now - startedAt) : null;
1630
1665
  const headerStats = [elapsed, tokensDelta > 0 ? `\u2191 ${formatTokens(tokensDelta)} tokens` : null].filter(Boolean).join(" \xB7 ");
1631
1666
  const visibleTasks = tasks.slice(0, MAX_VISIBLE);
1632
1667
  const hiddenPending = Math.max(0, tasks.length - visibleTasks.length);
1633
1668
  return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", marginBottom: 1, children: [
1634
1669
  /* @__PURE__ */ jsxs8(Box8, { children: [
1635
- /* @__PURE__ */ jsxs8(Text8, { color: allDone ? "green" : theme.accent, bold: true, children: [
1636
- allDone ? "\u2713" : "\u25B8",
1637
- " ",
1638
- header
1639
- ] }),
1670
+ /* @__PURE__ */ jsx8(Text8, { color: allDone ? "green" : theme.accent, bold: true, children: header }),
1640
1671
  headerStats && /* @__PURE__ */ jsxs8(Text8, { color: theme.info.color, dimColor: theme.info.dim, children: [
1641
1672
  " ",
1642
1673
  "(",
@@ -2423,18 +2454,28 @@ function cachePath() {
2423
2454
  const xdg = process.env.XDG_CONFIG_HOME || join3(homedir4(), ".config");
2424
2455
  return join3(xdg, "kimiflare", "update-check.json");
2425
2456
  }
2426
- function localPackageJsonPath() {
2427
- const here = dirname2(fileURLToPath(import.meta.url));
2428
- return join3(here, "..", "..", "package.json");
2457
+ async function findPackageJson(startDir) {
2458
+ let dir = startDir;
2459
+ while (true) {
2460
+ const candidate = join3(dir, "package.json");
2461
+ try {
2462
+ const raw = await readFile6(candidate, "utf8");
2463
+ const parsed = JSON.parse(raw);
2464
+ if (parsed.name === "kimiflare" && parsed.version) {
2465
+ return { path: candidate, version: parsed.version };
2466
+ }
2467
+ } catch {
2468
+ }
2469
+ const parent = dirname2(dir);
2470
+ if (parent === dir) break;
2471
+ dir = parent;
2472
+ }
2473
+ return null;
2429
2474
  }
2430
2475
  async function readLocalVersion() {
2431
- try {
2432
- const raw = await readFile6(localPackageJsonPath(), "utf8");
2433
- const parsed = JSON.parse(raw);
2434
- return parsed.version ?? null;
2435
- } catch {
2436
- return null;
2437
- }
2476
+ const here = dirname2(fileURLToPath(import.meta.url));
2477
+ const found = await findPackageJson(here);
2478
+ return found?.version ?? null;
2438
2479
  }
2439
2480
  async function readCache() {
2440
2481
  try {
@@ -2494,13 +2535,18 @@ async function checkForUpdate() {
2494
2535
  return { hasUpdate, localVersion, latestVersion };
2495
2536
  }
2496
2537
  async function isGitRepo() {
2497
- try {
2498
- const here = dirname2(fileURLToPath(import.meta.url));
2499
- await access(join3(here, "..", "..", ".git"));
2500
- return true;
2501
- } catch {
2502
- return false;
2538
+ let dir = dirname2(fileURLToPath(import.meta.url));
2539
+ while (true) {
2540
+ try {
2541
+ await access(join3(dir, ".git"));
2542
+ return true;
2543
+ } catch {
2544
+ }
2545
+ const parent = dirname2(dir);
2546
+ if (parent === dir) break;
2547
+ dir = parent;
2503
2548
  }
2549
+ return false;
2504
2550
  }
2505
2551
  var CACHE_TTL_MS, NPM_REGISTRY;
2506
2552
  var init_update_check = __esm({
@@ -2521,6 +2567,7 @@ function Onboarding({ onDone }) {
2521
2567
  const [apiToken, setApiToken] = useState3("");
2522
2568
  const [model, setModel] = useState3(DEFAULT_MODEL);
2523
2569
  const [savedPath, setSavedPath] = useState3(null);
2570
+ const stepIndex = STEPS.indexOf(step) + 1;
2524
2571
  const handleAccountIdSubmit = (value) => {
2525
2572
  const trimmed = value.trim();
2526
2573
  if (!trimmed) return;
@@ -2548,13 +2595,24 @@ function Onboarding({ onDone }) {
2548
2595
  setSavedPath(`error: ${e.message}`);
2549
2596
  }
2550
2597
  };
2551
- return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
2552
- /* @__PURE__ */ jsx10(Text10, { bold: true, color: "cyan", children: "Welcome to kimiflare!" }),
2553
- /* @__PURE__ */ jsx10(Text10, { color: "gray", dimColor: true, children: "Terminal coding agent powered by Kimi-K2.6 on Cloudflare Workers AI." }),
2598
+ return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", paddingY: 1, children: [
2599
+ /* @__PURE__ */ jsxs9(Box9, { marginBottom: 1, children: [
2600
+ /* @__PURE__ */ jsx10(Text10, { bold: true, color: "cyan", children: "kimiflare" }),
2601
+ /* @__PURE__ */ jsxs9(Text10, { color: "gray", dimColor: true, children: [
2602
+ " ",
2603
+ "Terminal coding agent"
2604
+ ] })
2605
+ ] }),
2606
+ /* @__PURE__ */ jsxs9(Text10, { color: "gray", dimColor: true, children: [
2607
+ "Step ",
2608
+ stepIndex,
2609
+ " of ",
2610
+ STEPS.length
2611
+ ] }),
2554
2612
  /* @__PURE__ */ jsxs9(Box9, { marginTop: 1, flexDirection: "column", children: [
2555
2613
  step === "accountId" && /* @__PURE__ */ jsxs9(Fragment, { children: [
2556
- /* @__PURE__ */ jsx10(Text10, { children: "Enter your Cloudflare Account ID:" }),
2557
- /* @__PURE__ */ jsxs9(Box9, { children: [
2614
+ /* @__PURE__ */ jsx10(Text10, { children: "Enter your Cloudflare Account ID" }),
2615
+ /* @__PURE__ */ jsxs9(Box9, { marginTop: 1, children: [
2558
2616
  /* @__PURE__ */ jsx10(Text10, { color: "cyan", children: "\u203A " }),
2559
2617
  /* @__PURE__ */ jsx10(
2560
2618
  CustomTextInput,
@@ -2567,9 +2625,9 @@ function Onboarding({ onDone }) {
2567
2625
  ] })
2568
2626
  ] }),
2569
2627
  step === "apiToken" && /* @__PURE__ */ jsxs9(Fragment, { children: [
2570
- /* @__PURE__ */ jsx10(Text10, { children: "Enter your Cloudflare API Token:" }),
2628
+ /* @__PURE__ */ jsx10(Text10, { children: "Enter your Cloudflare API Token" }),
2571
2629
  /* @__PURE__ */ jsx10(Text10, { color: "gray", dimColor: true, children: "Create one at https://dash.cloudflare.com/profile/api-tokens" }),
2572
- /* @__PURE__ */ jsxs9(Box9, { children: [
2630
+ /* @__PURE__ */ jsxs9(Box9, { marginTop: 1, children: [
2573
2631
  /* @__PURE__ */ jsx10(Text10, { color: "cyan", children: "\u203A " }),
2574
2632
  /* @__PURE__ */ jsx10(
2575
2633
  CustomTextInput,
@@ -2583,12 +2641,12 @@ function Onboarding({ onDone }) {
2583
2641
  ] })
2584
2642
  ] }),
2585
2643
  step === "model" && /* @__PURE__ */ jsxs9(Fragment, { children: [
2586
- /* @__PURE__ */ jsx10(Text10, { children: "Model ID (press Enter for default):" }),
2644
+ /* @__PURE__ */ jsx10(Text10, { children: "Model ID (press Enter for default)" }),
2587
2645
  /* @__PURE__ */ jsxs9(Text10, { color: "gray", dimColor: true, children: [
2588
2646
  "default: ",
2589
2647
  DEFAULT_MODEL
2590
2648
  ] }),
2591
- /* @__PURE__ */ jsxs9(Box9, { children: [
2649
+ /* @__PURE__ */ jsxs9(Box9, { marginTop: 1, children: [
2592
2650
  /* @__PURE__ */ jsx10(Text10, { color: "cyan", children: "\u203A " }),
2593
2651
  /* @__PURE__ */ jsx10(
2594
2652
  CustomTextInput,
@@ -2601,23 +2659,34 @@ function Onboarding({ onDone }) {
2601
2659
  ] })
2602
2660
  ] }),
2603
2661
  step === "confirm" && /* @__PURE__ */ jsxs9(Fragment, { children: [
2604
- /* @__PURE__ */ jsx10(Text10, { children: "Ready to save configuration:" }),
2605
- /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", marginLeft: 2, children: [
2606
- /* @__PURE__ */ jsxs9(Text10, { color: "gray", children: [
2607
- "Account ID: ",
2608
- accountId
2609
- ] }),
2610
- /* @__PURE__ */ jsxs9(Text10, { color: "gray", children: [
2611
- "API Token: ",
2612
- "\u2022".repeat(apiToken.length)
2613
- ] }),
2614
- /* @__PURE__ */ jsxs9(Text10, { color: "gray", children: [
2615
- "Model: ",
2616
- model
2617
- ] })
2618
- ] }),
2619
- /* @__PURE__ */ jsx10(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx10(Text10, { children: "Press Enter to confirm, or Ctrl+C to cancel" }) }),
2620
- /* @__PURE__ */ jsxs9(Box9, { children: [
2662
+ /* @__PURE__ */ jsx10(Text10, { children: "Ready to save configuration" }),
2663
+ /* @__PURE__ */ jsxs9(
2664
+ Box9,
2665
+ {
2666
+ flexDirection: "column",
2667
+ marginTop: 1,
2668
+ marginBottom: 1,
2669
+ borderStyle: "single",
2670
+ borderColor: "gray",
2671
+ paddingX: 1,
2672
+ children: [
2673
+ /* @__PURE__ */ jsxs9(Text10, { color: "gray", children: [
2674
+ "Account ID: ",
2675
+ accountId
2676
+ ] }),
2677
+ /* @__PURE__ */ jsxs9(Text10, { color: "gray", children: [
2678
+ "API Token: ",
2679
+ "\u2022".repeat(apiToken.length)
2680
+ ] }),
2681
+ /* @__PURE__ */ jsxs9(Text10, { color: "gray", children: [
2682
+ "Model: ",
2683
+ model
2684
+ ] })
2685
+ ]
2686
+ }
2687
+ ),
2688
+ /* @__PURE__ */ jsx10(Text10, { children: "Press Enter to confirm, or Ctrl+C to cancel" }),
2689
+ /* @__PURE__ */ jsxs9(Box9, { marginTop: 1, children: [
2621
2690
  /* @__PURE__ */ jsx10(Text10, { color: "cyan", children: "\u203A " }),
2622
2691
  /* @__PURE__ */ jsx10(
2623
2692
  CustomTextInput,
@@ -2637,11 +2706,48 @@ function Onboarding({ onDone }) {
2637
2706
  ] })
2638
2707
  ] });
2639
2708
  }
2709
+ var STEPS;
2640
2710
  var init_onboarding = __esm({
2641
2711
  "src/ui/onboarding.tsx"() {
2642
2712
  "use strict";
2643
2713
  init_text_input();
2644
2714
  init_config();
2715
+ STEPS = ["accountId", "apiToken", "model", "confirm"];
2716
+ }
2717
+ });
2718
+
2719
+ // src/ui/welcome.tsx
2720
+ import { Box as Box10, Text as Text11 } from "ink";
2721
+ import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
2722
+ function Welcome({ theme }) {
2723
+ return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", marginBottom: 1, children: [
2724
+ /* @__PURE__ */ jsxs10(Box10, { marginBottom: 1, children: [
2725
+ /* @__PURE__ */ jsx11(Text11, { bold: true, color: theme.accent, children: "kimiflare" }),
2726
+ /* @__PURE__ */ jsxs10(Text11, { color: theme.info.color, dimColor: theme.info.dim, children: [
2727
+ " ",
2728
+ "Ready when you are."
2729
+ ] })
2730
+ ] }),
2731
+ /* @__PURE__ */ jsx11(Box10, { flexDirection: "column", children: SUGGESTIONS.map((s, i) => /* @__PURE__ */ jsxs10(Box10, { children: [
2732
+ /* @__PURE__ */ jsxs10(Text11, { color: theme.info.color, dimColor: theme.info.dim, children: [
2733
+ " ",
2734
+ "\u203A",
2735
+ " "
2736
+ ] }),
2737
+ /* @__PURE__ */ jsx11(Text11, { color: theme.user, children: s })
2738
+ ] }, i)) }),
2739
+ /* @__PURE__ */ jsx11(Box10, { marginTop: 1, children: /* @__PURE__ */ jsx11(Text11, { color: theme.info.color, dimColor: theme.info.dim, children: "Type a message or /help for commands \xB7 ctrl-c to exit \xB7 shift+tab to cycle modes" }) })
2740
+ ] });
2741
+ }
2742
+ var SUGGESTIONS;
2743
+ var init_welcome = __esm({
2744
+ "src/ui/welcome.tsx"() {
2745
+ "use strict";
2746
+ SUGGESTIONS = [
2747
+ "Explain this codebase",
2748
+ "Find and fix a bug",
2749
+ "Refactor a file"
2750
+ ];
2645
2751
  }
2646
2752
  });
2647
2753
 
@@ -2662,14 +2768,14 @@ var init_theme = __esm({
2662
2768
  label: "dark (default \u2014 for dark terminals)",
2663
2769
  user: "cyan",
2664
2770
  assistant: void 0,
2665
- reasoning: { color: "gray", dim: false },
2666
- info: { color: "gray", dim: false },
2771
+ reasoning: { color: "gray", dim: true },
2772
+ info: { color: "gray", dim: true },
2667
2773
  error: "red",
2668
2774
  warn: "yellow",
2669
- tool: "magenta",
2775
+ tool: "cyan",
2670
2776
  spinner: "yellow",
2671
2777
  permission: "yellow",
2672
- queue: { color: "gray", dim: false },
2778
+ queue: { color: "gray", dim: true },
2673
2779
  accent: "cyan",
2674
2780
  modeBadge: { plan: "blue", auto: "green", edit: "cyan" }
2675
2781
  };
@@ -2784,29 +2890,15 @@ __export(app_exports, {
2784
2890
  renderApp: () => renderApp
2785
2891
  });
2786
2892
  import { useState as useState4, useRef as useRef2, useEffect as useEffect3, useCallback } from "react";
2787
- import { Box as Box10, Text as Text11, useApp, useInput as useInput2, render } from "ink";
2788
- import Spinner2 from "ink-spinner";
2893
+ import { Box as Box11, Text as Text12, useApp, useInput as useInput2, render } from "ink";
2789
2894
  import { existsSync } from "fs";
2790
2895
  import { join as join5 } from "path";
2791
2896
  import { unlink } from "fs/promises";
2792
- import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
2897
+ import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
2793
2898
  function App({ initialCfg }) {
2794
2899
  const { exit } = useApp();
2795
2900
  const [cfg, setCfg] = useState4(initialCfg);
2796
- const [events, setEvents] = useState4(() => {
2797
- const initial = [
2798
- { kind: "info", key: mkKey(), text: "kimiflare \xB7 /help for commands \xB7 ctrl-c to exit \xB7 shift+tab to cycle modes" }
2799
- ];
2800
- const ctxFile = loadContextFile(process.cwd());
2801
- if (ctxFile) {
2802
- initial.push({
2803
- kind: "info",
2804
- key: mkKey(),
2805
- text: `loaded project context from ${ctxFile.name} (${ctxFile.lineCount} lines)`
2806
- });
2807
- }
2808
- return initial;
2809
- });
2901
+ const [events, setEvents] = useState4([]);
2810
2902
  const [input, setInput] = useState4("");
2811
2903
  const [busy, setBusy] = useState4(false);
2812
2904
  const [usage, setUsage] = useState4(null);
@@ -2816,7 +2908,6 @@ function App({ initialCfg }) {
2816
2908
  const [history, setHistory] = useState4([]);
2817
2909
  const [historyIndex, setHistoryIndex] = useState4(-1);
2818
2910
  const [draftInput, setDraftInput] = useState4("");
2819
- const [updateInfo, setUpdateInfo] = useState4(null);
2820
2911
  const [mode, setMode] = useState4("edit");
2821
2912
  const [effort, setEffort] = useState4(
2822
2913
  initialCfg?.reasoningEffort ?? DEFAULT_REASONING_EFFORT
@@ -2899,25 +2990,11 @@ function App({ initialCfg }) {
2899
2990
  return;
2900
2991
  }
2901
2992
  if (key.shift && key.tab) {
2902
- setMode((m) => {
2903
- const nm = nextMode(m);
2904
- setEvents((e) => [
2905
- ...e,
2906
- { kind: "info", key: mkKey(), text: `mode: ${nm}` }
2907
- ]);
2908
- return nm;
2909
- });
2993
+ setMode((m) => nextMode(m));
2910
2994
  return;
2911
2995
  }
2912
2996
  if (key.ctrl && inputChar === "o") {
2913
- setVerbose((v) => {
2914
- const next = !v;
2915
- setEvents((e) => [
2916
- ...e,
2917
- { kind: "info", key: mkKey(), text: `output: ${next ? "verbose (full tool results)" : "compact"}` }
2918
- ]);
2919
- return next;
2920
- });
2997
+ setVerbose((v) => !v);
2921
2998
  return;
2922
2999
  }
2923
3000
  });
@@ -3316,42 +3393,33 @@ use: /thinking low | medium | high`
3316
3393
  return true;
3317
3394
  }
3318
3395
  if (c === "/update") {
3319
- if (updateInfo?.hasUpdate) {
3320
- setEvents((e) => [
3321
- ...e,
3322
- {
3323
- kind: "info",
3324
- key: mkKey(),
3325
- text: `updating from ${updateInfo.localVersion} \u2192 ${updateInfo.latestVersion}\u2026`
3326
- }
3327
- ]);
3328
- isGitRepo().then((git) => {
3329
- if (git) {
3330
- setEvents((e) => [
3331
- ...e,
3332
- {
3333
- kind: "info",
3334
- key: mkKey(),
3335
- text: "run: git pull && npm install && npm run build then restart kimiflare"
3336
- }
3337
- ]);
3338
- } else {
3396
+ void checkForUpdate().then((result) => {
3397
+ if (result.hasUpdate) {
3398
+ setEvents((e) => [
3399
+ ...e,
3400
+ {
3401
+ kind: "info",
3402
+ key: mkKey(),
3403
+ text: `update available: ${result.localVersion} \u2192 ${result.latestVersion}`
3404
+ }
3405
+ ]);
3406
+ void isGitRepo().then((git) => {
3339
3407
  setEvents((e) => [
3340
3408
  ...e,
3341
3409
  {
3342
3410
  kind: "info",
3343
3411
  key: mkKey(),
3344
- text: "run: npm update -g kimiflare then restart"
3412
+ text: git ? "run: git pull && npm install && npm run build then restart kimiflare" : "run: npm update -g kimiflare then restart"
3345
3413
  }
3346
3414
  ]);
3347
- }
3348
- });
3349
- } else {
3350
- setEvents((e) => [
3351
- ...e,
3352
- { kind: "info", key: mkKey(), text: "no update available" }
3353
- ]);
3354
- }
3415
+ });
3416
+ } else {
3417
+ setEvents((e) => [
3418
+ ...e,
3419
+ { kind: "info", key: mkKey(), text: "no update available" }
3420
+ ]);
3421
+ }
3422
+ });
3355
3423
  return true;
3356
3424
  }
3357
3425
  if (c === "/logout") {
@@ -3377,7 +3445,7 @@ use: /thinking low | medium | high`
3377
3445
  }
3378
3446
  return false;
3379
3447
  },
3380
- [cfg, exit, usage, updateInfo, effort, theme, mode, openResumePicker, runCompact, runInit]
3448
+ [cfg, exit, usage, effort, theme, mode, openResumePicker, runCompact, runInit]
3381
3449
  );
3382
3450
  const processMessage = useCallback(
3383
3451
  async (text, displayText) => {
@@ -3534,21 +3602,6 @@ use: /thinking low | medium | high`
3534
3602
  },
3535
3603
  [busy, processMessage]
3536
3604
  );
3537
- useEffect3(() => {
3538
- checkForUpdate().then((result) => {
3539
- if (result.hasUpdate) {
3540
- setUpdateInfo(result);
3541
- setEvents((e) => [
3542
- ...e,
3543
- {
3544
- kind: "info",
3545
- key: mkKey(),
3546
- text: `update available: ${result.localVersion} \u2192 ${result.latestVersion} \xB7 run /update to upgrade`
3547
- }
3548
- ]);
3549
- }
3550
- });
3551
- }, []);
3552
3605
  useEffect3(() => {
3553
3606
  if (usage && usage.prompt_tokens / CONTEXT_LIMIT >= AUTO_COMPACT_SUGGEST_PCT) {
3554
3607
  setEvents((e) => {
@@ -3566,7 +3619,7 @@ use: /thinking low | medium | high`
3566
3619
  }
3567
3620
  }, [usage]);
3568
3621
  if (!cfg) {
3569
- return /* @__PURE__ */ jsx11(
3622
+ return /* @__PURE__ */ jsx12(
3570
3623
  Onboarding,
3571
3624
  {
3572
3625
  onDone: (newCfg) => {
@@ -3580,11 +3633,12 @@ use: /thinking low | medium | high`
3580
3633
  );
3581
3634
  }
3582
3635
  if (resumeSessions !== null) {
3583
- return /* @__PURE__ */ jsx11(Box10, { flexDirection: "column", children: /* @__PURE__ */ jsx11(ResumePicker, { sessions: resumeSessions, onPick: handleResumePick, theme }) });
3636
+ return /* @__PURE__ */ jsx12(Box11, { flexDirection: "column", children: /* @__PURE__ */ jsx12(ResumePicker, { sessions: resumeSessions, onPick: handleResumePick, theme }) });
3584
3637
  }
3585
- return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
3586
- /* @__PURE__ */ jsx11(ChatView, { events, showReasoning, theme, verbose }),
3587
- perm ? /* @__PURE__ */ jsx11(
3638
+ const hasConversation = events.some((e) => e.kind === "user" || e.kind === "assistant");
3639
+ return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", children: [
3640
+ !hasConversation && events.length === 0 ? /* @__PURE__ */ jsx12(Welcome, { theme }) : /* @__PURE__ */ jsx12(ChatView, { events, showReasoning, theme, verbose }),
3641
+ perm ? /* @__PURE__ */ jsx12(
3588
3642
  PermissionModal,
3589
3643
  {
3590
3644
  tool: perm.tool,
@@ -3595,8 +3649,8 @@ use: /thinking low | medium | high`
3595
3649
  setPerm(null);
3596
3650
  }
3597
3651
  }
3598
- ) : /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", marginTop: 1, children: [
3599
- tasks.length > 0 && /* @__PURE__ */ jsx11(
3652
+ ) : /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", marginTop: 1, children: [
3653
+ tasks.length > 0 && /* @__PURE__ */ jsx12(
3600
3654
  TaskList,
3601
3655
  {
3602
3656
  tasks,
@@ -3605,30 +3659,25 @@ use: /thinking low | medium | high`
3605
3659
  tokensDelta: Math.max(0, (usage?.prompt_tokens ?? 0) - tasksStartTokens)
3606
3660
  }
3607
3661
  ),
3608
- queue.length > 0 && /* @__PURE__ */ jsx11(Box10, { flexDirection: "column", marginBottom: 1, children: queue.map((q, i) => /* @__PURE__ */ jsxs10(Text11, { color: theme.queue.color, dimColor: theme.queue.dim, children: [
3662
+ queue.length > 0 && /* @__PURE__ */ jsx12(Box11, { flexDirection: "column", marginBottom: 1, children: queue.map((q, i) => /* @__PURE__ */ jsxs11(Text12, { color: theme.queue.color, dimColor: theme.queue.dim, children: [
3609
3663
  "\u23F3 ",
3610
3664
  q.display
3611
3665
  ] }, `queue_${i}`)) }),
3612
- /* @__PURE__ */ jsx11(
3666
+ /* @__PURE__ */ jsx12(
3613
3667
  StatusBar,
3614
3668
  {
3615
3669
  model: cfg.model,
3616
3670
  usage,
3617
3671
  thinking: busy,
3618
- hint: busy ? "ctrl-c to interrupt \xB7 type to queue next" : "enter to send \xB7 /help \xB7 shift+tab cycles mode",
3619
3672
  theme,
3620
3673
  mode,
3621
3674
  effort,
3622
3675
  contextLimit: CONTEXT_LIMIT
3623
3676
  }
3624
3677
  ),
3625
- busy && /* @__PURE__ */ jsxs10(Box10, { children: [
3626
- /* @__PURE__ */ jsx11(Text11, { color: theme.spinner, children: /* @__PURE__ */ jsx11(Spinner2, { type: "dots" }) }),
3627
- /* @__PURE__ */ jsx11(Text11, { color: theme.info.color, dimColor: theme.info.dim, children: " working\u2026" })
3628
- ] }),
3629
- /* @__PURE__ */ jsxs10(Box10, { children: [
3630
- /* @__PURE__ */ jsx11(Text11, { color: theme.user, children: busy ? "\u23F3 " : "\u203A " }),
3631
- /* @__PURE__ */ jsx11(
3678
+ /* @__PURE__ */ jsxs11(Box11, { marginTop: 1, children: [
3679
+ /* @__PURE__ */ jsx12(Text12, { color: theme.accent, children: "\u203A " }),
3680
+ /* @__PURE__ */ jsx12(
3632
3681
  CustomTextInput,
3633
3682
  {
3634
3683
  value: input,
@@ -3677,7 +3726,7 @@ use: /thinking low | medium | high`
3677
3726
  ] });
3678
3727
  }
3679
3728
  async function renderApp(cfg) {
3680
- const instance = render(/* @__PURE__ */ jsx11(App, { initialCfg: cfg }));
3729
+ const instance = render(/* @__PURE__ */ jsx12(App, { initialCfg: cfg }));
3681
3730
  await instance.waitUntilExit();
3682
3731
  }
3683
3732
  var CONTEXT_LIMIT, AUTO_COMPACT_SUGGEST_PCT, nextAssistantId, nextKey, mkKey, EFFORT_DESCRIPTIONS;
@@ -3693,10 +3742,10 @@ var init_app = __esm({
3693
3742
  init_permission();
3694
3743
  init_resume_picker();
3695
3744
  init_task_list();
3696
- init_system_prompt();
3697
3745
  init_text_input();
3698
3746
  init_update_check();
3699
3747
  init_onboarding();
3748
+ init_welcome();
3700
3749
  init_config();
3701
3750
  init_theme();
3702
3751
  init_mode();