@tachikomagundam/abathur 0.2.1 → 0.2.2

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
@@ -139,8 +139,10 @@ abathur run --genome toy-smoke --dry-run # plan + requires[] probes, zero sp
139
139
  ### Inside opencode
140
140
 
141
141
  Abathur ships an official opencode plugin adapter. The harness remains the
142
- orchestrator, but once installed an opencode session can also drive the CLI
143
- directly:
142
+ orchestrator, but once set up an opencode session can also drive the CLI
143
+ directly. Two install routes:
144
+
145
+ **Route A — one command (tool + `/abathur` slash command).**
144
146
 
145
147
  ```bash
146
148
  npm i -g @tachikomagundam/abathur
@@ -148,7 +150,22 @@ abathur opencode install # copies plugin assets into ~/.config/opencode/
148
150
  # restart opencode
149
151
  ```
150
152
 
151
- After a restart the session gets two things:
153
+ **Route B config only (tool, no slash command).** Put the package name in
154
+ your opencode config and restart:
155
+
156
+ ```jsonc
157
+ { "plugin": ["@tachikomagundam/abathur"] }
158
+ ```
159
+
160
+ opencode then downloads the package from npm at startup into its own cache
161
+ (`~/.cache/opencode/packages/…`) and loads the package's `./server` export —
162
+ no file copying, no uninstall step (delete the line). Two honest limits: the
163
+ `abathur` **CLI** still must exist on `PATH` (or `ABATHUR_BIN`) because the
164
+ tool spawns it, so keep the `npm i -g` install; and slash commands are plain
165
+ markdown files that plugins cannot register upstream, so `/abathur` is Route A
166
+ only.
167
+
168
+ Either route gives the session:
152
169
 
153
170
  - the agent tool **`abathur`** — spawns the `abathur` CLI argv-only (never a
154
171
  shell), restricted to eight commands (`genome`, `run`, `status`, `bundle`,
@@ -159,11 +176,13 @@ After a restart the session gets two things:
159
176
  so the allowlist limits typos and UX, not capability. `promote` and
160
177
  `tombstone` are deliberately NOT reachable through the tool: they are
161
178
  human gates and must be run in a terminal.
162
- - the user command **`/abathur <args…>`** — a slash command that tells the
163
- agent to translate its arguments into a tool call and report the exit code.
179
+ - the user command **`/abathur <args…>`** (Route A only) — a slash command
180
+ that tells the agent to translate its arguments into a tool call and report
181
+ the exit code.
164
182
 
165
- `abathur opencode status` shows each target's path, installed/packaged sha256,
166
- and state (up-to-date / outdated / foreign / absent).
183
+ Route A ships its own manager commands: `abathur opencode status` shows each
184
+ target's path, installed/packaged sha256, and state (up-to-date / outdated /
185
+ foreign / absent).
167
186
  `abathur opencode uninstall` removes only files carrying the abathur marker; a
168
187
  foreign file at a target path makes both commands refuse with exit 2 and name
169
188
  the path — nothing is ever overwritten or deleted behind your back (there is
@@ -408,8 +427,10 @@ abathur run --genome toy-smoke --dry-run # 计划 + requires[] 探针,零
408
427
 
409
428
  ### 在 opencode 里调用
410
429
 
411
- Abathur 自带官方 opencode 插件适配器。工装仍是编排者,但安装之后,opencode
412
- 会话也可以直接驱动 CLI
430
+ Abathur 自带官方 opencode 插件适配器。工装仍是编排者,但配置之后,opencode
431
+ 会话也可以直接驱动 CLI。安装有两条路线:
432
+
433
+ **路线 A——一条命令(工具 + `/abathur` 斜杠命令)。**
413
434
 
414
435
  ```bash
415
436
  npm i -g @tachikomagundam/abathur
@@ -417,7 +438,21 @@ abathur opencode install # 把插件资产复制进 ~/.config/opencode/
417
438
  # 重启 opencode
418
439
  ```
419
440
 
420
- 重启后会话获得两样东西:
441
+ **路线 B——纯配置(只有工具,没有斜杠命令)。** 把包名写进 opencode 配置再
442
+ 重启:
443
+
444
+ ```jsonc
445
+ { "plugin": ["@tachikomagundam/abathur"] }
446
+ ```
447
+
448
+ opencode 会在启动时自行从 npm 把包下载到它自己的缓存
449
+ (`~/.cache/opencode/packages/…`)并加载该包的 `./server` 导出——不复制文件,
450
+ 也没有 uninstall 步骤(删掉那行即可)。两点诚实的限制:工具 spawn 的是
451
+ `abathur` **CLI**,所以 CLI 仍必须在 `PATH`(或 `ABATHUR_BIN`)上可达,
452
+ `npm i -g` 不能省;而斜杠命令在上游只是 markdown 文件、插件无法注册,
453
+ 所以 `/abathur` 只有路线 A 提供。
454
+
455
+ 任一路线都会让会话获得:
421
456
 
422
457
  - 智能体工具 **`abathur`**——以纯 argv 方式 spawn `abathur` CLI(绝不经过
423
458
  shell),顶层命令限定为八个(`genome`、`run`、`status`、`bundle`、`graft`、
@@ -426,10 +461,11 @@ abathur opencode install # 把插件资产复制进 ~/.config/opencode/
426
461
  bash 等同的权限——`run` 与 `genome` 按设计就会 spawn 变异器/引擎二进制——
427
462
  所以允许清单限制的是笔误与体验,而非能力。`promote` 与 `tombstone` 刻意
428
463
  不可经由工具触达:它们是人类闸门,必须在终端里运行。
429
- - 用户命令 **`/abathur <参数…>`**——斜杠命令,指示智能体把参数翻译成工具调用
430
- 并回报退出码。
464
+ - 用户命令 **`/abathur <参数…>`**(仅路线 A)——斜杠命令,指示智能体把参数
465
+ 翻译成工具调用并回报退出码。
431
466
 
432
- `abathur opencode status` 逐目标打印路径、已安装/随包 sha256 与状态
467
+ 路线 A 自带管理命令:`abathur opencode status` 逐目标打印路径、已安装/随包
468
+ sha256 与状态
433
469
  (up-to-date / outdated / foreign / absent)。
434
470
  `abathur opencode uninstall` 只删除带有 abathur 标记的文件;若目标路径上躺着
435
471
  别人的文件,两条命令都会 exit 2 并点名路径——绝不会背着你覆盖或删除任何东西
@@ -255,6 +255,26 @@ test("shipped plugin assets carry zero machine literals (D7 discipline extended
255
255
  }
256
256
  }
257
257
  });
