dskcode 0.1.30 → 0.1.31
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/{chunk-UV4IWYHZ.js → chunk-LWOBXEMJ.js} +9 -9
- package/dist/{chunk-UV4IWYHZ.js.map → chunk-LWOBXEMJ.js.map} +1 -1
- package/dist/deepseek-WFSVA5UQ.js +9 -0
- package/dist/index.js +1661 -770
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/deepseek-PGX76BK5.js +0 -7
- /package/dist/{deepseek-PGX76BK5.js.map → deepseek-WFSVA5UQ.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
estimateTokens,
|
|
8
8
|
getModelMeta,
|
|
9
9
|
isSupportedModel
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-LWOBXEMJ.js";
|
|
11
11
|
|
|
12
12
|
// src/cli/index.tsx
|
|
13
13
|
import { Command } from "commander";
|
|
@@ -805,7 +805,7 @@ var LOGO_LINES = [
|
|
|
805
805
|
];
|
|
806
806
|
|
|
807
807
|
// src/ui/ChatSession.tsx
|
|
808
|
-
import { Box as
|
|
808
|
+
import { Box as Box10, Text as Text11, useInput, Static } from "ink";
|
|
809
809
|
import TextInput from "ink-text-input";
|
|
810
810
|
import { useEffect as useEffect4, useState as useState4, useCallback as useCallback2, useMemo, useRef as useRef3 } from "react";
|
|
811
811
|
|
|
@@ -838,7 +838,7 @@ function useDoubleCtrlC(onExit) {
|
|
|
838
838
|
}
|
|
839
839
|
|
|
840
840
|
// src/ui/ChatSession.tsx
|
|
841
|
-
import
|
|
841
|
+
import InkSpinner3 from "ink-spinner";
|
|
842
842
|
|
|
843
843
|
// src/ui/AssistantMessage.tsx
|
|
844
844
|
import { Box as Box5, Text as Text6 } from "ink";
|
|
@@ -1179,17 +1179,17 @@ function ToolCallBlock({ call, showPendingHint = true }) {
|
|
|
1179
1179
|
const argsDisplay = formatArgsSummary(call.arguments);
|
|
1180
1180
|
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", marginLeft: 3, marginTop: 1, children: [
|
|
1181
1181
|
/* @__PURE__ */ jsxs3(Box3, { children: [
|
|
1182
|
-
/* @__PURE__ */ jsxs3(Text4, {
|
|
1182
|
+
/* @__PURE__ */ jsxs3(Text4, { dimColor: true, children: [
|
|
1183
1183
|
"\u{1F4E6} ",
|
|
1184
1184
|
call.name
|
|
1185
1185
|
] }),
|
|
1186
|
-
/* @__PURE__ */ jsxs3(Text4, {
|
|
1186
|
+
/* @__PURE__ */ jsxs3(Text4, { dimColor: true, children: [
|
|
1187
1187
|
" ",
|
|
1188
1188
|
"\u2500".repeat(Math.max(1, 30 - call.name.length))
|
|
1189
1189
|
] })
|
|
1190
1190
|
] }),
|
|
1191
|
-
/* @__PURE__ */ jsx3(Box3, { flexDirection: "column", children: /* @__PURE__ */ jsx3(Text4, {
|
|
1192
|
-
showPendingHint && /* @__PURE__ */ jsx3(Box3, { children: /* @__PURE__ */ jsx3(Text4, {
|
|
1191
|
+
/* @__PURE__ */ jsx3(Box3, { flexDirection: "column", children: /* @__PURE__ */ jsx3(Text4, { dimColor: true, children: argsDisplay }) }),
|
|
1192
|
+
showPendingHint && /* @__PURE__ */ jsx3(Box3, { children: /* @__PURE__ */ jsx3(Text4, { dimColor: true, children: "\u23F3 \u7B49\u5F85\u6267\u884C" }) })
|
|
1193
1193
|
] });
|
|
1194
1194
|
}
|
|
1195
1195
|
|
|
@@ -1278,6 +1278,226 @@ function formatUsageSummary(usage) {
|
|
|
1278
1278
|
|
|
1279
1279
|
// src/ui/HighlightedText.tsx
|
|
1280
1280
|
import { Box as Box4, Text as Text5 } from "ink";
|
|
1281
|
+
|
|
1282
|
+
// src/ui/table-layout.ts
|
|
1283
|
+
var TABLE_MIN_COL_WIDTH = 3;
|
|
1284
|
+
var DEFAULT_TERM_WIDTH = 80;
|
|
1285
|
+
var TABLE_MARGIN = 2;
|
|
1286
|
+
function cpWidth(cp2) {
|
|
1287
|
+
if (cp2 >= 4352 && cp2 <= 4447 || // Hangul Jamo
|
|
1288
|
+
cp2 === 9001 || cp2 === 9002 || cp2 >= 11904 && cp2 <= 42191 || // CJK Radicals ~ Yi
|
|
1289
|
+
cp2 >= 43360 && cp2 <= 43391 || // Hangul Extended
|
|
1290
|
+
cp2 >= 44032 && cp2 <= 55215 || // Hangul Syllables
|
|
1291
|
+
cp2 >= 63744 && cp2 <= 64255 || // CJK Compat
|
|
1292
|
+
cp2 >= 65040 && cp2 <= 65055 || // Vertical forms
|
|
1293
|
+
cp2 >= 65281 && cp2 <= 65376 || // Fullwidth ASCII / 标点
|
|
1294
|
+
cp2 >= 65504 && cp2 <= 65510 || // Fullwidth signs
|
|
1295
|
+
cp2 >= 126976 && cp2 <= 131071 || // Emoji / Symbols
|
|
1296
|
+
cp2 >= 12288 && cp2 <= 12351 || // CJK Symbols & Punctuation(含「、。·」等)
|
|
1297
|
+
cp2 >= 131072 && cp2 <= 196607) {
|
|
1298
|
+
return 2;
|
|
1299
|
+
}
|
|
1300
|
+
if (cp2 < 32 || cp2 >= 127 && cp2 < 160) return 0;
|
|
1301
|
+
return 1;
|
|
1302
|
+
}
|
|
1303
|
+
function visualWidth(text) {
|
|
1304
|
+
let w = 0;
|
|
1305
|
+
for (const ch of text) {
|
|
1306
|
+
const cp2 = ch.codePointAt(0);
|
|
1307
|
+
if (cp2 === void 0) continue;
|
|
1308
|
+
if (cp2 === 8205) continue;
|
|
1309
|
+
if (cp2 >= 65024 && cp2 <= 65039) continue;
|
|
1310
|
+
w += cpWidth(cp2);
|
|
1311
|
+
}
|
|
1312
|
+
return w;
|
|
1313
|
+
}
|
|
1314
|
+
function* iterateChars(text) {
|
|
1315
|
+
for (const ch of text) {
|
|
1316
|
+
const cp2 = ch.codePointAt(0);
|
|
1317
|
+
if (cp2 === void 0) continue;
|
|
1318
|
+
if (cp2 === 8205) continue;
|
|
1319
|
+
if (cp2 >= 65024 && cp2 <= 65039) continue;
|
|
1320
|
+
yield { ch, width: cpWidth(cp2) };
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
1323
|
+
function wrapByWidth(text, maxWidth) {
|
|
1324
|
+
if (maxWidth <= 0) return [text];
|
|
1325
|
+
const out = [];
|
|
1326
|
+
for (const para of text.split("\n")) {
|
|
1327
|
+
if (para.length === 0) {
|
|
1328
|
+
out.push("");
|
|
1329
|
+
continue;
|
|
1330
|
+
}
|
|
1331
|
+
const wrapped = wrapOneLine(para, maxWidth);
|
|
1332
|
+
for (const w of wrapped) out.push(w);
|
|
1333
|
+
}
|
|
1334
|
+
return out.length === 0 ? [""] : out;
|
|
1335
|
+
}
|
|
1336
|
+
function wrapOneLine(text, maxWidth) {
|
|
1337
|
+
if (visualWidth(text) <= maxWidth) return [text];
|
|
1338
|
+
const lines = [];
|
|
1339
|
+
let current = "";
|
|
1340
|
+
let currentW = 0;
|
|
1341
|
+
let breakCandidate = -1;
|
|
1342
|
+
let breakCandidateW = 0;
|
|
1343
|
+
for (const { ch, width } of iterateChars(text)) {
|
|
1344
|
+
if (ch === " " || ch === " ") {
|
|
1345
|
+
breakCandidate = current.length;
|
|
1346
|
+
breakCandidateW = currentW + width;
|
|
1347
|
+
current += ch;
|
|
1348
|
+
currentW += width;
|
|
1349
|
+
continue;
|
|
1350
|
+
}
|
|
1351
|
+
if (currentW + width > maxWidth) {
|
|
1352
|
+
if (breakCandidate > 0) {
|
|
1353
|
+
const split = current.slice(0, breakCandidate).replace(/[ \t]+$/, "");
|
|
1354
|
+
lines.push(split);
|
|
1355
|
+
const rest = current.slice(breakCandidate).replace(/^[ \t]+/, "");
|
|
1356
|
+
current = rest + ch;
|
|
1357
|
+
currentW = visualWidth(current);
|
|
1358
|
+
breakCandidate = -1;
|
|
1359
|
+
breakCandidateW = 0;
|
|
1360
|
+
} else {
|
|
1361
|
+
lines.push(current);
|
|
1362
|
+
current = ch;
|
|
1363
|
+
currentW = width;
|
|
1364
|
+
}
|
|
1365
|
+
} else {
|
|
1366
|
+
current += ch;
|
|
1367
|
+
currentW += width;
|
|
1368
|
+
}
|
|
1369
|
+
}
|
|
1370
|
+
if (current.length > 0) lines.push(current);
|
|
1371
|
+
return lines;
|
|
1372
|
+
}
|
|
1373
|
+
function wrapRowCells(cells, colWidths, alignments) {
|
|
1374
|
+
return cells.map((cell, ci) => {
|
|
1375
|
+
const w = colWidths[ci] ?? TABLE_MIN_COL_WIDTH;
|
|
1376
|
+
const lines = wrapByWidth(cell, w);
|
|
1377
|
+
return lines.map((l) => padToWidth(l, w, alignments[ci] ?? "left"));
|
|
1378
|
+
});
|
|
1379
|
+
}
|
|
1380
|
+
function padToWidth(text, targetWidth, align = "left") {
|
|
1381
|
+
const vw = visualWidth(text);
|
|
1382
|
+
const delta = targetWidth - vw;
|
|
1383
|
+
if (delta <= 0) return text;
|
|
1384
|
+
const leftPad = align === "right" ? delta : align === "center" ? Math.floor(delta / 2) : 0;
|
|
1385
|
+
const rightPad = delta - leftPad;
|
|
1386
|
+
return " ".repeat(leftPad) + text + " ".repeat(rightPad);
|
|
1387
|
+
}
|
|
1388
|
+
function parseTableCells(line) {
|
|
1389
|
+
const t = line.trim();
|
|
1390
|
+
if (!t.startsWith("|") || !t.endsWith("|")) return [];
|
|
1391
|
+
const inner = t.slice(1, t.length - 1);
|
|
1392
|
+
return inner.split("|").map((c) => c.trim());
|
|
1393
|
+
}
|
|
1394
|
+
function parseAlignments(sepLine) {
|
|
1395
|
+
return parseTableCells(sepLine).map((c) => {
|
|
1396
|
+
const l = c.startsWith(":");
|
|
1397
|
+
const r = c.endsWith(":");
|
|
1398
|
+
if (l && r) return "center";
|
|
1399
|
+
if (r) return "right";
|
|
1400
|
+
return "left";
|
|
1401
|
+
});
|
|
1402
|
+
}
|
|
1403
|
+
function layoutTable(text, options = {}) {
|
|
1404
|
+
const termWidth = options.termWidth ?? DEFAULT_TERM_WIDTH;
|
|
1405
|
+
const outerMargin = options.outerMargin ?? 0;
|
|
1406
|
+
const usable = Math.max(termWidth - outerMargin, 20);
|
|
1407
|
+
const rawLines = text.split("\n").filter((l) => l.trim().length > 0);
|
|
1408
|
+
if (rawLines.length < 2) {
|
|
1409
|
+
return { lines: rawLines, colWidths: [], totalWidth: 0 };
|
|
1410
|
+
}
|
|
1411
|
+
let sepIdx = -1;
|
|
1412
|
+
for (let k = 0; k < rawLines.length; k++) {
|
|
1413
|
+
const t = (rawLines[k] ?? "").trim();
|
|
1414
|
+
if (/^\|[-: |]+\|$/.test(t) && t.includes("-")) {
|
|
1415
|
+
sepIdx = k;
|
|
1416
|
+
break;
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
if (sepIdx === -1) {
|
|
1420
|
+
return { lines: rawLines, colWidths: [], totalWidth: 0 };
|
|
1421
|
+
}
|
|
1422
|
+
const headerCells = parseTableCells(rawLines.slice(0, sepIdx).join(""));
|
|
1423
|
+
const alignments = parseAlignments(rawLines[sepIdx] ?? "");
|
|
1424
|
+
const dataRows = rawLines.slice(sepIdx + 1).map(parseTableCells);
|
|
1425
|
+
const colCount = headerCells.length;
|
|
1426
|
+
if (colCount === 0) {
|
|
1427
|
+
return { lines: rawLines, colWidths: [], totalWidth: 0 };
|
|
1428
|
+
}
|
|
1429
|
+
const colMaxWidths = [];
|
|
1430
|
+
for (let ci = 0; ci < colCount; ci++) {
|
|
1431
|
+
let max = visualWidth(headerCells[ci] ?? "");
|
|
1432
|
+
for (const row of dataRows) {
|
|
1433
|
+
const w = visualWidth(row[ci] ?? "");
|
|
1434
|
+
if (w > max) max = w;
|
|
1435
|
+
}
|
|
1436
|
+
colMaxWidths.push(Math.max(max, TABLE_MIN_COL_WIDTH));
|
|
1437
|
+
}
|
|
1438
|
+
const margin = TABLE_MARGIN;
|
|
1439
|
+
const totalMinWidth = colMaxWidths.reduce((s, w) => s + w + margin, 1);
|
|
1440
|
+
let colWidths;
|
|
1441
|
+
if (totalMinWidth <= usable) {
|
|
1442
|
+
colWidths = colMaxWidths;
|
|
1443
|
+
} else {
|
|
1444
|
+
const available = usable - 1 - margin * colCount;
|
|
1445
|
+
const sum = colMaxWidths.reduce((s, w) => s + w, 0);
|
|
1446
|
+
colWidths = colMaxWidths.map(
|
|
1447
|
+
(w) => Math.max(TABLE_MIN_COL_WIDTH, Math.floor(w / sum * available))
|
|
1448
|
+
);
|
|
1449
|
+
let total = colWidths.reduce((s, w) => s + w + margin, 1);
|
|
1450
|
+
while (total > usable && colWidths.length > 0) {
|
|
1451
|
+
const last = colWidths.length - 1;
|
|
1452
|
+
const cur = colWidths[last] ?? TABLE_MIN_COL_WIDTH;
|
|
1453
|
+
if (cur <= TABLE_MIN_COL_WIDTH) break;
|
|
1454
|
+
colWidths[last] = cur - 1;
|
|
1455
|
+
total = colWidths.reduce((s, w) => s + w + margin, 1);
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1458
|
+
const H = "\u2500";
|
|
1459
|
+
const makeSep = (l, m, r) => l + colWidths.map((w) => H.repeat(w + margin)).join(m) + r;
|
|
1460
|
+
const topBorder = makeSep("\u250C", "\u252C", "\u2510");
|
|
1461
|
+
const midBorder = makeSep("\u251C", "\u253C", "\u2524");
|
|
1462
|
+
const botBorder = makeSep("\u2514", "\u2534", "\u2518");
|
|
1463
|
+
function buildRow(cells) {
|
|
1464
|
+
const wrapped = wrapRowCells(cells, colWidths, alignments);
|
|
1465
|
+
const rowHeight = Math.max(1, ...wrapped.map((lines2) => lines2.length));
|
|
1466
|
+
const lines = [];
|
|
1467
|
+
for (let li = 0; li < rowHeight; li++) {
|
|
1468
|
+
let row = "\u2502";
|
|
1469
|
+
for (let ci = 0; ci < colCount; ci++) {
|
|
1470
|
+
const cellLines = wrapped[ci] ?? [];
|
|
1471
|
+
const segment = cellLines[li] ?? " ".repeat(colWidths[ci] ?? TABLE_MIN_COL_WIDTH);
|
|
1472
|
+
row += " " + segment + " ";
|
|
1473
|
+
if (ci < colCount - 1) row += "\u2502";
|
|
1474
|
+
}
|
|
1475
|
+
row += "\u2502";
|
|
1476
|
+
lines.push(row);
|
|
1477
|
+
}
|
|
1478
|
+
return lines;
|
|
1479
|
+
}
|
|
1480
|
+
const headerRow = buildRow(headerCells);
|
|
1481
|
+
const dataRowsOut = dataRows.map(buildRow);
|
|
1482
|
+
const totalWidth = colWidths.reduce((s, w) => s + w + margin, 1);
|
|
1483
|
+
return {
|
|
1484
|
+
lines: [
|
|
1485
|
+
topBorder,
|
|
1486
|
+
...headerRow,
|
|
1487
|
+
midBorder,
|
|
1488
|
+
...dataRowsOut.flat(),
|
|
1489
|
+
botBorder
|
|
1490
|
+
],
|
|
1491
|
+
colWidths,
|
|
1492
|
+
totalWidth
|
|
1493
|
+
};
|
|
1494
|
+
}
|
|
1495
|
+
function detectTermWidth() {
|
|
1496
|
+
const c = process.stdout?.columns;
|
|
1497
|
+
return typeof c === "number" && c > 0 ? c : void 0;
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1500
|
+
// src/ui/HighlightedText.tsx
|
|
1281
1501
|
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1282
1502
|
function parseCodeBlocks(text) {
|
|
1283
1503
|
const segments = [];
|
|
@@ -1450,111 +1670,19 @@ function CodeBlockRenderer({ code }) {
|
|
|
1450
1670
|
})
|
|
1451
1671
|
] });
|
|
1452
1672
|
}
|
|
1453
|
-
var TABLE_MAX_WIDTH = 90;
|
|
1454
|
-
var TABLE_MIN_COL_WIDTH = 3;
|
|
1455
|
-
function charWidth(ch) {
|
|
1456
|
-
const cp2 = ch.codePointAt(0);
|
|
1457
|
-
if (cp2 === void 0) return 0;
|
|
1458
|
-
if (cp2 >= 4352 && cp2 <= 4447 || // Hangul Jamo
|
|
1459
|
-
cp2 === 9001 || cp2 === 9002 || cp2 >= 11904 && cp2 <= 42191 || // CJK Radicals ~ Yi
|
|
1460
|
-
cp2 >= 43360 && cp2 <= 43391 || // Hangul Extended
|
|
1461
|
-
cp2 >= 44032 && cp2 <= 55215 || // Hangul Syllables
|
|
1462
|
-
cp2 >= 63744 && cp2 <= 64255 || // CJK Compat
|
|
1463
|
-
cp2 >= 65040 && cp2 <= 65055 || // Vertical forms
|
|
1464
|
-
cp2 >= 65281 && cp2 <= 65376 || // Fullwidth
|
|
1465
|
-
cp2 >= 65504 && cp2 <= 65510 || cp2 >= 126976 && cp2 <= 131071) {
|
|
1466
|
-
return 2;
|
|
1467
|
-
}
|
|
1468
|
-
return 1;
|
|
1469
|
-
}
|
|
1470
|
-
function visualWidth(text) {
|
|
1471
|
-
let w = 0;
|
|
1472
|
-
for (const ch of text) {
|
|
1473
|
-
w += charWidth(ch);
|
|
1474
|
-
}
|
|
1475
|
-
return w;
|
|
1476
|
-
}
|
|
1477
|
-
function padToWidth(text, targetWidth, align) {
|
|
1478
|
-
const vw = visualWidth(text);
|
|
1479
|
-
const delta = targetWidth - vw;
|
|
1480
|
-
if (delta <= 0) return text;
|
|
1481
|
-
const leftPad = align === "right" ? delta : align === "center" ? Math.floor(delta / 2) : 0;
|
|
1482
|
-
const rightPad = delta - leftPad;
|
|
1483
|
-
return " ".repeat(leftPad) + text + " ".repeat(rightPad);
|
|
1484
|
-
}
|
|
1485
|
-
function parseTableCells(line) {
|
|
1486
|
-
const t = line.trim();
|
|
1487
|
-
const inner = t.slice(1, t.length - 1);
|
|
1488
|
-
return inner.split("|").map((c) => c.trim());
|
|
1489
|
-
}
|
|
1490
|
-
function parseAlignments(sepLine) {
|
|
1491
|
-
const cells = parseTableCells(sepLine);
|
|
1492
|
-
return cells.map((c) => {
|
|
1493
|
-
const l = c.startsWith(":");
|
|
1494
|
-
const r = c.endsWith(":");
|
|
1495
|
-
if (l && r) return "center";
|
|
1496
|
-
if (r) return "right";
|
|
1497
|
-
return "left";
|
|
1498
|
-
});
|
|
1499
|
-
}
|
|
1500
1673
|
function TableRenderer({ text }) {
|
|
1501
|
-
const
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
const alignments = parseAlignments(rawLines[sepIdx]);
|
|
1514
|
-
const dataRows = rawLines.slice(sepIdx + 1).map(parseTableCells);
|
|
1515
|
-
const colCount = headerCells.length;
|
|
1516
|
-
const colMaxWidths = headerCells.map((_, ci) => {
|
|
1517
|
-
let max = visualWidth(headerCells[ci] ?? "");
|
|
1518
|
-
for (const row of dataRows) {
|
|
1519
|
-
const w = visualWidth(row[ci] ?? "");
|
|
1520
|
-
if (w > max) max = w;
|
|
1521
|
-
}
|
|
1522
|
-
return Math.max(max, TABLE_MIN_COL_WIDTH);
|
|
1523
|
-
});
|
|
1524
|
-
const margin = 2;
|
|
1525
|
-
const totalMinWidth = colMaxWidths.reduce((s, w) => s + w + margin, 1);
|
|
1526
|
-
let colWidths;
|
|
1527
|
-
if (totalMinWidth <= TABLE_MAX_WIDTH) {
|
|
1528
|
-
colWidths = colMaxWidths;
|
|
1529
|
-
} else {
|
|
1530
|
-
const available = TABLE_MAX_WIDTH - 1 - margin * colCount;
|
|
1531
|
-
const sum = colMaxWidths.reduce((s, w) => s + w, 0);
|
|
1532
|
-
colWidths = colMaxWidths.map((w) => Math.max(TABLE_MIN_COL_WIDTH, Math.floor(w / sum * available)));
|
|
1533
|
-
}
|
|
1534
|
-
const H = "\u2500";
|
|
1535
|
-
const makeSep = (l, m, r) => l + colWidths.map((w) => H.repeat(w + margin)).join(m) + r;
|
|
1536
|
-
const topBorder = makeSep("\u250C", "\u252C", "\u2510");
|
|
1537
|
-
const midBorder = makeSep("\u251C", "\u253C", "\u2524");
|
|
1538
|
-
const botBorder = makeSep("\u2514", "\u2534", "\u2518");
|
|
1539
|
-
function rowLine(cells, keyBase) {
|
|
1540
|
-
return /* @__PURE__ */ jsxs4(Text5, { children: [
|
|
1541
|
-
"\u2502",
|
|
1542
|
-
cells.map((cell, ci) => /* @__PURE__ */ jsxs4(Text5, { children: [
|
|
1543
|
-
" ",
|
|
1544
|
-
padToWidth(cell.slice(0, colWidths[ci] ?? TABLE_MIN_COL_WIDTH), colWidths[ci] ?? TABLE_MIN_COL_WIDTH, alignments[ci] ?? "left"),
|
|
1545
|
-
" ",
|
|
1546
|
-
"\u2502"
|
|
1547
|
-
] }, ci))
|
|
1548
|
-
] }, keyBase);
|
|
1549
|
-
}
|
|
1550
|
-
const rows = [
|
|
1551
|
-
/* @__PURE__ */ jsx4(Text5, { color: "#888888", children: topBorder }, "top"),
|
|
1552
|
-
rowLine(headerCells, "hdr"),
|
|
1553
|
-
/* @__PURE__ */ jsx4(Text5, { color: "#888888", children: midBorder }, "mid"),
|
|
1554
|
-
...dataRows.map((cells, ri) => rowLine(cells, `d${ri}`)),
|
|
1555
|
-
/* @__PURE__ */ jsx4(Text5, { color: "#888888", children: botBorder }, "bot")
|
|
1556
|
-
];
|
|
1557
|
-
return /* @__PURE__ */ jsx4(Box4, { flexDirection: "column", marginTop: 1, children: rows });
|
|
1674
|
+
const termWidth = detectTermWidth();
|
|
1675
|
+
const layout = layoutTable(text, { termWidth });
|
|
1676
|
+
if (layout.colWidths.length === 0) {
|
|
1677
|
+
return /* @__PURE__ */ jsx4(Text5, { children: text });
|
|
1678
|
+
}
|
|
1679
|
+
return /* @__PURE__ */ jsx4(Box4, { flexDirection: "column", marginTop: 1, children: layout.lines.map((line, i) => {
|
|
1680
|
+
const isFirst = i === 0;
|
|
1681
|
+
const isLast = i === layout.lines.length - 1;
|
|
1682
|
+
const isMid = !isFirst && !isLast && line.startsWith("\u251C");
|
|
1683
|
+
const color = isFirst || isLast || isMid ? "#888888" : void 0;
|
|
1684
|
+
return /* @__PURE__ */ jsx4(Text5, { color, children: line }, i);
|
|
1685
|
+
}) });
|
|
1558
1686
|
}
|
|
1559
1687
|
var EMOJI_CP_RE = /[\u{1F000}-\u{1FFFF}\u{FE00}-\u{FE0F}\u{200D}\u{20E3}\u{2600}-\u{27BF}\u{231A}-\u{23FF}\u{2934}\u{2935}\u{25AA}-\u{25FE}\u{2B50}\u{2B55}\u{00A9}\u{00AE}\u{2122}\u{3030}\u{303D}\u{3297}\u{3299}]/u;
|
|
1560
1688
|
function isEmojiCluster(text) {
|
|
@@ -1674,6 +1802,23 @@ function HighlightedText({ children: text }) {
|
|
|
1674
1802
|
return /* @__PURE__ */ jsx4(Box4, { flexDirection: "column", children: rendered });
|
|
1675
1803
|
}
|
|
1676
1804
|
|
|
1805
|
+
// src/ui/reasoning-utils.ts
|
|
1806
|
+
var DEFAULT_REASONING_MAX_LINES = 8;
|
|
1807
|
+
function joinReasoningSegments(segments) {
|
|
1808
|
+
return segments.map((s) => s.trim()).filter((s) => s.length > 0).join("\n");
|
|
1809
|
+
}
|
|
1810
|
+
function truncateReasoningLines(text, maxLines) {
|
|
1811
|
+
const lines = text.split("\n");
|
|
1812
|
+
if (lines.length <= maxLines) {
|
|
1813
|
+
return { visible: text, hiddenLines: 0, totalLines: lines.length };
|
|
1814
|
+
}
|
|
1815
|
+
return {
|
|
1816
|
+
visible: lines.slice(-maxLines).join("\n"),
|
|
1817
|
+
hiddenLines: lines.length - maxLines,
|
|
1818
|
+
totalLines: lines.length
|
|
1819
|
+
};
|
|
1820
|
+
}
|
|
1821
|
+
|
|
1677
1822
|
// src/ui/AssistantMessage.tsx
|
|
1678
1823
|
import { Fragment, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1679
1824
|
function formatElapsed(ms) {
|
|
@@ -1707,10 +1852,7 @@ function AnimatedUsage({ usage, cost }) {
|
|
|
1707
1852
|
}
|
|
1708
1853
|
const tokensDelta = targetTokens - displayedTokens;
|
|
1709
1854
|
const costDelta = targetCost - displayedCost;
|
|
1710
|
-
const durationMs = Math.min(
|
|
1711
|
-
600,
|
|
1712
|
-
Math.max(220, Math.max(tokensDelta, 0) * 1.2 + 220)
|
|
1713
|
-
);
|
|
1855
|
+
const durationMs = Math.min(600, Math.max(220, Math.max(tokensDelta, 0) * 1.2 + 220));
|
|
1714
1856
|
startRef.current = {
|
|
1715
1857
|
fromTokens: displayedTokens,
|
|
1716
1858
|
fromCost: displayedCost,
|
|
@@ -1761,6 +1903,7 @@ function AnimatedUsage({ usage, cost }) {
|
|
|
1761
1903
|
}
|
|
1762
1904
|
function AssistantMessage({
|
|
1763
1905
|
content,
|
|
1906
|
+
reasoning,
|
|
1764
1907
|
toolCalls,
|
|
1765
1908
|
isStreaming = false,
|
|
1766
1909
|
usage,
|
|
@@ -1768,21 +1911,43 @@ function AssistantMessage({
|
|
|
1768
1911
|
cost,
|
|
1769
1912
|
model: _model
|
|
1770
1913
|
}) {
|
|
1771
|
-
if (!content && (!toolCalls || toolCalls.length === 0) && !isStreaming) {
|
|
1914
|
+
if (!content && (!toolCalls || toolCalls.length === 0) && (!reasoning || reasoning.length === 0) && !isStreaming) {
|
|
1772
1915
|
return null;
|
|
1773
1916
|
}
|
|
1774
1917
|
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", marginTop: 1, children: [
|
|
1918
|
+
reasoning && reasoning.length > 0 && (() => {
|
|
1919
|
+
const merged = joinReasoningSegments(reasoning);
|
|
1920
|
+
if (!merged) return null;
|
|
1921
|
+
const { visible } = truncateReasoningLines(
|
|
1922
|
+
merged,
|
|
1923
|
+
DEFAULT_REASONING_MAX_LINES
|
|
1924
|
+
);
|
|
1925
|
+
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "row", marginBottom: 1, children: [
|
|
1926
|
+
/* @__PURE__ */ jsx5(Box5, { width: 4, flexShrink: 0, children: /* @__PURE__ */ jsx5(Text6, { dimColor: true, children: "\u{1F9E0}" }) }),
|
|
1927
|
+
/* @__PURE__ */ jsx5(
|
|
1928
|
+
Box5,
|
|
1929
|
+
{
|
|
1930
|
+
flexGrow: 1,
|
|
1931
|
+
flexDirection: "column",
|
|
1932
|
+
borderStyle: "single",
|
|
1933
|
+
borderColor: "#444444",
|
|
1934
|
+
paddingLeft: 1,
|
|
1935
|
+
paddingRight: 1,
|
|
1936
|
+
children: /* @__PURE__ */ jsx5(Text6, { dimColor: true, wrap: "wrap", children: visible })
|
|
1937
|
+
}
|
|
1938
|
+
)
|
|
1939
|
+
] });
|
|
1940
|
+
})(),
|
|
1775
1941
|
/* @__PURE__ */ jsxs5(Box5, { flexDirection: "row", children: [
|
|
1776
1942
|
/* @__PURE__ */ jsx5(Box5, { width: 4, flexShrink: 0, children: /* @__PURE__ */ jsx5(Text6, { bold: true, color: "#ff00ff", children: "\u{1F916}" }) }),
|
|
1777
1943
|
/* @__PURE__ */ jsxs5(Box5, { flexGrow: 1, flexDirection: "column", children: [
|
|
1778
1944
|
content && /* @__PURE__ */ jsx5(HighlightedText, { children: content }),
|
|
1779
|
-
isStreaming && !content && /* @__PURE__ */ jsx5(Text6, { color: "#888888", children: "..." })
|
|
1945
|
+
isStreaming && !content && (!reasoning || reasoning.length === 0) && /* @__PURE__ */ jsx5(Text6, { color: "#888888", children: "..." })
|
|
1780
1946
|
] })
|
|
1781
1947
|
] }),
|
|
1782
1948
|
toolCalls && toolCalls.length > 0 && /* @__PURE__ */ jsx5(Box5, { flexDirection: "column", children: toolCalls.map((tc, i) => /* @__PURE__ */ jsx5(ToolCallBlock, { call: tc }, tc.id ?? i)) }),
|
|
1783
1949
|
isStreaming && (usage || cost !== void 0) && /* @__PURE__ */ jsx5(Box5, { flexDirection: "row", marginTop: 1, marginLeft: 3, children: /* @__PURE__ */ jsxs5(Text6, { color: "#666666", dimColor: true, children: [
|
|
1784
|
-
"\u23F3 \u5DF2\u6D88\u8017",
|
|
1785
|
-
" ",
|
|
1950
|
+
"\u23F3 \u5DF2\u6D88\u8017 ",
|
|
1786
1951
|
/* @__PURE__ */ jsx5(AnimatedUsage, { usage, cost })
|
|
1787
1952
|
] }) }),
|
|
1788
1953
|
!isStreaming && (usage || elapsed !== void 0) && /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", marginTop: 1, marginLeft: 3, children: [
|
|
@@ -1891,6 +2056,49 @@ function FileSelector({ files, input, selectedIndex }) {
|
|
|
1891
2056
|
] });
|
|
1892
2057
|
}
|
|
1893
2058
|
|
|
2059
|
+
// src/ui/TodoListPanel.tsx
|
|
2060
|
+
import { Box as Box9, Text as Text10 } from "ink";
|
|
2061
|
+
import InkSpinner2 from "ink-spinner";
|
|
2062
|
+
import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
2063
|
+
function statusIcon(status) {
|
|
2064
|
+
switch (status) {
|
|
2065
|
+
case "pending":
|
|
2066
|
+
return "\u2610";
|
|
2067
|
+
case "done":
|
|
2068
|
+
return "\u2611";
|
|
2069
|
+
case "failed":
|
|
2070
|
+
return "\u2717";
|
|
2071
|
+
case "skipped":
|
|
2072
|
+
return "\u2298";
|
|
2073
|
+
// running 不走这里,由 TodoIcon 走 Spinner 组件
|
|
2074
|
+
case "running":
|
|
2075
|
+
return "\u25B6";
|
|
2076
|
+
}
|
|
2077
|
+
}
|
|
2078
|
+
function TodoIcon({ status }) {
|
|
2079
|
+
if (status === "running") {
|
|
2080
|
+
return /* @__PURE__ */ jsx9(Text10, { color: "cyan", children: /* @__PURE__ */ jsx9(InkSpinner2, { type: "dots" }) });
|
|
2081
|
+
}
|
|
2082
|
+
if (status === "done") {
|
|
2083
|
+
return /* @__PURE__ */ jsx9(Text10, { color: "green", children: "\u2705" });
|
|
2084
|
+
}
|
|
2085
|
+
if (status === "failed") {
|
|
2086
|
+
return /* @__PURE__ */ jsx9(Text10, { color: "red", children: statusIcon(status) });
|
|
2087
|
+
}
|
|
2088
|
+
return /* @__PURE__ */ jsx9(Text10, { dimColor: true, children: statusIcon(status) });
|
|
2089
|
+
}
|
|
2090
|
+
function TodoListPanel({ items }) {
|
|
2091
|
+
if (items.length === 0) return null;
|
|
2092
|
+
return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", marginTop: 1, children: [
|
|
2093
|
+
/* @__PURE__ */ jsx9(Box9, { children: /* @__PURE__ */ jsx9(Text10, { dimColor: true, children: "\u{1F527} \u4EFB\u52A1\u8FDB\u5EA6" }) }),
|
|
2094
|
+
items.map((it) => /* @__PURE__ */ jsxs9(Box9, { children: [
|
|
2095
|
+
/* @__PURE__ */ jsx9(Text10, { dimColor: true, children: " " }),
|
|
2096
|
+
/* @__PURE__ */ jsx9(TodoIcon, { status: it.status }),
|
|
2097
|
+
/* @__PURE__ */ jsx9(Text10, { dimColor: true, children: ` ${it.content}` })
|
|
2098
|
+
] }, it.id))
|
|
2099
|
+
] });
|
|
2100
|
+
}
|
|
2101
|
+
|
|
1894
2102
|
// src/provider/registry.ts
|
|
1895
2103
|
var ProviderRegistry = class {
|
|
1896
2104
|
#factories = /* @__PURE__ */ new Map();
|
|
@@ -1985,10 +2193,10 @@ var AlwaysAllowGate = class {
|
|
|
1985
2193
|
import Handlebars from "handlebars";
|
|
1986
2194
|
|
|
1987
2195
|
// src/agent/prompts/system-prompt.hbs
|
|
1988
|
-
var system_prompt_default = '\u4F60\u662F dskcode\uFF0C\u4E00\u4E2A\u57FA\u4E8E DeepSeek \u7684 AI \u7F16\u7A0B\u52A9\u624B\uFF0C\u8FD0\u884C\u5728\u7528\u6237\u7EC8\u7AEF\u4E2D\u3002\u4F60\u7684\u804C\u8D23\u662F\u5E2E\u52A9\u5F00\u53D1\u8005\u7F16\u5199\u3001\u7406\u89E3\u3001\u8C03\u8BD5\u548C\u91CD\u6784\u4EE3\u7801\u3002\r\n\r\n## \u6838\u5FC3\u539F\u5219\r\n- \u56DE\u7B54\u4F7F\u7528\u4E2D\u6587\uFF0C\u4EE3\u7801\u6807\u8BC6\u7B26\u4FDD\u6301\u82F1\u6587\r\n- \u63D0\u4F9B\u51C6\u786E\u3001\u5B9E\u7528\u3001\u53EF\u64CD\u4F5C\u7684\u5EFA\u8BAE\r\n- \u5BF9\u4E0D\u786E\u5B9A\u7684\u5185\u5BB9\u660E\u786E\u6807\u6CE8\uFF0C\u4E0D\u7F16\u9020\u4E8B\u5B9E\r\n- \u4EE3\u7801\u793A\u4F8B\u4FDD\u6301\u7B80\u6D01\uFF0C\u9644\u5E26\u5FC5\u8981\u7684\u6CE8\u91CA\r\n\r\n## \u5DE5\u4F5C\u6D41\u7A0B\r\n\r\n\u4F60\u5904\u4E8E\u4E00\u4E2A\u5DE5\u5177\u8C03\u7528\u5FAA\u73AF\u4E2D\uFF1A\r\n1. \u6536\u5230\u7528\u6237\u8BF7\u6C42\r\n2. \u8C03\u7528\u5DE5\u5177\u83B7\u53D6\u4FE1\u606F\u6216\u4FEE\u6539\u6587\u4EF6\r\n3. \u5DE5\u5177\u7ED3\u679C\u8FD4\u56DE\u7ED9\u4F60\r\n4. \u6839\u636E\u7ED3\u679C\u51B3\u5B9A\u4E0B\u4E00\u6B65\uFF08\u7EE7\u7EED\u8C03\u7528\u5DE5\u5177\u6216\u7ED9\u51FA\u6700\u7EC8\u56DE\u7B54\uFF09\r\n5. \u4E00\u8F6E\u6700\u591A {{maxToolRounds}} \u6B21\u5DE5\u5177\u8C03\u7528\r\n\r\n## \u5DE5\u5177\u4F7F\u7528\u7B56\u7565\r\n\r\n{{#if tools}}\r\n\u5F53\u524D\u53EF\u7528\u7684\u5DE5\u5177\uFF1A\r\n{{#each tools}}\r\n- **{{name}}**\uFF1A{{description}}{{#if params}}\uFF08\u53C2\u6570\uFF1A{{params}}\uFF09{{/if}}\r\n{{/each}}\r\n\r\n\u4F7F\u7528\u539F\u5219\uFF1A\r\n- **\u5148\u641C\u7D22\u518D\u8BFB\u53D6** \u2014 \u4E0D\u786E\u5B9A\u76EE\u6807\u4F4D\u7F6E\u65F6\u5148\u7528 grep/glob \u5B9A\u4F4D\uFF0C\u518D\u7528 read_file \u8BFB\u53D6\r\n- **\u5148\u8BFB\u53D6\u518D\u4FEE\u6539** \u2014 \u7F16\u8F91\u6587\u4EF6\u524D\u5148 read_file \u786E\u8BA4\u5F53\u524D\u5185\u5BB9\r\n- **\u6279\u91CF\u64CD\u4F5C\u4E00\u6B21\u5B8C\u6210** \u2014 \u540C\u4E00\u6587\u4EF6\u7684\u591A\u5904\u6539\u52A8\u5728\u5355\u6B21 edit_file \u4E2D\u5B8C\u6210\r\n- **\u5DE5\u5177\u51FA\u9519\u65F6** \u2014 \u5206\u6790\u9519\u8BEF\u539F\u56E0\uFF08\u8DEF\u5F84\u4E0D\u5BF9\uFF1F\u683C\u5F0F\u4E0D\u5BF9\uFF1F\u6743\u9650\u4E0D\u8DB3\uFF1F\uFF09\uFF0C\u4FEE\u6B63\u540E\u91CD\u8BD5\uFF0C\u4E0D\u8981\u91CD\u590D\u76F8\u540C\u7684\u9519\u8BEF\u8C03\u7528\r\n- **\u5BA1\u614E\u6267\u884C** \u2014 bash \u6267\u884C\u5371\u9669\u547D\u4EE4\uFF08rm -rf\u3001\u5F3A\u5236\u5199\u5165\u7B49\uFF09\u524D\u5148\u786E\u8BA4\r\n{{/if}}\r\n\r\n{{#if projectContext}}\r\n## \u9879\u76EE\u4E0A\u4E0B\u6587\r\n\r\n{{projectContext}}\r\n{{/if}}\r\n\r\n## \u56DE\u7B54\u683C\u5F0F\r\n\r\n\u7EC8\u7AEF\u4E0D\u652F\u6301 Markdown \u6E32\u67D3\u3002\u56DE\u590D\u683C\u5F0F\u8981\u6C42\uFF1A\r\n\r\n- \u7528 emoji \u505A\u89C6\u89C9\u6807\u8BB0\uFF08\u{1F4CC} \u8981\u70B9 \u26A0\uFE0F \u6CE8\u610F \u{1F4DD} \u5F85\u529E \u2705 \u5B8C\u6210\uFF09\r\n- \u7528\u6570\u5B57\u5E8F\u53F7\u6216\u77ED\u6A2A\u7EBF\u7EC4\u7EC7\u5217\u8868\r\n- \u4EE3\u7801\u6807\u8BC6\u7B26\u3001\u6587\u4EF6\u8DEF\u5F84\u3001\u7C7B\u578B\u540D\u7528\u5355\u4E2A\u53CD\u5F15\u53F7 ` \u5305\u88F9\uFF0C\u4F1A\u88AB\u81EA\u52A8\u9AD8\u4EAE\r\n- \u5F3A\u8C03\u5185\u5BB9\u7528 **\u52A0\u7C97** \u5305\u88F9\uFF0C\u4F1A\u88AB\u81EA\u52A8\u9AD8\u4EAE\r\n- \u591A\u884C\u4EE3\u7801\u7528\u7F29\u8FDB 4 \u4E2A\u7A7A\u683C\u8868\u793A\uFF0C\u4E0D\u8981\u7528\u4E09\u53CD\u5F15\u53F7\u4EE3\u7801\u5757\r\n- \u6BB5\u843D\u95F4\u7528\u7A7A\u884C\u5206\u9694\r\n- **\u4E0D\u8981\u4F7F\u7528 `#` \u7B26\u53F7** \u2014 \u7EC8\u7AEF\u4E0D\u6E32\u67D3 Markdown \u6807\u9898\uFF0C\u8BF7\u7528 emoji + \u52A0\u7C97\u66FF\u4EE3\uFF08\u5982 `\u{1F4CC} **\u6807\u9898**`\uFF09\r\n\r\n\u6B63\u786E\u793A\u4F8B\uFF1A\r\n\r\n\u{1F4CC} **\u4FEE\u6539\u8BA1\u5212**\r\n\r\n\u{1F4CC} \u9700\u8981\u4FEE\u6539\u4E24\u4E2A\u5730\u65B9\uFF1A\r\n1. \u7B2C 12 \u884C\u7684 `interface FileDiff` \u6539\u4E3A `interface Diff`\r\n2. \u7B2C 432 \u884C\u7684 `): FileDiff` \u6539\u4E3A `): Diff`\r\n\r\n \u4EE3\u7801\u793A\u4F8B\uFF1A\r\n const pool = new Pool({ max: 20 });\r\n await pool.query("SELECT * FROM users");\r\n\r\n## \u884C\u4E3A\u7EA6\u675F\r\n- \u5982\u679C\u7528\u6237\u8BF7\u6C42\u4E0D\u660E\u786E\uFF0C\u4E3B\u52A8\u8BE2\u95EE\u6F84\u6E05\r\n- \u5BF9\u4E0D\u786E\u5B9A\u7684\u4FE1\u606F\u660E\u786E\u6807\u6CE8\uFF0C\u4E0D\u7F16\u9020\u4E8B\u5B9E\r\n- \u4E0D\u6267\u884C\u53EF\u80FD\u9020\u6210\u4E0D\u53EF\u9006\u635F\u5BB3\u7684\u64CD\u4F5C\uFF08\u5982 rm -rf\uFF09\uFF0C\u9664\u975E\u7528\u6237\u660E\u786E\u9010\u6761\u786E\u8BA4\r\n- \u5DE5\u5177\u8C03\u7528\u8FD4\u56DE\u9519\u8BEF\u65F6\uFF0C\u5148\u5206\u6790\u539F\u56E0\u518D\u91CD\u8BD5\uFF0C\u4E0D\u8981\u76F2\u76EE\u91CD\u8BD5\r\n\r\n## \u5F53\u524D\u6A21\u578B\r\n- \u6A21\u578B\uFF1A{{model}}\r\n\r\n## \u65F6\u95F4\u4E0A\u4E0B\u6587\r\n- \u5F53\u524D\u65E5\u671F\uFF1A{{date}}\r\n- \u5F53\u524D\u65F6\u95F4\uFF1A{{time}}\r\n- \u5DE5\u4F5C\u76EE\u5F55\uFF1A{{cwd}}\r\n';
|
|
2196
|
+
var system_prompt_default = '\u4F60\u662F dskcode\uFF0C\u4E00\u4E2A\u57FA\u4E8E DeepSeek \u7684 AI \u7F16\u7A0B\u52A9\u624B\uFF0C\u8FD0\u884C\u5728\u7528\u6237\u7EC8\u7AEF\u4E2D\u3002\u4F60\u7684\u804C\u8D23\u662F\u5E2E\u52A9\u5F00\u53D1\u8005\u7F16\u5199\u3001\u7406\u89E3\u3001\u8C03\u8BD5\u548C\u91CD\u6784\u4EE3\u7801\u3002\r\n\r\n## \u6838\u5FC3\u539F\u5219\r\n- \u56DE\u7B54\u4F7F\u7528\u4E2D\u6587\uFF0C\u4EE3\u7801\u6807\u8BC6\u7B26\u4FDD\u6301\u82F1\u6587\r\n- **\u601D\u8003\u8FC7\u7A0B\uFF08CoT\uFF09\u4E5F\u4F7F\u7528\u4E2D\u6587**\uFF0C\u4E0D\u8981\u7528\u82F1\u6587\u601D\u8003\u3002\u5982\u679C\u4F60\u53D1\u73B0\u81EA\u5DF1\u5728\u7528\u82F1\u6587\r\n \u60F3\uFF0C\u8BF7\u5207\u6362\u5230\u4E2D\u6587\u3002\u4F60\u7684\u6240\u6709\u5185\u5FC3\u72EC\u767D\u548C\u6700\u7EC8\u56DE\u7B54\u90FD\u5E94\u7528\u4E2D\u6587\u8868\u8FBE\u3002\r\n- \u63D0\u4F9B\u51C6\u786E\u3001\u5B9E\u7528\u3001\u53EF\u64CD\u4F5C\u7684\u5EFA\u8BAE\r\n- \u5BF9\u4E0D\u786E\u5B9A\u7684\u5185\u5BB9\u660E\u786E\u6807\u6CE8\uFF0C\u4E0D\u7F16\u9020\u4E8B\u5B9E\r\n- \u4EE3\u7801\u793A\u4F8B\u4FDD\u6301\u7B80\u6D01\uFF0C\u9644\u5E26\u5FC5\u8981\u7684\u6CE8\u91CA\r\n\r\n## \u7528\u6237\u8F93\u5165\u8BED\u6CD5\r\n- `@<\u8DEF\u5F84>` \u8868\u793A\u4E00\u4E2A**\u6587\u4EF6\u8DEF\u5F84**\u7684\u5F15\u7528\u6807\u8BC6\u3002`@` \u4E0D\u662F\u90AE\u7BB1\u7B26\u53F7\u3001\u4E5F\u4E0D\u662F\u88C5\u9970\u540E\u7F00\u3002\r\n - `@test.ts` = \u5F15\u7528\u5F53\u524D\u76EE\u5F55\u4E0B\u540D\u4E3A `test.ts` \u7684\u6587\u4EF6\r\n - `@src/foo/bar.ts` = \u5F15\u7528 `src/foo/bar.ts`\r\n - \u591A\u4E2A\u5F15\u7528\uFF1A`\u8BF7\u8BFB @a.ts \u548C @b/d.ts`\r\n - \u8DEF\u5F84\u53EF\u4EE5\u662F\u76F8\u5BF9\u8DEF\u5F84\uFF08\u76F8\u5BF9\u5DE5\u4F5C\u76EE\u5F55\uFF09\u6216\u7EDD\u5BF9\u8DEF\u5F84\r\n- `\\/<\u547D\u4EE4>` \u8868\u793A\u4E00\u4E2A**\u659C\u6760\u547D\u4EE4**\uFF08\u5982 `\\/help`\u3001`\\/plan`\u3001`\\/code`\uFF09\uFF0C\u4E0D\u662F\u76EE\u5F55\u3002\r\n - \u6536\u5230 `/xxx` \u5F00\u5934\u7684\u5185\u5BB9\u5148\u5224\u5B9A\u662F\u4E0D\u662F\u5DF2\u6CE8\u518C\u547D\u4EE4\uFF1B\u4E0D\u662F\u5219\u5F53\u4F5C\u666E\u901A\u6587\u672C\u5904\u7406\u3002\r\n- \u4E0A\u8FF0\u4E24\u79CD\u524D\u7F00\u662F**\u7528\u6237\u8F93\u5165\u9762**\u8BED\u6CD5\uFF0C\u4F60**\u4E0D\u8981\u5728\u56DE\u590D\u4E2D\u8F93\u51FA**\u5B83\u4EEC\uFF08\u4E0D\u8981\u4F2A\u9020 `@/path` \u8FD9\u79CD\u4F2A\u5F15\u7528\uFF09\u3002\u5982\u679C\u8981\u5F15\u7528\u6587\u4EF6\uFF0C\u76F4\u63A5\u7528\u5355\u53CD\u5F15\u53F7\u5305\u88F9\u8DEF\u5F84\uFF08\u5982 `src/foo.ts`\uFF09\u3002\r\n\r\n## \u5DE5\u4F5C\u6D41\u7A0B\r\n\r\n\u4F60\u5904\u4E8E\u4E00\u4E2A\u5DE5\u5177\u8C03\u7528\u5FAA\u73AF\u4E2D\uFF1A\r\n1. \u6536\u5230\u7528\u6237\u8BF7\u6C42\r\n2. \u8C03\u7528\u5DE5\u5177\u83B7\u53D6\u4FE1\u606F\u6216\u4FEE\u6539\u6587\u4EF6\r\n3. \u5DE5\u5177\u7ED3\u679C\u8FD4\u56DE\u7ED9\u4F60\r\n4. \u6839\u636E\u7ED3\u679C\u51B3\u5B9A\u4E0B\u4E00\u6B65\uFF08\u7EE7\u7EED\u8C03\u7528\u5DE5\u5177\u6216\u7ED9\u51FA\u6700\u7EC8\u56DE\u7B54\uFF09\r\n5. \u4E00\u8F6E\u6700\u591A {{maxToolRounds}} \u6B21\u5DE5\u5177\u8C03\u7528\r\n\r\n## \u5DE5\u5177\u4F7F\u7528\u7B56\u7565\r\n\r\n{{#if tools}}\r\n\u5F53\u524D\u53EF\u7528\u7684\u5DE5\u5177\uFF1A\r\n{{#each tools}}\r\n- **{{name}}**\uFF1A{{description}}{{#if params}}\uFF08\u53C2\u6570\uFF1A{{params}}\uFF09{{/if}}\r\n{{/each}}\r\n\r\n\u4F7F\u7528\u539F\u5219\uFF1A\r\n- **\u5148\u641C\u7D22\u518D\u8BFB\u53D6** \u2014 \u4E0D\u786E\u5B9A\u76EE\u6807\u4F4D\u7F6E\u65F6\u5148\u7528 grep/glob \u5B9A\u4F4D\uFF0C\u518D\u7528 read_file \u8BFB\u53D6\r\n- **\u5148\u8BFB\u53D6\u518D\u4FEE\u6539** \u2014 \u7F16\u8F91\u6587\u4EF6\u524D\u5148 read_file \u786E\u8BA4\u5F53\u524D\u5185\u5BB9\r\n- **\u6279\u91CF\u64CD\u4F5C\u4E00\u6B21\u5B8C\u6210** \u2014 \u540C\u4E00\u6587\u4EF6\u7684\u591A\u5904\u6539\u52A8\u5728\u5355\u6B21 edit_file \u4E2D\u5B8C\u6210\r\n- **\u5DE5\u5177\u51FA\u9519\u65F6** \u2014 \u5206\u6790\u9519\u8BEF\u539F\u56E0\uFF08\u8DEF\u5F84\u4E0D\u5BF9\uFF1F\u683C\u5F0F\u4E0D\u5BF9\uFF1F\u6743\u9650\u4E0D\u8DB3\uFF1F\uFF09\uFF0C\u4FEE\u6B63\u540E\u91CD\u8BD5\uFF0C\u4E0D\u8981\u91CD\u590D\u76F8\u540C\u7684\u9519\u8BEF\u8C03\u7528\r\n- **\u5BA1\u614E\u6267\u884C** \u2014 bash \u6267\u884C\u5371\u9669\u547D\u4EE4\uFF08rm -rf\u3001\u5F3A\u5236\u5199\u5165\u7B49\uFF09\u524D\u5148\u786E\u8BA4\r\n{{/if}}\r\n\r\n## \u5DE5\u4F5C\u6D41\uFF08\u91CD\u8981\uFF09\u2014 \u590D\u6742\u4EFB\u52A1\u5224\u5B9A\r\n\r\n\u6536\u5230\u7528\u6237\u8BF7\u6C42\u540E\uFF0C**\u5148\u5224\u5B9A\u590D\u6742\u5EA6**\uFF0C\u518D\u51B3\u5B9A\u8981\u4E0D\u8981\u62C6 todo\u3002\r\n\r\n### \u9ED8\u8BA4\u5047\u8BBE\u662F\u300C\u590D\u6742\u300D\r\n\r\n\u9664\u975E\u660E\u786E\u5C5E\u4E8E\u4E0B\u9762\u300C\u7B80\u5355\u300D\u4E09\u9009\u4E00\uFF0C**\u9ED8\u8BA4\u6309\u590D\u6742\u5904\u7406\uFF0C\u5148 todo_add \u62C6 3-7 \u6B65**\u3002\r\n\r\n### \u5224\u5B9A\u95EE\u5377\uFF08\u9010\u6761 yes/no\uFF09\r\n\r\n\u95EE\u81EA\u5DF1\u4EE5\u4E0B\u95EE\u9898\uFF0C**\u4EFB\u4E00\u56DE\u7B54 yes \u2192 \u62C6 todo**\uFF1A\r\n- 1\uFE0F\u20E3 \u8981\u5199/\u6539/\u521B\u5EFA **\u8D85\u8FC7 1 \u4E2A**\u6587\u4EF6\uFF1F\r\n- 2\uFE0F\u20E3 \u8981\u5148 **\u8BFB\u540E\u6539**\uFF08edit_file / write_file \u4E4B\u524D\u5FC5\u987B read_file\uFF09\uFF1F\r\n- 3\uFE0F\u20E3 \u8981\u8DE8 **2 \u79CD\u4EE5\u4E0A**\u5DE5\u5177\uFF08read + edit + bash + ...\uFF09\uFF1F\r\n- 4\uFE0F\u20E3 \u8981 **\u5BF9\u6BD4 2 \u4E2A\u4EE5\u4E0A\u4E8B\u5B9E\u6E90**\uFF08\u5982 README \u8BF4\u7684 vs \u4EE3\u7801\u5B9E\u9645\u5199\u7684\u3001\u8FD9\u91CC vs \u90A3\u91CC\uFF09\uFF1F\r\n- 5\uFE0F\u20E3 \u53E5\u5B50\u8D85\u8FC7 **20 \u4E2A\u5B57** \u4E14 **\u5305\u542B\u300C\u6539\u6210 / \u52A0\u4E2A / \u5B9E\u73B0 / \u5199\u4E00\u4E2A / \u91CD\u6784 / \u4FEE\u590D / \u8C03\u6574\u300D** \u8FD9\u7C7B\u52A8\u8BCD\uFF1F\r\n\r\n### \u300C\u7B80\u5355\u300D\u4E09\u9009\u4E00\uFF08\u53EF\u4EE5\u4E0D\u62C6 todo\uFF09\r\n\r\n- \u7EAF\u67E5\u8BE2\uFF1A\u300C\u5217\u51FA X\u300D\u300C\u770B\u770B Y\u300D\u300C\u641C\u4E00\u4E0B Z\u300D\u2192 1 \u4E2A\u5DE5\u5177 1 \u8F6E\u641E\u5B9A\r\n- 1 \u4E2A\u5DE5\u5177 1 \u8F6E\u80FD\u641E\u5B9A\u7684\u8BFB/\u5217/\u67E5\u64CD\u4F5C\r\n- \u95F2\u804A / \u89E3\u91CA\u6027\u95EE\u9898\uFF08\u4E0D\u8C03\u4EFB\u4F55\u5DE5\u5177\uFF09\r\n\r\n### \u5224\u5B9A\u51B3\u7B56\u6811\r\n\r\n```\r\n\u7528\u6237\u8F93\u5165\r\n \u251C\u2500 \u662F\u300C\u7B80\u5355\u4E09\u9009\u4E00\u300D\uFF1F \u2192 \u76F4\u63A5\u8C03\u5DE5\u5177\uFF0C\u4E0D\u62C6 todo\r\n \u2514\u2500 \u4E0D\u662F\uFF1F \u2192 \u5148 todo_add \u62C6 3-7 \u6B65\u518D\u52A8\u624B\uFF08\u9ED8\u8BA4\u884C\u4E3A\uFF09\r\n```\r\n\r\n### todo \u62C6\u89E3\u6A21\u677F\r\n\r\n**\u6539\u52A8\u578B\u4EFB\u52A1**\uFF08\u6700\u5E38\u89C1\uFF09\uFF1A\r\n1. `todo_add("\u8BFB <\u76EE\u6807\u6587\u4EF6>")`\r\n2. `todo_add("<\u5177\u4F53\u6539\u52A8>", deps=[0])`\r\n3. `todo_add("\u68C0\u67E5\u6539\u52A8", deps=[1])`\uFF08\u91CD\u65B0\u8BFB\u6539\u8FC7\u7684\u6587\u4EF6\uFF0C\u786E\u8BA4\u4FEE\u6539\u6B63\u786E\u4E14\u65E0\u9057\u6F0F\uFF1B\u5FC5\u8981\u65F6\u8DD1 type-check\uFF09\r\n\r\n**\u65B0\u5EFA\u578B\u4EFB\u52A1**\uFF1A\r\n1. `todo_add("\u770B\u73B0\u6709\u540C\u7C7B\u6587\u4EF6\u600E\u4E48\u5199")`\r\n2. `todo_add("\u5B9E\u73B0\u65B0 <X>", deps=[0])`\r\n3. `todo_add("\u9A8C\u8BC1", deps=[1])`\r\n\r\n**\u8C03\u8BD5\u578B\u4EFB\u52A1**\uFF1A\r\n1. `todo_add("\u590D\u73B0 bug")`\r\n2. `todo_add("\u5B9A\u4F4D\u539F\u56E0", deps=[0])`\r\n3. `todo_add("\u4FEE\u590D", deps=[1])`\r\n4. `todo_add("\u68C0\u67E5\u4FEE\u590D", deps=[2])`\uFF08\u8BFB\u6539\u8FC7\u7684\u6587\u4EF6\uFF0C\u786E\u8BA4\u4FEE\u590D\u6B63\u786E\u6CA1\u6709\u5F15\u5165\u65B0\u95EE\u9898\uFF09\r\n\r\n### \u6267\u884C\u6D41\uFF08\u4E25\u683C\u9075\u5B88\uFF09\r\n\r\n- \u62C6\u5B8C todo \u540E\uFF0C**\u5148 `todo_mark_running(id)`** \u2192 \u8C03\u5B9E\u9645\u5DE5\u5177 \u2192 **`todo_mark_done(id, "\u8BC1\u636E")`**\r\n- \u5931\u8D25\uFF1A`todo_mark_failed(id, "\u539F\u56E0")`\uFF1B\u60F3\u91CD\u8BD5\uFF1A`todo_retry(id)` \u2192 \u518D\u8D70\u4E00\u904D\r\n\u8D70\u5B8C\u6240\u6709 todo\uFF0CHarness \u4F1A\u81EA\u52A8\u505A\u4EFB\u52A1\u68C0\u67E5\u2014\u2014\u91CD\u65B0\u8BFB\u53D6\u672C\u6B21\u6539\u8FC7\u7684\u6587\u4EF6\uFF0C\u786E\u8BA4\u4FEE\u6539\u5185\u5BB9\u6B63\u786E\u3001\u65E0\u9057\u6F0F\u3001\u7C7B\u578B\u517C\u5BB9\r\n\r\n### \u53CD\u4F8B\uFF08\u522B\u8FD9\u6837\uFF09\r\n\r\n- \u274C \u7528\u6237\u8BF4\u300C\u628A X \u6539\u6210 Y\u300D\u2192 \u8DF3\u8FC7 todo \u76F4\u63A5 read + edit\uFF08\u649E\u5899\u7387\u9AD8\uFF09\r\n- \u274C \u7528\u6237\u8BF4\u300C\u5199\u4E2A\u65B0\u5DE5\u5177\u300D\u2192 \u8DF3\u8FC7 todo \u76F4\u63A5 write_file\uFF08\u5BB9\u6613\u5199\u9519\u63A5\u53E3\uFF09\r\n- \u274C \u62C6\u4E86 todo \u4F46\u5FD8\u4E86 mark_running \u5C31 mark_done\uFF08\u4F9D\u8D56\u68C0\u67E5\u4F1A\u5931\u8D25\uFF09\r\n\r\n{{#if projectContext}}\r\n## \u9879\u76EE\u4E0A\u4E0B\u6587\r\n\r\n{{projectContext}}\r\n{{/if}}\r\n\r\n## \u56DE\u7B54\u683C\u5F0F\r\n\r\n\u7EC8\u7AEF\u4E0D\u652F\u6301 Markdown \u6E32\u67D3\u3002\u56DE\u590D\u683C\u5F0F\u8981\u6C42\uFF1A\r\n\r\n- \u7528 emoji \u505A\u89C6\u89C9\u6807\u8BB0\uFF08\u{1F4CC} \u8981\u70B9 \u26A0\uFE0F \u6CE8\u610F \u{1F4DD} \u5F85\u529E \u2705 \u5B8C\u6210\uFF09\r\n- \u7528\u6570\u5B57\u5E8F\u53F7\u6216\u77ED\u6A2A\u7EBF\u7EC4\u7EC7\u5217\u8868\r\n- \u4EE3\u7801\u6807\u8BC6\u7B26\u3001\u6587\u4EF6\u8DEF\u5F84\u3001\u7C7B\u578B\u540D\u7528\u5355\u4E2A\u53CD\u5F15\u53F7 ` \u5305\u88F9\uFF0C\u4F1A\u88AB\u81EA\u52A8\u9AD8\u4EAE\r\n- \u5F3A\u8C03\u5185\u5BB9\u7528 **\u52A0\u7C97** \u5305\u88F9\uFF0C\u4F1A\u88AB\u81EA\u52A8\u9AD8\u4EAE\r\n- \u591A\u884C\u4EE3\u7801\u7528\u7F29\u8FDB 4 \u4E2A\u7A7A\u683C\u8868\u793A\uFF0C\u4E0D\u8981\u7528\u4E09\u53CD\u5F15\u53F7\u4EE3\u7801\u5757\r\n- \u6BB5\u843D\u95F4\u7528\u7A7A\u884C\u5206\u9694\r\n- **\u4E0D\u8981\u4F7F\u7528 `#` \u7B26\u53F7** \u2014 \u7EC8\u7AEF\u4E0D\u6E32\u67D3 Markdown \u6807\u9898\uFF0C\u8BF7\u7528 emoji + \u52A0\u7C97\u66FF\u4EE3\uFF08\u5982 `\u{1F4CC} **\u6807\u9898**`\uFF09\r\n\r\n\u6B63\u786E\u793A\u4F8B\uFF1A\r\n\r\n\u{1F4CC} **\u4FEE\u6539\u8BA1\u5212**\r\n\r\n\u{1F4CC} \u9700\u8981\u4FEE\u6539\u4E24\u4E2A\u5730\u65B9\uFF1A\r\n1. \u7B2C 12 \u884C\u7684 `interface FileDiff` \u6539\u4E3A `interface Diff`\r\n2. \u7B2C 432 \u884C\u7684 `): FileDiff` \u6539\u4E3A `): Diff`\r\n\r\n \u4EE3\u7801\u793A\u4F8B\uFF1A\r\n const pool = new Pool({ max: 20 });\r\n await pool.query("SELECT * FROM users");\r\n\r\n## \u884C\u4E3A\u7EA6\u675F\r\n- \u5982\u679C\u7528\u6237\u8BF7\u6C42\u4E0D\u660E\u786E\uFF0C\u4E3B\u52A8\u8BE2\u95EE\u6F84\u6E05\r\n- \u5BF9\u4E0D\u786E\u5B9A\u7684\u4FE1\u606F\u660E\u786E\u6807\u6CE8\uFF0C\u4E0D\u7F16\u9020\u4E8B\u5B9E\r\n- \u4E0D\u6267\u884C\u53EF\u80FD\u9020\u6210\u4E0D\u53EF\u9006\u635F\u5BB3\u7684\u64CD\u4F5C\uFF08\u5982 rm -rf\uFF09\uFF0C\u9664\u975E\u7528\u6237\u660E\u786E\u9010\u6761\u786E\u8BA4\r\n- \u5DE5\u5177\u8C03\u7528\u8FD4\u56DE\u9519\u8BEF\u65F6\uFF0C\u5148\u5206\u6790\u539F\u56E0\u518D\u91CD\u8BD5\uFF0C\u4E0D\u8981\u76F2\u76EE\u91CD\u8BD5\r\n\r\n## \u5F53\u524D\u6A21\u578B\r\n- \u6A21\u578B\uFF1A{{model}}\r\n\r\n## \u65F6\u95F4\u4E0A\u4E0B\u6587\r\n- \u5F53\u524D\u65E5\u671F\uFF1A{{date}}\r\n- \u5F53\u524D\u65F6\u95F4\uFF1A{{time}}\r\n- \u5DE5\u4F5C\u76EE\u5F55\uFF1A{{cwd}}\r\n';
|
|
1989
2197
|
|
|
1990
2198
|
// src/agent/prompts/plan-prompt.hbs
|
|
1991
|
-
var plan_prompt_default = "\u4F60\u662F dskcode\uFF0C\u5F53\u524D\u5DE5\u4F5C\u5728**\u8BA1\u5212\u6A21\u5F0F\uFF08Plan Mode\uFF09**\u3002\r\n\r\n\u5728\u6B64\u6A21\u5F0F\u4E0B\uFF0C**\u4F60\u53EA\u80FD\u8BFB\u53D6\u548C\u5206\u6790\u4EE3\u7801\uFF0C\u4E0D\u80FD\u6267\u884C\u4EFB\u4F55\u4FEE\u6539\u64CD\u4F5C**\u3002\u4F60\u7684\u804C\u8D23\u662F\u5E2E\u52A9\u7528\u6237\u7406\u89E3\u4EE3\u7801\u3001\u8BBE\u8BA1\u67B6\u6784\u3001\u89C4\u5212\u4EFB\u52A1\u3001\u8BC4\u4F30\u65B9\u6848\u3002\r\n\r\n## \u6838\u5FC3\u539F\u5219\r\n- \u56DE\u7B54\u4F7F\u7528\u4E2D\u6587\uFF0C\u4EE3\u7801\u6807\u8BC6\u7B26\u4FDD\u6301\u82F1\u6587\r\n- \u63D0\u4F9B\u51C6\u786E\u3001\u5B9E\u7528\u3001\u53EF\u64CD\u4F5C\u7684\u5EFA\u8BAE\r\n- \u5BF9\u4E0D\u786E\u5B9A\u7684\u5185\u5BB9\u660E\u786E\u6807\u6CE8\uFF0C\u4E0D\u7F16\u9020\u4E8B\u5B9E\r\n- **\u7EDD\u4E0D\u6267\u884C\u4EFB\u4F55\u5199\u64CD\u4F5C** \u2014 \u4F60\u53EA\u80FD\u8BFB\u53D6\u548C\u5206\u6790\r\n\r\n## \u5DE5\u4F5C\u6D41\u7A0B\r\n1. \u6536\u5230\u7528\u6237\u8BF7\u6C42\r\n2. \u4F7F\u7528\u8BFB\u5DE5\u5177\uFF08read-file, grep, glob, ls, fetch\uFF09\u63A2\u7D22\u4EE3\u7801\u5E93\r\n3. \u6839\u636E\u53D1\u73B0\u7684\u4FE1\u606F\u63D0\u4F9B\u7ED3\u6784\u5316\u7684\u5206\u6790\u6216\u8BA1\u5212\r\n4. \u5DE5\u5177\u8FD4\u56DE\u51FA\u9519\u65F6\u5206\u6790\u539F\u56E0\u5E76\u4FEE\u6B63\u540E\u91CD\u8BD5\r\n5. \u5B8C\u6210\u540E\u8F93\u51FA\u6700\u7EC8\u5206\u6790\u7ED3\u679C\r\n\r\n## \u5DE5\u5177\u9650\u5236\r\n**\u4F60\u53EA\u80FD\u4F7F\u7528\u8BFB\u5DE5\u5177**\uFF0C\u4E0D\u80FD\u4F7F\u7528\u4EFB\u4F55\u5199\u5DE5\u5177\uFF08write-file, edit-file, multi-edit, delete-range, bash\uFF09\u3002\r\n\u5982\u679C\u7528\u6237\u8BF7\u6C42\u4FEE\u6539\u4EE3\u7801\uFF0C\u8BF7\uFF1A\r\n- \u63D0\u4F9B\u4FEE\u6539\u5EFA\u8BAE\u548C\u65B9\u6848\r\n- \u6307\u51FA\u9700\u8981\u4FEE\u6539\u7684\u6587\u4EF6\u548C\u4F4D\u7F6E\r\n- \u89E3\u91CA\u4FEE\u6539\u7684\u5F71\u54CD\r\n- \u4F46\u4E0D\u6267\u884C\u4EFB\u4F55\u4FEE\u6539\r\n\r\n## \u8BA1\u5212\u8F93\u51FA\u683C\u5F0F\r\n\r\n\u5F53\u7528\u6237\u8BF7\u6C42\u8BA1\u5212/\u65B9\u6848\u65F6\uFF0C\u5EFA\u8BAE\u6309\u7167\u4EE5\u4E0B\u7ED3\u6784\u7EC4\u7EC7\u8F93\u51FA\uFF1A\r\n\r\n\u{1F4CB} **\u6982\u8FF0**\r\n 1-2 \u53E5\u8BDD\u8BF4\u660E\u8981\u505A\u4EC0\u4E48\u4EE5\u53CA\u4E3A\u4EC0\u4E48\u8981\u505A\r\n\r\n\u{1F50D} **\u73B0\u72B6\u5206\u6790**\r\n \u5F53\u524D\u4EE3\u7801\u7684\u7EC4\u7EC7\u7ED3\u6784\u548C\u5173\u952E\u53D1\u73B0\r\n\r\n\u26A1 **\u5F71\u54CD\u8303\u56F4**\r\n \u54EA\u4E9B\u6587\u4EF6/\u6A21\u5757\u4F1A\u53D7\u5230\u5F71\u54CD\r\n\r\n\u{1F4DD} **\u5B9E\u65BD\u6B65\u9AA4**\r\n 1. \u7B2C\u4E00\u6B65\uFF08\u6587\u4EF6\u8DEF\u5F84/\u53D8\u66F4\u8BF4\u660E\uFF09\r\n 2. \u7B2C\u4E8C\u6B65\uFF08\u6587\u4EF6\u8DEF\u5F84/\u53D8\u66F4\u8BF4\u660E\uFF09\r\n 3. ...\r\n\r\n\u26A0\uFE0F **\u98CE\u9669\u4E0E\u6CE8\u610F\u4E8B\u9879**\r\n \u53EF\u80FD\u7684\u98CE\u9669\u70B9\u3001\u4F9D\u8D56\u5173\u7CFB\u3001\u56DE\u9000\u7B56\u7565\r\n\r\n## \u56DE\u7B54\u683C\u5F0F\r\n\r\n\u7EC8\u7AEF\u4E0D\u652F\u6301 Markdown \u6E32\u67D3\u3002\u56DE\u590D\u683C\u5F0F\u8981\u6C42\uFF1A\r\n- \u7528 emoji \u505A\u89C6\u89C9\u6807\u8BB0\r\n- \u7528\u6570\u5B57\u5E8F\u53F7\u6216\u77ED\u6A2A\u7EBF\u7EC4\u7EC7\u5217\u8868\r\n- \u4EE3\u7801\u6807\u8BC6\u7B26\u3001\u6587\u4EF6\u8DEF\u5F84\u7528\u5355\u4E2A\u53CD\u5F15\u53F7 ` \u5305\u88F9\r\n- \u591A\u884C\u4EE3\u7801\u7528\u7F29\u8FDB 4 \u4E2A\u7A7A\u683C\u8868\u793A\r\n- \u6BB5\u843D\u95F4\u7528\u7A7A\u884C\u5206\u9694\r\n- **\u4E0D\u8981\u4F7F\u7528 `#` \u7B26\u53F7** \u2014 \u7EC8\u7AEF\u4E0D\u6E32\u67D3 Markdown \u6807\u9898\uFF0C\u8BF7\u7528 emoji + \u52A0\u7C97\u66FF\u4EE3\r\n\r\n## \u5F53\u524D\u6A21\u578B\r\n- \u6A21\u578B\uFF1A{{model}}\r\n\r\n## \u65F6\u95F4\u4E0A\u4E0B\u6587\r\n- \u5F53\u524D\u65E5\u671F\uFF1A{{date}}\r\n- \u5F53\u524D\u65F6\u95F4\uFF1A{{time}}\r\n- \u5DE5\u4F5C\u76EE\u5F55\uFF1A{{cwd}}\r\n";
|
|
2199
|
+
var plan_prompt_default = "\u4F60\u662F dskcode\uFF0C\u5F53\u524D\u5DE5\u4F5C\u5728**\u8BA1\u5212\u6A21\u5F0F\uFF08Plan Mode\uFF09**\u3002\r\n\r\n\u5728\u6B64\u6A21\u5F0F\u4E0B\uFF0C**\u4F60\u53EA\u80FD\u8BFB\u53D6\u548C\u5206\u6790\u4EE3\u7801\uFF0C\u4E0D\u80FD\u6267\u884C\u4EFB\u4F55\u4FEE\u6539\u64CD\u4F5C**\u3002\u4F60\u7684\u804C\u8D23\u662F\u5E2E\u52A9\u7528\u6237\u7406\u89E3\u4EE3\u7801\u3001\u8BBE\u8BA1\u67B6\u6784\u3001\u89C4\u5212\u4EFB\u52A1\u3001\u8BC4\u4F30\u65B9\u6848\u3002\r\n\r\n## \u6838\u5FC3\u539F\u5219\r\n- \u56DE\u7B54\u4F7F\u7528\u4E2D\u6587\uFF0C\u4EE3\u7801\u6807\u8BC6\u7B26\u4FDD\u6301\u82F1\u6587\r\n- **\u601D\u8003\u8FC7\u7A0B\uFF08CoT\uFF09\u4E5F\u4F7F\u7528\u4E2D\u6587**\uFF0C\u4E0D\u8981\u7528\u82F1\u6587\u601D\u8003\u3002\r\n- \u63D0\u4F9B\u51C6\u786E\u3001\u5B9E\u7528\u3001\u53EF\u64CD\u4F5C\u7684\u5EFA\u8BAE\r\n- \u5BF9\u4E0D\u786E\u5B9A\u7684\u5185\u5BB9\u660E\u786E\u6807\u6CE8\uFF0C\u4E0D\u7F16\u9020\u4E8B\u5B9E\r\n- **\u7EDD\u4E0D\u6267\u884C\u4EFB\u4F55\u5199\u64CD\u4F5C** \u2014 \u4F60\u53EA\u80FD\u8BFB\u53D6\u548C\u5206\u6790\r\n\r\n## \u7528\u6237\u8F93\u5165\u8BED\u6CD5\r\n- `@<\u8DEF\u5F84>` \u8868\u793A\u4E00\u4E2A**\u6587\u4EF6\u8DEF\u5F84**\u7684\u5F15\u7528\u6807\u8BC6\u3002`@` \u4E0D\u662F\u90AE\u7BB1\u7B26\u53F7\u3001\u4E5F\u4E0D\u662F\u88C5\u9970\u540E\u7F00\u3002\r\n - `@test.ts` = \u5F15\u7528\u5F53\u524D\u76EE\u5F55\u4E0B\u540D\u4E3A `test.ts` \u7684\u6587\u4EF6\r\n - `@src/foo/bar.ts` = \u5F15\u7528 `src/foo/bar.ts`\r\n - \u591A\u4E2A\u5F15\u7528\uFF1A`\u8BF7\u8BFB @a.ts \u548C @b/d.ts`\r\n - \u8DEF\u5F84\u53EF\u4EE5\u662F\u76F8\u5BF9\u8DEF\u5F84\uFF08\u76F8\u5BF9\u5DE5\u4F5C\u76EE\u5F55\uFF09\u6216\u7EDD\u5BF9\u8DEF\u5F84\r\n- `\\/<\u547D\u4EE4>` \u8868\u793A\u4E00\u4E2A**\u659C\u6760\u547D\u4EE4**\uFF08\u5982 `\\/help`\u3001`\\/plan`\u3001`\\/code`\uFF09\uFF0C\u4E0D\u662F\u76EE\u5F55\u3002\r\n - \u6536\u5230 `/xxx` \u5F00\u5934\u7684\u5185\u5BB9\u5148\u5224\u5B9A\u662F\u4E0D\u662F\u5DF2\u6CE8\u518C\u547D\u4EE4\uFF1B\u4E0D\u662F\u5219\u5F53\u4F5C\u666E\u901A\u6587\u672C\u5904\u7406\u3002\r\n- \u4E0A\u8FF0\u4E24\u79CD\u524D\u7F00\u662F**\u7528\u6237\u8F93\u5165\u9762**\u8BED\u6CD5\uFF0C\u4F60**\u4E0D\u8981\u5728\u56DE\u590D\u4E2D\u8F93\u51FA**\u5B83\u4EEC\uFF08\u4E0D\u8981\u4F2A\u9020 `@/path` \u8FD9\u79CD\u4F2A\u5F15\u7528\uFF09\u3002\u5982\u679C\u8981\u5F15\u7528\u6587\u4EF6\uFF0C\u76F4\u63A5\u7528\u5355\u53CD\u5F15\u53F7\u5305\u88F9\u8DEF\u5F84\uFF08\u5982 `src/foo.ts`\uFF09\u3002\r\n\r\n## \u5DE5\u4F5C\u6D41\u7A0B\r\n1. \u6536\u5230\u7528\u6237\u8BF7\u6C42\r\n2. \u4F7F\u7528\u8BFB\u5DE5\u5177\uFF08read-file, grep, glob, ls, fetch\uFF09\u63A2\u7D22\u4EE3\u7801\u5E93\r\n3. \u6839\u636E\u53D1\u73B0\u7684\u4FE1\u606F\u63D0\u4F9B\u7ED3\u6784\u5316\u7684\u5206\u6790\u6216\u8BA1\u5212\r\n4. \u5DE5\u5177\u8FD4\u56DE\u51FA\u9519\u65F6\u5206\u6790\u539F\u56E0\u5E76\u4FEE\u6B63\u540E\u91CD\u8BD5\r\n5. \u5B8C\u6210\u540E\u8F93\u51FA\u6700\u7EC8\u5206\u6790\u7ED3\u679C\r\n\r\n## \u5DE5\u5177\u9650\u5236\r\n**\u4F60\u53EA\u80FD\u4F7F\u7528\u8BFB\u5DE5\u5177**\uFF0C\u4E0D\u80FD\u4F7F\u7528\u4EFB\u4F55\u5199\u5DE5\u5177\uFF08write-file, edit-file, multi-edit, delete-range, bash\uFF09\u3002\r\n\u5982\u679C\u7528\u6237\u8BF7\u6C42\u4FEE\u6539\u4EE3\u7801\uFF0C\u8BF7\uFF1A\r\n- \u63D0\u4F9B\u4FEE\u6539\u5EFA\u8BAE\u548C\u65B9\u6848\r\n- \u6307\u51FA\u9700\u8981\u4FEE\u6539\u7684\u6587\u4EF6\u548C\u4F4D\u7F6E\r\n- \u89E3\u91CA\u4FEE\u6539\u7684\u5F71\u54CD\r\n- \u4F46\u4E0D\u6267\u884C\u4EFB\u4F55\u4FEE\u6539\r\n\r\n## \u8BA1\u5212\u8F93\u51FA\u683C\u5F0F\r\n\r\n\u5F53\u7528\u6237\u8BF7\u6C42\u8BA1\u5212/\u65B9\u6848\u65F6\uFF0C\u5EFA\u8BAE\u6309\u7167\u4EE5\u4E0B\u7ED3\u6784\u7EC4\u7EC7\u8F93\u51FA\uFF1A\r\n\r\n\u{1F4CB} **\u6982\u8FF0**\r\n 1-2 \u53E5\u8BDD\u8BF4\u660E\u8981\u505A\u4EC0\u4E48\u4EE5\u53CA\u4E3A\u4EC0\u4E48\u8981\u505A\r\n\r\n\u{1F50D} **\u73B0\u72B6\u5206\u6790**\r\n \u5F53\u524D\u4EE3\u7801\u7684\u7EC4\u7EC7\u7ED3\u6784\u548C\u5173\u952E\u53D1\u73B0\r\n\r\n\u26A1 **\u5F71\u54CD\u8303\u56F4**\r\n \u54EA\u4E9B\u6587\u4EF6/\u6A21\u5757\u4F1A\u53D7\u5230\u5F71\u54CD\r\n\r\n\u{1F4DD} **\u5B9E\u65BD\u6B65\u9AA4**\r\n 1. \u7B2C\u4E00\u6B65\uFF08\u6587\u4EF6\u8DEF\u5F84/\u53D8\u66F4\u8BF4\u660E\uFF09\r\n 2. \u7B2C\u4E8C\u6B65\uFF08\u6587\u4EF6\u8DEF\u5F84/\u53D8\u66F4\u8BF4\u660E\uFF09\r\n 3. ...\r\n\r\n\u26A0\uFE0F **\u98CE\u9669\u4E0E\u6CE8\u610F\u4E8B\u9879**\r\n \u53EF\u80FD\u7684\u98CE\u9669\u70B9\u3001\u4F9D\u8D56\u5173\u7CFB\u3001\u56DE\u9000\u7B56\u7565\r\n\r\n## \u56DE\u7B54\u683C\u5F0F\r\n\r\n\u7EC8\u7AEF\u4E0D\u652F\u6301 Markdown \u6E32\u67D3\u3002\u56DE\u590D\u683C\u5F0F\u8981\u6C42\uFF1A\r\n- \u7528 emoji \u505A\u89C6\u89C9\u6807\u8BB0\r\n- \u7528\u6570\u5B57\u5E8F\u53F7\u6216\u77ED\u6A2A\u7EBF\u7EC4\u7EC7\u5217\u8868\r\n- \u4EE3\u7801\u6807\u8BC6\u7B26\u3001\u6587\u4EF6\u8DEF\u5F84\u7528\u5355\u4E2A\u53CD\u5F15\u53F7 ` \u5305\u88F9\r\n- \u591A\u884C\u4EE3\u7801\u7528\u7F29\u8FDB 4 \u4E2A\u7A7A\u683C\u8868\u793A\r\n- \u6BB5\u843D\u95F4\u7528\u7A7A\u884C\u5206\u9694\r\n- **\u4E0D\u8981\u4F7F\u7528 `#` \u7B26\u53F7** \u2014 \u7EC8\u7AEF\u4E0D\u6E32\u67D3 Markdown \u6807\u9898\uFF0C\u8BF7\u7528 emoji + \u52A0\u7C97\u66FF\u4EE3\r\n\r\n## \u5F53\u524D\u6A21\u578B\r\n- \u6A21\u578B\uFF1A{{model}}\r\n\r\n## \u65F6\u95F4\u4E0A\u4E0B\u6587\r\n- \u5F53\u524D\u65E5\u671F\uFF1A{{date}}\r\n- \u5F53\u524D\u65F6\u95F4\uFF1A{{time}}\r\n- \u5DE5\u4F5C\u76EE\u5F55\uFF1A{{cwd}}\r\n";
|
|
1992
2200
|
|
|
1993
2201
|
// src/agent/system-prompt.ts
|
|
1994
2202
|
var compiledTemplate = Handlebars.compile(system_prompt_default);
|
|
@@ -2581,68 +2789,492 @@ function buildToolDefinitions(registry2, mode) {
|
|
|
2581
2789
|
}));
|
|
2582
2790
|
}
|
|
2583
2791
|
|
|
2584
|
-
// src/
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2792
|
+
// src/harness/todo-list.ts
|
|
2793
|
+
var TodoList = class {
|
|
2794
|
+
#items = [];
|
|
2795
|
+
#nextId = 0;
|
|
2796
|
+
/**
|
|
2797
|
+
* 新增一个 todo,返回分配的 id。
|
|
2798
|
+
*
|
|
2799
|
+
* @param content — 步骤描述(中文)
|
|
2800
|
+
* @param deps — 依赖的 todo id 列表;为空表示无依赖,立即可 running
|
|
2801
|
+
* @returns 新 todo 的 id
|
|
2802
|
+
* @throws 当 deps 引用了不存在的 id 时抛出,避免 LLM 错把不存在的依赖塞进计划
|
|
2803
|
+
*/
|
|
2804
|
+
add(content, deps = []) {
|
|
2805
|
+
for (const d of deps) {
|
|
2806
|
+
if (!this.#items.find((it) => it.id === d)) {
|
|
2807
|
+
throw new Error(`todo \u4F9D\u8D56 #${d} \u4E0D\u5B58\u5728\uFF08\u5DF2\u5206\u914D\u7684 id: ${this.#items.map((it) => it.id).join(", ") || "(\u7A7A)"}\uFF09`);
|
|
2808
|
+
}
|
|
2809
|
+
}
|
|
2810
|
+
const id = this.#nextId++;
|
|
2811
|
+
this.#items.push({
|
|
2812
|
+
id,
|
|
2813
|
+
content,
|
|
2814
|
+
status: "pending",
|
|
2815
|
+
deps: [...deps],
|
|
2816
|
+
updatedAt: Date.now()
|
|
2817
|
+
});
|
|
2818
|
+
return id;
|
|
2819
|
+
}
|
|
2820
|
+
/**
|
|
2821
|
+
* 把失败的 todo 重置回 pending(用于"重试"工作流)。
|
|
2822
|
+
*
|
|
2823
|
+
* 不允许把 done / skipped 重置(一旦完成不应反悔)。
|
|
2824
|
+
* 不允许把 running 重置(应该先 markFailed 再重试)。
|
|
2825
|
+
*
|
|
2826
|
+
* @param id — todo id
|
|
2827
|
+
* @returns 是否成功
|
|
2828
|
+
*/
|
|
2829
|
+
resetForRetry(id) {
|
|
2830
|
+
const item = this.#find(id);
|
|
2831
|
+
if (!item) return false;
|
|
2832
|
+
if (item.status !== "failed") return false;
|
|
2833
|
+
item.status = "pending";
|
|
2834
|
+
item.evidence = void 0;
|
|
2835
|
+
item.updatedAt = Date.now();
|
|
2592
2836
|
return true;
|
|
2593
|
-
} catch {
|
|
2594
|
-
return false;
|
|
2595
2837
|
}
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2838
|
+
/**
|
|
2839
|
+
* 把 todo 标记为 running。
|
|
2840
|
+
*
|
|
2841
|
+
* 前提:该 todo 存在 + 当前是 pending + 依赖全 done。
|
|
2842
|
+
* 不满足时静默返回 false(不抛错,避免污染 agent 主循环)。
|
|
2843
|
+
*
|
|
2844
|
+
* @param id — todo id
|
|
2845
|
+
* @returns 是否成功转换
|
|
2846
|
+
*/
|
|
2847
|
+
markRunning(id) {
|
|
2848
|
+
const item = this.#find(id);
|
|
2849
|
+
if (!item) return false;
|
|
2850
|
+
if (item.status !== "pending") return false;
|
|
2851
|
+
if (!this.#depsAllDone(item.deps)) return false;
|
|
2852
|
+
item.status = "running";
|
|
2853
|
+
item.updatedAt = Date.now();
|
|
2600
2854
|
return true;
|
|
2601
|
-
} catch {
|
|
2602
|
-
return false;
|
|
2603
2855
|
}
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2856
|
+
/**
|
|
2857
|
+
* 标记完成。
|
|
2858
|
+
*
|
|
2859
|
+
* @param id — todo id
|
|
2860
|
+
* @param evidence — 完成证据(如 "读取成功"、"type-check 通过")
|
|
2861
|
+
* @returns 是否成功
|
|
2862
|
+
*/
|
|
2863
|
+
markDone(id, evidence) {
|
|
2864
|
+
const item = this.#find(id);
|
|
2865
|
+
if (!item) return false;
|
|
2866
|
+
if (item.status !== "running" && item.status !== "pending") return false;
|
|
2867
|
+
item.status = "done";
|
|
2868
|
+
if (evidence !== void 0) item.evidence = evidence;
|
|
2869
|
+
item.updatedAt = Date.now();
|
|
2870
|
+
return true;
|
|
2616
2871
|
}
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
const newSha = newShas.find((s) => !beforeShas.includes(s)) ?? newShas[0];
|
|
2633
|
-
await git(["stash", "apply", newSha], cwd);
|
|
2634
|
-
return { stashSha: newSha, timestamp, cwd, isGitRepo: true };
|
|
2635
|
-
}
|
|
2636
|
-
async function restoreCheckpointForce(checkpoint) {
|
|
2637
|
-
if (!checkpoint.isGitRepo) throw new Error("\u975E git \u4ED3\u5E93\uFF0C\u65E0\u6CD5\u6062\u590D\u6587\u4EF6\u72B6\u6001");
|
|
2638
|
-
if (!checkpoint.stashSha) throw new Error("\u68C0\u67E5\u70B9\u4E3A\u7A7A\uFF08\u5DE5\u4F5C\u533A\u539F\u672C\u5C31\u5E72\u51C0\uFF09\uFF0C\u65E0\u9700\u6062\u590D");
|
|
2639
|
-
const { cwd, stashSha } = checkpoint;
|
|
2640
|
-
const currentShas = await listStashShas(cwd);
|
|
2641
|
-
if (!currentShas.includes(stashSha)) {
|
|
2642
|
-
throw new Error("\u68C0\u67E5\u70B9\u5DF2\u5931\u6548\uFF08stash entry \u5DF2\u88AB\u6D88\u8D39\u6216 GC\uFF09\uFF0C\u65E0\u6CD5\u6062\u590D");
|
|
2872
|
+
/**
|
|
2873
|
+
* 标记失败。
|
|
2874
|
+
*
|
|
2875
|
+
* @param id — todo id
|
|
2876
|
+
* @param reason — 失败原因(人类可读)
|
|
2877
|
+
* @returns 是否成功
|
|
2878
|
+
*/
|
|
2879
|
+
markFailed(id, reason) {
|
|
2880
|
+
const item = this.#find(id);
|
|
2881
|
+
if (!item) return false;
|
|
2882
|
+
if (item.status === "done") return false;
|
|
2883
|
+
item.status = "failed";
|
|
2884
|
+
item.evidence = reason;
|
|
2885
|
+
item.updatedAt = Date.now();
|
|
2886
|
+
return true;
|
|
2643
2887
|
}
|
|
2644
|
-
|
|
2645
|
-
|
|
2888
|
+
/**
|
|
2889
|
+
* 标记跳过。
|
|
2890
|
+
*
|
|
2891
|
+
* @param id — todo id
|
|
2892
|
+
* @param reason — 跳过原因(如 "项目无测试基建")
|
|
2893
|
+
* @returns 是否成功
|
|
2894
|
+
*/
|
|
2895
|
+
markSkipped(id, reason) {
|
|
2896
|
+
const item = this.#find(id);
|
|
2897
|
+
if (!item) return false;
|
|
2898
|
+
if (item.status === "done" || item.status === "failed") return false;
|
|
2899
|
+
item.status = "skipped";
|
|
2900
|
+
item.evidence = reason;
|
|
2901
|
+
item.updatedAt = Date.now();
|
|
2902
|
+
return true;
|
|
2903
|
+
}
|
|
2904
|
+
/**
|
|
2905
|
+
* 取出所有"立即可做"的 todo(deps 全 done 且 pending)。
|
|
2906
|
+
*
|
|
2907
|
+
* @returns 可执行的 todo 列表
|
|
2908
|
+
*/
|
|
2909
|
+
pending() {
|
|
2910
|
+
return this.#items.filter(
|
|
2911
|
+
(it) => it.status === "pending" && this.#depsAllDone(it.deps)
|
|
2912
|
+
);
|
|
2913
|
+
}
|
|
2914
|
+
/**
|
|
2915
|
+
* 取出所有未完成项(pending / running / failed)。
|
|
2916
|
+
*/
|
|
2917
|
+
unfinished() {
|
|
2918
|
+
return this.#items.filter(
|
|
2919
|
+
(it) => it.status === "pending" || it.status === "running" || it.status === "failed"
|
|
2920
|
+
);
|
|
2921
|
+
}
|
|
2922
|
+
/**
|
|
2923
|
+
* 是否全部结束(done / failed / skipped)。
|
|
2924
|
+
*/
|
|
2925
|
+
isAllTerminated() {
|
|
2926
|
+
return this.#items.every(
|
|
2927
|
+
(it) => it.status === "done" || it.status === "failed" || it.status === "skipped"
|
|
2928
|
+
);
|
|
2929
|
+
}
|
|
2930
|
+
/** 全部条目(只读快照) */
|
|
2931
|
+
get items() {
|
|
2932
|
+
return this.#items;
|
|
2933
|
+
}
|
|
2934
|
+
/**
|
|
2935
|
+
* 把 todo 列表拼成 markdown,用于注入 system prompt。
|
|
2936
|
+
*
|
|
2937
|
+
* @param maxItems — 最多展示多少条;超出时保留"最近 N 条 + 进行中",折叠已完成
|
|
2938
|
+
* @returns markdown 字符串
|
|
2939
|
+
*/
|
|
2940
|
+
toMarkdown(maxItems = 20) {
|
|
2941
|
+
if (this.#items.length === 0) return "";
|
|
2942
|
+
const active = this.#items.filter(
|
|
2943
|
+
(it) => it.status === "pending" || it.status === "running" || it.status === "failed"
|
|
2944
|
+
);
|
|
2945
|
+
const finished = this.#items.filter(
|
|
2946
|
+
(it) => it.status === "done" || it.status === "skipped"
|
|
2947
|
+
);
|
|
2948
|
+
const finishedSorted = [...finished].sort((a, b) => b.updatedAt - a.updatedAt);
|
|
2949
|
+
const truncated = finishedSorted.length > maxItems;
|
|
2950
|
+
const finishedToShow = truncated ? finishedSorted.slice(0, Math.max(0, maxItems - active.length)) : finishedSorted;
|
|
2951
|
+
const lines = [...active, ...finishedToShow].map((it) => {
|
|
2952
|
+
const box = this.#statusBox(it.status);
|
|
2953
|
+
const depStr = it.deps.length > 0 ? ` (\u4F9D\u8D56: #${it.deps.join(", #")})` : "";
|
|
2954
|
+
const eviStr = it.evidence ? ` \u2014 ${it.evidence}` : "";
|
|
2955
|
+
return `- ${box} #${it.id} ${it.content}${depStr}${eviStr}`;
|
|
2956
|
+
});
|
|
2957
|
+
if (truncated) {
|
|
2958
|
+
const hidden = finishedSorted.length - finishedToShow.length;
|
|
2959
|
+
lines.push(`- ...\uFF08\u53E6\u6709 ${hidden} \u6761\u5DF2\u5B8C\u6210\u5DF2\u6298\u53E0\uFF09`);
|
|
2960
|
+
}
|
|
2961
|
+
return [
|
|
2962
|
+
"## \u{1F4CB} \u5F53\u524D\u4EFB\u52A1\u8FDB\u5EA6",
|
|
2963
|
+
...lines,
|
|
2964
|
+
"",
|
|
2965
|
+
"\u89C4\u5219\uFF1A\u6309\u987A\u5E8F\u63A8\u8FDB\uFF1B\u672A\u5B8C\u6210\u4F9D\u8D56\u65F6\u4E0D\u8981\u8DF3\u6B65\uFF1B\u5B8C\u6210\u8BF7\u8C03\u7528 todo_mark_done\uFF0C\u5931\u8D25\u8BF7\u8C03\u7528 todo_mark_failed\uFF1B\u91CD\u8BD5\u5931\u8D25\u9879\u5148\u8C03 todo_retry \u518D\u91CD\u8DD1\u3002"
|
|
2966
|
+
].join("\n");
|
|
2967
|
+
}
|
|
2968
|
+
// -------------------------------------------------------------------------
|
|
2969
|
+
// 内部
|
|
2970
|
+
// -------------------------------------------------------------------------
|
|
2971
|
+
#find(id) {
|
|
2972
|
+
return this.#items.find((it) => it.id === id);
|
|
2973
|
+
}
|
|
2974
|
+
#depsAllDone(deps) {
|
|
2975
|
+
return deps.every((d) => {
|
|
2976
|
+
const item = this.#items.find((it) => it.id === d);
|
|
2977
|
+
return item?.status === "done" || item?.status === "skipped";
|
|
2978
|
+
});
|
|
2979
|
+
}
|
|
2980
|
+
#statusBox(status) {
|
|
2981
|
+
switch (status) {
|
|
2982
|
+
case "pending":
|
|
2983
|
+
return "\u2610";
|
|
2984
|
+
case "running":
|
|
2985
|
+
return "\u25B6";
|
|
2986
|
+
case "done":
|
|
2987
|
+
return "\u2705";
|
|
2988
|
+
case "failed":
|
|
2989
|
+
return "\u274C";
|
|
2990
|
+
case "skipped":
|
|
2991
|
+
return "\u23ED";
|
|
2992
|
+
}
|
|
2993
|
+
}
|
|
2994
|
+
};
|
|
2995
|
+
|
|
2996
|
+
// src/harness/tools.ts
|
|
2997
|
+
function createHarnessTools(todoList) {
|
|
2998
|
+
return [
|
|
2999
|
+
makeTodoAddTool(todoList),
|
|
3000
|
+
makeTodoMarkRunningTool(todoList),
|
|
3001
|
+
makeTodoMarkDoneTool(todoList),
|
|
3002
|
+
makeTodoMarkFailedTool(todoList),
|
|
3003
|
+
makeTodoRetryTool(todoList)
|
|
3004
|
+
];
|
|
3005
|
+
}
|
|
3006
|
+
function makeTodoAddTool(todoList) {
|
|
3007
|
+
return {
|
|
3008
|
+
name: "todo_add",
|
|
3009
|
+
kind: "other" /* Other */,
|
|
3010
|
+
description: '\u26A0\uFE0F \u3010\u590D\u6742\u4EFB\u52A1\u7B2C\u4E00\u6B65\u3011\u6DFB\u52A0\u4E00\u4E2A\u5F85\u529E\u5230\u5F53\u524D\u4EFB\u52A1\u8FDB\u5EA6\u3002\n\n\u4EC0\u4E48\u60C5\u51B5\u4E0B\u8C03\u6211\uFF1A\n - \u9700\u8981\u591A\u6B65\u624D\u80FD\u5B8C\u6210\uFF08\u6539\u591A\u4E2A\u6587\u4EF6 / \u8DE8\u591A\u8F6E\uFF09\n - \u9700\u5148\u8BFB\u540E\u6539\uFF08edit/write \u4E4B\u524D\uFF09\n - \u4F9D\u8D56\u5916\u90E8\u72B6\u6001\uFF08\u6587\u4EF6\u3001API\u3001\u8FD0\u884C\u7ED3\u679C\uFF09\n\n\u4EC0\u4E48\u60C5\u51B5\u4E0B\u4E0D\u8981\u8C03\uFF1A\n - \u4E00\u53E5\u8BDD\u80FD\u5B8C\u6210\u7684\u4E8B\uFF08\u67E5\u3001\u5217\u3001\u95EE\uFF09\n\n\u7528\u6CD5\uFF1A\u6BCF\u6B21\u52A0\u4E00\u4E2A step\uFF0C\u591A\u6B65\u5C31\u8C03\u591A\u6B21\u3002\u6709\u4F9D\u8D56\u5173\u7CFB\u4F20 deps=[\u524D\u6B65 id]\u3002\u8FD4\u56DE\u5206\u914D\u7684 id\uFF0C\u540E\u7EED\u7528 todo_mark_done / todo_mark_failed \u5F15\u7528\u3002\n\n\u793A\u4F8B\uFF1A\u7528\u6237\u8BF4\u300C\u628A X \u6539\u6210 Y\u300D\u2192 \u8C03 1) todo_add("\u8BFB X") 2) todo_add("\u6539 X", deps=[0]) 3) todo_add("\u68C0\u67E5\u6539\u52A8", deps=[1])',
|
|
3011
|
+
parameters: {
|
|
3012
|
+
type: "object",
|
|
3013
|
+
properties: {
|
|
3014
|
+
content: { type: "string", description: "\u6B65\u9AA4\u63CF\u8FF0\uFF08\u4E2D\u6587\uFF0C\u5EFA\u8BAE\u7B80\u6D01\uFF09" },
|
|
3015
|
+
deps: {
|
|
3016
|
+
type: "array",
|
|
3017
|
+
description: "\u4F9D\u8D56\u7684 todo id \u6570\u7EC4\uFF08\u8FD9\u4E9B\u90FD done \u540E\u672C\u9879\u624D\u53EF\u6267\u884C\uFF09",
|
|
3018
|
+
items: { type: "number" }
|
|
3019
|
+
}
|
|
3020
|
+
},
|
|
3021
|
+
required: ["content"],
|
|
3022
|
+
additionalProperties: false
|
|
3023
|
+
},
|
|
3024
|
+
async execute(args) {
|
|
3025
|
+
if (typeof args?.content !== "string" || args.content.length === 0) {
|
|
3026
|
+
return { success: false, data: "\u7F3A\u5C11 content \u53C2\u6570", error: "INVALID_ARGS" };
|
|
3027
|
+
}
|
|
3028
|
+
const deps = Array.isArray(args.deps) ? args.deps.filter((d) => typeof d === "number") : [];
|
|
3029
|
+
try {
|
|
3030
|
+
const id = todoList.add(args.content, deps);
|
|
3031
|
+
return {
|
|
3032
|
+
success: true,
|
|
3033
|
+
data: `\u5DF2\u6DFB\u52A0 todo #${id}\uFF1A${args.content}${deps.length > 0 ? `\uFF08\u4F9D\u8D56: ${deps.join(", ")})` : ""}`,
|
|
3034
|
+
summary: `\u{1F4CB} \u6DFB\u52A0 #${id}`
|
|
3035
|
+
};
|
|
3036
|
+
} catch (err) {
|
|
3037
|
+
return {
|
|
3038
|
+
success: false,
|
|
3039
|
+
data: err instanceof Error ? err.message : String(err),
|
|
3040
|
+
error: "TODO_DEPS_INVALID"
|
|
3041
|
+
};
|
|
3042
|
+
}
|
|
3043
|
+
}
|
|
3044
|
+
};
|
|
3045
|
+
}
|
|
3046
|
+
function makeTodoMarkRunningTool(todoList) {
|
|
3047
|
+
return {
|
|
3048
|
+
name: "todo_mark_running",
|
|
3049
|
+
kind: "other" /* Other */,
|
|
3050
|
+
description: "\u628A todo \u4ECE pending \u63A8\u8FDB\u5230 running\uFF0C\u8868\u793A\u4F60\u300C\u6B63\u5728\u505A\u300D\u8FD9\u4E00\u6B65\u3002\n\u524D\u63D0\uFF1A\u8BE5 todo \u5B58\u5728\u3001\u5F53\u524D\u662F pending\u3001\u4E14\u6240\u6709 deps \u5DF2 done \u6216 skipped\u3002\n\u5DE5\u4F5C\u6D41\uFF1A\u5148\u8C03 todo_mark_running\uFF0C\u518D\u53BB\u8C03\u5B9E\u9645\u7684\u5DE5\u5177\uFF08read_file / edit_file \u7B49\uFF09\uFF0C\u6700\u540E\u7528 todo_mark_done \u6216 todo_mark_failed \u6536\u5C3E\u3002\n**\u4E0D\u8981\u8DF3\u8FC7 mark_running \u76F4\u63A5 mark_done** \u2014 \u4F1A\u7834\u574F\u4F9D\u8D56\u68C0\u67E5\uFF0C\u4E0B\u6E38\u6B65\u9AA4\u53EF\u80FD\u8BEF\u4EE5\u4E3A\u4F9D\u8D56\u5DF2\u6EE1\u8DB3\u3002",
|
|
3051
|
+
parameters: {
|
|
3052
|
+
type: "object",
|
|
3053
|
+
properties: {
|
|
3054
|
+
id: { type: "number", description: "todo \u7684 id" }
|
|
3055
|
+
},
|
|
3056
|
+
required: ["id"],
|
|
3057
|
+
additionalProperties: false
|
|
3058
|
+
},
|
|
3059
|
+
async execute(args) {
|
|
3060
|
+
if (typeof args?.id !== "number") {
|
|
3061
|
+
return { success: false, data: "\u7F3A\u5C11 id \u53C2\u6570", error: "INVALID_ARGS" };
|
|
3062
|
+
}
|
|
3063
|
+
const item = todoList.items.find((it) => it.id === args.id);
|
|
3064
|
+
if (!item) {
|
|
3065
|
+
return { success: false, data: `todo #${args.id} \u4E0D\u5B58\u5728`, error: "TODO_NOT_FOUND" };
|
|
3066
|
+
}
|
|
3067
|
+
if (item.status !== "pending") {
|
|
3068
|
+
return {
|
|
3069
|
+
success: false,
|
|
3070
|
+
data: `todo #${args.id} \u5F53\u524D\u72B6\u6001\u662F ${item.status}\uFF0C\u53EA\u6709 pending \u53EF\u4EE5\u63A8\u8FDB\u5230 running`,
|
|
3071
|
+
error: "TODO_INVALID_STATE"
|
|
3072
|
+
};
|
|
3073
|
+
}
|
|
3074
|
+
const ok = todoList.markRunning(args.id);
|
|
3075
|
+
if (!ok) {
|
|
3076
|
+
return {
|
|
3077
|
+
success: false,
|
|
3078
|
+
data: `todo #${args.id} \u4F9D\u8D56\u672A\u5168\u90E8\u5B8C\u6210\uFF08\u4F9D\u8D56: #${item.deps.join(", #")}\uFF09`,
|
|
3079
|
+
error: "TODO_DEPS_NOT_READY"
|
|
3080
|
+
};
|
|
3081
|
+
}
|
|
3082
|
+
return {
|
|
3083
|
+
success: true,
|
|
3084
|
+
data: `\u5DF2\u5F00\u59CB todo #${args.id}\uFF1A${item.content}`,
|
|
3085
|
+
summary: `\u25B6 \u5F00\u59CB #${args.id}`
|
|
3086
|
+
};
|
|
3087
|
+
}
|
|
3088
|
+
};
|
|
3089
|
+
}
|
|
3090
|
+
function makeTodoMarkDoneTool(todoList) {
|
|
3091
|
+
return {
|
|
3092
|
+
name: "todo_mark_done",
|
|
3093
|
+
kind: "other" /* Other */,
|
|
3094
|
+
description: "\u628A todo \u6807\u8BB0\u4E3A\u5B8C\u6210\u3002evidence \u586B\u300C\u5B8C\u6210\u8BC1\u636E\u300D\uFF08\u5982\u300C\u8BFB\u5230 120 \u884C\u300D\u3001\u300Ctypecheck \u901A\u8FC7\u300D\u3001\u300Cedit \u6210\u529F\u300D\uFF09\uFF0C\u4E0D\u586B\u4E5F\u884C\u3002\n\u524D\u63D0\uFF1A\u5F53\u524D\u72B6\u6001\u5FC5\u987B\u662F running\u3002\u82E5\u8FD8\u662F pending\uFF0C\u5148\u8C03 todo_mark_running\u3002",
|
|
3095
|
+
parameters: {
|
|
3096
|
+
type: "object",
|
|
3097
|
+
properties: {
|
|
3098
|
+
id: { type: "number", description: "todo \u7684 id" },
|
|
3099
|
+
evidence: { type: "string", description: "\u5B8C\u6210\u8BC1\u636E\uFF08\u4E00\u53E5\u8BDD\uFF0C\u53EF\u9009\uFF09" }
|
|
3100
|
+
},
|
|
3101
|
+
required: ["id"],
|
|
3102
|
+
additionalProperties: false
|
|
3103
|
+
},
|
|
3104
|
+
async execute(args) {
|
|
3105
|
+
if (typeof args?.id !== "number") {
|
|
3106
|
+
return { success: false, data: "\u7F3A\u5C11 id \u53C2\u6570", error: "INVALID_ARGS" };
|
|
3107
|
+
}
|
|
3108
|
+
const item = todoList.items.find((it) => it.id === args.id);
|
|
3109
|
+
if (!item) {
|
|
3110
|
+
return { success: false, data: `todo #${args.id} \u4E0D\u5B58\u5728`, error: "TODO_NOT_FOUND" };
|
|
3111
|
+
}
|
|
3112
|
+
if (item.status !== "running") {
|
|
3113
|
+
return {
|
|
3114
|
+
success: false,
|
|
3115
|
+
data: `todo #${args.id} \u5F53\u524D\u72B6\u6001\u662F ${item.status}\uFF0C\u53EA\u6709 running \u53EF\u4EE5 mark_done\uFF1B\u5982\u9700\u91CD\u8BD5\u8BF7\u5148 todo_retry`,
|
|
3116
|
+
error: "TODO_INVALID_STATE"
|
|
3117
|
+
};
|
|
3118
|
+
}
|
|
3119
|
+
const ok = todoList.markDone(args.id, args.evidence);
|
|
3120
|
+
if (!ok) {
|
|
3121
|
+
return { success: false, data: `todo #${args.id} \u72B6\u6001\u8F6C\u6362\u5931\u8D25`, error: "TODO_INVALID" };
|
|
3122
|
+
}
|
|
3123
|
+
return {
|
|
3124
|
+
success: true,
|
|
3125
|
+
data: `\u5DF2\u6807\u8BB0 todo #${args.id} \u5B8C\u6210${args.evidence ? `\uFF1A${args.evidence}` : ""}`,
|
|
3126
|
+
summary: `\u2705 \u5B8C\u6210 #${args.id}`
|
|
3127
|
+
};
|
|
3128
|
+
}
|
|
3129
|
+
};
|
|
3130
|
+
}
|
|
3131
|
+
function makeTodoMarkFailedTool(todoList) {
|
|
3132
|
+
return {
|
|
3133
|
+
name: "todo_mark_failed",
|
|
3134
|
+
kind: "other" /* Other */,
|
|
3135
|
+
description: "\u628A todo \u6807\u8BB0\u4E3A\u5931\u8D25\uFF0Creason \u586B\u300C\u5931\u8D25\u539F\u56E0\u300D\uFF08\u5982\u300Cold_text \u62FC\u9519\u300D\u3001\u300C\u6587\u4EF6\u4E0D\u5B58\u5728\u300D\uFF09\u3002\n\u524D\u63D0\uFF1A\u5F53\u524D\u72B6\u6001\u5FC5\u987B\u662F running\u3002\u82E5\u8FD8\u662F pending\uFF0C\u5148\u8C03 todo_mark_running\u3002\n\u8C03\u7528\u540E\u8BE5 step \u72B6\u6001\u53D8\u4E3A failed\u3002\u60F3\u91CD\u8BD5\uFF1A\u8C03 todo_retry(id) \u91CD\u7F6E\u56DE pending\uFF0C\u518D mark_running \u2192 \u8DD1\u5DE5\u5177 \u2192 mark_done\u3002",
|
|
3136
|
+
parameters: {
|
|
3137
|
+
type: "object",
|
|
3138
|
+
properties: {
|
|
3139
|
+
id: { type: "number", description: "todo \u7684 id" },
|
|
3140
|
+
reason: { type: "string", description: "\u5931\u8D25\u539F\u56E0\uFF08\u4E00\u53E5\u8BDD\uFF09" }
|
|
3141
|
+
},
|
|
3142
|
+
required: ["id", "reason"],
|
|
3143
|
+
additionalProperties: false
|
|
3144
|
+
},
|
|
3145
|
+
async execute(args) {
|
|
3146
|
+
if (typeof args?.id !== "number") {
|
|
3147
|
+
return { success: false, data: "\u7F3A\u5C11 id \u53C2\u6570", error: "INVALID_ARGS" };
|
|
3148
|
+
}
|
|
3149
|
+
if (typeof args?.reason !== "string") {
|
|
3150
|
+
return { success: false, data: "\u7F3A\u5C11 reason \u53C2\u6570", error: "INVALID_ARGS" };
|
|
3151
|
+
}
|
|
3152
|
+
const item = todoList.items.find((it) => it.id === args.id);
|
|
3153
|
+
if (!item) {
|
|
3154
|
+
return { success: false, data: `todo #${args.id} \u4E0D\u5B58\u5728`, error: "TODO_NOT_FOUND" };
|
|
3155
|
+
}
|
|
3156
|
+
if (item.status !== "running") {
|
|
3157
|
+
return {
|
|
3158
|
+
success: false,
|
|
3159
|
+
data: `todo #${args.id} \u5F53\u524D\u72B6\u6001\u662F ${item.status}\uFF0C\u53EA\u6709 running \u53EF\u4EE5 mark_failed`,
|
|
3160
|
+
error: "TODO_INVALID_STATE"
|
|
3161
|
+
};
|
|
3162
|
+
}
|
|
3163
|
+
const ok = todoList.markFailed(args.id, args.reason);
|
|
3164
|
+
if (!ok) {
|
|
3165
|
+
return { success: false, data: `todo #${args.id} \u72B6\u6001\u8F6C\u6362\u5931\u8D25`, error: "TODO_INVALID" };
|
|
3166
|
+
}
|
|
3167
|
+
return {
|
|
3168
|
+
success: true,
|
|
3169
|
+
data: `\u5DF2\u6807\u8BB0 todo #${args.id} \u5931\u8D25\uFF1A${args.reason}`,
|
|
3170
|
+
summary: `\u274C \u5931\u8D25 #${args.id}`
|
|
3171
|
+
};
|
|
3172
|
+
}
|
|
3173
|
+
};
|
|
3174
|
+
}
|
|
3175
|
+
function makeTodoRetryTool(todoList) {
|
|
3176
|
+
return {
|
|
3177
|
+
name: "todo_retry",
|
|
3178
|
+
kind: "other" /* Other */,
|
|
3179
|
+
description: "\u628A\u5931\u8D25\u7684 todo \u91CD\u7F6E\u56DE pending\uFF08\u6E05\u7A7A evidence\uFF09\uFF0C\u7136\u540E\u4F60\u53EF\u4EE5\u91CD\u65B0\u8D70 todo_mark_running \u2192 \u8DD1\u5DE5\u5177 \u2192 todo_mark_done \u7684\u6D41\u7A0B\u3002\n\u524D\u63D0\uFF1A\u5F53\u524D\u72B6\u6001\u5FC5\u987B\u662F failed\u3002done / skipped / running \u4E0D\u5141\u8BB8\u91CD\u8BD5\uFF08done \u4E0D\u53EF\u53CD\u6094\u3001running \u5E94\u5148 mark_failed\uFF09\u3002",
|
|
3180
|
+
parameters: {
|
|
3181
|
+
type: "object",
|
|
3182
|
+
properties: {
|
|
3183
|
+
id: { type: "number", description: "todo \u7684 id" }
|
|
3184
|
+
},
|
|
3185
|
+
required: ["id"],
|
|
3186
|
+
additionalProperties: false
|
|
3187
|
+
},
|
|
3188
|
+
async execute(args) {
|
|
3189
|
+
if (typeof args?.id !== "number") {
|
|
3190
|
+
return { success: false, data: "\u7F3A\u5C11 id \u53C2\u6570", error: "INVALID_ARGS" };
|
|
3191
|
+
}
|
|
3192
|
+
const item = todoList.items.find((it) => it.id === args.id);
|
|
3193
|
+
if (!item) {
|
|
3194
|
+
return { success: false, data: `todo #${args.id} \u4E0D\u5B58\u5728`, error: "TODO_NOT_FOUND" };
|
|
3195
|
+
}
|
|
3196
|
+
if (item.status !== "failed") {
|
|
3197
|
+
return {
|
|
3198
|
+
success: false,
|
|
3199
|
+
data: `todo #${args.id} \u5F53\u524D\u72B6\u6001\u662F ${item.status}\uFF0C\u53EA\u6709 failed \u53EF\u4EE5\u91CD\u8BD5`,
|
|
3200
|
+
error: "TODO_INVALID_STATE"
|
|
3201
|
+
};
|
|
3202
|
+
}
|
|
3203
|
+
const ok = todoList.resetForRetry(args.id);
|
|
3204
|
+
if (!ok) {
|
|
3205
|
+
return { success: false, data: `todo #${args.id} \u72B6\u6001\u8F6C\u6362\u5931\u8D25`, error: "TODO_INVALID" };
|
|
3206
|
+
}
|
|
3207
|
+
return {
|
|
3208
|
+
success: true,
|
|
3209
|
+
data: `\u5DF2\u91CD\u7F6E todo #${args.id} \u4E3A pending\uFF0C\u53EF\u91CD\u65B0\u8DD1`,
|
|
3210
|
+
summary: `\u{1F504} \u91CD\u8BD5 #${args.id}`
|
|
3211
|
+
};
|
|
3212
|
+
}
|
|
3213
|
+
};
|
|
3214
|
+
}
|
|
3215
|
+
|
|
3216
|
+
// src/checkpoint/git-checkpoint.ts
|
|
3217
|
+
import { execFile } from "child_process";
|
|
3218
|
+
import { promisify } from "util";
|
|
3219
|
+
var execFileAsync = promisify(execFile);
|
|
3220
|
+
var EXEC_OPTIONS = { windowsHide: true };
|
|
3221
|
+
async function isGitRepo(cwd) {
|
|
3222
|
+
try {
|
|
3223
|
+
await execFileAsync("git", ["rev-parse", "--is-inside-work-tree"], { cwd, ...EXEC_OPTIONS });
|
|
3224
|
+
return true;
|
|
3225
|
+
} catch {
|
|
3226
|
+
return false;
|
|
3227
|
+
}
|
|
3228
|
+
}
|
|
3229
|
+
async function hasCommits(cwd) {
|
|
3230
|
+
try {
|
|
3231
|
+
await execFileAsync("git", ["rev-parse", "--verify", "HEAD"], { cwd, ...EXEC_OPTIONS });
|
|
3232
|
+
return true;
|
|
3233
|
+
} catch {
|
|
3234
|
+
return false;
|
|
3235
|
+
}
|
|
3236
|
+
}
|
|
3237
|
+
async function hasWorkingChanges(cwd) {
|
|
3238
|
+
const out = await execFileAsync("git", ["status", "--porcelain"], { cwd, ...EXEC_OPTIONS });
|
|
3239
|
+
return out.stdout.trim().length > 0;
|
|
3240
|
+
}
|
|
3241
|
+
async function git(args, cwd) {
|
|
3242
|
+
try {
|
|
3243
|
+
const { stdout } = await execFileAsync("git", args, { cwd, ...EXEC_OPTIONS });
|
|
3244
|
+
return stdout;
|
|
3245
|
+
} catch (err) {
|
|
3246
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
3247
|
+
throw new Error(`git ${args.join(" ")} \u5931\u8D25: ${msg}`);
|
|
3248
|
+
}
|
|
3249
|
+
}
|
|
3250
|
+
async function listStashShas(cwd) {
|
|
3251
|
+
const out = await git(["stash", "list", "--format=%H"], cwd);
|
|
3252
|
+
return out.split("\n").map((l) => l.trim()).filter(Boolean);
|
|
3253
|
+
}
|
|
3254
|
+
async function createCheckpoint(cwd) {
|
|
3255
|
+
const timestamp = Date.now();
|
|
3256
|
+
const inRepo = await isGitRepo(cwd);
|
|
3257
|
+
if (!inRepo) return { stashSha: "", timestamp, cwd, isGitRepo: false };
|
|
3258
|
+
if (!await hasCommits(cwd)) return { stashSha: "", timestamp, cwd, isGitRepo: true };
|
|
3259
|
+
if (!await hasWorkingChanges(cwd)) return { stashSha: "", timestamp, cwd, isGitRepo: true };
|
|
3260
|
+
const beforeShas = await listStashShas(cwd);
|
|
3261
|
+
await git(["stash", "push", "-m", `dskcode-cp-${timestamp}`, "-u"], cwd);
|
|
3262
|
+
const newShas = await listStashShas(cwd);
|
|
3263
|
+
if (newShas.length === 0) throw new Error("git stash push \u672A\u80FD\u521B\u5EFA stash entry");
|
|
3264
|
+
const newSha = newShas.find((s) => !beforeShas.includes(s)) ?? newShas[0];
|
|
3265
|
+
await git(["stash", "apply", newSha], cwd);
|
|
3266
|
+
return { stashSha: newSha, timestamp, cwd, isGitRepo: true };
|
|
3267
|
+
}
|
|
3268
|
+
async function restoreCheckpointForce(checkpoint) {
|
|
3269
|
+
if (!checkpoint.isGitRepo) throw new Error("\u975E git \u4ED3\u5E93\uFF0C\u65E0\u6CD5\u6062\u590D\u6587\u4EF6\u72B6\u6001");
|
|
3270
|
+
if (!checkpoint.stashSha) throw new Error("\u68C0\u67E5\u70B9\u4E3A\u7A7A\uFF08\u5DE5\u4F5C\u533A\u539F\u672C\u5C31\u5E72\u51C0\uFF09\uFF0C\u65E0\u9700\u6062\u590D");
|
|
3271
|
+
const { cwd, stashSha } = checkpoint;
|
|
3272
|
+
const currentShas = await listStashShas(cwd);
|
|
3273
|
+
if (!currentShas.includes(stashSha)) {
|
|
3274
|
+
throw new Error("\u68C0\u67E5\u70B9\u5DF2\u5931\u6548\uFF08stash entry \u5DF2\u88AB\u6D88\u8D39\u6216 GC\uFF09\uFF0C\u65E0\u6CD5\u6062\u590D");
|
|
3275
|
+
}
|
|
3276
|
+
await git(["checkout", "--", "."], cwd);
|
|
3277
|
+
await git(["clean", "-fd"], cwd);
|
|
2646
3278
|
await git(["stash", "apply", stashSha], cwd);
|
|
2647
3279
|
const refIndex = currentShas.indexOf(stashSha);
|
|
2648
3280
|
if (refIndex >= 0) await git(["stash", "drop", `stash@{${refIndex}}`], cwd);
|
|
@@ -2849,6 +3481,10 @@ var ConversationLogger = class _ConversationLogger {
|
|
|
2849
3481
|
logAssistantText(content, round) {
|
|
2850
3482
|
this.log({ ts: Date.now(), type: "assistant_text", content, round });
|
|
2851
3483
|
}
|
|
3484
|
+
/** 记录思考链(thinking 模式下模型的 CoT) */
|
|
3485
|
+
logReasoning(content, round) {
|
|
3486
|
+
this.log({ ts: Date.now(), type: "reasoning", content, round });
|
|
3487
|
+
}
|
|
2852
3488
|
/** 记录工具调用 */
|
|
2853
3489
|
logToolCall(name, callId, args, round) {
|
|
2854
3490
|
this.log({ ts: Date.now(), type: "tool_call", name, callId, arguments: args, round });
|
|
@@ -2999,6 +3635,10 @@ var Session = class _Session {
|
|
|
2999
3635
|
#reflector;
|
|
3000
3636
|
/** 本轮工具执行结果(仅在 chat() 循环内使用;用于下一轮注入 reflection) */
|
|
3001
3637
|
#lastRoundResults = null;
|
|
3638
|
+
/** Harness 任务列表(仅在 enableHarness 时非 null) */
|
|
3639
|
+
#todoList;
|
|
3640
|
+
/** 本会话内是否已发出过「未拆 todo」护栏提示(避免每轮骚扰) */
|
|
3641
|
+
#harnessHintEmitted = false;
|
|
3002
3642
|
/**
|
|
3003
3643
|
* 构造一个 Session。
|
|
3004
3644
|
*
|
|
@@ -3028,7 +3668,8 @@ var Session = class _Session {
|
|
|
3028
3668
|
writeRoots: options?.writeRoots ?? [options?.cwd ?? process.cwd()],
|
|
3029
3669
|
enableCheckpoint: options?.enableCheckpoint ?? true,
|
|
3030
3670
|
enableLog: options?.enableLog ?? true,
|
|
3031
|
-
enableReflection: options?.enableReflection !== false
|
|
3671
|
+
enableReflection: options?.enableReflection !== false,
|
|
3672
|
+
enableHarness: options?.enableHarness !== false
|
|
3032
3673
|
};
|
|
3033
3674
|
this.#sessionId = options?.sessionId ?? SessionStore.newId();
|
|
3034
3675
|
this.#store = options?.store === false ? null : options?.store ?? new SessionStore();
|
|
@@ -3036,9 +3677,23 @@ var Session = class _Session {
|
|
|
3036
3677
|
this.#logger = new ConversationLogger(this.#sessionId, this.#options.cwd, {
|
|
3037
3678
|
enabled: this.#options.enableLog
|
|
3038
3679
|
});
|
|
3039
|
-
this.#logger.logSessionStart(
|
|
3680
|
+
this.#logger.logSessionStart(
|
|
3681
|
+
this.#sessionId,
|
|
3682
|
+
this.#options.cwd,
|
|
3683
|
+
this.#provider.model(),
|
|
3684
|
+
this.#mode
|
|
3685
|
+
);
|
|
3040
3686
|
this.#stormDetector = new StormDetector({ threshold: 3 });
|
|
3041
3687
|
this.#reflector = this.#options.enableReflection ? new Reflector() : null;
|
|
3688
|
+
if (this.#options.enableHarness) {
|
|
3689
|
+
const todoList = new TodoList();
|
|
3690
|
+
this.#todoList = todoList;
|
|
3691
|
+
for (const t of createHarnessTools(todoList)) {
|
|
3692
|
+
this.#toolRegistry.registerErased(eraseTool(t));
|
|
3693
|
+
}
|
|
3694
|
+
} else {
|
|
3695
|
+
this.#todoList = null;
|
|
3696
|
+
}
|
|
3042
3697
|
}
|
|
3043
3698
|
/** 当前会话的完整消息历史(只读视图) */
|
|
3044
3699
|
get messages() {
|
|
@@ -3118,6 +3773,7 @@ var Session = class _Session {
|
|
|
3118
3773
|
const startTime = Date.now();
|
|
3119
3774
|
let toolRounds = 0;
|
|
3120
3775
|
const toolExecutor = this.#buildToolExecutor();
|
|
3776
|
+
this.#harnessHintEmitted = false;
|
|
3121
3777
|
try {
|
|
3122
3778
|
while (toolRounds < this.#options.maxToolRounds) {
|
|
3123
3779
|
let systemPrompt = this.#buildSystemPrompt();
|
|
@@ -3129,20 +3785,21 @@ var Session = class _Session {
|
|
|
3129
3785
|
if (reflections.length > 0) {
|
|
3130
3786
|
systemPrompt = this.#reflector.injectIntoPrompt(systemPrompt, reflections);
|
|
3131
3787
|
this.#logger.logReflections(
|
|
3132
|
-
reflections.map((r) => ({
|
|
3788
|
+
reflections.map((r) => ({
|
|
3789
|
+
category: r.category,
|
|
3790
|
+
toolName: r.toolName,
|
|
3791
|
+
hint: r.hint
|
|
3792
|
+
}))
|
|
3133
3793
|
);
|
|
3134
3794
|
}
|
|
3135
3795
|
this.#lastRoundResults = null;
|
|
3136
3796
|
}
|
|
3137
|
-
const [trimmed] = trimMessages(
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
preserveRecentRounds: this.#options.preserveRecentRounds
|
|
3144
|
-
}
|
|
3145
|
-
);
|
|
3797
|
+
const [trimmed] = trimMessages([...this.#messages], {
|
|
3798
|
+
model: this.#provider.model(),
|
|
3799
|
+
reservedForOutput: this.#options.reservedForOutput,
|
|
3800
|
+
systemPrompt,
|
|
3801
|
+
preserveRecentRounds: this.#options.preserveRecentRounds
|
|
3802
|
+
});
|
|
3146
3803
|
const apiMessages = buildApiMessages(systemPrompt, trimmed);
|
|
3147
3804
|
const toolDefs = buildToolDefinitions(this.#toolRegistry, this.#mode);
|
|
3148
3805
|
const stream = this.#provider.chat(apiMessages, {
|
|
@@ -3155,6 +3812,7 @@ var Session = class _Session {
|
|
|
3155
3812
|
});
|
|
3156
3813
|
const modelId = this.#provider.model();
|
|
3157
3814
|
let accumulatedText = "";
|
|
3815
|
+
let accumulatedReasoning = "";
|
|
3158
3816
|
let lastUsage;
|
|
3159
3817
|
let lastToolCalls;
|
|
3160
3818
|
let _lastFinishReason = null;
|
|
@@ -3165,6 +3823,10 @@ var Session = class _Session {
|
|
|
3165
3823
|
let lastEmitMs = 0;
|
|
3166
3824
|
const EST_EMIT_INTERVAL_MS = 300;
|
|
3167
3825
|
for await (const chunk of stream) {
|
|
3826
|
+
if (chunk.reasoningContent) {
|
|
3827
|
+
accumulatedReasoning += chunk.reasoningContent;
|
|
3828
|
+
yield { type: "reasoning_delta", content: chunk.reasoningContent };
|
|
3829
|
+
}
|
|
3168
3830
|
if (chunk.content) {
|
|
3169
3831
|
accumulatedText += chunk.content;
|
|
3170
3832
|
yield { type: "text_delta", content: chunk.content };
|
|
@@ -3186,7 +3848,8 @@ var Session = class _Session {
|
|
|
3186
3848
|
};
|
|
3187
3849
|
}
|
|
3188
3850
|
}
|
|
3189
|
-
if (chunk.toolCalls && chunk.toolCalls.length > 0)
|
|
3851
|
+
if (chunk.toolCalls && chunk.toolCalls.length > 0)
|
|
3852
|
+
lastToolCalls = chunk.toolCalls;
|
|
3190
3853
|
if (chunk.usage) {
|
|
3191
3854
|
lastUsage = chunk.usage;
|
|
3192
3855
|
const realCost = calculateCost(chunk.usage, modelId);
|
|
@@ -3229,15 +3892,22 @@ var Session = class _Session {
|
|
|
3229
3892
|
yield { type: "usage", usage: lastUsage, model: modelId };
|
|
3230
3893
|
}
|
|
3231
3894
|
const assistantMsg = { role: "assistant", content: accumulatedText };
|
|
3232
|
-
if (lastToolCalls && lastToolCalls.length > 0)
|
|
3895
|
+
if (lastToolCalls && lastToolCalls.length > 0)
|
|
3896
|
+
assistantMsg.toolCalls = lastToolCalls;
|
|
3233
3897
|
this.#messages.push(assistantMsg);
|
|
3234
3898
|
this.#logger.logAssistantText(accumulatedText, toolRounds);
|
|
3899
|
+
if (accumulatedReasoning) {
|
|
3900
|
+
this.#logger.logReasoning(accumulatedReasoning, toolRounds);
|
|
3901
|
+
}
|
|
3235
3902
|
if (lastToolCalls && lastToolCalls.length > 0) {
|
|
3236
3903
|
yield { type: "tool_calls", calls: lastToolCalls };
|
|
3237
3904
|
for (const tc of lastToolCalls) {
|
|
3238
3905
|
this.#logger.logToolCall(tc.name, tc.id, tc.arguments, toolRounds);
|
|
3239
3906
|
}
|
|
3240
|
-
const stormBroken = this.#stormDetector.shouldBreak(
|
|
3907
|
+
const stormBroken = this.#stormDetector.shouldBreak(
|
|
3908
|
+
this.#stormRecords,
|
|
3909
|
+
lastToolCalls
|
|
3910
|
+
);
|
|
3241
3911
|
if (stormBroken) {
|
|
3242
3912
|
const stormMsg = "\n\u26A0\uFE0F \u540C\u4E00\u5DE5\u5177\u91CD\u590D\u51FA\u9519\uFF0C\u5DF2\u5F3A\u5236\u5207\u6362\u7B56\u7565\n";
|
|
3243
3913
|
yield { type: "text_delta", content: stormMsg };
|
|
@@ -3249,7 +3919,6 @@ var Session = class _Session {
|
|
|
3249
3919
|
}
|
|
3250
3920
|
const results = await toolExecutor.executeBatch(lastToolCalls);
|
|
3251
3921
|
this.#stormRecords = results.records;
|
|
3252
|
-
console.log("results", results);
|
|
3253
3922
|
this.#lastRoundResults = results.items.map((it) => {
|
|
3254
3923
|
const tool = this.#toolRegistry.get(it.name);
|
|
3255
3924
|
return {
|
|
@@ -3260,7 +3929,13 @@ var Session = class _Session {
|
|
|
3260
3929
|
};
|
|
3261
3930
|
});
|
|
3262
3931
|
for (const item of results.items) {
|
|
3263
|
-
|
|
3932
|
+
const todoSnapshot = item.name.startsWith("todo_") && this.#todoList ? this.#todoList.items : void 0;
|
|
3933
|
+
yield {
|
|
3934
|
+
type: "tool_result",
|
|
3935
|
+
name: item.name,
|
|
3936
|
+
result: item.result,
|
|
3937
|
+
todoSnapshot
|
|
3938
|
+
};
|
|
3264
3939
|
this.#logger.logToolResult(
|
|
3265
3940
|
item.name,
|
|
3266
3941
|
item.callId,
|
|
@@ -3271,7 +3946,8 @@ var Session = class _Session {
|
|
|
3271
3946
|
toolRounds
|
|
3272
3947
|
);
|
|
3273
3948
|
let toolContent = item.result.data;
|
|
3274
|
-
if (item.result.diff && item.result.diff.patch)
|
|
3949
|
+
if (item.result.diff && item.result.diff.patch)
|
|
3950
|
+
toolContent += `
|
|
3275
3951
|
|
|
3276
3952
|
${item.result.diff.patch}`;
|
|
3277
3953
|
this.#messages.push({
|
|
@@ -3281,9 +3957,16 @@ ${item.result.diff.patch}`;
|
|
|
3281
3957
|
name: item.name
|
|
3282
3958
|
});
|
|
3283
3959
|
}
|
|
3960
|
+
this.#maybeEmitHarnessHint(results.items);
|
|
3284
3961
|
toolRounds++;
|
|
3285
3962
|
continue;
|
|
3286
3963
|
}
|
|
3964
|
+
if (this.#todoList && this.#todoList.items.length > 0 && this.#todoList.isAllTerminated()) {
|
|
3965
|
+
this.#messages.push({
|
|
3966
|
+
role: "user",
|
|
3967
|
+
content: "[\u7CFB\u7EDF] \u5168\u90E8 todo \u5DF2\u5B8C\u6210\u3002\u8BF7\u505A\u4E00\u6B21\u4EFB\u52A1\u81EA\u68C0\uFF1A\u91CD\u65B0\u8BFB\u53D6\u672C\u6B21\u4FEE\u6539\u8FC7\u7684\u6587\u4EF6\uFF0C\u786E\u8BA4\u6539\u52A8\u6B63\u786E\u65E0\u8BEF\u3001\u7C7B\u578B\u517C\u5BB9\u3001\u6CA1\u6709\u9057\u6F0F\u3002\u5982\u6709\u95EE\u9898\u8BF7\u65B0\u589E todo \u4FEE\u590D\uFF1B\u786E\u8BA4\u65E0\u8BEF\u540E\u8F93\u51FA\u6700\u7EC8\u603B\u7ED3\u3002"
|
|
3968
|
+
});
|
|
3969
|
+
}
|
|
3287
3970
|
break;
|
|
3288
3971
|
}
|
|
3289
3972
|
} catch (err) {
|
|
@@ -3439,7 +4122,11 @@ ${item.result.diff.patch}`;
|
|
|
3439
4122
|
if (!store) throw new Error("resume \u9700\u8981\u542F\u7528\u6301\u4E45\u5316\uFF08options.store \u4E0D\u80FD\u4E3A false\uFF09");
|
|
3440
4123
|
const stored = await store.load(id);
|
|
3441
4124
|
if (!stored) throw new Error(`\u4F1A\u8BDD ${id} \u4E0D\u5B58\u5728`);
|
|
3442
|
-
const session = new _Session(provider, tools, costTracker, {
|
|
4125
|
+
const session = new _Session(provider, tools, costTracker, {
|
|
4126
|
+
...options,
|
|
4127
|
+
sessionId: id,
|
|
4128
|
+
store
|
|
4129
|
+
});
|
|
3443
4130
|
for (const m of stored.messages) {
|
|
3444
4131
|
session.#messages.push({
|
|
3445
4132
|
role: m.role,
|
|
@@ -3471,7 +4158,12 @@ ${item.result.diff.patch}`;
|
|
|
3471
4158
|
for (const [index, checkpoint] of this.#checkpoints) {
|
|
3472
4159
|
const msg = this.#messages[index];
|
|
3473
4160
|
if (!msg || msg.role !== "user") continue;
|
|
3474
|
-
result.push({
|
|
4161
|
+
result.push({
|
|
4162
|
+
index,
|
|
4163
|
+
preview: msg.content.slice(0, 80),
|
|
4164
|
+
timestamp: checkpoint.timestamp,
|
|
4165
|
+
isGitRepo: checkpoint.isGitRepo
|
|
4166
|
+
});
|
|
3475
4167
|
}
|
|
3476
4168
|
return result.sort((a, b) => a.index - b.index);
|
|
3477
4169
|
}
|
|
@@ -3599,8 +4291,38 @@ ${item.result.diff.patch}`;
|
|
|
3599
4291
|
projectContext: this.#options.projectContext ?? void 0,
|
|
3600
4292
|
cwd: this.#options.cwd
|
|
3601
4293
|
};
|
|
3602
|
-
|
|
3603
|
-
|
|
4294
|
+
let base;
|
|
4295
|
+
if (this.#mode === "plan") base = buildPlanSystemPrompt(opts);
|
|
4296
|
+
else base = buildSystemPrompt(opts);
|
|
4297
|
+
if (this.#todoList && this.#todoList.items.length > 0) {
|
|
4298
|
+
base = base + "\n\n" + this.#todoList.toMarkdown();
|
|
4299
|
+
}
|
|
4300
|
+
return base;
|
|
4301
|
+
}
|
|
4302
|
+
/**
|
|
4303
|
+
* Harness 护栏:模型跳过 todo_add 直接动手时,主动发一条提示让其重评。
|
|
4304
|
+
*
|
|
4305
|
+
* 触发条件(全部需满足):
|
|
4306
|
+
* 1. Harness 开启(#todoList 非空)
|
|
4307
|
+
* 2. todoList 仍为空(未拆 todo)
|
|
4308
|
+
* 3. 本会话内未提示过(#harnessHintEmitted 为 false)
|
|
4309
|
+
* 4. 本轮调了 ≥1 个**非 todo_* 的工具**(说明模型跳过了 todo_add 直接干活)
|
|
4310
|
+
*
|
|
4311
|
+
* 动作:push 一条 user role 消息到 #messages,让下一轮 LLM 看到;设 #harnessHintEmitted = true。
|
|
4312
|
+
*
|
|
4313
|
+
* @sideEffect 写 #messages / #harnessHintEmitted
|
|
4314
|
+
*/
|
|
4315
|
+
#maybeEmitHarnessHint(items) {
|
|
4316
|
+
if (!this.#todoList) return;
|
|
4317
|
+
if (this.#todoList.items.length > 0) return;
|
|
4318
|
+
if (this.#harnessHintEmitted) return;
|
|
4319
|
+
const hasNonTodo = items.some((it) => !it.name.startsWith("todo_"));
|
|
4320
|
+
if (!hasNonTodo) return;
|
|
4321
|
+
this.#harnessHintEmitted = true;
|
|
4322
|
+
this.#messages.push({
|
|
4323
|
+
role: "user",
|
|
4324
|
+
content: "[\u7CFB\u7EDF\u63D0\u793A] \u4F60\u8FD8\u6CA1\u6709 todo \u8FC7\uFF0C\u4F46\u5DF2\u7ECF\u8C03\u4E86\u5177\u4F53\u5DE5\u5177\u3002\n\u8BF7\u56DE\u987E\u4F60\u521A\u505A\u7684\u4E8B\uFF1A\u8FD9\u662F\u300C\u7B80\u5355\u300D\u4EFB\u52A1\uFF081 \u8F6E 1 \u5DE5\u5177\u80FD\u5B8C\u6210\uFF09\u8FD8\u662F\u300C\u590D\u6742\u300D\u4EFB\u52A1\uFF1F\n\u5982\u679C\u662F\u590D\u6742\uFF08\u6539\u4E86/\u521B\u5EFA\u4E86/\u8981\u8BFB\u540E\u6539/\u8DE8\u591A\u79CD\u5DE5\u5177\uFF09\uFF0C\u8BF7\u505C\u4E0B\uFF0C\u5148\u8C03 todo_add \u62C6\u89E3 3-7 \u6B65\u518D\u7EE7\u7EED\u3002\n\u5982\u679C\u662F\u7B80\u5355\uFF0C\u5FFD\u7565\u672C\u63D0\u793A\u3002\n\uFF08\u672C\u63D0\u793A\u672C\u4F1A\u8BDD\u4EC5\u53D1\u4E00\u6B21\uFF0C\u540E\u7EED\u4E0D\u518D\u63D0\u9192\u3002\uFF09"
|
|
4325
|
+
});
|
|
3604
4326
|
}
|
|
3605
4327
|
};
|
|
3606
4328
|
|
|
@@ -5104,7 +5826,7 @@ function getGradientColors(text, phase, stops) {
|
|
|
5104
5826
|
}
|
|
5105
5827
|
|
|
5106
5828
|
// src/ui/ChatSession.tsx
|
|
5107
|
-
import { Fragment as Fragment2, jsx as
|
|
5829
|
+
import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
5108
5830
|
var PHASE_CONFIG = {
|
|
5109
5831
|
thinking: { icon: "\u{1F9E0}", label: "\u6DF1\u5EA6\u601D\u8003\u4E2D", color: "#ff9800" },
|
|
5110
5832
|
generating: { icon: "\u2728", label: "\u751F\u6210\u4E2D", color: "#00ff41" },
|
|
@@ -5135,15 +5857,45 @@ registerCommand("/help", {
|
|
|
5135
5857
|
}
|
|
5136
5858
|
});
|
|
5137
5859
|
registerCommand("/clear", { desc: "\u6E05\u7A7A\u5BF9\u8BDD\u5386\u53F2", handler: () => ({ kind: "clear" }) });
|
|
5138
|
-
registerCommand("/version", {
|
|
5139
|
-
|
|
5140
|
-
|
|
5141
|
-
|
|
5142
|
-
registerCommand("/
|
|
5143
|
-
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
registerCommand("/
|
|
5860
|
+
registerCommand("/version", {
|
|
5861
|
+
desc: "\u663E\u793A\u7248\u672C\u4FE1\u606F",
|
|
5862
|
+
handler: () => ({ kind: "text", content: "dskcode v0.1.10" })
|
|
5863
|
+
});
|
|
5864
|
+
registerCommand("/model", {
|
|
5865
|
+
desc: "\u5207\u6362\u6A21\u578B",
|
|
5866
|
+
handler: () => ({ kind: "text", content: "\u8BF7\u76F4\u63A5\u8F93\u5165 /model \u8FDB\u5165\u9009\u62E9\u754C\u9762" })
|
|
5867
|
+
});
|
|
5868
|
+
registerCommand("/thinking", {
|
|
5869
|
+
desc: "\u5207\u6362\u6DF1\u5EA6\u601D\u8003\u6A21\u5F0F",
|
|
5870
|
+
handler: () => ({ kind: "text", content: "\u8BF7\u76F4\u63A5\u8F93\u5165 /thinking \u5207\u6362" })
|
|
5871
|
+
});
|
|
5872
|
+
registerCommand("/effort", {
|
|
5873
|
+
desc: "\u5207\u6362\u63A8\u7406\u7B49\u7EA7 High/Max",
|
|
5874
|
+
handler: () => ({ kind: "text", content: "\u8BF7\u76F4\u63A5\u8F93\u5165 /effort \u5207\u6362" })
|
|
5875
|
+
});
|
|
5876
|
+
registerCommand("/game", {
|
|
5877
|
+
desc: "\u542F\u52A8\u6E38\u620F",
|
|
5878
|
+
handler: () => ({ kind: "navigate", target: "game" })
|
|
5879
|
+
});
|
|
5880
|
+
registerCommand("/stock", {
|
|
5881
|
+
desc: "\u67E5\u770B\u80A1\u7968\u884C\u60C5",
|
|
5882
|
+
handler: () => ({ kind: "navigate", target: "stock" })
|
|
5883
|
+
});
|
|
5884
|
+
registerCommand("/plan", {
|
|
5885
|
+
desc: "\u5207\u6362\u4E3A\u8BA1\u5212\u6A21\u5F0F\uFF08Shift+Tab\uFF09",
|
|
5886
|
+
handler: () => ({ kind: "text", content: "\u8F93\u5165 /plan \u6216\u6309 Shift+Tab \u5207\u6362\u4E3A\u8BA1\u5212\u6A21\u5F0F" })
|
|
5887
|
+
});
|
|
5888
|
+
registerCommand("/code", {
|
|
5889
|
+
desc: "\u5207\u6362\u56DE\u4EE3\u7801\u6A21\u5F0F\uFF08Shift+Tab\uFF09",
|
|
5890
|
+
handler: () => ({ kind: "text", content: "\u8F93\u5165 /code \u6216\u6309 Shift+Tab \u5207\u6362\u56DE\u4EE3\u7801\u6A21\u5F0F" })
|
|
5891
|
+
});
|
|
5892
|
+
registerCommand("/rewind", {
|
|
5893
|
+
desc: "\u56DE\u9000\u5230\u5386\u53F2\u68C0\u67E5\u70B9\uFF081 = \u6700\u65B0\uFF09",
|
|
5894
|
+
handler: () => ({
|
|
5895
|
+
kind: "text",
|
|
5896
|
+
content: "\u8BF7\u76F4\u63A5\u8F93\u5165 /rewind \u67E5\u770B\u53EF\u56DE\u9000\u7684\u68C0\u67E5\u70B9\u5217\u8868\uFF0C\u6216 /rewind <\u5E8F\u53F7> \u76F4\u63A5\u56DE\u9000\uFF081 = \u6700\u65B0\uFF0C2 = \u4E0A\u4E00\u6B21\uFF0C\u4F9D\u6B64\u7C7B\u63A8\uFF09"
|
|
5897
|
+
})
|
|
5898
|
+
});
|
|
5147
5899
|
var STREAMING_PLACEHOLDERS = [
|
|
5148
5900
|
"\u8BA9\u5B50\u5F39\u98DE\u4E00\u4F1A\u513F...",
|
|
5149
5901
|
"\u9A6C\u4E0A\u5C31\u597D...",
|
|
@@ -5188,12 +5940,15 @@ function ChatSession({
|
|
|
5188
5940
|
const [isStreaming, setIsStreaming] = useState4(false);
|
|
5189
5941
|
const [streamingPhase, setStreamingPhase] = useState4(null);
|
|
5190
5942
|
const [streamingPlaceholder, setStreamingPlaceholder] = useState4("");
|
|
5191
|
-
const [idlePlaceholder, setIdlePlaceholder] = useState4(
|
|
5943
|
+
const [idlePlaceholder, setIdlePlaceholder] = useState4(
|
|
5944
|
+
() => pickRandom(IDLE_PLACEHOLDERS)
|
|
5945
|
+
);
|
|
5192
5946
|
const [gradientColors, setGradientColors] = useState4([]);
|
|
5193
5947
|
const gradientPhaseRef = useRef3(0);
|
|
5194
5948
|
const [streamingGradientColors, setStreamingGradientColors] = useState4([]);
|
|
5195
5949
|
const streamingPhaseRef = useRef3(0);
|
|
5196
5950
|
const [currentContent, setCurrentContent] = useState4("");
|
|
5951
|
+
const [currentReasoning, setCurrentReasoning] = useState4([]);
|
|
5197
5952
|
const [currentToolCalls, setCurrentToolCalls] = useState4([]);
|
|
5198
5953
|
const [_currentUsage, setCurrentUsage] = useState4(void 0);
|
|
5199
5954
|
const [_currentElapsed, setCurrentElapsed] = useState4(void 0);
|
|
@@ -5201,11 +5956,14 @@ function ChatSession({
|
|
|
5201
5956
|
const [activeModel, setActiveModel] = useState4(model);
|
|
5202
5957
|
const [_streamingModel, setStreamingModel] = useState4(void 0);
|
|
5203
5958
|
const [streamError, setStreamError] = useState4(void 0);
|
|
5959
|
+
const [todoSnapshot, setTodoSnapshot] = useState4([]);
|
|
5204
5960
|
const [sessionMode, setSessionMode] = useState4("code");
|
|
5205
5961
|
const [thinkingEnabled, setThinkingEnabled] = useState4(true);
|
|
5206
5962
|
const [thinkingEffort, setThinkingEffort] = useState4("high");
|
|
5207
5963
|
const [responseFormat] = useState4("text");
|
|
5208
|
-
const [toolChoice, setToolChoice] = useState4(
|
|
5964
|
+
const [toolChoice, setToolChoice] = useState4(
|
|
5965
|
+
void 0
|
|
5966
|
+
);
|
|
5209
5967
|
const sessionCost = useMemo(() => {
|
|
5210
5968
|
return displayMessages.reduce((sum, msg) => {
|
|
5211
5969
|
if (msg.assistantDetail?.cost) {
|
|
@@ -5226,7 +5984,9 @@ function ChatSession({
|
|
|
5226
5984
|
const [rewindSelectIndex, setRewindSelectIndex] = useState4(0);
|
|
5227
5985
|
const [rewindList, setRewindList] = useState4([]);
|
|
5228
5986
|
const [rewinding, setRewinding] = useState4(false);
|
|
5229
|
-
const [rewindHintPhase, setRewindHintPhase] = useState4(
|
|
5987
|
+
const [rewindHintPhase, setRewindHintPhase] = useState4(
|
|
5988
|
+
"idle"
|
|
5989
|
+
);
|
|
5230
5990
|
const currentRoundModifiedRef = useRef3(false);
|
|
5231
5991
|
const rewindHintTimerRef = useRef3(null);
|
|
5232
5992
|
const [selectingModel, setSelectingModel] = useState4(false);
|
|
@@ -5235,6 +5995,7 @@ function ChatSession({
|
|
|
5235
5995
|
const sessionRef = useRef3(null);
|
|
5236
5996
|
const abortRef = useRef3(null);
|
|
5237
5997
|
const currentContentRef = useRef3("");
|
|
5998
|
+
const currentReasoningRef = useRef3([]);
|
|
5238
5999
|
const currentToolCallsRef = useRef3([]);
|
|
5239
6000
|
const currentUsageRef = useRef3(void 0);
|
|
5240
6001
|
const currentElapsedRef = useRef3(void 0);
|
|
@@ -5304,42 +6065,48 @@ function ChatSession({
|
|
|
5304
6065
|
setDisplayMessages(next);
|
|
5305
6066
|
setStaticKey((prev) => prev + 1);
|
|
5306
6067
|
}
|
|
5307
|
-
const doRewind = useCallback2(
|
|
5308
|
-
|
|
5309
|
-
|
|
5310
|
-
|
|
5311
|
-
|
|
5312
|
-
|
|
5313
|
-
|
|
5314
|
-
|
|
5315
|
-
|
|
5316
|
-
|
|
5317
|
-
|
|
5318
|
-
|
|
5319
|
-
|
|
5320
|
-
|
|
5321
|
-
|
|
5322
|
-
|
|
5323
|
-
|
|
5324
|
-
|
|
6068
|
+
const doRewind = useCallback2(
|
|
6069
|
+
async (target, displayNumber) => {
|
|
6070
|
+
const session = sessionRef.current;
|
|
6071
|
+
if (!session) return;
|
|
6072
|
+
setRewinding(true);
|
|
6073
|
+
setIsStreaming(true);
|
|
6074
|
+
setStreamingPhase("thinking");
|
|
6075
|
+
setStreamingPlaceholder("\u23EA \u6B63\u5728\u56DE\u9000\u5230\u68C0\u67E5\u70B9\u2026");
|
|
6076
|
+
setInput("");
|
|
6077
|
+
try {
|
|
6078
|
+
const r = await session.rewind(target.index);
|
|
6079
|
+
if (r.ok) {
|
|
6080
|
+
rebuildDisplayFromSession(session);
|
|
6081
|
+
const tail = r.fileRestored ? "\uFF0C\u5DE5\u4F5C\u533A\u6587\u4EF6\u5DF2\u6062\u590D" : "\uFF08\u4EC5\u5BF9\u8BDD\u56DE\u9000\uFF0C\u672A\u6062\u590D\u6587\u4EF6\uFF09";
|
|
6082
|
+
setDisplayMessages((prev) => [
|
|
6083
|
+
...prev,
|
|
6084
|
+
{
|
|
6085
|
+
role: "assistant",
|
|
6086
|
+
content: `\u23EA \u5DF2\u56DE\u9000\u5230\u68C0\u67E5\u70B9 #${displayNumber}${tail}\u3002`
|
|
6087
|
+
}
|
|
6088
|
+
]);
|
|
6089
|
+
} else {
|
|
6090
|
+
setDisplayMessages((prev) => [
|
|
6091
|
+
...prev,
|
|
6092
|
+
{ role: "assistant", content: `\u26A0 \u56DE\u9000\u5931\u8D25\uFF1A${r.error}` }
|
|
6093
|
+
]);
|
|
6094
|
+
}
|
|
6095
|
+
} catch (err) {
|
|
6096
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
5325
6097
|
setDisplayMessages((prev) => [
|
|
5326
6098
|
...prev,
|
|
5327
|
-
{ role: "assistant", content: `\u26A0 \u56DE\u9000\
|
|
6099
|
+
{ role: "assistant", content: `\u26A0 \u56DE\u9000\u5F02\u5E38\uFF1A${msg}` }
|
|
5328
6100
|
]);
|
|
6101
|
+
} finally {
|
|
6102
|
+
setRewinding(false);
|
|
6103
|
+
setIsStreaming(false);
|
|
6104
|
+
setStreamingPhase(null);
|
|
6105
|
+
setStreamingPlaceholder("");
|
|
5329
6106
|
}
|
|
5330
|
-
}
|
|
5331
|
-
|
|
5332
|
-
|
|
5333
|
-
...prev,
|
|
5334
|
-
{ role: "assistant", content: `\u26A0 \u56DE\u9000\u5F02\u5E38\uFF1A${msg}` }
|
|
5335
|
-
]);
|
|
5336
|
-
} finally {
|
|
5337
|
-
setRewinding(false);
|
|
5338
|
-
setIsStreaming(false);
|
|
5339
|
-
setStreamingPhase(null);
|
|
5340
|
-
setStreamingPlaceholder("");
|
|
5341
|
-
}
|
|
5342
|
-
}, []);
|
|
6107
|
+
},
|
|
6108
|
+
[]
|
|
6109
|
+
);
|
|
5343
6110
|
const { doubleCtrlC, handleCtrlC } = useDoubleCtrlC(() => {
|
|
5344
6111
|
const s = sessionRef.current;
|
|
5345
6112
|
if (s) {
|
|
@@ -5353,7 +6120,9 @@ function ChatSession({
|
|
|
5353
6120
|
(_input, key) => {
|
|
5354
6121
|
if (rewindSelecting) {
|
|
5355
6122
|
if (key.upArrow) {
|
|
5356
|
-
setRewindSelectIndex(
|
|
6123
|
+
setRewindSelectIndex(
|
|
6124
|
+
(prev) => (prev - 1 + rewindList.length) % rewindList.length
|
|
6125
|
+
);
|
|
5357
6126
|
} else if (key.downArrow) {
|
|
5358
6127
|
setRewindSelectIndex((prev) => (prev + 1) % rewindList.length);
|
|
5359
6128
|
} else if (key.return) {
|
|
@@ -5373,7 +6142,9 @@ function ChatSession({
|
|
|
5373
6142
|
}
|
|
5374
6143
|
if (selectingModel) {
|
|
5375
6144
|
if (key.upArrow) {
|
|
5376
|
-
setModelSelectIndex(
|
|
6145
|
+
setModelSelectIndex(
|
|
6146
|
+
(prev) => (prev - 1 + modelOptions.length) % modelOptions.length
|
|
6147
|
+
);
|
|
5377
6148
|
} else if (key.downArrow) {
|
|
5378
6149
|
setModelSelectIndex((prev) => (prev + 1) % modelOptions.length);
|
|
5379
6150
|
} else if (key.return) {
|
|
@@ -5381,7 +6152,10 @@ function ChatSession({
|
|
|
5381
6152
|
if (selected === activeModel) {
|
|
5382
6153
|
setDisplayMessages((prev) => [
|
|
5383
6154
|
...prev,
|
|
5384
|
-
{
|
|
6155
|
+
{
|
|
6156
|
+
role: "assistant",
|
|
6157
|
+
content: `\u5DF2\u7ECF\u5728\u4F7F\u7528 ${SUPPORTED_MODELS[selected].displayName}`
|
|
6158
|
+
}
|
|
5385
6159
|
]);
|
|
5386
6160
|
} else {
|
|
5387
6161
|
setActiveModel(selected);
|
|
@@ -5390,7 +6164,10 @@ function ChatSession({
|
|
|
5390
6164
|
});
|
|
5391
6165
|
setDisplayMessages((prev) => [
|
|
5392
6166
|
...prev,
|
|
5393
|
-
{
|
|
6167
|
+
{
|
|
6168
|
+
role: "assistant",
|
|
6169
|
+
content: `\u6A21\u578B\u5DF2\u5207\u6362\u4E3A ${SUPPORTED_MODELS[selected].displayName}\uFF08${selected}\uFF09`
|
|
6170
|
+
}
|
|
5394
6171
|
]);
|
|
5395
6172
|
}
|
|
5396
6173
|
setSelectingModel(false);
|
|
@@ -5424,7 +6201,9 @@ function ChatSession({
|
|
|
5424
6201
|
}
|
|
5425
6202
|
if (skillList.length > 0) {
|
|
5426
6203
|
if (key.upArrow) {
|
|
5427
|
-
setSkillSelectIndex(
|
|
6204
|
+
setSkillSelectIndex(
|
|
6205
|
+
(prev) => (prev - 1 + skillList.length) % skillList.length
|
|
6206
|
+
);
|
|
5428
6207
|
return;
|
|
5429
6208
|
}
|
|
5430
6209
|
if (key.downArrow) {
|
|
@@ -5477,7 +6256,26 @@ function ChatSession({
|
|
|
5477
6256
|
setInput(_input);
|
|
5478
6257
|
}
|
|
5479
6258
|
},
|
|
5480
|
-
[
|
|
6259
|
+
[
|
|
6260
|
+
selectingModel,
|
|
6261
|
+
modelSelectIndex,
|
|
6262
|
+
modelOptions,
|
|
6263
|
+
activeModel,
|
|
6264
|
+
isStreaming,
|
|
6265
|
+
handleCtrlC,
|
|
6266
|
+
input,
|
|
6267
|
+
skills,
|
|
6268
|
+
skillSelectIndex,
|
|
6269
|
+
fileSelectIndex,
|
|
6270
|
+
getFilteredSkills,
|
|
6271
|
+
getFilteredFiles,
|
|
6272
|
+
sessionMode,
|
|
6273
|
+
setSessionMode,
|
|
6274
|
+
rewindSelecting,
|
|
6275
|
+
rewindSelectIndex,
|
|
6276
|
+
rewindList,
|
|
6277
|
+
doRewind
|
|
6278
|
+
]
|
|
5481
6279
|
)
|
|
5482
6280
|
);
|
|
5483
6281
|
useEffect4(() => {
|
|
@@ -5498,7 +6296,9 @@ function ChatSession({
|
|
|
5498
6296
|
setCmdTipGradientColors(getGradientColors(text, 1, CMD_TIP_GRADIENT_STOPS));
|
|
5499
6297
|
const interval = setInterval(() => {
|
|
5500
6298
|
cmdTipPhaseRef.current = (cmdTipPhaseRef.current + GRADIENT_ANIMATION.cmdTipPhaseStep) % 1;
|
|
5501
|
-
setCmdTipGradientColors(
|
|
6299
|
+
setCmdTipGradientColors(
|
|
6300
|
+
getGradientColors(text, 1 - cmdTipPhaseRef.current, CMD_TIP_GRADIENT_STOPS)
|
|
6301
|
+
);
|
|
5502
6302
|
}, GRADIENT_ANIMATION.cmdTipInterval);
|
|
5503
6303
|
return () => clearInterval(interval);
|
|
5504
6304
|
}, [cmdTipIndex, cmdTips.length]);
|
|
@@ -5531,7 +6331,7 @@ function ChatSession({
|
|
|
5531
6331
|
if (!apiKey || !baseUrl) return;
|
|
5532
6332
|
let cancelled = false;
|
|
5533
6333
|
setBalanceLoading(true);
|
|
5534
|
-
import("./deepseek-
|
|
6334
|
+
import("./deepseek-WFSVA5UQ.js").then(({ DeepSeekProvider: DeepSeekProvider2 }) => {
|
|
5535
6335
|
const provider = new DeepSeekProvider2({
|
|
5536
6336
|
apiKey,
|
|
5537
6337
|
baseUrl,
|
|
@@ -5579,7 +6379,13 @@ function ChatSession({
|
|
|
5579
6379
|
setGradientColors(getGradientColors(idlePlaceholder, 1, IDLE_GRADIENT_STOPS));
|
|
5580
6380
|
const interval = setInterval(() => {
|
|
5581
6381
|
gradientPhaseRef.current = (gradientPhaseRef.current + GRADIENT_ANIMATION.idlePhaseStep) % 1;
|
|
5582
|
-
setGradientColors(
|
|
6382
|
+
setGradientColors(
|
|
6383
|
+
getGradientColors(
|
|
6384
|
+
idlePlaceholder,
|
|
6385
|
+
1 - gradientPhaseRef.current,
|
|
6386
|
+
IDLE_GRADIENT_STOPS
|
|
6387
|
+
)
|
|
6388
|
+
);
|
|
5583
6389
|
}, GRADIENT_ANIMATION.idleInterval);
|
|
5584
6390
|
return () => clearInterval(interval);
|
|
5585
6391
|
}, [isStreaming, idlePlaceholder]);
|
|
@@ -5589,385 +6395,465 @@ function ChatSession({
|
|
|
5589
6395
|
return;
|
|
5590
6396
|
}
|
|
5591
6397
|
streamingPhaseRef.current = 0;
|
|
5592
|
-
setStreamingGradientColors(
|
|
6398
|
+
setStreamingGradientColors(
|
|
6399
|
+
getGradientColors(streamingPlaceholder, 1, STREAMING_GRADIENT_STOPS)
|
|
6400
|
+
);
|
|
5593
6401
|
const interval = setInterval(() => {
|
|
5594
6402
|
streamingPhaseRef.current = (streamingPhaseRef.current + GRADIENT_ANIMATION.streamingPhaseStep) % 1;
|
|
5595
|
-
setStreamingGradientColors(
|
|
6403
|
+
setStreamingGradientColors(
|
|
6404
|
+
getGradientColors(
|
|
6405
|
+
streamingPlaceholder,
|
|
6406
|
+
1 - streamingPhaseRef.current,
|
|
6407
|
+
STREAMING_GRADIENT_STOPS
|
|
6408
|
+
)
|
|
6409
|
+
);
|
|
5596
6410
|
}, GRADIENT_ANIMATION.streamingInterval);
|
|
5597
6411
|
return () => clearInterval(interval);
|
|
5598
6412
|
}, [isStreaming, streamingPlaceholder]);
|
|
5599
|
-
const handleSubmit = useCallback2(
|
|
5600
|
-
|
|
5601
|
-
|
|
5602
|
-
|
|
5603
|
-
|
|
5604
|
-
|
|
5605
|
-
if (
|
|
5606
|
-
|
|
6413
|
+
const handleSubmit = useCallback2(
|
|
6414
|
+
async (value) => {
|
|
6415
|
+
const trimmed = value.trim();
|
|
6416
|
+
if (!trimmed) return;
|
|
6417
|
+
if (trimmed.startsWith("/") && trimmed.length > 1) {
|
|
6418
|
+
const cmdLower = trimmed.toLowerCase();
|
|
6419
|
+
if (cmdLower === "/rewind" || cmdLower.startsWith("/rewind ")) {
|
|
6420
|
+
if (isStreaming || rewinding) {
|
|
6421
|
+
const reason = rewinding ? "\u56DE\u9000\u4E2D" : "\u751F\u6210\u4E2D";
|
|
6422
|
+
setDisplayMessages((prev) => [
|
|
6423
|
+
...prev,
|
|
6424
|
+
{ role: "user", content: trimmed },
|
|
6425
|
+
{ role: "assistant", content: `\u26A0 \u6B63\u5728${reason}\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5 /rewind\u3002` }
|
|
6426
|
+
]);
|
|
6427
|
+
setInput("");
|
|
6428
|
+
return;
|
|
6429
|
+
}
|
|
6430
|
+
if (!sessionRef.current) {
|
|
6431
|
+
setDisplayMessages((prev) => [
|
|
6432
|
+
...prev,
|
|
6433
|
+
{ role: "user", content: trimmed },
|
|
6434
|
+
{ role: "assistant", content: "\u26A0 Session \u672A\u5C31\u7EEA\uFF0C\u65E0\u6CD5\u56DE\u9000\u3002" }
|
|
6435
|
+
]);
|
|
6436
|
+
setInput("");
|
|
6437
|
+
return;
|
|
6438
|
+
}
|
|
6439
|
+
const cps = sessionRef.current.listCheckpoints();
|
|
6440
|
+
if (cps.length === 0) {
|
|
6441
|
+
setDisplayMessages((prev) => [
|
|
6442
|
+
...prev,
|
|
6443
|
+
{ role: "user", content: trimmed },
|
|
6444
|
+
{
|
|
6445
|
+
role: "assistant",
|
|
6446
|
+
content: "\u26A0 \u6CA1\u6709\u53EF\u56DE\u9000\u7684\u68C0\u67E5\u70B9\u3002\n\u53EA\u6709\u5728 git \u4ED3\u5E93\u5185\u4E14\u53D1\u751F\u8FC7\u5BF9\u8BDD\u540E\u624D\u4F1A\u751F\u6210\u68C0\u67E5\u70B9\u3002"
|
|
6447
|
+
}
|
|
6448
|
+
]);
|
|
6449
|
+
setInput("");
|
|
6450
|
+
return;
|
|
6451
|
+
}
|
|
6452
|
+
const parts = trimmed.split(/\s+/);
|
|
6453
|
+
if (parts.length >= 2) {
|
|
6454
|
+
const n = Number(parts[1]);
|
|
6455
|
+
if (!Number.isInteger(n) || n < 1 || n > cps.length) {
|
|
6456
|
+
setDisplayMessages((prev) => [
|
|
6457
|
+
...prev,
|
|
6458
|
+
{ role: "user", content: trimmed },
|
|
6459
|
+
{
|
|
6460
|
+
role: "assistant",
|
|
6461
|
+
content: `\u26A0 \u65E0\u6548\u7684\u5E8F\u53F7\u300C${parts[1]}\u300D\u3002\u53EF\u7528\u8303\u56F4 1~${cps.length}\uFF081 \u8868\u793A\u6700\u65B0\uFF09\u3002`
|
|
6462
|
+
}
|
|
6463
|
+
]);
|
|
6464
|
+
setInput("");
|
|
6465
|
+
return;
|
|
6466
|
+
}
|
|
6467
|
+
const target = cps[cps.length - n];
|
|
6468
|
+
setInput("");
|
|
6469
|
+
await doRewind(target, n);
|
|
6470
|
+
return;
|
|
6471
|
+
}
|
|
6472
|
+
setRewindList([...cps].reverse());
|
|
6473
|
+
setRewindSelectIndex(0);
|
|
6474
|
+
setRewindSelecting(true);
|
|
5607
6475
|
setDisplayMessages((prev) => [
|
|
5608
6476
|
...prev,
|
|
5609
6477
|
{ role: "user", content: trimmed },
|
|
5610
|
-
{
|
|
6478
|
+
{
|
|
6479
|
+
role: "assistant",
|
|
6480
|
+
content: `\u23F7\u2191\u2193 \u9009\u62E9\u68C0\u67E5\u70B9\uFF0CEnter \u786E\u8BA4\uFF0CEsc \u53D6\u6D88\uFF08\u5171 ${cps.length} \u4E2A\u53EF\u56DE\u9000\u4F4D\u7F6E\uFF09`
|
|
6481
|
+
}
|
|
5611
6482
|
]);
|
|
5612
6483
|
setInput("");
|
|
5613
6484
|
return;
|
|
5614
6485
|
}
|
|
5615
|
-
if (
|
|
6486
|
+
if (cmdLower === "/model") {
|
|
6487
|
+
const curIdx = modelOptions.indexOf(activeModel);
|
|
6488
|
+
setModelSelectIndex(curIdx >= 0 ? curIdx : 0);
|
|
6489
|
+
setSelectingModel(true);
|
|
6490
|
+
setInput("");
|
|
6491
|
+
return;
|
|
6492
|
+
}
|
|
6493
|
+
if (cmdLower === "/thinking") {
|
|
6494
|
+
setThinkingEnabled((prev) => !prev);
|
|
5616
6495
|
setDisplayMessages((prev) => [
|
|
5617
6496
|
...prev,
|
|
5618
6497
|
{ role: "user", content: trimmed },
|
|
5619
|
-
{
|
|
6498
|
+
{
|
|
6499
|
+
role: "assistant",
|
|
6500
|
+
content: `\u6DF1\u5EA6\u601D\u8003\u5DF2${thinkingEnabled ? "\u5173\u95ED" : "\u5F00\u542F"}`
|
|
6501
|
+
}
|
|
5620
6502
|
]);
|
|
5621
6503
|
setInput("");
|
|
5622
6504
|
return;
|
|
5623
6505
|
}
|
|
5624
|
-
|
|
5625
|
-
|
|
6506
|
+
if (cmdLower === "/effort") {
|
|
6507
|
+
const next = thinkingEffort === "high" ? "max" : "high";
|
|
6508
|
+
setThinkingEffort(next);
|
|
5626
6509
|
setDisplayMessages((prev) => [
|
|
5627
6510
|
...prev,
|
|
5628
6511
|
{ role: "user", content: trimmed },
|
|
5629
|
-
{
|
|
6512
|
+
{
|
|
6513
|
+
role: "assistant",
|
|
6514
|
+
content: `\u63A8\u7406\u7B49\u7EA7\u5DF2\u5207\u6362\u4E3A ${next === "high" ? "High" : "Max"}`
|
|
6515
|
+
}
|
|
5630
6516
|
]);
|
|
5631
6517
|
setInput("");
|
|
5632
6518
|
return;
|
|
5633
6519
|
}
|
|
5634
|
-
|
|
5635
|
-
|
|
5636
|
-
const n = Number(parts[1]);
|
|
5637
|
-
if (!Number.isInteger(n) || n < 1 || n > cps.length) {
|
|
6520
|
+
if (cmdLower === "/plan") {
|
|
6521
|
+
if (sessionMode === "plan") {
|
|
5638
6522
|
setDisplayMessages((prev) => [
|
|
5639
6523
|
...prev,
|
|
5640
6524
|
{ role: "user", content: trimmed },
|
|
5641
|
-
{
|
|
6525
|
+
{
|
|
6526
|
+
role: "assistant",
|
|
6527
|
+
content: "\u5DF2\u7ECF\u5728\u8BA1\u5212\u6A21\u5F0F\u4E2D\u3002\u8F93\u5165 /code \u5207\u56DE\u4EE3\u7801\u6A21\u5F0F\u3002"
|
|
6528
|
+
}
|
|
5642
6529
|
]);
|
|
5643
|
-
|
|
5644
|
-
|
|
6530
|
+
} else {
|
|
6531
|
+
setSessionMode("plan");
|
|
6532
|
+
sessionRef.current?.setMode("plan");
|
|
6533
|
+
setToolChoice(void 0);
|
|
6534
|
+
setDisplayMessages((prev) => [
|
|
6535
|
+
...prev,
|
|
6536
|
+
{ role: "user", content: trimmed },
|
|
6537
|
+
{
|
|
6538
|
+
role: "assistant",
|
|
6539
|
+
content: "\u{1F4CB} \u5DF2\u5207\u6362\u4E3A **\u8BA1\u5212\u6A21\u5F0F**\n\n\u5728\u6B64\u6A21\u5F0F\u4E0B\uFF0C\u6211\u53EA\u80FD\u8BFB\u53D6\u548C\u5206\u6790\u4EE3\u7801\uFF0C\u4E0D\u4F1A\u6267\u884C\u4EFB\u4F55\u4FEE\u6539\u3002\n\u8F93\u5165 /code \u5207\u56DE\u4EE3\u7801\u6A21\u5F0F\u3002"
|
|
6540
|
+
}
|
|
6541
|
+
]);
|
|
6542
|
+
sessionRef.current?.reset();
|
|
5645
6543
|
}
|
|
5646
|
-
const target = cps[cps.length - n];
|
|
5647
6544
|
setInput("");
|
|
5648
|
-
await doRewind(target, n);
|
|
5649
6545
|
return;
|
|
5650
6546
|
}
|
|
5651
|
-
|
|
5652
|
-
|
|
5653
|
-
|
|
5654
|
-
|
|
5655
|
-
|
|
5656
|
-
|
|
5657
|
-
|
|
5658
|
-
|
|
5659
|
-
|
|
5660
|
-
|
|
5661
|
-
|
|
5662
|
-
|
|
5663
|
-
|
|
5664
|
-
|
|
5665
|
-
|
|
5666
|
-
|
|
5667
|
-
|
|
5668
|
-
|
|
5669
|
-
|
|
5670
|
-
|
|
5671
|
-
|
|
5672
|
-
|
|
5673
|
-
|
|
5674
|
-
|
|
5675
|
-
|
|
5676
|
-
|
|
5677
|
-
return;
|
|
5678
|
-
}
|
|
5679
|
-
if (cmdLower === "/effort") {
|
|
5680
|
-
const next = thinkingEffort === "high" ? "max" : "high";
|
|
5681
|
-
setThinkingEffort(next);
|
|
5682
|
-
setDisplayMessages((prev) => [
|
|
5683
|
-
...prev,
|
|
5684
|
-
{ role: "user", content: trimmed },
|
|
5685
|
-
{ role: "assistant", content: `\u63A8\u7406\u7B49\u7EA7\u5DF2\u5207\u6362\u4E3A ${next === "high" ? "High" : "Max"}` }
|
|
5686
|
-
]);
|
|
5687
|
-
setInput("");
|
|
5688
|
-
return;
|
|
5689
|
-
}
|
|
5690
|
-
if (cmdLower === "/plan") {
|
|
5691
|
-
if (sessionMode === "plan") {
|
|
5692
|
-
setDisplayMessages((prev) => [
|
|
5693
|
-
...prev,
|
|
5694
|
-
{ role: "user", content: trimmed },
|
|
5695
|
-
{ role: "assistant", content: "\u5DF2\u7ECF\u5728\u8BA1\u5212\u6A21\u5F0F\u4E2D\u3002\u8F93\u5165 /code \u5207\u56DE\u4EE3\u7801\u6A21\u5F0F\u3002" }
|
|
5696
|
-
]);
|
|
5697
|
-
} else {
|
|
5698
|
-
setSessionMode("plan");
|
|
5699
|
-
sessionRef.current?.setMode("plan");
|
|
5700
|
-
setToolChoice(void 0);
|
|
5701
|
-
setDisplayMessages((prev) => [
|
|
5702
|
-
...prev,
|
|
5703
|
-
{ role: "user", content: trimmed },
|
|
5704
|
-
{ role: "assistant", content: "\u{1F4CB} \u5DF2\u5207\u6362\u4E3A **\u8BA1\u5212\u6A21\u5F0F**\n\n\u5728\u6B64\u6A21\u5F0F\u4E0B\uFF0C\u6211\u53EA\u80FD\u8BFB\u53D6\u548C\u5206\u6790\u4EE3\u7801\uFF0C\u4E0D\u4F1A\u6267\u884C\u4EFB\u4F55\u4FEE\u6539\u3002\n\u8F93\u5165 /code \u5207\u56DE\u4EE3\u7801\u6A21\u5F0F\u3002" }
|
|
5705
|
-
]);
|
|
5706
|
-
sessionRef.current?.reset();
|
|
6547
|
+
if (cmdLower === "/code") {
|
|
6548
|
+
if (sessionMode === "code") {
|
|
6549
|
+
setDisplayMessages((prev) => [
|
|
6550
|
+
...prev,
|
|
6551
|
+
{ role: "user", content: trimmed },
|
|
6552
|
+
{
|
|
6553
|
+
role: "assistant",
|
|
6554
|
+
content: "\u5DF2\u7ECF\u5728\u4EE3\u7801\u6A21\u5F0F\u4E2D\u3002\u8F93\u5165 /plan \u5207\u56DE\u8BA1\u5212\u6A21\u5F0F\u3002"
|
|
6555
|
+
}
|
|
6556
|
+
]);
|
|
6557
|
+
} else {
|
|
6558
|
+
setSessionMode("code");
|
|
6559
|
+
sessionRef.current?.setMode("code");
|
|
6560
|
+
setToolChoice(void 0);
|
|
6561
|
+
setDisplayMessages((prev) => [
|
|
6562
|
+
...prev,
|
|
6563
|
+
{ role: "user", content: trimmed },
|
|
6564
|
+
{
|
|
6565
|
+
role: "assistant",
|
|
6566
|
+
content: "\u{1F6E0} \u5DF2\u5207\u6362\u4E3A **\u4EE3\u7801\u6A21\u5F0F**\n\n\u73B0\u5728\u53EF\u4EE5\u6B63\u5E38\u8BFB\u53D6\u548C\u4FEE\u6539\u4EE3\u7801\u4E86\u3002\n\u8F93\u5165 /plan \u5207\u6362\u4E3A\u8BA1\u5212\u6A21\u5F0F\uFF08\u53EA\u8BFB\u5206\u6790\uFF09\u3002"
|
|
6567
|
+
}
|
|
6568
|
+
]);
|
|
6569
|
+
sessionRef.current?.reset();
|
|
6570
|
+
}
|
|
6571
|
+
setInput("");
|
|
6572
|
+
return;
|
|
5707
6573
|
}
|
|
5708
|
-
|
|
5709
|
-
|
|
5710
|
-
|
|
5711
|
-
|
|
5712
|
-
if (sessionMode === "code") {
|
|
5713
|
-
setDisplayMessages((prev) => [
|
|
5714
|
-
...prev,
|
|
5715
|
-
{ role: "user", content: trimmed },
|
|
5716
|
-
{ role: "assistant", content: "\u5DF2\u7ECF\u5728\u4EE3\u7801\u6A21\u5F0F\u4E2D\u3002\u8F93\u5165 /plan \u5207\u56DE\u8BA1\u5212\u6A21\u5F0F\u3002" }
|
|
5717
|
-
]);
|
|
5718
|
-
} else {
|
|
5719
|
-
setSessionMode("code");
|
|
5720
|
-
sessionRef.current?.setMode("code");
|
|
5721
|
-
setToolChoice(void 0);
|
|
6574
|
+
if (cmdLower === "/tools") {
|
|
6575
|
+
const next = toolChoice === void 0 ? "none" : toolChoice === "none" ? "required" : toolChoice === "required" ? "auto" : void 0;
|
|
6576
|
+
setToolChoice(next);
|
|
6577
|
+
const label = next === void 0 ? "\u81EA\u52A8\uFF08\u9ED8\u8BA4\uFF09" : next === "none" ? "\u7981\u6B62\u8C03\u7528" : next === "required" ? "\u5F3A\u5236\u8C03\u7528" : "\u81EA\u52A8\uFF08\u9ED8\u8BA4\uFF09";
|
|
5722
6578
|
setDisplayMessages((prev) => [
|
|
5723
6579
|
...prev,
|
|
5724
6580
|
{ role: "user", content: trimmed },
|
|
5725
|
-
{ role: "assistant", content:
|
|
6581
|
+
{ role: "assistant", content: `\u5DE5\u5177\u8C03\u7528\u7B56\u7565\u5DF2\u5207\u6362\u4E3A ${label}` }
|
|
5726
6582
|
]);
|
|
5727
|
-
|
|
6583
|
+
setInput("");
|
|
6584
|
+
return;
|
|
6585
|
+
}
|
|
6586
|
+
const cmd = commandRegistry.get(cmdLower);
|
|
6587
|
+
if (cmd) {
|
|
6588
|
+
const result = cmd.handler();
|
|
6589
|
+
switch (result.kind) {
|
|
6590
|
+
case "exit":
|
|
6591
|
+
await sessionRef.current?.flushLog();
|
|
6592
|
+
process.exit(0);
|
|
6593
|
+
return;
|
|
6594
|
+
case "clear":
|
|
6595
|
+
setDisplayMessages([]);
|
|
6596
|
+
setStaticKey((prev) => prev + 1);
|
|
6597
|
+
setInput("");
|
|
6598
|
+
setStreamError(void 0);
|
|
6599
|
+
process.stdout.write("\x1B[2J\x1B[H\x1B[3J");
|
|
6600
|
+
sessionRef.current?.reset();
|
|
6601
|
+
return;
|
|
6602
|
+
case "navigate":
|
|
6603
|
+
setInput("");
|
|
6604
|
+
if (result.target === "game") {
|
|
6605
|
+
onLaunchGame?.();
|
|
6606
|
+
} else if (result.target === "stock") {
|
|
6607
|
+
onLaunchStock?.();
|
|
6608
|
+
}
|
|
6609
|
+
return;
|
|
6610
|
+
case "text":
|
|
6611
|
+
setDisplayMessages((prev) => [
|
|
6612
|
+
...prev,
|
|
6613
|
+
{ role: "user", content: trimmed },
|
|
6614
|
+
{ role: "assistant", content: result.content }
|
|
6615
|
+
]);
|
|
6616
|
+
setInput("");
|
|
6617
|
+
return;
|
|
6618
|
+
}
|
|
5728
6619
|
}
|
|
6620
|
+
setDisplayMessages((prev) => [
|
|
6621
|
+
...prev,
|
|
6622
|
+
{ role: "user", content: trimmed },
|
|
6623
|
+
{ role: "assistant", content: `\u672A\u77E5\u547D\u4EE4\uFF1A${trimmed}\u3002\u8F93\u5165 /help \u67E5\u770B\u3002` }
|
|
6624
|
+
]);
|
|
5729
6625
|
setInput("");
|
|
5730
6626
|
return;
|
|
5731
6627
|
}
|
|
5732
|
-
if (
|
|
5733
|
-
const next = toolChoice === void 0 ? "none" : toolChoice === "none" ? "required" : toolChoice === "required" ? "auto" : void 0;
|
|
5734
|
-
setToolChoice(next);
|
|
5735
|
-
const label = next === void 0 ? "\u81EA\u52A8\uFF08\u9ED8\u8BA4\uFF09" : next === "none" ? "\u7981\u6B62\u8C03\u7528" : next === "required" ? "\u5F3A\u5236\u8C03\u7528" : "\u81EA\u52A8\uFF08\u9ED8\u8BA4\uFF09";
|
|
6628
|
+
if (!sessionRef.current) {
|
|
5736
6629
|
setDisplayMessages((prev) => [
|
|
5737
6630
|
...prev,
|
|
5738
6631
|
{ role: "user", content: trimmed },
|
|
5739
|
-
{
|
|
6632
|
+
{
|
|
6633
|
+
role: "assistant",
|
|
6634
|
+
content: "\u26A0 \u65E0\u6CD5\u8FDE\u63A5\u5230 Provider\u3002\u8BF7\u68C0\u67E5 API Key \u548C\u7F51\u7EDC\u914D\u7F6E\u3002"
|
|
6635
|
+
}
|
|
5740
6636
|
]);
|
|
5741
6637
|
setInput("");
|
|
5742
6638
|
return;
|
|
5743
6639
|
}
|
|
5744
|
-
|
|
5745
|
-
if (cmd) {
|
|
5746
|
-
const result = cmd.handler();
|
|
5747
|
-
switch (result.kind) {
|
|
5748
|
-
case "exit":
|
|
5749
|
-
await sessionRef.current?.flushLog();
|
|
5750
|
-
process.exit(0);
|
|
5751
|
-
return;
|
|
5752
|
-
case "clear":
|
|
5753
|
-
setDisplayMessages([]);
|
|
5754
|
-
setStaticKey((prev) => prev + 1);
|
|
5755
|
-
setInput("");
|
|
5756
|
-
setStreamError(void 0);
|
|
5757
|
-
process.stdout.write("\x1B[2J\x1B[H\x1B[3J");
|
|
5758
|
-
sessionRef.current?.reset();
|
|
5759
|
-
return;
|
|
5760
|
-
case "navigate":
|
|
5761
|
-
setInput("");
|
|
5762
|
-
if (result.target === "game") {
|
|
5763
|
-
onLaunchGame?.();
|
|
5764
|
-
} else if (result.target === "stock") {
|
|
5765
|
-
onLaunchStock?.();
|
|
5766
|
-
}
|
|
5767
|
-
return;
|
|
5768
|
-
case "text":
|
|
5769
|
-
setDisplayMessages((prev) => [
|
|
5770
|
-
...prev,
|
|
5771
|
-
{ role: "user", content: trimmed },
|
|
5772
|
-
{ role: "assistant", content: result.content }
|
|
5773
|
-
]);
|
|
5774
|
-
setInput("");
|
|
5775
|
-
return;
|
|
5776
|
-
}
|
|
5777
|
-
}
|
|
5778
|
-
setDisplayMessages((prev) => [
|
|
5779
|
-
...prev,
|
|
5780
|
-
{ role: "user", content: trimmed },
|
|
5781
|
-
{ role: "assistant", content: `\u672A\u77E5\u547D\u4EE4\uFF1A${trimmed}\u3002\u8F93\u5165 /help \u67E5\u770B\u3002` }
|
|
5782
|
-
]);
|
|
6640
|
+
setDisplayMessages((prev) => [...prev, { role: "user", content: trimmed }]);
|
|
5783
6641
|
setInput("");
|
|
5784
|
-
|
|
5785
|
-
|
|
5786
|
-
|
|
5787
|
-
|
|
5788
|
-
|
|
5789
|
-
|
|
5790
|
-
|
|
5791
|
-
|
|
5792
|
-
|
|
5793
|
-
|
|
5794
|
-
|
|
5795
|
-
|
|
5796
|
-
|
|
5797
|
-
|
|
5798
|
-
|
|
5799
|
-
|
|
5800
|
-
|
|
5801
|
-
|
|
5802
|
-
|
|
5803
|
-
|
|
5804
|
-
|
|
5805
|
-
|
|
5806
|
-
|
|
5807
|
-
|
|
5808
|
-
|
|
5809
|
-
|
|
5810
|
-
|
|
5811
|
-
|
|
5812
|
-
|
|
5813
|
-
|
|
5814
|
-
|
|
5815
|
-
|
|
5816
|
-
|
|
5817
|
-
|
|
5818
|
-
|
|
5819
|
-
|
|
5820
|
-
|
|
5821
|
-
|
|
5822
|
-
|
|
5823
|
-
|
|
5824
|
-
|
|
5825
|
-
|
|
5826
|
-
|
|
5827
|
-
|
|
5828
|
-
|
|
5829
|
-
|
|
5830
|
-
|
|
5831
|
-
|
|
5832
|
-
|
|
5833
|
-
|
|
5834
|
-
|
|
5835
|
-
|
|
5836
|
-
|
|
5837
|
-
|
|
5838
|
-
|
|
5839
|
-
|
|
5840
|
-
|
|
5841
|
-
|
|
5842
|
-
|
|
5843
|
-
|
|
5844
|
-
|
|
5845
|
-
|
|
5846
|
-
|
|
5847
|
-
|
|
5848
|
-
|
|
5849
|
-
|
|
5850
|
-
for (const call of event.calls) {
|
|
5851
|
-
if (isFileMutatingTool(call.name)) {
|
|
5852
|
-
currentRoundModifiedRef.current = true;
|
|
5853
|
-
break;
|
|
6642
|
+
setIsStreaming(true);
|
|
6643
|
+
setStreamingPhase("thinking");
|
|
6644
|
+
setStreamingPlaceholder(pickRandom(STREAMING_PLACEHOLDERS));
|
|
6645
|
+
setCurrentContent("");
|
|
6646
|
+
setCurrentReasoning([]);
|
|
6647
|
+
setCurrentToolCalls([]);
|
|
6648
|
+
setCurrentUsage(void 0);
|
|
6649
|
+
setCurrentElapsed(void 0);
|
|
6650
|
+
setCurrentCost(void 0);
|
|
6651
|
+
setStreamingModel(void 0);
|
|
6652
|
+
setStreamError(void 0);
|
|
6653
|
+
currentContentRef.current = "";
|
|
6654
|
+
currentReasoningRef.current = [];
|
|
6655
|
+
currentToolCallsRef.current = [];
|
|
6656
|
+
currentUsageRef.current = void 0;
|
|
6657
|
+
currentElapsedRef.current = void 0;
|
|
6658
|
+
currentCostRef.current = void 0;
|
|
6659
|
+
currentModelRef.current = void 0;
|
|
6660
|
+
streamErrorRef.current = void 0;
|
|
6661
|
+
currentRoundModifiedRef.current = false;
|
|
6662
|
+
setRewindHintPhase("idle");
|
|
6663
|
+
if (rewindHintTimerRef.current) {
|
|
6664
|
+
clearTimeout(rewindHintTimerRef.current);
|
|
6665
|
+
rewindHintTimerRef.current = null;
|
|
6666
|
+
}
|
|
6667
|
+
const session = sessionRef.current;
|
|
6668
|
+
const abortController = new AbortController();
|
|
6669
|
+
abortRef.current = abortController;
|
|
6670
|
+
try {
|
|
6671
|
+
for await (const event of session.chat(trimmed, {
|
|
6672
|
+
thinkingAllowed: thinkingEnabled || void 0,
|
|
6673
|
+
thinkingEffort: thinkingEnabled ? thinkingEffort : void 0,
|
|
6674
|
+
responseFormat: responseFormat !== "text" ? responseFormat : void 0,
|
|
6675
|
+
toolChoice
|
|
6676
|
+
})) {
|
|
6677
|
+
if (abortController.signal.aborted) break;
|
|
6678
|
+
switch (event.type) {
|
|
6679
|
+
case "text_delta":
|
|
6680
|
+
setStreamingPhase("generating");
|
|
6681
|
+
setCurrentContent((prev) => {
|
|
6682
|
+
const next = prev + event.content;
|
|
6683
|
+
currentContentRef.current = next;
|
|
6684
|
+
return next;
|
|
6685
|
+
});
|
|
6686
|
+
break;
|
|
6687
|
+
case "reasoning_delta":
|
|
6688
|
+
setStreamingPhase("thinking");
|
|
6689
|
+
setCurrentReasoning((prev) => {
|
|
6690
|
+
const last = prev[prev.length - 1];
|
|
6691
|
+
const next = last !== void 0 ? [...prev.slice(0, -1), last + event.content] : [...prev, event.content];
|
|
6692
|
+
currentReasoningRef.current = next;
|
|
6693
|
+
return next;
|
|
6694
|
+
});
|
|
6695
|
+
break;
|
|
6696
|
+
case "tool_calls":
|
|
6697
|
+
setStreamingPhase("calling_tools");
|
|
6698
|
+
setCurrentToolCalls((prev) => {
|
|
6699
|
+
const next = [...prev, ...event.calls];
|
|
6700
|
+
currentToolCallsRef.current = next;
|
|
6701
|
+
return next;
|
|
6702
|
+
});
|
|
6703
|
+
for (const call of event.calls) {
|
|
6704
|
+
if (isFileMutatingTool(call.name)) {
|
|
6705
|
+
currentRoundModifiedRef.current = true;
|
|
6706
|
+
break;
|
|
6707
|
+
}
|
|
5854
6708
|
}
|
|
5855
|
-
|
|
5856
|
-
|
|
5857
|
-
|
|
5858
|
-
|
|
5859
|
-
|
|
5860
|
-
|
|
5861
|
-
|
|
5862
|
-
|
|
5863
|
-
|
|
5864
|
-
|
|
5865
|
-
|
|
5866
|
-
|
|
5867
|
-
|
|
6709
|
+
break;
|
|
6710
|
+
case "tool_result":
|
|
6711
|
+
setStreamingPhase("executing_tools");
|
|
6712
|
+
setTimeout(() => setStreamingPhase("thinking"), 300);
|
|
6713
|
+
setCurrentContent("");
|
|
6714
|
+
currentContentRef.current = "";
|
|
6715
|
+
setCurrentReasoning((prev) => {
|
|
6716
|
+
const next = [...prev, ""];
|
|
6717
|
+
currentReasoningRef.current = next;
|
|
6718
|
+
return next;
|
|
6719
|
+
});
|
|
6720
|
+
setCurrentToolCalls([]);
|
|
6721
|
+
currentToolCallsRef.current = [];
|
|
6722
|
+
const r = event.result;
|
|
6723
|
+
if (event.name.startsWith("todo_") && event.todoSnapshot) {
|
|
6724
|
+
setTodoSnapshot(event.todoSnapshot);
|
|
6725
|
+
} else {
|
|
6726
|
+
const line = r.success ? r.summary ?? `\u2705 ${event.name}: ${r.data.slice(0, 500)}${r.data.length > 500 ? "..." : ""}` : `\u274C ${event.name}: ${r.error ?? "\u6267\u884C\u5931\u8D25"}`;
|
|
6727
|
+
setDisplayMessages((prev) => [
|
|
6728
|
+
...prev,
|
|
6729
|
+
{
|
|
6730
|
+
role: "tool",
|
|
6731
|
+
content: line,
|
|
6732
|
+
diff: r.diff
|
|
6733
|
+
}
|
|
6734
|
+
]);
|
|
6735
|
+
}
|
|
6736
|
+
break;
|
|
6737
|
+
case "usage":
|
|
6738
|
+
setCurrentUsage(event.usage);
|
|
6739
|
+
setStreamingModel(event.model);
|
|
6740
|
+
currentUsageRef.current = event.usage;
|
|
6741
|
+
currentModelRef.current = event.model;
|
|
5868
6742
|
{
|
|
5869
|
-
|
|
5870
|
-
|
|
5871
|
-
|
|
6743
|
+
const cost = calculateCost(
|
|
6744
|
+
event.usage,
|
|
6745
|
+
event.model
|
|
6746
|
+
);
|
|
6747
|
+
setCurrentCost(cost.totalCost);
|
|
6748
|
+
currentCostRef.current = cost.totalCost;
|
|
5872
6749
|
}
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
|
|
5877
|
-
|
|
5878
|
-
|
|
5879
|
-
|
|
6750
|
+
break;
|
|
6751
|
+
case "done":
|
|
6752
|
+
setCurrentElapsed(event.elapsed);
|
|
6753
|
+
currentElapsedRef.current = event.elapsed;
|
|
6754
|
+
break;
|
|
6755
|
+
case "error":
|
|
6756
|
+
setStreamError(event.error.message);
|
|
6757
|
+
streamErrorRef.current = event.error.message;
|
|
6758
|
+
break;
|
|
6759
|
+
}
|
|
6760
|
+
}
|
|
6761
|
+
} catch (err) {
|
|
6762
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
6763
|
+
setStreamError(msg);
|
|
6764
|
+
streamErrorRef.current = msg;
|
|
6765
|
+
} finally {
|
|
6766
|
+
setIsStreaming(false);
|
|
6767
|
+
setStreamingPhase(null);
|
|
6768
|
+
setIdlePlaceholder(pickRandom(IDLE_PLACEHOLDERS));
|
|
6769
|
+
abortRef.current = null;
|
|
6770
|
+
const finContent = currentContentRef.current;
|
|
6771
|
+
const finReasoning = currentReasoningRef.current.map((s) => s.trim()).filter((s) => s.length > 0);
|
|
6772
|
+
const finToolCalls = currentToolCallsRef.current.length > 0 ? currentToolCallsRef.current : void 0;
|
|
6773
|
+
const finStreamError = streamErrorRef.current;
|
|
6774
|
+
if (finContent || finToolCalls || finStreamError) {
|
|
6775
|
+
const completed = {
|
|
6776
|
+
content: finStreamError ? `\u26A0 \u8BF7\u6C42\u51FA\u9519\uFF1A${finStreamError}` : finContent || "",
|
|
6777
|
+
...finReasoning.length > 0 ? { reasoning: finReasoning } : {},
|
|
6778
|
+
toolCalls: finToolCalls,
|
|
6779
|
+
usage: currentUsageRef.current,
|
|
6780
|
+
elapsed: currentElapsedRef.current,
|
|
6781
|
+
cost: currentCostRef.current,
|
|
6782
|
+
model: currentModelRef.current
|
|
6783
|
+
};
|
|
6784
|
+
setDisplayMessages((prev) => [
|
|
6785
|
+
...prev,
|
|
5880
6786
|
{
|
|
5881
|
-
|
|
5882
|
-
|
|
5883
|
-
|
|
6787
|
+
role: "assistant",
|
|
6788
|
+
content: completed.content,
|
|
6789
|
+
assistantDetail: completed
|
|
5884
6790
|
}
|
|
5885
|
-
|
|
5886
|
-
|
|
5887
|
-
|
|
5888
|
-
|
|
5889
|
-
|
|
5890
|
-
|
|
5891
|
-
|
|
5892
|
-
|
|
5893
|
-
|
|
6791
|
+
]);
|
|
6792
|
+
}
|
|
6793
|
+
if (currentRoundModifiedRef.current && !finStreamError) {
|
|
6794
|
+
setRewindHintPhase("pending");
|
|
6795
|
+
if (rewindHintTimerRef.current) clearTimeout(rewindHintTimerRef.current);
|
|
6796
|
+
rewindHintTimerRef.current = setTimeout(() => {
|
|
6797
|
+
setRewindHintPhase((prev) => prev === "pending" ? "visible" : prev);
|
|
6798
|
+
rewindHintTimerRef.current = null;
|
|
6799
|
+
}, 2e3);
|
|
5894
6800
|
}
|
|
5895
6801
|
}
|
|
5896
|
-
}
|
|
5897
|
-
|
|
5898
|
-
|
|
5899
|
-
|
|
5900
|
-
|
|
5901
|
-
|
|
5902
|
-
|
|
5903
|
-
|
|
5904
|
-
|
|
5905
|
-
|
|
5906
|
-
|
|
5907
|
-
|
|
5908
|
-
|
|
5909
|
-
|
|
5910
|
-
|
|
5911
|
-
|
|
5912
|
-
|
|
5913
|
-
|
|
5914
|
-
|
|
5915
|
-
|
|
5916
|
-
};
|
|
5917
|
-
setDisplayMessages((prev) => [
|
|
5918
|
-
...prev,
|
|
5919
|
-
{
|
|
5920
|
-
role: "assistant",
|
|
5921
|
-
content: completed.content,
|
|
5922
|
-
assistantDetail: completed
|
|
5923
|
-
}
|
|
5924
|
-
]);
|
|
5925
|
-
}
|
|
5926
|
-
if (currentRoundModifiedRef.current && !finStreamError) {
|
|
5927
|
-
setRewindHintPhase("pending");
|
|
5928
|
-
if (rewindHintTimerRef.current) clearTimeout(rewindHintTimerRef.current);
|
|
5929
|
-
rewindHintTimerRef.current = setTimeout(() => {
|
|
5930
|
-
setRewindHintPhase((prev) => prev === "pending" ? "visible" : prev);
|
|
5931
|
-
rewindHintTimerRef.current = null;
|
|
5932
|
-
}, 2e3);
|
|
5933
|
-
}
|
|
5934
|
-
}
|
|
5935
|
-
}, [onLaunchGame, onLaunchStock, currentContent, currentToolCalls, skills, skillSelectIndex, getFilteredSkills, thinkingEnabled, thinkingEffort, responseFormat, toolChoice, activeModel, sessionMode, isStreaming, rewinding]);
|
|
6802
|
+
},
|
|
6803
|
+
[
|
|
6804
|
+
onLaunchGame,
|
|
6805
|
+
onLaunchStock,
|
|
6806
|
+
currentContent,
|
|
6807
|
+
currentReasoning,
|
|
6808
|
+
currentToolCalls,
|
|
6809
|
+
skills,
|
|
6810
|
+
skillSelectIndex,
|
|
6811
|
+
getFilteredSkills,
|
|
6812
|
+
thinkingEnabled,
|
|
6813
|
+
thinkingEffort,
|
|
6814
|
+
responseFormat,
|
|
6815
|
+
toolChoice,
|
|
6816
|
+
activeModel,
|
|
6817
|
+
sessionMode,
|
|
6818
|
+
isStreaming,
|
|
6819
|
+
rewinding
|
|
6820
|
+
]
|
|
6821
|
+
);
|
|
5936
6822
|
useEffect4(() => {
|
|
5937
6823
|
if (!isStreaming && externalCostTracker) {
|
|
5938
6824
|
setTodayCost(externalCostTracker.todayTotalCost);
|
|
5939
6825
|
}
|
|
5940
6826
|
}, [isStreaming, externalCostTracker]);
|
|
5941
|
-
return /* @__PURE__ */
|
|
5942
|
-
!hasConversationStarted && /* @__PURE__ */
|
|
5943
|
-
/* @__PURE__ */
|
|
6827
|
+
return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", paddingLeft: 1, paddingRight: 1, children: [
|
|
6828
|
+
!hasConversationStarted && /* @__PURE__ */ jsxs10(Box10, { flexDirection: "row", marginBottom: 1, children: [
|
|
6829
|
+
/* @__PURE__ */ jsx10(Box10, { flexDirection: "column", marginRight: 4, children: LOGO_LINES.map((line, i) => {
|
|
5944
6830
|
const colorIndex = (i + offset) % CYBER_PALETTE.length;
|
|
5945
|
-
return /* @__PURE__ */
|
|
6831
|
+
return /* @__PURE__ */ jsx10(Box10, { children: /* @__PURE__ */ jsx10(Text11, { bold: true, color: CYBER_PALETTE[colorIndex], children: line }) }, i);
|
|
5946
6832
|
}) }),
|
|
5947
|
-
/* @__PURE__ */
|
|
5948
|
-
/* @__PURE__ */
|
|
6833
|
+
/* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", justifyContent: "center", children: [
|
|
6834
|
+
/* @__PURE__ */ jsxs10(Text11, { color: "#00ff41", children: [
|
|
5949
6835
|
" \u2714 ",
|
|
5950
6836
|
"\u5DF2\u5C31\u7EEA ",
|
|
5951
6837
|
skillCount,
|
|
5952
6838
|
" \u4E2A Skill"
|
|
5953
6839
|
] }),
|
|
5954
|
-
/* @__PURE__ */
|
|
6840
|
+
/* @__PURE__ */ jsxs10(Text11, { color: "#00ffff", children: [
|
|
5955
6841
|
" \u2139 ",
|
|
5956
6842
|
"\u5DF2\u5C31\u7EEA ",
|
|
5957
6843
|
toolCount,
|
|
5958
6844
|
" \u4E2A\u5DE5\u5177"
|
|
5959
6845
|
] }),
|
|
5960
|
-
/* @__PURE__ */
|
|
6846
|
+
/* @__PURE__ */ jsxs10(Text11, { color: "#00ffff", children: [
|
|
5961
6847
|
" \u{1F527} \u6A21\u578B ",
|
|
5962
6848
|
SUPPORTED_MODELS[activeModel]?.displayName ?? activeModel
|
|
5963
6849
|
] }),
|
|
5964
|
-
thinkingEnabled && /* @__PURE__ */
|
|
6850
|
+
thinkingEnabled && /* @__PURE__ */ jsxs10(Text11, { color: "#ff9800", children: [
|
|
5965
6851
|
" \u{1F9E0} \u6DF1\u5EA6\u601D\u8003 ",
|
|
5966
6852
|
thinkingEffort === "max" ? "Max" : "High"
|
|
5967
6853
|
] }),
|
|
5968
|
-
sessionMode === "plan" && /* @__PURE__ */
|
|
5969
|
-
responseFormat === "json_object" && /* @__PURE__ */
|
|
5970
|
-
toolChoice !== void 0 && /* @__PURE__ */
|
|
6854
|
+
sessionMode === "plan" && /* @__PURE__ */ jsx10(Text11, { color: "#ff69b4", bold: true, children: " \u{1F4CB} \u8BA1\u5212\u6A21\u5F0F" }),
|
|
6855
|
+
responseFormat === "json_object" && /* @__PURE__ */ jsx10(Text11, { color: "#4caf50", children: " \u{1F4C4} JSON" }),
|
|
6856
|
+
toolChoice !== void 0 && /* @__PURE__ */ jsxs10(Text11, { color: "#e91e63", children: [
|
|
5971
6857
|
" \u{1F6E0} ",
|
|
5972
6858
|
toolChoice === "none" ? "\u7981\u6B62\u5DE5\u5177" : toolChoice === "required" ? "\u5F3A\u5236\u5DE5\u5177" : ""
|
|
5973
6859
|
] }),
|
|
@@ -5975,52 +6861,62 @@ function ChatSession({
|
|
|
5975
6861
|
const tip = cmdTips[cmdTipIndex % cmdTips.length];
|
|
5976
6862
|
if (!tip) return null;
|
|
5977
6863
|
const text = `${tip.name} ${tip.desc}`;
|
|
5978
|
-
return /* @__PURE__ */
|
|
5979
|
-
/* @__PURE__ */
|
|
5980
|
-
cmdTipGradientColors.length > 0 ? text.split("").map((ch, i) => /* @__PURE__ */
|
|
6864
|
+
return /* @__PURE__ */ jsxs10(Text11, { children: [
|
|
6865
|
+
/* @__PURE__ */ jsx10(Text11, { color: "#808080", children: " \u{1F4A1} " }),
|
|
6866
|
+
cmdTipGradientColors.length > 0 ? text.split("").map((ch, i) => /* @__PURE__ */ jsx10(Text11, { color: cmdTipGradientColors[i] || void 0, children: ch }, i)) : /* @__PURE__ */ jsx10(Text11, { color: "#808080", children: text })
|
|
5981
6867
|
] });
|
|
5982
6868
|
})(),
|
|
5983
|
-
verbose ? /* @__PURE__ */
|
|
6869
|
+
verbose ? /* @__PURE__ */ jsx10(Text11, { color: "#ff1493", children: " \u26A1 Verbose" }) : null
|
|
5984
6870
|
] }),
|
|
5985
|
-
/* @__PURE__ */
|
|
5986
|
-
|
|
5987
|
-
|
|
5988
|
-
|
|
5989
|
-
|
|
5990
|
-
|
|
5991
|
-
|
|
5992
|
-
|
|
5993
|
-
|
|
5994
|
-
|
|
5995
|
-
|
|
5996
|
-
|
|
5997
|
-
|
|
5998
|
-
|
|
5999
|
-
|
|
6000
|
-
|
|
6871
|
+
/* @__PURE__ */ jsxs10(
|
|
6872
|
+
Box10,
|
|
6873
|
+
{
|
|
6874
|
+
flexGrow: 1,
|
|
6875
|
+
flexDirection: "column",
|
|
6876
|
+
justifyContent: "center",
|
|
6877
|
+
alignItems: "flex-end",
|
|
6878
|
+
children: [
|
|
6879
|
+
balanceLoading && balance === null ? /* @__PURE__ */ jsx10(Text11, { color: "yellow", children: " \u23F3 \u67E5\u8BE2\u4F59\u989D..." }) : balance !== null ? /* @__PURE__ */ jsxs10(Box10, { flexDirection: "row", children: [
|
|
6880
|
+
/* @__PURE__ */ jsx10(Text11, { color: "yellow", children: "\u{1F4B0} " }),
|
|
6881
|
+
/* @__PURE__ */ jsxs10(Text11, { color: "yellow", children: [
|
|
6882
|
+
"\u4F59\u989D \xA5",
|
|
6883
|
+
balance.toFixed(2)
|
|
6884
|
+
] })
|
|
6885
|
+
] }) : null,
|
|
6886
|
+
todayCost !== null ? /* @__PURE__ */ jsxs10(Box10, { flexDirection: "row", children: [
|
|
6887
|
+
/* @__PURE__ */ jsx10(Text11, { color: "cyan", children: "\u{1F4CA} " }),
|
|
6888
|
+
/* @__PURE__ */ jsxs10(Text11, { color: "cyan", children: [
|
|
6889
|
+
"\u4ECA\u65E5 \xA5",
|
|
6890
|
+
todayCost.toFixed(2)
|
|
6891
|
+
] })
|
|
6892
|
+
] }) : null
|
|
6893
|
+
]
|
|
6894
|
+
}
|
|
6895
|
+
)
|
|
6001
6896
|
] }),
|
|
6002
|
-
/* @__PURE__ */
|
|
6003
|
-
/* @__PURE__ */
|
|
6897
|
+
/* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", marginTop: 1, children: [
|
|
6898
|
+
/* @__PURE__ */ jsx10(Static, { items: displayMessages, children: (msg, i) => {
|
|
6004
6899
|
if (msg.role === "user") {
|
|
6005
|
-
return /* @__PURE__ */
|
|
6006
|
-
/* @__PURE__ */
|
|
6007
|
-
/* @__PURE__ */
|
|
6900
|
+
return /* @__PURE__ */ jsxs10(Box10, { marginTop: 1, children: [
|
|
6901
|
+
/* @__PURE__ */ jsx10(Box10, { width: 4, flexShrink: 0, children: /* @__PURE__ */ jsx10(Text11, { bold: true, color: "#00ff41", children: "\u{1F464}" }) }),
|
|
6902
|
+
/* @__PURE__ */ jsx10(Box10, { flexGrow: 1, children: /* @__PURE__ */ jsx10(Text11, { wrap: "wrap", children: msg.content }) })
|
|
6008
6903
|
] }, i);
|
|
6009
6904
|
}
|
|
6010
6905
|
if (msg.role === "tool") {
|
|
6011
|
-
return /* @__PURE__ */
|
|
6012
|
-
/* @__PURE__ */
|
|
6013
|
-
/* @__PURE__ */
|
|
6014
|
-
/* @__PURE__ */
|
|
6906
|
+
return /* @__PURE__ */ jsxs10(Box10, { marginTop: 1, flexDirection: "column", children: [
|
|
6907
|
+
/* @__PURE__ */ jsxs10(Box10, { flexDirection: "row", children: [
|
|
6908
|
+
/* @__PURE__ */ jsx10(Box10, { width: 4, flexShrink: 0, children: /* @__PURE__ */ jsx10(Text11, { dimColor: true, children: "\u{1F527}" }) }),
|
|
6909
|
+
/* @__PURE__ */ jsx10(Box10, { flexGrow: 1, children: /* @__PURE__ */ jsx10(Text11, { dimColor: true, wrap: "wrap", children: msg.content }) })
|
|
6015
6910
|
] }),
|
|
6016
|
-
msg.diff && /* @__PURE__ */
|
|
6911
|
+
msg.diff && /* @__PURE__ */ jsx10(DiffPreview, { diff: msg.diff })
|
|
6017
6912
|
] }, i);
|
|
6018
6913
|
}
|
|
6019
6914
|
const detail = msg.assistantDetail;
|
|
6020
|
-
return /* @__PURE__ */
|
|
6915
|
+
return /* @__PURE__ */ jsx10(
|
|
6021
6916
|
AssistantMessage,
|
|
6022
6917
|
{
|
|
6023
6918
|
content: msg.content,
|
|
6919
|
+
reasoning: detail?.reasoning,
|
|
6024
6920
|
toolCalls: detail?.toolCalls,
|
|
6025
6921
|
isStreaming: false,
|
|
6026
6922
|
usage: detail?.usage,
|
|
@@ -6031,10 +6927,11 @@ function ChatSession({
|
|
|
6031
6927
|
i
|
|
6032
6928
|
);
|
|
6033
6929
|
} }, staticKey),
|
|
6034
|
-
isStreaming && /* @__PURE__ */
|
|
6930
|
+
isStreaming && /* @__PURE__ */ jsx10(
|
|
6035
6931
|
AssistantMessage,
|
|
6036
6932
|
{
|
|
6037
6933
|
content: currentContent,
|
|
6934
|
+
reasoning: currentReasoning,
|
|
6038
6935
|
toolCalls: currentToolCalls.length > 0 ? currentToolCalls : void 0,
|
|
6039
6936
|
isStreaming: true,
|
|
6040
6937
|
usage: _currentUsage,
|
|
@@ -6042,106 +6939,100 @@ function ChatSession({
|
|
|
6042
6939
|
model: _streamingModel
|
|
6043
6940
|
}
|
|
6044
6941
|
),
|
|
6045
|
-
!isStreaming && streamError && /* @__PURE__ */
|
|
6942
|
+
!isStreaming && streamError && /* @__PURE__ */ jsx10(Box10, { marginTop: 1, marginLeft: 3, children: /* @__PURE__ */ jsxs10(Text11, { color: "red", children: [
|
|
6046
6943
|
"\u26A0 ",
|
|
6047
6944
|
streamError
|
|
6048
6945
|
] }) })
|
|
6049
6946
|
] }),
|
|
6050
|
-
|
|
6051
|
-
|
|
6052
|
-
/* @__PURE__ */
|
|
6053
|
-
|
|
6947
|
+
todoSnapshot.length > 0 && /* @__PURE__ */ jsx10(TodoListPanel, { items: todoSnapshot }),
|
|
6948
|
+
selectingModel ? /* @__PURE__ */ jsxs10(Box10, { marginTop: 1, flexDirection: "column", children: [
|
|
6949
|
+
/* @__PURE__ */ jsx10(Text11, { color: "#00ffff", dimColor: true, children: "\u2500".repeat(dividerWidth) }),
|
|
6950
|
+
/* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", marginTop: 1, children: [
|
|
6951
|
+
/* @__PURE__ */ jsx10(Text11, { bold: true, color: "#00ffff", children: "\u9009\u62E9\u6A21\u578B\uFF1A" }),
|
|
6054
6952
|
modelOptions.map((id, i) => {
|
|
6055
6953
|
const meta = SUPPORTED_MODELS[id];
|
|
6056
6954
|
const isCurrent = id === activeModel;
|
|
6057
6955
|
const isSelected = i === modelSelectIndex;
|
|
6058
6956
|
const marker = isSelected ? " > " : " ";
|
|
6059
6957
|
const suffix = isCurrent ? " (\u5F53\u524D)" : "";
|
|
6060
|
-
return /* @__PURE__ */
|
|
6061
|
-
/* @__PURE__ */
|
|
6062
|
-
|
|
6063
|
-
|
|
6064
|
-
|
|
6065
|
-
|
|
6066
|
-
|
|
6067
|
-
marker,
|
|
6068
|
-
meta.displayName,
|
|
6069
|
-
suffix
|
|
6070
|
-
]
|
|
6071
|
-
}
|
|
6072
|
-
),
|
|
6073
|
-
isSelected && /* @__PURE__ */ jsxs9(Text10, { color: "#808080", children: [
|
|
6958
|
+
return /* @__PURE__ */ jsxs10(Box10, { children: [
|
|
6959
|
+
/* @__PURE__ */ jsxs10(Text11, { color: isSelected ? "#00ff41" : void 0, bold: isSelected, children: [
|
|
6960
|
+
marker,
|
|
6961
|
+
meta.displayName,
|
|
6962
|
+
suffix
|
|
6963
|
+
] }),
|
|
6964
|
+
isSelected && /* @__PURE__ */ jsxs10(Text11, { color: "#808080", children: [
|
|
6074
6965
|
" \u2014 ",
|
|
6075
6966
|
id
|
|
6076
6967
|
] })
|
|
6077
6968
|
] }, id);
|
|
6078
6969
|
}),
|
|
6079
|
-
/* @__PURE__ */
|
|
6970
|
+
/* @__PURE__ */ jsx10(Box10, { marginTop: 1, children: /* @__PURE__ */ jsx10(Text11, { color: "#808080", dimColor: true, children: "\u2191\u2193 \u9009\u62E9 \xB7 Enter \u786E\u8BA4 \xB7 Esc \u53D6\u6D88" }) })
|
|
6080
6971
|
] }),
|
|
6081
|
-
/* @__PURE__ */
|
|
6082
|
-
] }) : rewindSelecting ? /* @__PURE__ */
|
|
6083
|
-
/* @__PURE__ */
|
|
6084
|
-
/* @__PURE__ */
|
|
6085
|
-
/* @__PURE__ */
|
|
6972
|
+
/* @__PURE__ */ jsx10(Text11, { color: "#00ffff", dimColor: true, children: "\u2500".repeat(dividerWidth) })
|
|
6973
|
+
] }) : rewindSelecting ? /* @__PURE__ */ jsxs10(Box10, { marginTop: 1, flexDirection: "column", children: [
|
|
6974
|
+
/* @__PURE__ */ jsx10(Text11, { color: "#00ffff", dimColor: true, children: "\u2500".repeat(dividerWidth) }),
|
|
6975
|
+
/* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", marginTop: 1, children: [
|
|
6976
|
+
/* @__PURE__ */ jsx10(Text11, { bold: true, color: "#ff9800", children: "\u9009\u62E9\u8981\u56DE\u9000\u7684\u68C0\u67E5\u70B9\uFF1A" }),
|
|
6086
6977
|
rewindList.map((cp2, i) => {
|
|
6087
6978
|
const isSelected = i === rewindSelectIndex;
|
|
6088
6979
|
const marker = isSelected ? " > " : " ";
|
|
6089
6980
|
const time = new Date(cp2.timestamp).toLocaleTimeString();
|
|
6090
6981
|
const preview = cp2.preview || "(\u7A7A)";
|
|
6091
6982
|
const tag = cp2.isGitRepo ? "" : " [\u975E git\uFF0C\u4EC5\u5BF9\u8BDD]";
|
|
6092
|
-
return /* @__PURE__ */
|
|
6093
|
-
|
|
6094
|
-
|
|
6095
|
-
|
|
6096
|
-
|
|
6097
|
-
|
|
6098
|
-
|
|
6099
|
-
|
|
6100
|
-
|
|
6101
|
-
|
|
6102
|
-
|
|
6103
|
-
" `",
|
|
6104
|
-
preview,
|
|
6105
|
-
tag,
|
|
6106
|
-
"`"
|
|
6107
|
-
]
|
|
6108
|
-
}
|
|
6109
|
-
) }, cp2.index);
|
|
6983
|
+
return /* @__PURE__ */ jsx10(Box10, { children: /* @__PURE__ */ jsxs10(Text11, { color: isSelected ? "#ff9800" : void 0, bold: isSelected, children: [
|
|
6984
|
+
marker,
|
|
6985
|
+
"#",
|
|
6986
|
+
i + 1,
|
|
6987
|
+
" ",
|
|
6988
|
+
time,
|
|
6989
|
+
" `",
|
|
6990
|
+
preview,
|
|
6991
|
+
tag,
|
|
6992
|
+
"`"
|
|
6993
|
+
] }) }, cp2.index);
|
|
6110
6994
|
}),
|
|
6111
|
-
/* @__PURE__ */
|
|
6995
|
+
/* @__PURE__ */ jsx10(Box10, { marginTop: 1, children: /* @__PURE__ */ jsx10(Text11, { color: "#808080", dimColor: true, children: "\u2191\u2193 \u9009\u62E9 \xB7 Enter \u786E\u8BA4 \xB7 Esc \u53D6\u6D88" }) })
|
|
6112
6996
|
] }),
|
|
6113
|
-
/* @__PURE__ */
|
|
6114
|
-
] }) : /* @__PURE__ */
|
|
6115
|
-
(hasConversationStarted || sessionMode === "plan") && isStreaming && streamingPhase ? /* @__PURE__ */
|
|
6997
|
+
/* @__PURE__ */ jsx10(Text11, { color: "#00ffff", dimColor: true, children: "\u2500".repeat(dividerWidth) })
|
|
6998
|
+
] }) : /* @__PURE__ */ jsxs10(Fragment2, { children: [
|
|
6999
|
+
(hasConversationStarted || sessionMode === "plan") && isStreaming && streamingPhase ? /* @__PURE__ */ jsx10(Box10, { marginTop: 1, justifyContent: "center", children: /* @__PURE__ */ jsxs10(Text11, { bold: true, color: PHASE_CONFIG[streamingPhase].color, children: [
|
|
6116
7000
|
PHASE_CONFIG[streamingPhase].icon,
|
|
6117
7001
|
" ",
|
|
6118
7002
|
PHASE_CONFIG[streamingPhase].label,
|
|
6119
7003
|
" ",
|
|
6120
|
-
/* @__PURE__ */
|
|
7004
|
+
/* @__PURE__ */ jsx10(InkSpinner3, { type: "dots" })
|
|
6121
7005
|
] }) }) : rewindHintPhase === "visible" ? (
|
|
6122
7006
|
// 本轮修改了文件时,流式结束后 2s 在原位置展示 /rewind 提示
|
|
6123
7007
|
// 一直保留到下次对话开始,与 /rewind 1(最新检查点)配套
|
|
6124
|
-
/* @__PURE__ */
|
|
7008
|
+
/* @__PURE__ */ jsx10(Box10, { marginTop: 1, justifyContent: "center", children: /* @__PURE__ */ jsx10(Text11, { color: "#808080", children: "\u21A9 /rewind 1 \u53EF\u64A4\u56DE\u672C\u6B21\u4FEE\u6539" }) })
|
|
6125
7009
|
) : null,
|
|
6126
|
-
/* @__PURE__ */
|
|
6127
|
-
|
|
6128
|
-
|
|
6129
|
-
"
|
|
6130
|
-
|
|
6131
|
-
|
|
6132
|
-
|
|
6133
|
-
|
|
6134
|
-
|
|
6135
|
-
|
|
6136
|
-
|
|
6137
|
-
|
|
6138
|
-
|
|
6139
|
-
|
|
6140
|
-
|
|
6141
|
-
|
|
6142
|
-
|
|
6143
|
-
|
|
6144
|
-
|
|
7010
|
+
/* @__PURE__ */ jsx10(Box10, { marginTop: 1, children: hasConversationStarted || sessionMode === "plan" ? /* @__PURE__ */ jsxs10(
|
|
7011
|
+
Text11,
|
|
7012
|
+
{
|
|
7013
|
+
color: sessionMode === "plan" ? "#ff69b4" : "#00ffff",
|
|
7014
|
+
dimColor: sessionMode !== "plan",
|
|
7015
|
+
children: [
|
|
7016
|
+
/* @__PURE__ */ jsx10(Text11, { children: sessionMode === "plan" ? "\u2500".repeat(Math.max(dividerWidth - 48, 1)) : "\u2500".repeat(Math.max(dividerWidth - 35, 10)) }),
|
|
7017
|
+
balance !== null && /* @__PURE__ */ jsxs10(Text11, { color: "yellow", children: [
|
|
7018
|
+
" \u{1F4B0} \u4F59\u989D \xA5",
|
|
7019
|
+
balance.toFixed(2)
|
|
7020
|
+
] }),
|
|
7021
|
+
isStreaming ? /* @__PURE__ */ jsxs10(Text11, { color: "cyan", children: [
|
|
7022
|
+
" \u{1F4CA} \u672C\u6B21 \xA5",
|
|
7023
|
+
sessionCost > 0 ? sessionCost.toFixed(4) + " " : "",
|
|
7024
|
+
/* @__PURE__ */ jsx10(InkSpinner3, { type: "dots" })
|
|
7025
|
+
] }) : sessionCost > 0 ? /* @__PURE__ */ jsxs10(Text11, { color: "cyan", children: [
|
|
7026
|
+
" \u{1F4CA} \u672C\u6B21 \xA5",
|
|
7027
|
+
sessionCost.toFixed(4)
|
|
7028
|
+
] }) : null,
|
|
7029
|
+
sessionMode === "plan" && /* @__PURE__ */ jsx10(Text11, { color: "#ff69b4", bold: true, children: " \u{1F4CB} \u8BA1\u5212\u6A21\u5F0F" })
|
|
7030
|
+
]
|
|
7031
|
+
}
|
|
7032
|
+
) : /* @__PURE__ */ jsx10(Text11, { color: "#00ffff", dimColor: true, children: "\u2500".repeat(dividerWidth) }) }),
|
|
7033
|
+
/* @__PURE__ */ jsxs10(Box10, { children: [
|
|
7034
|
+
/* @__PURE__ */ jsx10(Box10, { width: 4, flexShrink: 0, children: /* @__PURE__ */ jsx10(Text11, { bold: true, color: "#00ff41", children: "\u26A1" }) }),
|
|
7035
|
+
/* @__PURE__ */ jsx10(Box10, { flexGrow: 1, children: !input && !isStreaming && idlePlaceholder && gradientColors.length > 0 ? /* @__PURE__ */ jsx10(Text11, { children: idlePlaceholder.split("").map((ch, i) => /* @__PURE__ */ jsx10(Text11, { color: gradientColors[i] ?? void 0, children: ch }, i)) }) : !input && isStreaming && streamingPlaceholder && streamingGradientColors.length > 0 ? /* @__PURE__ */ jsx10(Text11, { children: streamingPlaceholder.split("").map((ch, i) => /* @__PURE__ */ jsx10(Text11, { color: streamingGradientColors[i] ?? void 0, children: ch }, i)) }) : /* @__PURE__ */ jsx10(
|
|
6145
7036
|
TextInput,
|
|
6146
7037
|
{
|
|
6147
7038
|
value: input,
|
|
@@ -6152,19 +7043,19 @@ function ChatSession({
|
|
|
6152
7043
|
inputKey
|
|
6153
7044
|
) })
|
|
6154
7045
|
] }),
|
|
6155
|
-
/* @__PURE__ */
|
|
6156
|
-
/* @__PURE__ */
|
|
6157
|
-
/* @__PURE__ */
|
|
7046
|
+
/* @__PURE__ */ jsx10(Box10, { children: /* @__PURE__ */ jsx10(Text11, { color: "#00ffff", dimColor: true, children: "\u2500".repeat(dividerWidth) }) }),
|
|
7047
|
+
/* @__PURE__ */ jsx10(SkillSelector, { skills, input, selectedIndex: skillSelectIndex }),
|
|
7048
|
+
/* @__PURE__ */ jsx10(FileSelector, { files, input, selectedIndex: fileSelectIndex })
|
|
6158
7049
|
] }),
|
|
6159
|
-
doubleCtrlC && !isStreaming && /* @__PURE__ */
|
|
6160
|
-
isStreaming && /* @__PURE__ */
|
|
7050
|
+
doubleCtrlC && !isStreaming && /* @__PURE__ */ jsx10(Box10, { marginTop: 1, children: /* @__PURE__ */ jsx10(Text11, { color: "#ff1493", bold: true, children: " \u26A0 \u518D\u6309\u4E00\u6B21 Ctrl+C \u9000\u51FA dskcode" }) }),
|
|
7051
|
+
isStreaming && /* @__PURE__ */ jsx10(Box10, { marginTop: 1, children: /* @__PURE__ */ jsx10(Text11, { color: "yellow", dimColor: true, children: " \u63D0\u793A\uFF1A\u6309 Ctrl+C \u53D6\u6D88\u5F53\u524D\u8BF7\u6C42" }) })
|
|
6161
7052
|
] });
|
|
6162
7053
|
}
|
|
6163
7054
|
|
|
6164
7055
|
// src/ui/GamePicker.tsx
|
|
6165
|
-
import { Box as
|
|
7056
|
+
import { Box as Box11, Text as Text12, useInput as useInput2 } from "ink";
|
|
6166
7057
|
import { useState as useState5, useCallback as useCallback3 } from "react";
|
|
6167
|
-
import { jsx as
|
|
7058
|
+
import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
6168
7059
|
function GamePicker({ games, onSelect, onExit, onBackToChat }) {
|
|
6169
7060
|
const [selectedIndex, setSelectedIndex] = useState5(0);
|
|
6170
7061
|
const exitAction = onBackToChat ?? onExit ?? (() => process.exit(0));
|
|
@@ -6192,18 +7083,18 @@ function GamePicker({ games, onSelect, onExit, onBackToChat }) {
|
|
|
6192
7083
|
[games, selectedIndex, onSelect, onExit, onBackToChat, handleCtrlC]
|
|
6193
7084
|
)
|
|
6194
7085
|
);
|
|
6195
|
-
return /* @__PURE__ */
|
|
6196
|
-
/* @__PURE__ */
|
|
6197
|
-
/* @__PURE__ */
|
|
7086
|
+
return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", children: [
|
|
7087
|
+
/* @__PURE__ */ jsx11(Box11, { marginBottom: 1, children: /* @__PURE__ */ jsx11(Text12, { bold: true, color: "#00ffff", children: "\u{1F3AE} \u6E38\u620F\u5217\u8868" }) }),
|
|
7088
|
+
/* @__PURE__ */ jsx11(Box11, { flexDirection: "column", children: games.map((game, index) => {
|
|
6198
7089
|
const isSelected = index === selectedIndex;
|
|
6199
|
-
return /* @__PURE__ */
|
|
6200
|
-
/* @__PURE__ */
|
|
6201
|
-
/* @__PURE__ */
|
|
6202
|
-
/* @__PURE__ */
|
|
7090
|
+
return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "row", children: [
|
|
7091
|
+
/* @__PURE__ */ jsx11(Box11, { width: 3, flexShrink: 0, children: isSelected ? /* @__PURE__ */ jsx11(Text12, { bold: true, color: "#00ff41", children: "\u25B8 " }) : /* @__PURE__ */ jsx11(Text12, { children: " " }) }),
|
|
7092
|
+
/* @__PURE__ */ jsx11(Box11, { width: 20, flexShrink: 0, children: /* @__PURE__ */ jsx11(Text12, { bold: true, color: isSelected ? "#00ff41" : "#ffffff", children: game.name }) }),
|
|
7093
|
+
/* @__PURE__ */ jsx11(Box11, { children: /* @__PURE__ */ jsx11(Text12, { color: "#888888", children: game.description }) })
|
|
6203
7094
|
] }, game.id);
|
|
6204
7095
|
}) }),
|
|
6205
|
-
/* @__PURE__ */
|
|
6206
|
-
doubleCtrlC && /* @__PURE__ */
|
|
7096
|
+
/* @__PURE__ */ jsx11(Box11, { marginTop: 1, children: /* @__PURE__ */ jsx11(Text12, { dimColor: true, children: " \u2191/\u2193 \u9009\u62E9 Enter \u542F\u52A8 q \u8FD4\u56DE" }) }),
|
|
7097
|
+
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" }) })
|
|
6207
7098
|
] });
|
|
6208
7099
|
}
|
|
6209
7100
|
|
|
@@ -6220,9 +7111,9 @@ function listGames() {
|
|
|
6220
7111
|
}
|
|
6221
7112
|
|
|
6222
7113
|
// src/game/brick-breaker/index.tsx
|
|
6223
|
-
import { Box as
|
|
7114
|
+
import { Box as Box12, Text as Text13, useInput as useInput3, render as render2 } from "ink";
|
|
6224
7115
|
import { useState as useState6, useEffect as useEffect5, useRef as useRef4, useCallback as useCallback4 } from "react";
|
|
6225
|
-
import { jsx as
|
|
7116
|
+
import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
6226
7117
|
var GAME_WIDTH = 40;
|
|
6227
7118
|
var GAME_HEIGHT = 18;
|
|
6228
7119
|
var PADDLE_WIDTH = 9;
|
|
@@ -6412,49 +7303,49 @@ function BrickBreakerGame({ onExit: _onExit }) {
|
|
|
6412
7303
|
const board = buildBoard(s);
|
|
6413
7304
|
const def = getLevel(s.level);
|
|
6414
7305
|
void tick2;
|
|
6415
|
-
return /* @__PURE__ */
|
|
6416
|
-
/* @__PURE__ */
|
|
6417
|
-
/* @__PURE__ */
|
|
7306
|
+
return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", children: [
|
|
7307
|
+
/* @__PURE__ */ jsxs12(Box12, { flexDirection: "row", children: [
|
|
7308
|
+
/* @__PURE__ */ jsx12(Box12, { width: 20, children: /* @__PURE__ */ jsxs12(Text13, { children: [
|
|
6418
7309
|
"\u5173\u5361 ",
|
|
6419
7310
|
s.level,
|
|
6420
7311
|
": ",
|
|
6421
|
-
/* @__PURE__ */
|
|
7312
|
+
/* @__PURE__ */ jsx12(Text13, { color: "cyan", children: def.desc })
|
|
6422
7313
|
] }) }),
|
|
6423
|
-
/* @__PURE__ */
|
|
7314
|
+
/* @__PURE__ */ jsx12(Box12, { width: 12, children: /* @__PURE__ */ jsxs12(Text13, { children: [
|
|
6424
7315
|
"\u5206\u6570: ",
|
|
6425
|
-
/* @__PURE__ */
|
|
7316
|
+
/* @__PURE__ */ jsx12(Text13, { color: "yellow", children: String(s.score).padStart(3, "0") })
|
|
6426
7317
|
] }) }),
|
|
6427
|
-
/* @__PURE__ */
|
|
7318
|
+
/* @__PURE__ */ jsx12(Box12, { width: 12, children: /* @__PURE__ */ jsxs12(Text13, { children: [
|
|
6428
7319
|
"\u751F\u547D: ",
|
|
6429
|
-
/* @__PURE__ */
|
|
7320
|
+
/* @__PURE__ */ jsx12(Text13, { color: "red", children: "\u2665".repeat(Math.max(0, s.lives)) })
|
|
6430
7321
|
] }) }),
|
|
6431
|
-
/* @__PURE__ */
|
|
7322
|
+
/* @__PURE__ */ jsx12(Box12, { width: 10, children: /* @__PURE__ */ jsxs12(Text13, { children: [
|
|
6432
7323
|
"\u7816\u5757: ",
|
|
6433
|
-
/* @__PURE__ */
|
|
7324
|
+
/* @__PURE__ */ jsx12(Text13, { color: "cyan", children: aliveCount })
|
|
6434
7325
|
] }) }),
|
|
6435
|
-
/* @__PURE__ */
|
|
7326
|
+
/* @__PURE__ */ jsx12(Box12, { children: /* @__PURE__ */ jsxs12(Text13, { color: s.paused ? "gray" : "green", children: [
|
|
6436
7327
|
"[",
|
|
6437
7328
|
s.paused ? "\u6682\u505C" : "\u8FD0\u884C\u4E2D",
|
|
6438
7329
|
"]"
|
|
6439
7330
|
] }) })
|
|
6440
7331
|
] }),
|
|
6441
|
-
/* @__PURE__ */
|
|
6442
|
-
/* @__PURE__ */
|
|
7332
|
+
/* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", children: [
|
|
7333
|
+
/* @__PURE__ */ jsxs12(Text13, { children: [
|
|
6443
7334
|
"\u250C",
|
|
6444
7335
|
"\u2500".repeat(GAME_WIDTH),
|
|
6445
7336
|
"\u2510"
|
|
6446
7337
|
] }),
|
|
6447
|
-
/* @__PURE__ */
|
|
6448
|
-
/* @__PURE__ */
|
|
7338
|
+
/* @__PURE__ */ jsx12(Text13, { children: selectingLevel ? " \x1B[90m\u9009\u62E9\u5173\u5361\u540E\u5F00\u59CB...\x1B[0m" : board }),
|
|
7339
|
+
/* @__PURE__ */ jsxs12(Text13, { children: [
|
|
6449
7340
|
"\u2514",
|
|
6450
7341
|
"\u2500".repeat(GAME_WIDTH),
|
|
6451
7342
|
"\u2518"
|
|
6452
7343
|
] })
|
|
6453
7344
|
] }),
|
|
6454
|
-
selectingLevel && /* @__PURE__ */
|
|
6455
|
-
/* @__PURE__ */
|
|
6456
|
-
/* @__PURE__ */
|
|
6457
|
-
/* @__PURE__ */
|
|
7345
|
+
selectingLevel && /* @__PURE__ */ jsxs12(Box12, { marginTop: 1, flexDirection: "column", children: [
|
|
7346
|
+
/* @__PURE__ */ jsx12(Text13, { bold: true, color: "yellow", children: "\u9009\u62E9\u5173\u5361" }),
|
|
7347
|
+
/* @__PURE__ */ jsx12(Box12, { flexDirection: "row", flexWrap: "wrap", children: LEVELS.map((lv, i) => /* @__PURE__ */ jsx12(Box12, { width: 22, children: /* @__PURE__ */ jsxs12(Text13, { children: [
|
|
7348
|
+
/* @__PURE__ */ jsx12(Text13, { color: initialLevel === i + 1 ? "green" : "white", children: i + 1 === 10 ? "0" : String(i + 1) }),
|
|
6458
7349
|
". ",
|
|
6459
7350
|
lv.desc,
|
|
6460
7351
|
" (",
|
|
@@ -6463,16 +7354,16 @@ function BrickBreakerGame({ onExit: _onExit }) {
|
|
|
6463
7354
|
lv.cols,
|
|
6464
7355
|
")"
|
|
6465
7356
|
] }) }, i)) }),
|
|
6466
|
-
/* @__PURE__ */
|
|
7357
|
+
/* @__PURE__ */ jsx12(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx12(Text13, { dimColor: true, children: "\u6309\u6570\u5B57\u9009\u5173 q \u9000\u51FA" }) })
|
|
6467
7358
|
] }),
|
|
6468
|
-
!selectingLevel && (s.gameOver || s.win) && /* @__PURE__ */
|
|
6469
|
-
/* @__PURE__ */
|
|
6470
|
-
/* @__PURE__ */
|
|
7359
|
+
!selectingLevel && (s.gameOver || s.win) && /* @__PURE__ */ jsxs12(Box12, { marginTop: 1, children: [
|
|
7360
|
+
/* @__PURE__ */ jsx12(Text13, { bold: true, color: s.gameOver ? "red" : "green", children: s.gameOver ? "\u6E38\u620F\u7ED3\u675F\uFF01" : "\u606D\u559C\u901A\u5173\uFF01" }),
|
|
7361
|
+
/* @__PURE__ */ jsxs12(Text13, { children: [
|
|
6471
7362
|
" \u5206\u6570: ",
|
|
6472
|
-
/* @__PURE__ */
|
|
7363
|
+
/* @__PURE__ */ jsx12(Text13, { color: "yellow", children: s.score })
|
|
6473
7364
|
] })
|
|
6474
7365
|
] }),
|
|
6475
|
-
!selectingLevel && /* @__PURE__ */
|
|
7366
|
+
!selectingLevel && /* @__PURE__ */ jsx12(Box12, { marginTop: 1, children: s.gameOver || s.win ? /* @__PURE__ */ jsx12(Text13, { dimColor: true, children: "\u2190 \u2192 \u79FB\u52A8 r \u91CD\u5F00 l \u9009\u5173 q \u9000\u51FA" }) : /* @__PURE__ */ jsx12(Text13, { dimColor: true, children: "\u2190 \u2192 \u79FB\u52A8 p \u6682\u505C q \u9000\u51FA" }) })
|
|
6476
7367
|
] });
|
|
6477
7368
|
}
|
|
6478
7369
|
var brick_breaker_default = {
|
|
@@ -6482,7 +7373,7 @@ var brick_breaker_default = {
|
|
|
6482
7373
|
play: async () => {
|
|
6483
7374
|
await new Promise((resolve2) => {
|
|
6484
7375
|
const { unmount } = render2(
|
|
6485
|
-
/* @__PURE__ */
|
|
7376
|
+
/* @__PURE__ */ jsx12(BrickBreakerGame, { onExit: () => {
|
|
6486
7377
|
unmount();
|
|
6487
7378
|
resolve2();
|
|
6488
7379
|
} })
|
|
@@ -6492,9 +7383,9 @@ var brick_breaker_default = {
|
|
|
6492
7383
|
};
|
|
6493
7384
|
|
|
6494
7385
|
// src/game/coder-check/index.tsx
|
|
6495
|
-
import { Box as
|
|
7386
|
+
import { Box as Box13, Text as Text14, useInput as useInput4, render as render3 } from "ink";
|
|
6496
7387
|
import { useState as useState7, useEffect as useEffect6, useRef as useRef5, useCallback as useCallback5 } from "react";
|
|
6497
|
-
import { jsx as
|
|
7388
|
+
import { jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
6498
7389
|
var GAME_W = 66;
|
|
6499
7390
|
var GAME_H = 20;
|
|
6500
7391
|
var SCORE_H = 6;
|
|
@@ -6965,44 +7856,44 @@ function CoderCheck({ onExit: _onExit }) {
|
|
|
6965
7856
|
const scoreLines = buildScoreLines(scoreStr);
|
|
6966
7857
|
const view = buildGameView(s, scoreLines, scoreColor, s.message);
|
|
6967
7858
|
void tick2;
|
|
6968
|
-
return /* @__PURE__ */
|
|
6969
|
-
/* @__PURE__ */
|
|
7859
|
+
return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", paddingX: 1, children: [
|
|
7860
|
+
/* @__PURE__ */ jsx13(Box13, { flexDirection: "row", children: /* @__PURE__ */ jsxs13(Text14, { children: [
|
|
6970
7861
|
"\u751F\u547D ",
|
|
6971
|
-
/* @__PURE__ */
|
|
7862
|
+
/* @__PURE__ */ jsx13(Text14, { color: "red", children: "\u2665".repeat(Math.max(0, s.lives)) }),
|
|
6972
7863
|
" ",
|
|
6973
7864
|
"\u901F\u5EA6 ",
|
|
6974
|
-
/* @__PURE__ */
|
|
7865
|
+
/* @__PURE__ */ jsxs13(Text14, { color: "cyan", children: [
|
|
6975
7866
|
"Lv.",
|
|
6976
7867
|
Math.floor(s.speed * 10)
|
|
6977
7868
|
] })
|
|
6978
7869
|
] }) }),
|
|
6979
|
-
!s.gameOver && s.target && /* @__PURE__ */
|
|
7870
|
+
!s.gameOver && s.target && /* @__PURE__ */ jsx13(Box13, { marginTop: 1, children: /* @__PURE__ */ jsxs13(Text14, { children: [
|
|
6980
7871
|
"\u6253\u5B57: ",
|
|
6981
|
-
/* @__PURE__ */
|
|
6982
|
-
/* @__PURE__ */
|
|
7872
|
+
/* @__PURE__ */ jsx13(Text14, { color: "green", children: s.typed }),
|
|
7873
|
+
/* @__PURE__ */ jsx13(Text14, { color: "white", children: s.target.slice(s.typed.length) })
|
|
6983
7874
|
] }) }),
|
|
6984
|
-
/* @__PURE__ */
|
|
6985
|
-
/* @__PURE__ */
|
|
7875
|
+
/* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", marginTop: 1, children: [
|
|
7876
|
+
/* @__PURE__ */ jsxs13(Text14, { children: [
|
|
6986
7877
|
"\u250C",
|
|
6987
7878
|
"\u2500".repeat(GAME_W),
|
|
6988
7879
|
"\u2510"
|
|
6989
7880
|
] }),
|
|
6990
|
-
view.map((row, i) => /* @__PURE__ */
|
|
6991
|
-
/* @__PURE__ */
|
|
7881
|
+
view.map((row, i) => /* @__PURE__ */ jsx13(Text14, { children: `\u2502${row}\u2502` }, i)),
|
|
7882
|
+
/* @__PURE__ */ jsxs13(Text14, { children: [
|
|
6992
7883
|
"\u2514",
|
|
6993
7884
|
"\u2500".repeat(GAME_W),
|
|
6994
7885
|
"\u2518"
|
|
6995
7886
|
] })
|
|
6996
7887
|
] }),
|
|
6997
|
-
s.gameOver && /* @__PURE__ */
|
|
6998
|
-
/* @__PURE__ */
|
|
6999
|
-
/* @__PURE__ */
|
|
7888
|
+
s.gameOver && /* @__PURE__ */ jsxs13(Box13, { marginTop: 1, children: [
|
|
7889
|
+
/* @__PURE__ */ jsx13(Text14, { bold: true, color: "red", children: "\u6E38\u620F\u7ED3\u675F\uFF01" }),
|
|
7890
|
+
/* @__PURE__ */ jsxs13(Text14, { children: [
|
|
7000
7891
|
" \u5F97\u5206: ",
|
|
7001
|
-
/* @__PURE__ */
|
|
7892
|
+
/* @__PURE__ */ jsx13(Text14, { color: "yellow", children: s.score }),
|
|
7002
7893
|
" r \u91CD\u5F00 q \u9000\u51FA"
|
|
7003
7894
|
] })
|
|
7004
7895
|
] }),
|
|
7005
|
-
/* @__PURE__ */
|
|
7896
|
+
/* @__PURE__ */ jsx13(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx13(Text14, { dimColor: true, children: "\u6253\u5B57\u6D88\u9664\u5355\u8BCD \u7A7A\u683C/Ctrl+P\u6682\u505C Ctrl+Q\u9000\u51FA" }) })
|
|
7006
7897
|
] });
|
|
7007
7898
|
}
|
|
7008
7899
|
var coder_check_default = {
|
|
@@ -7012,7 +7903,7 @@ var coder_check_default = {
|
|
|
7012
7903
|
play: async () => {
|
|
7013
7904
|
await new Promise((resolve2) => {
|
|
7014
7905
|
const { unmount } = render3(
|
|
7015
|
-
/* @__PURE__ */
|
|
7906
|
+
/* @__PURE__ */ jsx13(CoderCheck, { onExit: () => {
|
|
7016
7907
|
unmount();
|
|
7017
7908
|
resolve2();
|
|
7018
7909
|
} })
|
|
@@ -7392,12 +8283,12 @@ import { render as render4 } from "ink";
|
|
|
7392
8283
|
import chalk5 from "chalk";
|
|
7393
8284
|
|
|
7394
8285
|
// src/stock/StockList.tsx
|
|
7395
|
-
import { Box as
|
|
8286
|
+
import { Box as Box14, Text as Text15, useInput as useInput5 } from "ink";
|
|
7396
8287
|
import { useState as useState8, useCallback as useCallback6, useEffect as useEffect7, useMemo as useMemo2 } from "react";
|
|
7397
8288
|
import asciichart from "asciichart";
|
|
7398
8289
|
import os from "os";
|
|
7399
8290
|
import { join as join10 } from "path";
|
|
7400
|
-
import { jsx as
|
|
8291
|
+
import { jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
7401
8292
|
var SETTINGS_PATH = join10(os.homedir(), ".dskcode", "settings.json");
|
|
7402
8293
|
function toFileUrl(p) {
|
|
7403
8294
|
const norm = p.replace(/\\/g, "/");
|
|
@@ -7616,64 +8507,64 @@ function StockList({ codes, onExit, onBackToChat }) {
|
|
|
7616
8507
|
);
|
|
7617
8508
|
if (detailView) {
|
|
7618
8509
|
if (detailLoading) {
|
|
7619
|
-
return /* @__PURE__ */
|
|
8510
|
+
return /* @__PURE__ */ jsx14(Box14, { paddingLeft: 1, children: /* @__PURE__ */ jsx14(Text15, { dimColor: true, children: " \u27F3 \u52A0\u8F7D\u5206\u65F6\u6570\u636E..." }) });
|
|
7620
8511
|
}
|
|
7621
8512
|
return renderDetail(detailView, () => setDetailView(null), detailPrices ?? void 0, detailCountdown, currentTime);
|
|
7622
8513
|
}
|
|
7623
8514
|
const cp2 = (c) => dimMode ? { dimColor: true } : { color: c };
|
|
7624
|
-
return /* @__PURE__ */
|
|
7625
|
-
/* @__PURE__ */
|
|
7626
|
-
/* @__PURE__ */
|
|
7627
|
-
/* @__PURE__ */
|
|
8515
|
+
return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", children: [
|
|
8516
|
+
/* @__PURE__ */ jsxs14(Box14, { marginBottom: 1, justifyContent: "space-between", children: [
|
|
8517
|
+
/* @__PURE__ */ jsx14(Text15, { bold: true, ...cp2("#00ffff"), children: " \u{1F4C8} \u81EA\u9009\u80A1\u76D1\u63A7" }),
|
|
8518
|
+
/* @__PURE__ */ jsxs14(Text15, { dimColor: true, children: [
|
|
7628
8519
|
" \u{1F550} ",
|
|
7629
8520
|
currentTime
|
|
7630
8521
|
] }),
|
|
7631
|
-
/* @__PURE__ */
|
|
8522
|
+
/* @__PURE__ */ jsx14(Text15, { dimColor: true, children: loading ? " \u27F3 \u5237\u65B0\u4E2D..." : ` ${countdown}s \u540E\u81EA\u52A8\u5237\u65B0` })
|
|
7632
8523
|
] }),
|
|
7633
|
-
/* @__PURE__ */
|
|
7634
|
-
/* @__PURE__ */
|
|
7635
|
-
/* @__PURE__ */
|
|
7636
|
-
/* @__PURE__ */
|
|
7637
|
-
/* @__PURE__ */
|
|
7638
|
-
/* @__PURE__ */
|
|
8524
|
+
/* @__PURE__ */ jsxs14(Box14, { children: [
|
|
8525
|
+
/* @__PURE__ */ jsx14(Box14, { width: 3 }),
|
|
8526
|
+
/* @__PURE__ */ jsx14(Box14, { width: 9, children: /* @__PURE__ */ jsx14(Text15, { dimColor: true, children: "\u4EE3\u7801" }) }),
|
|
8527
|
+
/* @__PURE__ */ jsx14(Box14, { width: 16, children: /* @__PURE__ */ jsx14(Text15, { dimColor: true, children: "\u540D\u79F0" }) }),
|
|
8528
|
+
/* @__PURE__ */ jsx14(Box14, { width: 12, children: /* @__PURE__ */ jsx14(Text15, { dimColor: true, children: "\u6700\u65B0\u4EF7" }) }),
|
|
8529
|
+
/* @__PURE__ */ jsx14(Box14, { width: 12, children: /* @__PURE__ */ jsxs14(Text15, { dimColor: true, children: [
|
|
7639
8530
|
"\u6DA8\u8DCC\u5E45",
|
|
7640
8531
|
sortOrder === "desc" ? " \u25BC" : sortOrder === "asc" ? " \u25B2" : ""
|
|
7641
8532
|
] }) }),
|
|
7642
|
-
/* @__PURE__ */
|
|
7643
|
-
/* @__PURE__ */
|
|
7644
|
-
/* @__PURE__ */
|
|
7645
|
-
/* @__PURE__ */
|
|
8533
|
+
/* @__PURE__ */ jsx14(Box14, { width: 12, children: /* @__PURE__ */ jsx14(Text15, { dimColor: true, children: "\u6DA8\u8DCC\u989D" }) }),
|
|
8534
|
+
/* @__PURE__ */ jsx14(Box14, { width: 12, children: /* @__PURE__ */ jsx14(Text15, { dimColor: true, children: "\u6700\u9AD8" }) }),
|
|
8535
|
+
/* @__PURE__ */ jsx14(Box14, { width: 12, children: /* @__PURE__ */ jsx14(Text15, { dimColor: true, children: "\u6700\u4F4E" }) }),
|
|
8536
|
+
/* @__PURE__ */ jsx14(Box14, { children: /* @__PURE__ */ jsx14(Text15, { dimColor: true, children: "\u6210\u4EA4\u989D" }) })
|
|
7646
8537
|
] }),
|
|
7647
|
-
/* @__PURE__ */
|
|
7648
|
-
/* @__PURE__ */
|
|
8538
|
+
/* @__PURE__ */ jsx14(Box14, { children: /* @__PURE__ */ jsx14(Text15, { dimColor: true, children: " " + "\u2500".repeat(100) }) }),
|
|
8539
|
+
/* @__PURE__ */ jsx14(Box14, { flexDirection: "column", children: sortedStocks.map((stock, index) => {
|
|
7649
8540
|
const isSelected = index === selectedIndex;
|
|
7650
8541
|
const isUp = stock.changePercent >= 0;
|
|
7651
8542
|
const color = isUp ? "#ff1493" : "#00ff41";
|
|
7652
|
-
return /* @__PURE__ */
|
|
7653
|
-
/* @__PURE__ */
|
|
7654
|
-
/* @__PURE__ */
|
|
7655
|
-
/* @__PURE__ */
|
|
7656
|
-
/* @__PURE__ */
|
|
7657
|
-
/* @__PURE__ */
|
|
8543
|
+
return /* @__PURE__ */ jsxs14(Box14, { children: [
|
|
8544
|
+
/* @__PURE__ */ jsx14(Box14, { width: 3, flexShrink: 0, children: isSelected ? /* @__PURE__ */ jsx14(Text15, { bold: true, ...cp2("#00ffff"), children: "\u25B8 " }) : /* @__PURE__ */ jsx14(Text15, { children: " " }) }),
|
|
8545
|
+
/* @__PURE__ */ jsx14(Box14, { width: 9, children: /* @__PURE__ */ jsx14(Text15, { bold: true, ...cp2(isSelected ? "#00ffff" : "#ffffff"), children: stock.code }) }),
|
|
8546
|
+
/* @__PURE__ */ jsx14(Box14, { width: 16, children: /* @__PURE__ */ jsx14(Text15, { ...cp2(isSelected ? "#ffffff" : "#cccccc"), children: stock.name }) }),
|
|
8547
|
+
/* @__PURE__ */ jsx14(Box14, { width: 12, children: /* @__PURE__ */ jsx14(Text15, { bold: true, ...cp2(color), children: formatPrice(stock.price) }) }),
|
|
8548
|
+
/* @__PURE__ */ jsx14(Box14, { width: 12, children: /* @__PURE__ */ jsxs14(Text15, { ...cp2(color), children: [
|
|
7658
8549
|
isUp ? "+" : "",
|
|
7659
8550
|
stock.changePercent.toFixed(2),
|
|
7660
8551
|
"%"
|
|
7661
8552
|
] }) }),
|
|
7662
|
-
/* @__PURE__ */
|
|
8553
|
+
/* @__PURE__ */ jsx14(Box14, { width: 12, children: /* @__PURE__ */ jsxs14(Text15, { ...cp2(color), children: [
|
|
7663
8554
|
isUp ? "+" : "",
|
|
7664
8555
|
stock.changeAmount.toFixed(3)
|
|
7665
8556
|
] }) }),
|
|
7666
|
-
/* @__PURE__ */
|
|
7667
|
-
/* @__PURE__ */
|
|
7668
|
-
/* @__PURE__ */
|
|
8557
|
+
/* @__PURE__ */ jsx14(Box14, { width: 12, children: /* @__PURE__ */ jsx14(Text15, { ...cp2("#cccccc"), children: formatPrice(stock.high) }) }),
|
|
8558
|
+
/* @__PURE__ */ jsx14(Box14, { width: 12, children: /* @__PURE__ */ jsx14(Text15, { ...cp2("#888888"), children: formatPrice(stock.low) }) }),
|
|
8559
|
+
/* @__PURE__ */ jsx14(Box14, { children: /* @__PURE__ */ jsx14(Text15, { ...cp2("#888888"), children: formatAmount(stock.amount) }) })
|
|
7669
8560
|
] }, stock.code);
|
|
7670
8561
|
}) }),
|
|
7671
|
-
/* @__PURE__ */
|
|
7672
|
-
/* @__PURE__ */
|
|
7673
|
-
/* @__PURE__ */
|
|
7674
|
-
/* @__PURE__ */
|
|
8562
|
+
/* @__PURE__ */ jsx14(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx14(Text15, { dimColor: true, children: ` \u2191/\u2193 \u9009\u62E9 Enter \u8BE6\u60C5 r \u624B\u52A8\u5237\u65B0 o \u6392\u5E8F h \u7F6E\u7070/\u6062\u590D q \u8FD4\u56DE` }) }),
|
|
8563
|
+
/* @__PURE__ */ jsxs14(Box14, { children: [
|
|
8564
|
+
/* @__PURE__ */ jsx14(Text15, { dimColor: true, children: ` \u6700\u540E\u66F4\u65B0: ${lastUpdate} \u7F16\u8F91\u81EA\u9009\u80A1: ` }),
|
|
8565
|
+
/* @__PURE__ */ jsx14(Text15, { ...cp2("#c792ea"), children: osc8Link(toFileUrl(SETTINGS_PATH), SETTINGS_PATH) })
|
|
7675
8566
|
] }),
|
|
7676
|
-
doubleCtrlC && /* @__PURE__ */
|
|
8567
|
+
doubleCtrlC && /* @__PURE__ */ jsx14(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx14(Text15, { bold: true, ...cp2("#ff1493"), children: " \u26A0 \u518D\u6309\u4E00\u6B21 Ctrl+C \u9000\u51FA dskcode" }) })
|
|
7677
8568
|
] });
|
|
7678
8569
|
}
|
|
7679
8570
|
function renderDetail(stock, _onBack, prices, countdown = 10, currentTime) {
|
|
@@ -7691,33 +8582,33 @@ function renderDetail(stock, _onBack, prices, countdown = 10, currentTime) {
|
|
|
7691
8582
|
raw = raw.replaceAll("\u256D", "\u250C").replaceAll("\u256E", "\u2510").replaceAll("\u2570", "\u2514").replaceAll("\u256F", "\u2518");
|
|
7692
8583
|
chartLines = raw.split("\n");
|
|
7693
8584
|
}
|
|
7694
|
-
return /* @__PURE__ */
|
|
7695
|
-
/* @__PURE__ */
|
|
7696
|
-
/* @__PURE__ */
|
|
7697
|
-
/* @__PURE__ */
|
|
8585
|
+
return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", paddingLeft: 1, children: [
|
|
8586
|
+
/* @__PURE__ */ jsxs14(Box14, { marginBottom: 1, justifyContent: "space-between", children: [
|
|
8587
|
+
/* @__PURE__ */ jsxs14(Box14, { children: [
|
|
8588
|
+
/* @__PURE__ */ jsxs14(Text15, { bold: true, color: "#00ffff", children: [
|
|
7698
8589
|
" \u{1F4CA} ",
|
|
7699
8590
|
stock.name,
|
|
7700
8591
|
" "
|
|
7701
8592
|
] }),
|
|
7702
|
-
/* @__PURE__ */
|
|
7703
|
-
currentTime && /* @__PURE__ */
|
|
8593
|
+
/* @__PURE__ */ jsx14(Text15, { dimColor: true, children: stock.code }),
|
|
8594
|
+
currentTime && /* @__PURE__ */ jsxs14(Text15, { dimColor: true, children: [
|
|
7704
8595
|
" \u{1F550} ",
|
|
7705
8596
|
currentTime
|
|
7706
8597
|
] })
|
|
7707
8598
|
] }),
|
|
7708
|
-
/* @__PURE__ */
|
|
8599
|
+
/* @__PURE__ */ jsx14(Text15, { dimColor: true, children: `${countdown}s \u540E\u5237\u65B0` })
|
|
7709
8600
|
] }),
|
|
7710
|
-
/* @__PURE__ */
|
|
7711
|
-
/* @__PURE__ */
|
|
7712
|
-
/* @__PURE__ */
|
|
8601
|
+
/* @__PURE__ */ jsxs14(Box14, { children: [
|
|
8602
|
+
/* @__PURE__ */ jsx14(Box14, { width: 16, children: /* @__PURE__ */ jsx14(Text15, { bold: true, color: "#888888", children: "\u5F53\u524D\u4EF7" }) }),
|
|
8603
|
+
/* @__PURE__ */ jsx14(Box14, { children: /* @__PURE__ */ jsxs14(Text15, { bold: true, color: colorCode, children: [
|
|
7713
8604
|
arrow,
|
|
7714
8605
|
" ",
|
|
7715
8606
|
formatPrice(stock.price)
|
|
7716
8607
|
] }) })
|
|
7717
8608
|
] }),
|
|
7718
|
-
/* @__PURE__ */
|
|
7719
|
-
/* @__PURE__ */
|
|
7720
|
-
/* @__PURE__ */
|
|
8609
|
+
/* @__PURE__ */ jsxs14(Box14, { children: [
|
|
8610
|
+
/* @__PURE__ */ jsx14(Box14, { width: 16, children: /* @__PURE__ */ jsx14(Text15, { color: "#888888", children: "\u6DA8\u8DCC\u5E45" }) }),
|
|
8611
|
+
/* @__PURE__ */ jsx14(Box14, { children: /* @__PURE__ */ jsxs14(Text15, { color: colorCode, children: [
|
|
7721
8612
|
isUp ? "+" : "",
|
|
7722
8613
|
stock.changePercent.toFixed(2),
|
|
7723
8614
|
"%",
|
|
@@ -7726,8 +8617,8 @@ function renderDetail(stock, _onBack, prices, countdown = 10, currentTime) {
|
|
|
7726
8617
|
stock.changeAmount.toFixed(3)
|
|
7727
8618
|
] }) })
|
|
7728
8619
|
] }),
|
|
7729
|
-
chartLines.length > 0 && /* @__PURE__ */
|
|
7730
|
-
/* @__PURE__ */
|
|
8620
|
+
chartLines.length > 0 && /* @__PURE__ */ jsx14(Box14, { marginTop: 1, flexDirection: "column", children: chartLines.map((line, i) => /* @__PURE__ */ jsx14(Box14, { children: /* @__PURE__ */ jsx14(Text15, { color: colorCode, children: line || " " }) }, i)) }),
|
|
8621
|
+
/* @__PURE__ */ jsx14(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx14(Text15, { dimColor: true, children: " Space/q \u8FD4\u56DE\u5217\u8868" }) })
|
|
7731
8622
|
] });
|
|
7732
8623
|
}
|
|
7733
8624
|
|
|
@@ -7812,7 +8703,7 @@ async function scanProjectFiles(baseDir, dir) {
|
|
|
7812
8703
|
}
|
|
7813
8704
|
|
|
7814
8705
|
// src/cli/index.tsx
|
|
7815
|
-
import { jsx as
|
|
8706
|
+
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
7816
8707
|
var SUBCOMMANDS = ["chat", "run", "setup", "init", "completion", "game", "stock"];
|
|
7817
8708
|
function createCli() {
|
|
7818
8709
|
const program2 = new Command();
|
|
@@ -7914,7 +8805,7 @@ compdef _dskcode_completion dskcode`);
|
|
|
7914
8805
|
const freshResult = await loadAndValidate();
|
|
7915
8806
|
const codeList = codes && codes.length > 0 ? codes : freshResult.config.stock?.symbols?.map((s) => s.code) ?? ["sh000001", "sz399006", "sh601688"];
|
|
7916
8807
|
const app = renderApp(
|
|
7917
|
-
/* @__PURE__ */
|
|
8808
|
+
/* @__PURE__ */ jsx15(
|
|
7918
8809
|
StockList,
|
|
7919
8810
|
{
|
|
7920
8811
|
codes: codeList,
|
|
@@ -7943,7 +8834,7 @@ compdef _dskcode_completion dskcode`);
|
|
|
7943
8834
|
}
|
|
7944
8835
|
const selectedGame = await new Promise((resolve2) => {
|
|
7945
8836
|
const { unmount } = render4(
|
|
7946
|
-
/* @__PURE__ */
|
|
8837
|
+
/* @__PURE__ */ jsx15(
|
|
7947
8838
|
GamePicker,
|
|
7948
8839
|
{
|
|
7949
8840
|
games,
|
|
@@ -7983,7 +8874,7 @@ async function startChat(ctx, costTracker) {
|
|
|
7983
8874
|
);
|
|
7984
8875
|
const model = defaultProvider?.model ?? "deepseek-v4-flash";
|
|
7985
8876
|
const chatApp = renderApp(
|
|
7986
|
-
/* @__PURE__ */
|
|
8877
|
+
/* @__PURE__ */ jsx15(
|
|
7987
8878
|
ChatSession,
|
|
7988
8879
|
{
|
|
7989
8880
|
skillCount,
|
|
@@ -8001,7 +8892,7 @@ async function startChat(ctx, costTracker) {
|
|
|
8001
8892
|
initGames();
|
|
8002
8893
|
const games = listGames();
|
|
8003
8894
|
const { unmount } = render4(
|
|
8004
|
-
/* @__PURE__ */
|
|
8895
|
+
/* @__PURE__ */ jsx15(
|
|
8005
8896
|
GamePicker,
|
|
8006
8897
|
{
|
|
8007
8898
|
games,
|
|
@@ -8025,7 +8916,7 @@ async function startChat(ctx, costTracker) {
|
|
|
8025
8916
|
setImmediate(() => {
|
|
8026
8917
|
const defaultStockCodes = ctx?.config.stock?.symbols?.map((s) => s.code) ?? ["sh000001", "sz399006", "sh601688"];
|
|
8027
8918
|
const stockApp = renderApp(
|
|
8028
|
-
/* @__PURE__ */
|
|
8919
|
+
/* @__PURE__ */ jsx15(
|
|
8029
8920
|
StockList,
|
|
8030
8921
|
{
|
|
8031
8922
|
codes: defaultStockCodes,
|