opencode-gbk-tools 0.1.7 → 0.1.8

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.
@@ -16750,6 +16750,12 @@ gbk_read output looks like "3787: SENDMSG 0 content". The "3787: " is a navigati
16750
16750
  oldString must be the raw file content: "SENDMSG 0 content" (no line number prefix).
16751
16751
  Including line numbers in oldString will cause GBK_NO_MATCH even if the content exists.
16752
16752
 
16753
+ CRITICAL \u2014 do NOT use bare newlines or whitespace-only as oldString:
16754
+ Using oldString="
16755
+ " or oldString="" to append content will always fail.
16756
+ To append content to the END of a file, use gbk_write with append=true instead:
16757
+ gbk_write(filePath=..., content="\\r\\n\u65B0\u5185\u5BB9", append=true)
16758
+
16753
16759
  Recommended workflow for large files (when gbk_read returned truncated=true):
16754
16760
  1. gbk_search(pattern) \u2192 find exact lineNumber
16755
16761
  2. gbk_read(offset=<lineNumber>, limit=20) \u2192 get the exact block (strip "N: " prefixes)
@@ -16314,9 +16314,49 @@ async function writeGbkFile(input) {
16314
16314
  const encoding = input.encoding ?? "gbk";
16315
16315
  const createDirectories = input.createDirectories ?? true;
16316
16316
  const overwrite = input.overwrite ?? false;
16317
+ const append = input.append ?? false;
16317
16318
  const { candidatePath } = await assertPathAllowed(input.filePath, input.context, input.allowExternal ?? false);
16318
16319
  const parent = path2.dirname(candidatePath);
16319
16320
  assertEncodingSupported(encoding);
16321
+ if (append) {
16322
+ try {
16323
+ const parentStat = await fs2.stat(parent);
16324
+ if (!parentStat.isDirectory()) {
16325
+ throw createGbkError("GBK_PARENT_DIRECTORY_MISSING", `\u7236\u76EE\u5F55\u4E0D\u5B58\u5728: ${parent}`);
16326
+ }
16327
+ } catch (error45) {
16328
+ if (error45 instanceof Error && "code" in error45 && error45.code === "ENOENT") {
16329
+ if (!createDirectories) {
16330
+ throw createGbkError("GBK_PARENT_DIRECTORY_MISSING", `\u7236\u76EE\u5F55\u4E0D\u5B58\u5728: ${parent}`);
16331
+ }
16332
+ await fs2.mkdir(parent, { recursive: true });
16333
+ } else if (error45 instanceof Error && "code" in error45) {
16334
+ throw error45;
16335
+ }
16336
+ }
16337
+ let existingContent = "";
16338
+ let existed = false;
16339
+ try {
16340
+ const existingBuffer = await fs2.readFile(candidatePath);
16341
+ existingContent = import_iconv_lite.default.decode(existingBuffer, encoding);
16342
+ existed = true;
16343
+ } catch (error45) {
16344
+ if (!(error45 instanceof Error && "code" in error45 && error45.code === "ENOENT")) {
16345
+ throw createGbkError("GBK_IO_ERROR", `\u8BFB\u53D6\u6587\u4EF6\u5931\u8D25: ${candidatePath}`, error45);
16346
+ }
16347
+ }
16348
+ const combined = existingContent + input.content;
16349
+ const buffer = import_iconv_lite.default.encode(combined, encoding);
16350
+ await fs2.writeFile(candidatePath, buffer);
16351
+ return {
16352
+ filePath: candidatePath,
16353
+ encoding,
16354
+ bytesWritten: buffer.byteLength,
16355
+ created: !existed,
16356
+ overwritten: false,
16357
+ appended: true
16358
+ };
16359
+ }
16320
16360
  try {
16321
16361
  const stat = await fs2.stat(candidatePath);
16322
16362
  if (stat.isDirectory()) {
@@ -16370,13 +16410,24 @@ async function writeGbkFile(input) {
16370
16410
 
16371
16411
  // src/tools/gbk_write.ts
16372
16412
  var gbk_write_default = tool({
16373
- description: "Write GBK encoded text files",
16413
+ description: `Write GBK encoded text files.
16414
+
16415
+ **append=true** (recommended for adding content to existing files):
16416
+ - Reads the existing file content and appends new content at the end.
16417
+ - Works whether the file exists or not (creates it if missing).
16418
+ - Use this whenever you want to add lines/content to an existing GBK file.
16419
+ - Example: gbk_write(filePath=..., content="\\r\\n\u65B0\u5185\u5BB9", append=true)
16420
+
16421
+ **overwrite=true**: Replace the entire file with new content.
16422
+
16423
+ **Default (overwrite=false, append=false)**: Fails if the file already exists.`,
16374
16424
  args: {
16375
16425
  filePath: tool.schema.string().describe("Target file path"),
16376
- content: tool.schema.string().describe("Text content to write"),
16426
+ content: tool.schema.string().describe("Text content to write (or append)"),
16377
16427
  encoding: tool.schema.enum(["gbk", "gb18030"]).optional().describe("Text encoding"),
16378
16428
  createDirectories: tool.schema.boolean().optional().describe("Create parent directories"),
16379
- overwrite: tool.schema.boolean().optional().describe("Overwrite existing file"),
16429
+ overwrite: tool.schema.boolean().optional().describe("Overwrite existing file (replaces entire content)"),
16430
+ append: tool.schema.boolean().optional().describe("Append content to existing file instead of overwriting; creates the file if it does not exist"),
16380
16431
  allowExternal: tool.schema.boolean().optional().describe("Allow paths outside workspace root")
16381
16432
  },
16382
16433
  async execute(args, context) {
@@ -16984,9 +16984,49 @@ async function writeGbkFile(input) {
16984
16984
  const encoding = input.encoding ?? "gbk";
16985
16985
  const createDirectories = input.createDirectories ?? true;
16986
16986
  const overwrite = input.overwrite ?? false;
16987
+ const append = input.append ?? false;
16987
16988
  const { candidatePath } = await assertPathAllowed(input.filePath, input.context, input.allowExternal ?? false);
16988
16989
  const parent = path2.dirname(candidatePath);
16989
16990
  assertEncodingSupported(encoding);
16991
+ if (append) {
16992
+ try {
16993
+ const parentStat = await fs2.stat(parent);
16994
+ if (!parentStat.isDirectory()) {
16995
+ throw createGbkError("GBK_PARENT_DIRECTORY_MISSING", `\u7236\u76EE\u5F55\u4E0D\u5B58\u5728: ${parent}`);
16996
+ }
16997
+ } catch (error45) {
16998
+ if (error45 instanceof Error && "code" in error45 && error45.code === "ENOENT") {
16999
+ if (!createDirectories) {
17000
+ throw createGbkError("GBK_PARENT_DIRECTORY_MISSING", `\u7236\u76EE\u5F55\u4E0D\u5B58\u5728: ${parent}`);
17001
+ }
17002
+ await fs2.mkdir(parent, { recursive: true });
17003
+ } else if (error45 instanceof Error && "code" in error45) {
17004
+ throw error45;
17005
+ }
17006
+ }
17007
+ let existingContent = "";
17008
+ let existed = false;
17009
+ try {
17010
+ const existingBuffer = await fs2.readFile(candidatePath);
17011
+ existingContent = import_iconv_lite.default.decode(existingBuffer, encoding);
17012
+ existed = true;
17013
+ } catch (error45) {
17014
+ if (!(error45 instanceof Error && "code" in error45 && error45.code === "ENOENT")) {
17015
+ throw createGbkError("GBK_IO_ERROR", `\u8BFB\u53D6\u6587\u4EF6\u5931\u8D25: ${candidatePath}`, error45);
17016
+ }
17017
+ }
17018
+ const combined = existingContent + input.content;
17019
+ const buffer = import_iconv_lite.default.encode(combined, encoding);
17020
+ await fs2.writeFile(candidatePath, buffer);
17021
+ return {
17022
+ filePath: candidatePath,
17023
+ encoding,
17024
+ bytesWritten: buffer.byteLength,
17025
+ created: !existed,
17026
+ overwritten: false,
17027
+ appended: true
17028
+ };
17029
+ }
16990
17030
  try {
16991
17031
  const stat = await fs2.stat(candidatePath);
16992
17032
  if (stat.isDirectory()) {
@@ -17050,6 +17090,12 @@ gbk_read output looks like "3787: SENDMSG 0 content". The "3787: " is a navigati
17050
17090
  oldString must be the raw file content: "SENDMSG 0 content" (no line number prefix).
17051
17091
  Including line numbers in oldString will cause GBK_NO_MATCH even if the content exists.
17052
17092
 
17093
+ CRITICAL \u2014 do NOT use bare newlines or whitespace-only as oldString:
17094
+ Using oldString="
17095
+ " or oldString="" to append content will always fail.
17096
+ To append content to the END of a file, use gbk_write with append=true instead:
17097
+ gbk_write(filePath=..., content="\\r\\n\u65B0\u5185\u5BB9", append=true)
17098
+
17053
17099
  Recommended workflow for large files (when gbk_read returned truncated=true):
17054
17100
  1. gbk_search(pattern) \u2192 find exact lineNumber
17055
17101
  2. gbk_read(offset=<lineNumber>, limit=20) \u2192 get the exact block (strip "N: " prefixes)
@@ -17138,13 +17184,24 @@ Workflow for large files:
17138
17184
 
17139
17185
  // src/tools/gbk_write.ts
17140
17186
  var gbk_write_default = tool({
17141
- description: "Write GBK encoded text files",
17187
+ description: `Write GBK encoded text files.
17188
+
17189
+ **append=true** (recommended for adding content to existing files):
17190
+ - Reads the existing file content and appends new content at the end.
17191
+ - Works whether the file exists or not (creates it if missing).
17192
+ - Use this whenever you want to add lines/content to an existing GBK file.
17193
+ - Example: gbk_write(filePath=..., content="\\r\\n\u65B0\u5185\u5BB9", append=true)
17194
+
17195
+ **overwrite=true**: Replace the entire file with new content.
17196
+
17197
+ **Default (overwrite=false, append=false)**: Fails if the file already exists.`,
17142
17198
  args: {
17143
17199
  filePath: tool.schema.string().describe("Target file path"),
17144
- content: tool.schema.string().describe("Text content to write"),
17200
+ content: tool.schema.string().describe("Text content to write (or append)"),
17145
17201
  encoding: tool.schema.enum(["gbk", "gb18030"]).optional().describe("Text encoding"),
17146
17202
  createDirectories: tool.schema.boolean().optional().describe("Create parent directories"),
17147
- overwrite: tool.schema.boolean().optional().describe("Overwrite existing file"),
17203
+ overwrite: tool.schema.boolean().optional().describe("Overwrite existing file (replaces entire content)"),
17204
+ append: tool.schema.boolean().optional().describe("Append content to existing file instead of overwriting; creates the file if it does not exist"),
17148
17205
  allowExternal: tool.schema.boolean().optional().describe("Allow paths outside workspace root")
17149
17206
  },
17150
17207
  async execute(args, context) {
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "manifestVersion": 1,
3
3
  "packageName": "opencode-gbk-tools",
4
- "packageVersion": "0.1.7",
4
+ "packageVersion": "0.1.8",
5
5
  "artifacts": [
6
6
  {
7
7
  "relativePath": "tools/gbk_edit.js",
8
8
  "kind": "tool",
9
- "expectedHash": "783a97cc6f7d1378f0b841ce0c6809e93db104aa192a64f72878ce6d432c997e",
9
+ "expectedHash": "68d8398eae66592166de62e1bdce35ac51a6c22f27e6b48eca83c62370bc44f5",
10
10
  "hashAlgorithm": "sha256"
11
11
  },
12
12
  {
@@ -24,7 +24,7 @@
24
24
  {
25
25
  "relativePath": "tools/gbk_write.js",
26
26
  "kind": "tool",
27
- "expectedHash": "fcb35107b599a9d2a60a1549372ef39f9b4e7f3759b5242faca3ed4b0170330f",
27
+ "expectedHash": "fa69eecf0c6133ebcd670fa81983a2acb5d011128f1ebc4a99fea4f5f1c37136",
28
28
  "hashAlgorithm": "sha256"
29
29
  },
30
30
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-gbk-tools",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "GBK/GB18030 custom tools and agent for OpenCode",
5
5
  "type": "module",
6
6
  "license": "MIT",