darkfoo-code 0.1.4 → 0.2.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.
Files changed (2) hide show
  1. package/dist/main.js +366 -144
  2. package/package.json +1 -1
package/dist/main.js CHANGED
@@ -1785,7 +1785,7 @@ var init_tasks = __esm({
1785
1785
  async call(_input, _context) {
1786
1786
  const { tasks } = getAppState();
1787
1787
  if (tasks.length === 0) return { output: "No tasks." };
1788
- const statusIcon = { pending: "\u25CB", in_progress: "\u25D1", completed: "\u25CF" };
1788
+ const statusIcon = { pending: "[ ]", in_progress: "[~]", completed: "[x]" };
1789
1789
  const lines = tasks.map(
1790
1790
  (t) => `${statusIcon[t.status]} #${t.id} [${t.status}] ${t.subject}`
1791
1791
  );
@@ -1926,15 +1926,219 @@ function App({ model, systemPromptOverride, children }) {
1926
1926
  }
1927
1927
 
1928
1928
  // src/repl.tsx
1929
- import { useState as useState2, useCallback as useCallback2, useEffect, useRef } from "react";
1930
- import { Box as Box6, Text as Text6, useApp, useInput as useInput2 } from "ink";
1929
+ import { useState as useState3, useCallback as useCallback2, useEffect as useEffect2, useRef } from "react";
1930
+ import { Box as Box7, Text as Text7, useApp, useInput as useInput2 } from "ink";
1931
1931
  import Spinner2 from "ink-spinner";
1932
1932
  import { nanoid as nanoid6 } from "nanoid";
1933
1933
 
1934
1934
  // src/components/Banner.tsx
1935
1935
  init_theme();
1936
+ import { Box as Box2, Text as Text2 } from "ink";
1937
+
1938
+ // src/components/Fox.tsx
1939
+ init_theme();
1940
+ import { useState, useEffect } from "react";
1936
1941
  import { Box, Text } from "ink";
1937
1942
  import { jsx as jsx2, jsxs } from "react/jsx-runtime";
1943
+ var IDLE_FRAMES = [
1944
+ [
1945
+ " /\\_/\\ ",
1946
+ " ( o.o ) ",
1947
+ " > ^ < ",
1948
+ " /| |\\ ",
1949
+ "(_| |_)",
1950
+ " ~ "
1951
+ ],
1952
+ [
1953
+ " /\\_/\\ ",
1954
+ " ( o.o ) ",
1955
+ " > ^ < ",
1956
+ " /| |\\ ",
1957
+ "(_| |_)",
1958
+ " ~ "
1959
+ ],
1960
+ [
1961
+ " /\\_/\\ ",
1962
+ " ( o.o ) ",
1963
+ " > ^ < ",
1964
+ " /| |\\ ",
1965
+ "(_| |_)",
1966
+ " ~ "
1967
+ ],
1968
+ [
1969
+ " /\\_/\\ ",
1970
+ " ( o.o ) ",
1971
+ " > ^ < ",
1972
+ " /| |\\ ",
1973
+ "(_| |_)",
1974
+ " ~ "
1975
+ ]
1976
+ ];
1977
+ var THINKING_FRAMES = [
1978
+ [
1979
+ " /\\_/\\ ",
1980
+ " ( o.o ) ",
1981
+ " > ^ < ",
1982
+ " | | ",
1983
+ " |___| ",
1984
+ " . . "
1985
+ ],
1986
+ [
1987
+ " /\\_/\\ ",
1988
+ " ( o.- ) ",
1989
+ " > ^ < ",
1990
+ " | | ",
1991
+ " |___| ",
1992
+ " . . . "
1993
+ ],
1994
+ [
1995
+ " /\\_/\\ ",
1996
+ " ( -.o ) ",
1997
+ " > ^ < ",
1998
+ " | | ",
1999
+ " |___| ",
2000
+ " . . . . "
2001
+ ],
2002
+ [
2003
+ " /\\_/\\ ",
2004
+ " ( o.o ) ",
2005
+ " > ^ < ",
2006
+ " | | ",
2007
+ " |___| ",
2008
+ " . . . "
2009
+ ]
2010
+ ];
2011
+ var WORKING_FRAMES = [
2012
+ [
2013
+ " /\\_/\\ ",
2014
+ " ( >.< ) ",
2015
+ " > ^ < ",
2016
+ " /| |\\ ",
2017
+ "(_| |_)",
2018
+ " ~/ "
2019
+ ],
2020
+ [
2021
+ " /\\_/\\ ",
2022
+ " ( >.< ) ",
2023
+ " > ^ < ",
2024
+ " /| |\\ ",
2025
+ "(_| |_)",
2026
+ " /~ "
2027
+ ]
2028
+ ];
2029
+ var SUCCESS_FRAMES = [
2030
+ [
2031
+ " /\\_/\\ ",
2032
+ " ( ^.^ ) ",
2033
+ " > w < ",
2034
+ " /| |\\ ",
2035
+ "(_| |_)",
2036
+ " \\~/ "
2037
+ ],
2038
+ [
2039
+ " /\\_/\\ ",
2040
+ " ( ^.^ ) ",
2041
+ " > w < ",
2042
+ " /| |\\ ",
2043
+ " (_|_|_) ",
2044
+ " \\~/ "
2045
+ ]
2046
+ ];
2047
+ var ERROR_FRAMES = [
2048
+ [
2049
+ " /\\_/\\ ",
2050
+ " ( ;.; ) ",
2051
+ " > n < ",
2052
+ " | | ",
2053
+ " |___| ",
2054
+ " . "
2055
+ ]
2056
+ ];
2057
+ var GREETING_FRAMES = [
2058
+ [
2059
+ " /\\_/\\ ",
2060
+ " ( ^.^ )/",
2061
+ " > w < ",
2062
+ " /| | ",
2063
+ "(_| |) ",
2064
+ " \\~/ "
2065
+ ],
2066
+ [
2067
+ " /\\_/\\ ",
2068
+ " ( ^.^ ) ",
2069
+ " > w <\\ ",
2070
+ " /| | ",
2071
+ "(_| |) ",
2072
+ " \\~/ "
2073
+ ]
2074
+ ];
2075
+ var FRAME_SETS = {
2076
+ idle: IDLE_FRAMES,
2077
+ thinking: THINKING_FRAMES,
2078
+ working: WORKING_FRAMES,
2079
+ success: SUCCESS_FRAMES,
2080
+ error: ERROR_FRAMES,
2081
+ greeting: GREETING_FRAMES
2082
+ };
2083
+ var FRAME_SPEEDS = {
2084
+ idle: 600,
2085
+ thinking: 400,
2086
+ working: 250,
2087
+ success: 500,
2088
+ error: 1e3,
2089
+ greeting: 400
2090
+ };
2091
+ var MOOD_COLORS = {
2092
+ idle: theme.cyan ?? "#5eead4",
2093
+ thinking: theme.purple ?? "#a78bfa",
2094
+ working: theme.yellow ?? "#fbbf24",
2095
+ success: theme.green ?? "#4ade80",
2096
+ error: theme.pink ?? "#f472b6",
2097
+ greeting: theme.cyan ?? "#5eead4"
2098
+ };
2099
+ var ACCENT_COLORS = {
2100
+ idle: theme.text ?? "#e2e8f0",
2101
+ thinking: theme.cyan ?? "#5eead4",
2102
+ working: theme.cyan ?? "#5eead4",
2103
+ success: theme.green ?? "#4ade80",
2104
+ error: theme.pink ?? "#f472b6",
2105
+ greeting: theme.green ?? "#4ade80"
2106
+ };
2107
+ function Fox({ mood = "idle" }) {
2108
+ const [frameIdx, setFrameIdx] = useState(0);
2109
+ const frames = FRAME_SETS[mood];
2110
+ const speed = FRAME_SPEEDS[mood];
2111
+ useEffect(() => {
2112
+ setFrameIdx(0);
2113
+ const interval = setInterval(() => {
2114
+ setFrameIdx((prev) => (prev + 1) % frames.length);
2115
+ }, speed);
2116
+ return () => clearInterval(interval);
2117
+ }, [mood, frames.length, speed]);
2118
+ const frame = frames[frameIdx] ?? frames[0];
2119
+ const bodyColor = MOOD_COLORS[mood];
2120
+ const accentColor = ACCENT_COLORS[mood];
2121
+ return /* @__PURE__ */ jsx2(Box, { flexDirection: "column", children: frame.map((line, i) => /* @__PURE__ */ jsx2(Text, { color: i <= 1 ? accentColor : bodyColor, children: line }, i)) });
2122
+ }
2123
+ function FoxBubble({ text }) {
2124
+ if (!text) return null;
2125
+ const maxWidth = 30;
2126
+ const display = text.length > maxWidth ? text.slice(0, maxWidth - 3) + "..." : text;
2127
+ const padding = display.length;
2128
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginLeft: 1, children: [
2129
+ /* @__PURE__ */ jsx2(Text, { color: theme.dim ?? "#7e8ea6", children: "." + "-".repeat(padding + 2) + "." }),
2130
+ /* @__PURE__ */ jsxs(Text, { color: theme.dim ?? "#7e8ea6", children: [
2131
+ "| ",
2132
+ /* @__PURE__ */ jsx2(Text, { color: theme.text ?? "#e2e8f0", children: display }),
2133
+ " |"
2134
+ ] }),
2135
+ /* @__PURE__ */ jsx2(Text, { color: theme.dim ?? "#7e8ea6", children: "'" + "-".repeat(padding + 2) + "'" }),
2136
+ /* @__PURE__ */ jsx2(Text, { color: theme.dim ?? "#7e8ea6", children: "/" })
2137
+ ] });
2138
+ }
2139
+
2140
+ // src/components/Banner.tsx
2141
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
1938
2142
  var LOGO_LINES = [
1939
2143
  " \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 ",
1940
2144
  " \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557 \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557 \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2554\u255D \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557 \u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557",
@@ -1943,69 +2147,71 @@ var LOGO_LINES = [
1943
2147
  " \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2557 \u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D \u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D",
1944
2148
  " \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D "
1945
2149
  ];
1946
- var SUBTITLE = " \u2584\u2580 C O D E \u2580\u2584";
2150
+ var SUBTITLE = " -- C O D E --";
1947
2151
  var GRADIENT = [
1948
2152
  "#5eead4",
1949
- // cyan
1950
2153
  "#6ee0c8",
1951
- // cyan-light
1952
2154
  "#82c8d0",
1953
- // cyan-blue
1954
2155
  "#96b0d8",
1955
- // blue-ish
1956
2156
  "#a78bfa",
1957
- // purple
1958
2157
  "#c47ee8",
1959
- // purple-pink
1960
2158
  "#f472b6"
1961
- // pink
1962
2159
  ];
1963
2160
  function lineColor(index) {
1964
2161
  const t = index / (LOGO_LINES.length - 1);
1965
- const gradientIdx = Math.round(t * (GRADIENT.length - 1));
1966
- return GRADIENT[gradientIdx];
1967
- }
1968
- function gradientDivider(width) {
1969
- const chars = [];
1970
- for (let i = 0; i < width; i++) {
1971
- const t = i / (width - 1);
1972
- const gradientIdx = Math.round(t * (GRADIENT.length - 1));
1973
- chars.push({ char: "\u2501", color: GRADIENT[gradientIdx] });
1974
- }
1975
- return chars;
1976
- }
1977
- function Banner({ model, cwd }) {
1978
- const divider = gradientDivider(60);
1979
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
1980
- LOGO_LINES.map((line, i) => /* @__PURE__ */ jsx2(Text, { color: lineColor(i), bold: true, children: line }, i)),
1981
- /* @__PURE__ */ jsx2(Text, { color: theme.purple, bold: true, children: SUBTITLE }),
1982
- /* @__PURE__ */ jsx2(Text, { children: " " }),
1983
- /* @__PURE__ */ jsxs(Text, { children: [
2162
+ return GRADIENT[Math.round(t * (GRADIENT.length - 1))];
2163
+ }
2164
+ function gradientBar(width) {
2165
+ return Array.from({ length: width }, (_, i) => ({
2166
+ char: "\u2501",
2167
+ color: GRADIENT[Math.round(i / (width - 1) * (GRADIENT.length - 1))]
2168
+ }));
2169
+ }
2170
+ function Banner({ model, cwd, providerName, providerOnline }) {
2171
+ const bar = gradientBar(60);
2172
+ const statusTag = providerOnline ? "[connected]" : "[offline]";
2173
+ const statusColor = providerOnline ? theme.green ?? "#4ade80" : theme.pink ?? "#f472b6";
2174
+ return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", marginBottom: 1, children: [
2175
+ /* @__PURE__ */ jsxs2(Box2, { children: [
2176
+ /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
2177
+ LOGO_LINES.map((line, i) => /* @__PURE__ */ jsx3(Text2, { color: lineColor(i), bold: true, children: line }, i)),
2178
+ /* @__PURE__ */ jsx3(Text2, { color: theme.purple ?? "#a78bfa", bold: true, children: SUBTITLE })
2179
+ ] }),
2180
+ /* @__PURE__ */ jsxs2(Box2, { marginLeft: 2, flexDirection: "row", alignItems: "flex-end", children: [
2181
+ /* @__PURE__ */ jsx3(Fox, { mood: "greeting" }),
2182
+ /* @__PURE__ */ jsx3(FoxBubble, { text: "Ready to work." })
2183
+ ] })
2184
+ ] }),
2185
+ /* @__PURE__ */ jsx3(Text2, { children: " " }),
2186
+ /* @__PURE__ */ jsxs2(Text2, { children: [
1984
2187
  " ",
1985
- divider.map((d, i) => /* @__PURE__ */ jsx2(Text, { color: d.color, children: d.char }, i))
2188
+ bar.map((d, i) => /* @__PURE__ */ jsx3(Text2, { color: d.color, children: d.char }, i))
2189
+ ] }),
2190
+ /* @__PURE__ */ jsxs2(Box2, { marginTop: 1, marginLeft: 2, children: [
2191
+ /* @__PURE__ */ jsx3(Text2, { color: theme.dim ?? "#7e8ea6", children: "model " }),
2192
+ /* @__PURE__ */ jsx3(Text2, { color: theme.cyan ?? "#5eead4", bold: true, children: model })
1986
2193
  ] }),
1987
- /* @__PURE__ */ jsxs(Box, { marginTop: 1, marginLeft: 2, children: [
1988
- /* @__PURE__ */ jsx2(Text, { color: theme.dim, children: "\u26A1 " }),
1989
- /* @__PURE__ */ jsx2(Text, { color: theme.cyan, bold: true, children: model }),
1990
- /* @__PURE__ */ jsx2(Text, { color: theme.dim, children: " \u2502 " }),
1991
- /* @__PURE__ */ jsx2(Text, { color: theme.text, children: cwd })
2194
+ /* @__PURE__ */ jsxs2(Box2, { marginLeft: 2, children: [
2195
+ /* @__PURE__ */ jsx3(Text2, { color: theme.dim ?? "#7e8ea6", children: "via " }),
2196
+ /* @__PURE__ */ jsx3(Text2, { color: theme.text ?? "#e2e8f0", children: providerName }),
2197
+ /* @__PURE__ */ jsx3(Text2, { color: theme.dim ?? "#7e8ea6", children: " " }),
2198
+ /* @__PURE__ */ jsx3(Text2, { color: statusColor, children: statusTag })
1992
2199
  ] }),
1993
- /* @__PURE__ */ jsxs(Box, { marginLeft: 2, children: [
1994
- /* @__PURE__ */ jsx2(Text, { color: theme.dim, children: " Type a message to begin. " }),
1995
- /* @__PURE__ */ jsx2(Text, { color: theme.cyanDim, children: "Ctrl+C" }),
1996
- /* @__PURE__ */ jsx2(Text, { color: theme.dim, children: " to abort or exit." })
2200
+ /* @__PURE__ */ jsxs2(Box2, { marginLeft: 2, children: [
2201
+ /* @__PURE__ */ jsx3(Text2, { color: theme.dim ?? "#7e8ea6", children: "cwd " }),
2202
+ /* @__PURE__ */ jsx3(Text2, { color: theme.text ?? "#e2e8f0", children: cwd })
1997
2203
  ] }),
1998
- /* @__PURE__ */ jsxs(Text, { children: [
2204
+ /* @__PURE__ */ jsx3(Box2, { marginTop: 1, children: /* @__PURE__ */ jsxs2(Text2, { children: [
1999
2205
  " ",
2000
- divider.map((d, i) => /* @__PURE__ */ jsx2(Text, { color: d.color, children: d.char }, i))
2001
- ] })
2206
+ bar.map((d, i) => /* @__PURE__ */ jsx3(Text2, { color: d.color, children: d.char }, i))
2207
+ ] }) })
2002
2208
  ] });
2003
2209
  }
2004
2210
 
2005
2211
  // src/components/Messages.tsx
2006
2212
  init_theme();
2007
2213
  init_format();
2008
- import { Box as Box2, Text as Text2 } from "ink";
2214
+ import { Box as Box3, Text as Text3 } from "ink";
2009
2215
 
2010
2216
  // src/utils/markdown.ts
2011
2217
  function renderMarkdown(text) {
@@ -2069,31 +2275,31 @@ function renderInline(text) {
2069
2275
  }
2070
2276
 
2071
2277
  // src/components/Messages.tsx
2072
- import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
2278
+ import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
2073
2279
  function Messages({ messages }) {
2074
- return /* @__PURE__ */ jsx3(Box2, { flexDirection: "column", children: messages.map((msg) => /* @__PURE__ */ jsx3(MessageRow, { message: msg }, msg.id)) });
2280
+ return /* @__PURE__ */ jsx4(Box3, { flexDirection: "column", children: messages.map((msg) => /* @__PURE__ */ jsx4(MessageRow, { message: msg }, msg.id)) });
2075
2281
  }
2076
2282
  function MessageRow({ message }) {
2077
2283
  switch (message.role) {
2078
2284
  case "user":
2079
- return /* @__PURE__ */ jsxs2(Box2, { marginTop: 1, marginBottom: 1, children: [
2080
- /* @__PURE__ */ jsx3(Text2, { color: theme.cyan, bold: true, children: "\u276F " }),
2081
- /* @__PURE__ */ jsx3(Text2, { bold: true, color: theme.text, children: message.content })
2285
+ return /* @__PURE__ */ jsxs3(Box3, { marginTop: 1, marginBottom: 1, children: [
2286
+ /* @__PURE__ */ jsx4(Text3, { color: theme.cyan, bold: true, children: "\u276F " }),
2287
+ /* @__PURE__ */ jsx4(Text3, { bold: true, color: theme.text, children: message.content })
2082
2288
  ] });
2083
2289
  case "assistant": {
2084
2290
  if (!message.content && message.toolCalls) return null;
2085
2291
  if (!message.content) return null;
2086
2292
  const rendered = renderMarkdown(message.content);
2087
- return /* @__PURE__ */ jsx3(Box2, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsxs2(Box2, { children: [
2088
- /* @__PURE__ */ jsx3(Text2, { color: theme.cyan, children: "\u23BF " }),
2089
- /* @__PURE__ */ jsx3(Text2, { wrap: "wrap", children: rendered })
2293
+ return /* @__PURE__ */ jsx4(Box3, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsxs3(Box3, { children: [
2294
+ /* @__PURE__ */ jsx4(Text3, { color: theme.cyan, children: "\u23BF " }),
2295
+ /* @__PURE__ */ jsx4(Text3, { wrap: "wrap", children: rendered })
2090
2296
  ] }) });
2091
2297
  }
2092
2298
  case "tool": {
2093
2299
  const lines = message.content.split("\n");
2094
2300
  const preview = lines.length > 8 ? lines.slice(0, 8).join("\n") + `
2095
2301
  ... (${lines.length - 8} more lines)` : message.content;
2096
- return /* @__PURE__ */ jsx3(Box2, { flexDirection: "column", marginLeft: 2, marginBottom: 1, children: /* @__PURE__ */ jsxs2(Text2, { color: theme.dim, children: [
2302
+ return /* @__PURE__ */ jsx4(Box3, { flexDirection: "column", marginLeft: 2, marginBottom: 1, children: /* @__PURE__ */ jsxs3(Text3, { color: theme.dim, children: [
2097
2303
  "\u23BF ",
2098
2304
  truncate(preview, 1200)
2099
2305
  ] }) });
@@ -2106,17 +2312,17 @@ function MessageRow({ message }) {
2106
2312
  // src/components/ToolCall.tsx
2107
2313
  init_theme();
2108
2314
  init_format();
2109
- import { Box as Box3, Text as Text3 } from "ink";
2315
+ import { Box as Box4, Text as Text4 } from "ink";
2110
2316
  import Spinner from "ink-spinner";
2111
- import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
2317
+ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
2112
2318
  function ActiveToolCall({ toolName, args }) {
2113
- return /* @__PURE__ */ jsxs3(Box3, { marginLeft: 2, children: [
2114
- /* @__PURE__ */ jsx4(Text3, { color: theme.cyan, children: /* @__PURE__ */ jsx4(Spinner, { type: "dots" }) }),
2115
- /* @__PURE__ */ jsxs3(Text3, { bold: true, color: theme.yellow, children: [
2319
+ return /* @__PURE__ */ jsxs4(Box4, { marginLeft: 2, children: [
2320
+ /* @__PURE__ */ jsx5(Text4, { color: theme.cyan, children: /* @__PURE__ */ jsx5(Spinner, { type: "dots" }) }),
2321
+ /* @__PURE__ */ jsxs4(Text4, { bold: true, color: theme.yellow, children: [
2116
2322
  " ",
2117
2323
  toolName
2118
2324
  ] }),
2119
- args ? /* @__PURE__ */ jsxs3(Text3, { color: theme.dim, children: [
2325
+ args ? /* @__PURE__ */ jsxs4(Text4, { color: theme.dim, children: [
2120
2326
  " ",
2121
2327
  formatToolArgs(args)
2122
2328
  ] }) : null
@@ -2128,15 +2334,15 @@ function ToolResultDisplay({ toolName, output, isError }) {
2128
2334
  const lines = output.split("\n");
2129
2335
  const preview = lines.length > 6 ? lines.slice(0, 6).join("\n") + `
2130
2336
  ... (${lines.length - 6} more lines)` : output;
2131
- return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", marginLeft: 2, marginBottom: 1, children: [
2132
- /* @__PURE__ */ jsxs3(Box3, { children: [
2133
- /* @__PURE__ */ jsxs3(Text3, { color: iconColor, children: [
2337
+ return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", marginLeft: 2, marginBottom: 1, children: [
2338
+ /* @__PURE__ */ jsxs4(Box4, { children: [
2339
+ /* @__PURE__ */ jsxs4(Text4, { color: iconColor, children: [
2134
2340
  icon,
2135
2341
  " "
2136
2342
  ] }),
2137
- /* @__PURE__ */ jsx4(Text3, { bold: true, color: theme.yellow, children: toolName })
2343
+ /* @__PURE__ */ jsx5(Text4, { bold: true, color: theme.yellow, children: toolName })
2138
2344
  ] }),
2139
- /* @__PURE__ */ jsx4(Box3, { marginLeft: 2, children: /* @__PURE__ */ jsxs3(Text3, { color: theme.dim, children: [
2345
+ /* @__PURE__ */ jsx5(Box4, { marginLeft: 2, children: /* @__PURE__ */ jsxs4(Text4, { color: theme.dim, children: [
2140
2346
  "\u23BF ",
2141
2347
  truncate(preview, 1200)
2142
2348
  ] }) })
@@ -2157,8 +2363,8 @@ function formatToolArgs(args) {
2157
2363
  // src/components/StatusLine.tsx
2158
2364
  init_theme();
2159
2365
  init_state();
2160
- import { Box as Box4, Text as Text4 } from "ink";
2161
- import { Fragment, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
2366
+ import { Box as Box5, Text as Text5 } from "ink";
2367
+ import { Fragment, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
2162
2368
  function getContextLimit(model) {
2163
2369
  const lower = model.toLowerCase();
2164
2370
  if (lower.includes("llama3.1")) return 131072;
@@ -2176,40 +2382,40 @@ function StatusLine({ model, messageCount, tokenEstimate, isStreaming }) {
2176
2382
  const pct = (usage * 100).toFixed(0);
2177
2383
  const usageColor = usage > 0.8 ? theme.pink : usage > 0.5 ? theme.yellow : theme.cyan;
2178
2384
  const activeTasks = state2.tasks.filter((t) => t.status === "in_progress").length;
2179
- return /* @__PURE__ */ jsxs4(Box4, { marginTop: 1, children: [
2180
- /* @__PURE__ */ jsxs4(Text4, { color: theme.dim, children: [
2385
+ return /* @__PURE__ */ jsxs5(Box5, { marginTop: 1, children: [
2386
+ /* @__PURE__ */ jsxs5(Text5, { color: theme.dim, children: [
2181
2387
  "\u2500".repeat(2),
2182
2388
  " "
2183
2389
  ] }),
2184
- /* @__PURE__ */ jsx5(Text4, { color: theme.cyan, bold: true, children: model.split(":")[0] }),
2185
- /* @__PURE__ */ jsx5(Text4, { color: theme.dim, children: " \u2502 " }),
2186
- /* @__PURE__ */ jsxs4(Text4, { color: theme.dim, children: [
2390
+ /* @__PURE__ */ jsx6(Text5, { color: theme.cyan, bold: true, children: model.split(":")[0] }),
2391
+ /* @__PURE__ */ jsx6(Text5, { color: theme.dim, children: " \u2502 " }),
2392
+ /* @__PURE__ */ jsxs5(Text5, { color: theme.dim, children: [
2187
2393
  messageCount,
2188
2394
  " msgs"
2189
2395
  ] }),
2190
- /* @__PURE__ */ jsx5(Text4, { color: theme.dim, children: " \u2502 " }),
2191
- /* @__PURE__ */ jsxs4(Text4, { color: usageColor, children: [
2396
+ /* @__PURE__ */ jsx6(Text5, { color: theme.dim, children: " \u2502 " }),
2397
+ /* @__PURE__ */ jsxs5(Text5, { color: usageColor, children: [
2192
2398
  "ctx ",
2193
2399
  pct,
2194
2400
  "%"
2195
2401
  ] }),
2196
- state2.planMode ? /* @__PURE__ */ jsxs4(Fragment, { children: [
2197
- /* @__PURE__ */ jsx5(Text4, { color: theme.dim, children: " \u2502 " }),
2198
- /* @__PURE__ */ jsx5(Text4, { color: theme.yellow, bold: true, children: "PLAN" })
2402
+ state2.planMode ? /* @__PURE__ */ jsxs5(Fragment, { children: [
2403
+ /* @__PURE__ */ jsx6(Text5, { color: theme.dim, children: " \u2502 " }),
2404
+ /* @__PURE__ */ jsx6(Text5, { color: theme.yellow, bold: true, children: "PLAN" })
2199
2405
  ] }) : null,
2200
- activeTasks > 0 ? /* @__PURE__ */ jsxs4(Fragment, { children: [
2201
- /* @__PURE__ */ jsx5(Text4, { color: theme.dim, children: " \u2502 " }),
2202
- /* @__PURE__ */ jsxs4(Text4, { color: theme.green, children: [
2406
+ activeTasks > 0 ? /* @__PURE__ */ jsxs5(Fragment, { children: [
2407
+ /* @__PURE__ */ jsx6(Text5, { color: theme.dim, children: " \u2502 " }),
2408
+ /* @__PURE__ */ jsxs5(Text5, { color: theme.green, children: [
2203
2409
  activeTasks,
2204
2410
  " task",
2205
2411
  activeTasks > 1 ? "s" : ""
2206
2412
  ] })
2207
2413
  ] }) : null,
2208
- isStreaming ? /* @__PURE__ */ jsxs4(Fragment, { children: [
2209
- /* @__PURE__ */ jsx5(Text4, { color: theme.dim, children: " \u2502 " }),
2210
- /* @__PURE__ */ jsx5(Text4, { color: theme.cyan, children: "streaming" })
2414
+ isStreaming ? /* @__PURE__ */ jsxs5(Fragment, { children: [
2415
+ /* @__PURE__ */ jsx6(Text5, { color: theme.dim, children: " \u2502 " }),
2416
+ /* @__PURE__ */ jsx6(Text5, { color: theme.cyan, children: "streaming" })
2211
2417
  ] }) : null,
2212
- /* @__PURE__ */ jsxs4(Text4, { color: theme.dim, children: [
2418
+ /* @__PURE__ */ jsxs5(Text5, { color: theme.dim, children: [
2213
2419
  " ",
2214
2420
  "\u2500".repeat(2)
2215
2421
  ] })
@@ -2218,8 +2424,8 @@ function StatusLine({ model, messageCount, tokenEstimate, isStreaming }) {
2218
2424
 
2219
2425
  // src/components/UserInput.tsx
2220
2426
  init_theme();
2221
- import { useState, useCallback } from "react";
2222
- import { Box as Box5, Text as Text5, useInput } from "ink";
2427
+ import { useState as useState2, useCallback } from "react";
2428
+ import { Box as Box6, Text as Text6, useInput } from "ink";
2223
2429
  import TextInput from "ink-text-input";
2224
2430
 
2225
2431
  // src/commands/help.ts
@@ -2408,7 +2614,7 @@ var contextCommand = {
2408
2614
  `\x1B[2m Model: ${context.model} (${contextLimit.toLocaleString()} ctx)\x1B[0m`
2409
2615
  ];
2410
2616
  if (usage > 0.8) {
2411
- lines.push("", "\x1B[33m \u26A0 Context is getting full. Consider /compact to free space.\x1B[0m");
2617
+ lines.push("", "\x1B[33m [!] Context is getting full. Consider /compact to free space.\x1B[0m");
2412
2618
  }
2413
2619
  return { output: lines.join("\n"), silent: true };
2414
2620
  }
@@ -2614,7 +2820,7 @@ ${truncatedDiff}`
2614
2820
  const output = await gitExec(["commit", "-m", commitMsg], context.cwd);
2615
2821
  return {
2616
2822
  output: [
2617
- `\x1B[32m\u2713\x1B[0m Committed: ${commitMsg}`,
2823
+ `\x1B[32m[ok]\x1B[0m Committed: ${commitMsg}`,
2618
2824
  "",
2619
2825
  output.trim()
2620
2826
  ].join("\n"),
@@ -2858,7 +3064,7 @@ var themeCommand = {
2858
3064
  const names = Object.keys(THEMES);
2859
3065
  const lines = names.map((name2) => {
2860
3066
  const t = THEMES[name2];
2861
- const swatch = `\x1B[38;2;${hexToRgb(t.cyan)}m\u25CF\x1B[0m\x1B[38;2;${hexToRgb(t.pink)}m\u25CF\x1B[0m\x1B[38;2;${hexToRgb(t.green)}m\u25CF\x1B[0m\x1B[38;2;${hexToRgb(t.yellow)}m\u25CF\x1B[0m\x1B[38;2;${hexToRgb(t.purple)}m\u25CF\x1B[0m`;
3067
+ const swatch = `\x1B[38;2;${hexToRgb(t.cyan)}m#\x1B[0m\x1B[38;2;${hexToRgb(t.pink)}m#\x1B[0m\x1B[38;2;${hexToRgb(t.green)}m#\x1B[0m\x1B[38;2;${hexToRgb(t.yellow)}m#\x1B[0m\x1B[38;2;${hexToRgb(t.purple)}m#\x1B[0m`;
2862
3068
  return ` ${name2.padEnd(10)} ${swatch}`;
2863
3069
  });
2864
3070
  return {
@@ -3083,7 +3289,7 @@ var providerCommand = {
3083
3289
  ""
3084
3290
  ];
3085
3291
  for (const { config, online } of results) {
3086
- const status = online ? "\x1B[32m\u25CF online\x1B[0m" : "\x1B[31m\u25CF offline\x1B[0m";
3292
+ const status = online ? "\x1B[32m[online]\x1B[0m" : "\x1B[31m[offline]\x1B[0m";
3087
3293
  const isActive = config.name === active ? " \x1B[36m\u2190 active\x1B[0m" : "";
3088
3294
  lines.push(` ${config.name.padEnd(14)} ${config.label.padEnd(14)} ${config.baseUrl.padEnd(30)} ${status}${isActive}`);
3089
3295
  }
@@ -3210,10 +3416,10 @@ function getCommandNames() {
3210
3416
  }
3211
3417
 
3212
3418
  // src/components/UserInput.tsx
3213
- import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
3419
+ import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
3214
3420
  function UserInput({ value, onChange, onSubmit, disabled, history }) {
3215
- const [historyIdx, setHistoryIdx] = useState(-1);
3216
- const [suggestion, setSuggestion] = useState("");
3421
+ const [historyIdx, setHistoryIdx] = useState2(-1);
3422
+ const [suggestion, setSuggestion] = useState2("");
3217
3423
  useInput((_input, key) => {
3218
3424
  if (disabled || !history || history.length === 0) return;
3219
3425
  if (key.upArrow) {
@@ -3259,20 +3465,20 @@ function UserInput({ value, onChange, onSubmit, disabled, history }) {
3259
3465
  const borderColor = disabled ? theme.dim : isBash ? theme.yellow : isCommand ? theme.purple : theme.cyan;
3260
3466
  const promptChar = isBash ? "!" : "\u276F";
3261
3467
  const promptColor = isBash ? theme.yellow : theme.cyan;
3262
- return /* @__PURE__ */ jsxs5(
3263
- Box5,
3468
+ return /* @__PURE__ */ jsxs6(
3469
+ Box6,
3264
3470
  {
3265
3471
  borderStyle: "round",
3266
3472
  borderColor,
3267
3473
  paddingLeft: 1,
3268
3474
  paddingRight: 1,
3269
3475
  children: [
3270
- /* @__PURE__ */ jsxs5(Text5, { color: disabled ? theme.dim : promptColor, bold: true, children: [
3476
+ /* @__PURE__ */ jsxs6(Text6, { color: disabled ? theme.dim : promptColor, bold: true, children: [
3271
3477
  promptChar,
3272
3478
  " "
3273
3479
  ] }),
3274
- disabled ? /* @__PURE__ */ jsx6(Text5, { color: theme.dim, children: "..." }) : /* @__PURE__ */ jsxs5(Fragment2, { children: [
3275
- /* @__PURE__ */ jsx6(
3480
+ disabled ? /* @__PURE__ */ jsx7(Text6, { color: theme.dim, children: "..." }) : /* @__PURE__ */ jsxs6(Fragment2, { children: [
3481
+ /* @__PURE__ */ jsx7(
3276
3482
  TextInput,
3277
3483
  {
3278
3484
  value,
@@ -3286,7 +3492,7 @@ function UserInput({ value, onChange, onSubmit, disabled, history }) {
3286
3492
  }
3287
3493
  }
3288
3494
  ),
3289
- suggestion ? /* @__PURE__ */ jsx6(Text5, { color: theme.dim, children: suggestion }) : null
3495
+ suggestion ? /* @__PURE__ */ jsx7(Text6, { color: theme.dim, children: suggestion }) : null
3290
3496
  ] })
3291
3497
  ]
3292
3498
  }
@@ -3294,13 +3500,14 @@ function UserInput({ value, onChange, onSubmit, disabled, history }) {
3294
3500
  }
3295
3501
 
3296
3502
  // src/repl.tsx
3503
+ init_providers();
3297
3504
  init_query();
3298
3505
  init_system_prompt();
3299
3506
  init_providers();
3300
3507
  init_tools();
3301
3508
  init_bash();
3302
3509
  init_theme();
3303
- import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
3510
+ import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
3304
3511
  function getContextLimit3(model) {
3305
3512
  const lower = model.toLowerCase();
3306
3513
  if (lower.includes("llama3.1")) return 131072;
@@ -3314,29 +3521,34 @@ function getContextLimit3(model) {
3314
3521
  function REPL({ initialPrompt }) {
3315
3522
  const { model: initialModel, systemPromptOverride } = useDarkfooContext();
3316
3523
  const { exit } = useApp();
3317
- const [model, setModel] = useState2(initialModel);
3318
- const [messages, setMessages] = useState2([]);
3319
- const [inputValue, setInputValue] = useState2("");
3320
- const [isStreaming, setIsStreaming] = useState2(false);
3321
- const [streamingText, setStreamingText] = useState2("");
3322
- const [activeTool, setActiveTool] = useState2(null);
3323
- const [toolResults, setToolResults] = useState2([]);
3324
- const [commandOutput, setCommandOutput] = useState2(null);
3325
- const [inputHistory, setInputHistory] = useState2([]);
3326
- const [tokenCounts, setTokenCounts] = useState2({ input: 0, output: 0 });
3327
- const [systemPrompt, setSystemPrompt] = useState2("");
3524
+ const [model, setModel] = useState3(initialModel);
3525
+ const [messages, setMessages] = useState3([]);
3526
+ const [inputValue, setInputValue] = useState3("");
3527
+ const [isStreaming, setIsStreaming] = useState3(false);
3528
+ const [streamingText, setStreamingText] = useState3("");
3529
+ const [activeTool, setActiveTool] = useState3(null);
3530
+ const [toolResults, setToolResults] = useState3([]);
3531
+ const [commandOutput, setCommandOutput] = useState3(null);
3532
+ const [inputHistory, setInputHistory] = useState3([]);
3533
+ const [tokenCounts, setTokenCounts] = useState3({ input: 0, output: 0 });
3534
+ const [systemPrompt, setSystemPrompt] = useState3("");
3535
+ const [foxMood, setFoxMood] = useState3("idle");
3536
+ const [providerOnline, setProviderOnline] = useState3(true);
3328
3537
  const abortRef = useRef(null);
3329
3538
  const hasRun = useRef(false);
3330
3539
  const sessionId = useRef(createSessionId());
3331
3540
  const tools = getTools();
3332
3541
  const cwd = process.cwd();
3333
- useEffect(() => {
3542
+ useEffect2(() => {
3334
3543
  if (systemPromptOverride) {
3335
3544
  setSystemPrompt(systemPromptOverride);
3336
3545
  } else {
3337
3546
  buildSystemPrompt(tools, cwd).then(setSystemPrompt);
3338
3547
  }
3339
3548
  }, []);
3549
+ useEffect2(() => {
3550
+ getProvider().healthCheck().then((ok) => setProviderOnline(ok)).catch(() => setProviderOnline(false));
3551
+ }, [model]);
3340
3552
  const commandContext = {
3341
3553
  messages,
3342
3554
  model,
@@ -3365,6 +3577,7 @@ function REPL({ initialPrompt }) {
3365
3577
  setStreamingText("");
3366
3578
  setToolResults([]);
3367
3579
  setCommandOutput(null);
3580
+ setFoxMood("thinking");
3368
3581
  const controller = new AbortController();
3369
3582
  abortRef.current = controller;
3370
3583
  const allMessages = [...messages, userMsg];
@@ -3384,12 +3597,15 @@ function REPL({ initialPrompt }) {
3384
3597
  switch (event.type) {
3385
3598
  case "text_delta":
3386
3599
  setStreamingText((prev) => prev + event.text);
3600
+ setFoxMood("idle");
3387
3601
  break;
3388
3602
  case "tool_call":
3389
3603
  setActiveTool({ name: event.toolCall.function.name, args: event.toolCall.function.arguments });
3604
+ setFoxMood("working");
3390
3605
  break;
3391
3606
  case "tool_result":
3392
3607
  setActiveTool(null);
3608
+ setFoxMood(event.isError ? "error" : "working");
3393
3609
  setToolResults((prev) => [
3394
3610
  ...prev,
3395
3611
  { id: nanoid6(), toolName: event.toolName, output: event.output, isError: event.isError }
@@ -3409,6 +3625,7 @@ function REPL({ initialPrompt }) {
3409
3625
  setStreamingText("");
3410
3626
  break;
3411
3627
  case "error":
3628
+ setFoxMood("error");
3412
3629
  setMessages((prev) => [
3413
3630
  ...prev,
3414
3631
  { id: nanoid6(), role: "assistant", content: `Error: ${event.error}`, timestamp: Date.now() }
@@ -3429,6 +3646,8 @@ function REPL({ initialPrompt }) {
3429
3646
  setStreamingText("");
3430
3647
  setActiveTool(null);
3431
3648
  setToolResults([]);
3649
+ setFoxMood((prev) => prev === "error" ? "error" : "success");
3650
+ setTimeout(() => setFoxMood("idle"), 2e3);
3432
3651
  abortRef.current = null;
3433
3652
  }
3434
3653
  },
@@ -3484,14 +3703,14 @@ function REPL({ initialPrompt }) {
3484
3703
  },
3485
3704
  [addToHistory, commandContext, cwd, runQuery]
3486
3705
  );
3487
- useEffect(() => {
3706
+ useEffect2(() => {
3488
3707
  if (initialPrompt && !hasRun.current) {
3489
3708
  hasRun.current = true;
3490
3709
  runQuery(initialPrompt);
3491
3710
  }
3492
3711
  }, [initialPrompt, runQuery]);
3493
3712
  const autoCompactRef = useRef(false);
3494
- useEffect(() => {
3713
+ useEffect2(() => {
3495
3714
  if (isStreaming || autoCompactRef.current || messages.length < 6) return;
3496
3715
  const totalChars = messages.reduce((sum, m) => sum + m.content.length, 0);
3497
3716
  const estTokens = Math.ceil(totalChars / 4) + 2e3;
@@ -3499,7 +3718,7 @@ function REPL({ initialPrompt }) {
3499
3718
  const usage = estTokens / limit;
3500
3719
  if (usage > 0.85) {
3501
3720
  autoCompactRef.current = true;
3502
- setCommandOutput("\x1B[33m\u26A0 Context 85%+ full \u2014 auto-compacting...\x1B[0m");
3721
+ setCommandOutput("\x1B[33m[!] Context 85%+ full \u2014 auto-compacting...\x1B[0m");
3503
3722
  const transcript = messages.filter((m) => m.role === "user" || m.role === "assistant" && m.content).map((m) => `${m.role}: ${m.content}`).join("\n\n");
3504
3723
  getProvider().chat({
3505
3724
  model,
@@ -3517,10 +3736,10 @@ ${result.content}
3517
3736
  };
3518
3737
  setMessages([summaryMsg]);
3519
3738
  setTokenCounts({ input: Math.ceil(result.content.length / 4), output: 0 });
3520
- setCommandOutput("\x1B[32m\u2713 Auto-compacted conversation.\x1B[0m");
3739
+ setCommandOutput("\x1B[32m[ok] Auto-compacted conversation.\x1B[0m");
3521
3740
  autoCompactRef.current = false;
3522
3741
  }).catch(() => {
3523
- setCommandOutput("\x1B[31m\u2717 Auto-compact failed.\x1B[0m");
3742
+ setCommandOutput("\x1B[31m[err] Auto-compact failed.\x1B[0m");
3524
3743
  autoCompactRef.current = false;
3525
3744
  });
3526
3745
  }
@@ -3534,35 +3753,38 @@ ${result.content}
3534
3753
  }
3535
3754
  }
3536
3755
  });
3537
- return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", padding: 1, children: [
3538
- /* @__PURE__ */ jsx7(Banner, { model, cwd }),
3539
- /* @__PURE__ */ jsx7(Messages, { messages }),
3540
- commandOutput ? /* @__PURE__ */ jsx7(Box6, { marginBottom: 1, marginLeft: 2, flexDirection: "column", children: /* @__PURE__ */ jsx7(Text6, { children: commandOutput }) }) : null,
3541
- toolResults.map((tr) => /* @__PURE__ */ jsx7(ToolResultDisplay, { toolName: tr.toolName, output: tr.output, isError: tr.isError }, tr.id)),
3542
- activeTool ? /* @__PURE__ */ jsx7(ActiveToolCall, { toolName: activeTool.name, args: activeTool.args }) : null,
3543
- isStreaming && streamingText ? /* @__PURE__ */ jsxs6(Box6, { marginBottom: 1, children: [
3544
- /* @__PURE__ */ jsx7(Text6, { color: theme.cyan, children: "\u23BF " }),
3545
- /* @__PURE__ */ jsx7(Text6, { color: theme.text, wrap: "wrap", children: streamingText }),
3546
- /* @__PURE__ */ jsxs6(Text6, { color: theme.cyan, children: [
3756
+ return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", padding: 1, children: [
3757
+ /* @__PURE__ */ jsx8(Banner, { model, cwd, providerName: getActiveProviderName(), providerOnline }),
3758
+ /* @__PURE__ */ jsx8(Messages, { messages }),
3759
+ commandOutput ? /* @__PURE__ */ jsx8(Box7, { marginBottom: 1, marginLeft: 2, flexDirection: "column", children: /* @__PURE__ */ jsx8(Text7, { children: commandOutput }) }) : null,
3760
+ toolResults.map((tr) => /* @__PURE__ */ jsx8(ToolResultDisplay, { toolName: tr.toolName, output: tr.output, isError: tr.isError }, tr.id)),
3761
+ activeTool ? /* @__PURE__ */ jsx8(ActiveToolCall, { toolName: activeTool.name, args: activeTool.args }) : null,
3762
+ isStreaming && streamingText ? /* @__PURE__ */ jsxs7(Box7, { marginBottom: 1, children: [
3763
+ /* @__PURE__ */ jsx8(Text7, { color: theme.cyan, children: "\u23BF " }),
3764
+ /* @__PURE__ */ jsx8(Text7, { color: theme.text, wrap: "wrap", children: streamingText }),
3765
+ /* @__PURE__ */ jsxs7(Text7, { color: theme.cyan, children: [
3547
3766
  " ",
3548
- /* @__PURE__ */ jsx7(Spinner2, { type: "dots" })
3767
+ /* @__PURE__ */ jsx8(Spinner2, { type: "dots" })
3549
3768
  ] })
3550
3769
  ] }) : null,
3551
- isStreaming && !streamingText && !activeTool ? /* @__PURE__ */ jsxs6(Box6, { marginLeft: 2, children: [
3552
- /* @__PURE__ */ jsx7(Text6, { color: theme.cyan, children: /* @__PURE__ */ jsx7(Spinner2, { type: "dots" }) }),
3553
- /* @__PURE__ */ jsx7(Text6, { color: theme.dim, children: " Thinking..." })
3770
+ isStreaming && !streamingText && !activeTool ? /* @__PURE__ */ jsxs7(Box7, { marginLeft: 2, children: [
3771
+ /* @__PURE__ */ jsx8(Text7, { color: theme.cyan, children: /* @__PURE__ */ jsx8(Spinner2, { type: "dots" }) }),
3772
+ /* @__PURE__ */ jsx8(Text7, { color: theme.dim, children: " Thinking..." })
3554
3773
  ] }) : null,
3555
- /* @__PURE__ */ jsx7(
3556
- UserInput,
3557
- {
3558
- value: inputValue,
3559
- onChange: setInputValue,
3560
- onSubmit: handleSubmit,
3561
- disabled: isStreaming,
3562
- history: inputHistory
3563
- }
3564
- ),
3565
- /* @__PURE__ */ jsx7(
3774
+ /* @__PURE__ */ jsxs7(Box7, { children: [
3775
+ /* @__PURE__ */ jsx8(Fox, { mood: foxMood }),
3776
+ /* @__PURE__ */ jsx8(Box7, { flexDirection: "column", flexGrow: 1, marginLeft: 1, children: /* @__PURE__ */ jsx8(
3777
+ UserInput,
3778
+ {
3779
+ value: inputValue,
3780
+ onChange: setInputValue,
3781
+ onSubmit: handleSubmit,
3782
+ disabled: isStreaming,
3783
+ history: inputHistory
3784
+ }
3785
+ ) })
3786
+ ] }),
3787
+ /* @__PURE__ */ jsx8(
3566
3788
  StatusLine,
3567
3789
  {
3568
3790
  model,
@@ -3576,9 +3798,9 @@ ${result.content}
3576
3798
 
3577
3799
  // src/main.tsx
3578
3800
  init_providers();
3579
- import { jsx as jsx8 } from "react/jsx-runtime";
3801
+ import { jsx as jsx9 } from "react/jsx-runtime";
3580
3802
  var program = new Command();
3581
- program.name("darkfoo").description("Darkfoo Code \u2014 local AI coding assistant powered by local LLM providers").version("0.1.4").option("-m, --model <model>", "Model to use", "llama3.1:8b").option("-p, --prompt <prompt>", "Run a single prompt (non-interactive)").option("--provider <name>", "LLM provider backend (ollama, llama-cpp, vllm, tgi, etc.)").option("--system-prompt <prompt>", "Override the system prompt").action(async (options) => {
3803
+ program.name("darkfoo").description("Darkfoo Code \u2014 local AI coding assistant powered by local LLM providers").version("0.2.0").option("-m, --model <model>", "Model to use", "llama3.1:8b").option("-p, --prompt <prompt>", "Run a single prompt (non-interactive)").option("--provider <name>", "LLM provider backend (ollama, llama-cpp, vllm, tgi, etc.)").option("--system-prompt <prompt>", "Override the system prompt").action(async (options) => {
3582
3804
  const { model, prompt, provider, systemPrompt } = options;
3583
3805
  await loadProviderSettings();
3584
3806
  if (provider) {
@@ -3638,7 +3860,7 @@ Error: ${event.error}
3638
3860
  process.exit(0);
3639
3861
  }
3640
3862
  const { waitUntilExit } = render(
3641
- /* @__PURE__ */ jsx8(App, { model, systemPromptOverride: systemPrompt, children: /* @__PURE__ */ jsx8(REPL, {}) })
3863
+ /* @__PURE__ */ jsx9(App, { model, systemPromptOverride: systemPrompt, children: /* @__PURE__ */ jsx9(REPL, {}) })
3642
3864
  );
3643
3865
  await waitUntilExit();
3644
3866
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "darkfoo-code",
3
- "version": "0.1.4",
3
+ "version": "0.2.0",
4
4
  "description": "Darkfoo Code — local AI coding assistant powered by Ollama, vLLM, llama.cpp, and other LLM providers",
5
5
  "type": "module",
6
6
  "license": "MIT",