opencode-gbk-tools 0.1.24 → 0.1.26

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
@@ -2,7 +2,7 @@
2
2
 
3
3
  为 OpenCode 提供一套自动识别编码的文本工具,以及面向 `GBK` / `GB18030` 的专用工具。
4
4
 
5
- 解决 OpenCode 内置工具难以稳定处理非 UTF-8 文本文件的问题,并通过 plugin 让所有 agents 默认获得这些工具与规则,无需单独切换专属 GBK agent。
5
+ 解决 OpenCode 内置工具难以稳定处理非 UTF-8 文本文件的问题,并通过 plugin 让所有 agents 默认获得这些工具与规则;同时提供一个只允许调用 `text_*` / `gbk_*` 自定义工具的 `gbk-engine` agent。
6
6
 
7
7
  ---
8
8
 
@@ -18,6 +18,7 @@
18
18
  | `gbk_edit` | 精确替换 GBK 文件中的指定文本块 |
19
19
  | `gbk_search` | 在 GBK 文件中搜索关键词,返回行号和上下文 |
20
20
  | 本地/全局 plugin 规则 | 给所有 agents 注入“优先使用 `text_*`”的系统提示,并统一开放 `gbk_*` 工具 |
21
+ | `gbk-engine` agent | 禁用 OpenCode 内置读写编辑工具,只保留 `text_*` / `gbk_*` 自定义工具 |
21
22
 
22
23
  ---
23
24
 
@@ -34,8 +35,9 @@ npx opencode-gbk-tools install
34
35
  - `text_read` / `text_write` / `text_edit`
35
36
  - `gbk_read` / `gbk_write` / `gbk_edit` / `gbk_search`
36
37
  - 对文本文件优先使用 `text_*` 的系统提示
38
+ - `.opencode/agents/gbk-engine.md` 或 `~/.config/opencode/agents/gbk-engine.md`
37
39
 
38
- 不再需要单独安装或切换专属 `gbk-engine` agent。
40
+ 如果你希望强制禁用内置 `read` / `write` / `edit` / `apply_patch`,可以直接切换到专属 `gbk-engine` agent。
39
41
 
40
42
  ---
41
43
 
@@ -62,7 +64,8 @@ npx opencode-gbk-tools uninstall
62
64
  - 原编码
63
65
  - BOM
64
66
  - 换行风格
65
- - 新文件在 `encoding=auto` 下不会自动默认成 `utf8`,需要显式指定 `encoding`
67
+ - 新建 `.txt` 文件在 `encoding=auto` 下默认使用 `gbk`
68
+ - 其他新文件在 `encoding=auto` 下不会自动默认成 `utf8`,仍需要显式指定 `encoding`
66
69
  - 当前支持:
67
70
  - `utf8`
68
71
  - `utf8-bom`
@@ -205,6 +208,8 @@ A:不要。现在优先用 `mode="insertAfter"` 或 `mode="insertBefore"`,
205
208
 
206
209
  | 版本 | 说明 |
207
210
  |------|------|
211
+ | 0.1.26 | 新建 `.txt` 文件在 `encoding=auto` 下默认使用 `gbk`;保留已有文件的原编码检测与保持逻辑;同步更新工具提示、README 与测试覆盖 |
212
+ | 0.1.25 | 恢复并正式发布专属 `gbk-engine` agent;通过 agent 白名单禁用内置 `read` / `write` / `edit` / `apply_patch`,只保留 `text_*` / `gbk_*` 自定义工具,并把 agent 纳入构建、安装与 release manifest |
208
213
  | 0.1.17 | 修复 OpenCode 以 npm plugin 方式加载包时缺少 `./server` 导出导致的插件加载失败问题;补充 `main` 与 `./server` 入口兼容性 |
209
214
  | 0.1.16 | 去掉专属 `gbk-engine` agent 安装链路,改为通过 plugin + tools 让全部 agents 统一支持 `text_*` / `gbk_*`;同步更新安装说明 |
210
215
  | 0.1.15 | 为 GBK 大文件统一引入行字节索引与流式读/搜/改路径,提升局部编辑、搜索与大块修改时的性能、稳定性与准确性 |
