kimiflare 0.3.1 → 0.4.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
@@ -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
  "(",
@@ -2521,6 +2552,7 @@ function Onboarding({ onDone }) {
2521
2552
  const [apiToken, setApiToken] = useState3("");
2522
2553
  const [model, setModel] = useState3(DEFAULT_MODEL);
2523
2554
  const [savedPath, setSavedPath] = useState3(null);
2555
+ const stepIndex = STEPS.indexOf(step) + 1;
2524
2556
  const handleAccountIdSubmit = (value) => {
2525
2557
  const trimmed = value.trim();
2526
2558
  if (!trimmed) return;
@@ -2548,13 +2580,24 @@ function Onboarding({ onDone }) {
2548
2580
  setSavedPath(`error: ${e.message}`);
2549
2581
  }
2550
2582
  };
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." }),
2583
+ return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", paddingY: 1, children: [
2584
+ /* @__PURE__ */ jsxs9(Box9, { marginBottom: 1, children: [
2585
+ /* @__PURE__ */ jsx10(Text10, { bold: true, color: "cyan", children: "kimiflare" }),
2586
+ /* @__PURE__ */ jsxs9(Text10, { color: "gray", dimColor: true, children: [
2587
+ " ",
2588
+ "Terminal coding agent"
2589
+ ] })
2590
+ ] }),
2591
+ /* @__PURE__ */ jsxs9(Text10, { color: "gray", dimColor: true, children: [
2592
+ "Step ",
2593
+ stepIndex,
2594
+ " of ",
2595
+ STEPS.length
2596
+ ] }),
2554
2597
  /* @__PURE__ */ jsxs9(Box9, { marginTop: 1, flexDirection: "column", children: [
2555
2598
  step === "accountId" && /* @__PURE__ */ jsxs9(Fragment, { children: [
2556
- /* @__PURE__ */ jsx10(Text10, { children: "Enter your Cloudflare Account ID:" }),
2557
- /* @__PURE__ */ jsxs9(Box9, { children: [
2599
+ /* @__PURE__ */ jsx10(Text10, { children: "Enter your Cloudflare Account ID" }),
2600
+ /* @__PURE__ */ jsxs9(Box9, { marginTop: 1, children: [
2558
2601
  /* @__PURE__ */ jsx10(Text10, { color: "cyan", children: "\u203A " }),
2559
2602
  /* @__PURE__ */ jsx10(
2560
2603
  CustomTextInput,
@@ -2567,9 +2610,9 @@ function Onboarding({ onDone }) {
2567
2610
  ] })
2568
2611
  ] }),
2569
2612
  step === "apiToken" && /* @__PURE__ */ jsxs9(Fragment, { children: [
2570
- /* @__PURE__ */ jsx10(Text10, { children: "Enter your Cloudflare API Token:" }),
2613
+ /* @__PURE__ */ jsx10(Text10, { children: "Enter your Cloudflare API Token" }),
2571
2614
  /* @__PURE__ */ jsx10(Text10, { color: "gray", dimColor: true, children: "Create one at https://dash.cloudflare.com/profile/api-tokens" }),
2572
- /* @__PURE__ */ jsxs9(Box9, { children: [
2615
+ /* @__PURE__ */ jsxs9(Box9, { marginTop: 1, children: [
2573
2616
  /* @__PURE__ */ jsx10(Text10, { color: "cyan", children: "\u203A " }),
2574
2617
  /* @__PURE__ */ jsx10(
2575
2618
  CustomTextInput,
@@ -2583,12 +2626,12 @@ function Onboarding({ onDone }) {
2583
2626
  ] })
2584
2627
  ] }),
2585
2628
  step === "model" && /* @__PURE__ */ jsxs9(Fragment, { children: [
2586
- /* @__PURE__ */ jsx10(Text10, { children: "Model ID (press Enter for default):" }),
2629
+ /* @__PURE__ */ jsx10(Text10, { children: "Model ID (press Enter for default)" }),
2587
2630
  /* @__PURE__ */ jsxs9(Text10, { color: "gray", dimColor: true, children: [
2588
2631
  "default: ",
2589
2632
  DEFAULT_MODEL
2590
2633
  ] }),
2591
- /* @__PURE__ */ jsxs9(Box9, { children: [
2634
+ /* @__PURE__ */ jsxs9(Box9, { marginTop: 1, children: [
2592
2635
  /* @__PURE__ */ jsx10(Text10, { color: "cyan", children: "\u203A " }),
2593
2636
  /* @__PURE__ */ jsx10(
2594
2637
  CustomTextInput,
@@ -2601,23 +2644,34 @@ function Onboarding({ onDone }) {
2601
2644
  ] })
2602
2645
  ] }),
2603
2646
  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: [
2647
+ /* @__PURE__ */ jsx10(Text10, { children: "Ready to save configuration" }),
2648
+ /* @__PURE__ */ jsxs9(
2649
+ Box9,
2650
+ {
2651
+ flexDirection: "column",
2652
+ marginTop: 1,
2653
+ marginBottom: 1,
2654
+ borderStyle: "single",
2655
+ borderColor: "gray",
2656
+ paddingX: 1,
2657
+ children: [
2658
+ /* @__PURE__ */ jsxs9(Text10, { color: "gray", children: [
2659
+ "Account ID: ",
2660
+ accountId
2661
+ ] }),
2662
+ /* @__PURE__ */ jsxs9(Text10, { color: "gray", children: [
2663
+ "API Token: ",
2664
+ "\u2022".repeat(apiToken.length)
2665
+ ] }),
2666
+ /* @__PURE__ */ jsxs9(Text10, { color: "gray", children: [
2667
+ "Model: ",
2668
+ model
2669
+ ] })
2670
+ ]
2671
+ }
2672
+ ),
2673
+ /* @__PURE__ */ jsx10(Text10, { children: "Press Enter to confirm, or Ctrl+C to cancel" }),
2674
+ /* @__PURE__ */ jsxs9(Box9, { marginTop: 1, children: [
2621
2675
  /* @__PURE__ */ jsx10(Text10, { color: "cyan", children: "\u203A " }),
2622
2676
  /* @__PURE__ */ jsx10(
2623
2677
  CustomTextInput,
@@ -2637,11 +2691,48 @@ function Onboarding({ onDone }) {
2637
2691
  ] })
2638
2692
  ] });
2639
2693
  }
2694
+ var STEPS;
2640
2695
  var init_onboarding = __esm({
2641
2696
  "src/ui/onboarding.tsx"() {
2642
2697
  "use strict";
2643
2698
  init_text_input();
2644
2699
  init_config();
2700
+ STEPS = ["accountId", "apiToken", "model", "confirm"];
2701
+ }
2702
+ });
2703
+
2704
+ // src/ui/welcome.tsx
2705
+ import { Box as Box10, Text as Text11 } from "ink";
2706
+ import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
2707
+ function Welcome({ theme }) {
2708
+ return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", marginBottom: 1, children: [
2709
+ /* @__PURE__ */ jsxs10(Box10, { marginBottom: 1, children: [
2710
+ /* @__PURE__ */ jsx11(Text11, { bold: true, color: theme.accent, children: "kimiflare" }),
2711
+ /* @__PURE__ */ jsxs10(Text11, { color: theme.info.color, dimColor: theme.info.dim, children: [
2712
+ " ",
2713
+ "Ready when you are."
2714
+ ] })
2715
+ ] }),
2716
+ /* @__PURE__ */ jsx11(Box10, { flexDirection: "column", children: SUGGESTIONS.map((s, i) => /* @__PURE__ */ jsxs10(Box10, { children: [
2717
+ /* @__PURE__ */ jsxs10(Text11, { color: theme.info.color, dimColor: theme.info.dim, children: [
2718
+ " ",
2719
+ "\u203A",
2720
+ " "
2721
+ ] }),
2722
+ /* @__PURE__ */ jsx11(Text11, { color: theme.user, children: s })
2723
+ ] }, i)) }),
2724
+ /* @__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" }) })
2725
+ ] });
2726
+ }
2727
+ var SUGGESTIONS;
2728
+ var init_welcome = __esm({
2729
+ "src/ui/welcome.tsx"() {
2730
+ "use strict";
2731
+ SUGGESTIONS = [
2732
+ "Explain this codebase",
2733
+ "Find and fix a bug",
2734
+ "Refactor a file"
2735
+ ];
2645
2736
  }
2646
2737
  });
2647
2738
 
@@ -2662,14 +2753,14 @@ var init_theme = __esm({
2662
2753
  label: "dark (default \u2014 for dark terminals)",
2663
2754
  user: "cyan",
2664
2755
  assistant: void 0,
2665
- reasoning: { color: "gray", dim: false },
2666
- info: { color: "gray", dim: false },
2756
+ reasoning: { color: "gray", dim: true },
2757
+ info: { color: "gray", dim: true },
2667
2758
  error: "red",
2668
2759
  warn: "yellow",
2669
- tool: "magenta",
2760
+ tool: "cyan",
2670
2761
  spinner: "yellow",
2671
2762
  permission: "yellow",
2672
- queue: { color: "gray", dim: false },
2763
+ queue: { color: "gray", dim: true },
2673
2764
  accent: "cyan",
2674
2765
  modeBadge: { plan: "blue", auto: "green", edit: "cyan" }
2675
2766
  };
@@ -2784,29 +2875,15 @@ __export(app_exports, {
2784
2875
  renderApp: () => renderApp
2785
2876
  });
2786
2877
  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";
2878
+ import { Box as Box11, Text as Text12, useApp, useInput as useInput2, render } from "ink";
2789
2879
  import { existsSync } from "fs";
2790
2880
  import { join as join5 } from "path";
2791
2881
  import { unlink } from "fs/promises";
2792
- import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
2882
+ import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
2793
2883
  function App({ initialCfg }) {
2794
2884
  const { exit } = useApp();
2795
2885
  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
- });
2886
+ const [events, setEvents] = useState4([]);
2810
2887
  const [input, setInput] = useState4("");
2811
2888
  const [busy, setBusy] = useState4(false);
2812
2889
  const [usage, setUsage] = useState4(null);
@@ -2816,7 +2893,6 @@ function App({ initialCfg }) {
2816
2893
  const [history, setHistory] = useState4([]);
2817
2894
  const [historyIndex, setHistoryIndex] = useState4(-1);
2818
2895
  const [draftInput, setDraftInput] = useState4("");
2819
- const [updateInfo, setUpdateInfo] = useState4(null);
2820
2896
  const [mode, setMode] = useState4("edit");
2821
2897
  const [effort, setEffort] = useState4(
2822
2898
  initialCfg?.reasoningEffort ?? DEFAULT_REASONING_EFFORT
@@ -2899,25 +2975,11 @@ function App({ initialCfg }) {
2899
2975
  return;
2900
2976
  }
2901
2977
  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
- });
2978
+ setMode((m) => nextMode(m));
2910
2979
  return;
2911
2980
  }
2912
2981
  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
- });
2982
+ setVerbose((v) => !v);
2921
2983
  return;
2922
2984
  }
2923
2985
  });
@@ -3316,42 +3378,33 @@ use: /thinking low | medium | high`
3316
3378
  return true;
3317
3379
  }
3318
3380
  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 {
3381
+ void checkForUpdate().then((result) => {
3382
+ if (result.hasUpdate) {
3383
+ setEvents((e) => [
3384
+ ...e,
3385
+ {
3386
+ kind: "info",
3387
+ key: mkKey(),
3388
+ text: `update available: ${result.localVersion} \u2192 ${result.latestVersion}`
3389
+ }
3390
+ ]);
3391
+ void isGitRepo().then((git) => {
3339
3392
  setEvents((e) => [
3340
3393
  ...e,
3341
3394
  {
3342
3395
  kind: "info",
3343
3396
  key: mkKey(),
3344
- text: "run: npm update -g kimiflare then restart"
3397
+ text: git ? "run: git pull && npm install && npm run build then restart kimiflare" : "run: npm update -g kimiflare then restart"
3345
3398
  }
3346
3399
  ]);
3347
- }
3348
- });
3349
- } else {
3350
- setEvents((e) => [
3351
- ...e,
3352
- { kind: "info", key: mkKey(), text: "no update available" }
3353
- ]);
3354
- }
3400
+ });
3401
+ } else {
3402
+ setEvents((e) => [
3403
+ ...e,
3404
+ { kind: "info", key: mkKey(), text: "no update available" }
3405
+ ]);
3406
+ }
3407
+ });
3355
3408
  return true;
3356
3409
  }
3357
3410
  if (c === "/logout") {
@@ -3377,7 +3430,7 @@ use: /thinking low | medium | high`
3377
3430
  }
3378
3431
  return false;
3379
3432
  },
3380
- [cfg, exit, usage, updateInfo, effort, theme, mode, openResumePicker, runCompact, runInit]
3433
+ [cfg, exit, usage, effort, theme, mode, openResumePicker, runCompact, runInit]
3381
3434
  );
3382
3435
  const processMessage = useCallback(
3383
3436
  async (text, displayText) => {
@@ -3534,21 +3587,6 @@ use: /thinking low | medium | high`
3534
3587
  },
3535
3588
  [busy, processMessage]
3536
3589
  );
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
3590
  useEffect3(() => {
3553
3591
  if (usage && usage.prompt_tokens / CONTEXT_LIMIT >= AUTO_COMPACT_SUGGEST_PCT) {
3554
3592
  setEvents((e) => {
@@ -3566,7 +3604,7 @@ use: /thinking low | medium | high`
3566
3604
  }
3567
3605
  }, [usage]);
3568
3606
  if (!cfg) {
3569
- return /* @__PURE__ */ jsx11(
3607
+ return /* @__PURE__ */ jsx12(
3570
3608
  Onboarding,
3571
3609
  {
3572
3610
  onDone: (newCfg) => {
@@ -3580,11 +3618,12 @@ use: /thinking low | medium | high`
3580
3618
  );
3581
3619
  }
3582
3620
  if (resumeSessions !== null) {
3583
- return /* @__PURE__ */ jsx11(Box10, { flexDirection: "column", children: /* @__PURE__ */ jsx11(ResumePicker, { sessions: resumeSessions, onPick: handleResumePick, theme }) });
3621
+ return /* @__PURE__ */ jsx12(Box11, { flexDirection: "column", children: /* @__PURE__ */ jsx12(ResumePicker, { sessions: resumeSessions, onPick: handleResumePick, theme }) });
3584
3622
  }
3585
- return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
3586
- /* @__PURE__ */ jsx11(ChatView, { events, showReasoning, theme, verbose }),
3587
- perm ? /* @__PURE__ */ jsx11(
3623
+ const hasConversation = events.some((e) => e.kind === "user" || e.kind === "assistant");
3624
+ return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", children: [
3625
+ !hasConversation && events.length === 0 ? /* @__PURE__ */ jsx12(Welcome, { theme }) : /* @__PURE__ */ jsx12(ChatView, { events, showReasoning, theme, verbose }),
3626
+ perm ? /* @__PURE__ */ jsx12(
3588
3627
  PermissionModal,
3589
3628
  {
3590
3629
  tool: perm.tool,
@@ -3595,8 +3634,8 @@ use: /thinking low | medium | high`
3595
3634
  setPerm(null);
3596
3635
  }
3597
3636
  }
3598
- ) : /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", marginTop: 1, children: [
3599
- tasks.length > 0 && /* @__PURE__ */ jsx11(
3637
+ ) : /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", marginTop: 1, children: [
3638
+ tasks.length > 0 && /* @__PURE__ */ jsx12(
3600
3639
  TaskList,
3601
3640
  {
3602
3641
  tasks,
@@ -3605,30 +3644,25 @@ use: /thinking low | medium | high`
3605
3644
  tokensDelta: Math.max(0, (usage?.prompt_tokens ?? 0) - tasksStartTokens)
3606
3645
  }
3607
3646
  ),
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: [
3647
+ 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
3648
  "\u23F3 ",
3610
3649
  q.display
3611
3650
  ] }, `queue_${i}`)) }),
3612
- /* @__PURE__ */ jsx11(
3651
+ /* @__PURE__ */ jsx12(
3613
3652
  StatusBar,
3614
3653
  {
3615
3654
  model: cfg.model,
3616
3655
  usage,
3617
3656
  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
3657
  theme,
3620
3658
  mode,
3621
3659
  effort,
3622
3660
  contextLimit: CONTEXT_LIMIT
3623
3661
  }
3624
3662
  ),
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(
3663
+ /* @__PURE__ */ jsxs11(Box11, { marginTop: 1, children: [
3664
+ /* @__PURE__ */ jsx12(Text12, { color: theme.accent, children: "\u203A " }),
3665
+ /* @__PURE__ */ jsx12(
3632
3666
  CustomTextInput,
3633
3667
  {
3634
3668
  value: input,
@@ -3677,7 +3711,7 @@ use: /thinking low | medium | high`
3677
3711
  ] });
3678
3712
  }
3679
3713
  async function renderApp(cfg) {
3680
- const instance = render(/* @__PURE__ */ jsx11(App, { initialCfg: cfg }));
3714
+ const instance = render(/* @__PURE__ */ jsx12(App, { initialCfg: cfg }));
3681
3715
  await instance.waitUntilExit();
3682
3716
  }
3683
3717
  var CONTEXT_LIMIT, AUTO_COMPACT_SUGGEST_PCT, nextAssistantId, nextKey, mkKey, EFFORT_DESCRIPTIONS;
@@ -3693,10 +3727,10 @@ var init_app = __esm({
3693
3727
  init_permission();
3694
3728
  init_resume_picker();
3695
3729
  init_task_list();
3696
- init_system_prompt();
3697
3730
  init_text_input();
3698
3731
  init_update_check();
3699
3732
  init_onboarding();
3733
+ init_welcome();
3700
3734
  init_config();
3701
3735
  init_theme();
3702
3736
  init_mode();