@cydm/pie 2.6.4 → 2.6.6
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/builtin/extensions/ask-user/index.js +3 -3
- package/dist/builtin/extensions/mcp-adapter/index.js +148 -3
- package/dist/builtin/extensions/plan-mode/index.js +3 -3
- package/dist/builtin/extensions/subagent/index.js +4 -4
- package/dist/builtin/extensions/todo/index.js +3 -3
- package/dist/builtin/skills/chrome-devtools-axi/chrome-devtools-axi-bridge.js +3 -2
- package/dist/builtin/skills/chrome-devtools-axi/chrome-devtools-axi-runtime.js +1 -1
- package/dist/builtin/skills/chrome-devtools-axi/{chunk-UPATXALW.js → chunk-U75F4DPF.js} +60 -0
- package/dist/builtin/skills/chrome-devtools-axi/{cli-GB37NZHQ.js → cli-QAILYGLM.js} +97 -36
- package/dist/builtin/skills/skill-creator/SKILL.md +7 -8
- package/dist/chunks/{chunk-OCEYHWVX.js → chunk-G5B6D35K.js} +404 -8
- package/dist/chunks/{chunk-3AOMWS2Z.js → chunk-H6BAM2N4.js} +802 -186
- package/dist/chunks/{chunk-YEUBQBOB.js → chunk-KEARZX6F.js} +2 -2
- package/dist/chunks/{chunk-6QEDYZUR.js → chunk-OWSXALCG.js} +1 -1
- package/dist/chunks/{src-XT5S6AUQ.js → src-ZJXBS2DB.js} +2 -2
- package/dist/chunks/{test-stream-FNWDHRTM.js → test-stream-TI2S25NY.js} +1 -1
- package/dist/cli.js +454 -180
- package/package.json +2 -2
|
@@ -722,6 +722,9 @@ var NodeFileSystem = class {
|
|
|
722
722
|
}
|
|
723
723
|
}
|
|
724
724
|
async readTextRange(path, options, signal) {
|
|
725
|
+
if (options?.tailLines !== void 0) {
|
|
726
|
+
return this.readTextRangeTail(path, options, signal);
|
|
727
|
+
}
|
|
725
728
|
const fs = getNodeFs();
|
|
726
729
|
const range = normalizeRangeOptions(options);
|
|
727
730
|
const stat = await fs.promises.stat(path);
|
|
@@ -747,6 +750,7 @@ var NodeFileSystem = class {
|
|
|
747
750
|
const selectedBinaryDetector = new StreamingBinaryDetector();
|
|
748
751
|
const textDecoder = new TextDecoder("utf-8", { ignoreBOM: true });
|
|
749
752
|
let rawLineIndex = 0;
|
|
753
|
+
let lastCharWasNewline = false;
|
|
750
754
|
const selectedEndLine = Number.isFinite(range.limitLines) ? range.offsetLine + range.limitLines : Number.POSITIVE_INFINITY;
|
|
751
755
|
const startLine = () => {
|
|
752
756
|
if (lineStarted) return;
|
|
@@ -843,6 +847,7 @@ var NodeFileSystem = class {
|
|
|
843
847
|
for (const char of text) {
|
|
844
848
|
if (char === "\n") finishLine();
|
|
845
849
|
else scanLineChar(char);
|
|
850
|
+
lastCharWasNewline = char === "\n";
|
|
846
851
|
}
|
|
847
852
|
};
|
|
848
853
|
const stream = fs.createReadStream(path);
|
|
@@ -877,6 +882,181 @@ var NodeFileSystem = class {
|
|
|
877
882
|
firstLineExceedsLimit,
|
|
878
883
|
selectedBytesLookBinary: selectedBinaryDetector.finish(),
|
|
879
884
|
fileBytesLookBinary: fileBinaryDetector.finish(),
|
|
885
|
+
endsWithNewline: lastCharWasNewline,
|
|
886
|
+
mtimeMs: stat.mtime.getTime(),
|
|
887
|
+
size: stat.size
|
|
888
|
+
};
|
|
889
|
+
}
|
|
890
|
+
/**
|
|
891
|
+
* Tail read: select the last N lines in ONE forward scan. The full-file
|
|
892
|
+
* hash and totalLines (which the observation ledger requires of every
|
|
893
|
+
* read) force a complete scan anyway, so the tail window is extracted with
|
|
894
|
+
* a bounded ring buffer during that same scan — no probing passes, no
|
|
895
|
+
* second/third read. Ring bounds: at most `effectiveN` line entries and
|
|
896
|
+
* 2×maxOutputBytes of text; a single line longer than maxOutputBytes keeps
|
|
897
|
+
* only its byte length (it can never be output). When the ring evicts
|
|
898
|
+
* older lines (window bytes over budget), the result degrades honestly:
|
|
899
|
+
* truncated=true, and the reported window covers exactly what was kept.
|
|
900
|
+
*/
|
|
901
|
+
async readTextRangeTail(path, options, signal) {
|
|
902
|
+
const fs = getNodeFs();
|
|
903
|
+
const stat = await fs.promises.stat(path);
|
|
904
|
+
const maxOutputLines = Number.isFinite(options.maxOutputLines) ? Math.max(0, Math.floor(options.maxOutputLines)) : Number.POSITIVE_INFINITY;
|
|
905
|
+
const maxOutputBytes = Number.isFinite(options.maxOutputBytes) ? Math.max(0, Math.floor(options.maxOutputBytes)) : Number.POSITIVE_INFINITY;
|
|
906
|
+
const requested = Math.max(1, Math.floor(options.tailLines));
|
|
907
|
+
const effectiveN = Math.max(1, Math.min(requested, maxOutputLines));
|
|
908
|
+
const fullHasher = createTextHasher();
|
|
909
|
+
const fileBinaryDetector = new StreamingBinaryDetector();
|
|
910
|
+
const textDecoder = new TextDecoder("utf-8", { ignoreBOM: true });
|
|
911
|
+
const entries = [];
|
|
912
|
+
let entryBytes = 0;
|
|
913
|
+
let totalLines = 0;
|
|
914
|
+
let lastCharWasNewline = false;
|
|
915
|
+
let currentLine = "";
|
|
916
|
+
let currentLineBytes = 0;
|
|
917
|
+
let keepLineText = true;
|
|
918
|
+
const ringByteBudget = Number.isFinite(maxOutputBytes) ? 2 * maxOutputBytes : Number.POSITIVE_INFINITY;
|
|
919
|
+
const trimRing = () => {
|
|
920
|
+
while (entries.length > effectiveN || entries.length > 1 && entryBytes > ringByteBudget) {
|
|
921
|
+
const evicted = entries.shift();
|
|
922
|
+
entryBytes -= evicted.bytes;
|
|
923
|
+
}
|
|
924
|
+
};
|
|
925
|
+
const scanText = (text) => {
|
|
926
|
+
if (!text) return;
|
|
927
|
+
fullHasher.update(text);
|
|
928
|
+
for (const char of text) {
|
|
929
|
+
if (char === "\n") {
|
|
930
|
+
entries.push({ text: keepLineText ? currentLine : null, bytes: currentLineBytes });
|
|
931
|
+
entryBytes += currentLineBytes;
|
|
932
|
+
totalLines++;
|
|
933
|
+
currentLine = "";
|
|
934
|
+
currentLineBytes = 0;
|
|
935
|
+
keepLineText = true;
|
|
936
|
+
trimRing();
|
|
937
|
+
} else {
|
|
938
|
+
const charBytes = byteLength(char);
|
|
939
|
+
currentLineBytes += charBytes;
|
|
940
|
+
if (currentLineBytes > maxOutputBytes) {
|
|
941
|
+
keepLineText = false;
|
|
942
|
+
currentLine = "";
|
|
943
|
+
} else {
|
|
944
|
+
currentLine += char;
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
lastCharWasNewline = char === "\n";
|
|
948
|
+
}
|
|
949
|
+
};
|
|
950
|
+
const stream = fs.createReadStream(path);
|
|
951
|
+
try {
|
|
952
|
+
for await (const chunk of stream) {
|
|
953
|
+
if (signal?.aborted) {
|
|
954
|
+
stream.destroy();
|
|
955
|
+
throw new Error("Operation aborted");
|
|
956
|
+
}
|
|
957
|
+
const bytes = chunk;
|
|
958
|
+
fileBinaryDetector.update(bytes);
|
|
959
|
+
scanText(textDecoder.decode(bytes, { stream: true }));
|
|
960
|
+
}
|
|
961
|
+
scanText(textDecoder.decode());
|
|
962
|
+
} finally {
|
|
963
|
+
stream.destroy();
|
|
964
|
+
}
|
|
965
|
+
if (lastCharWasNewline) {
|
|
966
|
+
totalLines++;
|
|
967
|
+
} else if (currentLine !== "" || currentLineBytes > 0) {
|
|
968
|
+
entries.push({ text: keepLineText ? currentLine : null, bytes: currentLineBytes });
|
|
969
|
+
entryBytes += currentLineBytes;
|
|
970
|
+
totalLines++;
|
|
971
|
+
trimRing();
|
|
972
|
+
} else if (totalLines === 0) {
|
|
973
|
+
totalLines = 1;
|
|
974
|
+
}
|
|
975
|
+
const phantomIncluded = lastCharWasNewline;
|
|
976
|
+
const emptyFileSingleLine = entries.length === 0 && !phantomIncluded && totalLines === 1;
|
|
977
|
+
const windowLines = entries.length + (phantomIncluded ? 1 : 0) + (emptyFileSingleLine ? 1 : 0);
|
|
978
|
+
const selectedBytes = entries.reduce((sum, entry) => sum + entry.bytes, 0) + Math.max(0, windowLines - 1);
|
|
979
|
+
const firstLineBytes = entries.length > 0 ? entries[0].bytes : 0;
|
|
980
|
+
const firstLineExceedsLimit = entries.length === 1 && entries[0].text === null;
|
|
981
|
+
const streamedLines = totalLines - (phantomIncluded ? 1 : 0) - (emptyFileSingleLine ? 1 : 0);
|
|
982
|
+
const lostWindowLines = Math.max(0, Math.min(streamedLines, effectiveN) - entries.length);
|
|
983
|
+
const outputLines = [];
|
|
984
|
+
let outputBytes = 0;
|
|
985
|
+
let truncated = lostWindowLines > 0;
|
|
986
|
+
let truncatedBy = lostWindowLines > 0 ? "bytes" : null;
|
|
987
|
+
let firstShownEntryIndex;
|
|
988
|
+
const phantomReserve = phantomIncluded && !emptyFileSingleLine ? 1 : 0;
|
|
989
|
+
for (let index = entries.length - 1; index >= 0; index--) {
|
|
990
|
+
const entry = entries[index];
|
|
991
|
+
if (outputLines.length + phantomReserve >= maxOutputLines) {
|
|
992
|
+
truncated = true;
|
|
993
|
+
truncatedBy = truncatedBy ?? "lines";
|
|
994
|
+
break;
|
|
995
|
+
}
|
|
996
|
+
if (entry.text === null) {
|
|
997
|
+
truncated = true;
|
|
998
|
+
truncatedBy = "bytes";
|
|
999
|
+
break;
|
|
1000
|
+
}
|
|
1001
|
+
const candidate = outputBytes + (outputLines.length > 0 ? 1 : 0) + entry.bytes;
|
|
1002
|
+
if (candidate > maxOutputBytes) {
|
|
1003
|
+
truncated = true;
|
|
1004
|
+
truncatedBy = "bytes";
|
|
1005
|
+
break;
|
|
1006
|
+
}
|
|
1007
|
+
outputLines.unshift(entry.text);
|
|
1008
|
+
outputBytes = candidate;
|
|
1009
|
+
firstShownEntryIndex = index;
|
|
1010
|
+
}
|
|
1011
|
+
if (phantomIncluded) {
|
|
1012
|
+
if (outputLines.length + 1 <= maxOutputLines || outputLines.length === 0) {
|
|
1013
|
+
const phantomBytes = outputLines.length > 0 ? 1 : 0;
|
|
1014
|
+
if (outputBytes + phantomBytes <= maxOutputBytes) {
|
|
1015
|
+
outputLines.push("");
|
|
1016
|
+
outputBytes += phantomBytes;
|
|
1017
|
+
} else {
|
|
1018
|
+
truncated = true;
|
|
1019
|
+
truncatedBy = "bytes";
|
|
1020
|
+
}
|
|
1021
|
+
} else {
|
|
1022
|
+
truncated = true;
|
|
1023
|
+
truncatedBy = truncatedBy ?? "lines";
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
if (emptyFileSingleLine) {
|
|
1027
|
+
outputLines.push("");
|
|
1028
|
+
}
|
|
1029
|
+
if (firstLineExceedsLimit) {
|
|
1030
|
+
truncated = true;
|
|
1031
|
+
truncatedBy = "bytes";
|
|
1032
|
+
}
|
|
1033
|
+
const realLastLine = totalLines - (phantomIncluded ? 1 : 0);
|
|
1034
|
+
const outputStartLine = outputLines.length === 0 ? totalLines + 1 : firstShownEntryIndex !== void 0 ? realLastLine - entries.length + 1 + firstShownEntryIndex : totalLines;
|
|
1035
|
+
const content = outputLines.join("\n");
|
|
1036
|
+
const selectedHasher = createTextHasher();
|
|
1037
|
+
selectedHasher.update(content);
|
|
1038
|
+
const selectedBinaryDetector = new StreamingBinaryDetector();
|
|
1039
|
+
if (content.length > 0) {
|
|
1040
|
+
selectedBinaryDetector.update(Buffer.from(content, "utf-8"));
|
|
1041
|
+
}
|
|
1042
|
+
return {
|
|
1043
|
+
content,
|
|
1044
|
+
contentHash: fullHasher.digest(),
|
|
1045
|
+
selectedContentHash: selectedHasher.digest(),
|
|
1046
|
+
totalLines,
|
|
1047
|
+
totalBytes: stat.size,
|
|
1048
|
+
selectedLines: windowLines,
|
|
1049
|
+
selectedBytes,
|
|
1050
|
+
firstLineBytes,
|
|
1051
|
+
outputLines: outputLines.length,
|
|
1052
|
+
outputBytes,
|
|
1053
|
+
truncated,
|
|
1054
|
+
truncatedBy,
|
|
1055
|
+
firstLineExceedsLimit,
|
|
1056
|
+
selectedBytesLookBinary: selectedBinaryDetector.finish(),
|
|
1057
|
+
fileBytesLookBinary: fileBinaryDetector.finish(),
|
|
1058
|
+
endsWithNewline: lastCharWasNewline,
|
|
1059
|
+
outputStartLine,
|
|
880
1060
|
mtimeMs: stat.mtime.getTime(),
|
|
881
1061
|
size: stat.size
|
|
882
1062
|
};
|
|
@@ -1206,6 +1386,9 @@ var PuerTSFileSystem = class {
|
|
|
1206
1386
|
if (signal?.aborted) {
|
|
1207
1387
|
throw new Error("Operation aborted");
|
|
1208
1388
|
}
|
|
1389
|
+
if (options?.tailLines !== void 0 && Number.isFinite(options.tailLines) && options.tailLines > 0) {
|
|
1390
|
+
return this.readTextRangeTailViaBridge(path, options, signal);
|
|
1391
|
+
}
|
|
1209
1392
|
const bridge = getPieFileBridge();
|
|
1210
1393
|
const normalizedPath = this.normalizePath(path);
|
|
1211
1394
|
if (typeof bridge.StartReadTextRange !== "function" || typeof bridge.CancelRequest !== "function" || typeof bridge.ReleaseRequest !== "function") {
|
|
@@ -1237,6 +1420,71 @@ var PuerTSFileSystem = class {
|
|
|
1237
1420
|
bridge.ReleaseRequest(requestId);
|
|
1238
1421
|
}
|
|
1239
1422
|
}
|
|
1423
|
+
/**
|
|
1424
|
+
* Tail fallback for the PuerTS host: the Unity C# bridge has no native
|
|
1425
|
+
* tail support yet (follow-up: a purpose-built bridge method mirroring
|
|
1426
|
+
* NodeFileSystem's single-scan ring buffer). Until then, translate
|
|
1427
|
+
* tailLines into the bridge's offset/limit windows — a 1-line probe for
|
|
1428
|
+
* the line count, one for phantom detection, then the window read. The
|
|
1429
|
+
* extra scans stay inside the platform so every caller (the shared read
|
|
1430
|
+
* tool, future hosts) sees one uniform tailLines contract.
|
|
1431
|
+
*
|
|
1432
|
+
* Two contract guards live here because the bridge reads windows FORWARD:
|
|
1433
|
+
* 1. The C# side keeps the window's HEAD under the byte cap — the opposite
|
|
1434
|
+
* of tail semantics. Halve the window until it fits so the delivered
|
|
1435
|
+
* content always ends at the file's last line (matching NodeFileSystem);
|
|
1436
|
+
* a single over-cap line degrades to firstLineExceedsLimit, the same
|
|
1437
|
+
* signal Node produces.
|
|
1438
|
+
* 2. Out-of-band appends between the probes and the window read would
|
|
1439
|
+
* stale the line count; verify mtime stability and retry a bounded
|
|
1440
|
+
* number of times, then fall through best-effort (append-heavy logs
|
|
1441
|
+
* legitimately churn).
|
|
1442
|
+
*/
|
|
1443
|
+
async readTextRangeTailViaBridge(path, options, signal) {
|
|
1444
|
+
const probeOptions = {
|
|
1445
|
+
offsetLine: 0,
|
|
1446
|
+
limitLines: 1,
|
|
1447
|
+
maxOutputLines: 1,
|
|
1448
|
+
maxOutputBytes: options.maxOutputBytes
|
|
1449
|
+
};
|
|
1450
|
+
const maxOutputLines = Number.isFinite(options.maxOutputLines) ? Math.floor(options.maxOutputLines) : Number.POSITIVE_INFINITY;
|
|
1451
|
+
for (let attempt = 0; ; attempt++) {
|
|
1452
|
+
const countProbe = await this.readTextRange(path, probeOptions, signal);
|
|
1453
|
+
const totalLines = countProbe.totalLines;
|
|
1454
|
+
const requested = Math.floor(options.tailLines);
|
|
1455
|
+
let effectiveN = Math.max(1, Math.min(requested, maxOutputLines));
|
|
1456
|
+
const lastProbe = await this.readTextRange(path, { ...probeOptions, offsetLine: Math.max(0, totalLines - 1) }, signal);
|
|
1457
|
+
const phantom = lastProbe.selectedBytes === 0 && !lastProbe.firstLineExceedsLimit && totalLines > 1;
|
|
1458
|
+
let result;
|
|
1459
|
+
let windowOffsetLine = 0;
|
|
1460
|
+
for (; ; ) {
|
|
1461
|
+
windowOffsetLine = Math.max(0, totalLines - effectiveN - (phantom ? 1 : 0));
|
|
1462
|
+
result = await this.readTextRange(path, {
|
|
1463
|
+
offsetLine: windowOffsetLine,
|
|
1464
|
+
limitLines: effectiveN + (phantom ? 1 : 0),
|
|
1465
|
+
maxOutputLines: options.maxOutputLines,
|
|
1466
|
+
maxOutputBytes: options.maxOutputBytes
|
|
1467
|
+
}, signal);
|
|
1468
|
+
const byteTruncated = result.truncated && result.truncatedBy === "bytes" && !result.firstLineExceedsLimit;
|
|
1469
|
+
const oversizedHead = result.truncated && result.firstLineExceedsLimit;
|
|
1470
|
+
if (byteTruncated && effectiveN > 1) {
|
|
1471
|
+
effectiveN = Math.max(1, Math.floor(effectiveN / 2));
|
|
1472
|
+
continue;
|
|
1473
|
+
}
|
|
1474
|
+
if (oversizedHead) {
|
|
1475
|
+
const nextEffectiveN = totalLines - (phantom ? 1 : 0) - (windowOffsetLine + 1);
|
|
1476
|
+
if (nextEffectiveN < 1 || nextEffectiveN >= effectiveN) break;
|
|
1477
|
+
effectiveN = nextEffectiveN;
|
|
1478
|
+
continue;
|
|
1479
|
+
}
|
|
1480
|
+
break;
|
|
1481
|
+
}
|
|
1482
|
+
const stable = countProbe.mtimeMs === lastProbe.mtimeMs && lastProbe.mtimeMs === result.mtimeMs && countProbe.contentHash === lastProbe.contentHash && lastProbe.contentHash === result.contentHash;
|
|
1483
|
+
if (stable || attempt >= 2) {
|
|
1484
|
+
return { ...result, endsWithNewline: phantom, outputStartLine: windowOffsetLine + 1 };
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1240
1488
|
async writeFile(path, data, encoding = "utf-8") {
|
|
1241
1489
|
const bridge = getPieFileBridge();
|
|
1242
1490
|
const normalizedPath = this.normalizePath(path);
|
|
@@ -1755,6 +2003,7 @@ var NodeHttpClient = class {
|
|
|
1755
2003
|
let done = false;
|
|
1756
2004
|
let error = null;
|
|
1757
2005
|
let waiting = null;
|
|
2006
|
+
let consumerClosed = false;
|
|
1758
2007
|
const wake = (value) => {
|
|
1759
2008
|
if (!waiting) return;
|
|
1760
2009
|
const w = waiting;
|
|
@@ -1840,6 +2089,7 @@ var NodeHttpClient = class {
|
|
|
1840
2089
|
failStream(requestTimeoutError ?? new Error("SSE stream aborted"));
|
|
1841
2090
|
});
|
|
1842
2091
|
res.on("close", () => {
|
|
2092
|
+
if (consumerClosed) return;
|
|
1843
2093
|
if (!done || !res.complete) {
|
|
1844
2094
|
failStream(requestTimeoutError ?? new Error("SSE stream closed before end"));
|
|
1845
2095
|
}
|
|
@@ -1865,6 +2115,7 @@ var NodeHttpClient = class {
|
|
|
1865
2115
|
void waitResult;
|
|
1866
2116
|
}
|
|
1867
2117
|
} finally {
|
|
2118
|
+
consumerClosed = true;
|
|
1868
2119
|
if (signal && abortHandler) {
|
|
1869
2120
|
signal.removeEventListener("abort", abortHandler);
|
|
1870
2121
|
}
|
|
@@ -2524,9 +2775,19 @@ var FileSystemGateway = class {
|
|
|
2524
2775
|
const recursive = options?.recursive ?? true;
|
|
2525
2776
|
const platform = detectPlatform();
|
|
2526
2777
|
if (platform === "puerts" && typeof CS !== "undefined") {
|
|
2527
|
-
if (CS.System.IO.Directory.Exists(path)) {
|
|
2778
|
+
if (!CS.System.IO.Directory.Exists(path)) {
|
|
2779
|
+
return;
|
|
2780
|
+
}
|
|
2781
|
+
if (typeof CS.System.IO.Directory.Delete === "function") {
|
|
2528
2782
|
CS.System.IO.Directory.Delete(path, recursive);
|
|
2783
|
+
return;
|
|
2529
2784
|
}
|
|
2785
|
+
const info = new CS.System.IO.DirectoryInfo(path);
|
|
2786
|
+
if (info && typeof info.Delete === "function") {
|
|
2787
|
+
info.Delete(recursive);
|
|
2788
|
+
return;
|
|
2789
|
+
}
|
|
2790
|
+
deletePuertsDirectoryByEnumeration(path, recursive);
|
|
2530
2791
|
return;
|
|
2531
2792
|
}
|
|
2532
2793
|
const fs = nodeRequire("fs");
|
|
@@ -2549,9 +2810,20 @@ var FileSystemGateway = class {
|
|
|
2549
2810
|
throw new Error(`Directory not found: ${source}`);
|
|
2550
2811
|
}
|
|
2551
2812
|
if (CS.System.IO.Directory.Exists(destination)) {
|
|
2552
|
-
|
|
2813
|
+
const destinationFiles = Array.from(CS.System.IO.Directory.GetFiles(destination) ?? []);
|
|
2814
|
+
const destinationDirs = Array.from(CS.System.IO.Directory.GetDirectories(destination) ?? []);
|
|
2815
|
+
const isEmpty = destinationFiles.length === 0 && destinationDirs.length === 0;
|
|
2816
|
+
if (!isEmpty) {
|
|
2817
|
+
throw new Error(`Move target already exists: ${destination}`);
|
|
2818
|
+
}
|
|
2819
|
+
movePuertsDirectoryContents(source, destination);
|
|
2820
|
+
return;
|
|
2821
|
+
}
|
|
2822
|
+
if (typeof CS.System.IO.Directory.Move === "function") {
|
|
2823
|
+
CS.System.IO.Directory.Move(source, destination);
|
|
2824
|
+
} else {
|
|
2825
|
+
new CS.System.IO.DirectoryInfo(source).MoveTo(destination);
|
|
2553
2826
|
}
|
|
2554
|
-
CS.System.IO.Directory.Move(source, destination);
|
|
2555
2827
|
return;
|
|
2556
2828
|
}
|
|
2557
2829
|
const fs = nodeRequire("fs");
|
|
@@ -2671,6 +2943,100 @@ var FileSystemGateway = class {
|
|
|
2671
2943
|
return this.config;
|
|
2672
2944
|
}
|
|
2673
2945
|
};
|
|
2946
|
+
function movePuertsDirectoryContents(source, destination) {
|
|
2947
|
+
const directory = CS.System.IO.Directory;
|
|
2948
|
+
const file = CS.System.IO.File;
|
|
2949
|
+
if (typeof directory.GetFiles !== "function" || typeof directory.GetDirectories !== "function" || typeof directory.CreateDirectory !== "function" || typeof file.Copy !== "function") {
|
|
2950
|
+
throw new Error(
|
|
2951
|
+
`Host filesystem binding cannot move onto existing directory '${destination}': directory enumeration/copy is unavailable`
|
|
2952
|
+
);
|
|
2953
|
+
}
|
|
2954
|
+
if (isPuertsReparsePoint(source) || isPuertsReparsePoint(destination)) {
|
|
2955
|
+
throw new Error(
|
|
2956
|
+
`Refusing to move '${source}' through a reparse point (symlink/junction); resolve the link or delete it first`
|
|
2957
|
+
);
|
|
2958
|
+
}
|
|
2959
|
+
directory.CreateDirectory(destination);
|
|
2960
|
+
for (const entry of Array.from(directory.GetFiles(source) ?? [])) {
|
|
2961
|
+
const name = String(entry).replace(/\\/g, "/").split("/").pop();
|
|
2962
|
+
file.Copy(String(entry), `${destination}/${name}`, true);
|
|
2963
|
+
}
|
|
2964
|
+
for (const subdir of Array.from(directory.GetDirectories(source) ?? [])) {
|
|
2965
|
+
const name = String(subdir).replace(/\\/g, "/").split("/").pop();
|
|
2966
|
+
if (isPuertsReparsePoint(String(subdir))) continue;
|
|
2967
|
+
movePuertsDirectoryContents(String(subdir), `${destination}/${name}`);
|
|
2968
|
+
}
|
|
2969
|
+
for (const entry of Array.from(directory.GetFiles(source) ?? [])) {
|
|
2970
|
+
try {
|
|
2971
|
+
file.Delete(String(entry));
|
|
2972
|
+
} catch {
|
|
2973
|
+
}
|
|
2974
|
+
}
|
|
2975
|
+
}
|
|
2976
|
+
var warnedMissingPuertsGetAttributes = false;
|
|
2977
|
+
function isPuertsReparsePoint(path) {
|
|
2978
|
+
const file = CS.System.IO.File;
|
|
2979
|
+
if (typeof file.GetAttributes !== "function") {
|
|
2980
|
+
if (!warnedMissingPuertsGetAttributes) {
|
|
2981
|
+
warnedMissingPuertsGetAttributes = true;
|
|
2982
|
+
try {
|
|
2983
|
+
console.warn(
|
|
2984
|
+
"[platform] File.GetAttributes is unbound on this host; directory symlink checks are disabled (move/delete follow links)"
|
|
2985
|
+
);
|
|
2986
|
+
} catch {
|
|
2987
|
+
}
|
|
2988
|
+
}
|
|
2989
|
+
return false;
|
|
2990
|
+
}
|
|
2991
|
+
try {
|
|
2992
|
+
const attrs = file.GetAttributes(path);
|
|
2993
|
+
const raw = typeof attrs === "number" ? attrs : attrs.value__;
|
|
2994
|
+
const value = typeof raw === "number" ? raw : Number(raw);
|
|
2995
|
+
if (!Number.isFinite(value)) return false;
|
|
2996
|
+
return (value & 1024) !== 0;
|
|
2997
|
+
} catch {
|
|
2998
|
+
return false;
|
|
2999
|
+
}
|
|
3000
|
+
}
|
|
3001
|
+
var warnedPuertsDeletionShells = false;
|
|
3002
|
+
function warnPuertsDeletionShellsOnce(path) {
|
|
3003
|
+
if (warnedPuertsDeletionShells) return;
|
|
3004
|
+
warnedPuertsDeletionShells = true;
|
|
3005
|
+
try {
|
|
3006
|
+
console.warn(
|
|
3007
|
+
`[platform] Directory.Delete is unbound on this host; '${path}' contents were removed but empty directory shells cannot be deleted by this binding (logged once)`
|
|
3008
|
+
);
|
|
3009
|
+
} catch {
|
|
3010
|
+
}
|
|
3011
|
+
}
|
|
3012
|
+
function deletePuertsDirectoryByEnumeration(path, recursive) {
|
|
3013
|
+
const directory = CS.System.IO.Directory;
|
|
3014
|
+
const file = CS.System.IO.File;
|
|
3015
|
+
if (typeof directory.GetFiles !== "function" || typeof file.Delete !== "function") {
|
|
3016
|
+
throw new Error(
|
|
3017
|
+
`Host filesystem binding cannot delete directory '${path}': Directory.Delete and enumeration are unavailable`
|
|
3018
|
+
);
|
|
3019
|
+
}
|
|
3020
|
+
if (isPuertsReparsePoint(path)) {
|
|
3021
|
+
throw new Error(
|
|
3022
|
+
`Refusing to delete '${path}' through a reparse point (symlink/junction); resolve the link or delete it directly`
|
|
3023
|
+
);
|
|
3024
|
+
}
|
|
3025
|
+
const files = Array.from(directory.GetFiles(path) ?? []);
|
|
3026
|
+
const subdirs = Array.from(directory.GetDirectories(path) ?? []);
|
|
3027
|
+
if (!recursive) {
|
|
3028
|
+
if (files.length > 0 || subdirs.length > 0) {
|
|
3029
|
+
throw new Error(`Directory not empty: ${path}`);
|
|
3030
|
+
}
|
|
3031
|
+
return;
|
|
3032
|
+
}
|
|
3033
|
+
for (const entry of files) file.Delete(entry);
|
|
3034
|
+
for (const subdir of subdirs) {
|
|
3035
|
+
if (isPuertsReparsePoint(String(subdir))) continue;
|
|
3036
|
+
deletePuertsDirectoryByEnumeration(String(subdir), true);
|
|
3037
|
+
}
|
|
3038
|
+
warnPuertsDeletionShellsOnce(path);
|
|
3039
|
+
}
|
|
2674
3040
|
|
|
2675
3041
|
// ../../packages/platform/src/index.ts
|
|
2676
3042
|
var fileSystemInstance = null;
|
|
@@ -2740,10 +3106,15 @@ function parseStreamingJson(partialJson) {
|
|
|
2740
3106
|
}
|
|
2741
3107
|
|
|
2742
3108
|
// ../../packages/ai/src/providers/simple-options.ts
|
|
3109
|
+
var DEFAULT_MAX_TOKENS = 32e3;
|
|
3110
|
+
function positiveFiniteOrInfinity(value) {
|
|
3111
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : Number.POSITIVE_INFINITY;
|
|
3112
|
+
}
|
|
2743
3113
|
function buildBaseOptions(model, options, apiKey) {
|
|
3114
|
+
const modelMaxTokens = positiveFiniteOrInfinity(model.maxTokens);
|
|
2744
3115
|
return {
|
|
2745
3116
|
temperature: options?.temperature,
|
|
2746
|
-
maxTokens: options?.maxTokens || Math.min(
|
|
3117
|
+
maxTokens: options?.maxTokens || Math.min(modelMaxTokens, DEFAULT_MAX_TOKENS),
|
|
2747
3118
|
signal: options?.signal,
|
|
2748
3119
|
apiKey: apiKey || options?.apiKey,
|
|
2749
3120
|
cacheRetention: options?.cacheRetention,
|
|
@@ -2765,11 +3136,18 @@ function adjustMaxTokensForThinking(baseMaxTokens, modelMaxTokens, reasoningLeve
|
|
|
2765
3136
|
medium: 8192,
|
|
2766
3137
|
high: 16384
|
|
2767
3138
|
};
|
|
2768
|
-
const budgets = { ...defaultBudgets
|
|
3139
|
+
const budgets = { ...defaultBudgets };
|
|
3140
|
+
if (customBudgets) {
|
|
3141
|
+
for (const key of Object.keys(defaultBudgets)) {
|
|
3142
|
+
const value = customBudgets[key];
|
|
3143
|
+
if (typeof value === "number" && Number.isFinite(value) && value >= 0) budgets[key] = value;
|
|
3144
|
+
}
|
|
3145
|
+
}
|
|
2769
3146
|
const minOutputTokens = 1024;
|
|
2770
3147
|
const level = clampReasoning(reasoningLevel);
|
|
2771
|
-
let thinkingBudget = budgets[level];
|
|
2772
|
-
const
|
|
3148
|
+
let thinkingBudget = budgets[level] ?? defaultBudgets[level] ?? 0;
|
|
3149
|
+
const outputCap = positiveFiniteOrInfinity(modelMaxTokens);
|
|
3150
|
+
const maxTokens = Math.min(baseMaxTokens + thinkingBudget, outputCap);
|
|
2773
3151
|
if (maxTokens <= thinkingBudget) {
|
|
2774
3152
|
thinkingBudget = Math.max(0, maxTokens - minOutputTokens);
|
|
2775
3153
|
}
|
|
@@ -3695,7 +4073,11 @@ var streamOpenAICompletions = (model, context, options) => {
|
|
|
3695
4073
|
}
|
|
3696
4074
|
const emittedCallCounts = /* @__PURE__ */ new Map();
|
|
3697
4075
|
const excessDuplicateEntries = /* @__PURE__ */ new Set();
|
|
4076
|
+
const repeatExempt = new Set(
|
|
4077
|
+
(context.tools ?? []).filter((tool) => tool.allowIdenticalRepeatCalls === true).map((tool) => tool.name)
|
|
4078
|
+
);
|
|
3698
4079
|
for (const entry of toolCallEntries) {
|
|
4080
|
+
if (repeatExempt.has(entry.block.name)) continue;
|
|
3699
4081
|
const key = `${entry.block.name}
|
|
3700
4082
|
${entry.partialArgs}`;
|
|
3701
4083
|
const seen = (emittedCallCounts.get(key) ?? 0) + 1;
|
|
@@ -3734,8 +4116,11 @@ ${entry.partialArgs}`;
|
|
|
3734
4116
|
block.arguments = parseFinalToolArguments(partialArgs, block.name);
|
|
3735
4117
|
stream.push({ type: "toolcall_end", contentIndex, toolCall: block, partial: output });
|
|
3736
4118
|
}
|
|
3737
|
-
|
|
4119
|
+
const hasToolCallBlocks = output.content.some((block) => block.type === "toolCall");
|
|
4120
|
+
if (output.stopReason !== "error" && output.stopReason !== "aborted" && hasToolCallBlocks) {
|
|
3738
4121
|
output.stopReason = "toolUse";
|
|
4122
|
+
} else if (output.stopReason === "toolUse" && !hasToolCallBlocks) {
|
|
4123
|
+
output.stopReason = "stop";
|
|
3739
4124
|
}
|
|
3740
4125
|
if (options?.signal?.aborted) {
|
|
3741
4126
|
throw new Error("Request was aborted");
|
|
@@ -3767,8 +4152,18 @@ var streamSimpleOpenAICompletions = (model, context, options) => {
|
|
|
3767
4152
|
}
|
|
3768
4153
|
const base = buildBaseOptions(model, options, apiKey);
|
|
3769
4154
|
const reasoningEffort = clampReasoning(options?.reasoning);
|
|
4155
|
+
const needsThinkingAllowance = Boolean(model.reasoning) && options?.reasoning !== void 0;
|
|
4156
|
+
const adjusted = needsThinkingAllowance ? adjustMaxTokensForThinking(base.maxTokens || 0, model.maxTokens, options.reasoning, options?.thinkingBudgets) : void 0;
|
|
4157
|
+
let maxTokens = adjusted ? adjusted.maxTokens : base.maxTokens;
|
|
4158
|
+
if (maxTokens === void 0) {
|
|
4159
|
+
maxTokens = DEFAULT_MAX_TOKENS;
|
|
4160
|
+
}
|
|
4161
|
+
if (options?.maxTokens === void 0) {
|
|
4162
|
+
maxTokens = Math.min(maxTokens, DEFAULT_MAX_TOKENS);
|
|
4163
|
+
}
|
|
3770
4164
|
return streamOpenAICompletions(model, context, {
|
|
3771
4165
|
...base,
|
|
4166
|
+
maxTokens,
|
|
3772
4167
|
reasoningEffort
|
|
3773
4168
|
});
|
|
3774
4169
|
};
|
|
@@ -7689,6 +8084,7 @@ export {
|
|
|
7689
8084
|
type_exports,
|
|
7690
8085
|
ExtendsUndefinedCheck,
|
|
7691
8086
|
EventStream,
|
|
8087
|
+
AssistantMessageEventStream,
|
|
7692
8088
|
getModelCacheCapability,
|
|
7693
8089
|
EMPTY_ASSISTANT_CONTENT_ERROR,
|
|
7694
8090
|
OPENAI_COMPAT_PROTOCOL_ERROR_CODE,
|