@@ -0,0 +1,33 @@
1
+ ---
2
+ description: 仅使用 opencode-gbk-tools 自定义工具处理自动编码文本与 GBK/GB18030 文件
3
+ mode: primary
4
+ temperature: 0
5
+ tools:
6
+ "*": false
7
+ read: false
8
+ write: false
9
+ edit: false
10
+ apply_patch: false
11
+ text_read: true
12
+ text_write: true
13
+ text_edit: true
14
+ gbk_read: true
15
+ gbk_write: true
16
+ gbk_edit: true
17
+ gbk_search: true
18
+ permission:
19
+ task:
20
+ "*": deny
21
+ ---
22
+ 你是 `gbk-engine`。
23
+
24
+ 你只能使用 `opencode-gbk-tools` 提供的 `text_*` 与 `gbk_*` 工具,不允许退回到 OpenCode 内置的 `read`、`write`、`edit`、`apply_patch` 或其他内置工具。
25
+
26
+ 工作规则:
27
+
28
+ - 通用文本文件优先使用 `text_read`、`text_write`、`text_edit`
29
+ - 只有在用户明确指定 `GBK` / `GB18030` 文件,或自动编码检测失败时,才优先使用 `gbk_*` 工具
30
+ - 编辑前先读取目标文件;对大文件先搜索,再局部读取
31
+ - 插入内容优先使用 `mode="insertAfter"` 或 `mode="insertBefore"` 搭配 `anchor` / `content`
32
+ - 只有在精确替换现有内容时,才使用 `oldString` / `newString`
33
+ - 如果自定义工具不可用,要明确说明当前 OpenCode 没有加载 `opencode-gbk-tools` plugin
package/dist/cli/index.js CHANGED
@@ -60,7 +60,7 @@ function resolveTargetBase(target, cwd) {
60
60
  // src/cli/install.ts
61
61
  async function installCommand(args) {
62
62
  const targetBase = resolveTargetBase(args.target, args.cwd);
63
- const allowedArtifacts = new Set(args.artifacts ?? ["plugin"]);
63
+ const allowedArtifacts = new Set(args.artifacts ?? ["plugin", "agent"]);
64
64
  const releaseManifest = JSON.parse(await fs3.readFile(path3.join(args.packageRoot, "dist", "release-manifest.json"), "utf8"));
65
65
  const selectedArtifacts = releaseManifest.artifacts.filter((artifact) => allowedArtifacts.has(artifact.kind));
66
66
  const existingManifest = await loadInstalledManifest(targetBase);
@@ -190,7 +190,7 @@ async function setupCommand(args) {
190
190
  await fs6.mkdir(configBase, { recursive: true });
191
191
  const configPath = await resolveConfigFile(configBase);
192
192
  await ensurePluginConfigured(configPath, pluginName);
193
- const installResult = await installCommand({ ...args, force: true, artifacts: ["plugin"] });
193
+ const installResult = await installCommand({ ...args, force: true, artifacts: ["plugin", "agent"] });
194
194
  return {
195
195
  configPath,
196
196
  targetBase: installResult.targetBase
@@ -16340,6 +16340,9 @@ function resolveExplicitTextEncoding(value, fallback) {
16340
16340
  const requested = value ?? "auto";
16341
16341
  return requested === "auto" ? fallback : requested;
16342
16342
  }
16343
+ function shouldDefaultNewTextFileToGbk(filePath) {
16344
+ return path3.extname(filePath).toLowerCase() === ".txt";
16345
+ }
16343
16346
  function getBomPrefix(encoding, hasBom) {
16344
16347
  if (!hasBom) {
16345
16348
  return Buffer.alloc(0);
@@ -16626,10 +16629,11 @@ async function writeTextFile(input) {
16626
16629
  if (existing && !append && !overwrite) {
16627
16630
  throw createTextError("GBK_FILE_EXISTS", `\u76EE\u6807\u6587\u4EF6\u5DF2\u5B58\u5728: ${candidatePath}`);
16628
16631
  }
16629
- if (!existing && requestedEncoding === "auto") {
16630
- throw createTextError("TEXT_UNKNOWN_ENCODING", "\u65B0\u6587\u4EF6\u5728 encoding=auto \u4E0B\u65E0\u6CD5\u786E\u5B9A\u7F16\u7801\uFF0C\u8BF7\u663E\u5F0F\u6307\u5B9A encoding");
16632
+ const newFileDefaultEncoding = !existing && requestedEncoding === "auto" && shouldDefaultNewTextFileToGbk(candidatePath) ? "gbk" : null;
16633
+ if (!existing && requestedEncoding === "auto" && !newFileDefaultEncoding) {
16634
+ throw createTextError("TEXT_UNKNOWN_ENCODING", "\u65B0\u6587\u4EF6\u5728 encoding=auto \u4E0B\u65E0\u6CD5\u786E\u5B9A\u7F16\u7801\uFF1B.txt \u65B0\u6587\u4EF6\u4F1A\u9ED8\u8BA4\u4F7F\u7528 GBK\uFF0C\u5176\u4ED6\u6587\u4EF6\u8BF7\u663E\u5F0F\u6307\u5B9A encoding");
16631
16635
  }
16632
- const targetEncoding = existing && preserveEncoding ? existing.encoding : resolveExplicitTextEncoding(requestedEncoding, existing?.encoding ?? "utf8");
16636
+ const targetEncoding = existing && preserveEncoding ? existing.encoding : requestedEncoding === "auto" && newFileDefaultEncoding ? newFileDefaultEncoding : resolveExplicitTextEncoding(requestedEncoding, existing?.encoding ?? "utf8");
16633
16637
  const targetHasBom = targetEncoding === "utf8-bom" ? true : existing && preserveEncoding ? existing.hasBom : targetEncoding === "utf16le" || targetEncoding === "utf16be" ? true : false;
16634
16638
  const baseContent = append ? existing?.content ?? "" : "";
16635
16639
  const rawContent = `${baseContent}${input.content}`;
@@ -16657,7 +16661,8 @@ var text_write_default = tool({
16657
16661
  description: `Write text files while preserving detected encoding and newline style by default.
16658
16662
 
16659
16663
  - Existing files keep their original encoding when encoding=auto.
16660
- - New files require explicit encoding when encoding=auto.
16664
+ - New .txt files default to GBK when encoding=auto.
16665
+ - Other new files still require explicit encoding when encoding=auto.
16661
16666
  - Supports append and overwrite modes.`,
16662
16667
  args: {
16663
16668
  filePath: tool.schema.string().describe("Target file path"),
@@ -18036,7 +18036,7 @@ var TEXT_TOOL_SYSTEM_PROMPT = [
18036
18036
  "\u6587\u672C\u6587\u4EF6\u5904\u7406\u89C4\u5219\uFF1A",
18037
18037
  "- \u5904\u7406\u6587\u672C\u6587\u4EF6\u65F6\uFF0C\u4F18\u5148\u4F7F\u7528 text_read\u3001text_write\u3001text_edit\u3002",
18038
18038
  "- 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",
18039
- "- \u65B0\u6587\u4EF6\u5728 encoding=auto \u4E0B\u4E0D\u4F1A\u9759\u9ED8\u9ED8\u8BA4\u6210 utf8\uFF1B\u8BF7\u663E\u5F0F\u6307\u5B9A encoding\u3002",
18039
+ "- \u65B0\u5EFA .txt \u6587\u4EF6\u5728 encoding=auto \u4E0B\u9ED8\u8BA4\u4F7F\u7528 GBK\uFF1B\u5176\u4ED6\u65B0\u6587\u4EF6\u8BF7\u663E\u5F0F\u6307\u5B9A encoding\u3002",
18040
18040
  "- \u5982\u679C\u610F\u56FE\u662F\u2018\u5728\u67D0\u6807\u7B7E\u524D\u540E\u63D2\u5165\u5185\u5BB9\u2019\uFF0C\u4F18\u5148\u4F7F\u7528 mode=insertAfter \u6216 mode=insertBefore\uFF0C\u5E76\u4F20 anchor/content\u3002",
18041
18041
  "- \u53EA\u6709\u5728\u660E\u786E\u505A\u7CBE\u786E\u66FF\u6362\u65F6\uFF0C\u624D\u4F7F\u7528 oldString/newString\u3002",
18042
18042
  "- \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",
@@ -18089,6 +18089,9 @@ function resolveExplicitTextEncoding(value, fallback) {
18089
18089
  const requested = value ?? "auto";
18090
18090
  return requested === "auto" ? fallback : requested;
18091
18091
  }
18092
+ function shouldDefaultNewTextFileToGbk(filePath) {
18093
+ return path3.extname(filePath).toLowerCase() === ".txt";
18094
+ }
18092
18095
  function getBomPrefix(encoding, hasBom) {
18093
18096
  if (!hasBom) {
18094
18097
  return Buffer.alloc(0);
@@ -18817,10 +18820,11 @@ async function writeTextFile(input) {
18817
18820
  if (existing && !append && !overwrite) {
18818
18821
  throw createTextError("GBK_FILE_EXISTS", `\u76EE\u6807\u6587\u4EF6\u5DF2\u5B58\u5728: ${candidatePath}`);
18819
18822
  }
18820
- if (!existing && requestedEncoding === "auto") {
18821
- throw createTextError("TEXT_UNKNOWN_ENCODING", "\u65B0\u6587\u4EF6\u5728 encoding=auto \u4E0B\u65E0\u6CD5\u786E\u5B9A\u7F16\u7801\uFF0C\u8BF7\u663E\u5F0F\u6307\u5B9A encoding");
18823
+ const newFileDefaultEncoding = !existing && requestedEncoding === "auto" && shouldDefaultNewTextFileToGbk(candidatePath) ? "gbk" : null;
18824
+ if (!existing && requestedEncoding === "auto" && !newFileDefaultEncoding) {
18825
+ throw createTextError("TEXT_UNKNOWN_ENCODING", "\u65B0\u6587\u4EF6\u5728 encoding=auto \u4E0B\u65E0\u6CD5\u786E\u5B9A\u7F16\u7801\uFF1B.txt \u65B0\u6587\u4EF6\u4F1A\u9ED8\u8BA4\u4F7F\u7528 GBK\uFF0C\u5176\u4ED6\u6587\u4EF6\u8BF7\u663E\u5F0F\u6307\u5B9A encoding");
18822
18826
  }
18823
- const targetEncoding = existing && preserveEncoding ? existing.encoding : resolveExplicitTextEncoding(requestedEncoding, existing?.encoding ?? "utf8");
18827
+ const targetEncoding = existing && preserveEncoding ? existing.encoding : requestedEncoding === "auto" && newFileDefaultEncoding ? newFileDefaultEncoding : resolveExplicitTextEncoding(requestedEncoding, existing?.encoding ?? "utf8");
18824
18828
  const targetHasBom = targetEncoding === "utf8-bom" ? true : existing && preserveEncoding ? existing.hasBom : targetEncoding === "utf16le" || targetEncoding === "utf16be" ? true : false;
18825
18829
  const baseContent = append ? existing?.content ?? "" : "";
18826
18830
  const rawContent = `${baseContent}${input.content}`;
@@ -19063,7 +19067,8 @@ var text_write_default = tool({
19063
19067
  description: `Write text files while preserving detected encoding and newline style by default.
19064
19068
 
19065
19069
  - Existing files keep their original encoding when encoding=auto.
19066
- - New files require explicit encoding when encoding=auto.
19070
+ - New .txt files default to GBK when encoding=auto.
19071
+ - Other new files still require explicit encoding when encoding=auto.
19067
19072
  - Supports append and overwrite modes.`,
19068
19073
  args: {
19069
19074
  filePath: tool.schema.string().describe("Target file path"),
@@ -18036,7 +18036,7 @@ var TEXT_TOOL_SYSTEM_PROMPT = [
18036
18036
  "\u6587\u672C\u6587\u4EF6\u5904\u7406\u89C4\u5219\uFF1A",
18037
18037
  "- \u5904\u7406\u6587\u672C\u6587\u4EF6\u65F6\uFF0C\u4F18\u5148\u4F7F\u7528 text_read\u3001text_write\u3001text_edit\u3002",
18038
18038
  "- 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",
18039
- "- \u65B0\u6587\u4EF6\u5728 encoding=auto \u4E0B\u4E0D\u4F1A\u9759\u9ED8\u9ED8\u8BA4\u6210 utf8\uFF1B\u8BF7\u663E\u5F0F\u6307\u5B9A encoding\u3002",
18039
+ "- \u65B0\u5EFA .txt \u6587\u4EF6\u5728 encoding=auto \u4E0B\u9ED8\u8BA4\u4F7F\u7528 GBK\uFF1B\u5176\u4ED6\u65B0\u6587\u4EF6\u8BF7\u663E\u5F0F\u6307\u5B9A encoding\u3002",
18040
18040
  "- \u5982\u679C\u610F\u56FE\u662F\u2018\u5728\u67D0\u6807\u7B7E\u524D\u540E\u63D2\u5165\u5185\u5BB9\u2019\uFF0C\u4F18\u5148\u4F7F\u7528 mode=insertAfter \u6216 mode=insertBefore\uFF0C\u5E76\u4F20 anchor/content\u3002",
18041
18041
  "- \u53EA\u6709\u5728\u660E\u786E\u505A\u7CBE\u786E\u66FF\u6362\u65F6\uFF0C\u624D\u4F7F\u7528 oldString/newString\u3002",
18042
18042
  "- \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",
@@ -18089,6 +18089,9 @@ function resolveExplicitTextEncoding(value, fallback) {
18089
18089
  const requested = value ?? "auto";
18090
18090
  return requested === "auto" ? fallback : requested;
18091
18091
  }
18092
+ function shouldDefaultNewTextFileToGbk(filePath) {
18093
+ return path3.extname(filePath).toLowerCase() === ".txt";
18094
+ }
18092
18095
  function getBomPrefix(encoding, hasBom) {
18093
18096
  if (!hasBom) {
18094
18097
  return Buffer.alloc(0);
@@ -18817,10 +18820,11 @@ async function writeTextFile(input) {
18817
18820
  if (existing && !append && !overwrite) {
18818
18821
  throw createTextError("GBK_FILE_EXISTS", `\u76EE\u6807\u6587\u4EF6\u5DF2\u5B58\u5728: ${candidatePath}`);
18819
18822
  }
18820
- if (!existing && requestedEncoding === "auto") {
18821
- throw createTextError("TEXT_UNKNOWN_ENCODING", "\u65B0\u6587\u4EF6\u5728 encoding=auto \u4E0B\u65E0\u6CD5\u786E\u5B9A\u7F16\u7801\uFF0C\u8BF7\u663E\u5F0F\u6307\u5B9A encoding");
18823
+ const newFileDefaultEncoding = !existing && requestedEncoding === "auto" && shouldDefaultNewTextFileToGbk(candidatePath) ? "gbk" : null;
18824
+ if (!existing && requestedEncoding === "auto" && !newFileDefaultEncoding) {
18825
+ throw createTextError("TEXT_UNKNOWN_ENCODING", "\u65B0\u6587\u4EF6\u5728 encoding=auto \u4E0B\u65E0\u6CD5\u786E\u5B9A\u7F16\u7801\uFF1B.txt \u65B0\u6587\u4EF6\u4F1A\u9ED8\u8BA4\u4F7F\u7528 GBK\uFF0C\u5176\u4ED6\u6587\u4EF6\u8BF7\u663E\u5F0F\u6307\u5B9A encoding");
18822
18826
  }
18823
- const targetEncoding = existing && preserveEncoding ? existing.encoding : resolveExplicitTextEncoding(requestedEncoding, existing?.encoding ?? "utf8");
18827
+ const targetEncoding = existing && preserveEncoding ? existing.encoding : requestedEncoding === "auto" && newFileDefaultEncoding ? newFileDefaultEncoding : resolveExplicitTextEncoding(requestedEncoding, existing?.encoding ?? "utf8");
18824
18828
  const targetHasBom = targetEncoding === "utf8-bom" ? true : existing && preserveEncoding ? existing.hasBom : targetEncoding === "utf16le" || targetEncoding === "utf16be" ? true : false;
18825
18829
  const baseContent = append ? existing?.content ?? "" : "";
18826
18830
  const rawContent = `${baseContent}${input.content}`;
@@ -19063,7 +19067,8 @@ var text_write_default = tool({
19063
19067
  description: `Write text files while preserving detected encoding and newline style by default.
19064
19068
 
19065
19069
  - Existing files keep their original encoding when encoding=auto.
19066
- - New files require explicit encoding when encoding=auto.
19070
+ - New .txt files default to GBK when encoding=auto.
19071
+ - Other new files still require explicit encoding when encoding=auto.
19067
19072
  - Supports append and overwrite modes.`,
19068
19073
  args: {
19069
19074
  filePath: tool.schema.string().describe("Target file path"),
@@ -1,12 +1,18 @@
1
1
  {
2
2
  "manifestVersion": 1,
3
3
  "packageName": "opencode-gbk-tools",
4
- "packageVersion": "0.1.24",
4
+ "packageVersion": "0.1.26",
5
5
  "artifacts": [
6
6
  {
7
7
  "relativePath": "plugins/opencode-gbk-tools.js",
8
8
  "kind": "plugin",
9
- "expectedHash": "55f2eae379bf3bd5a9129fbc413f255a4ffd9186d90a4fe26ecb3cc75b5a4c68",
9
+ "expectedHash": "fd233ebb174994213fa19d2aab801812ce9065efbdddceb3048989efe1723963",
10
+ "hashAlgorithm": "sha256"
11
+ },
12
+ {
13
+ "relativePath": "agents/gbk-engine.md",
14
+ "kind": "agent",
15
+ "expectedHash": "05a97cfe24d72339e45616638d0706d46c0d3782a3bfedefa1e59978adc5c3be",
10
16
  "hashAlgorithm": "sha256"
11
17
  }
12
18
  ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-gbk-tools",
3
- "version": "0.1.24",
3
+ "version": "0.1.26",
4
4
  "description": "Auto-encoding text tools plus GBK/GB18030 tools for OpenCode",
5
5
  "type": "module",
6
6
  "main": "./dist/plugin/index.js",