opencode-gbk-tools 0.1.1 → 0.1.3

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
@@ -13,6 +13,24 @@
13
13
 
14
14
  推荐方式:直接作为 OpenCode npm plugin 加载工具。
15
15
 
16
+ 最方便的一键接入:
17
+
18
+ ```bash
19
+ npx opencode-gbk-tools setup --project
20
+ ```
21
+
22
+ 这条命令会自动:
23
+
24
+ - 在当前项目写入或更新 `opencode.json`
25
+ - 自动加入 `plugin: ["opencode-gbk-tools"]`
26
+ - 安装 `.opencode/agents/gbk-engine.md`
27
+
28
+ 如果你想装到用户全局 OpenCode 配置:
29
+
30
+ ```bash
31
+ npx opencode-gbk-tools setup
32
+ ```
33
+
16
34
  `opencode.json`:
17
35
 
18
36
  ```json
@@ -30,6 +48,8 @@
30
48
 
31
49
  如果你还需要预置 `gbk-engine` agent,请继续使用下面的 CLI 安装方式把 agent 文件写入本地配置目录。
32
50
 
51
+ 推荐优先使用 `setup`,`install` 更适合手动拆分安装流程。
52
+
33
53
  一次性使用:
34
54
 
35
55
  ```bash
@@ -41,6 +61,7 @@ npx opencode-gbk-tools install
41
61
  ```bash
42
62
  npm install -g opencode-gbk-tools
43
63
  opencode-gbk install
64
+ opencode-gbk setup
44
65
  ```
45
66
 
46
67
  安装到当前项目:
@@ -57,6 +78,9 @@ opencode-gbk install --project
57
78
  ## CLI
58
79
 
59
80
  ```bash
81
+ opencode-gbk setup
82
+ opencode-gbk setup --project
83
+
60
84
  opencode-gbk install
61
85
  opencode-gbk install --project
62
86
  opencode-gbk install --force
@@ -75,6 +99,7 @@ opencode-gbk doctor --project
75
99
  说明:
76
100
 
77
101
  - npm `plugin` 方式负责注册 `gbk_read`、`gbk_write`、`gbk_edit`
102
+ - `setup` 会自动写入 `plugin` 配置并安装 `gbk-engine`
78
103
  - `gbk-engine` 仍通过 CLI 安装到 `.opencode/agents/` 或 `~/.config/opencode/agents/`
79
104
  - 如果你只需要工具,不需要 agent,只配置 `plugin` 即可
80
105
 
@@ -93,6 +118,14 @@ opencode-gbk doctor --project
93
118
  - `edit: deny` 在 OpenCode 中会一起限制内置 `write`、`patch`、`multiedit`
94
119
  - 对无法映射的字符沿用 `iconv-lite` 默认替代行为
95
120
 
121
+ ## 大文件建议
122
+
123
+ - `gbk_read` 支持 `tail` 预览最后 N 行
124
+ - `gbk_read` 返回 `fileSize`、`newlineStyle`、`streamed`、`truncated`
125
+ - `gbk_edit` 支持 `startLine/endLine`
126
+ - `gbk_edit` 支持 `startAnchor/endAnchor`
127
+ - 大文件会自动走更省内存的流式路径
128
+
96
129
  ## 发布
97
130
 
98
131
  ```bash
@@ -18,6 +18,8 @@ permission:
18
18
  - 读取文件时优先使用 `gbk_read`
19
19
  - 创建或覆盖文件时优先使用 `gbk_write`
20
20
  - 修改已有文件时优先使用 `gbk_edit`
21
+ - 大文件读取优先使用 `gbk_read` 的分页或 `tail` 能力,避免一次读取过多内容
22
+ - 修改时优先缩小编辑范围:能用 `startLine/endLine` 或 `startAnchor/endAnchor` 就不要全文替换
21
23
  - 文件发现可使用 `glob`,但文件内容读取必须使用 `gbk_read`
22
24
  - 禁止依赖内置 `read`、`grep`、`write`、`edit`、`patch`
23
25
  - `edit: deny` 同时覆盖内置 `write`、`patch`、`multiedit`
package/dist/cli/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/cli/index.ts
2
- import path6 from "path";
2
+ import path7 from "path";
3
3
  import { fileURLToPath } from "url";
4
4
 
5
5
  // src/cli/install.ts
@@ -60,9 +60,11 @@ 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 ?? ["tool", "agent"]);
63
64
  const releaseManifest = JSON.parse(await fs3.readFile(path3.join(args.packageRoot, "dist", "release-manifest.json"), "utf8"));
65
+ const selectedArtifacts = releaseManifest.artifacts.filter((artifact) => allowedArtifacts.has(artifact.kind));
64
66
  const existingManifest = await loadInstalledManifest(targetBase);