258
+ test("npm name route: exports['./server'] ships the marker'd plugin + runtime dep declared", async () => {
259
+ const pkg = JSON.parse(await readFile(path.join(repoRoot, "package.json"), "utf8"));
260
+ // opencode picks the server entry via exports["./server"] (extractExportValue
261
+ // accepts a plain string; plugin/shared.ts resolvePackageEntrypoint).
262
+ const serverEntry = pkg.exports?.["./server"];
263
+ assert.equal(typeof serverEntry, "string", "./server export must be a plain string path");
264
+ const server = serverEntry;
265
+ const target = path.resolve(repoRoot, server);
266
+ const head = (await readFile(target, "utf8")).split("\n")[0] ?? "";
267
+ assert.ok(head.startsWith(PLUGIN_MARKER), `server entry must start with the plugin marker: ${head}`);
268
+ // The tarball must actually contain that file or the name route installs nothing to import.
269
+ assert.ok((pkg.files ?? []).some((entry) => server.startsWith(`./${entry}/`)), "server entry must live under a published files[] directory");
270
+ // Arborist installs the package's dependencies next to it in opencode's cache —
271
+ // that sibling copy is how the shipped import of @opencode-ai/plugin resolves (OMO mechanism).
272
+ const dep = pkg.dependencies?.["@opencode-ai/plugin"];
273
+ assert.equal(typeof dep, "string", "@opencode-ai/plugin must be a runtime dependency");
274
+ assert.ok((dep ?? "").length > 0, "dependency range must not be empty");
275
+ // Route B must serve the same bytes the route A installer copies: both resolve to plugin/abathur.ts.
276
+ assert.equal(serverEntry, "./plugin/abathur.ts", "server entry and installer asset must be one file");
277
+ });
258
278
  test("CLI help: opencode is a registered top-level command", async (t) => {
259
279
  const { env } = await makeEnv(t);
260
280
  const help = abathur(env, "--help");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tachikomagundam/abathur",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Evolution harness: observe failures, mutate, re-bench, select — human-gated promotion, offline lineage bundles.",
5
5
  "author": "TachikomaGundam",
6
6
  "type": "module",
@@ -20,6 +20,11 @@
20
20
  "abathur": "dist/cli.js"
21
21
  },
22
22
  "main": "dist/cli.js",
23
+ "exports": {
24
+ ".": "./dist/cli.js",
25
+ "./server": "./plugin/abathur.ts",
26
+ "./package.json": "./package.json"
27
+ },
23
28
  "files": [
24
29
  "dist",
25
30
  "config",
@@ -33,6 +38,7 @@
33
38
  "prepack": "npm run build"
34
39
  },
35
40
  "dependencies": {
41
+ "@opencode-ai/plugin": "^1.17.4",
36
42
  "zod": "^4.0.0"
37
43
  },
38
44
  "devDependencies": {
package/plugin/abathur.ts CHANGED
@@ -1,4 +1,4 @@
1
- // abathur-opencode-plugin v0.2.1
1
+ // abathur-opencode-plugin v0.2.2
2
2
  // Official opencode plugin adapter for the abathur evolution harness.
3
3
  // Registers ONE agent tool, `abathur`, that shells out to the abathur CLI —
4
4
  // argv-only (node:child_process execFile, never a shell), top-level commands
@@ -8,10 +8,15 @@
8
8
  // V1 plugin format (opencode >= 1.14): default export { id, server }, where
9
9
  // server(input, options) resolves to Hooks; Hooks.tool is a
10
10
  // { [name]: ToolDefinition } record (see @opencode-ai/plugin).
11
- // This file is shipped as-is (package.json "files") and copied into
12
- // ~/.config/opencode/plugins/ by `abathur opencode install`. It is NOT
13
- // compiled by abathur's tsc; "@opencode-ai/plugin" resolves inside opencode's
14
- // own config-directory install.
11
+ // This file is shipped as-is (package.json "files") and reaches a session by
12
+ // two routes, neither compiling it through abathur's tsc:
13
+ // (A) copied into ~/.config/opencode/plugins/ by `abathur opencode install`
14
+ // (adds the /abathur command too); "@opencode-ai/plugin" then resolves in
15
+ // opencode's config-directory node_modules.
16
+ // (B) served as the package's "./server" export when the npm package name is
17
+ // listed in opencode.jsonc "plugin" — opencode's arborist install places
18
+ // @opencode-ai/plugin (runtime dependency) next to the package in its
19
+ // cache, so the same import resolves there too.
15
20
 
16
21
  import { execFile } from "node:child_process";
17
22
  import { tool } from "@opencode-ai/plugin";