opencode-gbk-tools 0.1.9 → 0.1.10

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.
@@ -182,7 +182,7 @@ var require_internal = __commonJS({
182
182
  // Codec.
183
183
  _internal: InternalCodec
184
184
  };
185
- function InternalCodec(codecOptions, iconv2) {
185
+ function InternalCodec(codecOptions, iconv3) {
186
186
  this.enc = codecOptions.encodingName;
187
187
  this.bomAware = codecOptions.bomAware;
188
188
  if (this.enc === "base64") {
@@ -194,7 +194,7 @@ var require_internal = __commonJS({
194
194
  this.encoder = InternalEncoderCesu8;
195
195
  if (Buffer2.from("eda0bdedb2a9", "hex").toString() !== "\u{1F4A9}") {
196
196
  this.decoder = InternalDecoderCesu8;
197
- this.defaultCharUnicode = iconv2.defaultCharUnicode;
197
+ this.defaultCharUnicode = iconv3.defaultCharUnicode;
198
198
  }
199
199
  }
200
200
  }
@@ -351,8 +351,8 @@ var require_utf32 = __commonJS({
351
351
  "use strict";
352
352
  var Buffer2 = require_safer().Buffer;
353
353
  exports._utf32 = Utf32Codec;
354
- function Utf32Codec(codecOptions, iconv2) {
355
- this.iconv = iconv2;
354
+ function Utf32Codec(codecOptions, iconv3) {
355
+ this.iconv = iconv3;
356
356
  this.bomAware = true;
357
357
  this.isLE = codecOptions.isLE;
358
358
  }
@@ -476,8 +476,8 @@ var require_utf32 = __commonJS({
476
476
  };
477
477
  exports.utf32 = Utf32AutoCodec;
478
478
  exports.ucs4 = "utf32";
479
- function Utf32AutoCodec(options, iconv2) {
480
- this.iconv = iconv2;
479
+ function Utf32AutoCodec(options, iconv3) {
480
+ this.iconv = iconv3;
481
481
  }
482
482
  Utf32AutoCodec.prototype.encoder = Utf32AutoEncoder;
483
483
  Utf32AutoCodec.prototype.decoder = Utf32AutoDecoder;
@@ -627,8 +627,8 @@ var require_utf16 = __commonJS({
627
627
  this.overflowByte = -1;
628
628
  };
629
629
  exports.utf16 = Utf16Codec;
630
- function Utf16Codec(codecOptions, iconv2) {
631
- this.iconv = iconv2;
630
+ function Utf16Codec(codecOptions, iconv3) {
631
+ this.iconv = iconv3;
632
632
  }
633
633
  Utf16Codec.prototype.encoder = Utf16Encoder;
634
634
  Utf16Codec.prototype.decoder = Utf16Decoder;
@@ -726,8 +726,8 @@ var require_utf7 = __commonJS({
726
726
  var Buffer2 = require_safer().Buffer;
727
727
  exports.utf7 = Utf7Codec;
728
728
  exports.unicode11utf7 = "utf7";
729
- function Utf7Codec(codecOptions, iconv2) {
730
- this.iconv = iconv2;
729
+ function Utf7Codec(codecOptions, iconv3) {
730
+ this.iconv = iconv3;
731
731
  }
732
732
  Utf7Codec.prototype.encoder = Utf7Encoder;
733
733
  Utf7Codec.prototype.decoder = Utf7Decoder;
@@ -809,8 +809,8 @@ var require_utf7 = __commonJS({
809
809
  return res;
810
810
  };
811
811
  exports.utf7imap = Utf7IMAPCodec;
812
- function Utf7IMAPCodec(codecOptions, iconv2) {
813
- this.iconv = iconv2;
812
+ function Utf7IMAPCodec(codecOptions, iconv3) {
813
+ this.iconv = iconv3;
814
814
  }
815
815
  Utf7IMAPCodec.prototype.encoder = Utf7IMAPEncoder;
816
816
  Utf7IMAPCodec.prototype.decoder = Utf7IMAPDecoder;
@@ -943,7 +943,7 @@ var require_sbcs_codec = __commonJS({
943
943
  "use strict";
944
944
  var Buffer2 = require_safer().Buffer;
945
945
  exports._sbcs = SBCSCodec;
946
- function SBCSCodec(codecOptions, iconv2) {
946
+ function SBCSCodec(codecOptions, iconv3) {
947
947
  if (!codecOptions) {
948
948
  throw new Error("SBCS codec is called without the data.");
949
949
  }
@@ -958,7 +958,7 @@ var require_sbcs_codec = __commonJS({
958
958
  codecOptions.chars = asciiString + codecOptions.chars;
959
959
  }
960
960
  this.decodeBuf = Buffer2.from(codecOptions.chars, "ucs2");
961
- var encodeBuf = Buffer2.alloc(65536, iconv2.defaultCharSingleByte.charCodeAt(0));
961
+ var encodeBuf = Buffer2.alloc(65536, iconv3.defaultCharSingleByte.charCodeAt(0));
962
962
  for (var i = 0; i < codecOptions.chars.length; i++) {
963
963
  encodeBuf[codecOptions.chars.charCodeAt(i)] = i;
964
964
  }
@@ -1623,7 +1623,7 @@ var require_dbcs_codec = __commonJS({
1623
1623
  UNASSIGNED_NODE[i] = UNASSIGNED;
1624
1624
  }
1625
1625
  var i;
1626
- function DBCSCodec(codecOptions, iconv2) {
1626
+ function DBCSCodec(codecOptions, iconv3) {
1627
1627
  this.encodingName = codecOptions.encodingName;
1628
1628
  if (!codecOptions) {
1629
1629
  throw new Error("DBCS codec is called without the data.");
@@ -1672,7 +1672,7 @@ var require_dbcs_codec = __commonJS({
1672
1672
  }
1673
1673
  }
1674
1674
  }
1675
- this.defaultCharUnicode = iconv2.defaultCharUnicode;
1675
+ this.defaultCharUnicode = iconv3.defaultCharUnicode;
1676
1676
  this.encodeTable = [];
1677
1677
  this.encodeTableSeq = [];
1678
1678
  var skipEncodeChars = {};
@@ -1696,7 +1696,7 @@ var require_dbcs_codec = __commonJS({
1696
1696
  }
1697
1697
  }
1698
1698
  }
1699
- this.defCharSB = this.encodeTable[0][iconv2.defaultCharSingleByte.charCodeAt(0)];
1699
+ this.defCharSB = this.encodeTable[0][iconv3.defaultCharSingleByte.charCodeAt(0)];
1700
1700
  if (this.defCharSB === UNASSIGNED) this.defCharSB = this.encodeTable[0]["?"];
1701
1701
  if (this.defCharSB === UNASSIGNED) this.defCharSB = "?".charCodeAt(0);
1702
1702
  }
@@ -4547,10 +4547,10 @@ function mergeDefs(...defs) {
4547
4547
  function cloneDef(schema) {
4548
4548
  return mergeDefs(schema._zod.def);
4549
4549
  }
4550
- function getElementAtPath(obj, path3) {
4551
- if (!path3)
4550
+ function getElementAtPath(obj, path4) {
4551
+ if (!path4)
4552
4552
  return obj;
4553
- return path3.reduce((acc, key) => acc?.[key], obj);
4553
+ return path4.reduce((acc, key) => acc?.[key], obj);
4554
4554
  }
4555
4555
  function promiseAllObject(promisesObj) {
4556
4556
  const keys = Object.keys(promisesObj);
@@ -4911,11 +4911,11 @@ function aborted(x, startIndex = 0) {
4911
4911
  }
4912
4912
  return false;
4913
4913
  }
4914
- function prefixIssues(path3, issues) {
4914
+ function prefixIssues(path4, issues) {
4915
4915
  return issues.map((iss) => {
4916
4916
  var _a;
4917
4917
  (_a = iss).path ?? (_a.path = []);
4918
- iss.path.unshift(path3);
4918
+ iss.path.unshift(path4);
4919
4919
  return iss;
4920
4920
  });
4921
4921
  }
@@ -5083,7 +5083,7 @@ function treeifyError(error45, _mapper) {
5083
5083
  return issue2.message;
5084
5084
  };
5085
5085
  const result = { errors: [] };
5086
- const processError = (error46, path3 = []) => {
5086
+ const processError = (error46, path4 = []) => {
5087
5087
  var _a, _b;
5088
5088
  for (const issue2 of error46.issues) {
5089
5089
  if (issue2.code === "invalid_union" && issue2.errors.length) {
@@ -5093,7 +5093,7 @@ function treeifyError(error45, _mapper) {
5093
5093
  } else if (issue2.code === "invalid_element") {
5094
5094
  processError({ issues: issue2.issues }, issue2.path);
5095
5095
  } else {
5096
- const fullpath = [...path3, ...issue2.path];
5096
+ const fullpath = [...path4, ...issue2.path];
5097
5097
  if (fullpath.length === 0) {
5098
5098
  result.errors.push(mapper(issue2));
5099
5099
  continue;
@@ -5125,8 +5125,8 @@ function treeifyError(error45, _mapper) {
5125
5125
  }
5126
5126
  function toDotPath(_path) {
5127
5127
  const segs = [];
5128
- const path3 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
5129
- for (const seg of path3) {
5128
+ const path4 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
5129
+ for (const seg of path4) {
5130
5130
  if (typeof seg === "number")
5131
5131
  segs.push(`[${seg}]`);
5132
5132
  else if (typeof seg === "symbol")
@@ -16259,6 +16259,7 @@ var GbkToolError = class extends Error {
16259
16259
  function createGbkError(code, message, cause) {
16260
16260
  return new GbkToolError(code, message, cause);
16261
16261
  }
16262
+ var createTextError = createGbkError;
16262
16263
 
16263
16264
  // src/lib/path-sandbox.ts
16264
16265
  import fs from "fs/promises";
@@ -17119,6 +17120,17 @@ and avoid false matches. Scoped edits also improve performance on very large fil
17119
17120
  },
17120
17121
  async execute(args, context) {
17121
17122
  const result = await replaceGbkFileText({ ...args, context });
17123
+ context.metadata({
17124
+ title: `GBK \u7F16\u8F91 ${result.encoding.toUpperCase()} x${result.replacements}`,
17125
+ metadata: {
17126
+ filePath: result.filePath,
17127
+ encoding: result.encoding,
17128
+ replacements: result.replacements,
17129
+ occurrencesBefore: result.occurrencesBefore,
17130
+ bytesRead: result.bytesRead,
17131
+ bytesWritten: result.bytesWritten
17132
+ }
17133
+ });
17122
17134
  return JSON.stringify(result, null, 2);
17123
17135
  }
17124
17136
  });
@@ -17153,6 +17165,19 @@ Workflow when truncated=true:
17153
17165
  },
17154
17166
  async execute(args, context) {
17155
17167
  const result = await readGbkFile({ ...args, context });
17168
+ const lineRange = `${result.startLine}-${result.endLine}`;
17169
+ context.metadata({
17170
+ title: `GBK \u8BFB\u53D6 ${result.encoding.toUpperCase()} ${lineRange}`,
17171
+ metadata: {
17172
+ filePath: result.filePath,
17173
+ encoding: result.encoding,
17174
+ lineRange,
17175
+ totalLines: result.totalLines,
17176
+ newlineStyle: result.newlineStyle,
17177
+ truncated: result.truncated,
17178
+ tail: result.tail
17179
+ }
17180
+ });
17156
17181
  return JSON.stringify(result, null, 2);
17157
17182
  }
17158
17183
  });
@@ -17180,6 +17205,15 @@ Workflow for large files:
17180
17205
  },
17181
17206
  async execute(args, context) {
17182
17207
  const result = await searchGbkFile({ ...args, context });
17208
+ context.metadata({
17209
+ title: `GBK \u641C\u7D22 ${result.encoding.toUpperCase()} ${result.matchCount} \u547D\u4E2D`,
17210
+ metadata: {
17211
+ filePath: result.filePath,
17212
+ encoding: result.encoding,
17213
+ totalLines: result.totalLines,
17214
+ matchCount: result.matchCount
17215
+ }
17216
+ });
17183
17217
  return JSON.stringify(result, null, 2);
17184
17218
  }
17185
17219
  });
@@ -17208,6 +17242,683 @@ var gbk_write_default = tool({
17208
17242
  },
17209
17243
  async execute(args, context) {
17210
17244
  const result = await writeGbkFile({ ...args, context });
17245
+ const action = result.appended ? "\u8FFD\u52A0" : result.overwritten ? "\u8986\u76D6" : "\u5199\u5165";
17246
+ context.metadata({
17247
+ title: `GBK ${action} ${result.encoding.toUpperCase()}`,
17248
+ metadata: {
17249
+ filePath: result.filePath,
17250
+ encoding: result.encoding,
17251
+ created: result.created,
17252
+ overwritten: result.overwritten,
17253
+ appended: result.appended ?? false,
17254
+ bytesWritten: result.bytesWritten
17255
+ }
17256
+ });
17257
+ return JSON.stringify(result, null, 2);
17258
+ }
17259
+ });
17260
+
17261
+ // src/plugin/text-guidance.ts
17262
+ var TEXT_TOOL_SYSTEM_MARKER = "[opencode-gbk-tools:text-rules]";
17263
+ var TEXT_TOOL_SYSTEM_PROMPT = [
17264
+ TEXT_TOOL_SYSTEM_MARKER,
17265
+ "\u6587\u672C\u6587\u4EF6\u5904\u7406\u89C4\u5219\uFF1A",
17266
+ "- \u5904\u7406\u6587\u672C\u6587\u4EF6\u65F6\uFF0C\u4F18\u5148\u4F7F\u7528 text_read\u3001text_write\u3001text_edit\u3002",
17267
+ "- text_* \u9ED8\u8BA4\u4F1A\u81EA\u52A8\u8BC6\u522B\u73B0\u6709\u6587\u4EF6\u7F16\u7801\uFF0C\u5E76\u5728\u4FEE\u6539\u65F6\u5C3D\u91CF\u4FDD\u6301\u539F\u7F16\u7801\u3001BOM \u548C\u6362\u884C\u98CE\u683C\u3002",
17268
+ "- \u82E5\u68C0\u6D4B\u7F6E\u4FE1\u5EA6\u4E0D\u8DB3\u6216\u51FA\u73B0 TEXT_UNKNOWN_ENCODING\uFF0C\u8BF7\u663E\u5F0F\u6307\u5B9A encoding \u540E\u91CD\u8BD5\u3002",
17269
+ "- \u5904\u7406\u660E\u786E\u7684 GBK/GB18030 \u6587\u4EF6\u65F6\uFF0C\u4E5F\u53EF\u7EE7\u7EED\u4F7F\u7528 gbk_read\u3001gbk_write\u3001gbk_edit\u3001gbk_search\u3002"
17270
+ ].join("\n");
17271
+ function appendTextToolSystemPrompt(system) {
17272
+ if (system.some((item) => item.includes(TEXT_TOOL_SYSTEM_MARKER))) {
17273
+ return;
17274
+ }
17275
+ system.push(TEXT_TOOL_SYSTEM_PROMPT);
17276
+ }
17277
+
17278
+ // src/lib/text-file.ts
17279
+ var import_iconv_lite2 = __toESM(require_lib(), 1);
17280
+ import fs3 from "fs/promises";
17281
+ import path3 from "path";
17282
+ var TEXT_STREAMING_FILE_SIZE_THRESHOLD_BYTES = 1024 * 1024;
17283
+ var UTF8_DECODER = new TextDecoder("utf-8", { fatal: true });
17284
+ function isSupportedEncoding(value) {
17285
+ return value === "utf8" || value === "utf8-bom" || value === "utf16le" || value === "utf16be" || value === "gbk" || value === "gb18030";
17286
+ }
17287
+ function assertTextEncodingSupported(encoding) {
17288
+ if (encoding !== "auto" && !isSupportedEncoding(encoding)) {
17289
+ throw createTextError("GBK_INVALID_ENCODING", `\u4E0D\u652F\u6301\u7684\u7F16\u7801: ${encoding}`);
17290
+ }
17291
+ }
17292
+ function decodeUtf16be(buffer) {
17293
+ return import_iconv_lite2.default.decode(buffer, "utf16be");
17294
+ }
17295
+ function encodeText(content, encoding, hasBom = encoding === "utf8-bom") {
17296
+ if (encoding === "utf8") {
17297
+ return Buffer.from(content, "utf8");
17298
+ }
17299
+ if (encoding === "utf8-bom") {
17300
+ return Buffer.concat([Buffer.from([239, 187, 191]), Buffer.from(content, "utf8")]);
17301
+ }
17302
+ if (encoding === "utf16le") {
17303
+ const body = Buffer.from(content, "utf16le");
17304
+ return hasBom ? Buffer.concat([Buffer.from([255, 254]), body]) : body;
17305
+ }
17306
+ if (encoding === "utf16be") {
17307
+ const body = import_iconv_lite2.default.encode(content, "utf16be");
17308
+ return hasBom ? Buffer.concat([Buffer.from([254, 255]), body]) : body;
17309
+ }
17310
+ return import_iconv_lite2.default.encode(content, encoding);
17311
+ }
17312
+ function decodeText(buffer, encoding) {
17313
+ if (encoding === "utf8") {
17314
+ return buffer.toString("utf8");
17315
+ }
17316
+ if (encoding === "utf8-bom") {
17317
+ return buffer.subarray(3).toString("utf8");
17318
+ }
17319
+ if (encoding === "utf16le") {
17320
+ const withoutBom = buffer.length >= 2 && buffer[0] === 255 && buffer[1] === 254 ? buffer.subarray(2) : buffer;
17321
+ return withoutBom.toString("utf16le");
17322
+ }
17323
+ if (encoding === "utf16be") {
17324
+ const withoutBom = buffer.length >= 2 && buffer[0] === 254 && buffer[1] === 255 ? buffer.subarray(2) : buffer;
17325
+ return decodeUtf16be(withoutBom);
17326
+ }
17327
+ return import_iconv_lite2.default.decode(buffer, encoding);
17328
+ }
17329
+ function detectBom(buffer) {
17330
+ if (buffer.length >= 3 && buffer[0] === 239 && buffer[1] === 187 && buffer[2] === 191) {
17331
+ return {
17332
+ requestedEncoding: "auto",
17333
+ detectedEncoding: "utf8-bom",
17334
+ confidence: "high",
17335
+ hasBom: true
17336
+ };
17337
+ }
17338
+ if (buffer.length >= 2 && buffer[0] === 255 && buffer[1] === 254) {
17339
+ return {
17340
+ requestedEncoding: "auto",
17341
+ detectedEncoding: "utf16le",
17342
+ confidence: "high",
17343
+ hasBom: true
17344
+ };
17345
+ }
17346
+ if (buffer.length >= 2 && buffer[0] === 254 && buffer[1] === 255) {
17347
+ return {
17348
+ requestedEncoding: "auto",
17349
+ detectedEncoding: "utf16be",
17350
+ confidence: "high",
17351
+ hasBom: true
17352
+ };
17353
+ }
17354
+ return null;
17355
+ }
17356
+ function isValidUtf8(buffer) {
17357
+ try {
17358
+ UTF8_DECODER.decode(buffer);
17359
+ return true;
17360
+ } catch {
17361
+ return false;
17362
+ }
17363
+ }
17364
+ function hasUtf16Pattern(buffer) {
17365
+ const sample = buffer.subarray(0, Math.min(buffer.length, 512));
17366
+ let evenZeros = 0;
17367
+ let oddZeros = 0;
17368
+ for (let index = 0; index < sample.length; index += 1) {
17369
+ if (sample[index] === 0) {
17370
+ if (index % 2 === 0) {
17371
+ evenZeros += 1;
17372
+ } else {
17373
+ oddZeros += 1;
17374
+ }
17375
+ }
17376
+ }
17377
+ return {
17378
+ utf16be: evenZeros >= 2 && evenZeros >= oddZeros * 2,
17379
+ utf16le: oddZeros >= 2 && oddZeros >= evenZeros * 2
17380
+ };
17381
+ }
17382
+ function looksLossyRoundTrip(buffer, encoding) {
17383
+ const decoded = decodeText(buffer, encoding);
17384
+ const reencoded = encodeText(decoded, encoding, false);
17385
+ return !buffer.equals(reencoded);
17386
+ }
17387
+ function assertLikelyTextBuffer(buffer) {
17388
+ if (!buffer.includes(0)) {
17389
+ return;
17390
+ }
17391
+ const bom = detectBom(buffer);
17392
+ if (bom?.detectedEncoding === "utf16le" || bom?.detectedEncoding === "utf16be") {
17393
+ return;
17394
+ }
17395
+ const utf16Pattern = hasUtf16Pattern(buffer);
17396
+ if (utf16Pattern.utf16be || utf16Pattern.utf16le) {
17397
+ return;
17398
+ }
17399
+ throw createTextError("GBK_BINARY_FILE", "\u7591\u4F3C\u4E8C\u8FDB\u5236\u6587\u4EF6\uFF0C\u65E0\u6CD5\u6309\u6587\u672C\u5904\u7406");
17400
+ }
17401
+ function getNearestContext2(content, oldString) {
17402
+ const lines = content.split(/\r?\n/);
17403
+ const oldLines = oldString.replace(/\r\n/g, "\n").split("\n").filter(Boolean);
17404
+ const firstToken = oldLines[0] || oldString.trim();
17405
+ for (let index = 0; index < lines.length; index += 1) {
17406
+ if (lines[index].includes(firstToken)) {
17407
+ return lines.slice(index, index + 4).join("\n");
17408
+ }
17409
+ }
17410
+ return lines.slice(0, 4).join("\n");
17411
+ }
17412
+ function buildNoMatchMessage2(content, oldString) {
17413
+ return [
17414
+ "\u672A\u627E\u5230\u9700\u8981\u66FF\u6362\u7684\u6587\u672C\u3002",
17415
+ "oldString \u5FC5\u987B\u4E0E\u6587\u4EF6\u5B9E\u9645\u5185\u5BB9\u5B8C\u5168\u5BF9\u5E94\u3002",
17416
+ "\u6700\u63A5\u8FD1\u7684\u4E0A\u4E0B\u6587\uFF1A",
17417
+ getNearestContext2(content, oldString)
17418
+ ].join("\n");
17419
+ }
17420
+ function detectTextEncodingFromBuffer(buffer, requestedEncoding = "auto") {
17421
+ if (requestedEncoding !== "auto") {
17422
+ assertTextEncodingSupported(requestedEncoding);
17423
+ return {
17424
+ requestedEncoding,
17425
+ detectedEncoding: requestedEncoding,
17426
+ confidence: "high",
17427
+ hasBom: requestedEncoding === "utf8-bom" || requestedEncoding === "utf16le" || requestedEncoding === "utf16be"
17428
+ };
17429
+ }
17430
+ const bom = detectBom(buffer);
17431
+ if (bom) {
17432
+ return bom;
17433
+ }
17434
+ const utf16Pattern = hasUtf16Pattern(buffer);
17435
+ if (utf16Pattern.utf16be) {
17436
+ return {
17437
+ requestedEncoding,
17438
+ detectedEncoding: "utf16be",
17439
+ confidence: "medium",
17440
+ hasBom: false
17441
+ };
17442
+ }
17443
+ if (utf16Pattern.utf16le) {
17444
+ return {
17445
+ requestedEncoding,
17446
+ detectedEncoding: "utf16le",
17447
+ confidence: "medium",
17448
+ hasBom: false
17449
+ };
17450
+ }
17451
+ if (isValidUtf8(buffer)) {
17452
+ return {
17453
+ requestedEncoding,
17454
+ detectedEncoding: "utf8",
17455
+ confidence: "high",
17456
+ hasBom: false
17457
+ };
17458
+ }
17459
+ const gbkLossy = looksLossyRoundTrip(buffer, "gbk");
17460
+ const gb18030Lossy = looksLossyRoundTrip(buffer, "gb18030");
17461
+ if (gb18030Lossy && gbkLossy) {
17462
+ throw createTextError("TEXT_UNKNOWN_ENCODING", "\u65E0\u6CD5\u53EF\u9760\u8BC6\u522B\u6587\u4EF6\u7F16\u7801\uFF0C\u8BF7\u663E\u5F0F\u6307\u5B9A encoding");
17463
+ }
17464
+ return {
17465
+ requestedEncoding,
17466
+ detectedEncoding: gbkLossy ? "gb18030" : "gbk",
17467
+ confidence: gbkLossy || gb18030Lossy ? "medium" : "low",
17468
+ hasBom: false
17469
+ };
17470
+ }
17471
+ async function resolveReadableTextFile(input) {
17472
+ const { candidatePath } = await assertPathAllowed(input.filePath, input.context, input.allowExternal ?? false);
17473
+ let stat;
17474
+ try {
17475
+ stat = await fs3.stat(candidatePath);
17476
+ } catch (error45) {
17477
+ throw createTextError("GBK_FILE_NOT_FOUND", `\u6587\u4EF6\u4E0D\u5B58\u5728: ${candidatePath}`, error45);
17478
+ }
17479
+ if (stat.isDirectory()) {
17480
+ throw createTextError("GBK_IS_DIRECTORY", `\u76EE\u6807\u8DEF\u5F84\u662F\u76EE\u5F55: ${candidatePath}`);
17481
+ }
17482
+ return { filePath: candidatePath, stat };
17483
+ }
17484
+ async function readWholeTextFile(input) {
17485
+ const resolved = await resolveReadableTextFile(input);
17486
+ try {
17487
+ const buffer = await fs3.readFile(resolved.filePath);
17488
+ assertLikelyTextBuffer(buffer);
17489
+ const detected = detectTextEncodingFromBuffer(buffer, input.encoding ?? "auto");
17490
+ const content = decodeText(buffer, detected.detectedEncoding);
17491
+ return {
17492
+ filePath: resolved.filePath,
17493
+ bytesRead: buffer.byteLength,
17494
+ fileSize: buffer.byteLength,
17495
+ content,
17496
+ encoding: detected.detectedEncoding,
17497
+ requestedEncoding: detected.requestedEncoding,
17498
+ detectedEncoding: detected.detectedEncoding,
17499
+ confidence: detected.confidence,
17500
+ hasBom: detected.hasBom,
17501
+ newlineStyle: detectNewlineStyle(content)
17502
+ };
17503
+ } catch (error45) {
17504
+ if (error45 instanceof Error && "code" in error45) {
17505
+ throw error45;
17506
+ }
17507
+ throw createTextError("GBK_IO_ERROR", `\u8BFB\u53D6\u6587\u4EF6\u5931\u8D25: ${resolved.filePath}`, error45);
17508
+ }
17509
+ }
17510
+ function collectTailLines2(text, limit) {
17511
+ assertPositiveInteger(limit, "limit");
17512
+ const lines = text.split(/\r?\n/);
17513
+ const totalLines = lines.length;
17514
+ const startLine = Math.max(1, totalLines - limit + 1);
17515
+ const selected = lines.slice(startLine - 1);
17516
+ return {
17517
+ startLine,
17518
+ endLine: totalLines,
17519
+ totalLines,
17520
+ content: selected.map((line, index) => `${startLine + index}: ${line}`).join("\n"),
17521
+ truncated: startLine > 1,
17522
+ tail: true
17523
+ };
17524
+ }
17525
+ function normalizeNewlines2(text) {
17526
+ return text.replace(/\r\n/g, "\n");
17527
+ }
17528
+ function applyLineRange2(text, startLine, endLine) {
17529
+ if (startLine === void 0 && endLine === void 0) {
17530
+ return {
17531
+ selectedText: text,
17532
+ rangeStart: 0,
17533
+ rangeEnd: text.length
17534
+ };
17535
+ }
17536
+ const lines = text.split(/\r?\n/);
17537
+ const actualStartLine = startLine ?? 1;
17538
+ const actualEndLine = endLine ?? lines.length;
17539
+ assertPositiveInteger(actualStartLine, "startLine");
17540
+ assertPositiveInteger(actualEndLine, "endLine");
17541
+ if (actualEndLine < actualStartLine) {
17542
+ throw createTextError("GBK_INVALID_ARGUMENT", "endLine \u4E0D\u80FD\u5C0F\u4E8E startLine");
17543
+ }
17544
+ let cursor = 0;
17545
+ let rangeStart = 0;
17546
+ let rangeEnd = text.length;
17547
+ for (let lineNumber = 1; lineNumber <= lines.length; lineNumber += 1) {
17548
+ if (lineNumber === actualStartLine) {
17549
+ rangeStart = cursor;
17550
+ }
17551
+ cursor += lines[lineNumber - 1].length;
17552
+ if (lineNumber < lines.length) {
17553
+ const newlineLength = text.startsWith("\r\n", cursor) ? 2 : 1;
17554
+ cursor += newlineLength;
17555
+ }
17556
+ if (lineNumber === actualEndLine) {
17557
+ rangeEnd = cursor;
17558
+ break;
17559
+ }
17560
+ }
17561
+ return {
17562
+ selectedText: text.slice(rangeStart, rangeEnd),
17563
+ rangeStart,
17564
+ rangeEnd
17565
+ };
17566
+ }
17567
+ function applyAnchors2(text, startAnchor, endAnchor) {
17568
+ if (!startAnchor && !endAnchor) {
17569
+ return {
17570
+ selectedText: text,
17571
+ rangeStart: 0,
17572
+ rangeEnd: text.length
17573
+ };
17574
+ }
17575
+ let rangeStart = 0;
17576
+ let rangeEnd = text.length;
17577
+ if (startAnchor) {
17578
+ const found = text.indexOf(startAnchor);
17579
+ if (found === -1) {
17580
+ throw createTextError("GBK_NO_MATCH", `\u672A\u627E\u5230\u8D77\u59CB\u951A\u70B9: ${startAnchor}`);
17581
+ }
17582
+ rangeStart = found + startAnchor.length;
17583
+ }
17584
+ if (endAnchor) {
17585
+ const found = text.indexOf(endAnchor, rangeStart);
17586
+ if (found === -1) {
17587
+ throw createTextError("GBK_NO_MATCH", `\u672A\u627E\u5230\u7ED3\u675F\u951A\u70B9: ${endAnchor}`);
17588
+ }
17589
+ rangeEnd = found;
17590
+ }
17591
+ if (rangeEnd < rangeStart) {
17592
+ throw createTextError("GBK_INVALID_ARGUMENT", "\u951A\u70B9\u8303\u56F4\u65E0\u6548");
17593
+ }
17594
+ return {
17595
+ selectedText: text.slice(rangeStart, rangeEnd),
17596
+ rangeStart,
17597
+ rangeEnd
17598
+ };
17599
+ }
17600
+ function resolveEditScope2(text, input) {
17601
+ const anchored = applyAnchors2(text, input.startAnchor, input.endAnchor);
17602
+ const lineRanged = applyLineRange2(anchored.selectedText, input.startLine, input.endLine);
17603
+ return {
17604
+ selectedText: lineRanged.selectedText,
17605
+ rangeStart: anchored.rangeStart + lineRanged.rangeStart,
17606
+ rangeEnd: anchored.rangeStart + lineRanged.rangeEnd
17607
+ };
17608
+ }
17609
+ function alignTextToNewlineStyle(text, newlineStyle) {
17610
+ const normalized = text.replace(/\r\n/g, "\n");
17611
+ if (newlineStyle === "crlf") {
17612
+ return normalized.replace(/\n/g, "\r\n");
17613
+ }
17614
+ if (newlineStyle === "lf") {
17615
+ return normalized;
17616
+ }
17617
+ return text;
17618
+ }
17619
+ function ensureLossless(input, encoding, hasBom = encoding === "utf8-bom") {
17620
+ const buffer = encodeText(input, encoding, hasBom);
17621
+ const roundTrip = decodeText(buffer, encoding);
17622
+ if (roundTrip !== input) {
17623
+ throw createTextError("TEXT_ENCODING_LOSSY", `\u5185\u5BB9\u65E0\u6CD5\u65E0\u635F\u5199\u5165\u7F16\u7801 ${encoding}`);
17624
+ }
17625
+ }
17626
+ async function ensureParentDirectory(parent, createDirectories) {
17627
+ try {
17628
+ const parentStat = await fs3.stat(parent);
17629
+ if (!parentStat.isDirectory()) {
17630
+ throw createTextError("GBK_PARENT_DIRECTORY_MISSING", `\u7236\u76EE\u5F55\u4E0D\u5B58\u5728: ${parent}`);
17631
+ }
17632
+ } catch (error45) {
17633
+ if (error45 instanceof Error && "code" in error45 && error45.code === "ENOENT") {
17634
+ if (!createDirectories) {
17635
+ throw createTextError("GBK_PARENT_DIRECTORY_MISSING", `\u7236\u76EE\u5F55\u4E0D\u5B58\u5728: ${parent}`);
17636
+ }
17637
+ await fs3.mkdir(parent, { recursive: true });
17638
+ return;
17639
+ }
17640
+ throw error45;
17641
+ }
17642
+ }
17643
+ async function readTextFile(input) {
17644
+ const offset = normalizeOptionalPositiveInteger(input.offset, "offset") ?? 1;
17645
+ const limit = normalizeOptionalPositiveInteger(input.limit, "limit") ?? 2e3;
17646
+ const tail = input.tail ?? false;
17647
+ const loaded = await readWholeTextFile(input);
17648
+ const lineWindow = tail ? collectTailLines2(loaded.content, limit) : {
17649
+ ...splitLinesWithNumbers(loaded.content, offset, limit),
17650
+ tail: false,
17651
+ truncated: false
17652
+ };
17653
+ if (!tail) {
17654
+ lineWindow.truncated = lineWindow.endLine < lineWindow.totalLines;
17655
+ }
17656
+ return {
17657
+ filePath: loaded.filePath,
17658
+ encoding: loaded.encoding,
17659
+ requestedEncoding: loaded.requestedEncoding,
17660
+ detectedEncoding: loaded.detectedEncoding,
17661
+ confidence: loaded.confidence,
17662
+ hasBom: loaded.hasBom,
17663
+ bytesRead: loaded.bytesRead,
17664
+ fileSize: loaded.fileSize,
17665
+ streamed: false,
17666
+ newlineStyle: loaded.newlineStyle,
17667
+ ...lineWindow
17668
+ };
17669
+ }
17670
+ async function writeTextFile(input) {
17671
+ const requestedEncoding = input.encoding ?? "auto";
17672
+ assertTextEncodingSupported(requestedEncoding);
17673
+ const preserveEncoding = input.preserveEncoding ?? true;
17674
+ const preserveNewlineStyle = input.preserveNewlineStyle ?? true;
17675
+ const createDirectories = input.createDirectories ?? true;
17676
+ const overwrite = input.overwrite ?? false;
17677
+ const append = input.append ?? false;
17678
+ const { candidatePath } = await assertPathAllowed(input.filePath, input.context, input.allowExternal ?? false);
17679
+ const parent = path3.dirname(candidatePath);
17680
+ await ensureParentDirectory(parent, createDirectories);
17681
+ let existing = null;
17682
+ try {
17683
+ existing = await readWholeTextFile({
17684
+ filePath: candidatePath,
17685
+ encoding: requestedEncoding,
17686
+ allowExternal: input.allowExternal,
17687
+ context: input.context
17688
+ });
17689
+ } catch (error45) {
17690
+ if (!(error45 instanceof Error && "code" in error45 && error45.code === "GBK_FILE_NOT_FOUND")) {
17691
+ throw error45;
17692
+ }
17693
+ }
17694
+ if (existing && !append && !overwrite) {
17695
+ throw createTextError("GBK_FILE_EXISTS", `\u76EE\u6807\u6587\u4EF6\u5DF2\u5B58\u5728: ${candidatePath}`);
17696
+ }
17697
+ const targetEncoding = existing && preserveEncoding ? existing.encoding : requestedEncoding === "auto" ? "utf8" : requestedEncoding;
17698
+ const targetHasBom = targetEncoding === "utf8-bom" ? true : existing && preserveEncoding ? existing.hasBom : targetEncoding === "utf16le" || targetEncoding === "utf16be" ? true : false;
17699
+ const baseContent = append ? existing?.content ?? "" : "";
17700
+ const rawContent = `${baseContent}${input.content}`;
17701
+ const outputContent = existing && preserveNewlineStyle ? alignTextToNewlineStyle(rawContent, existing.newlineStyle) : rawContent;
17702
+ ensureLossless(outputContent, targetEncoding, targetHasBom);
17703
+ const buffer = encodeText(outputContent, targetEncoding, targetHasBom);
17704
+ await fs3.writeFile(candidatePath, buffer);
17705
+ return {
17706
+ filePath: candidatePath,
17707
+ encoding: targetEncoding,
17708
+ requestedEncoding,
17709
+ detectedEncoding: existing?.encoding ?? null,
17710
+ confidence: existing?.confidence ?? null,
17711
+ hasBom: targetHasBom,
17712
+ bytesWritten: buffer.byteLength,
17713
+ created: !existing,
17714
+ overwritten: Boolean(existing) && !append,
17715
+ appended: append,
17716
+ newlineStyle: detectNewlineStyle(outputContent)
17717
+ };
17718
+ }
17719
+ async function replaceTextFileText(input) {
17720
+ const normalizedInput = {
17721
+ ...input,
17722
+ startLine: normalizeOptionalPositiveInteger(input.startLine, "startLine"),
17723
+ endLine: normalizeOptionalPositiveInteger(input.endLine, "endLine")
17724
+ };
17725
+ if (input.oldString.length === 0) {
17726
+ throw createTextError("GBK_EMPTY_OLD_STRING", "oldString \u4E0D\u80FD\u4E3A\u7A7A");
17727
+ }
17728
+ const loaded = await readWholeTextFile({
17729
+ filePath: input.filePath,
17730
+ encoding: input.encoding ?? "auto",
17731
+ allowExternal: input.allowExternal,
17732
+ context: input.context
17733
+ });
17734
+ const scope = resolveEditScope2(loaded.content, normalizedInput);
17735
+ const replaceAll = normalizedInput.replaceAll ?? false;
17736
+ const preserveEncoding = normalizedInput.preserveEncoding ?? true;
17737
+ const requestedEncoding = normalizedInput.encoding ?? "auto";
17738
+ const occurrencesBefore = countOccurrences(scope.selectedText, normalizedInput.oldString);
17739
+ if (replaceAll) {
17740
+ if (occurrencesBefore === 0) {
17741
+ throw createTextError("GBK_NO_MATCH", buildNoMatchMessage2(scope.selectedText, normalizedInput.oldString));
17742
+ }
17743
+ } else if (occurrencesBefore === 0) {
17744
+ throw createTextError("GBK_NO_MATCH", buildNoMatchMessage2(scope.selectedText, normalizedInput.oldString));
17745
+ } else if (occurrencesBefore > 1) {
17746
+ throw createTextError("GBK_MULTIPLE_MATCHES", `\u627E\u5230\u591A\u4E2A\u5339\u914D\u9879: ${normalizedInput.oldString}`);
17747
+ }
17748
+ const alignedNewString = normalizedInput.preserveNewlineStyle === false ? normalizedInput.newString : alignTextToNewlineStyle(normalizedInput.newString, loaded.newlineStyle);
17749
+ const replaced = replaceAll ? scope.selectedText.split(normalizedInput.oldString).join(alignedNewString) : scope.selectedText.replace(normalizedInput.oldString, alignedNewString);
17750
+ const outputText = `${loaded.content.slice(0, scope.rangeStart)}${replaced}${loaded.content.slice(scope.rangeEnd)}`;
17751
+ const targetEncoding = preserveEncoding || requestedEncoding === "auto" ? loaded.encoding : requestedEncoding;
17752
+ const targetHasBom = preserveEncoding ? loaded.hasBom : targetEncoding === "utf8-bom" || targetEncoding === "utf16le" || targetEncoding === "utf16be";
17753
+ ensureLossless(outputText, targetEncoding, targetHasBom);
17754
+ const buffer = encodeText(outputText, targetEncoding, targetHasBom);
17755
+ await fs3.writeFile(loaded.filePath, buffer);
17756
+ return {
17757
+ filePath: loaded.filePath,
17758
+ encoding: targetEncoding,
17759
+ requestedEncoding: loaded.requestedEncoding,
17760
+ detectedEncoding: loaded.detectedEncoding,
17761
+ confidence: loaded.confidence,
17762
+ hasBom: targetHasBom,
17763
+ replacements: replaceAll ? occurrencesBefore : 1,
17764
+ occurrencesBefore,
17765
+ bytesRead: loaded.bytesRead,
17766
+ bytesWritten: buffer.byteLength,
17767
+ newlineStyle: detectNewlineStyle(outputText)
17768
+ };
17769
+ }
17770
+ async function createTextDiffPreview(input) {
17771
+ const loaded = await readWholeTextFile({
17772
+ filePath: input.filePath,
17773
+ encoding: input.encoding ?? "auto",
17774
+ allowExternal: input.allowExternal,
17775
+ context: input.context
17776
+ });
17777
+ const scope = resolveEditScope2(loaded.content, input);
17778
+ const alignedNewString = alignTextToNewlineStyle(input.newString, loaded.newlineStyle);
17779
+ const replaced = input.replaceAll ?? false ? scope.selectedText.split(input.oldString).join(alignedNewString) : scope.selectedText.replace(input.oldString, alignedNewString);
17780
+ const beforeLines = normalizeNewlines2(scope.selectedText).split("\n");
17781
+ const afterLines = normalizeNewlines2(replaced).split("\n");
17782
+ const maxLines = Math.max(beforeLines.length, afterLines.length);
17783
+ const lines = [
17784
+ `--- ${path3.basename(loaded.filePath)} (${loaded.encoding})`,
17785
+ `+++ ${path3.basename(loaded.filePath)} (${loaded.encoding})`
17786
+ ];
17787
+ for (let index = 0; index < maxLines; index += 1) {
17788
+ const before = beforeLines[index];
17789
+ const after = afterLines[index];
17790
+ if (before !== void 0 && after !== void 0 && before === after) {
17791
+ lines.push(` ${before}`);
17792
+ continue;
17793
+ }
17794
+ if (before !== void 0) {
17795
+ lines.push(`-${before}`);
17796
+ }
17797
+ if (after !== void 0) {
17798
+ lines.push(`+${after}`);
17799
+ }
17800
+ }
17801
+ return {
17802
+ filePath: loaded.filePath,
17803
+ encoding: loaded.encoding,
17804
+ preview: lines.join("\n")
17805
+ };
17806
+ }
17807
+
17808
+ // src/tools/text_edit.ts
17809
+ var text_edit_default = tool({
17810
+ description: `Edit text files with automatic encoding detection and preservation.
17811
+
17812
+ - Existing files keep their original encoding and BOM by default.
17813
+ - Existing newline style is preserved by default.
17814
+ - Use startLine/endLine or anchors to narrow the edit scope.`,
17815
+ args: {
17816
+ filePath: tool.schema.string().describe("Target file path"),
17817
+ oldString: tool.schema.string().describe("Exact text to replace"),
17818
+ newString: tool.schema.string().describe("Replacement text"),
17819
+ replaceAll: tool.schema.boolean().optional().describe("Replace all occurrences"),
17820
+ startLine: tool.schema.number().int().positive().optional().describe("Start line for scoped edit"),
17821
+ endLine: tool.schema.number().int().positive().optional().describe("End line for scoped edit"),
17822
+ startAnchor: tool.schema.string().optional().describe("Start anchor for scoped edit"),
17823
+ endAnchor: tool.schema.string().optional().describe("End anchor for scoped edit"),
17824
+ encoding: tool.schema.enum(["auto", "utf8", "utf8-bom", "utf16le", "utf16be", "gbk", "gb18030"]).optional().describe("Encoding override, default auto"),
17825
+ preserveEncoding: tool.schema.boolean().optional().describe("Preserve detected file encoding"),
17826
+ preserveNewlineStyle: tool.schema.boolean().optional().describe("Preserve detected file newline style"),
17827
+ allowExternal: tool.schema.boolean().optional().describe("Allow paths outside workspace root")
17828
+ },
17829
+ async execute(args, context) {
17830
+ const result = await replaceTextFileText({ ...args, context });
17831
+ const preview = await createTextDiffPreview({ ...args, context });
17832
+ context.metadata({
17833
+ title: `\u6587\u672C\u7F16\u8F91 ${result.encoding.toUpperCase()} x${result.replacements}`,
17834
+ metadata: {
17835
+ filePath: result.filePath,
17836
+ encoding: result.encoding,
17837
+ requestedEncoding: result.requestedEncoding,
17838
+ confidence: result.confidence,
17839
+ hasBom: result.hasBom,
17840
+ replacements: result.replacements,
17841
+ occurrencesBefore: result.occurrencesBefore,
17842
+ newlineStyle: result.newlineStyle,
17843
+ diffPreview: preview.preview
17844
+ }
17845
+ });
17846
+ return JSON.stringify(result, null, 2);
17847
+ }
17848
+ });
17849
+
17850
+ // src/tools/text_read.ts
17851
+ var text_read_default = tool({
17852
+ description: `Read text files with automatic encoding detection and preservation.
17853
+
17854
+ - Default encoding=auto detects the existing file encoding.
17855
+ - Supported encodings: utf8, utf8-bom, utf16le, utf16be, gbk, gb18030.
17856
+ - Returns line-numbered content and detected encoding metadata.`,
17857
+ args: {
17858
+ filePath: tool.schema.string().describe("Target file path"),
17859
+ offset: tool.schema.number().int().positive().optional().describe("1-based start line"),
17860
+ limit: tool.schema.number().int().positive().optional().describe("Maximum lines to return"),
17861
+ tail: tool.schema.boolean().optional().describe("Read from file end instead of start"),
17862
+ encoding: tool.schema.enum(["auto", "utf8", "utf8-bom", "utf16le", "utf16be", "gbk", "gb18030"]).optional().describe("Encoding override, default auto"),
17863
+ allowExternal: tool.schema.boolean().optional().describe("Allow paths outside workspace root")
17864
+ },
17865
+ async execute(args, context) {
17866
+ const result = await readTextFile({ ...args, context });
17867
+ const lineRange = `${result.startLine}-${result.endLine}`;
17868
+ context.metadata({
17869
+ title: `\u6587\u672C\u8BFB\u53D6 ${result.encoding.toUpperCase()} ${lineRange}`,
17870
+ metadata: {
17871
+ filePath: result.filePath,
17872
+ encoding: result.encoding,
17873
+ requestedEncoding: result.requestedEncoding,
17874
+ confidence: result.confidence,
17875
+ hasBom: result.hasBom,
17876
+ lineRange,
17877
+ totalLines: result.totalLines,
17878
+ newlineStyle: result.newlineStyle,
17879
+ truncated: result.truncated
17880
+ }
17881
+ });
17882
+ return JSON.stringify(result, null, 2);
17883
+ }
17884
+ });
17885
+
17886
+ // src/tools/text_write.ts
17887
+ var text_write_default = tool({
17888
+ description: `Write text files while preserving detected encoding and newline style by default.
17889
+
17890
+ - Existing files keep their original encoding when encoding=auto.
17891
+ - New files default to utf8 unless encoding is specified.
17892
+ - Supports append and overwrite modes.`,
17893
+ args: {
17894
+ filePath: tool.schema.string().describe("Target file path"),
17895
+ content: tool.schema.string().describe("Text content to write or append"),
17896
+ encoding: tool.schema.enum(["auto", "utf8", "utf8-bom", "utf16le", "utf16be", "gbk", "gb18030"]).optional().describe("Encoding override, default auto"),
17897
+ createDirectories: tool.schema.boolean().optional().describe("Create parent directories"),
17898
+ overwrite: tool.schema.boolean().optional().describe("Overwrite existing file"),
17899
+ append: tool.schema.boolean().optional().describe("Append content to existing file"),
17900
+ preserveEncoding: tool.schema.boolean().optional().describe("Preserve detected file encoding when file exists"),
17901
+ preserveNewlineStyle: tool.schema.boolean().optional().describe("Preserve detected file newline style when file exists"),
17902
+ allowExternal: tool.schema.boolean().optional().describe("Allow paths outside workspace root")
17903
+ },
17904
+ async execute(args, context) {
17905
+ const result = await writeTextFile({ ...args, context });
17906
+ const action = result.appended ? "\u8FFD\u52A0" : result.overwritten ? "\u8986\u76D6" : "\u5199\u5165";
17907
+ context.metadata({
17908
+ title: `\u6587\u672C${action} ${result.encoding.toUpperCase()}`,
17909
+ metadata: {
17910
+ filePath: result.filePath,
17911
+ encoding: result.encoding,
17912
+ requestedEncoding: result.requestedEncoding,
17913
+ detectedEncoding: result.detectedEncoding,
17914
+ confidence: result.confidence,
17915
+ hasBom: result.hasBom,
17916
+ created: result.created,
17917
+ overwritten: result.overwritten,
17918
+ appended: result.appended,
17919
+ newlineStyle: result.newlineStyle
17920
+ }
17921
+ });
17211
17922
  return JSON.stringify(result, null, 2);
17212
17923
  }
17213
17924
  });
@@ -17221,7 +17932,13 @@ var pluginModule = {
17221
17932
  gbk_read: gbk_read_default,
17222
17933
  gbk_write: gbk_write_default,
17223
17934
  gbk_edit: gbk_edit_default,
17224
- gbk_search: gbk_search_default
17935
+ gbk_search: gbk_search_default,
17936
+ text_read: text_read_default,
17937
+ text_write: text_write_default,
17938
+ text_edit: text_edit_default
17939
+ },
17940
+ async "experimental.chat.system.transform"(_input, output) {
17941
+ appendTextToolSystemPrompt(output.system);
17225
17942
  }
17226
17943
  };
17227
17944
  }