opencode-gbk-tools 0.1.21 → 0.1.23
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/opencode-tools/gbk_edit.js +50 -28
- package/dist/opencode-tools/gbk_read.js +3 -3
- package/dist/opencode-tools/gbk_search.js +3 -3
- package/dist/opencode-tools/gbk_write.js +2 -2
- package/dist/opencode-tools/text_edit.js +30 -8
- package/dist/plugin/index.js +83 -38
- package/dist/plugins/opencode-gbk-tools.js +83 -38
- package/dist/release-manifest.json +2 -2
- package/package.json +1 -1
|
@@ -16311,29 +16311,36 @@ var ANSI_RED = "\x1B[31m";
|
|
|
16311
16311
|
var ANSI_GREEN = "\x1B[32m";
|
|
16312
16312
|
var ANSI_DIM = "\x1B[2m";
|
|
16313
16313
|
var ANSI_RESET = "\x1B[0m";
|
|
16314
|
+
var MAX_DIFF_LINES = 80;
|
|
16314
16315
|
function buildGbkLineDiffPreview(filePath, encoding, beforeText, afterText) {
|
|
16315
16316
|
const beforeLines = normalizeNewlines(beforeText).split("\n");
|
|
16316
16317
|
const afterLines = normalizeNewlines(afterText).split("\n");
|
|
16317
16318
|
const maxLines = Math.max(beforeLines.length, afterLines.length);
|
|
16318
|
-
const
|
|
16319
|
+
const header = [
|
|
16319
16320
|
`${ANSI_DIM}--- ${path2.basename(filePath)} (${encoding})${ANSI_RESET}`,
|
|
16320
16321
|
`${ANSI_DIM}+++ ${path2.basename(filePath)} (${encoding})${ANSI_RESET}`
|
|
16321
16322
|
];
|
|
16323
|
+
const body = [];
|
|
16322
16324
|
for (let index = 0; index < maxLines; index += 1) {
|
|
16323
16325
|
const before = beforeLines[index];
|
|
16324
16326
|
const after = afterLines[index];
|
|
16325
16327
|
if (before !== void 0 && after !== void 0 && before === after) {
|
|
16326
|
-
|
|
16328
|
+
body.push(` ${before}`);
|
|
16327
16329
|
continue;
|
|
16328
16330
|
}
|
|
16329
16331
|
if (before !== void 0) {
|
|
16330
|
-
|
|
16332
|
+
body.push(`${ANSI_RED}-${before}${ANSI_RESET}`);
|
|
16331
16333
|
}
|
|
16332
16334
|
if (after !== void 0) {
|
|
16333
|
-
|
|
16335
|
+
body.push(`${ANSI_GREEN}+${after}${ANSI_RESET}`);
|
|
16334
16336
|
}
|
|
16335
16337
|
}
|
|
16336
|
-
|
|
16338
|
+
if (header.length + body.length <= MAX_DIFF_LINES) {
|
|
16339
|
+
return "\n" + [...header, ...body].join("\n");
|
|
16340
|
+
}
|
|
16341
|
+
const changedOnly = body.filter((l) => l.startsWith(ANSI_RED) || l.startsWith(ANSI_GREEN));
|
|
16342
|
+
const notice = `${ANSI_DIM}... (\u4E0A\u4E0B\u6587\u5DF2\u7701\u7565\uFF0C\u4EC5\u663E\u793A\u53D8\u66F4\u884C)${ANSI_RESET}`;
|
|
16343
|
+
return "\n" + [...header, notice, ...changedOnly].join("\n");
|
|
16337
16344
|
}
|
|
16338
16345
|
function toSafeNumber(value) {
|
|
16339
16346
|
return typeof value === "bigint" ? Number(value) : value;
|
|
@@ -16357,10 +16364,10 @@ function assertInsertArguments(input) {
|
|
|
16357
16364
|
throw createGbkError("GBK_INVALID_ARGUMENT", "content \u4E0D\u80FD\u4E3A\u7A7A");
|
|
16358
16365
|
}
|
|
16359
16366
|
if (input.replaceAll !== void 0) {
|
|
16360
|
-
throw createGbkError("GBK_INVALID_ARGUMENT", "\u63D2\u5165\u6A21\u5F0F\u4E0D\u652F\uFFFD
|
|
16367
|
+
throw createGbkError("GBK_INVALID_ARGUMENT", "\u63D2\u5165\u6A21\u5F0F\u4E0D\u652F\uFFFD? replaceAll");
|
|
16361
16368
|
}
|
|
16362
16369
|
if (input.startLine !== void 0 || input.endLine !== void 0 || input.startAnchor !== void 0 || input.endAnchor !== void 0) {
|
|
16363
|
-
throw createGbkError("GBK_INVALID_ARGUMENT", "\u63D2\u5165\u6A21\u5F0F\u4E0D\u652F\uFFFD
|
|
16370
|
+
throw createGbkError("GBK_INVALID_ARGUMENT", "\u63D2\u5165\u6A21\u5F0F\u4E0D\u652F\uFFFD? startLine/endLine/startAnchor/endAnchor");
|
|
16364
16371
|
}
|
|
16365
16372
|
}
|
|
16366
16373
|
function findOccurrenceIndex(text, token, occurrence) {
|
|
@@ -16384,9 +16391,9 @@ function findOccurrenceIndex(text, token, occurrence) {
|
|
|
16384
16391
|
searchFrom = index + token.length;
|
|
16385
16392
|
}
|
|
16386
16393
|
if (count === 0) {
|
|
16387
|
-
throw createGbkError("GBK_NO_MATCH", `\u672A\u627E\u5230\u951A\uFFFD
|
|
16394
|
+
throw createGbkError("GBK_NO_MATCH", `\u672A\u627E\u5230\u951A\uFFFD?: ${token}`);
|
|
16388
16395
|
}
|
|
16389
|
-
throw createGbkError("GBK_NO_MATCH", `\u951A\u70B9 ${token} \u53EA\u627E\uFFFD
|
|
16396
|
+
throw createGbkError("GBK_NO_MATCH", `\u951A\u70B9 ${token} \u53EA\u627E\uFFFD? ${count} \u5904\uFF0C\u65E0\u6CD5\u4F7F\u7528\uFFFD? ${occurrence} \u5904`);
|
|
16390
16397
|
}
|
|
16391
16398
|
function insertByAnchor(text, mode, anchor, content, occurrence, ifExists, newlineStyle) {
|
|
16392
16399
|
const alignedContent = newlineStyle === "crlf" ? content.replace(/\r\n/g, "\n").replace(/\n/g, "\r\n") : newlineStyle === "lf" ? content.replace(/\r\n/g, "\n") : content;
|
|
@@ -16395,7 +16402,7 @@ function insertByAnchor(text, mode, anchor, content, occurrence, ifExists, newli
|
|
|
16395
16402
|
const alreadyExists = mode === "insertAfter" ? text.slice(insertionPoint, insertionPoint + alignedContent.length) === alignedContent : text.slice(Math.max(0, insertionPoint - alignedContent.length), insertionPoint) === alignedContent;
|
|
16396
16403
|
if (alreadyExists) {
|
|
16397
16404
|
if (ifExists === "error") {
|
|
16398
|
-
throw createGbkError("GBK_INVALID_ARGUMENT", "\u63D2\u5165\u4F4D\u7F6E\u5DF2\u5B58\u5728\u76F8\u540C\u5185\uFFFD
|
|
16405
|
+
throw createGbkError("GBK_INVALID_ARGUMENT", "\u63D2\u5165\u4F4D\u7F6E\u5DF2\u5B58\u5728\u76F8\u540C\u5185\uFFFD?");
|
|
16399
16406
|
}
|
|
16400
16407
|
if (ifExists === "skip") {
|
|
16401
16408
|
return {
|
|
@@ -16436,7 +16443,7 @@ function normalizeOptionalPositiveInteger(value, name) {
|
|
|
16436
16443
|
}
|
|
16437
16444
|
function assertNotBinary(buffer) {
|
|
16438
16445
|
if (buffer.includes(0)) {
|
|
16439
|
-
throw createGbkError("GBK_BINARY_FILE", "\u7591\u4F3C\u4E8C\u8FDB\u5236\u6587\u4EF6\uFF0C\u65E0\u6CD5\uFFFD
|
|
16446
|
+
throw createGbkError("GBK_BINARY_FILE", "\u7591\u4F3C\u4E8C\u8FDB\u5236\u6587\u4EF6\uFF0C\u65E0\u6CD5\uFFFD? GBK \u6587\u672C\u5904\u7406");
|
|
16440
16447
|
}
|
|
16441
16448
|
}
|
|
16442
16449
|
function detectNewlineStyle(text) {
|
|
@@ -16517,14 +16524,14 @@ function applyAnchors(text, startAnchor, endAnchor) {
|
|
|
16517
16524
|
if (startAnchor) {
|
|
16518
16525
|
const found = text.indexOf(startAnchor);
|
|
16519
16526
|
if (found === -1) {
|
|
16520
|
-
throw createGbkError("GBK_NO_MATCH", `\u672A\u627E\u5230\u8D77\u59CB\u951A\uFFFD
|
|
16527
|
+
throw createGbkError("GBK_NO_MATCH", `\u672A\u627E\u5230\u8D77\u59CB\u951A\uFFFD?: ${startAnchor}`);
|
|
16521
16528
|
}
|
|
16522
16529
|
rangeStart = found + startAnchor.length;
|
|
16523
16530
|
}
|
|
16524
16531
|
if (endAnchor) {
|
|
16525
16532
|
const found = text.indexOf(endAnchor, rangeStart);
|
|
16526
16533
|
if (found === -1) {
|
|
16527
|
-
throw createGbkError("GBK_NO_MATCH", `\u672A\u627E\u5230\u7ED3\u675F\u951A\uFFFD
|
|
16534
|
+
throw createGbkError("GBK_NO_MATCH", `\u672A\u627E\u5230\u7ED3\u675F\u951A\uFFFD?: ${endAnchor}`);
|
|
16528
16535
|
}
|
|
16529
16536
|
rangeEnd = found;
|
|
16530
16537
|
}
|
|
@@ -16577,9 +16584,9 @@ function getNearestContext(content, oldString) {
|
|
|
16577
16584
|
}
|
|
16578
16585
|
function buildNoMatchMessage(content, oldString) {
|
|
16579
16586
|
return [
|
|
16580
|
-
"\u672A\u627E\u5230\u9700\u8981\u66FF\u6362\u7684\u6587\u672C\uFFFD
|
|
16581
|
-
"oldString \u5FC5\u987B\u4E0E\u6587\u4EF6\u5B9E\u9645\u5185\u5BB9\u5B8C\u5168\u5BF9\u5E94\uFF0C\u6216\u4EC5\u5728\u6362\uFFFD
|
|
16582
|
-
"\u6700\u63A5\u8FD1\u7684\u4E0A\u4E0B\u6587\uFFFD
|
|
16587
|
+
"\u672A\u627E\u5230\u9700\u8981\u66FF\u6362\u7684\u6587\u672C\uFFFD?",
|
|
16588
|
+
"oldString \u5FC5\u987B\u4E0E\u6587\u4EF6\u5B9E\u9645\u5185\u5BB9\u5B8C\u5168\u5BF9\u5E94\uFF0C\u6216\u4EC5\u5728\u6362\uFFFD?/\u5C3E\u968F\u7A7A\u884C\u4E0A\u5B58\u5728\u8F7B\u5FAE\u5DEE\u5F02\uFFFD?",
|
|
16589
|
+
"\u6700\u63A5\u8FD1\u7684\u4E0A\u4E0B\u6587\uFFFD?",
|
|
16583
16590
|
getNearestContext(content, oldString)
|
|
16584
16591
|
].join("\n");
|
|
16585
16592
|
}
|
|
@@ -16702,10 +16709,10 @@ async function resolveReadableGbkFile(input) {
|
|
|
16702
16709
|
try {
|
|
16703
16710
|
stat = await fs2.stat(candidatePath);
|
|
16704
16711
|
} catch (error45) {
|
|
16705
|
-
throw createGbkError("GBK_FILE_NOT_FOUND", `\u6587\u4EF6\u4E0D\u5B58\uFFFD
|
|
16712
|
+
throw createGbkError("GBK_FILE_NOT_FOUND", `\u6587\u4EF6\u4E0D\u5B58\uFFFD?: ${candidatePath}`, error45);
|
|
16706
16713
|
}
|
|
16707
16714
|
if (stat.isDirectory()) {
|
|
16708
|
-
throw createGbkError("GBK_IS_DIRECTORY", `\u76EE\u6807\u8DEF\u5F84\u662F\u76EE\uFFFD
|
|
16715
|
+
throw createGbkError("GBK_IS_DIRECTORY", `\u76EE\u6807\u8DEF\u5F84\u662F\u76EE\uFFFD?: ${candidatePath}`);
|
|
16709
16716
|
}
|
|
16710
16717
|
return {
|
|
16711
16718
|
filePath: candidatePath,
|
|
@@ -16902,7 +16909,7 @@ function replaceScopedTextContent(scopeText, oldString, newString, replaceAll, n
|
|
|
16902
16909
|
} else if (occurrencesBefore === 0) {
|
|
16903
16910
|
throw createGbkError("GBK_NO_MATCH", buildNoMatchMessage(scopeText, oldString));
|
|
16904
16911
|
} else if (occurrencesBefore > 1) {
|
|
16905
|
-
throw createGbkError("GBK_MULTIPLE_MATCHES", `\u627E\u5230\u591A\u4E2A\u5339\u914D\uFFFD
|
|
16912
|
+
throw createGbkError("GBK_MULTIPLE_MATCHES", `\u627E\u5230\u591A\u4E2A\u5339\u914D\uFFFD?: ${oldString}`);
|
|
16906
16913
|
}
|
|
16907
16914
|
const alignedNewString = alignTextToNewlineStyle(newString, newlineStyle);
|
|
16908
16915
|
return {
|
|
@@ -17007,7 +17014,7 @@ async function replaceLargeGbkFileByAnchor(input) {
|
|
|
17007
17014
|
const alreadyExists = input.mode === "insertAfter" ? after.startsWith(alignedContent) : before.endsWith(alignedContent);
|
|
17008
17015
|
if (alreadyExists) {
|
|
17009
17016
|
if (input.ifExists === "error") {
|
|
17010
|
-
throw createGbkError("GBK_INVALID_ARGUMENT", "\u63D2\u5165\u4F4D\u7F6E\u5DF2\u5B58\u5728\u76F8\u540C\u5185\uFFFD
|
|
17017
|
+
throw createGbkError("GBK_INVALID_ARGUMENT", "\u63D2\u5165\u4F4D\u7F6E\u5DF2\u5B58\u5728\u76F8\u540C\u5185\uFFFD?");
|
|
17011
17018
|
}
|
|
17012
17019
|
if (input.ifExists === "skip") {
|
|
17013
17020
|
skipped = true;
|
|
@@ -17054,7 +17061,7 @@ async function replaceLargeGbkFileByAnchor(input) {
|
|
|
17054
17061
|
const alreadyExists = input.mode === "insertAfter" ? after.startsWith(alignedContent) : before.endsWith(alignedContent);
|
|
17055
17062
|
if (alreadyExists) {
|
|
17056
17063
|
if (input.ifExists === "error") {
|
|
17057
|
-
throw createGbkError("GBK_INVALID_ARGUMENT", "\u63D2\u5165\u4F4D\u7F6E\u5DF2\u5B58\u5728\u76F8\u540C\u5185\uFFFD
|
|
17064
|
+
throw createGbkError("GBK_INVALID_ARGUMENT", "\u63D2\u5165\u4F4D\u7F6E\u5DF2\u5B58\u5728\u76F8\u540C\u5185\uFFFD?");
|
|
17058
17065
|
}
|
|
17059
17066
|
if (input.ifExists === "skip") {
|
|
17060
17067
|
skipped = true;
|
|
@@ -17068,10 +17075,10 @@ async function replaceLargeGbkFileByAnchor(input) {
|
|
|
17068
17075
|
}
|
|
17069
17076
|
}
|
|
17070
17077
|
if (!inserted && totalMatches === 0) {
|
|
17071
|
-
throw createGbkError("GBK_NO_MATCH", `\u672A\u627E\u5230\u951A\uFFFD
|
|
17078
|
+
throw createGbkError("GBK_NO_MATCH", `\u672A\u627E\u5230\u951A\uFFFD?: ${input.anchor}`);
|
|
17072
17079
|
}
|
|
17073
17080
|
if (!inserted && totalMatches > 0) {
|
|
17074
|
-
throw createGbkError("GBK_NO_MATCH", `\u951A\u70B9 ${input.anchor} \u53EA\u627E\uFFFD
|
|
17081
|
+
throw createGbkError("GBK_NO_MATCH", `\u951A\u70B9 ${input.anchor} \u53EA\u627E\uFFFD? ${totalMatches} \u5904\uFF0C\u65E0\u6CD5\u4F7F\u7528\uFFFD? ${input.occurrence} \u5904`);
|
|
17075
17082
|
}
|
|
17076
17083
|
await finalizeInserted();
|
|
17077
17084
|
await handle.close();
|
|
@@ -17134,10 +17141,10 @@ async function replaceLargeGbkFileText(input) {
|
|
|
17134
17141
|
});
|
|
17135
17142
|
await flushText("", true);
|
|
17136
17143
|
if (occurrencesBefore === 0) {
|
|
17137
|
-
throw createGbkError("GBK_NO_MATCH", `\u672A\u627E\u5230\u8981\u66FF\u6362\u7684\u5185\uFFFD
|
|
17144
|
+
throw createGbkError("GBK_NO_MATCH", `\u672A\u627E\u5230\u8981\u66FF\u6362\u7684\u5185\uFFFD?: ${input.oldString}`);
|
|
17138
17145
|
}
|
|
17139
17146
|
if (!input.replaceAll && occurrencesBefore > 1) {
|
|
17140
|
-
throw createGbkError("GBK_MULTIPLE_MATCHES", `\u627E\u5230\u591A\u4E2A\u5339\u914D\uFFFD
|
|
17147
|
+
throw createGbkError("GBK_MULTIPLE_MATCHES", `\u627E\u5230\u591A\u4E2A\u5339\u914D\uFFFD?: ${input.oldString}`);
|
|
17141
17148
|
}
|
|
17142
17149
|
await handle.close();
|
|
17143
17150
|
const mode = typeof input.stat.mode === "bigint" ? Number(input.stat.mode) : input.stat.mode;
|
|
@@ -17286,7 +17293,7 @@ async function replaceGbkFileText(input) {
|
|
|
17286
17293
|
} else if (occurrencesBefore === 0) {
|
|
17287
17294
|
throw createGbkError("GBK_NO_MATCH", buildNoMatchMessage(scope.selectedText, effectiveOldString));
|
|
17288
17295
|
} else if (occurrencesBefore > 1) {
|
|
17289
|
-
throw createGbkError("GBK_MULTIPLE_MATCHES", `\u627E\u5230\u591A\u4E2A\u5339\u914D\uFFFD
|
|
17296
|
+
throw createGbkError("GBK_MULTIPLE_MATCHES", `\u627E\u5230\u591A\u4E2A\u5339\u914D\uFFFD?: ${effectiveOldString}`);
|
|
17290
17297
|
}
|
|
17291
17298
|
const fileNewlineStyle = detectNewlineStyle(current.content);
|
|
17292
17299
|
const alignedNewString = fileNewlineStyle === "crlf" ? input.newString.replace(/\r\n/g, "\n").replace(/\n/g, "\r\n") : fileNewlineStyle === "lf" ? input.newString.replace(/\r\n/g, "\n") : input.newString;
|
|
@@ -17307,7 +17314,22 @@ async function replaceGbkFileText(input) {
|
|
|
17307
17314
|
};
|
|
17308
17315
|
}
|
|
17309
17316
|
|
|
17317
|
+
// src/lib/model-context.ts
|
|
17318
|
+
var _currentContextTokens = null;
|
|
17319
|
+
function getMaxOutputChars(fallback = 8e3) {
|
|
17320
|
+
if (_currentContextTokens === null) return fallback;
|
|
17321
|
+
const computed = Math.round(_currentContextTokens * 0.01 * 4);
|
|
17322
|
+
return Math.max(4e3, Math.min(32e3, computed));
|
|
17323
|
+
}
|
|
17324
|
+
|
|
17310
17325
|
// src/tools/gbk_edit.ts
|
|
17326
|
+
function truncateToolOutput(content) {
|
|
17327
|
+
const maxChars = getMaxOutputChars();
|
|
17328
|
+
if (content.length <= maxChars) return content;
|
|
17329
|
+
const truncated = content.slice(0, maxChars);
|
|
17330
|
+
return truncated + `
|
|
17331
|
+
\x1B[2m... (\u8F93\u51FA\u5DF2\u622A\u65AD\uFF0C\u8D85\u51FA ${maxChars} \u5B57\u7B26\u4E0A\u9650)\x1B[0m`;
|
|
17332
|
+
}
|
|
17311
17333
|
var gbk_edit_default = tool({
|
|
17312
17334
|
description: `Edit GBK/GB18030 encoded text files with exact string replacement.
|
|
17313
17335
|
|
|
@@ -17377,8 +17399,8 @@ Insert mode:
|
|
|
17377
17399
|
diffPreview
|
|
17378
17400
|
}
|
|
17379
17401
|
});
|
|
17380
|
-
if (diffPreview) return diffPreview;
|
|
17381
|
-
return JSON.stringify(result, null, 2);
|
|
17402
|
+
if (diffPreview) return truncateToolOutput(diffPreview);
|
|
17403
|
+
return truncateToolOutput(JSON.stringify(result, null, 2));
|
|
17382
17404
|
}
|
|
17383
17405
|
});
|
|
17384
17406
|
export {
|
|
@@ -16329,7 +16329,7 @@ function normalizeOptionalPositiveInteger(value, name) {
|
|
|
16329
16329
|
}
|
|
16330
16330
|
function assertNotBinary(buffer) {
|
|
16331
16331
|
if (buffer.includes(0)) {
|
|
16332
|
-
throw createGbkError("GBK_BINARY_FILE", "\u7591\u4F3C\u4E8C\u8FDB\u5236\u6587\u4EF6\uFF0C\u65E0\u6CD5\uFFFD
|
|
16332
|
+
throw createGbkError("GBK_BINARY_FILE", "\u7591\u4F3C\u4E8C\u8FDB\u5236\u6587\u4EF6\uFF0C\u65E0\u6CD5\uFFFD? GBK \u6587\u672C\u5904\u7406");
|
|
16333
16333
|
}
|
|
16334
16334
|
}
|
|
16335
16335
|
function splitLinesWithNumbers(text, offset = 1, limit = 2e3) {
|
|
@@ -16420,10 +16420,10 @@ async function resolveReadableGbkFile(input) {
|
|
|
16420
16420
|
try {
|
|
16421
16421
|
stat = await fs2.stat(candidatePath);
|
|
16422
16422
|
} catch (error45) {
|
|
16423
|
-
throw createGbkError("GBK_FILE_NOT_FOUND", `\u6587\u4EF6\u4E0D\u5B58\uFFFD
|
|
16423
|
+
throw createGbkError("GBK_FILE_NOT_FOUND", `\u6587\u4EF6\u4E0D\u5B58\uFFFD?: ${candidatePath}`, error45);
|
|
16424
16424
|
}
|
|
16425
16425
|
if (stat.isDirectory()) {
|
|
16426
|
-
throw createGbkError("GBK_IS_DIRECTORY", `\u76EE\u6807\u8DEF\u5F84\u662F\u76EE\uFFFD
|
|
16426
|
+
throw createGbkError("GBK_IS_DIRECTORY", `\u76EE\u6807\u8DEF\u5F84\u662F\u76EE\uFFFD?: ${candidatePath}`);
|
|
16427
16427
|
}
|
|
16428
16428
|
return {
|
|
16429
16429
|
filePath: candidatePath,
|
|
@@ -16313,7 +16313,7 @@ function assertEncodingSupported(encoding) {
|
|
|
16313
16313
|
}
|
|
16314
16314
|
function assertNotBinary(buffer) {
|
|
16315
16315
|
if (buffer.includes(0)) {
|
|
16316
|
-
throw createGbkError("GBK_BINARY_FILE", "\u7591\u4F3C\u4E8C\u8FDB\u5236\u6587\u4EF6\uFF0C\u65E0\u6CD5\uFFFD
|
|
16316
|
+
throw createGbkError("GBK_BINARY_FILE", "\u7591\u4F3C\u4E8C\u8FDB\u5236\u6587\u4EF6\uFF0C\u65E0\u6CD5\uFFFD? GBK \u6587\u672C\u5904\u7406");
|
|
16317
16317
|
}
|
|
16318
16318
|
}
|
|
16319
16319
|
async function resolveReadableGbkFile(input) {
|
|
@@ -16324,10 +16324,10 @@ async function resolveReadableGbkFile(input) {
|
|
|
16324
16324
|
try {
|
|
16325
16325
|
stat = await fs2.stat(candidatePath);
|
|
16326
16326
|
} catch (error45) {
|
|
16327
|
-
throw createGbkError("GBK_FILE_NOT_FOUND", `\u6587\u4EF6\u4E0D\u5B58\uFFFD
|
|
16327
|
+
throw createGbkError("GBK_FILE_NOT_FOUND", `\u6587\u4EF6\u4E0D\u5B58\uFFFD?: ${candidatePath}`, error45);
|
|
16328
16328
|
}
|
|
16329
16329
|
if (stat.isDirectory()) {
|
|
16330
|
-
throw createGbkError("GBK_IS_DIRECTORY", `\u76EE\u6807\u8DEF\u5F84\u662F\u76EE\uFFFD
|
|
16330
|
+
throw createGbkError("GBK_IS_DIRECTORY", `\u76EE\u6807\u8DEF\u5F84\u662F\u76EE\uFFFD?: ${candidatePath}`);
|
|
16331
16331
|
}
|
|
16332
16332
|
return {
|
|
16333
16333
|
filePath: candidatePath,
|
|
@@ -16370,10 +16370,10 @@ async function writeGbkFile(input) {
|
|
|
16370
16370
|
try {
|
|
16371
16371
|
const stat = await fs2.stat(candidatePath);
|
|
16372
16372
|
if (stat.isDirectory()) {
|
|
16373
|
-
throw createGbkError("GBK_IS_DIRECTORY", `\u76EE\u6807\u8DEF\u5F84\u662F\u76EE\uFFFD
|
|
16373
|
+
throw createGbkError("GBK_IS_DIRECTORY", `\u76EE\u6807\u8DEF\u5F84\u662F\u76EE\uFFFD?: ${candidatePath}`);
|
|
16374
16374
|
}
|
|
16375
16375
|
if (!overwrite) {
|
|
16376
|
-
throw createGbkError("GBK_FILE_EXISTS", `\u76EE\u6807\u6587\u4EF6\u5DF2\u5B58\uFFFD
|
|
16376
|
+
throw createGbkError("GBK_FILE_EXISTS", `\u76EE\u6807\u6587\u4EF6\u5DF2\u5B58\uFFFD?: ${candidatePath}`);
|
|
16377
16377
|
}
|
|
16378
16378
|
} catch (error45) {
|
|
16379
16379
|
if (error45 instanceof Error && "code" in error45) {
|
|
@@ -16581,29 +16581,36 @@ var ANSI_RED = "\x1B[31m";
|
|
|
16581
16581
|
var ANSI_GREEN = "\x1B[32m";
|
|
16582
16582
|
var ANSI_DIM = "\x1B[2m";
|
|
16583
16583
|
var ANSI_RESET = "\x1B[0m";
|
|
16584
|
+
var MAX_DIFF_LINES = 80;
|
|
16584
16585
|
function buildLineDiffPreview(filePath, encoding, beforeText, afterText) {
|
|
16585
16586
|
const beforeLines = normalizeNewlines(beforeText).split("\n");
|
|
16586
16587
|
const afterLines = normalizeNewlines(afterText).split("\n");
|
|
16587
16588
|
const maxLines = Math.max(beforeLines.length, afterLines.length);
|
|
16588
|
-
const
|
|
16589
|
+
const header = [
|
|
16589
16590
|
`${ANSI_DIM}--- ${path3.basename(filePath)} (${encoding})${ANSI_RESET}`,
|
|
16590
16591
|
`${ANSI_DIM}+++ ${path3.basename(filePath)} (${encoding})${ANSI_RESET}`
|
|
16591
16592
|
];
|
|
16593
|
+
const body = [];
|
|
16592
16594
|
for (let index = 0; index < maxLines; index += 1) {
|
|
16593
16595
|
const before = beforeLines[index];
|
|
16594
16596
|
const after = afterLines[index];
|
|
16595
16597
|
if (before !== void 0 && after !== void 0 && before === after) {
|
|
16596
|
-
|
|
16598
|
+
body.push(` ${before}`);
|
|
16597
16599
|
continue;
|
|
16598
16600
|
}
|
|
16599
16601
|
if (before !== void 0) {
|
|
16600
|
-
|
|
16602
|
+
body.push(`${ANSI_RED}-${before}${ANSI_RESET}`);
|
|
16601
16603
|
}
|
|
16602
16604
|
if (after !== void 0) {
|
|
16603
|
-
|
|
16605
|
+
body.push(`${ANSI_GREEN}+${after}${ANSI_RESET}`);
|
|
16604
16606
|
}
|
|
16605
16607
|
}
|
|
16606
|
-
|
|
16608
|
+
if (header.length + body.length <= MAX_DIFF_LINES) {
|
|
16609
|
+
return "\n" + [...header, ...body].join("\n");
|
|
16610
|
+
}
|
|
16611
|
+
const changedOnly = body.filter((l) => l.startsWith(ANSI_RED) || l.startsWith(ANSI_GREEN));
|
|
16612
|
+
const notice = `${ANSI_DIM}... (\u4E0A\u4E0B\u6587\u5DF2\u7701\u7565\uFF0C\u4EC5\u663E\u793A\u53D8\u66F4\u884C)${ANSI_RESET}`;
|
|
16613
|
+
return "\n" + [...header, notice, ...changedOnly].join("\n");
|
|
16607
16614
|
}
|
|
16608
16615
|
function buildInsertOutput(text, mode, anchor, content, occurrence, ifExists, newlineStyle) {
|
|
16609
16616
|
const alignedContent = alignTextToNewlineStyle(content, newlineStyle);
|
|
@@ -16979,11 +16986,26 @@ async function replaceTextFileText(input) {
|
|
|
16979
16986
|
bytesRead: loaded.bytesRead,
|
|
16980
16987
|
bytesWritten: buffer.byteLength,
|
|
16981
16988
|
newlineStyle: detectNewlineStyle(outputText),
|
|
16982
|
-
diffPreview: buildLineDiffPreview(loaded.filePath, targetEncoding,
|
|
16989
|
+
diffPreview: buildLineDiffPreview(loaded.filePath, targetEncoding, input.oldString, alignedNewString)
|
|
16983
16990
|
};
|
|
16984
16991
|
}
|
|
16985
16992
|
|
|
16993
|
+
// src/lib/model-context.ts
|
|
16994
|
+
var _currentContextTokens = null;
|
|
16995
|
+
function getMaxOutputChars(fallback = 8e3) {
|
|
16996
|
+
if (_currentContextTokens === null) return fallback;
|
|
16997
|
+
const computed = Math.round(_currentContextTokens * 0.01 * 4);
|
|
16998
|
+
return Math.max(4e3, Math.min(32e3, computed));
|
|
16999
|
+
}
|
|
17000
|
+
|
|
16986
17001
|
// src/tools/text_edit.ts
|
|
17002
|
+
function truncateToolOutput(content) {
|
|
17003
|
+
const maxChars = getMaxOutputChars();
|
|
17004
|
+
if (content.length <= maxChars) return content;
|
|
17005
|
+
const truncated = content.slice(0, maxChars);
|
|
17006
|
+
return truncated + `
|
|
17007
|
+
\x1B[2m... (\u8F93\u51FA\u5DF2\u622A\u65AD\uFF0C\u8D85\u51FA ${maxChars} \u5B57\u7B26\u4E0A\u9650)\x1B[0m`;
|
|
17008
|
+
}
|
|
16987
17009
|
var text_edit_default = tool({
|
|
16988
17010
|
description: `Edit text files with automatic encoding detection and preservation.
|
|
16989
17011
|
|
|
@@ -17034,8 +17056,8 @@ var text_edit_default = tool({
|
|
|
17034
17056
|
diffPreview
|
|
17035
17057
|
}
|
|
17036
17058
|
});
|
|
17037
|
-
if (diffPreview) return diffPreview;
|
|
17038
|
-
return JSON.stringify(result, null, 2);
|
|
17059
|
+
if (diffPreview) return truncateToolOutput(diffPreview);
|
|
17060
|
+
return truncateToolOutput(JSON.stringify(result, null, 2));
|
|
17039
17061
|
}
|
|
17040
17062
|
});
|
|
17041
17063
|
export {
|
package/dist/plugin/index.js
CHANGED
|
@@ -16312,29 +16312,36 @@ var ANSI_RED = "\x1B[31m";
|
|
|
16312
16312
|
var ANSI_GREEN = "\x1B[32m";
|
|
16313
16313
|
var ANSI_DIM = "\x1B[2m";
|
|
16314
16314
|
var ANSI_RESET = "\x1B[0m";
|
|
16315
|
+
var MAX_DIFF_LINES = 80;
|
|
16315
16316
|
function buildGbkLineDiffPreview(filePath, encoding, beforeText, afterText) {
|
|
16316
16317
|
const beforeLines = normalizeNewlines(beforeText).split("\n");
|
|
16317
16318
|
const afterLines = normalizeNewlines(afterText).split("\n");
|
|
16318
16319
|
const maxLines = Math.max(beforeLines.length, afterLines.length);
|
|
16319
|
-
const
|
|
16320
|
+
const header = [
|
|
16320
16321
|
`${ANSI_DIM}--- ${path2.basename(filePath)} (${encoding})${ANSI_RESET}`,
|
|
16321
16322
|
`${ANSI_DIM}+++ ${path2.basename(filePath)} (${encoding})${ANSI_RESET}`
|
|
16322
16323
|
];
|
|
16324
|
+
const body = [];
|
|
16323
16325
|
for (let index = 0; index < maxLines; index += 1) {
|
|
16324
16326
|
const before = beforeLines[index];
|
|
16325
16327
|
const after = afterLines[index];
|
|
16326
16328
|
if (before !== void 0 && after !== void 0 && before === after) {
|
|
16327
|
-
|
|
16329
|
+
body.push(` ${before}`);
|
|
16328
16330
|
continue;
|
|
16329
16331
|
}
|
|
16330
16332
|
if (before !== void 0) {
|
|
16331
|
-
|
|
16333
|
+
body.push(`${ANSI_RED}-${before}${ANSI_RESET}`);
|
|
16332
16334
|
}
|
|
16333
16335
|
if (after !== void 0) {
|
|
16334
|
-
|
|
16336
|
+
body.push(`${ANSI_GREEN}+${after}${ANSI_RESET}`);
|
|
16335
16337
|
}
|
|
16336
16338
|
}
|
|
16337
|
-
|
|
16339
|
+
if (header.length + body.length <= MAX_DIFF_LINES) {
|
|
16340
|
+
return "\n" + [...header, ...body].join("\n");
|
|
16341
|
+
}
|
|
16342
|
+
const changedOnly = body.filter((l) => l.startsWith(ANSI_RED) || l.startsWith(ANSI_GREEN));
|
|
16343
|
+
const notice = `${ANSI_DIM}... (\u4E0A\u4E0B\u6587\u5DF2\u7701\u7565\uFF0C\u4EC5\u663E\u793A\u53D8\u66F4\u884C)${ANSI_RESET}`;
|
|
16344
|
+
return "\n" + [...header, notice, ...changedOnly].join("\n");
|
|
16338
16345
|
}
|
|
16339
16346
|
function toSafeNumber(value) {
|
|
16340
16347
|
return typeof value === "bigint" ? Number(value) : value;
|
|
@@ -16358,10 +16365,10 @@ function assertInsertArguments(input) {
|
|
|
16358
16365
|
throw createGbkError("GBK_INVALID_ARGUMENT", "content \u4E0D\u80FD\u4E3A\u7A7A");
|
|
16359
16366
|
}
|
|
16360
16367
|
if (input.replaceAll !== void 0) {
|
|
16361
|
-
throw createGbkError("GBK_INVALID_ARGUMENT", "\u63D2\u5165\u6A21\u5F0F\u4E0D\u652F\uFFFD
|
|
16368
|
+
throw createGbkError("GBK_INVALID_ARGUMENT", "\u63D2\u5165\u6A21\u5F0F\u4E0D\u652F\uFFFD? replaceAll");
|
|
16362
16369
|
}
|
|
16363
16370
|
if (input.startLine !== void 0 || input.endLine !== void 0 || input.startAnchor !== void 0 || input.endAnchor !== void 0) {
|
|
16364
|
-
throw createGbkError("GBK_INVALID_ARGUMENT", "\u63D2\u5165\u6A21\u5F0F\u4E0D\u652F\uFFFD
|
|
16371
|
+
throw createGbkError("GBK_INVALID_ARGUMENT", "\u63D2\u5165\u6A21\u5F0F\u4E0D\u652F\uFFFD? startLine/endLine/startAnchor/endAnchor");
|
|
16365
16372
|
}
|
|
16366
16373
|
}
|
|
16367
16374
|
function findOccurrenceIndex(text, token, occurrence) {
|
|
@@ -16385,9 +16392,9 @@ function findOccurrenceIndex(text, token, occurrence) {
|
|
|
16385
16392
|
searchFrom = index + token.length;
|
|
16386
16393
|
}
|
|
16387
16394
|
if (count === 0) {
|
|
16388
|
-
throw createGbkError("GBK_NO_MATCH", `\u672A\u627E\u5230\u951A\uFFFD
|
|
16395
|
+
throw createGbkError("GBK_NO_MATCH", `\u672A\u627E\u5230\u951A\uFFFD?: ${token}`);
|
|
16389
16396
|
}
|
|
16390
|
-
throw createGbkError("GBK_NO_MATCH", `\u951A\u70B9 ${token} \u53EA\u627E\uFFFD
|
|
16397
|
+
throw createGbkError("GBK_NO_MATCH", `\u951A\u70B9 ${token} \u53EA\u627E\uFFFD? ${count} \u5904\uFF0C\u65E0\u6CD5\u4F7F\u7528\uFFFD? ${occurrence} \u5904`);
|
|
16391
16398
|
}
|
|
16392
16399
|
function insertByAnchor(text, mode, anchor, content, occurrence, ifExists, newlineStyle) {
|
|
16393
16400
|
const alignedContent = newlineStyle === "crlf" ? content.replace(/\r\n/g, "\n").replace(/\n/g, "\r\n") : newlineStyle === "lf" ? content.replace(/\r\n/g, "\n") : content;
|
|
@@ -16396,7 +16403,7 @@ function insertByAnchor(text, mode, anchor, content, occurrence, ifExists, newli
|
|
|
16396
16403
|
const alreadyExists = mode === "insertAfter" ? text.slice(insertionPoint, insertionPoint + alignedContent.length) === alignedContent : text.slice(Math.max(0, insertionPoint - alignedContent.length), insertionPoint) === alignedContent;
|
|
16397
16404
|
if (alreadyExists) {
|
|
16398
16405
|
if (ifExists === "error") {
|
|
16399
|
-
throw createGbkError("GBK_INVALID_ARGUMENT", "\u63D2\u5165\u4F4D\u7F6E\u5DF2\u5B58\u5728\u76F8\u540C\u5185\uFFFD
|
|
16406
|
+
throw createGbkError("GBK_INVALID_ARGUMENT", "\u63D2\u5165\u4F4D\u7F6E\u5DF2\u5B58\u5728\u76F8\u540C\u5185\uFFFD?");
|
|
16400
16407
|
}
|
|
16401
16408
|
if (ifExists === "skip") {
|
|
16402
16409
|
return {
|
|
@@ -16437,7 +16444,7 @@ function normalizeOptionalPositiveInteger(value, name) {
|
|
|
16437
16444
|
}
|
|
16438
16445
|
function assertNotBinary(buffer) {
|
|
16439
16446
|
if (buffer.includes(0)) {
|
|
16440
|
-
throw createGbkError("GBK_BINARY_FILE", "\u7591\u4F3C\u4E8C\u8FDB\u5236\u6587\u4EF6\uFF0C\u65E0\u6CD5\uFFFD
|
|
16447
|
+
throw createGbkError("GBK_BINARY_FILE", "\u7591\u4F3C\u4E8C\u8FDB\u5236\u6587\u4EF6\uFF0C\u65E0\u6CD5\uFFFD? GBK \u6587\u672C\u5904\u7406");
|
|
16441
16448
|
}
|
|
16442
16449
|
}
|
|
16443
16450
|
function splitLinesWithNumbers(text, offset = 1, limit = 2e3) {
|
|
@@ -16567,14 +16574,14 @@ function applyAnchors(text, startAnchor, endAnchor) {
|
|
|
16567
16574
|
if (startAnchor) {
|
|
16568
16575
|
const found = text.indexOf(startAnchor);
|
|
16569
16576
|
if (found === -1) {
|
|
16570
|
-
throw createGbkError("GBK_NO_MATCH", `\u672A\u627E\u5230\u8D77\u59CB\u951A\uFFFD
|
|
16577
|
+
throw createGbkError("GBK_NO_MATCH", `\u672A\u627E\u5230\u8D77\u59CB\u951A\uFFFD?: ${startAnchor}`);
|
|
16571
16578
|
}
|
|
16572
16579
|
rangeStart = found + startAnchor.length;
|
|
16573
16580
|
}
|
|
16574
16581
|
if (endAnchor) {
|
|
16575
16582
|
const found = text.indexOf(endAnchor, rangeStart);
|
|
16576
16583
|
if (found === -1) {
|
|
16577
|
-
throw createGbkError("GBK_NO_MATCH", `\u672A\u627E\u5230\u7ED3\u675F\u951A\uFFFD
|
|
16584
|
+
throw createGbkError("GBK_NO_MATCH", `\u672A\u627E\u5230\u7ED3\u675F\u951A\uFFFD?: ${endAnchor}`);
|
|
16578
16585
|
}
|
|
16579
16586
|
rangeEnd = found;
|
|
16580
16587
|
}
|
|
@@ -16627,9 +16634,9 @@ function getNearestContext(content, oldString) {
|
|
|
16627
16634
|
}
|
|
16628
16635
|
function buildNoMatchMessage(content, oldString) {
|
|
16629
16636
|
return [
|
|
16630
|
-
"\u672A\u627E\u5230\u9700\u8981\u66FF\u6362\u7684\u6587\u672C\uFFFD
|
|
16631
|
-
"oldString \u5FC5\u987B\u4E0E\u6587\u4EF6\u5B9E\u9645\u5185\u5BB9\u5B8C\u5168\u5BF9\u5E94\uFF0C\u6216\u4EC5\u5728\u6362\uFFFD
|
|
16632
|
-
"\u6700\u63A5\u8FD1\u7684\u4E0A\u4E0B\u6587\uFFFD
|
|
16637
|
+
"\u672A\u627E\u5230\u9700\u8981\u66FF\u6362\u7684\u6587\u672C\uFFFD?",
|
|
16638
|
+
"oldString \u5FC5\u987B\u4E0E\u6587\u4EF6\u5B9E\u9645\u5185\u5BB9\u5B8C\u5168\u5BF9\u5E94\uFF0C\u6216\u4EC5\u5728\u6362\uFFFD?/\u5C3E\u968F\u7A7A\u884C\u4E0A\u5B58\u5728\u8F7B\u5FAE\u5DEE\u5F02\uFFFD?",
|
|
16639
|
+
"\u6700\u63A5\u8FD1\u7684\u4E0A\u4E0B\u6587\uFFFD?",
|
|
16633
16640
|
getNearestContext(content, oldString)
|
|
16634
16641
|
].join("\n");
|
|
16635
16642
|
}
|
|
@@ -16752,10 +16759,10 @@ async function resolveReadableGbkFile(input) {
|
|
|
16752
16759
|
try {
|
|
16753
16760
|
stat = await fs2.stat(candidatePath);
|
|
16754
16761
|
} catch (error45) {
|
|
16755
|
-
throw createGbkError("GBK_FILE_NOT_FOUND", `\u6587\u4EF6\u4E0D\u5B58\uFFFD
|
|
16762
|
+
throw createGbkError("GBK_FILE_NOT_FOUND", `\u6587\u4EF6\u4E0D\u5B58\uFFFD?: ${candidatePath}`, error45);
|
|
16756
16763
|
}
|
|
16757
16764
|
if (stat.isDirectory()) {
|
|
16758
|
-
throw createGbkError("GBK_IS_DIRECTORY", `\u76EE\u6807\u8DEF\u5F84\u662F\u76EE\uFFFD
|
|
16765
|
+
throw createGbkError("GBK_IS_DIRECTORY", `\u76EE\u6807\u8DEF\u5F84\u662F\u76EE\uFFFD?: ${candidatePath}`);
|
|
16759
16766
|
}
|
|
16760
16767
|
return {
|
|
16761
16768
|
filePath: candidatePath,
|
|
@@ -16960,7 +16967,7 @@ function replaceScopedTextContent(scopeText, oldString, newString, replaceAll, n
|
|
|
16960
16967
|
} else if (occurrencesBefore === 0) {
|
|
16961
16968
|
throw createGbkError("GBK_NO_MATCH", buildNoMatchMessage(scopeText, oldString));
|
|
16962
16969
|
} else if (occurrencesBefore > 1) {
|
|
16963
|
-
throw createGbkError("GBK_MULTIPLE_MATCHES", `\u627E\u5230\u591A\u4E2A\u5339\u914D\uFFFD
|
|
16970
|
+
throw createGbkError("GBK_MULTIPLE_MATCHES", `\u627E\u5230\u591A\u4E2A\u5339\u914D\uFFFD?: ${oldString}`);
|
|
16964
16971
|
}
|
|
16965
16972
|
const alignedNewString = alignTextToNewlineStyle(newString, newlineStyle);
|
|
16966
16973
|
return {
|
|
@@ -17065,7 +17072,7 @@ async function replaceLargeGbkFileByAnchor(input) {
|
|
|
17065
17072
|
const alreadyExists = input.mode === "insertAfter" ? after.startsWith(alignedContent) : before.endsWith(alignedContent);
|
|
17066
17073
|
if (alreadyExists) {
|
|
17067
17074
|
if (input.ifExists === "error") {
|
|
17068
|
-
throw createGbkError("GBK_INVALID_ARGUMENT", "\u63D2\u5165\u4F4D\u7F6E\u5DF2\u5B58\u5728\u76F8\u540C\u5185\uFFFD
|
|
17075
|
+
throw createGbkError("GBK_INVALID_ARGUMENT", "\u63D2\u5165\u4F4D\u7F6E\u5DF2\u5B58\u5728\u76F8\u540C\u5185\uFFFD?");
|
|
17069
17076
|
}
|
|
17070
17077
|
if (input.ifExists === "skip") {
|
|
17071
17078
|
skipped = true;
|
|
@@ -17112,7 +17119,7 @@ async function replaceLargeGbkFileByAnchor(input) {
|
|
|
17112
17119
|
const alreadyExists = input.mode === "insertAfter" ? after.startsWith(alignedContent) : before.endsWith(alignedContent);
|
|
17113
17120
|
if (alreadyExists) {
|
|
17114
17121
|
if (input.ifExists === "error") {
|
|
17115
|
-
throw createGbkError("GBK_INVALID_ARGUMENT", "\u63D2\u5165\u4F4D\u7F6E\u5DF2\u5B58\u5728\u76F8\u540C\u5185\uFFFD
|
|
17122
|
+
throw createGbkError("GBK_INVALID_ARGUMENT", "\u63D2\u5165\u4F4D\u7F6E\u5DF2\u5B58\u5728\u76F8\u540C\u5185\uFFFD?");
|
|
17116
17123
|
}
|
|
17117
17124
|
if (input.ifExists === "skip") {
|
|
17118
17125
|
skipped = true;
|
|
@@ -17126,10 +17133,10 @@ async function replaceLargeGbkFileByAnchor(input) {
|
|
|
17126
17133
|
}
|
|
17127
17134
|
}
|
|
17128
17135
|
if (!inserted && totalMatches === 0) {
|
|
17129
|
-
throw createGbkError("GBK_NO_MATCH", `\u672A\u627E\u5230\u951A\uFFFD
|
|
17136
|
+
throw createGbkError("GBK_NO_MATCH", `\u672A\u627E\u5230\u951A\uFFFD?: ${input.anchor}`);
|
|
17130
17137
|
}
|
|
17131
17138
|
if (!inserted && totalMatches > 0) {
|
|
17132
|
-
throw createGbkError("GBK_NO_MATCH", `\u951A\u70B9 ${input.anchor} \u53EA\u627E\uFFFD
|
|
17139
|
+
throw createGbkError("GBK_NO_MATCH", `\u951A\u70B9 ${input.anchor} \u53EA\u627E\uFFFD? ${totalMatches} \u5904\uFF0C\u65E0\u6CD5\u4F7F\u7528\uFFFD? ${input.occurrence} \u5904`);
|
|
17133
17140
|
}
|
|
17134
17141
|
await finalizeInserted();
|
|
17135
17142
|
await handle.close();
|
|
@@ -17192,10 +17199,10 @@ async function replaceLargeGbkFileText(input) {
|
|
|
17192
17199
|
});
|
|
17193
17200
|
await flushText("", true);
|
|
17194
17201
|
if (occurrencesBefore === 0) {
|
|
17195
|
-
throw createGbkError("GBK_NO_MATCH", `\u672A\u627E\u5230\u8981\u66FF\u6362\u7684\u5185\uFFFD
|
|
17202
|
+
throw createGbkError("GBK_NO_MATCH", `\u672A\u627E\u5230\u8981\u66FF\u6362\u7684\u5185\uFFFD?: ${input.oldString}`);
|
|
17196
17203
|
}
|
|
17197
17204
|
if (!input.replaceAll && occurrencesBefore > 1) {
|
|
17198
|
-
throw createGbkError("GBK_MULTIPLE_MATCHES", `\u627E\u5230\u591A\u4E2A\u5339\u914D\uFFFD
|
|
17205
|
+
throw createGbkError("GBK_MULTIPLE_MATCHES", `\u627E\u5230\u591A\u4E2A\u5339\u914D\uFFFD?: ${input.oldString}`);
|
|
17199
17206
|
}
|
|
17200
17207
|
await handle.close();
|
|
17201
17208
|
const mode = typeof input.stat.mode === "bigint" ? Number(input.stat.mode) : input.stat.mode;
|
|
@@ -17421,7 +17428,7 @@ async function replaceGbkFileText(input) {
|
|
|
17421
17428
|
} else if (occurrencesBefore === 0) {
|
|
17422
17429
|
throw createGbkError("GBK_NO_MATCH", buildNoMatchMessage(scope.selectedText, effectiveOldString));
|
|
17423
17430
|
} else if (occurrencesBefore > 1) {
|
|
17424
|
-
throw createGbkError("GBK_MULTIPLE_MATCHES", `\u627E\u5230\u591A\u4E2A\u5339\u914D\uFFFD
|
|
17431
|
+
throw createGbkError("GBK_MULTIPLE_MATCHES", `\u627E\u5230\u591A\u4E2A\u5339\u914D\uFFFD?: ${effectiveOldString}`);
|
|
17425
17432
|
}
|
|
17426
17433
|
const fileNewlineStyle = detectNewlineStyle(current.content);
|
|
17427
17434
|
const alignedNewString = fileNewlineStyle === "crlf" ? input.newString.replace(/\r\n/g, "\n").replace(/\n/g, "\r\n") : fileNewlineStyle === "lf" ? input.newString.replace(/\r\n/g, "\n") : input.newString;
|
|
@@ -17554,10 +17561,10 @@ async function writeGbkFile(input) {
|
|
|
17554
17561
|
try {
|
|
17555
17562
|
const stat = await fs2.stat(candidatePath);
|
|
17556
17563
|
if (stat.isDirectory()) {
|
|
17557
|
-
throw createGbkError("GBK_IS_DIRECTORY", `\u76EE\u6807\u8DEF\u5F84\u662F\u76EE\uFFFD
|
|
17564
|
+
throw createGbkError("GBK_IS_DIRECTORY", `\u76EE\u6807\u8DEF\u5F84\u662F\u76EE\uFFFD?: ${candidatePath}`);
|
|
17558
17565
|
}
|
|
17559
17566
|
if (!overwrite) {
|
|
17560
|
-
throw createGbkError("GBK_FILE_EXISTS", `\u76EE\u6807\u6587\u4EF6\u5DF2\u5B58\uFFFD
|
|
17567
|
+
throw createGbkError("GBK_FILE_EXISTS", `\u76EE\u6807\u6587\u4EF6\u5DF2\u5B58\uFFFD?: ${candidatePath}`);
|
|
17561
17568
|
}
|
|
17562
17569
|
} catch (error45) {
|
|
17563
17570
|
if (error45 instanceof Error && "code" in error45) {
|
|
@@ -17603,7 +17610,25 @@ async function writeGbkFile(input) {
|
|
|
17603
17610
|
}
|
|
17604
17611
|
}
|
|
17605
17612
|
|
|
17613
|
+
// src/lib/model-context.ts
|
|
17614
|
+
var _currentContextTokens = null;
|
|
17615
|
+
function setCurrentContextTokens(tokens) {
|
|
17616
|
+
_currentContextTokens = tokens;
|
|
17617
|
+
}
|
|
17618
|
+
function getMaxOutputChars(fallback = 8e3) {
|
|
17619
|
+
if (_currentContextTokens === null) return fallback;
|
|
17620
|
+
const computed = Math.round(_currentContextTokens * 0.01 * 4);
|
|
17621
|
+
return Math.max(4e3, Math.min(32e3, computed));
|
|
17622
|
+
}
|
|
17623
|
+
|
|
17606
17624
|
// src/tools/gbk_edit.ts
|
|
17625
|
+
function truncateToolOutput(content) {
|
|
17626
|
+
const maxChars = getMaxOutputChars();
|
|
17627
|
+
if (content.length <= maxChars) return content;
|
|
17628
|
+
const truncated = content.slice(0, maxChars);
|
|
17629
|
+
return truncated + `
|
|
17630
|
+
\x1B[2m... (\u8F93\u51FA\u5DF2\u622A\u65AD\uFF0C\u8D85\u51FA ${maxChars} \u5B57\u7B26\u4E0A\u9650)\x1B[0m`;
|
|
17631
|
+
}
|
|
17607
17632
|
var gbk_edit_default = tool({
|
|
17608
17633
|
description: `Edit GBK/GB18030 encoded text files with exact string replacement.
|
|
17609
17634
|
|
|
@@ -17673,8 +17698,8 @@ Insert mode:
|
|
|
17673
17698
|
diffPreview
|
|
17674
17699
|
}
|
|
17675
17700
|
});
|
|
17676
|
-
if (diffPreview) return diffPreview;
|
|
17677
|
-
return JSON.stringify(result, null, 2);
|
|
17701
|
+
if (diffPreview) return truncateToolOutput(diffPreview);
|
|
17702
|
+
return truncateToolOutput(JSON.stringify(result, null, 2));
|
|
17678
17703
|
}
|
|
17679
17704
|
});
|
|
17680
17705
|
|
|
@@ -18059,29 +18084,36 @@ var ANSI_RED2 = "\x1B[31m";
|
|
|
18059
18084
|
var ANSI_GREEN2 = "\x1B[32m";
|
|
18060
18085
|
var ANSI_DIM2 = "\x1B[2m";
|
|
18061
18086
|
var ANSI_RESET2 = "\x1B[0m";
|
|
18087
|
+
var MAX_DIFF_LINES2 = 80;
|
|
18062
18088
|
function buildLineDiffPreview(filePath, encoding, beforeText, afterText) {
|
|
18063
18089
|
const beforeLines = normalizeNewlines2(beforeText).split("\n");
|
|
18064
18090
|
const afterLines = normalizeNewlines2(afterText).split("\n");
|
|
18065
18091
|
const maxLines = Math.max(beforeLines.length, afterLines.length);
|
|
18066
|
-
const
|
|
18092
|
+
const header = [
|
|
18067
18093
|
`${ANSI_DIM2}--- ${path3.basename(filePath)} (${encoding})${ANSI_RESET2}`,
|
|
18068
18094
|
`${ANSI_DIM2}+++ ${path3.basename(filePath)} (${encoding})${ANSI_RESET2}`
|
|
18069
18095
|
];
|
|
18096
|
+
const body = [];
|
|
18070
18097
|
for (let index = 0; index < maxLines; index += 1) {
|
|
18071
18098
|
const before = beforeLines[index];
|
|
18072
18099
|
const after = afterLines[index];
|
|
18073
18100
|
if (before !== void 0 && after !== void 0 && before === after) {
|
|
18074
|
-
|
|
18101
|
+
body.push(` ${before}`);
|
|
18075
18102
|
continue;
|
|
18076
18103
|
}
|
|
18077
18104
|
if (before !== void 0) {
|
|
18078
|
-
|
|
18105
|
+
body.push(`${ANSI_RED2}-${before}${ANSI_RESET2}`);
|
|
18079
18106
|
}
|
|
18080
18107
|
if (after !== void 0) {
|
|
18081
|
-
|
|
18108
|
+
body.push(`${ANSI_GREEN2}+${after}${ANSI_RESET2}`);
|
|
18082
18109
|
}
|
|
18083
18110
|
}
|
|
18084
|
-
|
|
18111
|
+
if (header.length + body.length <= MAX_DIFF_LINES2) {
|
|
18112
|
+
return "\n" + [...header, ...body].join("\n");
|
|
18113
|
+
}
|
|
18114
|
+
const changedOnly = body.filter((l) => l.startsWith(ANSI_RED2) || l.startsWith(ANSI_GREEN2));
|
|
18115
|
+
const notice = `${ANSI_DIM2}... (\u4E0A\u4E0B\u6587\u5DF2\u7701\u7565\uFF0C\u4EC5\u663E\u793A\u53D8\u66F4\u884C)${ANSI_RESET2}`;
|
|
18116
|
+
return "\n" + [...header, notice, ...changedOnly].join("\n");
|
|
18085
18117
|
}
|
|
18086
18118
|
function buildInsertOutput(text, mode, anchor, content, occurrence, ifExists, newlineStyle) {
|
|
18087
18119
|
const alignedContent = alignTextToNewlineStyle2(content, newlineStyle);
|
|
@@ -18728,11 +18760,18 @@ async function replaceTextFileText(input) {
|
|
|
18728
18760
|
bytesRead: loaded.bytesRead,
|
|
18729
18761
|
bytesWritten: buffer.byteLength,
|
|
18730
18762
|
newlineStyle: detectNewlineStyle(outputText),
|
|
18731
|
-
diffPreview: buildLineDiffPreview(loaded.filePath, targetEncoding,
|
|
18763
|
+
diffPreview: buildLineDiffPreview(loaded.filePath, targetEncoding, input.oldString, alignedNewString)
|
|
18732
18764
|
};
|
|
18733
18765
|
}
|
|
18734
18766
|
|
|
18735
18767
|
// src/tools/text_edit.ts
|
|
18768
|
+
function truncateToolOutput2(content) {
|
|
18769
|
+
const maxChars = getMaxOutputChars();
|
|
18770
|
+
if (content.length <= maxChars) return content;
|
|
18771
|
+
const truncated = content.slice(0, maxChars);
|
|
18772
|
+
return truncated + `
|
|
18773
|
+
\x1B[2m... (\u8F93\u51FA\u5DF2\u622A\u65AD\uFF0C\u8D85\u51FA ${maxChars} \u5B57\u7B26\u4E0A\u9650)\x1B[0m`;
|
|
18774
|
+
}
|
|
18736
18775
|
var text_edit_default = tool({
|
|
18737
18776
|
description: `Edit text files with automatic encoding detection and preservation.
|
|
18738
18777
|
|
|
@@ -18783,8 +18822,8 @@ var text_edit_default = tool({
|
|
|
18783
18822
|
diffPreview
|
|
18784
18823
|
}
|
|
18785
18824
|
});
|
|
18786
|
-
if (diffPreview) return diffPreview;
|
|
18787
|
-
return JSON.stringify(result, null, 2);
|
|
18825
|
+
if (diffPreview) return truncateToolOutput2(diffPreview);
|
|
18826
|
+
return truncateToolOutput2(JSON.stringify(result, null, 2));
|
|
18788
18827
|
}
|
|
18789
18828
|
});
|
|
18790
18829
|
|
|
@@ -18876,6 +18915,12 @@ function createOpencodeGbkHooks() {
|
|
|
18876
18915
|
text_write: text_write_default,
|
|
18877
18916
|
text_edit: text_edit_default
|
|
18878
18917
|
},
|
|
18918
|
+
async "chat.params"(input) {
|
|
18919
|
+
const contextTokens = input.model?.limit?.context;
|
|
18920
|
+
if (typeof contextTokens === "number" && contextTokens > 0) {
|
|
18921
|
+
setCurrentContextTokens(contextTokens);
|
|
18922
|
+
}
|
|
18923
|
+
},
|
|
18879
18924
|
async "experimental.chat.system.transform"(_input, output) {
|
|
18880
18925
|
appendTextToolSystemPrompt(output.system);
|
|
18881
18926
|
}
|
|
@@ -16312,29 +16312,36 @@ var ANSI_RED = "\x1B[31m";
|
|
|
16312
16312
|
var ANSI_GREEN = "\x1B[32m";
|
|
16313
16313
|
var ANSI_DIM = "\x1B[2m";
|
|
16314
16314
|
var ANSI_RESET = "\x1B[0m";
|
|
16315
|
+
var MAX_DIFF_LINES = 80;
|
|
16315
16316
|
function buildGbkLineDiffPreview(filePath, encoding, beforeText, afterText) {
|
|
16316
16317
|
const beforeLines = normalizeNewlines(beforeText).split("\n");
|
|
16317
16318
|
const afterLines = normalizeNewlines(afterText).split("\n");
|
|
16318
16319
|
const maxLines = Math.max(beforeLines.length, afterLines.length);
|
|
16319
|
-
const
|
|
16320
|
+
const header = [
|
|
16320
16321
|
`${ANSI_DIM}--- ${path2.basename(filePath)} (${encoding})${ANSI_RESET}`,
|
|
16321
16322
|
`${ANSI_DIM}+++ ${path2.basename(filePath)} (${encoding})${ANSI_RESET}`
|
|
16322
16323
|
];
|
|
16324
|
+
const body = [];
|
|
16323
16325
|
for (let index = 0; index < maxLines; index += 1) {
|
|
16324
16326
|
const before = beforeLines[index];
|
|
16325
16327
|
const after = afterLines[index];
|
|
16326
16328
|
if (before !== void 0 && after !== void 0 && before === after) {
|
|
16327
|
-
|
|
16329
|
+
body.push(` ${before}`);
|
|
16328
16330
|
continue;
|
|
16329
16331
|
}
|
|
16330
16332
|
if (before !== void 0) {
|
|
16331
|
-
|
|
16333
|
+
body.push(`${ANSI_RED}-${before}${ANSI_RESET}`);
|
|
16332
16334
|
}
|
|
16333
16335
|
if (after !== void 0) {
|
|
16334
|
-
|
|
16336
|
+
body.push(`${ANSI_GREEN}+${after}${ANSI_RESET}`);
|
|
16335
16337
|
}
|
|
16336
16338
|
}
|
|
16337
|
-
|
|
16339
|
+
if (header.length + body.length <= MAX_DIFF_LINES) {
|
|
16340
|
+
return "\n" + [...header, ...body].join("\n");
|
|
16341
|
+
}
|
|
16342
|
+
const changedOnly = body.filter((l) => l.startsWith(ANSI_RED) || l.startsWith(ANSI_GREEN));
|
|
16343
|
+
const notice = `${ANSI_DIM}... (\u4E0A\u4E0B\u6587\u5DF2\u7701\u7565\uFF0C\u4EC5\u663E\u793A\u53D8\u66F4\u884C)${ANSI_RESET}`;
|
|
16344
|
+
return "\n" + [...header, notice, ...changedOnly].join("\n");
|
|
16338
16345
|
}
|
|
16339
16346
|
function toSafeNumber(value) {
|
|
16340
16347
|
return typeof value === "bigint" ? Number(value) : value;
|
|
@@ -16358,10 +16365,10 @@ function assertInsertArguments(input) {
|
|
|
16358
16365
|
throw createGbkError("GBK_INVALID_ARGUMENT", "content \u4E0D\u80FD\u4E3A\u7A7A");
|
|
16359
16366
|
}
|
|
16360
16367
|
if (input.replaceAll !== void 0) {
|
|
16361
|
-
throw createGbkError("GBK_INVALID_ARGUMENT", "\u63D2\u5165\u6A21\u5F0F\u4E0D\u652F\uFFFD
|
|
16368
|
+
throw createGbkError("GBK_INVALID_ARGUMENT", "\u63D2\u5165\u6A21\u5F0F\u4E0D\u652F\uFFFD? replaceAll");
|
|
16362
16369
|
}
|
|
16363
16370
|
if (input.startLine !== void 0 || input.endLine !== void 0 || input.startAnchor !== void 0 || input.endAnchor !== void 0) {
|
|
16364
|
-
throw createGbkError("GBK_INVALID_ARGUMENT", "\u63D2\u5165\u6A21\u5F0F\u4E0D\u652F\uFFFD
|
|
16371
|
+
throw createGbkError("GBK_INVALID_ARGUMENT", "\u63D2\u5165\u6A21\u5F0F\u4E0D\u652F\uFFFD? startLine/endLine/startAnchor/endAnchor");
|
|
16365
16372
|
}
|
|
16366
16373
|
}
|
|
16367
16374
|
function findOccurrenceIndex(text, token, occurrence) {
|
|
@@ -16385,9 +16392,9 @@ function findOccurrenceIndex(text, token, occurrence) {
|
|
|
16385
16392
|
searchFrom = index + token.length;
|
|
16386
16393
|
}
|
|
16387
16394
|
if (count === 0) {
|
|
16388
|
-
throw createGbkError("GBK_NO_MATCH", `\u672A\u627E\u5230\u951A\uFFFD
|
|
16395
|
+
throw createGbkError("GBK_NO_MATCH", `\u672A\u627E\u5230\u951A\uFFFD?: ${token}`);
|
|
16389
16396
|
}
|
|
16390
|
-
throw createGbkError("GBK_NO_MATCH", `\u951A\u70B9 ${token} \u53EA\u627E\uFFFD
|
|
16397
|
+
throw createGbkError("GBK_NO_MATCH", `\u951A\u70B9 ${token} \u53EA\u627E\uFFFD? ${count} \u5904\uFF0C\u65E0\u6CD5\u4F7F\u7528\uFFFD? ${occurrence} \u5904`);
|
|
16391
16398
|
}
|
|
16392
16399
|
function insertByAnchor(text, mode, anchor, content, occurrence, ifExists, newlineStyle) {
|
|
16393
16400
|
const alignedContent = newlineStyle === "crlf" ? content.replace(/\r\n/g, "\n").replace(/\n/g, "\r\n") : newlineStyle === "lf" ? content.replace(/\r\n/g, "\n") : content;
|
|
@@ -16396,7 +16403,7 @@ function insertByAnchor(text, mode, anchor, content, occurrence, ifExists, newli
|
|
|
16396
16403
|
const alreadyExists = mode === "insertAfter" ? text.slice(insertionPoint, insertionPoint + alignedContent.length) === alignedContent : text.slice(Math.max(0, insertionPoint - alignedContent.length), insertionPoint) === alignedContent;
|
|
16397
16404
|
if (alreadyExists) {
|
|
16398
16405
|
if (ifExists === "error") {
|
|
16399
|
-
throw createGbkError("GBK_INVALID_ARGUMENT", "\u63D2\u5165\u4F4D\u7F6E\u5DF2\u5B58\u5728\u76F8\u540C\u5185\uFFFD
|
|
16406
|
+
throw createGbkError("GBK_INVALID_ARGUMENT", "\u63D2\u5165\u4F4D\u7F6E\u5DF2\u5B58\u5728\u76F8\u540C\u5185\uFFFD?");
|
|
16400
16407
|
}
|
|
16401
16408
|
if (ifExists === "skip") {
|
|
16402
16409
|
return {
|
|
@@ -16437,7 +16444,7 @@ function normalizeOptionalPositiveInteger(value, name) {
|
|
|
16437
16444
|
}
|
|
16438
16445
|
function assertNotBinary(buffer) {
|
|
16439
16446
|
if (buffer.includes(0)) {
|
|
16440
|
-
throw createGbkError("GBK_BINARY_FILE", "\u7591\u4F3C\u4E8C\u8FDB\u5236\u6587\u4EF6\uFF0C\u65E0\u6CD5\uFFFD
|
|
16447
|
+
throw createGbkError("GBK_BINARY_FILE", "\u7591\u4F3C\u4E8C\u8FDB\u5236\u6587\u4EF6\uFF0C\u65E0\u6CD5\uFFFD? GBK \u6587\u672C\u5904\u7406");
|
|
16441
16448
|
}
|
|
16442
16449
|
}
|
|
16443
16450
|
function splitLinesWithNumbers(text, offset = 1, limit = 2e3) {
|
|
@@ -16567,14 +16574,14 @@ function applyAnchors(text, startAnchor, endAnchor) {
|
|
|
16567
16574
|
if (startAnchor) {
|
|
16568
16575
|
const found = text.indexOf(startAnchor);
|
|
16569
16576
|
if (found === -1) {
|
|
16570
|
-
throw createGbkError("GBK_NO_MATCH", `\u672A\u627E\u5230\u8D77\u59CB\u951A\uFFFD
|
|
16577
|
+
throw createGbkError("GBK_NO_MATCH", `\u672A\u627E\u5230\u8D77\u59CB\u951A\uFFFD?: ${startAnchor}`);
|
|
16571
16578
|
}
|
|
16572
16579
|
rangeStart = found + startAnchor.length;
|
|
16573
16580
|
}
|
|
16574
16581
|
if (endAnchor) {
|
|
16575
16582
|
const found = text.indexOf(endAnchor, rangeStart);
|
|
16576
16583
|
if (found === -1) {
|
|
16577
|
-
throw createGbkError("GBK_NO_MATCH", `\u672A\u627E\u5230\u7ED3\u675F\u951A\uFFFD
|
|
16584
|
+
throw createGbkError("GBK_NO_MATCH", `\u672A\u627E\u5230\u7ED3\u675F\u951A\uFFFD?: ${endAnchor}`);
|
|
16578
16585
|
}
|
|
16579
16586
|
rangeEnd = found;
|
|
16580
16587
|
}
|
|
@@ -16627,9 +16634,9 @@ function getNearestContext(content, oldString) {
|
|
|
16627
16634
|
}
|
|
16628
16635
|
function buildNoMatchMessage(content, oldString) {
|
|
16629
16636
|
return [
|
|
16630
|
-
"\u672A\u627E\u5230\u9700\u8981\u66FF\u6362\u7684\u6587\u672C\uFFFD
|
|
16631
|
-
"oldString \u5FC5\u987B\u4E0E\u6587\u4EF6\u5B9E\u9645\u5185\u5BB9\u5B8C\u5168\u5BF9\u5E94\uFF0C\u6216\u4EC5\u5728\u6362\uFFFD
|
|
16632
|
-
"\u6700\u63A5\u8FD1\u7684\u4E0A\u4E0B\u6587\uFFFD
|
|
16637
|
+
"\u672A\u627E\u5230\u9700\u8981\u66FF\u6362\u7684\u6587\u672C\uFFFD?",
|
|
16638
|
+
"oldString \u5FC5\u987B\u4E0E\u6587\u4EF6\u5B9E\u9645\u5185\u5BB9\u5B8C\u5168\u5BF9\u5E94\uFF0C\u6216\u4EC5\u5728\u6362\uFFFD?/\u5C3E\u968F\u7A7A\u884C\u4E0A\u5B58\u5728\u8F7B\u5FAE\u5DEE\u5F02\uFFFD?",
|
|
16639
|
+
"\u6700\u63A5\u8FD1\u7684\u4E0A\u4E0B\u6587\uFFFD?",
|
|
16633
16640
|
getNearestContext(content, oldString)
|
|
16634
16641
|
].join("\n");
|
|
16635
16642
|
}
|
|
@@ -16752,10 +16759,10 @@ async function resolveReadableGbkFile(input) {
|
|
|
16752
16759
|
try {
|
|
16753
16760
|
stat = await fs2.stat(candidatePath);
|
|
16754
16761
|
} catch (error45) {
|
|
16755
|
-
throw createGbkError("GBK_FILE_NOT_FOUND", `\u6587\u4EF6\u4E0D\u5B58\uFFFD
|
|
16762
|
+
throw createGbkError("GBK_FILE_NOT_FOUND", `\u6587\u4EF6\u4E0D\u5B58\uFFFD?: ${candidatePath}`, error45);
|
|
16756
16763
|
}
|
|
16757
16764
|
if (stat.isDirectory()) {
|
|
16758
|
-
throw createGbkError("GBK_IS_DIRECTORY", `\u76EE\u6807\u8DEF\u5F84\u662F\u76EE\uFFFD
|
|
16765
|
+
throw createGbkError("GBK_IS_DIRECTORY", `\u76EE\u6807\u8DEF\u5F84\u662F\u76EE\uFFFD?: ${candidatePath}`);
|
|
16759
16766
|
}
|
|
16760
16767
|
return {
|
|
16761
16768
|
filePath: candidatePath,
|
|
@@ -16960,7 +16967,7 @@ function replaceScopedTextContent(scopeText, oldString, newString, replaceAll, n
|
|
|
16960
16967
|
} else if (occurrencesBefore === 0) {
|
|
16961
16968
|
throw createGbkError("GBK_NO_MATCH", buildNoMatchMessage(scopeText, oldString));
|
|
16962
16969
|
} else if (occurrencesBefore > 1) {
|
|
16963
|
-
throw createGbkError("GBK_MULTIPLE_MATCHES", `\u627E\u5230\u591A\u4E2A\u5339\u914D\uFFFD
|
|
16970
|
+
throw createGbkError("GBK_MULTIPLE_MATCHES", `\u627E\u5230\u591A\u4E2A\u5339\u914D\uFFFD?: ${oldString}`);
|
|
16964
16971
|
}
|
|
16965
16972
|
const alignedNewString = alignTextToNewlineStyle(newString, newlineStyle);
|
|
16966
16973
|
return {
|
|
@@ -17065,7 +17072,7 @@ async function replaceLargeGbkFileByAnchor(input) {
|
|
|
17065
17072
|
const alreadyExists = input.mode === "insertAfter" ? after.startsWith(alignedContent) : before.endsWith(alignedContent);
|
|
17066
17073
|
if (alreadyExists) {
|
|
17067
17074
|
if (input.ifExists === "error") {
|
|
17068
|
-
throw createGbkError("GBK_INVALID_ARGUMENT", "\u63D2\u5165\u4F4D\u7F6E\u5DF2\u5B58\u5728\u76F8\u540C\u5185\uFFFD
|
|
17075
|
+
throw createGbkError("GBK_INVALID_ARGUMENT", "\u63D2\u5165\u4F4D\u7F6E\u5DF2\u5B58\u5728\u76F8\u540C\u5185\uFFFD?");
|
|
17069
17076
|
}
|
|
17070
17077
|
if (input.ifExists === "skip") {
|
|
17071
17078
|
skipped = true;
|
|
@@ -17112,7 +17119,7 @@ async function replaceLargeGbkFileByAnchor(input) {
|
|
|
17112
17119
|
const alreadyExists = input.mode === "insertAfter" ? after.startsWith(alignedContent) : before.endsWith(alignedContent);
|
|
17113
17120
|
if (alreadyExists) {
|
|
17114
17121
|
if (input.ifExists === "error") {
|
|
17115
|
-
throw createGbkError("GBK_INVALID_ARGUMENT", "\u63D2\u5165\u4F4D\u7F6E\u5DF2\u5B58\u5728\u76F8\u540C\u5185\uFFFD
|
|
17122
|
+
throw createGbkError("GBK_INVALID_ARGUMENT", "\u63D2\u5165\u4F4D\u7F6E\u5DF2\u5B58\u5728\u76F8\u540C\u5185\uFFFD?");
|
|
17116
17123
|
}
|
|
17117
17124
|
if (input.ifExists === "skip") {
|
|
17118
17125
|
skipped = true;
|
|
@@ -17126,10 +17133,10 @@ async function replaceLargeGbkFileByAnchor(input) {
|
|
|
17126
17133
|
}
|
|
17127
17134
|
}
|
|
17128
17135
|
if (!inserted && totalMatches === 0) {
|
|
17129
|
-
throw createGbkError("GBK_NO_MATCH", `\u672A\u627E\u5230\u951A\uFFFD
|
|
17136
|
+
throw createGbkError("GBK_NO_MATCH", `\u672A\u627E\u5230\u951A\uFFFD?: ${input.anchor}`);
|
|
17130
17137
|
}
|
|
17131
17138
|
if (!inserted && totalMatches > 0) {
|
|
17132
|
-
throw createGbkError("GBK_NO_MATCH", `\u951A\u70B9 ${input.anchor} \u53EA\u627E\uFFFD
|
|
17139
|
+
throw createGbkError("GBK_NO_MATCH", `\u951A\u70B9 ${input.anchor} \u53EA\u627E\uFFFD? ${totalMatches} \u5904\uFF0C\u65E0\u6CD5\u4F7F\u7528\uFFFD? ${input.occurrence} \u5904`);
|
|
17133
17140
|
}
|
|
17134
17141
|
await finalizeInserted();
|
|
17135
17142
|
await handle.close();
|
|
@@ -17192,10 +17199,10 @@ async function replaceLargeGbkFileText(input) {
|
|
|
17192
17199
|
});
|
|
17193
17200
|
await flushText("", true);
|
|
17194
17201
|
if (occurrencesBefore === 0) {
|
|
17195
|
-
throw createGbkError("GBK_NO_MATCH", `\u672A\u627E\u5230\u8981\u66FF\u6362\u7684\u5185\uFFFD
|
|
17202
|
+
throw createGbkError("GBK_NO_MATCH", `\u672A\u627E\u5230\u8981\u66FF\u6362\u7684\u5185\uFFFD?: ${input.oldString}`);
|
|
17196
17203
|
}
|
|
17197
17204
|
if (!input.replaceAll && occurrencesBefore > 1) {
|
|
17198
|
-
throw createGbkError("GBK_MULTIPLE_MATCHES", `\u627E\u5230\u591A\u4E2A\u5339\u914D\uFFFD
|
|
17205
|
+
throw createGbkError("GBK_MULTIPLE_MATCHES", `\u627E\u5230\u591A\u4E2A\u5339\u914D\uFFFD?: ${input.oldString}`);
|
|
17199
17206
|
}
|
|
17200
17207
|
await handle.close();
|
|
17201
17208
|
const mode = typeof input.stat.mode === "bigint" ? Number(input.stat.mode) : input.stat.mode;
|
|
@@ -17421,7 +17428,7 @@ async function replaceGbkFileText(input) {
|
|
|
17421
17428
|
} else if (occurrencesBefore === 0) {
|
|
17422
17429
|
throw createGbkError("GBK_NO_MATCH", buildNoMatchMessage(scope.selectedText, effectiveOldString));
|
|
17423
17430
|
} else if (occurrencesBefore > 1) {
|
|
17424
|
-
throw createGbkError("GBK_MULTIPLE_MATCHES", `\u627E\u5230\u591A\u4E2A\u5339\u914D\uFFFD
|
|
17431
|
+
throw createGbkError("GBK_MULTIPLE_MATCHES", `\u627E\u5230\u591A\u4E2A\u5339\u914D\uFFFD?: ${effectiveOldString}`);
|
|
17425
17432
|
}
|
|
17426
17433
|
const fileNewlineStyle = detectNewlineStyle(current.content);
|
|
17427
17434
|
const alignedNewString = fileNewlineStyle === "crlf" ? input.newString.replace(/\r\n/g, "\n").replace(/\n/g, "\r\n") : fileNewlineStyle === "lf" ? input.newString.replace(/\r\n/g, "\n") : input.newString;
|
|
@@ -17554,10 +17561,10 @@ async function writeGbkFile(input) {
|
|
|
17554
17561
|
try {
|
|
17555
17562
|
const stat = await fs2.stat(candidatePath);
|
|
17556
17563
|
if (stat.isDirectory()) {
|
|
17557
|
-
throw createGbkError("GBK_IS_DIRECTORY", `\u76EE\u6807\u8DEF\u5F84\u662F\u76EE\uFFFD
|
|
17564
|
+
throw createGbkError("GBK_IS_DIRECTORY", `\u76EE\u6807\u8DEF\u5F84\u662F\u76EE\uFFFD?: ${candidatePath}`);
|
|
17558
17565
|
}
|
|
17559
17566
|
if (!overwrite) {
|
|
17560
|
-
throw createGbkError("GBK_FILE_EXISTS", `\u76EE\u6807\u6587\u4EF6\u5DF2\u5B58\uFFFD
|
|
17567
|
+
throw createGbkError("GBK_FILE_EXISTS", `\u76EE\u6807\u6587\u4EF6\u5DF2\u5B58\uFFFD?: ${candidatePath}`);
|
|
17561
17568
|
}
|
|
17562
17569
|
} catch (error45) {
|
|
17563
17570
|
if (error45 instanceof Error && "code" in error45) {
|
|
@@ -17603,7 +17610,25 @@ async function writeGbkFile(input) {
|
|
|
17603
17610
|
}
|
|
17604
17611
|
}
|
|
17605
17612
|
|
|
17613
|
+
// src/lib/model-context.ts
|
|
17614
|
+
var _currentContextTokens = null;
|
|
17615
|
+
function setCurrentContextTokens(tokens) {
|
|
17616
|
+
_currentContextTokens = tokens;
|
|
17617
|
+
}
|
|
17618
|
+
function getMaxOutputChars(fallback = 8e3) {
|
|
17619
|
+
if (_currentContextTokens === null) return fallback;
|
|
17620
|
+
const computed = Math.round(_currentContextTokens * 0.01 * 4);
|
|
17621
|
+
return Math.max(4e3, Math.min(32e3, computed));
|
|
17622
|
+
}
|
|
17623
|
+
|
|
17606
17624
|
// src/tools/gbk_edit.ts
|
|
17625
|
+
function truncateToolOutput(content) {
|
|
17626
|
+
const maxChars = getMaxOutputChars();
|
|
17627
|
+
if (content.length <= maxChars) return content;
|
|
17628
|
+
const truncated = content.slice(0, maxChars);
|
|
17629
|
+
return truncated + `
|
|
17630
|
+
\x1B[2m... (\u8F93\u51FA\u5DF2\u622A\u65AD\uFF0C\u8D85\u51FA ${maxChars} \u5B57\u7B26\u4E0A\u9650)\x1B[0m`;
|
|
17631
|
+
}
|
|
17607
17632
|
var gbk_edit_default = tool({
|
|
17608
17633
|
description: `Edit GBK/GB18030 encoded text files with exact string replacement.
|
|
17609
17634
|
|
|
@@ -17673,8 +17698,8 @@ Insert mode:
|
|
|
17673
17698
|
diffPreview
|
|
17674
17699
|
}
|
|
17675
17700
|
});
|
|
17676
|
-
if (diffPreview) return diffPreview;
|
|
17677
|
-
return JSON.stringify(result, null, 2);
|
|
17701
|
+
if (diffPreview) return truncateToolOutput(diffPreview);
|
|
17702
|
+
return truncateToolOutput(JSON.stringify(result, null, 2));
|
|
17678
17703
|
}
|
|
17679
17704
|
});
|
|
17680
17705
|
|
|
@@ -18059,29 +18084,36 @@ var ANSI_RED2 = "\x1B[31m";
|
|
|
18059
18084
|
var ANSI_GREEN2 = "\x1B[32m";
|
|
18060
18085
|
var ANSI_DIM2 = "\x1B[2m";
|
|
18061
18086
|
var ANSI_RESET2 = "\x1B[0m";
|
|
18087
|
+
var MAX_DIFF_LINES2 = 80;
|
|
18062
18088
|
function buildLineDiffPreview(filePath, encoding, beforeText, afterText) {
|
|
18063
18089
|
const beforeLines = normalizeNewlines2(beforeText).split("\n");
|
|
18064
18090
|
const afterLines = normalizeNewlines2(afterText).split("\n");
|
|
18065
18091
|
const maxLines = Math.max(beforeLines.length, afterLines.length);
|
|
18066
|
-
const
|
|
18092
|
+
const header = [
|
|
18067
18093
|
`${ANSI_DIM2}--- ${path3.basename(filePath)} (${encoding})${ANSI_RESET2}`,
|
|
18068
18094
|
`${ANSI_DIM2}+++ ${path3.basename(filePath)} (${encoding})${ANSI_RESET2}`
|
|
18069
18095
|
];
|
|
18096
|
+
const body = [];
|
|
18070
18097
|
for (let index = 0; index < maxLines; index += 1) {
|
|
18071
18098
|
const before = beforeLines[index];
|
|
18072
18099
|
const after = afterLines[index];
|
|
18073
18100
|
if (before !== void 0 && after !== void 0 && before === after) {
|
|
18074
|
-
|
|
18101
|
+
body.push(` ${before}`);
|
|
18075
18102
|
continue;
|
|
18076
18103
|
}
|
|
18077
18104
|
if (before !== void 0) {
|
|
18078
|
-
|
|
18105
|
+
body.push(`${ANSI_RED2}-${before}${ANSI_RESET2}`);
|
|
18079
18106
|
}
|
|
18080
18107
|
if (after !== void 0) {
|
|
18081
|
-
|
|
18108
|
+
body.push(`${ANSI_GREEN2}+${after}${ANSI_RESET2}`);
|
|
18082
18109
|
}
|
|
18083
18110
|
}
|
|
18084
|
-
|
|
18111
|
+
if (header.length + body.length <= MAX_DIFF_LINES2) {
|
|
18112
|
+
return "\n" + [...header, ...body].join("\n");
|
|
18113
|
+
}
|
|
18114
|
+
const changedOnly = body.filter((l) => l.startsWith(ANSI_RED2) || l.startsWith(ANSI_GREEN2));
|
|
18115
|
+
const notice = `${ANSI_DIM2}... (\u4E0A\u4E0B\u6587\u5DF2\u7701\u7565\uFF0C\u4EC5\u663E\u793A\u53D8\u66F4\u884C)${ANSI_RESET2}`;
|
|
18116
|
+
return "\n" + [...header, notice, ...changedOnly].join("\n");
|
|
18085
18117
|
}
|
|
18086
18118
|
function buildInsertOutput(text, mode, anchor, content, occurrence, ifExists, newlineStyle) {
|
|
18087
18119
|
const alignedContent = alignTextToNewlineStyle2(content, newlineStyle);
|
|
@@ -18728,11 +18760,18 @@ async function replaceTextFileText(input) {
|
|
|
18728
18760
|
bytesRead: loaded.bytesRead,
|
|
18729
18761
|
bytesWritten: buffer.byteLength,
|
|
18730
18762
|
newlineStyle: detectNewlineStyle(outputText),
|
|
18731
|
-
diffPreview: buildLineDiffPreview(loaded.filePath, targetEncoding,
|
|
18763
|
+
diffPreview: buildLineDiffPreview(loaded.filePath, targetEncoding, input.oldString, alignedNewString)
|
|
18732
18764
|
};
|
|
18733
18765
|
}
|
|
18734
18766
|
|
|
18735
18767
|
// src/tools/text_edit.ts
|
|
18768
|
+
function truncateToolOutput2(content) {
|
|
18769
|
+
const maxChars = getMaxOutputChars();
|
|
18770
|
+
if (content.length <= maxChars) return content;
|
|
18771
|
+
const truncated = content.slice(0, maxChars);
|
|
18772
|
+
return truncated + `
|
|
18773
|
+
\x1B[2m... (\u8F93\u51FA\u5DF2\u622A\u65AD\uFF0C\u8D85\u51FA ${maxChars} \u5B57\u7B26\u4E0A\u9650)\x1B[0m`;
|
|
18774
|
+
}
|
|
18736
18775
|
var text_edit_default = tool({
|
|
18737
18776
|
description: `Edit text files with automatic encoding detection and preservation.
|
|
18738
18777
|
|
|
@@ -18783,8 +18822,8 @@ var text_edit_default = tool({
|
|
|
18783
18822
|
diffPreview
|
|
18784
18823
|
}
|
|
18785
18824
|
});
|
|
18786
|
-
if (diffPreview) return diffPreview;
|
|
18787
|
-
return JSON.stringify(result, null, 2);
|
|
18825
|
+
if (diffPreview) return truncateToolOutput2(diffPreview);
|
|
18826
|
+
return truncateToolOutput2(JSON.stringify(result, null, 2));
|
|
18788
18827
|
}
|
|
18789
18828
|
});
|
|
18790
18829
|
|
|
@@ -18876,6 +18915,12 @@ function createOpencodeGbkHooks() {
|
|
|
18876
18915
|
text_write: text_write_default,
|
|
18877
18916
|
text_edit: text_edit_default
|
|
18878
18917
|
},
|
|
18918
|
+
async "chat.params"(input) {
|
|
18919
|
+
const contextTokens = input.model?.limit?.context;
|
|
18920
|
+
if (typeof contextTokens === "number" && contextTokens > 0) {
|
|
18921
|
+
setCurrentContextTokens(contextTokens);
|
|
18922
|
+
}
|
|
18923
|
+
},
|
|
18879
18924
|
async "experimental.chat.system.transform"(_input, output) {
|
|
18880
18925
|
appendTextToolSystemPrompt(output.system);
|
|
18881
18926
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifestVersion": 1,
|
|
3
3
|
"packageName": "opencode-gbk-tools",
|
|
4
|
-
"packageVersion": "0.1.
|
|
4
|
+
"packageVersion": "0.1.23",
|
|
5
5
|
"artifacts": [
|
|
6
6
|
{
|
|
7
7
|
"relativePath": "plugins/opencode-gbk-tools.js",
|
|
8
8
|
"kind": "plugin",
|
|
9
|
-
"expectedHash": "
|
|
9
|
+
"expectedHash": "28e00665097934ea390c85f9a991f9074f77d31ff7ffe6f118035e834b911d2d",
|
|
10
10
|
"hashAlgorithm": "sha256"
|
|
11
11
|
}
|
|
12
12
|
]
|