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.
- package/dist/index.js +244 -111
- 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
|
|
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(
|
|
1443
|
-
|
|
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
|
-
|
|
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 === "
|
|
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.
|
|
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();
|