shenxiang-ai-cli 0.3.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +244 -111
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -255,6 +255,7 @@ var OpenAICompatibleProvider = class {
255
255
  const delta = choice.delta || {};
256
256
  if (delta.reasoning_content) {
257
257
  reasoningContent += delta.reasoning_content;
258
+ yield { type: "thinking", content: delta.reasoning_content };
258
259
  }
259
260
  if (delta.content) {
260
261
  yield { type: "text", content: delta.content };
@@ -695,6 +696,160 @@ ${sorted.map((f) => ` ${f}`).join("\n")}`;
695
696
  // src/core/tools/file-write.ts
696
697
  import fs2 from "fs/promises";
697
698
  import path2 from "path";
699
+
700
+ // src/ui/renderer.ts
701
+ import { Marked } from "marked";
702
+ import { markedTerminal } from "marked-terminal";
703
+ import chalk2 from "chalk";
704
+
705
+ // src/ui/theme.ts
706
+ import chalk from "chalk";
707
+ var theme = {
708
+ // Brand colors
709
+ brand: chalk.hex("#A78BFA"),
710
+ brandBold: chalk.hex("#A78BFA").bold,
711
+ brandDim: chalk.hex("#7C3AED"),
712
+ // Status
713
+ success: chalk.hex("#34D399"),
714
+ error: chalk.hex("#F87171"),
715
+ warning: chalk.hex("#FBBF24"),
716
+ info: chalk.hex("#60A5FA"),
717
+ // Text
718
+ dim: chalk.gray,
719
+ bold: chalk.bold,
720
+ italic: chalk.italic,
721
+ muted: chalk.hex("#6B7280"),
722
+ // Code
723
+ code: chalk.bgHex("#1F2937").hex("#E5E7EB"),
724
+ filePath: chalk.underline.hex("#60A5FA"),
725
+ // Roles
726
+ user: chalk.hex("#34D399").bold,
727
+ assistant: chalk.hex("#A78BFA").bold,
728
+ system: chalk.gray,
729
+ tool: chalk.hex("#FBBF24"),
730
+ // Token stats
731
+ tokenLabel: chalk.hex("#6B7280"),
732
+ tokenValue: chalk.hex("#A78BFA")
733
+ };
734
+ function banner() {
735
+ const p = theme.brand;
736
+ const b = theme.brandBold;
737
+ const d = theme.dim;
738
+ const m = theme.muted;
739
+ const y = chalk.hex("#FBBF24");
740
+ const r = chalk.hex("#F87171");
741
+ const w = chalk.white.bold;
742
+ const lines = [
743
+ ``,
744
+ ` ${p("/\\_/\\")} ${b("\u6C88\u7FD4\u7684AI\u52A9\u624B")} ${m("v0.4.0")}`,
745
+ ` ${p("(")} ${y("o")}${p(".")}${y("o")} ${p(")")} ${d("\u7EC8\u7AEF\u91CC\u7684AI\u5168\u6808\u5F00\u53D1\u642D\u6863")}`,
746
+ ` ${p("> ")}${r("^")}${p(" <")}`,
747
+ ` ${p("/|")}${p(" |")}${p("\\")} ${d("\u4F60\u7684\u7F16\u7A0B\u597D\u4F19\u4F34")} ${chalk.hex("#A78BFA")("\u{1F43E}")}`,
748
+ ` ${p("(_| |_)")}`
749
+ ];
750
+ return lines.join("\n");
751
+ }
752
+ function separator() {
753
+ return theme.dim("\u2500".repeat(40));
754
+ }
755
+
756
+ // src/ui/renderer.ts
757
+ var marked = new Marked(markedTerminal());
758
+ function streamChunk(text) {
759
+ process.stdout.write(text);
760
+ }
761
+ function streamThinking(text) {
762
+ process.stdout.write(theme.dim(text));
763
+ }
764
+ function printColoredDiff(oldContent, newContent, filepath) {
765
+ const oldLines = oldContent.split("\n");
766
+ const newLines = newContent.split("\n");
767
+ const maxLines = Math.max(oldLines.length, newLines.length);
768
+ const diffLines = [];
769
+ let additions = 0;
770
+ let deletions = 0;
771
+ let prefixLen = 0;
772
+ while (prefixLen < Math.min(oldLines.length, newLines.length) && oldLines[prefixLen] === newLines[prefixLen]) {
773
+ prefixLen++;
774
+ }
775
+ let suffixLen = 0;
776
+ while (suffixLen < Math.min(oldLines.length - prefixLen, newLines.length - prefixLen) && oldLines[oldLines.length - 1 - suffixLen] === newLines[newLines.length - 1 - suffixLen]) {
777
+ suffixLen++;
778
+ }
779
+ const oldStart = prefixLen;
780
+ const oldEnd = oldLines.length - suffixLen;
781
+ const newStart = prefixLen;
782
+ const newEnd = newLines.length - suffixLen;
783
+ const contextStart = Math.max(0, prefixLen - 2);
784
+ for (let i = contextStart; i < prefixLen; i++) {
785
+ diffLines.push(theme.dim(` ${String(i + 1).padStart(4)} ${oldLines[i]}`));
786
+ }
787
+ for (let i = oldStart; i < oldEnd; i++) {
788
+ diffLines.push(chalk2.red(` ${String(i + 1).padStart(4)} - ${oldLines[i]}`));
789
+ deletions++;
790
+ }
791
+ for (let i = newStart; i < newEnd; i++) {
792
+ diffLines.push(chalk2.green(` ${String(i + 1).padStart(4)} + ${newLines[i]}`));
793
+ additions++;
794
+ }
795
+ const contextEnd = Math.min(newLines.length, newEnd + 2);
796
+ for (let i = newEnd; i < contextEnd; i++) {
797
+ diffLines.push(theme.dim(` ${String(i + 1).padStart(4)} ${newLines[i]}`));
798
+ }
799
+ const maxDiffLines = 30;
800
+ if (diffLines.length > maxDiffLines) {
801
+ const shown = diffLines.slice(0, maxDiffLines);
802
+ shown.push(theme.dim(` ... ${diffLines.length - maxDiffLines} more lines`));
803
+ console.log(shown.join("\n"));
804
+ } else if (diffLines.length > 0) {
805
+ console.log(diffLines.join("\n"));
806
+ }
807
+ console.log(
808
+ ` ${theme.filePath(filepath)} ` + chalk2.green(`+${additions}`) + " " + chalk2.red(`-${deletions}`) + " lines"
809
+ );
810
+ }
811
+ function printToolCall(name, description) {
812
+ console.log(theme.tool(` \u25B8 ${description}`));
813
+ }
814
+ function printToolResult(result, truncate = 500) {
815
+ const display = result.length > truncate ? result.substring(0, truncate) + theme.dim(`
816
+ ... (${result.length} \u5B57\u7B26)`) : result;
817
+ const indented = display.split("\n").map((l) => " " + l).join("\n");
818
+ console.log(theme.dim(indented));
819
+ }
820
+ function printTokenUsage(usage, durationMs) {
821
+ const parts = [];
822
+ parts.push(theme.tokenLabel(" tokens: "));
823
+ parts.push(theme.tokenValue(`\u2191${usage.promptTokens}`));
824
+ parts.push(theme.tokenLabel(" + "));
825
+ parts.push(theme.tokenValue(`\u2193${usage.completionTokens}`));
826
+ parts.push(theme.tokenLabel(" = "));
827
+ parts.push(theme.brandBold(`${usage.totalTokens}`));
828
+ if (durationMs && durationMs > 0) {
829
+ const seconds = (durationMs / 1e3).toFixed(1);
830
+ const tokPerSec = usage.completionTokens > 0 ? (usage.completionTokens / (durationMs / 1e3)).toFixed(0) : "0";
831
+ parts.push(theme.tokenLabel(` \u23F1 ${seconds}s`));
832
+ parts.push(theme.tokenLabel(` (${tokPerSec} tok/s)`));
833
+ }
834
+ console.log(parts.join(""));
835
+ }
836
+ function printError(message) {
837
+ console.log(theme.error(` \u2717 ${message}`));
838
+ }
839
+ function printSuccess(message) {
840
+ console.log(theme.success(` \u2713 ${message}`));
841
+ }
842
+ function printInfo(message) {
843
+ console.log(theme.info(` \u2139 ${message}`));
844
+ }
845
+ function printWarning(message) {
846
+ console.log(theme.warning(` \u26A0 ${message}`));
847
+ }
848
+ function printSeparator() {
849
+ console.log(separator());
850
+ }
851
+
852
+ // src/core/tools/file-write.ts
698
853
  var writeFileTool = {
699
854
  definition: {
700
855
  name: "write_file",
@@ -717,12 +872,25 @@ var writeFileTool = {
717
872
  handler: async (args) => {
718
873
  try {
719
874
  const filePath = path2.resolve(process.cwd(), args.path);
875
+ let isNew = true;
876
+ let oldContent = "";
877
+ try {
878
+ oldContent = await fs2.readFile(filePath, "utf-8");
879
+ isNew = false;
880
+ } catch {
881
+ }
720
882
  await fs2.mkdir(path2.dirname(filePath), { recursive: true });
721
883
  await fs2.writeFile(filePath, args.content, "utf-8");
722
884
  const lines = args.content.split("\n").length;
885
+ if (!isNew && oldContent) {
886
+ try {
887
+ printColoredDiff(oldContent, args.content, args.path);
888
+ } catch {
889
+ }
890
+ }
723
891
  return {
724
892
  success: true,
725
- output: `File written: ${args.path} (${lines} lines)`
893
+ output: isNew ? `File created: ${args.path} (${lines} lines)` : `File overwritten: ${args.path} (${lines} lines)`
726
894
  };
727
895
  } catch (err) {
728
896
  const msg = err instanceof Error ? err.message : String(err);
@@ -777,6 +945,10 @@ var editFileTool = {
777
945
  }
778
946
  const newContent = content.replace(oldStr, newStr);
779
947
  await fs2.writeFile(filePath, newContent, "utf-8");
948
+ try {
949
+ printColoredDiff(content, newContent, args.path);
950
+ } catch {
951
+ }
780
952
  const addedLines = newStr.split("\n").length;
781
953
  const removedLines = oldStr.split("\n").length;
782
954
  return {
@@ -1137,107 +1309,6 @@ var gitLogTool = {
1137
1309
  requiresConfirmation: false
1138
1310
  };
1139
1311
 
1140
- // src/ui/renderer.ts
1141
- import { Marked } from "marked";
1142
- import { markedTerminal } from "marked-terminal";
1143
-
1144
- // src/ui/theme.ts
1145
- import chalk from "chalk";
1146
- var theme = {
1147
- // Brand colors
1148
- brand: chalk.hex("#A78BFA"),
1149
- brandBold: chalk.hex("#A78BFA").bold,
1150
- brandDim: chalk.hex("#7C3AED"),
1151
- // Status
1152
- success: chalk.hex("#34D399"),
1153
- error: chalk.hex("#F87171"),
1154
- warning: chalk.hex("#FBBF24"),
1155
- info: chalk.hex("#60A5FA"),
1156
- // Text
1157
- dim: chalk.gray,
1158
- bold: chalk.bold,
1159
- italic: chalk.italic,
1160
- muted: chalk.hex("#6B7280"),
1161
- // Code
1162
- code: chalk.bgHex("#1F2937").hex("#E5E7EB"),
1163
- filePath: chalk.underline.hex("#60A5FA"),
1164
- // Roles
1165
- user: chalk.hex("#34D399").bold,
1166
- assistant: chalk.hex("#A78BFA").bold,
1167
- system: chalk.gray,
1168
- tool: chalk.hex("#FBBF24"),
1169
- // Token stats
1170
- tokenLabel: chalk.hex("#6B7280"),
1171
- tokenValue: chalk.hex("#A78BFA")
1172
- };
1173
- function banner() {
1174
- const p = theme.brand;
1175
- const b = theme.brandBold;
1176
- const d = theme.dim;
1177
- const m = theme.muted;
1178
- const y = chalk.hex("#FBBF24");
1179
- const r = chalk.hex("#F87171");
1180
- const w = chalk.white.bold;
1181
- const lines = [
1182
- ``,
1183
- ` ${p("/\\_/\\")} ${b("\u6C88\u7FD4\u7684AI\u52A9\u624B")} ${m("v0.3.2")}`,
1184
- ` ${p("(")} ${y("o")}${p(".")}${y("o")} ${p(")")} ${d("\u7EC8\u7AEF\u91CC\u7684AI\u5168\u6808\u5F00\u53D1\u642D\u6863")}`,
1185
- ` ${p("> ")}${r("^")}${p(" <")}`,
1186
- ` ${p("/|")}${p(" |")}${p("\\")} ${d("\u4F60\u7684\u7F16\u7A0B\u597D\u4F19\u4F34")} ${chalk.hex("#A78BFA")("\u{1F43E}")}`,
1187
- ` ${p("(_| |_)")}`
1188
- ];
1189
- return lines.join("\n");
1190
- }
1191
- function separator() {
1192
- return theme.dim("\u2500".repeat(40));
1193
- }
1194
-
1195
- // src/ui/renderer.ts
1196
- var marked = new Marked(markedTerminal());
1197
- function streamChunk(text) {
1198
- process.stdout.write(text);
1199
- }
1200
- function printToolCall(name, description) {
1201
- console.log(theme.tool(` \u25B8 ${description}`));
1202
- }
1203
- function printToolResult(result, truncate = 500) {
1204
- const display = result.length > truncate ? result.substring(0, truncate) + theme.dim(`
1205
- ... (${result.length} \u5B57\u7B26)`) : result;
1206
- const indented = display.split("\n").map((l) => " " + l).join("\n");
1207
- console.log(theme.dim(indented));
1208
- }
1209
- function printTokenUsage(usage, durationMs) {
1210
- const parts = [];
1211
- parts.push(theme.tokenLabel(" tokens: "));
1212
- parts.push(theme.tokenValue(`\u2191${usage.promptTokens}`));
1213
- parts.push(theme.tokenLabel(" + "));
1214
- parts.push(theme.tokenValue(`\u2193${usage.completionTokens}`));
1215
- parts.push(theme.tokenLabel(" = "));
1216
- parts.push(theme.brandBold(`${usage.totalTokens}`));
1217
- if (durationMs && durationMs > 0) {
1218
- const seconds = (durationMs / 1e3).toFixed(1);
1219
- const tokPerSec = usage.completionTokens > 0 ? (usage.completionTokens / (durationMs / 1e3)).toFixed(0) : "0";
1220
- parts.push(theme.tokenLabel(` \u23F1 ${seconds}s`));
1221
- parts.push(theme.tokenLabel(` (${tokPerSec} tok/s)`));
1222
- }
1223
- console.log(parts.join(""));
1224
- }
1225
- function printError(message) {
1226
- console.log(theme.error(` \u2717 ${message}`));
1227
- }
1228
- function printSuccess(message) {
1229
- console.log(theme.success(` \u2713 ${message}`));
1230
- }
1231
- function printInfo(message) {
1232
- console.log(theme.info(` \u2139 ${message}`));
1233
- }
1234
- function printWarning(message) {
1235
- console.log(theme.warning(` \u26A0 ${message}`));
1236
- }
1237
- function printSeparator() {
1238
- console.log(separator());
1239
- }
1240
-
1241
1312
  // src/i18n/zh.ts
1242
1313
  var zh = {
1243
1314
  welcome: "\u6B22\u8FCE\u4F7F\u7528\u6C88\u7FD4\u7684AI\u52A9\u624B \u2014 \u4F60\u7684AI\u5168\u6808\u5F00\u53D1\u642D\u6863",
@@ -1410,6 +1481,13 @@ async function askQuestion(prompt) {
1410
1481
 
1411
1482
  // src/core/tools/index.ts
1412
1483
  var toolRegistry = /* @__PURE__ */ new Map();
1484
+ var _yoloMode = false;
1485
+ function setYoloMode(enabled) {
1486
+ _yoloMode = enabled;
1487
+ }
1488
+ function isYoloMode() {
1489
+ return _yoloMode;
1490
+ }
1413
1491
  function registerAllTools() {
1414
1492
  const tools = [
1415
1493
  readFileTool,
@@ -1439,8 +1517,9 @@ async function confirmExecution(toolName, args) {
1439
1517
  else if (toolName === "delete_file") description = `\u5220\u9664\u6587\u4EF6: ${args.path}`;
1440
1518
  else if (toolName === "git_commit") description = `Git\u63D0\u4EA4: ${args.message}`;
1441
1519
  const answer = await askQuestion(` \u26A1 ${description}
1442
- \u5141\u8BB8\u6267\u884C\uFF1F(y/n) `);
1443
- return answer.toLowerCase() === "y" || answer.toLowerCase() === "yes";
1520
+ \u5141\u8BB8\u6267\u884C\uFF1F(Y/n) `);
1521
+ const a = answer.toLowerCase().trim();
1522
+ return a === "" || a === "y" || a === "yes";
1444
1523
  }
