dskcode 0.1.15 → 0.1.16

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
@@ -490,7 +490,7 @@ async function promptForApiKey() {
490
490
  // src/cli/skill-import.ts
491
491
  import { createInterface as createInterface2 } from "readline";
492
492
  import { existsSync as existsSync2, statSync, lstatSync } from "fs";
493
- import { mkdir as mkdir2, readdir, cp, access, realpath } from "fs/promises";
493
+ import { mkdir as mkdir2, readdir, cp, access, realpath, readFile as readFile2 } from "fs/promises";
494
494
  import { join as join2 } from "path";
495
495
  import chalk3 from "chalk";
496
496
  function getClaudeSkillsDir() {
@@ -687,10 +687,94 @@ async function promptImportClaudeSkills(cwd) {
687
687
  console.log(chalk3.dim(" \u4F60\u53EF\u4EE5\u7A0D\u540E\u624B\u52A8\u590D\u5236 ~/.claude/skills \u5230 ~/.dskcode/skills\n"));
688
688
  }
689
689
  }
690
+ async function listDskcodeSkills() {
691
+ const dskcodeDir = getDskcodeSkillsDir();
692
+ if (!existsSync2(dskcodeDir)) return [];
693
+ let entries;
694
+ try {
695
+ entries = await readdir(dskcodeDir);
696
+ } catch {
697
+ return [];
698
+ }
699
+ const skills = [];
700
+ for (const name of entries) {
701
+ const full = join2(dskcodeDir, name);
702
+ if (statSync(full).isDirectory() && await isSkillDir(full)) {
703
+ skills.push(name);
704
+ }
705
+ }
706
+ return skills;
707
+ }
708
+ async function listProjectSkills(cwd) {
709
+ const skillDir = getProjectSkillDir(cwd);
710
+ if (!existsSync2(skillDir)) return [];
711
+ let entries;
712
+ try {
713
+ entries = await readdir(skillDir);
714
+ } catch {
715
+ return [];
716
+ }
717
+ const skills = [];
718
+ for (const name of entries) {
719
+ const full = join2(skillDir, name);
720
+ if (statSync(full).isDirectory() && await isSkillDir(full)) {
721
+ skills.push(name);
722
+ }
723
+ }
724
+ return skills;
725
+ }
726
+ async function readSkillInfo(skillDir) {
727
+ try {
728
+ const content = await readFile2(join2(skillDir, "SKILL.md"), "utf-8");
729
+ const match = content.match(/^---\n([\s\S]*?)\n---/);
730
+ if (!match) return null;
731
+ const frontMatter = match[1];
732
+ const nameMatch = frontMatter.match(/^name:\s*(.+)$/m);
733
+ const descMatch = frontMatter.match(/^description:\s*(.+)$/m);
734
+ return {
735
+ name: nameMatch?.[1]?.trim() ?? "",
736
+ description: descMatch?.[1]?.trim() ?? ""
737
+ };
738
+ } catch {
739
+ return null;
740
+ }
741
+ }
742
+ async function getAllSkills(cwd) {
743
+ const [globalNames, localNames] = await Promise.all([
744
+ listDskcodeSkills(),
745
+ listProjectSkills(cwd)
746
+ ]);
747
+ const seen = /* @__PURE__ */ new Set();
748
+ const allNames = [];
749
+ for (const name of [...localNames, ...globalNames]) {
750
+ if (!seen.has(name)) {
751
+ seen.add(name);
752
+ allNames.push(name);
753
+ }
754
+ }
755
+ const dskcodeDir = getDskcodeSkillsDir();
756
+ const projectDir = getProjectSkillDir(cwd);
757
+ const results = [];
758
+ for (const name of allNames) {
759
+ const localPath = join2(projectDir, name);
760
+ let info = null;
761
+ if (existsSync2(localPath)) {
762
+ info = await readSkillInfo(localPath);
763
+ }
764
+ if (!info) {
765
+ const globalPath = join2(dskcodeDir, name);
766
+ if (existsSync2(globalPath)) {
767
+ info = await readSkillInfo(globalPath);
768
+ }
769
+ }
770
+ results.push(info ?? { name, description: "" });
771
+ }
772
+ return results;
773
+ }
690
774
 
691
775
  // src/cli/index.tsx
692
- import { readFile as readFile3 } from "fs/promises";
693
- import { join as join4 } from "path";
776
+ import { readFile as readFile4 } from "fs/promises";
777
+ import { join as join5 } from "path";
694
778
 
695
779
  // src/ui/RenderScope.tsx
696
780
  import { render } from "ink";
@@ -732,7 +816,7 @@ var LOGO_LINES = [
732
816
  ];
733
817
 
734
818
  // src/ui/ChatSession.tsx
735
- import { Box as Box5, Text as Text6, useInput, Static } from "ink";
819
+ import { Box as Box7, Text as Text8, useInput, Static } from "ink";
736
820
  import TextInput from "ink-text-input";
737
821
  import { useEffect as useEffect3, useState as useState3, useCallback as useCallback2, useRef as useRef2 } from "react";
738
822
 
@@ -768,7 +852,7 @@ function useDoubleCtrlC(onExit) {
768
852
  import { Box as Box4, Text as Text5 } from "ink";
769
853
 
770
854
  // src/provider/cost-tracker.ts
771
- import { mkdir as mkdir3, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
855
+ import { mkdir as mkdir3, readFile as readFile3, writeFile as writeFile2 } from "fs/promises";
772
856
  import { join as join3 } from "path";
773
857
  var CostTracker = class {
774
858
  #costDir;
@@ -1003,7 +1087,7 @@ var CostTracker = class {
1003
1087
  async #loadStore() {
1004
1088
  const filePath = join3(this.#costDir, "history.json");
1005
1089
  try {
1006
- const raw = await readFile2(filePath, "utf-8");
1090
+ const raw = await readFile3(filePath, "utf-8");
1007
1091
  return JSON.parse(raw);
1008
1092
  } catch {
1009
1093
  return { version: 1, daily: {} };
@@ -1196,6 +1280,50 @@ function AssistantMessage({
1196
1280
  ] });
1197
1281
  }
1198
1282
 
1283
+ // src/ui/SkillSelector.tsx
1284
+ import { Box as Box5, Text as Text6 } from "ink";
1285
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1286
+ var HIGHLIGHT_COLOR = "#00bfff";
1287
+ function SkillSelector({ skills, input, selectedIndex }) {
1288
+ const match = input.match(/(?:^|\s)\/([^/]*)$/);
1289
+ if (!match) return null;
1290
+ const query = match[1].toLowerCase().trim();
1291
+ if (skills.length === 0) return null;
1292
+ const matched = !query && input.startsWith("/") ? skills.slice(0, 3) : skills.filter((s) => s.name.toLowerCase().includes(query)).slice(0, 3);
1293
+ if (query && matched.length > 0 && matched.some((s) => s.name.toLowerCase() === query)) return null;
1294
+ if (matched.length === 0) return null;
1295
+ return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", marginLeft: 4, marginTop: 1, children: [
1296
+ /* @__PURE__ */ jsx5(Text6, { color: "#808080", dimColor: true, children: "\u652F\u6301\u7684 Skill\uFF1A" }),
1297
+ matched.map((skill, i) => /* @__PURE__ */ jsx5(Box5, { children: /* @__PURE__ */ jsxs5(Text6, { color: i === selectedIndex ? HIGHLIGHT_COLOR : "#808080", children: [
1298
+ i === selectedIndex ? " \u203A " : " ",
1299
+ skill.name
1300
+ ] }) }, skill.name)),
1301
+ /* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx5(Text6, { color: "#808080", dimColor: true, children: "\u2191\u2193 \u9009\u62E9 \xB7 Tab \u8865\u5168" }) })
1302
+ ] });
1303
+ }
1304
+
1305
+ // src/ui/FileSelector.tsx
1306
+ import { Box as Box6, Text as Text7 } from "ink";
1307
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
1308
+ var HIGHLIGHT_COLOR2 = "#00ff41";
1309
+ function FileSelector({ files, input, selectedIndex }) {
1310
+ const match = input.match(/(?:^|\s)@([^@]*)$/);
1311
+ if (!match) return null;
1312
+ const query = match[1].toLowerCase().trim();
1313
+ if (files.length === 0) return null;
1314
+ const matched = !query && input.startsWith("@") ? files.slice(0, 5) : files.filter((f) => f.toLowerCase().includes(query)).slice(0, 5);
1315
+ if (query && matched.some((f) => f.toLowerCase() === query)) return null;
1316
+ if (matched.length === 0) return null;
1317
+ return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", marginLeft: 4, marginTop: 1, children: [
1318
+ /* @__PURE__ */ jsx6(Text7, { color: "#808080", dimColor: true, children: "\u9879\u76EE\u6587\u4EF6\uFF1A" }),
1319
+ matched.map((file, i) => /* @__PURE__ */ jsx6(Box6, { children: /* @__PURE__ */ jsxs6(Text7, { color: i === selectedIndex ? HIGHLIGHT_COLOR2 : "#808080", children: [
1320
+ i === selectedIndex ? " \u203A " : " ",
1321
+ file
1322
+ ] }) }, file)),
1323
+ /* @__PURE__ */ jsx6(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx6(Text7, { color: "#808080", dimColor: true, children: "\u2191\u2193 \u9009\u62E9 \xB7 Tab \u8865\u5168" }) })
1324
+ ] });
1325
+ }
1326
+
1199
1327
  // src/provider/registry.ts
1200
1328
  var ProviderRegistry = class {
1201
1329
  #factories = /* @__PURE__ */ new Map();
@@ -1590,7 +1718,7 @@ function getGradientColors(text, phase, stops) {
1590
1718
  }
1591
1719
 
1592
1720
  // src/ui/ChatSession.tsx
1593
- import { Fragment, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1721
+ import { Fragment, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
1594
1722
  var commandRegistry = /* @__PURE__ */ new Map();
1595
1723
  function registerCommand(name, cmd) {
1596
1724
  commandRegistry.set(name, cmd);
@@ -1637,6 +1765,8 @@ function pickRandom(arr) {
1637
1765
  }
1638
1766
  function ChatSession({
1639
1767
  skillCount,
1768
+ skills = [],
1769
+ files = [],
1640
1770
  toolCount,
1641
1771
  verbose,
1642
1772
  apiKey,
@@ -1674,6 +1804,9 @@ function ChatSession({
1674
1804
  const [cmdTipIndex, setCmdTipIndex] = useState3(0);
1675
1805
  const [cmdTipGradientColors, setCmdTipGradientColors] = useState3([]);
1676
1806
  const cmdTipPhaseRef = useRef2(0);
1807
+ const [skillSelectIndex, setSkillSelectIndex] = useState3(0);
1808
+ const [fileSelectIndex, setFileSelectIndex] = useState3(0);
1809
+ const [inputKey, setInputKey] = useState3(0);
1677
1810
  const [selectingModel, setSelectingModel] = useState3(false);
1678
1811
  const [modelSelectIndex, setModelSelectIndex] = useState3(0);
1679
1812
  const modelOptions = ["deepseek-v4-flash", "deepseek-v4-pro"];
@@ -1686,6 +1819,40 @@ function ChatSession({
1686
1819
  const currentCostRef = useRef2(void 0);
1687
1820
  const currentModelRef = useRef2(void 0);
1688
1821
  const streamErrorRef = useRef2(void 0);
1822
+ useEffect3(() => {
1823
+ setSkillSelectIndex(0);
1824
+ setFileSelectIndex(0);
1825
+ }, [input]);
1826
+ const getFilteredSkills = useCallback2(
1827
+ (value) => {
1828
+ const match = value.match(/(?:^|\s)\/([^/]*)$/);
1829
+ if (!match) return [];
1830
+ const q = match[1].toLowerCase().trim();
1831
+ if (!q) {
1832
+ if (value.startsWith("/")) return skills.slice(0, 3);
1833
+ return [];
1834
+ }
1835
+ const matched = skills.filter((s) => s.name.toLowerCase().includes(q)).slice(0, 3);
1836
+ if (matched.some((s) => s.name.toLowerCase() === q)) return [];
1837
+ return matched;
1838
+ },
1839
+ [skills]
1840
+ );
1841
+ const getFilteredFiles = useCallback2(
1842
+ (value) => {
1843
+ const match = value.match(/(?:^|\s)@([^@]*)$/);
1844
+ if (!match) return [];
1845
+ const q = match[1].toLowerCase().trim();
1846
+ if (!q) {
1847
+ if (value.startsWith("@")) return files.slice(0, 5);
1848
+ return [];
1849
+ }
1850
+ const matched = files.filter((f) => f.toLowerCase().includes(q)).slice(0, 5);
1851
+ if (matched.some((f) => f.toLowerCase() === q)) return [];
1852
+ return matched;
1853
+ },
1854
+ [files]
1855
+ );
1689
1856
  const { doubleCtrlC, handleCtrlC } = useDoubleCtrlC(() => {
1690
1857
  process.exit(0);
1691
1858
  });
@@ -1720,6 +1887,50 @@ function ChatSession({
1720
1887
  }
1721
1888
  return;
1722
1889
  }
1890
+ const fileList = getFilteredFiles(input);
1891
+ const skillList = fileList.length === 0 ? getFilteredSkills(input) : [];
1892
+ if (fileList.length > 0) {
1893
+ if (key.upArrow) {
1894
+ setFileSelectIndex((prev) => (prev - 1 + fileList.length) % fileList.length);
1895
+ return;
1896
+ }
1897
+ if (key.downArrow) {
1898
+ setFileSelectIndex((prev) => (prev + 1) % fileList.length);
1899
+ return;
1900
+ }
1901
+ if (key.tab) {
1902
+ const selected = fileList[fileSelectIndex];
1903
+ if (selected) {
1904
+ const atIdx = input.lastIndexOf("@");
1905
+ if (atIdx >= 0) {
1906
+ setInput(input.slice(0, atIdx) + "@" + selected + " ");
1907
+ setInputKey((k) => k + 1);
1908
+ }
1909
+ }
1910
+ return;
1911
+ }
1912
+ }
1913
+ if (skillList.length > 0) {
1914
+ if (key.upArrow) {
1915
+ setSkillSelectIndex((prev) => (prev - 1 + skillList.length) % skillList.length);
1916
+ return;
1917
+ }
1918
+ if (key.downArrow) {
1919
+ setSkillSelectIndex((prev) => (prev + 1) % skillList.length);
1920
+ return;
1921
+ }
1922
+ if (key.tab) {
1923
+ const selected = skillList[skillSelectIndex];
1924
+ if (selected) {
1925
+ const slashIdx = input.lastIndexOf("/");
1926
+ if (slashIdx >= 0) {
1927
+ setInput(input.slice(0, slashIdx) + "/" + selected.name + " ");
1928
+ setInputKey((k) => k + 1);
1929
+ }
1930
+ }
1931
+ return;
1932
+ }
1933
+ }
1723
1934
  if (key.ctrl && _input === "c") {
1724
1935
  if (isStreaming) {
1725
1936
  abortRef.current?.abort();
@@ -1732,7 +1943,7 @@ function ChatSession({
1732
1943
  setInput(_input);
1733
1944
  }
1734
1945
  },
1735
- [selectingModel, modelSelectIndex, modelOptions, activeModel, isStreaming, handleCtrlC, input]
1946
+ [selectingModel, modelSelectIndex, modelOptions, activeModel, isStreaming, handleCtrlC, input, skills, skillSelectIndex, fileSelectIndex, getFilteredSkills, getFilteredFiles]
1736
1947
  )
1737
1948
  );
1738
1949
  useEffect3(() => {
@@ -1852,7 +2063,7 @@ function ChatSession({
1852
2063
  const handleSubmit = useCallback2(async (value) => {
1853
2064
  const trimmed = value.trim();
1854
2065
  if (!trimmed) return;
1855
- if (trimmed.startsWith("/")) {
2066
+ if (trimmed.startsWith("/") && trimmed.length > 1) {
1856
2067
  if (trimmed.toLowerCase() === "/model") {
1857
2068
  const curIdx = modelOptions.indexOf(activeModel);
1858
2069
  setModelSelectIndex(curIdx >= 0 ? curIdx : 0);
@@ -1998,7 +2209,7 @@ function ChatSession({
1998
2209
  ]);
1999
2210
  }
2000
2211
  }
2001
- }, [onLaunchGame, onLaunchStock, currentContent, currentToolCalls]);
2212
+ }, [onLaunchGame, onLaunchStock, currentContent, currentToolCalls, skills, skillSelectIndex, getFilteredSkills]);
2002
2213
  useEffect3(() => {
2003
2214
  if (!isStreaming && externalCostTracker) {
2004
2215
  setTodayCost(externalCostTracker.todayTotalCost);
@@ -2013,26 +2224,26 @@ function ChatSession({
2013
2224
  });
2014
2225
  }
2015
2226
  }, [currentUsage, streamingModel, currentCost]);
2016
- return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", paddingLeft: 1, paddingRight: 1, children: [
2017
- /* @__PURE__ */ jsxs5(Box5, { flexDirection: "row", marginBottom: 1, children: [
2018
- /* @__PURE__ */ jsx5(Box5, { flexDirection: "column", marginRight: 4, children: LOGO_LINES.map((line, i) => {
2227
+ return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", paddingLeft: 1, paddingRight: 1, children: [
2228
+ /* @__PURE__ */ jsxs7(Box7, { flexDirection: "row", marginBottom: 1, children: [
2229
+ /* @__PURE__ */ jsx7(Box7, { flexDirection: "column", marginRight: 4, children: LOGO_LINES.map((line, i) => {
2019
2230
  const colorIndex = (i + offset) % CYBER_PALETTE.length;
2020
- return /* @__PURE__ */ jsx5(Box5, { children: /* @__PURE__ */ jsx5(Text6, { bold: true, color: CYBER_PALETTE[colorIndex], children: line }) }, i);
2231
+ return /* @__PURE__ */ jsx7(Box7, { children: /* @__PURE__ */ jsx7(Text8, { bold: true, color: CYBER_PALETTE[colorIndex], children: line }) }, i);
2021
2232
  }) }),
2022
- /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", justifyContent: "center", children: [
2023
- /* @__PURE__ */ jsxs5(Text6, { color: "#00ff41", children: [
2233
+ /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", justifyContent: "center", children: [
2234
+ /* @__PURE__ */ jsxs7(Text8, { color: "#00ff41", children: [
2024
2235
  " \u2714 ",
2025
- "\u5DF2\u52A0\u8F7D ",
2236
+ "\u5DF2\u5C31\u7EEA ",
2026
2237
  skillCount,
2027
2238
  " \u4E2A Skill"
2028
2239
  ] }),
2029
- /* @__PURE__ */ jsxs5(Text6, { color: "#00ffff", children: [
2240
+ /* @__PURE__ */ jsxs7(Text8, { color: "#00ffff", children: [
2030
2241
  " \u2139 ",
2031
2242
  "\u5DF2\u5C31\u7EEA ",
2032
2243
  toolCount,
2033
2244
  " \u4E2A\u5DE5\u5177"
2034
2245
  ] }),
2035
- /* @__PURE__ */ jsxs5(Text6, { color: "#00ffff", children: [
2246
+ /* @__PURE__ */ jsxs7(Text8, { color: "#00ffff", children: [
2036
2247
  " \u{1F527} \u6A21\u578B ",
2037
2248
  SUPPORTED_MODELS[activeModel]?.displayName ?? activeModel
2038
2249
  ] }),
@@ -2040,40 +2251,40 @@ function ChatSession({
2040
2251
  const tip = cmdTips[cmdTipIndex % cmdTips.length];
2041
2252
  if (!tip) return null;
2042
2253
  const text = `${tip.name} ${tip.desc}`;
2043
- return /* @__PURE__ */ jsxs5(Text6, { children: [
2044
- /* @__PURE__ */ jsx5(Text6, { color: "#808080", children: " \u{1F4A1} " }),
2045
- cmdTipGradientColors.length > 0 ? text.split("").map((ch, i) => /* @__PURE__ */ jsx5(Text6, { color: cmdTipGradientColors[i] || void 0, children: ch }, i)) : /* @__PURE__ */ jsx5(Text6, { color: "#808080", children: text })
2254
+ return /* @__PURE__ */ jsxs7(Text8, { children: [
2255
+ /* @__PURE__ */ jsx7(Text8, { color: "#808080", children: " \u{1F4A1} " }),
2256
+ cmdTipGradientColors.length > 0 ? text.split("").map((ch, i) => /* @__PURE__ */ jsx7(Text8, { color: cmdTipGradientColors[i] || void 0, children: ch }, i)) : /* @__PURE__ */ jsx7(Text8, { color: "#808080", children: text })
2046
2257
  ] });
2047
2258
  })(),
2048
- verbose ? /* @__PURE__ */ jsx5(Text6, { color: "#ff1493", children: " \u26A1 Verbose" }) : null
2259
+ verbose ? /* @__PURE__ */ jsx7(Text8, { color: "#ff1493", children: " \u26A1 Verbose" }) : null
2049
2260
  ] }),
2050
- /* @__PURE__ */ jsxs5(Box5, { flexGrow: 1, flexDirection: "column", justifyContent: "center", alignItems: "flex-end", children: [
2051
- balanceLoading && balance === null ? /* @__PURE__ */ jsx5(Text6, { color: "yellow", children: " \u23F3 \u67E5\u8BE2\u4F59\u989D..." }) : balance !== null ? /* @__PURE__ */ jsxs5(Box5, { flexDirection: "row", children: [
2052
- /* @__PURE__ */ jsx5(Text6, { color: "yellow", children: "\u{1F4B0} " }),
2053
- /* @__PURE__ */ jsxs5(Text6, { color: "yellow", children: [
2261
+ /* @__PURE__ */ jsxs7(Box7, { flexGrow: 1, flexDirection: "column", justifyContent: "center", alignItems: "flex-end", children: [
2262
+ balanceLoading && balance === null ? /* @__PURE__ */ jsx7(Text8, { color: "yellow", children: " \u23F3 \u67E5\u8BE2\u4F59\u989D..." }) : balance !== null ? /* @__PURE__ */ jsxs7(Box7, { flexDirection: "row", children: [
2263
+ /* @__PURE__ */ jsx7(Text8, { color: "yellow", children: "\u{1F4B0} " }),
2264
+ /* @__PURE__ */ jsxs7(Text8, { color: "yellow", children: [
2054
2265
  "\u4F59\u989D \xA5",
2055
2266
  balance.toFixed(2)
2056
2267
  ] })
2057
2268
  ] }) : null,
2058
- todayCost !== null ? /* @__PURE__ */ jsxs5(Box5, { flexDirection: "row", children: [
2059
- /* @__PURE__ */ jsx5(Text6, { color: "cyan", children: "\u{1F4CA} " }),
2060
- /* @__PURE__ */ jsxs5(Text6, { color: "cyan", children: [
2269
+ todayCost !== null ? /* @__PURE__ */ jsxs7(Box7, { flexDirection: "row", children: [
2270
+ /* @__PURE__ */ jsx7(Text8, { color: "cyan", children: "\u{1F4CA} " }),
2271
+ /* @__PURE__ */ jsxs7(Text8, { color: "cyan", children: [
2061
2272
  "\u4ECA\u65E5 \xA5",
2062
2273
  todayCost.toFixed(2)
2063
2274
  ] })
2064
2275
  ] }) : null
2065
2276
  ] })
2066
2277
  ] }),
2067
- /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", marginTop: 1, children: [
2068
- /* @__PURE__ */ jsx5(Static, { items: displayMessages, children: (msg, i) => {
2278
+ /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", marginTop: 1, children: [
2279
+ /* @__PURE__ */ jsx7(Static, { items: displayMessages, children: (msg, i) => {
2069
2280
  if (msg.role === "user") {
2070
- return /* @__PURE__ */ jsxs5(Box5, { marginTop: 1, children: [
2071
- /* @__PURE__ */ jsx5(Box5, { width: 4, flexShrink: 0, children: /* @__PURE__ */ jsx5(Text6, { bold: true, color: "#00ff41", children: "\u{1F464}" }) }),
2072
- /* @__PURE__ */ jsx5(Box5, { flexGrow: 1, children: /* @__PURE__ */ jsx5(Text6, { wrap: "wrap", children: msg.content }) })
2281
+ return /* @__PURE__ */ jsxs7(Box7, { marginTop: 1, children: [
2282
+ /* @__PURE__ */ jsx7(Box7, { width: 4, flexShrink: 0, children: /* @__PURE__ */ jsx7(Text8, { bold: true, color: "#00ff41", children: "\u{1F464}" }) }),
2283
+ /* @__PURE__ */ jsx7(Box7, { flexGrow: 1, children: /* @__PURE__ */ jsx7(Text8, { wrap: "wrap", children: msg.content }) })
2073
2284
  ] }, i);
2074
2285
  }
2075
2286
  const detail = msg.assistantDetail;
2076
- return /* @__PURE__ */ jsx5(
2287
+ return /* @__PURE__ */ jsx7(
2077
2288
  AssistantMessage,
2078
2289
  {
2079
2290
  content: msg.content,
@@ -2087,7 +2298,7 @@ function ChatSession({
2087
2298
  i
2088
2299
  );
2089
2300
  } }, staticKey),
2090
- isStreaming && /* @__PURE__ */ jsx5(
2301
+ isStreaming && /* @__PURE__ */ jsx7(
2091
2302
  AssistantMessage,
2092
2303
  {
2093
2304
  content: currentContent,
@@ -2095,25 +2306,25 @@ function ChatSession({
2095
2306
  isStreaming: true
2096
2307
  }
2097
2308
  ),
2098
- isStreaming && !currentContent && currentToolCalls.length === 0 && /* @__PURE__ */ jsx5(Box5, { marginTop: 1, marginLeft: 4, children: /* @__PURE__ */ jsx5(Spinner, { type: "dots", label: "\u601D\u8003\u4E2D..." }) }),
2099
- !isStreaming && streamError && /* @__PURE__ */ jsx5(Box5, { marginTop: 1, marginLeft: 3, children: /* @__PURE__ */ jsxs5(Text6, { color: "red", children: [
2309
+ isStreaming && !currentContent && currentToolCalls.length === 0 && /* @__PURE__ */ jsx7(Box7, { marginTop: 1, marginLeft: 4, children: /* @__PURE__ */ jsx7(Spinner, { type: "dots", label: "\u601D\u8003\u4E2D..." }) }),
2310
+ !isStreaming && streamError && /* @__PURE__ */ jsx7(Box7, { marginTop: 1, marginLeft: 3, children: /* @__PURE__ */ jsxs7(Text8, { color: "red", children: [
2100
2311
  "\u26A0 ",
2101
2312
  streamError
2102
2313
  ] }) })
2103
2314
  ] }),
2104
- selectingModel ? /* @__PURE__ */ jsxs5(Box5, { marginTop: 1, flexDirection: "column", children: [
2105
- /* @__PURE__ */ jsx5(Text6, { color: "#00ffff", dimColor: true, children: "\u2500".repeat(dividerWidth) }),
2106
- /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", marginTop: 1, children: [
2107
- /* @__PURE__ */ jsx5(Text6, { bold: true, color: "#00ffff", children: "\u9009\u62E9\u6A21\u578B\uFF1A" }),
2315
+ selectingModel ? /* @__PURE__ */ jsxs7(Box7, { marginTop: 1, flexDirection: "column", children: [
2316
+ /* @__PURE__ */ jsx7(Text8, { color: "#00ffff", dimColor: true, children: "\u2500".repeat(dividerWidth) }),
2317
+ /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", marginTop: 1, children: [
2318
+ /* @__PURE__ */ jsx7(Text8, { bold: true, color: "#00ffff", children: "\u9009\u62E9\u6A21\u578B\uFF1A" }),
2108
2319
  modelOptions.map((id, i) => {
2109
2320
  const meta = SUPPORTED_MODELS[id];
2110
2321
  const isCurrent = id === activeModel;
2111
2322
  const isSelected = i === modelSelectIndex;
2112
2323
  const marker = isSelected ? " > " : " ";
2113
2324
  const suffix = isCurrent ? " (\u5F53\u524D)" : "";
2114
- return /* @__PURE__ */ jsxs5(Box5, { children: [
2115
- /* @__PURE__ */ jsxs5(
2116
- Text6,
2325
+ return /* @__PURE__ */ jsxs7(Box7, { children: [
2326
+ /* @__PURE__ */ jsxs7(
2327
+ Text8,
2117
2328
  {
2118
2329
  color: isSelected ? "#00ff41" : void 0,
2119
2330
  bold: isSelected,
@@ -2124,40 +2335,43 @@ function ChatSession({
2124
2335
  ]
2125
2336
  }
2126
2337
  ),
2127
- isSelected && /* @__PURE__ */ jsxs5(Text6, { color: "#808080", children: [
2338
+ isSelected && /* @__PURE__ */ jsxs7(Text8, { color: "#808080", children: [
2128
2339
  " \u2014 ",
2129
2340
  id
2130
2341
  ] })
2131
2342
  ] }, id);
2132
2343
  }),
2133
- /* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx5(Text6, { color: "#808080", dimColor: true, children: "\u2191\u2193 \u9009\u62E9 \xB7 Enter \u786E\u8BA4 \xB7 Esc \u53D6\u6D88" }) })
2344
+ /* @__PURE__ */ jsx7(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text8, { color: "#808080", dimColor: true, children: "\u2191\u2193 \u9009\u62E9 \xB7 Enter \u786E\u8BA4 \xB7 Esc \u53D6\u6D88" }) })
2134
2345
  ] }),
2135
- /* @__PURE__ */ jsx5(Text6, { color: "#00ffff", dimColor: true, children: "\u2500".repeat(dividerWidth) })
2136
- ] }) : /* @__PURE__ */ jsxs5(Fragment, { children: [
2137
- /* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx5(Text6, { color: "#00ffff", dimColor: true, children: "\u2500".repeat(dividerWidth) }) }),
2138
- /* @__PURE__ */ jsxs5(Box5, { children: [
2139
- /* @__PURE__ */ jsx5(Box5, { width: 4, flexShrink: 0, children: /* @__PURE__ */ jsx5(Text6, { bold: true, color: "#00ff41", children: "\u26A1" }) }),
2140
- /* @__PURE__ */ jsx5(Box5, { flexGrow: 1, children: !input && !isStreaming && idlePlaceholder && gradientColors.length > 0 ? /* @__PURE__ */ jsx5(Text6, { children: idlePlaceholder.split("").map((ch, i) => /* @__PURE__ */ jsx5(Text6, { color: gradientColors[i] ?? void 0, children: ch }, i)) }) : !input && isStreaming && streamingPlaceholder && streamingGradientColors.length > 0 ? /* @__PURE__ */ jsx5(Text6, { children: streamingPlaceholder.split("").map((ch, i) => /* @__PURE__ */ jsx5(Text6, { color: streamingGradientColors[i] ?? void 0, children: ch }, i)) }) : /* @__PURE__ */ jsx5(
2346
+ /* @__PURE__ */ jsx7(Text8, { color: "#00ffff", dimColor: true, children: "\u2500".repeat(dividerWidth) })
2347
+ ] }) : /* @__PURE__ */ jsxs7(Fragment, { children: [
2348
+ /* @__PURE__ */ jsx7(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text8, { color: "#00ffff", dimColor: true, children: "\u2500".repeat(dividerWidth) }) }),
2349
+ /* @__PURE__ */ jsxs7(Box7, { children: [
2350
+ /* @__PURE__ */ jsx7(Box7, { width: 4, flexShrink: 0, children: /* @__PURE__ */ jsx7(Text8, { bold: true, color: "#00ff41", children: "\u26A1" }) }),
2351
+ /* @__PURE__ */ jsx7(Box7, { flexGrow: 1, children: !input && !isStreaming && idlePlaceholder && gradientColors.length > 0 ? /* @__PURE__ */ jsx7(Text8, { children: idlePlaceholder.split("").map((ch, i) => /* @__PURE__ */ jsx7(Text8, { color: gradientColors[i] ?? void 0, children: ch }, i)) }) : !input && isStreaming && streamingPlaceholder && streamingGradientColors.length > 0 ? /* @__PURE__ */ jsx7(Text8, { children: streamingPlaceholder.split("").map((ch, i) => /* @__PURE__ */ jsx7(Text8, { color: streamingGradientColors[i] ?? void 0, children: ch }, i)) }) : /* @__PURE__ */ jsx7(
2141
2352
  TextInput,
2142
2353
  {
2143
2354
  value: input,
2144
2355
  onChange: setInput,
2145
2356
  onSubmit: handleSubmit,
2146
2357
  placeholder: ""
2147
- }
2358
+ },
2359
+ inputKey
2148
2360
  ) })
2149
2361
  ] }),
2150
- /* @__PURE__ */ jsx5(Box5, { children: /* @__PURE__ */ jsx5(Text6, { color: "#00ffff", dimColor: true, children: "\u2500".repeat(dividerWidth) }) })
2362
+ /* @__PURE__ */ jsx7(Box7, { children: /* @__PURE__ */ jsx7(Text8, { color: "#00ffff", dimColor: true, children: "\u2500".repeat(dividerWidth) }) }),
2363
+ /* @__PURE__ */ jsx7(SkillSelector, { skills, input, selectedIndex: skillSelectIndex }),
2364
+ /* @__PURE__ */ jsx7(FileSelector, { files, input, selectedIndex: fileSelectIndex })
2151
2365
  ] }),
2152
- doubleCtrlC && !isStreaming && /* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx5(Text6, { color: "#ff1493", bold: true, children: " \u26A0 \u518D\u6309\u4E00\u6B21 Ctrl+C \u9000\u51FA dskcode" }) }),
2153
- isStreaming && /* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx5(Text6, { color: "yellow", dimColor: true, children: " \u63D0\u793A\uFF1A\u6309 Ctrl+C \u53D6\u6D88\u5F53\u524D\u8BF7\u6C42" }) })
2366
+ doubleCtrlC && !isStreaming && /* @__PURE__ */ jsx7(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text8, { color: "#ff1493", bold: true, children: " \u26A0 \u518D\u6309\u4E00\u6B21 Ctrl+C \u9000\u51FA dskcode" }) }),
2367
+ isStreaming && /* @__PURE__ */ jsx7(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text8, { color: "yellow", dimColor: true, children: " \u63D0\u793A\uFF1A\u6309 Ctrl+C \u53D6\u6D88\u5F53\u524D\u8BF7\u6C42" }) })
2154
2368
  ] });
2155
2369
  }
2156
2370
 
2157
2371
  // src/ui/GamePicker.tsx
2158
- import { Box as Box6, Text as Text7, useInput as useInput2 } from "ink";
2372
+ import { Box as Box8, Text as Text9, useInput as useInput2 } from "ink";
2159
2373
  import { useState as useState4, useCallback as useCallback3 } from "react";
2160
- import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
2374
+ import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
2161
2375
  function GamePicker({ games, onSelect, onExit, onBackToChat }) {
2162
2376
  const [selectedIndex, setSelectedIndex] = useState4(0);
2163
2377
  const exitAction = onBackToChat ?? onExit ?? (() => process.exit(0));
@@ -2185,18 +2399,18 @@ function GamePicker({ games, onSelect, onExit, onBackToChat }) {
2185
2399
  [games, selectedIndex, onSelect, onExit, onBackToChat, handleCtrlC]
2186
2400
  )
2187
2401
  );
2188
- return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
2189
- /* @__PURE__ */ jsx6(Box6, { marginBottom: 1, children: /* @__PURE__ */ jsx6(Text7, { bold: true, color: "#00ffff", children: "\u{1F3AE} \u6E38\u620F\u5217\u8868" }) }),
2190
- /* @__PURE__ */ jsx6(Box6, { flexDirection: "column", children: games.map((game, index) => {
2402
+ return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
2403
+ /* @__PURE__ */ jsx8(Box8, { marginBottom: 1, children: /* @__PURE__ */ jsx8(Text9, { bold: true, color: "#00ffff", children: "\u{1F3AE} \u6E38\u620F\u5217\u8868" }) }),
2404
+ /* @__PURE__ */ jsx8(Box8, { flexDirection: "column", children: games.map((game, index) => {
2191
2405
  const isSelected = index === selectedIndex;
2192
- return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "row", children: [
2193
- /* @__PURE__ */ jsx6(Box6, { width: 3, flexShrink: 0, children: isSelected ? /* @__PURE__ */ jsx6(Text7, { bold: true, color: "#00ff41", children: "\u25B8 " }) : /* @__PURE__ */ jsx6(Text7, { children: " " }) }),
2194
- /* @__PURE__ */ jsx6(Box6, { width: 20, flexShrink: 0, children: /* @__PURE__ */ jsx6(Text7, { bold: true, color: isSelected ? "#00ff41" : "#ffffff", children: game.name }) }),
2195
- /* @__PURE__ */ jsx6(Box6, { children: /* @__PURE__ */ jsx6(Text7, { color: "#888888", children: game.description }) })
2406
+ return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "row", children: [
2407
+ /* @__PURE__ */ jsx8(Box8, { width: 3, flexShrink: 0, children: isSelected ? /* @__PURE__ */ jsx8(Text9, { bold: true, color: "#00ff41", children: "\u25B8 " }) : /* @__PURE__ */ jsx8(Text9, { children: " " }) }),
2408
+ /* @__PURE__ */ jsx8(Box8, { width: 20, flexShrink: 0, children: /* @__PURE__ */ jsx8(Text9, { bold: true, color: isSelected ? "#00ff41" : "#ffffff", children: game.name }) }),
2409
+ /* @__PURE__ */ jsx8(Box8, { children: /* @__PURE__ */ jsx8(Text9, { color: "#888888", children: game.description }) })
2196
2410
  ] }, game.id);
2197
2411
  }) }),
2198
- /* @__PURE__ */ jsx6(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx6(Text7, { dimColor: true, children: " \u2191/\u2193 \u9009\u62E9 Enter \u542F\u52A8 q \u8FD4\u56DE" }) }),
2199
- doubleCtrlC && /* @__PURE__ */ jsx6(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx6(Text7, { color: "#ff1493", bold: true, children: " \u26A0 \u518D\u6309\u4E00\u6B21 Ctrl+C \u9000\u51FA dskcode" }) })
2412
+ /* @__PURE__ */ jsx8(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx8(Text9, { dimColor: true, children: " \u2191/\u2193 \u9009\u62E9 Enter \u542F\u52A8 q \u8FD4\u56DE" }) }),
2413
+ doubleCtrlC && /* @__PURE__ */ jsx8(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx8(Text9, { color: "#ff1493", bold: true, children: " \u26A0 \u518D\u6309\u4E00\u6B21 Ctrl+C \u9000\u51FA dskcode" }) })
2200
2414
  ] });
2201
2415
  }
2202
2416
 
@@ -2213,9 +2427,9 @@ function listGames() {
2213
2427
  }
2214
2428
 
2215
2429
  // src/game/brick-breaker/index.tsx
2216
- import { Box as Box7, Text as Text8, useInput as useInput3, render as render2 } from "ink";
2430
+ import { Box as Box9, Text as Text10, useInput as useInput3, render as render2 } from "ink";
2217
2431
  import { useState as useState5, useEffect as useEffect4, useRef as useRef3, useCallback as useCallback4 } from "react";
2218
- import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
2432
+ import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
2219
2433
  var GAME_WIDTH = 40;
2220
2434
  var GAME_HEIGHT = 18;
2221
2435
  var PADDLE_WIDTH = 9;
@@ -2405,49 +2619,49 @@ function BrickBreakerGame({ onExit: _onExit }) {
2405
2619
  const board = buildBoard(s);
2406
2620
  const def = getLevel(s.level);
2407
2621
  void tick;
2408
- return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
2409
- /* @__PURE__ */ jsxs7(Box7, { flexDirection: "row", children: [
2410
- /* @__PURE__ */ jsx7(Box7, { width: 20, children: /* @__PURE__ */ jsxs7(Text8, { children: [
2622
+ return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
2623
+ /* @__PURE__ */ jsxs9(Box9, { flexDirection: "row", children: [
2624
+ /* @__PURE__ */ jsx9(Box9, { width: 20, children: /* @__PURE__ */ jsxs9(Text10, { children: [
2411
2625
  "\u5173\u5361 ",
2412
2626
  s.level,
2413
2627
  ": ",
2414
- /* @__PURE__ */ jsx7(Text8, { color: "cyan", children: def.desc })
2628
+ /* @__PURE__ */ jsx9(Text10, { color: "cyan", children: def.desc })
2415
2629
  ] }) }),
2416
- /* @__PURE__ */ jsx7(Box7, { width: 12, children: /* @__PURE__ */ jsxs7(Text8, { children: [
2630
+ /* @__PURE__ */ jsx9(Box9, { width: 12, children: /* @__PURE__ */ jsxs9(Text10, { children: [
2417
2631
  "\u5206\u6570: ",
2418
- /* @__PURE__ */ jsx7(Text8, { color: "yellow", children: String(s.score).padStart(3, "0") })
2632
+ /* @__PURE__ */ jsx9(Text10, { color: "yellow", children: String(s.score).padStart(3, "0") })
2419
2633
  ] }) }),
2420
- /* @__PURE__ */ jsx7(Box7, { width: 12, children: /* @__PURE__ */ jsxs7(Text8, { children: [
2634
+ /* @__PURE__ */ jsx9(Box9, { width: 12, children: /* @__PURE__ */ jsxs9(Text10, { children: [
2421
2635
  "\u751F\u547D: ",
2422
- /* @__PURE__ */ jsx7(Text8, { color: "red", children: "\u2665".repeat(Math.max(0, s.lives)) })
2636
+ /* @__PURE__ */ jsx9(Text10, { color: "red", children: "\u2665".repeat(Math.max(0, s.lives)) })
2423
2637
  ] }) }),
2424
- /* @__PURE__ */ jsx7(Box7, { width: 10, children: /* @__PURE__ */ jsxs7(Text8, { children: [
2638
+ /* @__PURE__ */ jsx9(Box9, { width: 10, children: /* @__PURE__ */ jsxs9(Text10, { children: [
2425
2639
  "\u7816\u5757: ",
2426
- /* @__PURE__ */ jsx7(Text8, { color: "cyan", children: aliveCount })
2640
+ /* @__PURE__ */ jsx9(Text10, { color: "cyan", children: aliveCount })
2427
2641
  ] }) }),
2428
- /* @__PURE__ */ jsx7(Box7, { children: /* @__PURE__ */ jsxs7(Text8, { color: s.paused ? "gray" : "green", children: [
2642
+ /* @__PURE__ */ jsx9(Box9, { children: /* @__PURE__ */ jsxs9(Text10, { color: s.paused ? "gray" : "green", children: [
2429
2643
  "[",
2430
2644
  s.paused ? "\u6682\u505C" : "\u8FD0\u884C\u4E2D",
2431
2645
  "]"
2432
2646
  ] }) })
2433
2647
  ] }),
2434
- /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
2435
- /* @__PURE__ */ jsxs7(Text8, { children: [
2648
+ /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
2649
+ /* @__PURE__ */ jsxs9(Text10, { children: [
2436
2650
  "\u250C",
2437
2651
  "\u2500".repeat(GAME_WIDTH),
2438
2652
  "\u2510"
2439
2653
  ] }),
2440
- /* @__PURE__ */ jsx7(Text8, { children: selectingLevel ? " \x1B[90m\u9009\u62E9\u5173\u5361\u540E\u5F00\u59CB...\x1B[0m" : board }),
2441
- /* @__PURE__ */ jsxs7(Text8, { children: [
2654
+ /* @__PURE__ */ jsx9(Text10, { children: selectingLevel ? " \x1B[90m\u9009\u62E9\u5173\u5361\u540E\u5F00\u59CB...\x1B[0m" : board }),
2655
+ /* @__PURE__ */ jsxs9(Text10, { children: [
2442
2656
  "\u2514",
2443
2657
  "\u2500".repeat(GAME_WIDTH),
2444
2658
  "\u2518"
2445
2659
  ] })
2446
2660
  ] }),
2447
- selectingLevel && /* @__PURE__ */ jsxs7(Box7, { marginTop: 1, flexDirection: "column", children: [
2448
- /* @__PURE__ */ jsx7(Text8, { bold: true, color: "yellow", children: "\u9009\u62E9\u5173\u5361" }),
2449
- /* @__PURE__ */ jsx7(Box7, { flexDirection: "row", flexWrap: "wrap", children: LEVELS.map((lv, i) => /* @__PURE__ */ jsx7(Box7, { width: 22, children: /* @__PURE__ */ jsxs7(Text8, { children: [
2450
- /* @__PURE__ */ jsx7(Text8, { color: initialLevel === i + 1 ? "green" : "white", children: i + 1 === 10 ? "0" : String(i + 1) }),
2661
+ selectingLevel && /* @__PURE__ */ jsxs9(Box9, { marginTop: 1, flexDirection: "column", children: [
2662
+ /* @__PURE__ */ jsx9(Text10, { bold: true, color: "yellow", children: "\u9009\u62E9\u5173\u5361" }),
2663
+ /* @__PURE__ */ jsx9(Box9, { flexDirection: "row", flexWrap: "wrap", children: LEVELS.map((lv, i) => /* @__PURE__ */ jsx9(Box9, { width: 22, children: /* @__PURE__ */ jsxs9(Text10, { children: [
2664
+ /* @__PURE__ */ jsx9(Text10, { color: initialLevel === i + 1 ? "green" : "white", children: i + 1 === 10 ? "0" : String(i + 1) }),
2451
2665
  ". ",
2452
2666
  lv.desc,
2453
2667
  " (",
@@ -2456,16 +2670,16 @@ function BrickBreakerGame({ onExit: _onExit }) {
2456
2670
  lv.cols,
2457
2671
  ")"
2458
2672
  ] }) }, i)) }),
2459
- /* @__PURE__ */ jsx7(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text8, { dimColor: true, children: "\u6309\u6570\u5B57\u9009\u5173 q \u9000\u51FA" }) })
2673
+ /* @__PURE__ */ jsx9(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx9(Text10, { dimColor: true, children: "\u6309\u6570\u5B57\u9009\u5173 q \u9000\u51FA" }) })
2460
2674
  ] }),
2461
- !selectingLevel && (s.gameOver || s.win) && /* @__PURE__ */ jsxs7(Box7, { marginTop: 1, children: [
2462
- /* @__PURE__ */ jsx7(Text8, { bold: true, color: s.gameOver ? "red" : "green", children: s.gameOver ? "\u6E38\u620F\u7ED3\u675F\uFF01" : "\u606D\u559C\u901A\u5173\uFF01" }),
2463
- /* @__PURE__ */ jsxs7(Text8, { children: [
2675
+ !selectingLevel && (s.gameOver || s.win) && /* @__PURE__ */ jsxs9(Box9, { marginTop: 1, children: [
2676
+ /* @__PURE__ */ jsx9(Text10, { bold: true, color: s.gameOver ? "red" : "green", children: s.gameOver ? "\u6E38\u620F\u7ED3\u675F\uFF01" : "\u606D\u559C\u901A\u5173\uFF01" }),
2677
+ /* @__PURE__ */ jsxs9(Text10, { children: [
2464
2678
  " \u5206\u6570: ",
2465
- /* @__PURE__ */ jsx7(Text8, { color: "yellow", children: s.score })
2679
+ /* @__PURE__ */ jsx9(Text10, { color: "yellow", children: s.score })
2466
2680
  ] })
2467
2681
  ] }),
2468
- !selectingLevel && /* @__PURE__ */ jsx7(Box7, { marginTop: 1, children: s.gameOver || s.win ? /* @__PURE__ */ jsx7(Text8, { dimColor: true, children: "\u2190 \u2192 \u79FB\u52A8 r \u91CD\u5F00 l \u9009\u5173 q \u9000\u51FA" }) : /* @__PURE__ */ jsx7(Text8, { dimColor: true, children: "\u2190 \u2192 \u79FB\u52A8 p \u6682\u505C q \u9000\u51FA" }) })
2682
+ !selectingLevel && /* @__PURE__ */ jsx9(Box9, { marginTop: 1, children: s.gameOver || s.win ? /* @__PURE__ */ jsx9(Text10, { dimColor: true, children: "\u2190 \u2192 \u79FB\u52A8 r \u91CD\u5F00 l \u9009\u5173 q \u9000\u51FA" }) : /* @__PURE__ */ jsx9(Text10, { dimColor: true, children: "\u2190 \u2192 \u79FB\u52A8 p \u6682\u505C q \u9000\u51FA" }) })
2469
2683
  ] });
2470
2684
  }
2471
2685
  var brick_breaker_default = {
@@ -2475,7 +2689,7 @@ var brick_breaker_default = {
2475
2689
  play: async () => {
2476
2690
  await new Promise((resolve) => {
2477
2691
  const { unmount } = render2(
2478
- /* @__PURE__ */ jsx7(BrickBreakerGame, { onExit: () => {
2692
+ /* @__PURE__ */ jsx9(BrickBreakerGame, { onExit: () => {
2479
2693
  unmount();
2480
2694
  resolve();
2481
2695
  } })
@@ -2485,9 +2699,9 @@ var brick_breaker_default = {
2485
2699
  };
2486
2700
 
2487
2701
  // src/game/coder-check/index.tsx
2488
- import { Box as Box8, Text as Text9, useInput as useInput4, render as render3 } from "ink";
2702
+ import { Box as Box10, Text as Text11, useInput as useInput4, render as render3 } from "ink";
2489
2703
  import { useState as useState6, useEffect as useEffect5, useRef as useRef4, useCallback as useCallback5 } from "react";
2490
- import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
2704
+ import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
2491
2705
  var GAME_W = 66;
2492
2706
  var GAME_H = 20;
2493
2707
  var SCORE_H = 6;
@@ -2958,44 +3172,44 @@ function CoderCheck({ onExit: _onExit }) {
2958
3172
  const scoreLines = buildScoreLines(scoreStr);
2959
3173
  const view = buildGameView(s, scoreLines, scoreColor, s.message);
2960
3174
  void tick;
2961
- return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", paddingX: 1, children: [
2962
- /* @__PURE__ */ jsx8(Box8, { flexDirection: "row", children: /* @__PURE__ */ jsxs8(Text9, { children: [
3175
+ return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", paddingX: 1, children: [
3176
+ /* @__PURE__ */ jsx10(Box10, { flexDirection: "row", children: /* @__PURE__ */ jsxs10(Text11, { children: [
2963
3177
  "\u751F\u547D ",
2964
- /* @__PURE__ */ jsx8(Text9, { color: "red", children: "\u2665".repeat(Math.max(0, s.lives)) }),
3178
+ /* @__PURE__ */ jsx10(Text11, { color: "red", children: "\u2665".repeat(Math.max(0, s.lives)) }),
2965
3179
  " ",
2966
3180
  "\u901F\u5EA6 ",
2967
- /* @__PURE__ */ jsxs8(Text9, { color: "cyan", children: [
3181
+ /* @__PURE__ */ jsxs10(Text11, { color: "cyan", children: [
2968
3182
  "Lv.",
2969
3183
  Math.floor(s.speed * 10)
2970
3184
  ] })
2971
3185
  ] }) }),
2972
- !s.gameOver && s.target && /* @__PURE__ */ jsx8(Box8, { marginTop: 1, children: /* @__PURE__ */ jsxs8(Text9, { children: [
3186
+ !s.gameOver && s.target && /* @__PURE__ */ jsx10(Box10, { marginTop: 1, children: /* @__PURE__ */ jsxs10(Text11, { children: [
2973
3187
  "\u6253\u5B57: ",
2974
- /* @__PURE__ */ jsx8(Text9, { color: "green", children: s.typed }),
2975
- /* @__PURE__ */ jsx8(Text9, { color: "white", children: s.target.slice(s.typed.length) })
3188
+ /* @__PURE__ */ jsx10(Text11, { color: "green", children: s.typed }),
3189
+ /* @__PURE__ */ jsx10(Text11, { color: "white", children: s.target.slice(s.typed.length) })
2976
3190
  ] }) }),
2977
- /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", marginTop: 1, children: [
2978
- /* @__PURE__ */ jsxs8(Text9, { children: [
3191
+ /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", marginTop: 1, children: [
3192
+ /* @__PURE__ */ jsxs10(Text11, { children: [
2979
3193
  "\u250C",
2980
3194
  "\u2500".repeat(GAME_W),
2981
3195
  "\u2510"
2982
3196
  ] }),
2983
- view.map((row, i) => /* @__PURE__ */ jsx8(Text9, { children: `\u2502${row}\u2502` }, i)),
2984
- /* @__PURE__ */ jsxs8(Text9, { children: [
3197
+ view.map((row, i) => /* @__PURE__ */ jsx10(Text11, { children: `\u2502${row}\u2502` }, i)),
3198
+ /* @__PURE__ */ jsxs10(Text11, { children: [
2985
3199
  "\u2514",
2986
3200
  "\u2500".repeat(GAME_W),
2987
3201
  "\u2518"
2988
3202
  ] })
2989
3203
  ] }),
2990
- s.gameOver && /* @__PURE__ */ jsxs8(Box8, { marginTop: 1, children: [
2991
- /* @__PURE__ */ jsx8(Text9, { bold: true, color: "red", children: "\u6E38\u620F\u7ED3\u675F\uFF01" }),
2992
- /* @__PURE__ */ jsxs8(Text9, { children: [
3204
+ s.gameOver && /* @__PURE__ */ jsxs10(Box10, { marginTop: 1, children: [
3205
+ /* @__PURE__ */ jsx10(Text11, { bold: true, color: "red", children: "\u6E38\u620F\u7ED3\u675F\uFF01" }),
3206
+ /* @__PURE__ */ jsxs10(Text11, { children: [
2993
3207
  " \u5F97\u5206: ",
2994
- /* @__PURE__ */ jsx8(Text9, { color: "yellow", children: s.score }),
3208
+ /* @__PURE__ */ jsx10(Text11, { color: "yellow", children: s.score }),
2995
3209
  " r \u91CD\u5F00 q \u9000\u51FA"
2996
3210
  ] })
2997
3211
  ] }),
2998
- /* @__PURE__ */ jsx8(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx8(Text9, { dimColor: true, children: "\u6253\u5B57\u6D88\u9664\u5355\u8BCD \u7A7A\u683C/Ctrl+P\u6682\u505C Ctrl+Q\u9000\u51FA" }) })
3212
+ /* @__PURE__ */ jsx10(Box10, { marginTop: 1, children: /* @__PURE__ */ jsx10(Text11, { dimColor: true, children: "\u6253\u5B57\u6D88\u9664\u5355\u8BCD \u7A7A\u683C/Ctrl+P\u6682\u505C Ctrl+Q\u9000\u51FA" }) })
2999
3213
  ] });
3000
3214
  }
3001
3215
  var coder_check_default = {
@@ -3005,7 +3219,7 @@ var coder_check_default = {
3005
3219
  play: async () => {
3006
3220
  await new Promise((resolve) => {
3007
3221
  const { unmount } = render3(
3008
- /* @__PURE__ */ jsx8(CoderCheck, { onExit: () => {
3222
+ /* @__PURE__ */ jsx10(CoderCheck, { onExit: () => {
3009
3223
  unmount();
3010
3224
  resolve();
3011
3225
  } })
@@ -3026,10 +3240,10 @@ import { render as render4 } from "ink";
3026
3240
  import chalk4 from "chalk";
3027
3241
 
3028
3242
  // src/stock/StockList.tsx
3029
- import { Box as Box9, Text as Text10, useInput as useInput5 } from "ink";
3243
+ import { Box as Box11, Text as Text12, useInput as useInput5 } from "ink";
3030
3244
  import { useState as useState7, useCallback as useCallback6, useEffect as useEffect6 } from "react";
3031
3245
  import asciichart from "asciichart";
3032
- import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
3246
+ import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
3033
3247
  var MINUTE_API = "https://web.ifzq.gtimg.cn/appstock/app/minute/query?code={code}&r=0.1";
3034
3248
  function normalizeApiCode(code) {
3035
3249
  if (code.startsWith("sh") || code.startsWith("sz")) return code;
@@ -3226,57 +3440,57 @@ function StockList({ codes, onExit, onBackToChat }) {
3226
3440
  );
3227
3441
  if (detailView) {
3228
3442
  if (detailLoading) {
3229
- return /* @__PURE__ */ jsx9(Box9, { paddingLeft: 1, children: /* @__PURE__ */ jsx9(Text10, { dimColor: true, children: " \u27F3 \u52A0\u8F7D\u5206\u65F6\u6570\u636E..." }) });
3443
+ return /* @__PURE__ */ jsx11(Box11, { paddingLeft: 1, children: /* @__PURE__ */ jsx11(Text12, { dimColor: true, children: " \u27F3 \u52A0\u8F7D\u5206\u65F6\u6570\u636E..." }) });
3230
3444
  }
3231
3445
  return renderDetail(detailView, () => setDetailView(null), detailPrices ?? void 0, detailCountdown, currentTime);
3232
3446
  }
3233
- return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
3234
- /* @__PURE__ */ jsxs9(Box9, { marginBottom: 1, justifyContent: "space-between", children: [
3235
- /* @__PURE__ */ jsx9(Text10, { bold: true, color: "#00ffff", children: " \u{1F4C8} \u81EA\u9009\u80A1\u76D1\u63A7" }),
3236
- /* @__PURE__ */ jsxs9(Text10, { dimColor: true, children: [
3447
+ return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", children: [
3448
+ /* @__PURE__ */ jsxs11(Box11, { marginBottom: 1, justifyContent: "space-between", children: [
3449
+ /* @__PURE__ */ jsx11(Text12, { bold: true, color: "#00ffff", children: " \u{1F4C8} \u81EA\u9009\u80A1\u76D1\u63A7" }),
3450
+ /* @__PURE__ */ jsxs11(Text12, { dimColor: true, children: [
3237
3451
  " \u{1F550} ",
3238
3452
  currentTime
3239
3453
  ] }),
3240
- /* @__PURE__ */ jsx9(Text10, { dimColor: true, children: loading ? " \u27F3 \u5237\u65B0\u4E2D..." : ` ${countdown}s \u540E\u81EA\u52A8\u5237\u65B0` })
3454
+ /* @__PURE__ */ jsx11(Text12, { dimColor: true, children: loading ? " \u27F3 \u5237\u65B0\u4E2D..." : ` ${countdown}s \u540E\u81EA\u52A8\u5237\u65B0` })
3241
3455
  ] }),
3242
- /* @__PURE__ */ jsxs9(Box9, { children: [
3243
- /* @__PURE__ */ jsx9(Box9, { width: 3 }),
3244
- /* @__PURE__ */ jsx9(Box9, { width: 9, children: /* @__PURE__ */ jsx9(Text10, { dimColor: true, children: "\u4EE3\u7801" }) }),
3245
- /* @__PURE__ */ jsx9(Box9, { width: 16, children: /* @__PURE__ */ jsx9(Text10, { dimColor: true, children: "\u540D\u79F0" }) }),
3246
- /* @__PURE__ */ jsx9(Box9, { width: 12, children: /* @__PURE__ */ jsx9(Text10, { dimColor: true, children: "\u6700\u65B0\u4EF7" }) }),
3247
- /* @__PURE__ */ jsx9(Box9, { width: 12, children: /* @__PURE__ */ jsx9(Text10, { dimColor: true, children: "\u6DA8\u8DCC\u5E45" }) }),
3248
- /* @__PURE__ */ jsx9(Box9, { width: 12, children: /* @__PURE__ */ jsx9(Text10, { dimColor: true, children: "\u6DA8\u8DCC\u989D" }) }),
3249
- /* @__PURE__ */ jsx9(Box9, { width: 12, children: /* @__PURE__ */ jsx9(Text10, { dimColor: true, children: "\u6700\u9AD8" }) }),
3250
- /* @__PURE__ */ jsx9(Box9, { width: 12, children: /* @__PURE__ */ jsx9(Text10, { dimColor: true, children: "\u6700\u4F4E" }) }),
3251
- /* @__PURE__ */ jsx9(Box9, { children: /* @__PURE__ */ jsx9(Text10, { dimColor: true, children: "\u6210\u4EA4\u989D" }) })
3456
+ /* @__PURE__ */ jsxs11(Box11, { children: [
3457
+ /* @__PURE__ */ jsx11(Box11, { width: 3 }),
3458
+ /* @__PURE__ */ jsx11(Box11, { width: 9, children: /* @__PURE__ */ jsx11(Text12, { dimColor: true, children: "\u4EE3\u7801" }) }),
3459
+ /* @__PURE__ */ jsx11(Box11, { width: 16, children: /* @__PURE__ */ jsx11(Text12, { dimColor: true, children: "\u540D\u79F0" }) }),
3460
+ /* @__PURE__ */ jsx11(Box11, { width: 12, children: /* @__PURE__ */ jsx11(Text12, { dimColor: true, children: "\u6700\u65B0\u4EF7" }) }),
3461
+ /* @__PURE__ */ jsx11(Box11, { width: 12, children: /* @__PURE__ */ jsx11(Text12, { dimColor: true, children: "\u6DA8\u8DCC\u5E45" }) }),
3462
+ /* @__PURE__ */ jsx11(Box11, { width: 12, children: /* @__PURE__ */ jsx11(Text12, { dimColor: true, children: "\u6DA8\u8DCC\u989D" }) }),
3463
+ /* @__PURE__ */ jsx11(Box11, { width: 12, children: /* @__PURE__ */ jsx11(Text12, { dimColor: true, children: "\u6700\u9AD8" }) }),
3464
+ /* @__PURE__ */ jsx11(Box11, { width: 12, children: /* @__PURE__ */ jsx11(Text12, { dimColor: true, children: "\u6700\u4F4E" }) }),
3465
+ /* @__PURE__ */ jsx11(Box11, { children: /* @__PURE__ */ jsx11(Text12, { dimColor: true, children: "\u6210\u4EA4\u989D" }) })
3252
3466
  ] }),
3253
- /* @__PURE__ */ jsx9(Box9, { children: /* @__PURE__ */ jsx9(Text10, { dimColor: true, children: " " + "\u2500".repeat(100) }) }),
3254
- /* @__PURE__ */ jsx9(Box9, { flexDirection: "column", children: stocks.map((stock, index) => {
3467
+ /* @__PURE__ */ jsx11(Box11, { children: /* @__PURE__ */ jsx11(Text12, { dimColor: true, children: " " + "\u2500".repeat(100) }) }),
3468
+ /* @__PURE__ */ jsx11(Box11, { flexDirection: "column", children: stocks.map((stock, index) => {
3255
3469
  const isSelected = index === selectedIndex;
3256
3470
  const isUp = stock.changePercent >= 0;
3257
3471
  const color = isUp ? "#ff1493" : "#00ff41";
3258
- return /* @__PURE__ */ jsxs9(Box9, { children: [
3259
- /* @__PURE__ */ jsx9(Box9, { width: 3, flexShrink: 0, children: isSelected ? /* @__PURE__ */ jsx9(Text10, { bold: true, color: "#00ffff", children: "\u25B8 " }) : /* @__PURE__ */ jsx9(Text10, { children: " " }) }),
3260
- /* @__PURE__ */ jsx9(Box9, { width: 9, children: /* @__PURE__ */ jsx9(Text10, { bold: true, color: isSelected ? "#00ffff" : "#ffffff", children: stock.code }) }),
3261
- /* @__PURE__ */ jsx9(Box9, { width: 16, children: /* @__PURE__ */ jsx9(Text10, { color: isSelected ? "#ffffff" : "#cccccc", children: stock.name }) }),
3262
- /* @__PURE__ */ jsx9(Box9, { width: 12, children: /* @__PURE__ */ jsx9(Text10, { bold: true, color, children: formatPrice(stock.price) }) }),
3263
- /* @__PURE__ */ jsx9(Box9, { width: 12, children: /* @__PURE__ */ jsxs9(Text10, { color, children: [
3472
+ return /* @__PURE__ */ jsxs11(Box11, { children: [
3473
+ /* @__PURE__ */ jsx11(Box11, { width: 3, flexShrink: 0, children: isSelected ? /* @__PURE__ */ jsx11(Text12, { bold: true, color: "#00ffff", children: "\u25B8 " }) : /* @__PURE__ */ jsx11(Text12, { children: " " }) }),
3474
+ /* @__PURE__ */ jsx11(Box11, { width: 9, children: /* @__PURE__ */ jsx11(Text12, { bold: true, color: isSelected ? "#00ffff" : "#ffffff", children: stock.code }) }),
3475
+ /* @__PURE__ */ jsx11(Box11, { width: 16, children: /* @__PURE__ */ jsx11(Text12, { color: isSelected ? "#ffffff" : "#cccccc", children: stock.name }) }),
3476
+ /* @__PURE__ */ jsx11(Box11, { width: 12, children: /* @__PURE__ */ jsx11(Text12, { bold: true, color, children: formatPrice(stock.price) }) }),
3477
+ /* @__PURE__ */ jsx11(Box11, { width: 12, children: /* @__PURE__ */ jsxs11(Text12, { color, children: [
3264
3478
  isUp ? "+" : "",
3265
3479
  stock.changePercent.toFixed(2),
3266
3480
  "%"
3267
3481
  ] }) }),
3268
- /* @__PURE__ */ jsx9(Box9, { width: 12, children: /* @__PURE__ */ jsxs9(Text10, { color, children: [
3482
+ /* @__PURE__ */ jsx11(Box11, { width: 12, children: /* @__PURE__ */ jsxs11(Text12, { color, children: [
3269
3483
  isUp ? "+" : "",
3270
3484
  stock.changeAmount.toFixed(3)
3271
3485
  ] }) }),
3272
- /* @__PURE__ */ jsx9(Box9, { width: 12, children: /* @__PURE__ */ jsx9(Text10, { color: "#cccccc", children: formatPrice(stock.high) }) }),
3273
- /* @__PURE__ */ jsx9(Box9, { width: 12, children: /* @__PURE__ */ jsx9(Text10, { color: "#888888", children: formatPrice(stock.low) }) }),
3274
- /* @__PURE__ */ jsx9(Box9, { children: /* @__PURE__ */ jsx9(Text10, { color: "#888888", children: formatAmount(stock.amount) }) })
3486
+ /* @__PURE__ */ jsx11(Box11, { width: 12, children: /* @__PURE__ */ jsx11(Text12, { color: "#cccccc", children: formatPrice(stock.high) }) }),
3487
+ /* @__PURE__ */ jsx11(Box11, { width: 12, children: /* @__PURE__ */ jsx11(Text12, { color: "#888888", children: formatPrice(stock.low) }) }),
3488
+ /* @__PURE__ */ jsx11(Box11, { children: /* @__PURE__ */ jsx11(Text12, { color: "#888888", children: formatAmount(stock.amount) }) })
3275
3489
  ] }, stock.code);
3276
3490
  }) }),
3277
- /* @__PURE__ */ jsx9(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx9(Text10, { dimColor: true, children: ` \u2191/\u2193 \u9009\u62E9 Enter \u8BE6\u60C5 r \u624B\u52A8\u5237\u65B0 q \u8FD4\u56DE` }) }),
3278
- /* @__PURE__ */ jsx9(Box9, { children: /* @__PURE__ */ jsx9(Text10, { dimColor: true, children: ` \u6700\u540E\u66F4\u65B0: ${lastUpdate} \u7F16\u8F91\u81EA\u9009\u80A1: ~/.dskcode/settings.json` }) }),
3279
- doubleCtrlC && /* @__PURE__ */ jsx9(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx9(Text10, { color: "#ff1493", bold: true, children: " \u26A0 \u518D\u6309\u4E00\u6B21 Ctrl+C \u9000\u51FA dskcode" }) })
3491
+ /* @__PURE__ */ jsx11(Box11, { marginTop: 1, children: /* @__PURE__ */ jsx11(Text12, { dimColor: true, children: ` \u2191/\u2193 \u9009\u62E9 Enter \u8BE6\u60C5 r \u624B\u52A8\u5237\u65B0 q \u8FD4\u56DE` }) }),
3492
+ /* @__PURE__ */ jsx11(Box11, { children: /* @__PURE__ */ jsx11(Text12, { dimColor: true, children: ` \u6700\u540E\u66F4\u65B0: ${lastUpdate} \u7F16\u8F91\u81EA\u9009\u80A1: ~/.dskcode/settings.json` }) }),
3493
+ doubleCtrlC && /* @__PURE__ */ jsx11(Box11, { marginTop: 1, children: /* @__PURE__ */ jsx11(Text12, { color: "#ff1493", bold: true, children: " \u26A0 \u518D\u6309\u4E00\u6B21 Ctrl+C \u9000\u51FA dskcode" }) })
3280
3494
  ] });
3281
3495
  }
3282
3496
  function renderDetail(stock, _onBack, prices, countdown = 10, currentTime) {
@@ -3294,33 +3508,33 @@ function renderDetail(stock, _onBack, prices, countdown = 10, currentTime) {
3294
3508
  raw = raw.replaceAll("\u256D", "\u250C").replaceAll("\u256E", "\u2510").replaceAll("\u2570", "\u2514").replaceAll("\u256F", "\u2518");
3295
3509
  chartLines = raw.split("\n");
3296
3510
  }
3297
- return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", paddingLeft: 1, children: [
3298
- /* @__PURE__ */ jsxs9(Box9, { marginBottom: 1, justifyContent: "space-between", children: [
3299
- /* @__PURE__ */ jsxs9(Box9, { children: [
3300
- /* @__PURE__ */ jsxs9(Text10, { bold: true, color: "#00ffff", children: [
3511
+ return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", paddingLeft: 1, children: [
3512
+ /* @__PURE__ */ jsxs11(Box11, { marginBottom: 1, justifyContent: "space-between", children: [
3513
+ /* @__PURE__ */ jsxs11(Box11, { children: [
3514
+ /* @__PURE__ */ jsxs11(Text12, { bold: true, color: "#00ffff", children: [
3301
3515
  " \u{1F4CA} ",
3302
3516
  stock.name,
3303
3517
  " "
3304
3518
  ] }),
3305
- /* @__PURE__ */ jsx9(Text10, { dimColor: true, children: stock.code }),
3306
- currentTime && /* @__PURE__ */ jsxs9(Text10, { dimColor: true, children: [
3519
+ /* @__PURE__ */ jsx11(Text12, { dimColor: true, children: stock.code }),
3520
+ currentTime && /* @__PURE__ */ jsxs11(Text12, { dimColor: true, children: [
3307
3521
  " \u{1F550} ",
3308
3522
  currentTime
3309
3523
  ] })
3310
3524
  ] }),
3311
- /* @__PURE__ */ jsx9(Text10, { dimColor: true, children: `${countdown}s \u540E\u5237\u65B0` })
3525
+ /* @__PURE__ */ jsx11(Text12, { dimColor: true, children: `${countdown}s \u540E\u5237\u65B0` })
3312
3526
  ] }),
3313
- /* @__PURE__ */ jsxs9(Box9, { children: [
3314
- /* @__PURE__ */ jsx9(Box9, { width: 16, children: /* @__PURE__ */ jsx9(Text10, { bold: true, color: "#888888", children: "\u5F53\u524D\u4EF7" }) }),
3315
- /* @__PURE__ */ jsx9(Box9, { children: /* @__PURE__ */ jsxs9(Text10, { bold: true, color: colorCode, children: [
3527
+ /* @__PURE__ */ jsxs11(Box11, { children: [
3528
+ /* @__PURE__ */ jsx11(Box11, { width: 16, children: /* @__PURE__ */ jsx11(Text12, { bold: true, color: "#888888", children: "\u5F53\u524D\u4EF7" }) }),
3529
+ /* @__PURE__ */ jsx11(Box11, { children: /* @__PURE__ */ jsxs11(Text12, { bold: true, color: colorCode, children: [
3316
3530
  arrow,
3317
3531
  " ",
3318
3532
  formatPrice(stock.price)
3319
3533
  ] }) })
3320
3534
  ] }),
3321
- /* @__PURE__ */ jsxs9(Box9, { children: [
3322
- /* @__PURE__ */ jsx9(Box9, { width: 16, children: /* @__PURE__ */ jsx9(Text10, { color: "#888888", children: "\u6DA8\u8DCC\u5E45" }) }),
3323
- /* @__PURE__ */ jsx9(Box9, { children: /* @__PURE__ */ jsxs9(Text10, { color: colorCode, children: [
3535
+ /* @__PURE__ */ jsxs11(Box11, { children: [
3536
+ /* @__PURE__ */ jsx11(Box11, { width: 16, children: /* @__PURE__ */ jsx11(Text12, { color: "#888888", children: "\u6DA8\u8DCC\u5E45" }) }),
3537
+ /* @__PURE__ */ jsx11(Box11, { children: /* @__PURE__ */ jsxs11(Text12, { color: colorCode, children: [
3324
3538
  isUp ? "+" : "",
3325
3539
  stock.changePercent.toFixed(2),
3326
3540
  "%",
@@ -3329,13 +3543,93 @@ function renderDetail(stock, _onBack, prices, countdown = 10, currentTime) {
3329
3543
  stock.changeAmount.toFixed(3)
3330
3544
  ] }) })
3331
3545
  ] }),
3332
- chartLines.length > 0 && /* @__PURE__ */ jsx9(Box9, { marginTop: 1, flexDirection: "column", children: chartLines.map((line, i) => /* @__PURE__ */ jsx9(Box9, { children: /* @__PURE__ */ jsx9(Text10, { color: colorCode, children: line || " " }) }, i)) }),
3333
- /* @__PURE__ */ jsx9(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx9(Text10, { dimColor: true, children: " Space/q \u8FD4\u56DE\u5217\u8868" }) })
3546
+ chartLines.length > 0 && /* @__PURE__ */ jsx11(Box11, { marginTop: 1, flexDirection: "column", children: chartLines.map((line, i) => /* @__PURE__ */ jsx11(Box11, { children: /* @__PURE__ */ jsx11(Text12, { color: colorCode, children: line || " " }) }, i)) }),
3547
+ /* @__PURE__ */ jsx11(Box11, { marginTop: 1, children: /* @__PURE__ */ jsx11(Text12, { dimColor: true, children: " Space/q \u8FD4\u56DE\u5217\u8868" }) })
3334
3548
  ] });
3335
3549
  }
3336
3550
 
3551
+ // src/utils/scan-files.ts
3552
+ import { readdir as readdir2 } from "fs/promises";
3553
+ import { join as join4, relative } from "path";
3554
+ var IGNORE_DIRS = /* @__PURE__ */ new Set([
3555
+ "node_modules",
3556
+ ".git",
3557
+ ".svn",
3558
+ ".hg",
3559
+ ".dskcode",
3560
+ ".claude",
3561
+ "dist",
3562
+ "build",
3563
+ ".next",
3564
+ ".turbo",
3565
+ ".nx",
3566
+ "coverage",
3567
+ ".cache",
3568
+ ".nyc_output",
3569
+ ".vscode",
3570
+ ".idea",
3571
+ "__pycache__",
3572
+ ".venv",
3573
+ "venv",
3574
+ ".tox",
3575
+ "target",
3576
+ "vendor",
3577
+ "bower_components",
3578
+ "jspm_packages"
3579
+ ]);
3580
+ var SOURCE_EXTS = /* @__PURE__ */ new Set([
3581
+ ".ts",
3582
+ ".tsx",
3583
+ ".js",
3584
+ ".jsx",
3585
+ ".mjs",
3586
+ ".cjs",
3587
+ ".vue",
3588
+ ".svelte",
3589
+ ".astro",
3590
+ ".css",
3591
+ ".scss",
3592
+ ".less",
3593
+ ".html",
3594
+ ".json",
3595
+ ".md",
3596
+ ".yaml",
3597
+ ".yml",
3598
+ ".toml"
3599
+ ]);
3600
+ async function scanProjectFiles(baseDir, dir) {
3601
+ const currentDir = dir ?? baseDir;
3602
+ let entries;
3603
+ try {
3604
+ entries = await readdir2(currentDir, { withFileTypes: true });
3605
+ } catch {
3606
+ return [];
3607
+ }
3608
+ const files = [];
3609
+ const dirs = [];
3610
+ for (const entry of entries) {
3611
+ const name = entry.name;
3612
+ if (IGNORE_DIRS.has(name) || name.startsWith(".")) continue;
3613
+ if (entry.isDirectory()) {
3614
+ dirs.push(name);
3615
+ } else if (entry.isFile()) {
3616
+ const ext = name.slice(name.lastIndexOf(".")).toLowerCase();
3617
+ if (SOURCE_EXTS.has(ext)) {
3618
+ files.push(relative(baseDir, join4(currentDir, name)));
3619
+ }
3620
+ }
3621
+ }
3622
+ const nested = await Promise.all(
3623
+ dirs.map((d) => scanProjectFiles(baseDir, join4(currentDir, d)))
3624
+ );
3625
+ for (const n of nested) {
3626
+ files.push(...n);
3627
+ }
3628
+ return files;
3629
+ }
3630
+
3337
3631
  // src/cli/index.tsx
3338
- import { jsx as jsx10 } from "react/jsx-runtime";
3632
+ import { jsx as jsx12 } from "react/jsx-runtime";
3339
3633
  var SUBCOMMANDS = ["chat", "run", "setup", "init", "completion", "game", "stock"];
3340
3634
  function createCli() {
3341
3635
  const program2 = new Command();
@@ -3369,9 +3663,11 @@ function createCli() {
3369
3663
  startChat(ctx, costTracker);
3370
3664
  });
3371
3665
  async function startChat(ctx, costTracker) {
3372
- const [globalSkillCount, localSkillCount] = await Promise.all([
3666
+ const [globalSkillCount, localSkillCount, skills, files] = await Promise.all([
3373
3667
  countDskcodeSkills(),
3374
- countProjectLocalSkills(process.cwd())
3668
+ countProjectLocalSkills(process.cwd()),
3669
+ getAllSkills(process.cwd()),
3670
+ scanProjectFiles(process.cwd())
3375
3671
  ]);
3376
3672
  const skillCount = globalSkillCount + localSkillCount;
3377
3673
  const defaultProvider = ctx?.config.providers.find(
@@ -3379,10 +3675,12 @@ function createCli() {
3379
3675
  );
3380
3676
  const model = defaultProvider?.model ?? "deepseek-v4-flash";
3381
3677
  const chatApp = renderApp(
3382
- /* @__PURE__ */ jsx10(
3678
+ /* @__PURE__ */ jsx12(
3383
3679
  ChatSession,
3384
3680
  {
3385
3681
  skillCount,
3682
+ skills,
3683
+ files,
3386
3684
  toolCount: ctx?.config.tools.length ?? 0,
3387
3685
  verbose: ctx?.verbose ?? false,
3388
3686
  apiKey: defaultProvider?.apiKey,
@@ -3395,7 +3693,7 @@ function createCli() {
3395
3693
  initGames();
3396
3694
  const games = listGames();
3397
3695
  const { unmount } = render4(
3398
- /* @__PURE__ */ jsx10(
3696
+ /* @__PURE__ */ jsx12(
3399
3697
  GamePicker,
3400
3698
  {
3401
3699
  games,
@@ -3419,7 +3717,7 @@ function createCli() {
3419
3717
  setImmediate(() => {
3420
3718
  const defaultStockCodes = ctx?.config.stock?.symbols?.map((s) => s.code) ?? ["sh000001", "sz399006", "sh601688"];
3421
3719
  const stockApp = renderApp(
3422
- /* @__PURE__ */ jsx10(
3720
+ /* @__PURE__ */ jsx12(
3423
3721
  StockList,
3424
3722
  {
3425
3723
  codes: defaultStockCodes,
@@ -3483,10 +3781,10 @@ compdef _dskcode_completion dskcode`);
3483
3781
  program2.command("stock").description("\u67E5\u770B\u81EA\u9009\u80A1\u5B9E\u65F6\u884C\u60C5").argument("[codes...]", "\u80A1\u7968\u4EE3\u7801\uFF08\u7A7A\u683C\u5206\u9694\uFF09\uFF0C\u5982 513090 600519").action(async function(codes) {
3484
3782
  const ctx = this.dskcodeCtx;
3485
3783
  const home = process.env.HOME ?? process.env.USERPROFILE ?? "~";
3486
- const globalConfigPath = join4(home, ".dskcode", "settings.json");
3784
+ const globalConfigPath = join5(home, ".dskcode", "settings.json");
3487
3785
  let globalConfigHasStock = false;
3488
3786
  try {
3489
- const raw = await readFile3(globalConfigPath, "utf-8");
3787
+ const raw = await readFile4(globalConfigPath, "utf-8");
3490
3788
  const parsed = JSON.parse(raw);
3491
3789
  const stock = parsed.stock;
3492
3790
  globalConfigHasStock = Array.isArray(stock?.symbols) && stock.symbols.length > 0;
@@ -3506,7 +3804,7 @@ compdef _dskcode_completion dskcode`);
3506
3804
  const freshResult = await loadAndValidate();
3507
3805
  const codeList = codes && codes.length > 0 ? codes : freshResult.config.stock?.symbols?.map((s) => s.code) ?? ["sh000001", "sz399006", "sh601688"];
3508
3806
  const app = renderApp(
3509
- /* @__PURE__ */ jsx10(
3807
+ /* @__PURE__ */ jsx12(
3510
3808
  StockList,
3511
3809
  {
3512
3810
  codes: codeList,
@@ -3535,7 +3833,7 @@ compdef _dskcode_completion dskcode`);
3535
3833
  }
3536
3834
  const selectedGame = await new Promise((resolve) => {
3537
3835
  const { unmount } = render4(
3538
- /* @__PURE__ */ jsx10(
3836
+ /* @__PURE__ */ jsx12(
3539
3837
  GamePicker,
3540
3838
  {
3541
3839
  games,