opencode-gbk-tools 0.1.3 → 0.1.5

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/README.md CHANGED
@@ -92,6 +92,28 @@ opencode-gbk doctor
92
92
  opencode-gbk doctor --project
93
93
  ```
94
94
 
95
+ ## 卸载
96
+
97
+ 如果你是通过 `setup` 或手动修改 `opencode.json` / `opencode.jsonc` 启用 npm plugin:
98
+
99
+ - 删除 `plugin` 数组中的 `"opencode-gbk-tools"`
100
+ - 如果不再需要 `gbk-engine`,再删除对应 agent 文件
101
+ - 项目级:`.opencode/agents/gbk-engine.md`
102
+ - 全局:`~/.config/opencode/agents/gbk-engine.md`
103
+
104
+ 如果你是通过 CLI 安装 agent 或工具文件:
105
+
106
+ ```bash
107
+ opencode-gbk uninstall
108
+ opencode-gbk uninstall --project
109
+ ```
110
+
111
+ 说明:
112
+
113
+ - `opencode-gbk uninstall` 会卸载全局安装到 `~/.config/opencode` 下的文件
114
+ - `opencode-gbk uninstall --project` 会卸载当前项目 `.opencode/` 下的文件
115
+ - `uninstall` 只会删除通过本包 manifest 记录过的文件,不会自动改写你的 `opencode.json` / `opencode.jsonc` plugin 配置
116
+
95
117
  ## Agent
96
118
 
97
119
  安装后会生成 `gbk-engine`。
@@ -16315,6 +16315,13 @@ function assertPositiveInteger(value, name) {
16315
16315
  throw createGbkError("GBK_INVALID_ARGUMENT", `${name} \u5FC5\u987B\u662F\u6B63\u6574\u6570`);
16316
16316
  }
16317
16317
  }
16318
+ function normalizeOptionalPositiveInteger(value, name) {
16319
+ if (value === void 0 || value === -1) {
16320
+ return void 0;
16321
+ }
16322
+ assertPositiveInteger(value, name);
16323
+ return Number(value);
16324
+ }
16318
16325
  function assertNotBinary(buffer) {
16319
16326
  if (buffer.includes(0)) {
16320
16327
  throw createGbkError("GBK_BINARY_FILE", "\u7591\u4F3C\u4E8C\u8FDB\u5236\u6587\u4EF6\uFF0C\u65E0\u6CD5\u6309 GBK \u6587\u672C\u5904\u7406");
@@ -16650,12 +16657,17 @@ async function replaceLargeGbkFileText(input) {
16650
16657
  }
16651
16658
  }
16652
16659
  async function replaceGbkFileText(input) {
16660
+ const normalizedInput = {
16661
+ ...input,
16662
+ startLine: normalizeOptionalPositiveInteger(input.startLine, "startLine"),
16663
+ endLine: normalizeOptionalPositiveInteger(input.endLine, "endLine")
16664
+ };
16653
16665
  if (input.oldString.length === 0) {
16654
16666
  throw createGbkError("GBK_EMPTY_OLD_STRING", "oldString \u4E0D\u80FD\u4E3A\u7A7A");
16655
16667
  }
16656
- const replaceAll = input.replaceAll ?? false;
16657
- const resolved = await resolveReadableGbkFile(input);
16658
- const hasScopedRange = input.startLine !== void 0 || input.endLine !== void 0 || input.startAnchor !== void 0 || input.endAnchor !== void 0;
16668
+ const replaceAll = normalizedInput.replaceAll ?? false;
16669
+ const resolved = await resolveReadableGbkFile(normalizedInput);
16670
+ const hasScopedRange = normalizedInput.startLine !== void 0 || normalizedInput.endLine !== void 0 || normalizedInput.startAnchor !== void 0 || normalizedInput.endAnchor !== void 0;
16659
16671
  if (resolved.stat.size >= STREAMING_FILE_SIZE_THRESHOLD_BYTES && !hasScopedRange) {
16660
16672
  return await replaceLargeGbkFileText({
16661
16673
  ...resolved,
@@ -16665,10 +16677,10 @@ async function replaceGbkFileText(input) {
16665
16677
  });
16666
16678
  }
16667
16679
  const current = await readWholeGbkTextFile(resolved);
16668
- const scope = resolveEditScope(current.content, input);
16669
- const occurrencesBefore = countOccurrences(scope.selectedText, input.oldString);
16680
+ const scope = resolveEditScope(current.content, normalizedInput);
16681
+ const occurrencesBefore = countOccurrences(scope.selectedText, normalizedInput.oldString);
16670
16682
  if (!replaceAll && occurrencesBefore === 0) {
16671
- const loose = tryLooseBlockReplace(scope.selectedText, input.oldString, input.newString);
16683
+ const loose = tryLooseBlockReplace(scope.selectedText, normalizedInput.oldString, normalizedInput.newString);
16672
16684
  if (loose !== null) {
16673
16685
  const outputText2 = `${current.content.slice(0, scope.rangeStart)}${loose.content}${current.content.slice(scope.rangeEnd)}`;
16674
16686
  const buffer2 = import_iconv_lite.default.encode(outputText2, current.encoding);
@@ -16685,14 +16697,14 @@ async function replaceGbkFileText(input) {
16685
16697
  }
16686
16698
  if (replaceAll) {
16687
16699
  if (occurrencesBefore === 0) {
16688
- throw createGbkError("GBK_NO_MATCH", buildNoMatchMessage(scope.selectedText, input.oldString));
16700
+ throw createGbkError("GBK_NO_MATCH", buildNoMatchMessage(scope.selectedText, normalizedInput.oldString));
16689
16701
  }
16690
16702
  } else if (occurrencesBefore === 0) {
16691
- throw createGbkError("GBK_NO_MATCH", buildNoMatchMessage(scope.selectedText, input.oldString));
16703
+ throw createGbkError("GBK_NO_MATCH", buildNoMatchMessage(scope.selectedText, normalizedInput.oldString));
16692
16704
  } else if (occurrencesBefore > 1) {
16693
- throw createGbkError("GBK_MULTIPLE_MATCHES", `\u627E\u5230\u591A\u4E2A\u5339\u914D\u9879: ${input.oldString}`);
16705
+ throw createGbkError("GBK_MULTIPLE_MATCHES", `\u627E\u5230\u591A\u4E2A\u5339\u914D\u9879: ${normalizedInput.oldString}`);
16694
16706
  }
16695
- const replaced = replaceAll ? scope.selectedText.split(input.oldString).join(input.newString) : scope.selectedText.replace(input.oldString, input.newString);
16707
+ const replaced = replaceAll ? scope.selectedText.split(normalizedInput.oldString).join(normalizedInput.newString) : scope.selectedText.replace(normalizedInput.oldString, normalizedInput.newString);
16696
16708
  const outputText = `${current.content.slice(0, scope.rangeStart)}${replaced}${current.content.slice(scope.rangeEnd)}`;
16697
16709
  const buffer = import_iconv_lite.default.encode(outputText, current.encoding);
16698
16710
  await fs2.writeFile(current.filePath, buffer);
@@ -16708,17 +16720,23 @@ async function replaceGbkFileText(input) {
16708
16720
 
16709
16721
  // src/tools/gbk_edit.ts
16710
16722
  var gbk_edit_default = tool({
16711
- description: "Edit GBK encoded text files with exact replacement",
16723
+ description: `Edit GBK/GB18030 encoded text files with exact string replacement.
16724
+
16725
+ Reads the FULL file content regardless of file size \u2014 not limited by gbk_read's line window.
16726
+ Safe to use on files with more than 2000 lines.
16727
+
16728
+ For large files, use 'startLine'/'endLine' or 'startAnchor'/'endAnchor' to narrow the search scope
16729
+ and avoid false matches. Scoped edits also improve performance on very large files.`,
16712
16730
  args: {
16713
16731
  filePath: tool.schema.string().describe("Target file path"),
16714
- oldString: tool.schema.string().describe("Text to replace"),
16732
+ oldString: tool.schema.string().describe("Exact text to replace (must match file content, not gbk_read output with line numbers)"),
16715
16733
  newString: tool.schema.string().describe("Replacement text"),
16716
- replaceAll: tool.schema.boolean().optional().describe("Replace all occurrences"),
16717
- startLine: tool.schema.number().int().positive().optional().describe("Restrict edit to 1-based start line"),
16718
- endLine: tool.schema.number().int().positive().optional().describe("Restrict edit to 1-based end line"),
16719
- startAnchor: tool.schema.string().optional().describe("Restrict edit to content after this anchor"),
16720
- endAnchor: tool.schema.string().optional().describe("Restrict edit to content before this anchor"),
16721
- encoding: tool.schema.enum(["gbk", "gb18030"]).optional().describe("Text encoding"),
16734
+ replaceAll: tool.schema.boolean().optional().describe("Replace all occurrences (default: false, requires unique match)"),
16735
+ startLine: tool.schema.union([tool.schema.number().int().positive(), tool.schema.literal(-1)]).optional().describe("Restrict edit scope to 1-based start line (inclusive)"),
16736
+ endLine: tool.schema.union([tool.schema.number().int().positive(), tool.schema.literal(-1)]).optional().describe("Restrict edit scope to 1-based end line (inclusive)"),
16737
+ startAnchor: tool.schema.string().optional().describe("Restrict edit to content after this anchor string"),
16738
+ endAnchor: tool.schema.string().optional().describe("Restrict edit to content before this anchor string"),
16739
+ encoding: tool.schema.enum(["gbk", "gb18030"]).optional().describe("Text encoding (default: gbk)"),
16722
16740
  allowExternal: tool.schema.boolean().optional().describe("Allow paths outside workspace root")
16723
16741
  },
16724
16742
  async execute(args, context) {
@@ -16315,6 +16315,13 @@ function assertPositiveInteger(value, name) {
16315
16315
  throw createGbkError("GBK_INVALID_ARGUMENT", `${name} \u5FC5\u987B\u662F\u6B63\u6574\u6570`);
16316
16316
  }
16317
16317
  }
16318
+ function normalizeOptionalPositiveInteger(value, name) {
16319
+ if (value === void 0 || value === -1) {
16320
+ return void 0;
16321
+ }
16322
+ assertPositiveInteger(value, name);
16323
+ return Number(value);
16324
+ }
16318
16325
  function assertNotBinary(buffer) {
16319
16326
  if (buffer.includes(0)) {
16320
16327
  throw createGbkError("GBK_BINARY_FILE", "\u7591\u4F3C\u4E8C\u8FDB\u5236\u6587\u4EF6\uFF0C\u65E0\u6CD5\u6309 GBK \u6587\u672C\u5904\u7406");
@@ -16556,8 +16563,8 @@ function createTailCollector(limit) {
16556
16563
  };
16557
16564
  }
16558
16565
  async function readGbkFile(input) {
16559
- const offset = input.offset ?? 1;
16560
- const limit = input.limit ?? 2e3;
16566
+ const offset = normalizeOptionalPositiveInteger(input.offset, "offset") ?? 1;
16567
+ const limit = normalizeOptionalPositiveInteger(input.limit, "limit") ?? 2e3;
16561
16568
  const tail = input.tail ?? false;
16562
16569
  const resolved = await resolveReadableGbkFile(input);
16563
16570
  if (resolved.stat.size < STREAMING_FILE_SIZE_THRESHOLD_BYTES) {
@@ -16597,13 +16604,21 @@ async function readGbkFile(input) {
16597
16604
 
16598
16605
  // src/tools/gbk_read.ts
16599
16606
  var gbk_read_default = tool({
16600
- description: "Read GBK encoded text files",
16607
+ description: `Read GBK/GB18030 encoded text files with line numbers.
16608
+
16609
+ Returns up to 'limit' lines (default 2000) starting from 'offset'.
16610
+ When the file has more lines than the window, 'truncated' is true and 'totalLines' shows the full count.
16611
+
16612
+ IMPORTANT: If 'truncated' is true, the returned content is incomplete.
16613
+ DO NOT use the returned content as 'oldString' for gbk_edit on a truncated file.
16614
+ To edit content beyond the visible window, use gbk_edit with 'startLine'/'endLine' to target the exact range,
16615
+ or read the specific range first with 'offset' set to the desired line number.`,
16601
16616
  args: {
16602
16617
  filePath: tool.schema.string().describe("Target file path"),
16603
- offset: tool.schema.number().int().positive().optional().describe("1-based start line"),
16604
- limit: tool.schema.number().int().positive().optional().describe("Number of lines to read"),
16618
+ offset: tool.schema.union([tool.schema.number().int().positive(), tool.schema.literal(-1)]).optional().describe("1-based start line (default: 1)"),
16619
+ limit: tool.schema.union([tool.schema.number().int().positive(), tool.schema.literal(-1)]).optional().describe("Number of lines to read (default: 2000). Use -1 to apply the default."),
16605
16620
  tail: tool.schema.boolean().optional().describe("Read last N lines instead of offset-based window"),
16606
- encoding: tool.schema.enum(["gbk", "gb18030"]).optional().describe("Text encoding"),
16621
+ encoding: tool.schema.enum(["gbk", "gb18030"]).optional().describe("Text encoding (default: gbk)"),
16607
16622
  allowExternal: tool.schema.boolean().optional().describe("Allow paths outside workspace root")
16608
16623
  },
16609
16624
  async execute(args, context) {
@@ -16315,6 +16315,13 @@ function assertPositiveInteger(value, name) {
16315
16315
  throw createGbkError("GBK_INVALID_ARGUMENT", `${name} \u5FC5\u987B\u662F\u6B63\u6574\u6570`);
16316
16316
  }
16317
16317
  }
16318
+ function normalizeOptionalPositiveInteger(value, name) {
16319
+ if (value === void 0 || value === -1) {
16320
+ return void 0;
16321
+ }
16322
+ assertPositiveInteger(value, name);
16323
+ return Number(value);
16324
+ }
16318
16325
  function assertNotBinary(buffer) {
16319
16326
  if (buffer.includes(0)) {
16320
16327
  throw createGbkError("GBK_BINARY_FILE", "\u7591\u4F3C\u4E8C\u8FDB\u5236\u6587\u4EF6\uFF0C\u65E0\u6CD5\u6309 GBK \u6587\u672C\u5904\u7406");
@@ -16805,8 +16812,8 @@ async function replaceLargeGbkFileText(input) {
16805
16812
  }
16806
16813
  }
16807
16814
  async function readGbkFile(input) {
16808
- const offset = input.offset ?? 1;
16809
- const limit = input.limit ?? 2e3;
16815
+ const offset = normalizeOptionalPositiveInteger(input.offset, "offset") ?? 1;
16816
+ const limit = normalizeOptionalPositiveInteger(input.limit, "limit") ?? 2e3;
16810
16817
  const tail = input.tail ?? false;
16811
16818
  const resolved = await resolveReadableGbkFile(input);
16812
16819
  if (resolved.stat.size < STREAMING_FILE_SIZE_THRESHOLD_BYTES) {
@@ -16844,12 +16851,17 @@ async function readGbkFile(input) {
16844
16851
  };
16845
16852
  }
16846
16853
  async function replaceGbkFileText(input) {
16854
+ const normalizedInput = {
16855
+ ...input,
16856
+ startLine: normalizeOptionalPositiveInteger(input.startLine, "startLine"),
16857
+ endLine: normalizeOptionalPositiveInteger(input.endLine, "endLine")
16858
+ };
16847
16859
  if (input.oldString.length === 0) {
16848
16860
  throw createGbkError("GBK_EMPTY_OLD_STRING", "oldString \u4E0D\u80FD\u4E3A\u7A7A");
16849
16861
  }
16850
- const replaceAll = input.replaceAll ?? false;
16851
- const resolved = await resolveReadableGbkFile(input);
16852
- const hasScopedRange = input.startLine !== void 0 || input.endLine !== void 0 || input.startAnchor !== void 0 || input.endAnchor !== void 0;
16862
+ const replaceAll = normalizedInput.replaceAll ?? false;
16863
+ const resolved = await resolveReadableGbkFile(normalizedInput);
16864
+ const hasScopedRange = normalizedInput.startLine !== void 0 || normalizedInput.endLine !== void 0 || normalizedInput.startAnchor !== void 0 || normalizedInput.endAnchor !== void 0;
16853
16865
  if (resolved.stat.size >= STREAMING_FILE_SIZE_THRESHOLD_BYTES && !hasScopedRange) {
16854
16866
  return await replaceLargeGbkFileText({
16855
16867
  ...resolved,
@@ -16859,10 +16871,10 @@ async function replaceGbkFileText(input) {
16859
16871
  });
16860
16872
  }
16861
16873
  const current = await readWholeGbkTextFile(resolved);
16862
- const scope = resolveEditScope(current.content, input);
16863
- const occurrencesBefore = countOccurrences(scope.selectedText, input.oldString);
16874
+ const scope = resolveEditScope(current.content, normalizedInput);
16875
+ const occurrencesBefore = countOccurrences(scope.selectedText, normalizedInput.oldString);
16864
16876
  if (!replaceAll && occurrencesBefore === 0) {
16865
- const loose = tryLooseBlockReplace(scope.selectedText, input.oldString, input.newString);
16877
+ const loose = tryLooseBlockReplace(scope.selectedText, normalizedInput.oldString, normalizedInput.newString);
16866
16878
  if (loose !== null) {
16867
16879
  const outputText2 = `${current.content.slice(0, scope.rangeStart)}${loose.content}${current.content.slice(scope.rangeEnd)}`;
16868
16880
  const buffer2 = import_iconv_lite.default.encode(outputText2, current.encoding);
@@ -16879,14 +16891,14 @@ async function replaceGbkFileText(input) {
16879
16891
  }
16880
16892
  if (replaceAll) {
16881
16893
  if (occurrencesBefore === 0) {
16882
- throw createGbkError("GBK_NO_MATCH", buildNoMatchMessage(scope.selectedText, input.oldString));
16894
+ throw createGbkError("GBK_NO_MATCH", buildNoMatchMessage(scope.selectedText, normalizedInput.oldString));
16883
16895
  }
16884
16896
  } else if (occurrencesBefore === 0) {
16885
- throw createGbkError("GBK_NO_MATCH", buildNoMatchMessage(scope.selectedText, input.oldString));
16897
+ throw createGbkError("GBK_NO_MATCH", buildNoMatchMessage(scope.selectedText, normalizedInput.oldString));
16886
16898
  } else if (occurrencesBefore > 1) {
16887
- throw createGbkError("GBK_MULTIPLE_MATCHES", `\u627E\u5230\u591A\u4E2A\u5339\u914D\u9879: ${input.oldString}`);
16899
+ throw createGbkError("GBK_MULTIPLE_MATCHES", `\u627E\u5230\u591A\u4E2A\u5339\u914D\u9879: ${normalizedInput.oldString}`);
16888
16900
  }
16889
- const replaced = replaceAll ? scope.selectedText.split(input.oldString).join(input.newString) : scope.selectedText.replace(input.oldString, input.newString);
16901
+ const replaced = replaceAll ? scope.selectedText.split(normalizedInput.oldString).join(normalizedInput.newString) : scope.selectedText.replace(normalizedInput.oldString, normalizedInput.newString);
16890
16902
  const outputText = `${current.content.slice(0, scope.rangeStart)}${replaced}${current.content.slice(scope.rangeEnd)}`;
16891
16903
  const buffer = import_iconv_lite.default.encode(outputText, current.encoding);
16892
16904
  await fs2.writeFile(current.filePath, buffer);
@@ -16959,17 +16971,23 @@ async function writeGbkFile(input) {
16959
16971
 
16960
16972
  // src/tools/gbk_edit.ts
16961
16973
  var gbk_edit_default = tool({
16962
- description: "Edit GBK encoded text files with exact replacement",
16974
+ description: `Edit GBK/GB18030 encoded text files with exact string replacement.
16975
+
16976
+ Reads the FULL file content regardless of file size \u2014 not limited by gbk_read's line window.
16977
+ Safe to use on files with more than 2000 lines.
16978
+
16979
+ For large files, use 'startLine'/'endLine' or 'startAnchor'/'endAnchor' to narrow the search scope
16980
+ and avoid false matches. Scoped edits also improve performance on very large files.`,
16963
16981
  args: {
16964
16982
  filePath: tool.schema.string().describe("Target file path"),
16965
- oldString: tool.schema.string().describe("Text to replace"),
16983
+ oldString: tool.schema.string().describe("Exact text to replace (must match file content, not gbk_read output with line numbers)"),
16966
16984
  newString: tool.schema.string().describe("Replacement text"),
16967
- replaceAll: tool.schema.boolean().optional().describe("Replace all occurrences"),
16968
- startLine: tool.schema.number().int().positive().optional().describe("Restrict edit to 1-based start line"),
16969
- endLine: tool.schema.number().int().positive().optional().describe("Restrict edit to 1-based end line"),
16970
- startAnchor: tool.schema.string().optional().describe("Restrict edit to content after this anchor"),
16971
- endAnchor: tool.schema.string().optional().describe("Restrict edit to content before this anchor"),
16972
- encoding: tool.schema.enum(["gbk", "gb18030"]).optional().describe("Text encoding"),
16985
+ replaceAll: tool.schema.boolean().optional().describe("Replace all occurrences (default: false, requires unique match)"),
16986
+ startLine: tool.schema.union([tool.schema.number().int().positive(), tool.schema.literal(-1)]).optional().describe("Restrict edit scope to 1-based start line (inclusive)"),
16987
+ endLine: tool.schema.union([tool.schema.number().int().positive(), tool.schema.literal(-1)]).optional().describe("Restrict edit scope to 1-based end line (inclusive)"),
16988
+ startAnchor: tool.schema.string().optional().describe("Restrict edit to content after this anchor string"),
16989
+ endAnchor: tool.schema.string().optional().describe("Restrict edit to content before this anchor string"),
16990
+ encoding: tool.schema.enum(["gbk", "gb18030"]).optional().describe("Text encoding (default: gbk)"),
16973
16991
  allowExternal: tool.schema.boolean().optional().describe("Allow paths outside workspace root")
16974
16992
  },
16975
16993
  async execute(args, context) {
@@ -16980,13 +16998,21 @@ var gbk_edit_default = tool({
16980
16998
 
16981
16999
  // src/tools/gbk_read.ts
16982
17000
  var gbk_read_default = tool({
16983
- description: "Read GBK encoded text files",
17001
+ description: `Read GBK/GB18030 encoded text files with line numbers.
17002
+
17003
+ Returns up to 'limit' lines (default 2000) starting from 'offset'.
17004
+ When the file has more lines than the window, 'truncated' is true and 'totalLines' shows the full count.
17005
+
17006
+ IMPORTANT: If 'truncated' is true, the returned content is incomplete.
17007
+ DO NOT use the returned content as 'oldString' for gbk_edit on a truncated file.
17008
+ To edit content beyond the visible window, use gbk_edit with 'startLine'/'endLine' to target the exact range,
17009
+ or read the specific range first with 'offset' set to the desired line number.`,
16984
17010
  args: {
16985
17011
  filePath: tool.schema.string().describe("Target file path"),
16986
- offset: tool.schema.number().int().positive().optional().describe("1-based start line"),
16987
- limit: tool.schema.number().int().positive().optional().describe("Number of lines to read"),
17012
+ offset: tool.schema.union([tool.schema.number().int().positive(), tool.schema.literal(-1)]).optional().describe("1-based start line (default: 1)"),
17013
+ limit: tool.schema.union([tool.schema.number().int().positive(), tool.schema.literal(-1)]).optional().describe("Number of lines to read (default: 2000). Use -1 to apply the default."),
16988
17014
  tail: tool.schema.boolean().optional().describe("Read last N lines instead of offset-based window"),
16989
- encoding: tool.schema.enum(["gbk", "gb18030"]).optional().describe("Text encoding"),
17015
+ encoding: tool.schema.enum(["gbk", "gb18030"]).optional().describe("Text encoding (default: gbk)"),
16990
17016
  allowExternal: tool.schema.boolean().optional().describe("Allow paths outside workspace root")
16991
17017
  },
16992
17018
  async execute(args, context) {
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "manifestVersion": 1,
3
3
  "packageName": "opencode-gbk-tools",
4
- "packageVersion": "0.1.3",
4
+ "packageVersion": "0.1.5",
5
5
  "artifacts": [
6
6
  {
7
7
  "relativePath": "tools/gbk_edit.js",
8
8
  "kind": "tool",
9
- "expectedHash": "c23a8f2fe0dea3f6099cf5ecc27eecc7f5acd85b5f5beb41da09418646a4225a",
9
+ "expectedHash": "3d0eb2fab5e3eca869923c2a3cc00e58ed429a4be4dbed22d13e5a5343bd5acc",
10
10
  "hashAlgorithm": "sha256"
11
11
  },
12
12
  {
13
13
  "relativePath": "tools/gbk_read.js",
14
14
  "kind": "tool",
15
- "expectedHash": "4ed95d744e6d5a70f578908fe0efc7b70b4a8c416e9a42fd2ed8726c02562cbe",
15
+ "expectedHash": "799c53835bfe7237c5bf1e4858a67d20fffe00f90958ef48b72877cb95c1c07f",
16
16
  "hashAlgorithm": "sha256"
17
17
  },
18
18
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-gbk-tools",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "GBK/GB18030 custom tools and agent for OpenCode",
5
5
  "type": "module",
6
6
  "license": "MIT",