1445
1524
  async function executeTool(name, args, autoConfirm = false) {
1446
1525
  const tool = toolRegistry.get(name);
@@ -1461,7 +1540,8 @@ async function executeTool(name, args, autoConfirm = false) {
1461
1540
  git_log: "\u{1F4DC} \u67E5\u770BGit\u65E5\u5FD7"
1462
1541
  };
1463
1542
  printToolCall(name, descMap[name] || name);
1464
- if (tool.requiresConfirmation && !autoConfirm) {
1543
+ const shouldConfirm = tool.requiresConfirmation && !autoConfirm && !_yoloMode;
1544
+ if (shouldConfirm) {
1465
1545
  const confirmed = await confirmExecution(name, args);
1466
1546
  if (!confirmed) {
1467
1547
  return { success: false, output: "", error: "User declined execution." };
@@ -1550,6 +1630,20 @@ async function buildProjectContext(rootDir) {
1550
1630
  } catch {
1551
1631
  }
1552
1632
  ctx.structure = await buildStructureTree(rootDir);
1633
+ try {
1634
+ const memoryPaths = ["SXAI.md", ".sxai.md", "sxai.md"];
1635
+ for (const mp of memoryPaths) {
1636
+ try {
1637
+ const content = await fs4.readFile(path4.join(rootDir, mp), "utf-8");
1638
+ if (content.trim()) {
1639
+ ctx.projectMemory = content.trim();
1640
+ break;
1641
+ }
1642
+ } catch {
1643
+ }
1644
+ }
1645
+ } catch {
1646
+ }
1553
1647
  return ctx;
1554
1648
  }
1555
1649
  async function buildStructureTree(rootDir, maxDepth = 2) {
@@ -1612,6 +1706,11 @@ ${ctx.structure}`);
1612
1706
  [\u5DE5\u5177] \u4F60\u6709\u6587\u4EF6\u8BFB\u5199(read_file/write_file/edit_file/delete_file)\u3001\u76EE\u5F55(list_files)\u3001\u641C\u7D22(search_code)\u3001\u547D\u4EE4(run_command)\u3001Git(git_status/git_diff/git_commit/git_log)\u7B49\u5DE5\u5177\u3002\u5411\u7528\u6237\u63CF\u8FF0\u64CD\u4F5C\u65F6\u7528\u81EA\u7136\u8BED\u8A00\uFF0C\u4E0D\u66B4\u9732\u5DE5\u5177\u51FD\u6570\u540D\u3002`);
1613
1707
  parts.push(`
1614
1708
  [\u683C\u5F0F] Markdown\u56DE\u590D\uFF0C\u4EE3\u7801\u5757\u6807\u6CE8\u8BED\u8A00\uFF0C\u64CD\u4F5C\u524D\u89E3\u91CA\u539F\u56E0\uFF0C\u5B8C\u6210\u540E\u7B80\u8981\u603B\u7ED3\u3002\u9996\u6B21\u5BF9\u8BDD\u4ECB\u7ECD\u81EA\u5DF1\u5E76\u8BE2\u95EE\u9700\u6C42\u3002`);
1709
+ if (ctx.projectMemory) {
1710
+ parts.push(`
1711
+ [\u9879\u76EE\u6307\u4EE4 - \u6765\u81EA SXAI.md\uFF0C\u8BF7\u4E25\u683C\u9075\u5B88]
1712
+ ${ctx.projectMemory}`);
1713
+ }
1615
1714
  return parts.join("\n");
1616
1715
  }
1617
1716
  function getFrameworkGuide(framework) {
@@ -1775,13 +1874,16 @@ var Agent = class {
1775
1874
  const spinner = ora({ text: t("thinking"), spinner: "dots" }).start();
1776
1875
  let spinnerStopped = false;
1777
1876
  let hasTextOutput = false;
1877
+ let hasThinkingOutput = false;
1778
1878
  let toolSpinnerStarted = false;
1779
1879
  try {
1780
1880
  for await (const chunk of provider.chatStream(this.messages, this.tools, config3)) {
1781
- if (!spinnerStopped && (chunk.type === "text" || chunk.type === "tool_call")) {
1881
+ if (!spinnerStopped && (chunk.type === "text" || chunk.type === "tool_call" || chunk.type === "thinking")) {
1782
1882
  spinner.stop();
1783
1883
  spinnerStopped = true;
1784
- if (chunk.type === "text") {
1884
+ if (chunk.type === "thinking") {
1885
+ process.stdout.write("\n");
1886
+ } else if (chunk.type === "text") {
1785
1887
  process.stdout.write("\n");
1786
1888
  }
1787
1889
  if (chunk.type === "tool_call" && !hasTextOutput) {
@@ -1791,7 +1893,17 @@ var Agent = class {
1791
1893
  }
1792
1894
  }
1793
1895
  switch (chunk.type) {
1896
+ case "thinking":
1897
+ if (!hasThinkingOutput) {
1898
+ hasThinkingOutput = true;
1899
+ streamThinking("\u{1F4AD} ");
1900
+ }
1901
+ streamThinking(chunk.content || "");
1902
+ break;
1794
1903
  case "text":
1904
+ if (hasThinkingOutput && !hasTextOutput) {
1905
+ process.stdout.write("\n\n");
1906
+ }
1795
1907
  responseText += chunk.content || "";
1796
1908
  hasTextOutput = true;
1797
1909
  streamChunk(chunk.content || "");
@@ -1973,9 +2085,12 @@ var Agent = class {
1973
2085
  };
1974
2086
 
1975
2087
  // src/commands/chat.ts
1976
- async function chatCommand() {
2088
+ async function chatCommand(options = {}) {
1977
2089
  const config3 = getConfig();
1978
2090
  setLocale(config3.locale);
2091
+ if (options.yolo) {
2092
+ setYoloMode(true);
2093
+ }
1979
2094
  process.on("unhandledRejection", (reason) => {
1980
2095
  const msg = reason instanceof Error ? reason.message : String(reason);
1981
2096
  if (msg.includes("abort") || msg.includes("cancel") || msg.includes("ABORT")) return;
@@ -1987,6 +2102,9 @@ async function chatCommand() {
1987
2102
  \u26A0 \u672A\u6355\u83B7\u9519\u8BEF: ${err.message}`));
1988
2103
  });
1989
2104
  console.log(banner());
2105
+ if (isYoloMode()) {
2106
+ console.log(theme.warning(" \u26A1 \u81EA\u52A8\u6A21\u5F0F (YOLO) \u2014 \u6240\u6709\u64CD\u4F5C\u81EA\u52A8\u6267\u884C\uFF0C\u65E0\u9700\u786E\u8BA4"));
2107
+ }
1990
2108
  console.log(theme.dim(` ${t("exitHint")}`));
1991
2109
  const providerName = getProviderName(config3.model);
1992
2110
  const hasOwnKey = !!getProviderApiKey(providerName);
@@ -2022,6 +2140,9 @@ async function chatCommand() {
2022
2140
  }
2023
2141
  console.log(theme.dim(` \u9879\u76EE ${theme.info(parts.join(" \xB7 "))}`));
2024
2142
  }
2143
+ if (projectCtx?.projectMemory) {
2144
+ console.log(theme.dim(` \u{1F4CB} \u5DF2\u52A0\u8F7D SXAI.md \u9879\u76EE\u6307\u4EE4`));
2145
+ }
2025
2146
  printSeparator();
2026
2147
  console.log();
2027
2148
  } catch (err) {
@@ -2142,6 +2263,7 @@ async function handleSlashCommand(input, agent) {
2142
2263
  \u53EF\u7528\u547D\u4EE4:
2143
2264
  /help \u663E\u793A\u5E2E\u52A9
2144
2265
  /model \u67E5\u770B/\u5207\u6362\u6A21\u578B
2266
+ /auto \u5207\u6362\u81EA\u52A8\u6A21\u5F0F\uFF08\u8DF3\u8FC7\u786E\u8BA4\uFF09
2145
2267
  /clear \u6E05\u9664\u5BF9\u8BDD\u5386\u53F2
2146
2268
  /account \u67E5\u770B\u8D26\u6237\u4FE1\u606F
2147
2269
  /status \u67E5\u770B\u9879\u76EE\u4FE1\u606F
@@ -2150,6 +2272,17 @@ async function handleSlashCommand(input, agent) {
2150
2272
  /exit \u9000\u51FA\u7A0B\u5E8F
2151
2273
  `);
2152
2274
  break;
2275
+ case "/auto":
2276
+ case "/yolo": {
2277
+ const newState = !isYoloMode();
2278
+ setYoloMode(newState);
2279
+ if (newState) {
2280
+ printWarning("\u26A1 \u81EA\u52A8\u6A21\u5F0F\u5DF2\u5F00\u542F \u2014 \u6240\u6709\u64CD\u4F5C\u5C06\u81EA\u52A8\u6267\u884C\uFF0C\u65E0\u9700\u786E\u8BA4");
2281
+ } else {
2282
+ printSuccess("\u81EA\u52A8\u6A21\u5F0F\u5DF2\u5173\u95ED \u2014 \u5371\u9669\u64CD\u4F5C\u5C06\u518D\u6B21\u8BF7\u6C42\u786E\u8BA4");
2283
+ }
2284
+ break;
2285
+ }
2153
2286
  case "/clear":
2154
2287
  agent.clearHistory();
2155
2288
  printSuccess("\u5BF9\u8BDD\u5386\u53F2\u5DF2\u6E05\u9664\u3002");
@@ -2945,12 +3078,12 @@ function fmtTokens3(n) {
2945
3078
  var program = new Command();
2946
3079
  var config2 = getConfig();
2947
3080
  setLocale(config2.locale);
2948
- program.name("sxai").description(t("description")).version("0.1.0");
2949
- program.command("chat", { isDefault: true }).description("\u542F\u52A8\u4EA4\u4E92\u5F0FAI\u5BF9\u8BDD\uFF08\u9ED8\u8BA4\u547D\u4EE4\uFF09").option("-m, --model <model>", "\u6307\u5B9AAI\u6A21\u578B", config2.model).action(async (options) => {
3081
+ program.name("sxai").description(t("description")).version("0.4.0");
3082
+ program.command("chat", { isDefault: true }).description("\u542F\u52A8\u4EA4\u4E92\u5F0FAI\u5BF9\u8BDD\uFF08\u9ED8\u8BA4\u547D\u4EE4\uFF09").option("-m, --model <model>", "\u6307\u5B9AAI\u6A21\u578B", config2.model).option("-y, --yolo", "\u81EA\u52A8\u6A21\u5F0F\uFF1A\u8DF3\u8FC7\u6240\u6709\u786E\u8BA4\uFF0C\u8BA9AI\u81EA\u4E3B\u6267\u884C").action(async (options) => {
2950
3083
  if (options.model && options.model !== config2.model) {
2951
3084
  setConfig("model", options.model);
2952
3085
  }
2953
- await chatCommand();
3086
+ await chatCommand({ yolo: !!options.yolo });
2954
3087
  });
2955
3088
  program.command("register").description("\u6CE8\u518C\u65B0\u8D26\u6237").action(async () => {
2956
3089
  await registerCommand();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shenxiang-ai-cli",
3
- "version": "0.3.2",
3
+ "version": "0.4.0",
4
4
  "description": "沈翔的AI助手 - 终端里的AI全栈开发搭档",
5
5
  "type": "module",
6
6
  "bin": {