@ken-jo/agent-connector 0.3.1 → 0.4.0
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 +178 -14
- package/dist/action-PLZW5BGX.js +54 -0
- package/dist/action-PLZW5BGX.js.map +1 -0
- package/dist/{amp-YGV66GJT.js → amp-B524U6LO.js} +81 -5
- package/dist/amp-B524U6LO.js.map +1 -0
- package/dist/{antigravity-7IBYFO6P.js → antigravity-ANDKF3K7.js} +4 -4
- package/dist/{antigravity-cli-JEOUP2VN.js → antigravity-cli-LLRPDDOT.js} +4 -4
- package/dist/chunk-22Y24V7O.js +21 -0
- package/dist/chunk-22Y24V7O.js.map +1 -0
- package/dist/chunk-3PFFTFCU.js +190 -0
- package/dist/chunk-3PFFTFCU.js.map +1 -0
- package/dist/{chunk-SCVBYSF7.js → chunk-6XHB6BE3.js} +1 -1
- package/dist/chunk-76FUSVIA.js +43 -0
- package/dist/chunk-76FUSVIA.js.map +1 -0
- package/dist/{chunk-GSGDG2BV.js → chunk-ADTHT2FN.js} +109 -16
- package/dist/chunk-ADTHT2FN.js.map +1 -0
- package/dist/{chunk-ZAM4M7LI.js → chunk-BHUCB6LY.js} +135 -296
- package/dist/chunk-BHUCB6LY.js.map +1 -0
- package/dist/{chunk-MEH7GC7R.js → chunk-BXGFUENQ.js} +20 -3
- package/dist/chunk-BXGFUENQ.js.map +1 -0
- package/dist/chunk-CIRDOY2V.js +351 -0
- package/dist/chunk-CIRDOY2V.js.map +1 -0
- package/dist/{chunk-KMAKDD3Z.js → chunk-G3ER4SY5.js} +37 -12
- package/dist/chunk-G3ER4SY5.js.map +1 -0
- package/dist/{chunk-PD4VFEBY.js → chunk-IW77FFNX.js} +39 -1
- package/dist/chunk-IW77FFNX.js.map +1 -0
- package/dist/chunk-J3D5W5T2.js +83 -0
- package/dist/chunk-J3D5W5T2.js.map +1 -0
- package/dist/{openclaw-UZ5BMCGQ.js → chunk-KGGBNKI4.js} +125 -33
- package/dist/chunk-KGGBNKI4.js.map +1 -0
- package/dist/{chunk-3JCRUROU.js → chunk-KGJWE6A2.js} +13 -4
- package/dist/chunk-KGJWE6A2.js.map +1 -0
- package/dist/{chunk-3RBLIHPZ.js → chunk-KGXDYGNJ.js} +26 -16
- package/dist/chunk-KGXDYGNJ.js.map +1 -0
- package/dist/{chunk-KVAAFYRR.js → chunk-KHO5WNTP.js} +2 -18
- package/dist/chunk-KHO5WNTP.js.map +1 -0
- package/dist/{chunk-KQSNDFBN.js → chunk-LL4OBGRU.js} +3 -3
- package/dist/{chunk-WNREHWKL.js → chunk-MAH6QQTO.js} +3 -3
- package/dist/{claude-code-4275HQU4.js → claude-code-MLWS7CW6.js} +180 -28
- package/dist/claude-code-MLWS7CW6.js.map +1 -0
- package/dist/cli/sdk.js +4 -3
- package/dist/cli/sdk.js.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/{codebuff-LE3KBZGM.js → codebuff-SH2S3QAN.js} +102 -5
- package/dist/codebuff-SH2S3QAN.js.map +1 -0
- package/dist/{codex-4BY2ZJIW.js → codex-BXA4FIF4.js} +3 -3
- package/dist/{copilot-cli-IPISKO3V.js → copilot-cli-ROIBTTDT.js} +3 -3
- package/dist/{crush-X3E25EQG.js → crush-QLEFLHUC.js} +3 -3
- package/dist/{cursor-UH3W622V.js → cursor-ASJPWZ4R.js} +6 -3
- package/dist/cursor-ASJPWZ4R.js.map +1 -0
- package/dist/{detect-U3E7NVNW.js → detect-ZIIS55LD.js} +4 -3
- package/dist/{detect-U3E7NVNW.js.map → detect-ZIIS55LD.js.map} +1 -1
- package/dist/{doctor-DZTWED4O.js → doctor-TJUGSQ5C.js} +16 -12
- package/dist/doctor-TJUGSQ5C.js.map +1 -0
- package/dist/{droid-T5VBRXZF.js → droid-NCSS3B5Y.js} +170 -4
- package/dist/droid-NCSS3B5Y.js.map +1 -0
- package/dist/{gemini-cli-ZSUK55UA.js → gemini-cli-SLVWLXJW.js} +3 -3
- package/dist/{goose-M3RR3CZG.js → goose-PBA7KTE5.js} +100 -5
- package/dist/goose-PBA7KTE5.js.map +1 -0
- package/dist/{hermes-CUNKIAR5.js → hermes-ONDCECP2.js} +3 -3
- package/dist/{hook-EVY7LOUQ.js → hook-OU522ABV.js} +12 -9
- package/dist/{hook-EVY7LOUQ.js.map → hook-OU522ABV.js.map} +1 -1
- package/dist/index.d.ts +71 -3
- package/dist/index.js +22 -3
- package/dist/{install-OWAS5UIE.js → install-UDCBL7HP.js} +11 -9
- package/dist/{install-OWAS5UIE.js.map → install-UDCBL7HP.js.map} +1 -1
- package/dist/introspect-DuZSPSHB.d.ts +53 -0
- package/dist/{jetbrains-copilot-C3HDGGML.js → jetbrains-copilot-YABZ3HFA.js} +3 -3
- package/dist/{kilo-PKAJCWPX.js → kilo-F3ZDZKCT.js} +3 -3
- package/dist/{kilo-cli-QWUVXG2O.js → kilo-cli-3HWPWBY4.js} +3 -3
- package/dist/{kimi-EVD7YKXS.js → kimi-NV72FVAO.js} +3 -3
- package/dist/{kiro-UQRY6EIO.js → kiro-C5W6AGDR.js} +3 -3
- package/dist/{leaderboard-CSWHI4UY.js → leaderboard-TIBVONVT.js} +3 -3
- package/dist/mimo-code-IMM5YM3M.js +754 -0
- package/dist/mimo-code-IMM5YM3M.js.map +1 -0
- package/dist/{mux-5CI5FP2W.js → mux-DSSH4AFS.js} +3 -3
- package/dist/nemoclaw-3EVNKD3I.js +58 -0
- package/dist/nemoclaw-3EVNKD3I.js.map +1 -0
- package/dist/{omp-AXA7XY22.js → omp-Z6FRNDPN.js} +3 -3
- package/dist/openclaw-7G437NT7.js +18 -0
- package/dist/openclaw-7G437NT7.js.map +1 -0
- package/dist/{opencode-NZBRLJN3.js → opencode-Q6KBSAKW.js} +3 -3
- package/dist/{package-WFOS4QVU.js → package-RMPN57YZ.js} +7 -6
- package/dist/{package-WFOS4QVU.js.map → package-RMPN57YZ.js.map} +1 -1
- package/dist/{pi-WMTUX6ES.js → pi-LZT6WWAZ.js} +2 -2
- package/dist/{qwen-code-MRRIUQ3P.js → qwen-code-WQBKRPWJ.js} +3 -3
- package/dist/{roo-code-NI5UU6JB.js → roo-code-GWSNU3OW.js} +137 -4
- package/dist/roo-code-GWSNU3OW.js.map +1 -0
- package/dist/runtime/index.d.ts +96 -2
- package/dist/runtime/index.js +18 -10
- package/dist/sdk/index.d.ts +52 -0
- package/dist/sdk/index.js +81 -0
- package/dist/sdk/index.js.map +1 -0
- package/dist/sdk/test.d.ts +74 -0
- package/dist/sdk/test.js +291 -0
- package/dist/sdk/test.js.map +1 -0
- package/dist/{serve-3C2VFPAY.js → serve-D3GO36UT.js} +12 -9
- package/dist/{serve-3C2VFPAY.js.map → serve-D3GO36UT.js.map} +1 -1
- package/dist/{status-MKQYX5MW.js → status-KOSKCETC.js} +9 -7
- package/dist/{status-MKQYX5MW.js.map → status-KOSKCETC.js.map} +1 -1
- package/dist/statusline-ZNTCL5YC.js +59 -0
- package/dist/statusline-ZNTCL5YC.js.map +1 -0
- package/dist/{telemetry-3DN6XGYB.js → telemetry-XIKUUGTQ.js} +5 -4
- package/dist/{telemetry-3DN6XGYB.js.map → telemetry-XIKUUGTQ.js.map} +1 -1
- package/dist/{trae-CQC72RHH.js → trae-NWT3TMSZ.js} +99 -5
- package/dist/trae-NWT3TMSZ.js.map +1 -0
- package/dist/{types-CNigfEuR.d.ts → types-BEKsAium.d.ts} +268 -6
- package/dist/{uninstall-WG6PFWF3.js → uninstall-2LBLQVFA.js} +11 -9
- package/dist/{uninstall-WG6PFWF3.js.map → uninstall-2LBLQVFA.js.map} +1 -1
- package/dist/{upgrade-32NC2RKI.js → upgrade-ZC2S7VRN.js} +11 -9
- package/dist/{upgrade-32NC2RKI.js.map → upgrade-ZC2S7VRN.js.map} +1 -1
- package/dist/{usage-CJOM2WQM.js → usage-E2A4O2CY.js} +3 -3
- package/dist/{usage-event-472X3DOY.js → usage-event-JKMC4QC4.js} +11 -8
- package/dist/{usage-event-472X3DOY.js.map → usage-event-JKMC4QC4.js.map} +1 -1
- package/dist/{vscode-copilot-4RVRTCKV.js → vscode-copilot-ALV45XF6.js} +3 -3
- package/dist/{warp-X6MB67NT.js → warp-H6IX4U3J.js} +3 -3
- package/dist/{zed-NTCYW4V2.js → zed-RH34TNSW.js} +3 -3
- package/package.json +9 -1
- package/dist/amp-YGV66GJT.js.map +0 -1
- package/dist/chunk-3JCRUROU.js.map +0 -1
- package/dist/chunk-3RBLIHPZ.js.map +0 -1
- package/dist/chunk-GSGDG2BV.js.map +0 -1
- package/dist/chunk-KMAKDD3Z.js.map +0 -1
- package/dist/chunk-KVAAFYRR.js.map +0 -1
- package/dist/chunk-MEH7GC7R.js.map +0 -1
- package/dist/chunk-NJU275US.js +0 -238
- package/dist/chunk-NJU275US.js.map +0 -1
- package/dist/chunk-PD4VFEBY.js.map +0 -1
- package/dist/chunk-ZAM4M7LI.js.map +0 -1
- package/dist/claude-code-4275HQU4.js.map +0 -1
- package/dist/codebuff-LE3KBZGM.js.map +0 -1
- package/dist/cursor-UH3W622V.js.map +0 -1
- package/dist/doctor-DZTWED4O.js.map +0 -1
- package/dist/droid-T5VBRXZF.js.map +0 -1
- package/dist/goose-M3RR3CZG.js.map +0 -1
- package/dist/openclaw-UZ5BMCGQ.js.map +0 -1
- package/dist/roo-code-NI5UU6JB.js.map +0 -1
- package/dist/trae-CQC72RHH.js.map +0 -1
- /package/dist/{antigravity-7IBYFO6P.js.map → antigravity-ANDKF3K7.js.map} +0 -0
- /package/dist/{antigravity-cli-JEOUP2VN.js.map → antigravity-cli-LLRPDDOT.js.map} +0 -0
- /package/dist/{chunk-SCVBYSF7.js.map → chunk-6XHB6BE3.js.map} +0 -0
- /package/dist/{chunk-KQSNDFBN.js.map → chunk-LL4OBGRU.js.map} +0 -0
- /package/dist/{chunk-WNREHWKL.js.map → chunk-MAH6QQTO.js.map} +0 -0
- /package/dist/{codex-4BY2ZJIW.js.map → codex-BXA4FIF4.js.map} +0 -0
- /package/dist/{copilot-cli-IPISKO3V.js.map → copilot-cli-ROIBTTDT.js.map} +0 -0
- /package/dist/{crush-X3E25EQG.js.map → crush-QLEFLHUC.js.map} +0 -0
- /package/dist/{gemini-cli-ZSUK55UA.js.map → gemini-cli-SLVWLXJW.js.map} +0 -0
- /package/dist/{hermes-CUNKIAR5.js.map → hermes-ONDCECP2.js.map} +0 -0
- /package/dist/{jetbrains-copilot-C3HDGGML.js.map → jetbrains-copilot-YABZ3HFA.js.map} +0 -0
- /package/dist/{kilo-PKAJCWPX.js.map → kilo-F3ZDZKCT.js.map} +0 -0
- /package/dist/{kilo-cli-QWUVXG2O.js.map → kilo-cli-3HWPWBY4.js.map} +0 -0
- /package/dist/{kimi-EVD7YKXS.js.map → kimi-NV72FVAO.js.map} +0 -0
- /package/dist/{kiro-UQRY6EIO.js.map → kiro-C5W6AGDR.js.map} +0 -0
- /package/dist/{leaderboard-CSWHI4UY.js.map → leaderboard-TIBVONVT.js.map} +0 -0
- /package/dist/{mux-5CI5FP2W.js.map → mux-DSSH4AFS.js.map} +0 -0
- /package/dist/{omp-AXA7XY22.js.map → omp-Z6FRNDPN.js.map} +0 -0
- /package/dist/{opencode-NZBRLJN3.js.map → opencode-Q6KBSAKW.js.map} +0 -0
- /package/dist/{pi-WMTUX6ES.js.map → pi-LZT6WWAZ.js.map} +0 -0
- /package/dist/{qwen-code-MRRIUQ3P.js.map → qwen-code-WQBKRPWJ.js.map} +0 -0
- /package/dist/{usage-CJOM2WQM.js.map → usage-E2A4O2CY.js.map} +0 -0
- /package/dist/{vscode-copilot-4RVRTCKV.js.map → vscode-copilot-ALV45XF6.js.map} +0 -0
- /package/dist/{warp-X6MB67NT.js.map → warp-H6IX4U3J.js.map} +0 -0
- /package/dist/{zed-NTCYW4V2.js.map → zed-RH34TNSW.js.map} +0 -0
package/README.md
CHANGED
|
@@ -8,13 +8,13 @@
|
|
|
8
8
|
|
|
9
9
|
[](https://www.npmjs.com/package/@ken-jo/agent-connector)
|
|
10
10
|
[](LICENSE)
|
|
11
|
-

|
|
11
|
+

|
|
12
|
+

|
|
13
13
|

|
|
14
14
|

|
|
15
15
|

|
|
16
16
|

|
|
17
|
-

|
|
18
18
|
|
|
19
19
|
## Who this is for
|
|
20
20
|
|
|
@@ -57,14 +57,14 @@ agent-connector is the middleware that does it for you:
|
|
|
57
57
|
registered but **not wrapped** (the proxy cannot intercept remote transports),
|
|
58
58
|
so they yield no per-tool telemetry.
|
|
59
59
|
|
|
60
|
-
> Status: **
|
|
60
|
+
> Status: **31 platforms, all 3 hook paradigms** (exceeds the
|
|
61
61
|
> [tokscale](https://github.com/junhoyeo/tokscale) token-leaderboard coverage).
|
|
62
62
|
>
|
|
63
63
|
> | Paradigm | Platforms |
|
|
64
64
|
> |---|---|
|
|
65
65
|
> | `json-stdio` (full hook dispatch) | Claude Code · Codex CLI · Cursor · VS Code Copilot · JetBrains Copilot · GitHub Copilot CLI · Gemini CLI · Qwen CLI · Kiro · Kimi CLI · Crush · Goose · Hermes · Droid (Factory) · Antigravity · Antigravity CLI |
|
|
66
66
|
> | `mcp-only` (MCP registration only) | Warp · Kilo · Roo Code · Trae · Zed · Amp · Codebuff · Mux · Pi |
|
|
67
|
-
> | `ts-plugin` (generated bridge module) | OpenCode · Kilo CLI · OMP · OpenClaw |
|
|
67
|
+
> | `ts-plugin` (generated bridge module) | OpenCode · MiMoCode · Kilo CLI · Kilo · OMP · NemoClaw · OpenClaw |
|
|
68
68
|
>
|
|
69
69
|
> …plus the telemetry core. Adding a platform = **one registry entry + one
|
|
70
70
|
> adapter**. (Google Antigravity is now fully supported, including the `agy` CLI,
|
|
@@ -72,10 +72,13 @@ agent-connector is the middleware that does it for you:
|
|
|
72
72
|
|
|
73
73
|
## Verification
|
|
74
74
|
|
|
75
|
-
The full single-API contract is **install-verified across
|
|
75
|
+
The full single-API contract is **install-verified across the platform set**. A
|
|
76
76
|
sample connector declaring **all four launch surfaces** — MCP server **+**
|
|
77
77
|
lifecycle hooks **+** slash commands **+** tools (skills + subagents) — was
|
|
78
|
-
installed into an isolated environment for every adapter and inspected on disk
|
|
78
|
+
installed into an isolated environment for every adapter and inspected on disk
|
|
79
|
+
(the 29-platform full sweep below; the two newest adapters — MiMoCode and
|
|
80
|
+
NemoClaw — were added with a focused isolated-HOME install check landing the MCP
|
|
81
|
+
server in the right file + root key):
|
|
79
82
|
|
|
80
83
|
- **29 / 29 platforms — zero missing, zero failed surfaces.** Each surface is
|
|
81
84
|
written where the host supports it and gracefully *skip-warned* (never silently
|
|
@@ -102,7 +105,7 @@ installed into an isolated environment for every adapter and inspected on disk:
|
|
|
102
105
|
- **Clean uninstall + `--purge`.** Every installed surface reverses; `--purge`
|
|
103
106
|
deregisters the connector record and tears down the home binary when no
|
|
104
107
|
connectors remain (29 / 29).
|
|
105
|
-
- **
|
|
108
|
+
- **1727 tests passing** · `tsc` clean · build green.
|
|
106
109
|
|
|
107
110
|
The 0.2.0 additions — the `memory` surface, the `nativeHooks` passthrough, and
|
|
108
111
|
`configPatch` — went through the same bar: dogfooded against real connector
|
|
@@ -192,7 +195,7 @@ npx @ken-jo/agent-connector install
|
|
|
192
195
|
|
|
193
196
|
> `install` targets only the hosts actually **detected** on this machine (or an
|
|
194
197
|
> explicit `--targets` / `connector.targets` list), intersected with the
|
|
195
|
-
>
|
|
198
|
+
> 31-adapter registry — there is no "install to all 31 unconditionally" path.
|
|
196
199
|
|
|
197
200
|
> **Optional convenience.** A global `npm i -g @ken-jo/agent-connector` is **not**
|
|
198
201
|
> required for the flow above — `npx @ken-jo/agent-connector …` runs it straight from
|
|
@@ -254,6 +257,72 @@ acme-db`, `acme-db install` ≈ `agent-connector install --connector
|
|
|
254
257
|
tools share that infrastructure. An explicit `--connector` / `--connector-id`
|
|
255
258
|
always overrides the injected default.
|
|
256
259
|
|
|
260
|
+
### Author + test offline — the Connector SDK (`/sdk`, `/sdk/test`)
|
|
261
|
+
|
|
262
|
+
```ts
|
|
263
|
+
import { defineConnector, defineHook, hostsSupporting } from "@ken-jo/agent-connector/sdk";
|
|
264
|
+
import { simulate, explain } from "@ken-jo/agent-connector/sdk/test";
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
`@ken-jo/agent-connector/sdk` is the consolidated **authoring** surface — it
|
|
268
|
+
re-exports `defineConnector`, the full `define*` family, the introspection
|
|
269
|
+
helpers, and public types from one import site (the root export is unchanged;
|
|
270
|
+
`/sdk` is additive).
|
|
271
|
+
|
|
272
|
+
**`define*` typed helpers** — each is a typed identity function (`(def) => def`)
|
|
273
|
+
that gives you per-surface type inference and a single import site:
|
|
274
|
+
`defineCommand`, `defineSkill`, `defineSubagent`, `defineMemory`,
|
|
275
|
+
`defineConfigPatch`, `defineNativeHook`. `defineHook` is event-parameterized
|
|
276
|
+
so the handler payload narrows to the concrete event type:
|
|
277
|
+
|
|
278
|
+
```ts
|
|
279
|
+
const guard = defineHook("PreToolUse", {
|
|
280
|
+
handler(evt) {
|
|
281
|
+
// evt.toolName is typed as PreToolUseEvent — not the union
|
|
282
|
+
return evt.toolName === "acme_write"
|
|
283
|
+
? { decision: "ask", reason: "Confirm write" }
|
|
284
|
+
: { decision: "allow" };
|
|
285
|
+
},
|
|
286
|
+
});
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
**Introspection** (async — adapters load lazily):
|
|
290
|
+
|
|
291
|
+
- `hostsSupporting(surface)` → `Promise<PlatformId[]>` — which registered hosts
|
|
292
|
+
honor a surface (`"hooks"` | `"statusline"` | `"memory"` | …).
|
|
293
|
+
- `capabilitiesOf(host)` → `Promise<PlatformCapabilities | undefined>`.
|
|
294
|
+
- `surfaceSupport(host, surface)` → `Promise<boolean>` — convenience single-pair check.
|
|
295
|
+
|
|
296
|
+
**Offline harness** (`@ken-jo/agent-connector/sdk/test`) answers *"does my
|
|
297
|
+
handler / HUD actually work on host X?"* before you touch a real host:
|
|
298
|
+
|
|
299
|
+
- `explain(connector)` → `Promise<ExplainRow[]>` — the per-host × per-declared-surface
|
|
300
|
+
matrix. Each row is `{ host, surface, support: "native"|"skip-warn"|"disabled", reason }`.
|
|
301
|
+
Only surfaces the connector actually declares are included.
|
|
302
|
+
- `simulate(connector, { surface, host, event?, input })` → `Promise<{ honored, hostReply?, reason }>`
|
|
303
|
+
— runs the **real** adapter parse→handler→format chain offline and judges the
|
|
304
|
+
actual `(event, decision)` contract. It encodes each host's real honor / drop /
|
|
305
|
+
degrade quirks — not substring guessing:
|
|
306
|
+
|
|
307
|
+
```ts
|
|
308
|
+
// Does codex honor a context injection on UserPromptSubmit?
|
|
309
|
+
const result = await simulate(connector, {
|
|
310
|
+
surface: "hooks",
|
|
311
|
+
host: "codex",
|
|
312
|
+
event: "UserPromptSubmit",
|
|
313
|
+
input: { hookEventName: "UserPromptSubmit", prompt: "explain this" },
|
|
314
|
+
});
|
|
315
|
+
// → { honored: false, reason: "drops context on UserPromptSubmit (no stdout path)" }
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
> Other verdicts the harness encodes: a `deny` on `Stop`/`SubagentStop` is
|
|
319
|
+
> continuation/persistence → `honored:true` (reason explains); `deny` on
|
|
320
|
+
> `SubagentStart`/`PostToolUseFailure` degrades to a context note →
|
|
321
|
+
> `honored:false`; a PermissionRequest `ask` is honored by the host's native
|
|
322
|
+
> dialog → `honored:true`. Matcher-scoped handlers that don't match the input
|
|
323
|
+
> are not run. The harness mirrors the runtime exactly — tolerant stdin,
|
|
324
|
+
> matcher filtering, real verdict.
|
|
325
|
+
|
|
257
326
|
### Two ways to ship: direct install **or** a marketplace package
|
|
258
327
|
|
|
259
328
|
Same one definition, your choice of distribution:
|
|
@@ -332,14 +401,16 @@ export default defineConnector({
|
|
|
332
401
|
> Code only for now; other hosts skip-warn, never silently.
|
|
333
402
|
|
|
334
403
|
> **Host-config key patches.** For host-exclusive *settings keys* no other
|
|
335
|
-
> surface reaches (
|
|
336
|
-
> declare `platforms: { "claude-code": { configPatch: [{ key, value, reason }] } }`.
|
|
404
|
+
> surface reaches (e.g. an experimental `env.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS`
|
|
405
|
+
> flag), declare `platforms: { "claude-code": { configPatch: [{ key, value, reason }] } }`.
|
|
337
406
|
> Semantics are fixed: **set-if-absent + skip-warn on any conflict** — never
|
|
338
407
|
> overwrite, never deep-merge. Ownership is refcounted in a persisted ledger, so
|
|
339
408
|
> uninstall removes a key only when the last owning connector releases it and the
|
|
340
409
|
> value is untouched; security-relevant keys (`permissions*`, `apiKey*`,
|
|
341
|
-
> `env.ANTHROPIC_*`, token/secret env vars, …) are hard-refused
|
|
342
|
-
>
|
|
410
|
+
> `env.ANTHROPIC_*`, token/secret env vars, …) are hard-refused, as are keys
|
|
411
|
+
> agent-connector models as first-class surfaces (`hooks*`, `mcpServers*`,
|
|
412
|
+
> `statusLine` → use the `statusline` surface instead). Claude Code only for now;
|
|
413
|
+
> other hosts skip-warn with the exact manual edit.
|
|
343
414
|
|
|
344
415
|
`agent-connector install` turns that into, e.g.:
|
|
345
416
|
|
|
@@ -366,7 +437,7 @@ memory: [
|
|
|
366
437
|
```
|
|
367
438
|
|
|
368
439
|
**Write the guidance once — it lands in the standard
|
|
369
|
-
[AGENTS.md](https://agents.md) on
|
|
440
|
+
[AGENTS.md](https://agents.md) on 29 of the 31 hosts** (the open, Linux
|
|
370
441
|
Foundation-stewarded "README for agents" format): project scope targets
|
|
371
442
|
`<projectDir>/AGENTS.md` — and where a host resolves its rules file
|
|
372
443
|
exclusively, the target is *probed* so the block lands in the file the host
|
|
@@ -395,6 +466,99 @@ Uninstall excises exactly your blocks and `doctor` verifies them (present /
|
|
|
395
466
|
hash-intact / user-edited / file missing). Hosts with no writable memory file at
|
|
396
467
|
a scope skip-warn, never silently.
|
|
397
468
|
|
|
469
|
+
### Status line (`statusline`) — live HUD per connector
|
|
470
|
+
|
|
471
|
+
Ship a render function that the host calls on every status refresh:
|
|
472
|
+
|
|
473
|
+
```ts
|
|
474
|
+
import { defineConnector, defineStatusline } from "@ken-jo/agent-connector";
|
|
475
|
+
|
|
476
|
+
export default defineConnector({
|
|
477
|
+
id: "acme-db",
|
|
478
|
+
// ...
|
|
479
|
+
statusline: defineStatusline({
|
|
480
|
+
render(ctx) {
|
|
481
|
+
const model = ctx.model?.displayName ?? ctx.model?.id ?? "unknown";
|
|
482
|
+
return `acme-db · ${model} · $${(ctx.cost?.totalUsd ?? 0).toFixed(4)}`;
|
|
483
|
+
},
|
|
484
|
+
}),
|
|
485
|
+
});
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
`StatuslineContext` provides (where the host supplies them) `host`,
|
|
489
|
+
`connectorId`, `sessionId`, `cwd`, `model` (`id` / `displayName`),
|
|
490
|
+
`cost` (`totalUsd`), `context` (`usedTokens` / `maxTokens` / `percent`),
|
|
491
|
+
`transcriptPath`, and `raw` (the host's verbatim payload). Fields the host
|
|
492
|
+
does not provide are `undefined`.
|
|
493
|
+
|
|
494
|
+
> **`ctx.context` is reserved** — `context.usedTokens` / `maxTokens` / `percent`
|
|
495
|
+
> are declared in `StatuslineContext` for a future AC-usage integration but are
|
|
496
|
+
> **not populated by any v1 code path**. Rendering `ctx.context?.percent ?? 0`
|
|
497
|
+
> always produces `0%`. Use `ctx.cost?.totalUsd` and `ctx.model?.displayName`
|
|
498
|
+
> (both populated by claude-code) instead.
|
|
499
|
+
|
|
500
|
+
**v1: claude-code only.** Install registers `settings.json.statusLine` via the
|
|
501
|
+
same configPatch ownership ledger — **set-if-absent, never clobbers a
|
|
502
|
+
`statusLine` agent-connector doesn't own** (skip-warns and prints the manual
|
|
503
|
+
edit instead), refcounted, reversible. Every other host adapter skip-warns at
|
|
504
|
+
install time, never silently. The runtime is **fail-safe**: any error — a
|
|
505
|
+
throwing `render`, unknown connector, malformed stdin — exits 0 with empty
|
|
506
|
+
stdout so a HUD never wedges the host. `doctor` includes a dedicated
|
|
507
|
+
`statusline wired` check.
|
|
508
|
+
|
|
509
|
+
> `defineStatusline` is a typed identity helper and is optional — you can
|
|
510
|
+
> pass the `{ render }` object directly to `statusline:`. Both
|
|
511
|
+
> `StatuslineDef` and `StatuslineContext` are exported from
|
|
512
|
+
> `@ken-jo/agent-connector`.
|
|
513
|
+
|
|
514
|
+
### Actions (`defineAction`) — user-triggered dispatch
|
|
515
|
+
|
|
516
|
+
Declare named, user-invocable operations on your connector:
|
|
517
|
+
|
|
518
|
+
```ts
|
|
519
|
+
import { defineConnector, defineAction } from "@ken-jo/agent-connector";
|
|
520
|
+
|
|
521
|
+
export default defineConnector({
|
|
522
|
+
id: "acme-db",
|
|
523
|
+
// ...
|
|
524
|
+
actions: [
|
|
525
|
+
defineAction({
|
|
526
|
+
id: "flush-cache",
|
|
527
|
+
description: "Flush the acme-db query cache",
|
|
528
|
+
async run(ctx) {
|
|
529
|
+
// ctx is HostCtx — same context object as hooks
|
|
530
|
+
await flushCache();
|
|
531
|
+
return { message: "Cache flushed." };
|
|
532
|
+
},
|
|
533
|
+
}),
|
|
534
|
+
],
|
|
535
|
+
});
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
The **universal verb** runs any declared action from the shell (or from a
|
|
539
|
+
script / IDE task):
|
|
540
|
+
|
|
541
|
+
```bash
|
|
542
|
+
agent-connector action <platform> flush-cache --connector acme-db
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
`run(ctx)` executes and its optional `{ message }` return is printed to
|
|
546
|
+
stdout. **Error semantics are user-triggered**: an unknown action id or a
|
|
547
|
+
throw exits 1 and writes to stderr (unlike hooks and statusline, which are
|
|
548
|
+
fail-safe/silent on error).
|
|
549
|
+
|
|
550
|
+
`defineAction` is a typed identity helper and is exported from both
|
|
551
|
+
`@ken-jo/agent-connector` and `@ken-jo/agent-connector/sdk`.
|
|
552
|
+
`ActionDef = { id, description?, run, hosts? }` and `ActionResult = { message? }`.
|
|
553
|
+
|
|
554
|
+
**v1: dispatch backbone only.** `install` skip-warns on every host — there
|
|
555
|
+
is no host affordance emitter yet (binding a slash-command or keybinding to
|
|
556
|
+
the verb requires generated IDE extensions, a later phase). The `action`
|
|
557
|
+
verb is fully functional today; host-side registration is deferred.
|
|
558
|
+
`explain()` emits action rows (skip-warn everywhere in v1); `simulate()`
|
|
559
|
+
does not cover actions (actions take no host payload and have no host-honor
|
|
560
|
+
verdict — intentional).
|
|
561
|
+
|
|
398
562
|
## How it works (operating model)
|
|
399
563
|
|
|
400
564
|
- **Home-dir, single binary.** The runtime installs once under
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
fail
|
|
4
|
+
} from "./chunk-KGXDYGNJ.js";
|
|
5
|
+
import {
|
|
6
|
+
runAction
|
|
7
|
+
} from "./chunk-BHUCB6LY.js";
|
|
8
|
+
import "./chunk-OP4KBXUO.js";
|
|
9
|
+
import "./chunk-22Y24V7O.js";
|
|
10
|
+
import "./chunk-J3D5W5T2.js";
|
|
11
|
+
import "./chunk-CIRDOY2V.js";
|
|
12
|
+
import "./chunk-BCHWFTV4.js";
|
|
13
|
+
import "./chunk-KHO5WNTP.js";
|
|
14
|
+
import "./chunk-KGJWE6A2.js";
|
|
15
|
+
import "./chunk-ADTHT2FN.js";
|
|
16
|
+
import "./chunk-3PFFTFCU.js";
|
|
17
|
+
import "./chunk-BXGFUENQ.js";
|
|
18
|
+
import "./chunk-N6HH7K6P.js";
|
|
19
|
+
import "./chunk-TRQKHP7D.js";
|
|
20
|
+
|
|
21
|
+
// src/cli/commands/action.ts
|
|
22
|
+
import { parseArgs } from "util";
|
|
23
|
+
async function run(argv) {
|
|
24
|
+
const { values, positionals } = parseArgs({
|
|
25
|
+
args: argv,
|
|
26
|
+
options: {
|
|
27
|
+
connector: { type: "string" }
|
|
28
|
+
},
|
|
29
|
+
allowPositionals: true
|
|
30
|
+
});
|
|
31
|
+
const platformId = positionals[0];
|
|
32
|
+
const actionId = positionals[1];
|
|
33
|
+
if (!platformId || !actionId) {
|
|
34
|
+
return fail("usage: agent-connector action <platform> <actionId> --connector <id>");
|
|
35
|
+
}
|
|
36
|
+
const connectorId = values.connector;
|
|
37
|
+
if (!connectorId || connectorId.trim() === "") {
|
|
38
|
+
return fail("action requires --connector <id>");
|
|
39
|
+
}
|
|
40
|
+
const reply = await runAction({ platformId, actionId, connectorId });
|
|
41
|
+
if (reply.stdout !== void 0 && reply.stdout !== "") {
|
|
42
|
+
process.stdout.write(reply.stdout.endsWith("\n") ? reply.stdout : `${reply.stdout}
|
|
43
|
+
`);
|
|
44
|
+
}
|
|
45
|
+
if (reply.stderr !== void 0 && reply.stderr !== "") {
|
|
46
|
+
process.stderr.write(reply.stderr.endsWith("\n") ? reply.stderr : `${reply.stderr}
|
|
47
|
+
`);
|
|
48
|
+
}
|
|
49
|
+
process.exit(reply.exitCode);
|
|
50
|
+
}
|
|
51
|
+
export {
|
|
52
|
+
run
|
|
53
|
+
};
|
|
54
|
+
//# sourceMappingURL=action-PLZW5BGX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli/commands/action.ts"],"sourcesContent":["/**\n * cli/commands/action — the universal user-invokable action entrypoint.\n *\n * agent-connector action <platform> <actionId> --connector <id>\n *\n * A future host affordance (slash command / keybinding) points at the single\n * stable home binary (via core/spawn.buildHomeBinActionCommand). This command\n * parses the positionals + --connector, dispatches through runAction, writes any\n * stdout/stderr the action produced, and exits with its code. It reads NO stdin\n * (an action takes no host payload, unlike a hook or status line).\n *\n * USER-TRIGGERED is the runtime's contract: unlike the fail-open hook command,\n * an unknown action id or a throwing run surfaces as exit 1 + a stderr message —\n * the user invoked it deliberately, so the failure is shown, never swallowed.\n */\n\nimport { parseArgs } from \"node:util\";\n\nimport { runAction } from \"../../runtime/index.js\";\nimport { fail } from \"../app.js\";\n\nexport async function run(argv: string[]): Promise<number> {\n const { values, positionals } = parseArgs({\n args: argv,\n options: {\n connector: { type: \"string\" },\n },\n allowPositionals: true,\n });\n\n const platformId = positionals[0];\n const actionId = positionals[1];\n if (!platformId || !actionId) {\n return fail(\"usage: agent-connector action <platform> <actionId> --connector <id>\");\n }\n const connectorId = values.connector;\n if (!connectorId || connectorId.trim() === \"\") {\n return fail(\"action requires --connector <id>\");\n }\n\n const reply = await runAction({ platformId, actionId, connectorId });\n if (reply.stdout !== undefined && reply.stdout !== \"\") {\n process.stdout.write(reply.stdout.endsWith(\"\\n\") ? reply.stdout : `${reply.stdout}\\n`);\n }\n if (reply.stderr !== undefined && reply.stderr !== \"\") {\n process.stderr.write(reply.stderr.endsWith(\"\\n\") ? reply.stderr : `${reply.stderr}\\n`);\n }\n process.exit(reply.exitCode);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAgBA,SAAS,iBAAiB;AAK1B,eAAsB,IAAI,MAAiC;AACzD,QAAM,EAAE,QAAQ,YAAY,IAAI,UAAU;AAAA,IACxC,MAAM;AAAA,IACN,SAAS;AAAA,MACP,WAAW,EAAE,MAAM,SAAS;AAAA,IAC9B;AAAA,IACA,kBAAkB;AAAA,EACpB,CAAC;AAED,QAAM,aAAa,YAAY,CAAC;AAChC,QAAM,WAAW,YAAY,CAAC;AAC9B,MAAI,CAAC,cAAc,CAAC,UAAU;AAC5B,WAAO,KAAK,sEAAsE;AAAA,EACpF;AACA,QAAM,cAAc,OAAO;AAC3B,MAAI,CAAC,eAAe,YAAY,KAAK,MAAM,IAAI;AAC7C,WAAO,KAAK,kCAAkC;AAAA,EAChD;AAEA,QAAM,QAAQ,MAAM,UAAU,EAAE,YAAY,UAAU,YAAY,CAAC;AACnE,MAAI,MAAM,WAAW,UAAa,MAAM,WAAW,IAAI;AACrD,YAAQ,OAAO,MAAM,MAAM,OAAO,SAAS,IAAI,IAAI,MAAM,SAAS,GAAG,MAAM,MAAM;AAAA,CAAI;AAAA,EACvF;AACA,MAAI,MAAM,WAAW,UAAa,MAAM,WAAW,IAAI;AACrD,YAAQ,OAAO,MAAM,MAAM,OAAO,SAAS,IAAI,IAAI,MAAM,SAAS,GAAG,MAAM,MAAM;AAAA,CAAI;AAAA,EACvF;AACA,UAAQ,KAAK,MAAM,QAAQ;AAC7B;","names":[]}
|
|
@@ -4,13 +4,15 @@ import {
|
|
|
4
4
|
} from "./chunk-DBQMX75U.js";
|
|
5
5
|
import {
|
|
6
6
|
BaseAdapter
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import
|
|
7
|
+
} from "./chunk-IW77FFNX.js";
|
|
8
|
+
import {
|
|
9
|
+
renderSkillMd
|
|
10
|
+
} from "./chunk-7L6ITC4T.js";
|
|
9
11
|
import {
|
|
10
12
|
buildServeWrapperCommand,
|
|
11
13
|
isHomeBinHookCommand,
|
|
12
14
|
shouldWrapForTelemetry
|
|
13
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-BXGFUENQ.js";
|
|
14
16
|
import "./chunk-N6HH7K6P.js";
|
|
15
17
|
import "./chunk-TRQKHP7D.js";
|
|
16
18
|
|
|
@@ -41,7 +43,11 @@ var AmpAdapter = class extends BaseAdapter {
|
|
|
41
43
|
canModifyOutput: false,
|
|
42
44
|
canInjectSessionContext: false,
|
|
43
45
|
// Amp registers stdio and Streamable HTTP MCP servers.
|
|
44
|
-
transports: ["stdio", "http"]
|
|
46
|
+
transports: ["stdio", "http"],
|
|
47
|
+
// Skills: Amp reads SKILL.md from ~/.config/agents/skills/<name>/SKILL.md
|
|
48
|
+
// (user) and <projectDir>/.agents/skills/<name>/SKILL.md (project) — a root
|
|
49
|
+
// OUTSIDE the config dir, so the skillDir() helper resolves it explicitly.
|
|
50
|
+
supportsSkills: true
|
|
45
51
|
};
|
|
46
52
|
// ── Detection ────────────────────────────────────────────────────────────
|
|
47
53
|
detectInstalled(projectDir) {
|
|
@@ -150,6 +156,76 @@ var AmpAdapter = class extends BaseAdapter {
|
|
|
150
156
|
rewrite(value) {
|
|
151
157
|
return rewriteEnvRefs(value, ampEnvToken);
|
|
152
158
|
}
|
|
159
|
+
// ── Skills surface ───────────────────────────────────────────────────────
|
|
160
|
+
// CONTENT-ONLY: pure native-file writers under the skill root. No runtime
|
|
161
|
+
// dispatch, no home-bin pointer, no telemetry wrap. Idempotent (byte-identical
|
|
162
|
+
// → skip) via writeContentFile and reversible via removeContentFile. Honors
|
|
163
|
+
// platforms["amp"].skills === false to skip.
|
|
164
|
+
//
|
|
165
|
+
// QUIRK: the skill root is NOT under getConfigDir (~/.config/amp). Amp reads
|
|
166
|
+
// SKILL.md from the sibling cross-agent `agents` tree:
|
|
167
|
+
// user scope → ~/.config/agents/skills/<name>/SKILL.md
|
|
168
|
+
// project scope → <projectDir>/.agents/skills/<name>/SKILL.md
|
|
169
|
+
// so skillDir() resolves it explicitly rather than reusing getConfigDir.
|
|
170
|
+
/** Skill root: user `~/.config/agents/skills`, project `<projectDir>/.agents/skills`. */
|
|
171
|
+
skillsDir(ctx) {
|
|
172
|
+
return ctx.scope === "project" ? join(ctx.projectDir, ".agents", "skills") : join(homedir(), ".config", "agents", "skills");
|
|
173
|
+
}
|
|
174
|
+
/** Native skill dir: <skillRoot>/<name>. */
|
|
175
|
+
skillDir(ctx, name) {
|
|
176
|
+
return join(this.skillsDir(ctx), name);
|
|
177
|
+
}
|
|
178
|
+
installSkills(ctx) {
|
|
179
|
+
const { connector } = ctx;
|
|
180
|
+
if (connector.platforms[HOST]?.skills === false) {
|
|
181
|
+
return [{ platform: this.id, action: "skip", detail: "skills disabled for amp" }];
|
|
182
|
+
}
|
|
183
|
+
if (connector.skills.length === 0) {
|
|
184
|
+
return [{ platform: this.id, action: "skip", detail: "connector declares no skills" }];
|
|
185
|
+
}
|
|
186
|
+
const changes = [];
|
|
187
|
+
for (const skill of connector.skills) {
|
|
188
|
+
const dir = this.skillDir(ctx, skill.name);
|
|
189
|
+
changes.push(
|
|
190
|
+
this.writeContentFile(join(dir, "SKILL.md"), this.renderSkill(skill), ctx.dryRun)
|
|
191
|
+
);
|
|
192
|
+
for (const [rel, contents] of Object.entries(skill.resources ?? {})) {
|
|
193
|
+
const target = this.resolveWithin(dir, rel);
|
|
194
|
+
if (target === null) {
|
|
195
|
+
changes.push({
|
|
196
|
+
platform: this.id,
|
|
197
|
+
action: "warn",
|
|
198
|
+
detail: `skill resource "${rel}" escapes the skill dir; skipped`
|
|
199
|
+
});
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
changes.push(this.writeContentFile(target, contents, ctx.dryRun));
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return changes;
|
|
206
|
+
}
|
|
207
|
+
uninstallSkills(ctx) {
|
|
208
|
+
const { connector } = ctx;
|
|
209
|
+
if (connector.skills.length === 0) {
|
|
210
|
+
return [{ platform: this.id, action: "skip", detail: "connector declares no skills" }];
|
|
211
|
+
}
|
|
212
|
+
const changes = [];
|
|
213
|
+
for (const skill of connector.skills) {
|
|
214
|
+
const dir = this.skillDir(ctx, skill.name);
|
|
215
|
+
changes.push(this.removeContentFile(join(dir, "SKILL.md"), ctx.dryRun));
|
|
216
|
+
for (const rel of Object.keys(skill.resources ?? {})) {
|
|
217
|
+
const target = this.resolveWithin(dir, rel);
|
|
218
|
+
if (target === null) continue;
|
|
219
|
+
changes.push(this.removeContentFile(target, ctx.dryRun));
|
|
220
|
+
}
|
|
221
|
+
changes.push(this.removeDirIfEmpty(dir, ctx.dryRun));
|
|
222
|
+
}
|
|
223
|
+
return changes;
|
|
224
|
+
}
|
|
225
|
+
/** Render a skill's SKILL.md (delegates to the shared renderer). */
|
|
226
|
+
renderSkill(skill) {
|
|
227
|
+
return renderSkillMd(skill);
|
|
228
|
+
}
|
|
153
229
|
// ── Hooks (unavailable — Amp is mcp-only) ────────────────────────────────
|
|
154
230
|
installHooks(_ctx) {
|
|
155
231
|
return [
|
|
@@ -221,4 +297,4 @@ export {
|
|
|
221
297
|
adapter,
|
|
222
298
|
amp_default as default
|
|
223
299
|
};
|
|
224
|
-
//# sourceMappingURL=amp-
|
|
300
|
+
//# sourceMappingURL=amp-B524U6LO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/adapters/amp/index.ts"],"sourcesContent":["/**\n * adapters/amp — Amp (Sourcegraph / AmpCode) platform adapter for agent-connector.\n *\n * Amp is an **mcp-only** host: it exposes no lifecycle hook system, so MCP is the\n * only extensibility surface. This adapter installs the MCP server entry and\n * reports hooks as unavailable — the same shape validated by the Warp adapter.\n *\n * MCP config (report §2 / §5.3):\n * - user scope → ~/.config/amp/settings.json\n * - project scope → <projectDir>/.amp/settings.json\n * Both are JSONC (we write plain JSON, which is valid JSONC). The settings file\n * is SHARED with the rest of Amp's configuration, so we MERGE our entry into\n * the existing object and never clobber unrelated keys.\n *\n * QUIRK 1 — dotted top-level key: Amp does NOT use a nested `mcpServers` object.\n * The MCP registry is a single FLAT settings key literally named\n * `\"amp.mcpServers\"`, whose value is an object of `{ id: { command, args, env } }`.\n * We therefore set `settings[\"amp.mcpServers\"][connectorId] = entry`. Because the\n * base JSON helpers index `config[rootKey][serverId]`, passing the dotted string\n * as the root key writes exactly that flat key while preserving every sibling\n * setting (true merge).\n *\n * QUIRK 2 — native interpolation: Amp expands `${VAR_NAME}` in stdio entries at\n * runtime, so we KEEP env/header/url refs native by rewriting the portable\n * `${env:VAR}` syntax to Amp's `${VAR}` token rather than resolving to literals\n * (secrets stay out of the settings file).\n *\n * Skills surface: Amp reads SKILL.md files (dir-per-skill, same shape as\n * claude-code) from a skill root that is NOT under the config dir\n * (`~/.config/amp`):\n * - user scope → ~/.config/agents/skills/<name>/SKILL.md (the sibling\n * cross-agent `agents` dir — `~/.config/amp/skills/` is also documented-native,\n * but the `agents` root is the cross-agent standard we standardize on)\n * - project scope → <projectDir>/.agents/skills/<name>/SKILL.md\n * Because that root differs from getConfigDir, skills use a dedicated skillDir()\n * helper rather than reusing getConfigDir.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport { BaseAdapter } from \"../base.js\";\nimport type { Adapter, InstallContext } from \"../spi.js\";\nimport type {\n ChangeRecord,\n DetectedPlatform,\n HealthCheck,\n HookParadigm,\n PlatformCapabilities,\n PlatformId,\n ServerDef,\n SkillDef,\n Transport,\n} from \"../../core/types.js\";\nimport { rewriteEnvRefs } from \"../../core/interpolate.js\";\nimport {\n buildServeWrapperCommand,\n isHomeBinHookCommand,\n shouldWrapForTelemetry,\n} from \"../../core/spawn.js\";\nimport { renderSkillMd } from \"../claude-code/render.js\";\n\nconst HOST: PlatformId = \"amp\";\n/**\n * QUIRK: a single FLAT, dotted settings key — NOT a nested object. The base\n * JSON helpers treat this as `config[\"amp.mcpServers\"][serverId]`.\n */\nconst MCP_ROOT_KEY = \"amp.mcpServers\";\n\n/** Native MCP server entry shapes Amp accepts under `amp.mcpServers`. */\ninterface AmpStdioServer {\n command: string;\n args?: string[];\n env?: Record<string, string>;\n}\ninterface AmpHttpServer {\n url: string;\n headers?: Record<string, string>;\n}\n\nexport class AmpAdapter extends BaseAdapter implements Adapter {\n readonly id: PlatformId = HOST;\n readonly name = \"Amp\";\n readonly paradigm: HookParadigm = \"mcp-only\";\n\n readonly capabilities: PlatformCapabilities = {\n // Memory surface: AGENTS.md-first managed block via the BaseAdapter default\n // (memoryTargets: project <projectDir>/AGENTS.md; user scope where documented).\n supportsMemory: true,\n // Amp has no lifecycle hook system — every hook capability is false.\n preToolUse: false,\n postToolUse: false,\n preCompact: false,\n sessionStart: false,\n sessionEnd: false,\n userPromptSubmit: false,\n stop: false,\n notification: false,\n canModifyArgs: false,\n canModifyOutput: false,\n canInjectSessionContext: false,\n // Amp registers stdio and Streamable HTTP MCP servers.\n transports: [\"stdio\", \"http\"],\n // Skills: Amp reads SKILL.md from ~/.config/agents/skills/<name>/SKILL.md\n // (user) and <projectDir>/.agents/skills/<name>/SKILL.md (project) — a root\n // OUTSIDE the config dir, so the skillDir() helper resolves it explicitly.\n supportsSkills: true,\n };\n\n // ── Detection ────────────────────────────────────────────────────────────\n\n detectInstalled(projectDir: string): DetectedPlatform {\n const userDir = join(homedir(), \".config\", \"amp\");\n const userSettings = join(userDir, \"settings.json\");\n const projectDirAmp = join(projectDir, \".amp\");\n const projectSettings = join(projectDirAmp, \"settings.json\");\n\n const userInstalled = existsSync(userDir) || existsSync(userSettings);\n const projectInstalled = existsSync(projectDirAmp) || existsSync(projectSettings);\n const installed = userInstalled || projectInstalled;\n const scope = projectInstalled && !userInstalled ? \"project\" : \"user\";\n const configPath = scope === \"project\" ? projectSettings : userSettings;\n\n return {\n id: this.id,\n name: this.name,\n installed,\n paradigm: this.paradigm,\n capabilities: this.capabilities,\n configPath,\n scope,\n reason: installed\n ? `found Amp config (${scope}) at ${configPath}`\n : `no Amp config at ${userSettings} or ${projectSettings}`,\n confidence: installed ? \"high\" : \"low\",\n };\n }\n\n // ── Native paths ─────────────────────────────────────────────────────────\n\n getConfigDir(ctx: InstallContext): string {\n return ctx.scope === \"project\"\n ? join(ctx.projectDir, \".amp\")\n : join(homedir(), \".config\", \"amp\");\n }\n\n getServerConfigPath(ctx: InstallContext): string {\n return join(this.getConfigDir(ctx), \"settings.json\");\n }\n\n /**\n * Amp has no hook file — hooks are not a thing here. The hook \"config path\" is\n * the same settings.json so the generic doctor/backup behave sensibly.\n */\n getHookConfigPath(ctx: InstallContext): string {\n return this.getServerConfigPath(ctx);\n }\n\n // ── MCP server install / uninstall ───────────────────────────────────────\n\n installServer(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n const override = connector.platforms[HOST]?.server;\n if (!connector.server || override === false) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail: connector.server\n ? \"server registration disabled for amp\"\n : \"connector declares no MCP server\",\n },\n ];\n }\n\n // Shallow-merge any per-platform server override into the base ServerDef.\n const server: ServerDef =\n override && typeof override === \"object\"\n ? { ...connector.server, ...override }\n : connector.server;\n\n const serverPath = this.getServerConfigPath(ctx);\n const entry = this.renderServerEntry(ctx, server);\n\n // Upsert into the flat \"amp.mcpServers\" key, merging into existing settings.\n return [\n this.upsertServerInJson(serverPath, MCP_ROOT_KEY, connector.id, entry, ctx.dryRun),\n ];\n }\n\n uninstallServer(ctx: InstallContext): ChangeRecord[] {\n const serverPath = this.getServerConfigPath(ctx);\n return [\n this.removeServerFromJson(serverPath, MCP_ROOT_KEY, ctx.connector.id, ctx.dryRun),\n ];\n }\n\n /** Render a normalized ServerDef into Amp's native `amp.mcpServers` entry. */\n private renderServerEntry(\n ctx: InstallContext,\n server: ServerDef,\n ): AmpStdioServer | AmpHttpServer {\n const transport: Transport = server.transport;\n\n if (transport === \"stdio\") {\n let command = server.command ?? \"\";\n let args = [...(server.args ?? [])];\n\n // Transparent telemetry wrapping: route the real command through\n // `<homeBin> serve --connector <id> -- <command> <args...>`.\n if (shouldWrapForTelemetry(server, ctx.connector.telemetry)) {\n const wrapped = buildServeWrapperCommand(\n ctx.homeBinPath,\n ctx.connector.id,\n command,\n args,\n ctx.scope,\n this.id,\n );\n command = wrapped.command;\n args = wrapped.args;\n }\n\n // Amp expands ${VAR_NAME} natively, so keep refs native (no literals).\n const entry: AmpStdioServer = { command: this.rewrite(command) };\n if (args.length > 0) entry.args = args.map((a) => this.rewrite(a));\n const env = this.renderEnv(server.env);\n if (env) entry.env = env;\n return entry;\n }\n\n // http (and any other remote transport we surface) — Amp registers a URL.\n const entry: AmpHttpServer = { url: this.rewrite(server.url ?? \"\") };\n const headers = this.renderEnv(server.headers);\n if (headers) entry.headers = headers;\n return entry;\n }\n\n /**\n * Render env/header values. Amp supports native `${VAR_NAME}` interpolation,\n * so translate `${env:VAR}` refs to that native token rather than baking\n * secrets into the file. Literals pass through unchanged.\n */\n private renderEnv(\n env: Record<string, string> | undefined,\n ): Record<string, string> | undefined {\n if (!env || Object.keys(env).length === 0) return undefined;\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(env)) out[k] = this.rewrite(v);\n return out;\n }\n\n /** Translate `${env:VAR(:-default)}` to Amp's native `${VAR}` token. */\n private rewrite(value: string): string {\n return rewriteEnvRefs(value, ampEnvToken);\n }\n\n // ── Skills surface ───────────────────────────────────────────────────────\n // CONTENT-ONLY: pure native-file writers under the skill root. No runtime\n // dispatch, no home-bin pointer, no telemetry wrap. Idempotent (byte-identical\n // → skip) via writeContentFile and reversible via removeContentFile. Honors\n // platforms[\"amp\"].skills === false to skip.\n //\n // QUIRK: the skill root is NOT under getConfigDir (~/.config/amp). Amp reads\n // SKILL.md from the sibling cross-agent `agents` tree:\n // user scope → ~/.config/agents/skills/<name>/SKILL.md\n // project scope → <projectDir>/.agents/skills/<name>/SKILL.md\n // so skillDir() resolves it explicitly rather than reusing getConfigDir.\n\n /** Skill root: user `~/.config/agents/skills`, project `<projectDir>/.agents/skills`. */\n private skillsDir(ctx: InstallContext): string {\n return ctx.scope === \"project\"\n ? join(ctx.projectDir, \".agents\", \"skills\")\n : join(homedir(), \".config\", \"agents\", \"skills\");\n }\n\n /** Native skill dir: <skillRoot>/<name>. */\n private skillDir(ctx: InstallContext, name: string): string {\n return join(this.skillsDir(ctx), name);\n }\n\n override installSkills(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.platforms[HOST]?.skills === false) {\n return [{ platform: this.id, action: \"skip\", detail: \"skills disabled for amp\" }];\n }\n if (connector.skills.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\n }\n const changes: ChangeRecord[] = [];\n for (const skill of connector.skills) {\n const dir = this.skillDir(ctx, skill.name);\n changes.push(\n this.writeContentFile(join(dir, \"SKILL.md\"), this.renderSkill(skill), ctx.dryRun),\n );\n // Bundle any resource files beside SKILL.md (relative path → contents).\n // Defense-in-depth: skip+warn on any key that escapes the skill dir\n // (config-time validation already rejects these, but never trust input).\n for (const [rel, contents] of Object.entries(skill.resources ?? {})) {\n const target = this.resolveWithin(dir, rel);\n if (target === null) {\n changes.push({\n platform: this.id,\n action: \"warn\",\n detail: `skill resource \"${rel}\" escapes the skill dir; skipped`,\n });\n continue;\n }\n changes.push(this.writeContentFile(target, contents, ctx.dryRun));\n }\n }\n return changes;\n }\n\n override uninstallSkills(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.skills.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\n }\n const changes: ChangeRecord[] = [];\n for (const skill of connector.skills) {\n const dir = this.skillDir(ctx, skill.name);\n // Remove only the files we wrote (SKILL.md + declared resources), then the\n // skill dir itself when we own its full contents.\n changes.push(this.removeContentFile(join(dir, \"SKILL.md\"), ctx.dryRun));\n for (const rel of Object.keys(skill.resources ?? {})) {\n const target = this.resolveWithin(dir, rel);\n if (target === null) continue; // never delete outside the skill dir\n changes.push(this.removeContentFile(target, ctx.dryRun));\n }\n // Only remove the skill dir when WE own its full contents — never rm -rf a\n // dir that still holds user-added / sibling-tool / shared files.\n changes.push(this.removeDirIfEmpty(dir, ctx.dryRun));\n }\n return changes;\n }\n\n /** Render a skill's SKILL.md (delegates to the shared renderer). */\n private renderSkill(skill: SkillDef): string {\n return renderSkillMd(skill);\n }\n\n // ── Hooks (unavailable — Amp is mcp-only) ────────────────────────────────\n\n installHooks(_ctx: InstallContext): ChangeRecord[] {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail: \"hooks unavailable (Amp is mcp-only)\",\n },\n ];\n }\n\n uninstallHooks(_ctx: InstallContext): ChangeRecord[] {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail: \"hooks unavailable (Amp is mcp-only)\",\n },\n ];\n }\n\n /**\n * True when a hook command references our home binary AND this connector id\n * (anchored so a shared-prefix id can't collide — see isHomeBinHookCommand).\n * Amp installs no hooks, but this guard keeps any future shared-file edit from\n * removing another connector's entries.\n */\n private isOurCommand(command: string | undefined, ctx: InstallContext): boolean {\n return isHomeBinHookCommand(command, ctx.homeBinPath, ctx.connector.id);\n }\n\n // ── Diagnostics ──────────────────────────────────────────────────────────\n\n override getHealthChecks(ctx: InstallContext): readonly HealthCheck[] {\n const settingsPath = this.getServerConfigPath(ctx);\n const connectorId = ctx.connector.id;\n return [\n {\n name: `${this.name}: settings.json present`,\n check: () =>\n existsSync(settingsPath)\n ? { status: \"OK\", detail: settingsPath }\n : { status: \"FAIL\", detail: `not found: ${settingsPath}` },\n },\n {\n name: `${this.name}: server entry registered`,\n check: () => {\n // Only assert what the connector declares: a server-less connector\n // never writes a server entry, so its absence is healthy.\n if (!ctx.connector.server) {\n return { status: \"OK\", detail: \"no MCP server declared\" };\n }\n const cfg = this.readJson<{ [k: string]: Record<string, unknown> }>(settingsPath);\n const bucket = cfg?.[MCP_ROOT_KEY];\n if (!cfg || !bucket) {\n return { status: \"FAIL\", detail: `no \"${MCP_ROOT_KEY}\" in ${settingsPath}` };\n }\n return connectorId in bucket\n ? { status: \"OK\", detail: `\"${MCP_ROOT_KEY}\".${connectorId} present` }\n : {\n status: \"FAIL\",\n detail: `no \"${MCP_ROOT_KEY}\".${connectorId} in ${settingsPath}`,\n };\n },\n },\n ];\n }\n}\n\n/**\n * Amp native interpolation token: `${env:VAR}` → `${VAR}`.\n *\n * When the portable ref carried a default (`${env:VAR:-fallback}`), Amp's native\n * `${VAR}` token has no way to express it — so a bare native token would silently\n * DROP the default. Instead, resolve the default at install time: emit the live\n * value when VAR is set and non-empty, else the literal fallback. The native\n * token is only emitted when there is no default to preserve.\n */\nfunction ampEnvToken(name: string, def?: string): string {\n if (def !== undefined) {\n const v = process.env[name];\n return v != null && v !== \"\" ? v : def;\n }\n return `\\${${name}}`;\n}\n\nexport const adapter = new AmpAdapter();\nexport default adapter;\n"],"mappings":"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","names":["entry"]}
|
|
@@ -3,11 +3,11 @@ import {
|
|
|
3
3
|
AntigravityAdapter,
|
|
4
4
|
adapter,
|
|
5
5
|
antigravity_default
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-LL4OBGRU.js";
|
|
7
7
|
import "./chunk-DBQMX75U.js";
|
|
8
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-IW77FFNX.js";
|
|
9
9
|
import "./chunk-7L6ITC4T.js";
|
|
10
|
-
import "./chunk-
|
|
10
|
+
import "./chunk-BXGFUENQ.js";
|
|
11
11
|
import "./chunk-N6HH7K6P.js";
|
|
12
12
|
import "./chunk-TRQKHP7D.js";
|
|
13
13
|
export {
|
|
@@ -15,4 +15,4 @@ export {
|
|
|
15
15
|
adapter,
|
|
16
16
|
antigravity_default as default
|
|
17
17
|
};
|
|
18
|
-
//# sourceMappingURL=antigravity-
|
|
18
|
+
//# sourceMappingURL=antigravity-ANDKF3K7.js.map
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
AntigravityAdapter
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-LL4OBGRU.js";
|
|
5
5
|
import "./chunk-DBQMX75U.js";
|
|
6
|
-
import "./chunk-
|
|
6
|
+
import "./chunk-IW77FFNX.js";
|
|
7
7
|
import "./chunk-7L6ITC4T.js";
|
|
8
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-BXGFUENQ.js";
|
|
9
9
|
import "./chunk-N6HH7K6P.js";
|
|
10
10
|
import "./chunk-TRQKHP7D.js";
|
|
11
11
|
|
|
@@ -84,4 +84,4 @@ export {
|
|
|
84
84
|
adapter,
|
|
85
85
|
antigravity_cli_default as default
|
|
86
86
|
};
|
|
87
|
-
//# sourceMappingURL=antigravity-cli-
|
|
87
|
+
//# sourceMappingURL=antigravity-cli-LLRPDDOT.js.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
resolveSpawnCommand
|
|
4
|
+
} from "./chunk-BXGFUENQ.js";
|
|
5
|
+
|
|
6
|
+
// src/core/spawn-child.ts
|
|
7
|
+
import { spawn } from "child_process";
|
|
8
|
+
function winQuoteArg(s) {
|
|
9
|
+
return `"${s.replace(/"/g, '""')}"`;
|
|
10
|
+
}
|
|
11
|
+
function spawnChild(command, args, options) {
|
|
12
|
+
const resolved = resolveSpawnCommand(command);
|
|
13
|
+
if (!resolved.needsShell) return spawn(resolved.file, args, options);
|
|
14
|
+
const line = [resolved.file, ...args].map(winQuoteArg).join(" ");
|
|
15
|
+
return spawn(line, { ...options, shell: true });
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export {
|
|
19
|
+
spawnChild
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=chunk-22Y24V7O.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/spawn-child.ts"],"sourcesContent":["/**\n * core/spawn-child — the cross-platform child_process.spawn wrapper.\n *\n * Kept SEPARATE from core/spawn.ts (pure string/path helpers, imported widely\n * and early) so that pulling in `node:child_process` here does not perturb the\n * module-eval order of test suites that vi.mock(\"node:child_process\").\n */\n\nimport { type ChildProcess, type SpawnOptions, spawn } from \"node:child_process\";\n\nimport { resolveSpawnCommand } from \"./spawn.js\";\n\n/**\n * Quote one token for a cmd.exe command line: wrap in double quotes, doubling any\n * embedded double quote. Sufficient for the paths / package names / flags we\n * spawn (connector config, not untrusted end-user input) — we intentionally do\n * not escape cmd metacharacters (& | ^ %), which never appear in those tokens.\n */\nfunction winQuoteArg(s: string): string {\n return `\"${s.replace(/\"/g, '\"\"')}\"`;\n}\n\n/**\n * Cross-platform child spawn that fixes native-Windows package-runner launches.\n * Direct spawn on macOS/Linux. On win32 it routes through\n * {@link resolveSpawnCommand}; an `.exe` runs directly, while a `.cmd`/`.bat`\n * (npx.cmd, the agent-connector.cmd launcher) is launched via a SINGLE quoted\n * command line with `shell: true` — a string rather than an args array, which\n * Node requires for a batch file AND which avoids the DEP0190 deprecation that\n * `shell: true` + an args array triggers on Node ≥ 24.\n */\nexport function spawnChild(\n command: string,\n args: string[],\n options: SpawnOptions,\n): ChildProcess {\n const resolved = resolveSpawnCommand(command);\n if (!resolved.needsShell) return spawn(resolved.file, args, options);\n const line = [resolved.file, ...args].map(winQuoteArg).join(\" \");\n return spawn(line, { ...options, shell: true });\n}\n"],"mappings":";;;;;;AAQA,SAA+C,aAAa;AAU5D,SAAS,YAAY,GAAmB;AACtC,SAAO,IAAI,EAAE,QAAQ,MAAM,IAAI,CAAC;AAClC;AAWO,SAAS,WACd,SACA,MACA,SACc;AACd,QAAM,WAAW,oBAAoB,OAAO;AAC5C,MAAI,CAAC,SAAS,WAAY,QAAO,MAAM,SAAS,MAAM,MAAM,OAAO;AACnE,QAAM,OAAO,CAAC,SAAS,MAAM,GAAG,IAAI,EAAE,IAAI,WAAW,EAAE,KAAK,GAAG;AAC/D,SAAO,MAAM,MAAM,EAAE,GAAG,SAAS,OAAO,KAAK,CAAC;AAChD;","names":[]}
|