65
- for (const artifact of releaseManifest.artifacts) {
67
+ for (const artifact of selectedArtifacts) {
66
68
  const targetPath = path3.join(targetBase, artifact.relativePath);
67
69
  if (await pathExists(targetPath) && !existingManifest && !args.force) {
68
70
  throw new Error(`\u68C0\u6D4B\u5230\u672A\u53D7\u7BA1\u6587\u4EF6\u51B2\u7A81: ${targetPath}`);
@@ -78,13 +80,13 @@ async function installCommand(args) {
78
80
  targetType: args.target,
79
81
  targetBase,
80
82
  installedAt: (/* @__PURE__ */ new Date()).toISOString(),
81
- files: releaseManifest.artifacts.map((artifact) => ({
83
+ files: selectedArtifacts.map((artifact) => ({
82
84
  ...artifact,
83
85
  installedByVersion: releaseManifest.packageVersion
84
86
  }))
85
87
  };
86
88
  await writeInstalledManifest(targetBase, installedManifest);
87
- return { targetBase };
89
+ return { targetBase, installedFiles: selectedArtifacts.length };
88
90
  }
89
91
 
90
92
  // src/cli/uninstall.ts
@@ -131,13 +133,68 @@ async function doctorCommand(args) {
131
133
  return { ok: issues.length === 0, issues };
132
134
  }
133
135
 
136
+ // src/cli/setup.ts
137
+ import fs6 from "fs/promises";
138
+ import path6 from "path";
139
+ import os2 from "os";
140
+ import { applyEdits, modify, parse } from "jsonc-parser";
141
+ async function resolveConfigFile(baseDir) {
142
+ const jsoncPath = path6.join(baseDir, "opencode.jsonc");
143
+ const jsonPath = path6.join(baseDir, "opencode.json");
144
+ try {
145
+ await fs6.access(jsoncPath);
146
+ return jsoncPath;
147
+ } catch {
148
+ try {
149
+ await fs6.access(jsonPath);
150
+ return jsonPath;
151
+ } catch {
152
+ return jsonPath;
153
+ }
154
+ }
155
+ }
156
+ async function ensurePluginConfigured(configPath, pluginName) {
157
+ let content = '{\n "$schema": "https://opencode.ai/config.json"\n}\n';
158
+ try {
159
+ content = await fs6.readFile(configPath, "utf8");
160
+ } catch {
161
+ }
162
+ const parsed = parse(content);
163
+ const plugins = parsed?.plugin ?? [];
164
+ if (plugins.includes(pluginName)) {
165
+ return configPath;
166
+ }
167
+ const edits = modify(content, ["plugin"], [...plugins, pluginName], {
168
+ formattingOptions: {
169
+ insertSpaces: true,
170
+ tabSize: 2,
171
+ eol: "\n"
172
+ }
173
+ });
174
+ const updated = applyEdits(content, edits);
175
+ await fs6.writeFile(configPath, updated, "utf8");
176
+ return configPath;
177
+ }
178
+ async function setupCommand(args) {
179
+ const pluginName = "opencode-gbk-tools";
180
+ const configBase = args.target === "project" ? args.cwd : path6.join(os2.homedir(), ".config", "opencode");
181
+ await fs6.mkdir(configBase, { recursive: true });
182
+ const configPath = await resolveConfigFile(configBase);
183
+ await ensurePluginConfigured(configPath, pluginName);
184
+ const installResult = await installCommand({ ...args, force: true, artifacts: ["agent"] });
185
+ return {
186
+ configPath,
187
+ targetBase: installResult.targetBase
188
+ };
189
+ }
190
+
134
191
  // src/cli/index.ts
135
192
  function resolvePackageRoot(env = process.env, moduleUrl = import.meta.url) {
136
193
  if (env.OPENCODE_GBK_PACKAGE_ROOT) {
137
194
  return env.OPENCODE_GBK_PACKAGE_ROOT;
138
195
  }
139
196
  const modulePath = fileURLToPath(moduleUrl);
140
- return path6.resolve(path6.dirname(modulePath), "..", "..");
197
+ return path7.resolve(path7.dirname(modulePath), "..", "..");
141
198
  }
142
199
  async function main(argv, env = process.env) {
143
200
  const [command, ...rest] = argv;
@@ -148,6 +205,9 @@ async function main(argv, env = process.env) {
148
205
  if (command === "install") {
149
206
  return await installCommand({ packageRoot, target, cwd, force });
150
207
  }
208
+ if (command === "setup") {
209
+ return await setupCommand({ packageRoot, target, cwd });
210
+ }
151
211
  if (command === "uninstall") {
152
212
  return await uninstallCommand({ target, cwd });
153
213
  }