@ken-jo/agent-connector 0.4.91 → 0.4.93
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 +326 -563
- package/dist/{action-L44DXFHT.js → action-DOWHWEDZ.js} +14 -14
- package/dist/{amazon-q-B52EY2SV.js → amazon-q-ETMAGY3D.js} +5 -5
- package/dist/{amp-UXABVUKC.js → amp-67BZONGF.js} +5 -5
- package/dist/{antigravity-RZHN53VB.js → antigravity-VXLDLTO7.js} +6 -6
- package/dist/{antigravity-cli-JO6GUTV7.js → antigravity-cli-OM6SC3PE.js} +47 -16
- package/dist/antigravity-cli-OM6SC3PE.js.map +1 -0
- package/dist/{chunk-R6LML2YS.js → chunk-2RIFORQS.js} +2 -2
- package/dist/{chunk-QKLJU4JX.js → chunk-2Y2MZRLP.js} +56 -2
- package/dist/chunk-2Y2MZRLP.js.map +1 -0
- package/dist/{chunk-HORHRHNG.js → chunk-4NHXLXSD.js} +2 -2
- package/dist/{chunk-AY3RGRTT.js → chunk-6TF7MHG5.js} +2 -2
- package/dist/{chunk-NBUEL74R.js → chunk-6WZODR3Z.js} +3 -3
- package/dist/{chunk-LF76VPGQ.js → chunk-B5W3RHTI.js} +72 -22
- package/dist/chunk-B5W3RHTI.js.map +1 -0
- package/dist/{chunk-BLTVZACS.js → chunk-EHP7WISI.js} +9 -9
- package/dist/{chunk-4NSU3KWX.js → chunk-FJCUKXGX.js} +2 -2
- package/dist/{chunk-IXOQDZWC.js → chunk-GZGLCCEE.js} +5 -1
- package/dist/chunk-GZGLCCEE.js.map +1 -0
- package/dist/{chunk-LAIITCMW.js → chunk-I5TO42QC.js} +5 -5
- package/dist/{chunk-4FWETID5.js → chunk-IVAWP6HH.js} +2 -2
- package/dist/{chunk-UBB7T54N.js → chunk-JKKU2WKG.js} +3 -3
- package/dist/{chunk-G4CEELKO.js → chunk-KJLFGQQM.js} +180 -10
- package/dist/chunk-KJLFGQQM.js.map +1 -0
- package/dist/{chunk-NWLRJNXM.js → chunk-KSPMSRVU.js} +27 -15
- package/dist/chunk-KSPMSRVU.js.map +1 -0
- package/dist/{chunk-VVFDU4IX.js → chunk-MGTDQLJJ.js} +12 -5
- package/dist/{chunk-VVFDU4IX.js.map → chunk-MGTDQLJJ.js.map} +1 -1
- package/dist/{chunk-56R2ER7K.js → chunk-NBYKLUF6.js} +2 -2
- package/dist/chunk-OEADFFKO.js +590 -0
- package/dist/chunk-OEADFFKO.js.map +1 -0
- package/dist/{chunk-QARPXSIV.js → chunk-P23RVIUY.js} +4 -4
- package/dist/{chunk-25CPWJA7.js → chunk-SILKSP2Y.js} +43 -43
- package/dist/{chunk-KIRCPLM4.js → chunk-TTKSYJRY.js} +538 -226
- package/dist/chunk-TTKSYJRY.js.map +1 -0
- package/dist/{chunk-YYNXIUR2.js → chunk-UMQ6NBQR.js} +3 -3
- package/dist/chunk-UMQ6NBQR.js.map +1 -0
- package/dist/{chunk-4HVQ7IUM.js → chunk-XC5SJ35F.js} +17 -4
- package/dist/chunk-XC5SJ35F.js.map +1 -0
- package/dist/{chunk-LN76OGNR.js → chunk-Z2MRSS2I.js} +2 -2
- package/dist/{chunk-ZMLVR4J7.js → chunk-ZMAJ2XFD.js} +2 -2
- package/dist/{claude-code-WS4NAGZT.js → claude-code-DUZNOAS2.js} +9 -9
- package/dist/cli/sdk.js +7 -7
- package/dist/cli.js +1 -1
- package/dist/{cline-NNMVCECA.js → cline-25KW25IN.js} +5 -5
- package/dist/{codebuddy-RBEZGXBG.js → codebuddy-ZNYQACMF.js} +5 -5
- package/dist/{codebuff-RJIDSEU3.js → codebuff-VR6JUDIY.js} +5 -5
- package/dist/{codex-ZZ434GYR.js → codex-CPNKTXG3.js} +11 -5
- package/dist/{codex-ZZ434GYR.js.map → codex-CPNKTXG3.js.map} +1 -1
- package/dist/{continue-MNM7YVJY.js → continue-WU2IB5KS.js} +6 -6
- package/dist/{copilot-cli-SMTX5F65.js → copilot-cli-PAP377OM.js} +5 -5
- package/dist/{crush-NYDBHIJE.js → crush-3AVQA4YU.js} +5 -5
- package/dist/{cursor-AOELDNZU.js → cursor-GSLUET3V.js} +6 -6
- package/dist/define-connector-LQFJL_at.d.ts +89 -0
- package/dist/{detect-3S46RUMK.js → detect-DYQNUMXL.js} +4 -4
- package/dist/{devin-PRJY2TTD.js → devin-QMEM3OFA.js} +5 -5
- package/dist/{doctor-3CUBPQKU.js → doctor-H6XXAR63.js} +25 -21
- package/dist/doctor-H6XXAR63.js.map +1 -0
- package/dist/{droid-PTCH2K7Y.js → droid-MOKV53J4.js} +5 -5
- package/dist/{gemini-cli-QGLN2UMS.js → gemini-cli-47ZHCOZR.js} +5 -5
- package/dist/{goose-DQ6GSZ5O.js → goose-4EI5MYTI.js} +6 -6
- package/dist/{grok-cli-5QD235UB.js → grok-cli-QYQPDSVB.js} +5 -5
- package/dist/{hermes-E47IG63A.js → hermes-F75OSK3Y.js} +6 -6
- package/dist/{hook-P6EKDINW.js → hook-GIQTUDMN.js} +14 -14
- package/dist/index.d.ts +15 -88
- package/dist/index.js +15 -7
- package/dist/install-T27662FW.js +382 -0
- package/dist/install-T27662FW.js.map +1 -0
- package/dist/{introspect-DYOIX8Ov.d.ts → introspect-D4fEGuhN.d.ts} +1 -1
- package/dist/{jetbrains-copilot-T2EPKROP.js → jetbrains-copilot-ZGIWI6YV.js} +23 -7
- package/dist/jetbrains-copilot-ZGIWI6YV.js.map +1 -0
- package/dist/{junie-SQ4SDLGK.js → junie-DIFN2P22.js} +5 -5
- package/dist/{kilo-OU2ZLZKB.js → kilo-EMZJBEBB.js} +5 -5
- package/dist/{kilo-cli-NMWGYF4F.js → kilo-cli-S3GXBPAE.js} +5 -5
- package/dist/{kimi-Z7L2LEEI.js → kimi-IQJOIY6B.js} +5 -5
- package/dist/{kiro-4IN5IH46.js → kiro-BYX4HEAJ.js} +5 -5
- package/dist/{leaderboard-LF5SP6X2.js → leaderboard-CIMQBOUS.js} +5 -5
- package/dist/{mimo-code-G2CBZ4M6.js → mimo-code-7R53QDHB.js} +5 -5
- package/dist/{mistral-vibe-TRQDHAWV.js → mistral-vibe-LHJ55FSB.js} +5 -5
- package/dist/{mux-JNM3F2NW.js → mux-NYCNGL43.js} +5 -5
- package/dist/{nemoclaw-SHA4IUML.js → nemoclaw-WSIPSE7U.js} +6 -6
- package/dist/{omp-OOVUNXME.js → omp-562NK5BJ.js} +5 -5
- package/dist/{open-interpreter-4PKL56AA.js → open-interpreter-I2CNOEXY.js} +5 -5
- package/dist/openclaw-7EYBQS4R.js +17 -0
- package/dist/{opencode-W2RK4M7G.js → opencode-YS4WX2E2.js} +5 -5
- package/dist/{openhands-5LNH3BKB.js → openhands-QMYIKNOS.js} +5 -5
- package/dist/{package-2EAIYSJ4.js → package-LIPZKHAQ.js} +12 -12
- package/dist/{pi-BUADR5MJ.js → pi-644FIN3A.js} +5 -5
- package/dist/{qwen-code-TUJNHKNI.js → qwen-code-STDMX7EM.js} +6 -6
- package/dist/{roo-code-L5F7S6QH.js → roo-code-DLPIHHQ6.js} +5 -5
- package/dist/runtime/index.d.ts +1 -1
- package/dist/runtime/index.js +12 -12
- package/dist/sdk/index.d.ts +4 -4
- package/dist/sdk/index.js +6 -6
- package/dist/sdk/test.d.ts +2 -2
- package/dist/sdk/test.js +10 -10
- package/dist/{serve-K62FW3V7.js → serve-ABTO2NA2.js} +14 -14
- package/dist/{status-E5MCFZM6.js → status-J7SOUH7O.js} +10 -10
- package/dist/{statusline-LIPF2KVP.js → statusline-QF4G724E.js} +13 -13
- package/dist/{telemetry-4OC56NTM.js → telemetry-EICCFEIF.js} +10 -10
- package/dist/{trae-Z7CQ2A2Q.js → trae-UOYD6JZZ.js} +5 -5
- package/dist/{types-C4qMgbJn.d.ts → types-BhcUEIJJ.d.ts} +82 -3
- package/dist/{uninstall-2YYKN5DX.js → uninstall-NJNNZZZY.js} +35 -25
- package/dist/uninstall-NJNNZZZY.js.map +1 -0
- package/dist/{upgrade-55AFPJEF.js → upgrade-TIBUOQNM.js} +23 -17
- package/dist/upgrade-TIBUOQNM.js.map +1 -0
- package/dist/{usage-3PB3WZSL.js → usage-VEVBWPLS.js} +2 -2
- package/dist/{usage-event-KD5FW6W4.js → usage-event-GRQE7XWT.js} +13 -13
- package/dist/{vscode-copilot-LU5NC4ZS.js → vscode-copilot-NIMH2DGU.js} +20 -5
- package/dist/vscode-copilot-NIMH2DGU.js.map +1 -0
- package/dist/{warp-4PPG5LOM.js → warp-QYJGKURM.js} +5 -5
- package/dist/{windsurf-3T3RVXKM.js → windsurf-75LLZ37C.js} +5 -5
- package/dist/{zed-ZF2OQ75O.js → zed-HKAZXEJW.js} +5 -5
- package/package.json +1 -1
- package/dist/antigravity-cli-JO6GUTV7.js.map +0 -1
- package/dist/chunk-4HVQ7IUM.js.map +0 -1
- package/dist/chunk-7HUUINPB.js +0 -201
- package/dist/chunk-7HUUINPB.js.map +0 -1
- package/dist/chunk-G4CEELKO.js.map +0 -1
- package/dist/chunk-IXOQDZWC.js.map +0 -1
- package/dist/chunk-KIRCPLM4.js.map +0 -1
- package/dist/chunk-LF76VPGQ.js.map +0 -1
- package/dist/chunk-NWLRJNXM.js.map +0 -1
- package/dist/chunk-QKLJU4JX.js.map +0 -1
- package/dist/chunk-YYNXIUR2.js.map +0 -1
- package/dist/doctor-3CUBPQKU.js.map +0 -1
- package/dist/install-7DMK53SB.js +0 -96
- package/dist/install-7DMK53SB.js.map +0 -1
- package/dist/jetbrains-copilot-T2EPKROP.js.map +0 -1
- package/dist/openclaw-BD56E5MV.js +0 -17
- package/dist/uninstall-2YYKN5DX.js.map +0 -1
- package/dist/upgrade-55AFPJEF.js.map +0 -1
- package/dist/vscode-copilot-LU5NC4ZS.js.map +0 -1
- /package/dist/{action-L44DXFHT.js.map → action-DOWHWEDZ.js.map} +0 -0
- /package/dist/{amazon-q-B52EY2SV.js.map → amazon-q-ETMAGY3D.js.map} +0 -0
- /package/dist/{amp-UXABVUKC.js.map → amp-67BZONGF.js.map} +0 -0
- /package/dist/{antigravity-RZHN53VB.js.map → antigravity-VXLDLTO7.js.map} +0 -0
- /package/dist/{chunk-R6LML2YS.js.map → chunk-2RIFORQS.js.map} +0 -0
- /package/dist/{chunk-HORHRHNG.js.map → chunk-4NHXLXSD.js.map} +0 -0
- /package/dist/{chunk-AY3RGRTT.js.map → chunk-6TF7MHG5.js.map} +0 -0
- /package/dist/{chunk-NBUEL74R.js.map → chunk-6WZODR3Z.js.map} +0 -0
- /package/dist/{chunk-BLTVZACS.js.map → chunk-EHP7WISI.js.map} +0 -0
- /package/dist/{chunk-4NSU3KWX.js.map → chunk-FJCUKXGX.js.map} +0 -0
- /package/dist/{chunk-LAIITCMW.js.map → chunk-I5TO42QC.js.map} +0 -0
- /package/dist/{chunk-4FWETID5.js.map → chunk-IVAWP6HH.js.map} +0 -0
- /package/dist/{chunk-UBB7T54N.js.map → chunk-JKKU2WKG.js.map} +0 -0
- /package/dist/{chunk-56R2ER7K.js.map → chunk-NBYKLUF6.js.map} +0 -0
- /package/dist/{chunk-QARPXSIV.js.map → chunk-P23RVIUY.js.map} +0 -0
- /package/dist/{chunk-25CPWJA7.js.map → chunk-SILKSP2Y.js.map} +0 -0
- /package/dist/{chunk-LN76OGNR.js.map → chunk-Z2MRSS2I.js.map} +0 -0
- /package/dist/{chunk-ZMLVR4J7.js.map → chunk-ZMAJ2XFD.js.map} +0 -0
- /package/dist/{claude-code-WS4NAGZT.js.map → claude-code-DUZNOAS2.js.map} +0 -0
- /package/dist/{cline-NNMVCECA.js.map → cline-25KW25IN.js.map} +0 -0
- /package/dist/{codebuddy-RBEZGXBG.js.map → codebuddy-ZNYQACMF.js.map} +0 -0
- /package/dist/{codebuff-RJIDSEU3.js.map → codebuff-VR6JUDIY.js.map} +0 -0
- /package/dist/{continue-MNM7YVJY.js.map → continue-WU2IB5KS.js.map} +0 -0
- /package/dist/{copilot-cli-SMTX5F65.js.map → copilot-cli-PAP377OM.js.map} +0 -0
- /package/dist/{crush-NYDBHIJE.js.map → crush-3AVQA4YU.js.map} +0 -0
- /package/dist/{cursor-AOELDNZU.js.map → cursor-GSLUET3V.js.map} +0 -0
- /package/dist/{detect-3S46RUMK.js.map → detect-DYQNUMXL.js.map} +0 -0
- /package/dist/{devin-PRJY2TTD.js.map → devin-QMEM3OFA.js.map} +0 -0
- /package/dist/{droid-PTCH2K7Y.js.map → droid-MOKV53J4.js.map} +0 -0
- /package/dist/{gemini-cli-QGLN2UMS.js.map → gemini-cli-47ZHCOZR.js.map} +0 -0
- /package/dist/{goose-DQ6GSZ5O.js.map → goose-4EI5MYTI.js.map} +0 -0
- /package/dist/{grok-cli-5QD235UB.js.map → grok-cli-QYQPDSVB.js.map} +0 -0
- /package/dist/{hermes-E47IG63A.js.map → hermes-F75OSK3Y.js.map} +0 -0
- /package/dist/{hook-P6EKDINW.js.map → hook-GIQTUDMN.js.map} +0 -0
- /package/dist/{junie-SQ4SDLGK.js.map → junie-DIFN2P22.js.map} +0 -0
- /package/dist/{kilo-OU2ZLZKB.js.map → kilo-EMZJBEBB.js.map} +0 -0
- /package/dist/{kilo-cli-NMWGYF4F.js.map → kilo-cli-S3GXBPAE.js.map} +0 -0
- /package/dist/{kimi-Z7L2LEEI.js.map → kimi-IQJOIY6B.js.map} +0 -0
- /package/dist/{kiro-4IN5IH46.js.map → kiro-BYX4HEAJ.js.map} +0 -0
- /package/dist/{leaderboard-LF5SP6X2.js.map → leaderboard-CIMQBOUS.js.map} +0 -0
- /package/dist/{mimo-code-G2CBZ4M6.js.map → mimo-code-7R53QDHB.js.map} +0 -0
- /package/dist/{mistral-vibe-TRQDHAWV.js.map → mistral-vibe-LHJ55FSB.js.map} +0 -0
- /package/dist/{mux-JNM3F2NW.js.map → mux-NYCNGL43.js.map} +0 -0
- /package/dist/{nemoclaw-SHA4IUML.js.map → nemoclaw-WSIPSE7U.js.map} +0 -0
- /package/dist/{omp-OOVUNXME.js.map → omp-562NK5BJ.js.map} +0 -0
- /package/dist/{open-interpreter-4PKL56AA.js.map → open-interpreter-I2CNOEXY.js.map} +0 -0
- /package/dist/{openclaw-BD56E5MV.js.map → openclaw-7EYBQS4R.js.map} +0 -0
- /package/dist/{opencode-W2RK4M7G.js.map → opencode-YS4WX2E2.js.map} +0 -0
- /package/dist/{openhands-5LNH3BKB.js.map → openhands-QMYIKNOS.js.map} +0 -0
- /package/dist/{package-2EAIYSJ4.js.map → package-LIPZKHAQ.js.map} +0 -0
- /package/dist/{pi-BUADR5MJ.js.map → pi-644FIN3A.js.map} +0 -0
- /package/dist/{qwen-code-TUJNHKNI.js.map → qwen-code-STDMX7EM.js.map} +0 -0
- /package/dist/{roo-code-L5F7S6QH.js.map → roo-code-DLPIHHQ6.js.map} +0 -0
- /package/dist/{serve-K62FW3V7.js.map → serve-ABTO2NA2.js.map} +0 -0
- /package/dist/{status-E5MCFZM6.js.map → status-J7SOUH7O.js.map} +0 -0
- /package/dist/{statusline-LIPF2KVP.js.map → statusline-QF4G724E.js.map} +0 -0
- /package/dist/{telemetry-4OC56NTM.js.map → telemetry-EICCFEIF.js.map} +0 -0
- /package/dist/{trae-Z7CQ2A2Q.js.map → trae-UOYD6JZZ.js.map} +0 -0
- /package/dist/{usage-3PB3WZSL.js.map → usage-VEVBWPLS.js.map} +0 -0
- /package/dist/{usage-event-KD5FW6W4.js.map → usage-event-GRQE7XWT.js.map} +0 -0
- /package/dist/{warp-4PPG5LOM.js.map → warp-QYJGKURM.js.map} +0 -0
- /package/dist/{windsurf-3T3RVXKM.js.map → windsurf-75LLZ37C.js.map} +0 -0
- /package/dist/{zed-ZF2OQ75O.js.map → zed-HKAZXEJW.js.map} +0 -0
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
backupsDir,
|
|
5
5
|
connectorDir,
|
|
6
6
|
ensureDir
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-GZGLCCEE.js";
|
|
8
8
|
|
|
9
9
|
// src/core/managed-block.ts
|
|
10
10
|
import { createHash } from "crypto";
|
|
@@ -30,7 +30,7 @@ function hashBlockContent(inner) {
|
|
|
30
30
|
return createHash("sha256").update(normalizeInner(inner), "utf8").digest("hex").slice(0, 12);
|
|
31
31
|
}
|
|
32
32
|
function defaultNotice(connectorId) {
|
|
33
|
-
return `Managed by agent-connector for "${connectorId}". Do not edit between these markers:
|
|
33
|
+
return `Managed by agent-connector for "${connectorId}". Do not edit between these markers: run your connector package's upgrade/sync command to rewrite this block; run its uninstall command to remove it (framework fallback: \`agent-connector uninstall ${connectorId}\`).`;
|
|
34
34
|
}
|
|
35
35
|
function beginLine(blockId, hash, style) {
|
|
36
36
|
return style === "hash" ? `# ${MANAGED_BLOCK_BEGIN_TOKEN} ${blockId} hash=${hash}` : `<!-- ${MANAGED_BLOCK_BEGIN_TOKEN} ${blockId} hash=${hash} -->`;
|
|
@@ -493,4 +493,4 @@ export {
|
|
|
493
493
|
hasMemoryLedger,
|
|
494
494
|
recordMemoryTarget
|
|
495
495
|
};
|
|
496
|
-
//# sourceMappingURL=chunk-
|
|
496
|
+
//# sourceMappingURL=chunk-UMQ6NBQR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/managed-block.ts"],"sourcesContent":["/**\n * core/managed-block — the marker-fenced MANAGED BLOCK engine behind the\n * `memory` content surface.\n *\n * Memory/rules files (AGENTS.md, CLAUDE.md, GEMINI.md, …) are SHARED,\n * user-authored files — unlike commands/skills/subagents, agent-connector does\n * not own them. Every write therefore goes through this one module, which\n * implements idempotent, hash-stamped, uninstall-reversible blocks:\n *\n * <!-- agent-connector:begin <connectorId>/<name> hash=<sha256-12> -->\n * <!-- Managed by agent-connector for \"<connectorId>\". Do not edit … -->\n * …guidance…\n * <!-- agent-connector:end <connectorId>/<name> -->\n *\n * Design rules (each grounded in surveyed prior art — ansible blockinfile,\n * conda init, OMC mergeClaudeMd, Ruler, doctoc):\n * • UNIQUE marker per block: the blockId (`<connectorId>/<entryName>`) lives\n * ON the marker line, so multiple connectors coexist in one file and each\n * update path only ever touches its own pair (ansible's documented\n * multi-block rule). The shared `agent-connector` namespace token lets\n * doctor/uninstall enumerate every block with one scan.\n * • `hash=` is the first 12 hex chars of sha256 over the NORMALIZED inner\n * region (CRLF→LF + trim — stable under prettier/EOL converters): O(1)\n * idempotence (unchanged → skip, no mtime/git churn) and tamper detection\n * (actual inner hash ≠ recorded ⇒ the user edited inside the block ⇒ warn,\n * never clobber without an explicit force).\n * • IN-PLACE replacement (conda semantics): zero bytes outside the marker\n * pair ever change — no move-to-top, no user blank-line reflow.\n * • Line-anchored matching that explicitly tolerates `\\r` line ends and a\n * FENCE-AWARE scanner (markers quoted inside ``` / ~~~ code fences never\n * match) — fixes the CRLF duplicate-block and quoted-marker classes.\n * • First-begin / FIRST-end-after pairing (never last-end): a missing end\n * marker must not swallow a sibling connector's block.\n * • HTML-comment markers are CORRECT for CLAUDE.md: Claude Code strips HTML\n * comments from CLAUDE.md before context injection (verified against docs\n * and the 2.1.172 binary), so the markers and the do-not-edit notice are\n * INVISIBLE to the model there while remaining fully parseable by us for\n * sync/doctor/uninstall. On AGENTS.md hosts (which inline the whole file\n * into the prompt) the short notice doubles as an in-prompt \"do not edit\"\n * instruction to the host's own agent. A `commentStyle: \"hash\"` variant\n * exists for future non-markdown targets (`#`-prefixed marker lines).\n *\n * The module also owns the per-connector MEMORY OWNERSHIP LEDGER\n * (`connectorDir(id)/memory-state.json`): the markers in the file remain the\n * source of truth for uninstall (a teammate's machine with no ledger still\n * uninstalls via the prefix scan); the ledger only adds the created-vs-modified\n * distinction (file deletion rights) and doctor diagnostics.\n */\n\nimport { createHash } from \"node:crypto\";\nimport {\n chmodSync,\n copyFileSync,\n existsSync,\n readFileSync,\n renameSync,\n rmSync,\n statSync,\n writeFileSync,\n} from \"node:fs\";\nimport { basename, dirname, join } from \"node:path\";\n\nimport { assertNoSymlinkInPath, backupsDir, connectorDir, ensureDir } from \"./paths.js\";\n\n// ─────────────────────────────────────────────────────────────────────────\n// Grammar constants (shared with defineConnector's content validation)\n// ─────────────────────────────────────────────────────────────────────────\n\n/** Literal begin token. Connector memory content MUST NOT contain it. */\nexport const MANAGED_BLOCK_BEGIN_TOKEN = \"agent-connector:begin\";\n/** Literal end token. Connector memory content MUST NOT contain it. */\nexport const MANAGED_BLOCK_END_TOKEN = \"agent-connector:end\";\n\n/** Hard cap on one memory entry's content (ConnectorConfigError above this). */\nexport const MEMORY_CONTENT_HARD_CAP_BYTES = 16 * 1024;\n/**\n * Soft per-entry budget — exceeded → install-time `warn` ChangeRecord (memory\n * files are injected into EVERY prompt of EVERY session on the host; codex\n * additionally caps combined project docs at 32 KiB).\n */\nexport const MEMORY_CONTENT_SOFT_BUDGET_BYTES = 4 * 1024;\n\n/** Marker comment style: HTML comments (default, all v1 markdown targets) or `#` lines. */\nexport type BlockCommentStyle = \"html\" | \"hash\";\n\n// ─────────────────────────────────────────────────────────────────────────\n// Hashing / rendering\n// ─────────────────────────────────────────────────────────────────────────\n\n/** CRLF/CR → LF + trim: the normalization both hashing sides use. */\nfunction normalizeInner(s: string): string {\n return s.replace(/\\r\\n/g, \"\\n\").replace(/\\r/g, \"\\n\").trim();\n}\n\n/** First 12 hex chars of sha256 over the NORMALIZED inner region. */\nexport function hashBlockContent(inner: string): string {\n return createHash(\"sha256\").update(normalizeInner(inner), \"utf8\").digest(\"hex\").slice(0, 12);\n}\n\n/** The conda-style in-block warning, adapted for the LLM era (see header). */\nfunction defaultNotice(connectorId: string): string {\n return (\n `Managed by agent-connector for \"${connectorId}\". Do not edit between these markers: ` +\n `run your connector package's upgrade/sync command to rewrite this block; ` +\n `run its uninstall command to remove it ` +\n `(framework fallback: \\`agent-connector uninstall ${connectorId}\\`).`\n );\n}\n\nfunction beginLine(blockId: string, hash: string, style: BlockCommentStyle): string {\n return style === \"hash\"\n ? `# ${MANAGED_BLOCK_BEGIN_TOKEN} ${blockId} hash=${hash}`\n : `<!-- ${MANAGED_BLOCK_BEGIN_TOKEN} ${blockId} hash=${hash} -->`;\n}\n\n/** END line is a fixed exact string (no hash) so a content change never strands it. */\nfunction endLine(blockId: string, style: BlockCommentStyle): string {\n return style === \"hash\"\n ? `# ${MANAGED_BLOCK_END_TOKEN} ${blockId}`\n : `<!-- ${MANAGED_BLOCK_END_TOKEN} ${blockId} -->`;\n}\n\nfunction noticeLine(notice: string, style: BlockCommentStyle): string {\n return style === \"hash\" ? `# ${notice}` : `<!-- ${notice} -->`;\n}\n\nexport interface RenderBlockOptions {\n /** `<connectorId>/<entryName>` (or the reserved `_shared/<name>` bridge prefix). */\n blockId: string;\n /** Connector id named in the default do-not-edit notice line. */\n connectorId: string;\n /** The guidance payload (plain markdown; normalized + trimmed on emit). */\n content: string;\n /** Marker comment style; default \"html\". */\n commentStyle?: BlockCommentStyle;\n /** Override the default notice line TEXT (without comment delimiters). */\n notice?: string;\n}\n\n/**\n * Render the block as LOGICAL lines (no EOL chars). The recorded `hash=`\n * covers the full inner region (notice line + content) so install and scan\n * compare like for like.\n */\nexport function renderBlockLines(opts: RenderBlockOptions): string[] {\n const style = opts.commentStyle ?? \"html\";\n const inner = [\n noticeLine(opts.notice ?? defaultNotice(opts.connectorId), style),\n ...normalizeInner(opts.content).split(\"\\n\"),\n ];\n const hash = hashBlockContent(inner.join(\"\\n\"));\n return [beginLine(opts.blockId, hash, style), ...inner, endLine(opts.blockId, style)];\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Scanning (fence-aware, line-anchored, CRLF-tolerant)\n// ─────────────────────────────────────────────────────────────────────────\n\n// Both comment styles are RECOGNIZED in one pass (a file may legitimately mix\n// styles only across rewrites; emission always uses the requested style).\nconst BEGIN_RE =\n /^(?:<!--\\s+agent-connector:begin\\s+(\\S+)\\s+hash=([0-9a-f]{12})\\s+-->|#\\s+agent-connector:begin\\s+(\\S+)\\s+hash=([0-9a-f]{12}))\\s*$/;\nconst END_RE = /^(?:<!--\\s+agent-connector:end\\s+(\\S+)\\s+-->|#\\s+agent-connector:end\\s+(\\S+))\\s*$/;\n\ninterface MarkerEvent {\n kind: \"begin\" | \"end\";\n blockId: string;\n /** Recorded hash (begin markers only). */\n hash?: string;\n /** Line index into the logical-lines array. */\n index: number;\n}\n\n/** Strip ONE trailing `\\r` — `raw.split(\"\\n\")` leaves it on CRLF files. */\nfunction stripCr(line: string): string {\n return line.endsWith(\"\\r\") ? line.slice(0, -1) : line;\n}\n\n/**\n * Scan logical lines for marker events, tracking ``` / ~~~ fence state so a\n * marker QUOTED inside a fenced code block never matches (the OMC class of\n * false positives, eliminated rather than just reduced).\n */\nfunction scanMarkers(logical: string[]): MarkerEvent[] {\n const events: MarkerEvent[] = [];\n let fence: { char: string; len: number } | null = null;\n for (let i = 0; i < logical.length; i++) {\n const line = logical[i]!;\n if (fence) {\n const close = line.match(/^ {0,3}(`{3,}|~{3,})\\s*$/);\n if (close && close[1]![0] === fence.char && close[1]!.length >= fence.len) fence = null;\n continue;\n }\n const open = line.match(/^ {0,3}(`{3,}|~{3,})/);\n if (open) {\n fence = { char: open[1]![0]!, len: open[1]!.length };\n continue;\n }\n const b = line.match(BEGIN_RE);\n if (b) {\n events.push({ kind: \"begin\", blockId: (b[1] ?? b[3])!, hash: (b[2] ?? b[4])!, index: i });\n continue;\n }\n const e = line.match(END_RE);\n if (e) events.push({ kind: \"end\", blockId: (e[1] ?? e[2])!, index: i });\n }\n return events;\n}\n\n/**\n * Logical lines of `raw` that sit OUTSIDE ``` / ~~~ code fences — for host\n * probes that must ignore quoted examples (e.g. the claude-code `@AGENTS.md`\n * import detection). Fence lines themselves are excluded.\n */\nexport function linesOutsideFences(raw: string): string[] {\n const body = raw.startsWith(\"\\uFEFF\") ? raw.slice(1) : raw;\n const logical = body.split(\"\\n\").map(stripCr);\n const out: string[] = [];\n let fence: { char: string; len: number } | null = null;\n for (const line of logical) {\n if (fence) {\n const close = line.match(/^ {0,3}(`{3,}|~{3,})\\s*$/);\n if (close && close[1]![0] === fence.char && close[1]!.length >= fence.len) fence = null;\n continue;\n }\n const open = line.match(/^ {0,3}(`{3,}|~{3,})/);\n if (open) {\n fence = { char: open[1]![0]!, len: open[1]!.length };\n continue;\n }\n out.push(line);\n }\n return out;\n}\n\ninterface BlockPair {\n blockId: string;\n begin: MarkerEvent;\n end: MarkerEvent;\n}\n\n/**\n * Pair markers per blockId: first begin, then the FIRST end at-or-after it.\n * A nested begin for the SAME id (inside an open pair) is treated as inner\n * content; unpaired markers are returned as strays. Per-id state means a\n * missing end for connector A can never swallow connector B's block.\n */\nfunction pairMarkers(events: MarkerEvent[]): { pairs: BlockPair[]; strays: MarkerEvent[] } {\n const open = new Map<string, MarkerEvent>();\n const pairs: BlockPair[] = [];\n const strays: MarkerEvent[] = [];\n for (const ev of events) {\n if (ev.kind === \"begin\") {\n if (!open.has(ev.blockId)) open.set(ev.blockId, ev);\n // else: a begin inside an open pair — inner content / abuse; the hash\n // check will flag the pair as drifted rather than guessing boundaries.\n } else {\n const b = open.get(ev.blockId);\n if (b) {\n pairs.push({ blockId: ev.blockId, begin: b, end: ev });\n open.delete(ev.blockId);\n } else {\n strays.push(ev);\n }\n }\n }\n for (const b of open.values()) strays.push(b);\n return { pairs, strays };\n}\n\n/** One discovered block (for doctor / refcount / uninstall enumeration). */\nexport interface ManagedBlockInfo {\n blockId: string;\n /** The hash recorded on the begin marker line. */\n recordedHash: string;\n /** Hash of the actual normalized inner region as found on disk. */\n actualHash: string;\n /** True when recordedHash ≠ actualHash — the user edited inside the block. */\n drifted: boolean;\n beginLine: number;\n endLine: number;\n}\n\n/** Enumerate every complete agent-connector block in `raw` (namespace scan). */\nexport function listManagedBlocks(raw: string): ManagedBlockInfo[] {\n const body = raw.startsWith(\"\\uFEFF\") ? raw.slice(1) : raw;\n const logical = body.split(\"\\n\").map(stripCr);\n const { pairs } = pairMarkers(scanMarkers(logical));\n return pairs.map((p) => {\n const inner = logical.slice(p.begin.index + 1, p.end.index).join(\"\\n\");\n const actualHash = hashBlockContent(inner);\n const recordedHash = p.begin.hash ?? \"\";\n return {\n blockId: p.blockId,\n recordedHash,\n actualHash,\n drifted: recordedHash !== actualHash,\n beginLine: p.begin.index,\n endLine: p.end.index,\n };\n });\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Pure text upsert / removal\n// ─────────────────────────────────────────────────────────────────────────\n\nexport interface UpsertBlockOptions extends RenderBlockOptions {\n /** Overwrite a USER-EDITED (drifted) block. Default false → warn + leave intact. */\n force?: boolean;\n}\n\nexport interface BlockTextResult {\n /** Resulting full text (=== input when nothing changed). */\n text: string;\n action: \"create\" | \"update\" | \"skip\" | \"warn\";\n detail: string;\n changed: boolean;\n /**\n * True when the rewrite was DESTRUCTIVE-ADJACENT (force-overwrote a drifted\n * block, collapsed duplicate pairs, or stripped stray markers) — the file\n * wrapper writes a timestamped backup before persisting such a change.\n */\n recovered: boolean;\n /** Hash of the (new) rendered inner region — recorded in the ledger. */\n hash: string;\n}\n\n/** Detect the file's dominant EOL; new/replaced lines are emitted with it. */\nfunction detectEol(body: string): \"\\n\" | \"\\r\\n\" {\n const crlf = (body.match(/\\r\\n/g) ?? []).length;\n const total = (body.match(/\\n/g) ?? []).length;\n return crlf > 0 && crlf >= total - crlf ? \"\\r\\n\" : \"\\n\";\n}\n\n/** Add `\\r` to logical lines when the file is CRLF (joined with \"\\n\" later). */\nfunction withEol(lines: string[], eol: \"\\n\" | \"\\r\\n\"): string[] {\n return eol === \"\\r\\n\" ? lines.map((l) => `${l}\\r`) : lines;\n}\n\n/**\n * Strip trailing newline(s) + whitespace-only line tails WITHOUT touching\n * trailing spaces on the last content line (bytes outside our block).\n */\nfunction trimTrailingBlank(body: string): string {\n let out = body;\n for (;;) {\n const m = out.match(/\\r?\\n[ \\t]*$/);\n if (!m) return out;\n out = out.slice(0, out.length - m[0].length);\n }\n}\n\n/** Append the rendered block at EOF with exactly ONE blank separator line. */\nfunction appendBlock(body: string, blockLines: string[], eol: \"\\n\" | \"\\r\\n\"): string {\n const blockText = blockLines.join(eol) + eol;\n if (body.trim() === \"\") return blockText;\n return trimTrailingBlank(body) + eol + eol + blockText;\n}\n\n/**\n * Idempotent upsert of one managed block into `raw` (pure; no I/O).\n * See the module header for the full algorithm contract.\n */\nexport function upsertBlockInText(raw: string, opts: UpsertBlockOptions): BlockTextResult {\n const bom = raw.startsWith(\"\\uFEFF\");\n const body = bom ? raw.slice(1) : raw;\n const eol = detectEol(body);\n const lines = body.split(\"\\n\"); // elements keep a trailing \"\\r\" on CRLF files\n const logical = lines.map(stripCr);\n\n const events = scanMarkers(logical).filter((e) => e.blockId === opts.blockId);\n const { pairs, strays } = pairMarkers(events);\n\n const newLines = renderBlockLines(opts);\n const newHash = hashBlockContent(newLines.slice(1, -1).join(\"\\n\"));\n const finish = (text: string, r: Omit<BlockTextResult, \"text\" | \"hash\">): BlockTextResult => ({\n text: bom ? `\\uFEFF${text}` : text,\n hash: newHash,\n ...r,\n });\n\n if (pairs.length > 0) {\n const { begin, end } = pairs[0]!;\n const recorded = begin.hash ?? \"\";\n const actualHash = hashBlockContent(logical.slice(begin.index + 1, end.index).join(\"\\n\"));\n const drifted = actualHash !== recorded;\n\n if (drifted && !opts.force) {\n return finish(body, {\n action: \"warn\",\n detail:\n `block ${opts.blockId} was edited inside the markers ` +\n `(recorded hash ${recorded}, found ${actualHash}); left untouched — ` +\n `re-run with --force to overwrite the in-block edits`,\n changed: false,\n recovered: false,\n });\n }\n\n const duplicates = pairs.slice(1);\n const needsWrite =\n drifted || recorded !== newHash || duplicates.length > 0 || strays.length > 0;\n if (!needsWrite) {\n return finish(body, {\n action: \"skip\",\n detail: `block ${opts.blockId} already up to date (hash ${newHash})`,\n changed: false,\n recovered: false,\n });\n }\n\n // Build the deletion set: the canonical pair region (replaced in place),\n // duplicate pairs (+ ONE adjacent blank line each), and stray marker LINES.\n const del = new Set<number>();\n for (let i = begin.index; i <= end.index; i++) del.add(i);\n for (const dup of duplicates) {\n for (let i = dup.begin.index; i <= dup.end.index; i++) del.add(i);\n reclaimBlankLine(logical, dup.begin.index, dup.end.index, del, lines.length);\n }\n for (const s of strays) del.add(s.index);\n\n const out: string[] = [];\n for (let i = 0; i < lines.length; i++) {\n if (i === begin.index) out.push(...withEol(newLines, eol));\n if (!del.has(i)) out.push(lines[i]!);\n }\n const notes: string[] = [];\n if (drifted) notes.push(\"in-block edits overwritten (--force; backup taken)\");\n if (duplicates.length > 0) notes.push(`${duplicates.length} duplicate pair(s) collapsed`);\n if (strays.length > 0) notes.push(`${strays.length} stray marker line(s) removed`);\n return finish(out.join(\"\\n\"), {\n action: \"update\",\n detail:\n `block ${opts.blockId} updated (hash ${recorded || \"?\"} → ${newHash})` +\n (notes.length > 0 ? `; ${notes.join(\"; \")}` : \"\"),\n changed: true,\n recovered: drifted || duplicates.length > 0 || strays.length > 0,\n });\n }\n\n if (strays.length > 0) {\n // Corruption recovery: strip ONLY the stray marker line(s) (never the text\n // between guessed boundaries), then proceed as not-found.\n const del = new Set(strays.map((s) => s.index));\n const cleaned = lines.filter((_, i) => !del.has(i)).join(\"\\n\");\n return finish(appendBlock(cleaned, newLines, eol), {\n action: \"create\",\n detail:\n `block ${opts.blockId} appended after recovery: ${strays.length} stray ` +\n `marker line(s) removed (backup taken)`,\n changed: true,\n recovered: true,\n });\n }\n\n // Not found → append at EOF (one blank separator; whole file when empty).\n return finish(appendBlock(body, newLines, eol), {\n action: \"create\",\n detail: `block ${opts.blockId} appended (hash ${newHash})`,\n changed: true,\n recovered: false,\n });\n}\n\n/**\n * Mark ONE blank line adjacent to a removed begin..end region for deletion\n * (prefer the line before; never the post-final-newline \"\" sentinel).\n */\nfunction reclaimBlankLine(\n logical: string[],\n beginIdx: number,\n endIdx: number,\n del: Set<number>,\n lineCount: number,\n): void {\n const before = beginIdx - 1;\n if (before >= 0 && !del.has(before) && logical[before]!.trim() === \"\") {\n del.add(before);\n return;\n }\n const after = endIdx + 1;\n // The final \"\" element of split(\"\\n\") on a newline-terminated file is the\n // trailing-newline sentinel, not a blank line — leave it alone.\n const isSentinel = after === lineCount - 1 && logical[after] === \"\";\n if (after < lineCount && !isSentinel && !del.has(after) && logical[after]!.trim() === \"\") {\n del.add(after);\n }\n}\n\nexport interface RemoveBlocksOptions {\n /** Remove the block with EXACTLY this id… */\n blockId?: string;\n /** …or every block whose id starts with this prefix (e.g. `<connectorId>/`). */\n blockIdPrefix?: string;\n}\n\nexport interface RemoveRecord {\n blockId: string;\n action: \"remove\" | \"warn\";\n detail: string;\n}\n\nexport interface RemoveBlocksResult {\n text: string;\n changed: boolean;\n records: RemoveRecord[];\n /** True when the remaining text is whitespace-only (file-deletion candidate). */\n fileNowEmpty: boolean;\n /** True when a drifted block was removed or stray markers were stripped. */\n recovered: boolean;\n}\n\n/**\n * Remove every matching managed block (begin..end inclusive + at most ONE\n * adjacent blank separator line — no blank-line accumulation across cycles).\n * Drifted blocks are removed WITH a warn (uninstall intent is explicit; the\n * file wrapper backs the file up first). Stray matching markers are stripped\n * line-only with a warn. Pure; no I/O.\n */\nexport function removeBlocksFromText(raw: string, match: RemoveBlocksOptions): RemoveBlocksResult {\n const bom = raw.startsWith(\"\\uFEFF\");\n const body = bom ? raw.slice(1) : raw;\n const lines = body.split(\"\\n\");\n const logical = lines.map(stripCr);\n\n const matches = (id: string): boolean =>\n (match.blockId !== undefined && id === match.blockId) ||\n (match.blockIdPrefix !== undefined && id.startsWith(match.blockIdPrefix));\n\n const { pairs, strays } = pairMarkers(scanMarkers(logical));\n const targetPairs = pairs.filter((p) => matches(p.blockId));\n const targetStrays = strays.filter((s) => matches(s.blockId));\n\n if (targetPairs.length === 0 && targetStrays.length === 0) {\n return { text: raw, changed: false, records: [], fileNowEmpty: false, recovered: false };\n }\n\n const del = new Set<number>();\n const records: RemoveRecord[] = [];\n let recovered = false;\n\n for (const p of targetPairs) {\n const recorded = p.begin.hash ?? \"\";\n const actualHash = hashBlockContent(\n logical.slice(p.begin.index + 1, p.end.index).join(\"\\n\"),\n );\n for (let i = p.begin.index; i <= p.end.index; i++) del.add(i);\n reclaimBlankLine(logical, p.begin.index, p.end.index, del, lines.length);\n if (actualHash !== recorded) {\n recovered = true;\n records.push({\n blockId: p.blockId,\n action: \"warn\",\n detail:\n `block ${p.blockId} had in-block edits (recorded hash ${recorded}, found ` +\n `${actualHash}); removed anyway (backup taken)`,\n });\n }\n records.push({ blockId: p.blockId, action: \"remove\", detail: `block ${p.blockId} removed` });\n }\n for (const s of targetStrays) {\n del.add(s.index);\n recovered = true;\n records.push({\n blockId: s.blockId,\n action: \"warn\",\n detail: `stray ${s.kind} marker for ${s.blockId} removed (marker line only)`,\n });\n }\n\n const text = lines.filter((_, i) => !del.has(i)).join(\"\\n\");\n return {\n text: bom ? `\\uFEFF${text}` : text,\n changed: true,\n records,\n fileNowEmpty: text.trim() === \"\",\n recovered,\n };\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// File-level wrappers (atomic write, backups, dry-run)\n// ─────────────────────────────────────────────────────────────────────────\n\nexport interface BlockFileChange {\n action: \"create\" | \"update\" | \"skip\" | \"warn\" | \"remove\";\n path: string;\n detail: string;\n /** True when the FILE did not exist and this upsert created it (ledger fact). */\n createdFile: boolean;\n /** Set when a pre-mutation backup was written (destructive/recovery paths only). */\n backupPath?: string;\n /** Hash of the rendered inner region (ledger / doctor). */\n hash: string;\n}\n\n/** Timestamped copy into backupsDir(); best-effort (null on failure). */\nfunction backupFile(path: string): string | null {\n try {\n ensureDir(backupsDir());\n const stamp = new Date().toISOString().replace(/[:.]/g, \"-\");\n const dest = join(backupsDir(), `memory-${stamp}-${basename(path)}`);\n copyFileSync(path, dest);\n return dest;\n } catch {\n return null;\n }\n}\n\n/**\n * Atomic write: temp file in the SAME directory + rename, preserving the\n * destination's mode. Shrinks (does not eliminate) the read-modify-write race\n * with hosts that append to memory files mid-session (Claude `#` quick-memory).\n */\nfunction atomicWriteFile(path: string, text: string): void {\n const dir = dirname(path);\n ensureDir(dir);\n const tmp = join(dir, `.${basename(path)}.ac-tmp-${process.pid}-${Date.now()}`);\n try {\n writeFileSync(tmp, text, \"utf8\");\n try {\n chmodSync(tmp, statSync(path).mode);\n } catch {\n /* destination absent — default mode is fine */\n }\n renameSync(tmp, path);\n } catch (err) {\n rmSync(tmp, { force: true });\n throw err;\n }\n}\n\n/**\n * Upsert one managed block into the file at `path` (created when absent).\n * Re-reads immediately before computing+writing; honors dryRun (the action is\n * computed and reported, nothing is written).\n */\nexport function upsertManagedBlockFile(\n path: string,\n opts: UpsertBlockOptions & { dryRun: boolean },\n): BlockFileChange {\n let raw: string | null = null;\n if (existsSync(path)) {\n try {\n raw = readFileSync(path, \"utf8\");\n } catch {\n return {\n action: \"warn\",\n path,\n detail: `cannot read ${path}; memory block ${opts.blockId} not written`,\n createdFile: false,\n hash: \"\",\n };\n }\n }\n\n if (raw === null) {\n const lines = renderBlockLines(opts);\n const hash = hashBlockContent(lines.slice(1, -1).join(\"\\n\"));\n if (!opts.dryRun) atomicWriteFile(path, `${lines.join(\"\\n\")}\\n`);\n return {\n action: \"create\",\n path,\n detail: `created ${basename(path)} with block ${opts.blockId} (hash ${hash})`,\n createdFile: true,\n hash,\n };\n }\n\n const res = upsertBlockInText(raw, opts);\n const change: BlockFileChange = {\n action: res.action,\n path,\n detail: res.detail,\n createdFile: false,\n hash: res.hash,\n };\n if (res.changed && !opts.dryRun) {\n if (res.recovered) {\n const backup = backupFile(path);\n if (backup) change.backupPath = backup;\n }\n atomicWriteFile(path, res.text);\n }\n return change;\n}\n\n/**\n * Remove every matching managed block from the file at `path`. Missing file or\n * no matching markers → a single idempotent \"skip\". When the remaining content\n * is whitespace-only AND `deleteFileIfCreated` is true (the ledger recorded\n * that agent-connector created this file), the file itself is deleted (Ruler\n * revert semantics: delete only what we created).\n */\nexport function removeManagedBlocksFile(\n path: string,\n match: RemoveBlocksOptions,\n opts: { dryRun: boolean; deleteFileIfCreated?: boolean },\n): BlockFileChange[] {\n if (!existsSync(path)) {\n return [\n {\n action: \"skip\",\n path,\n detail: `${basename(path)} absent; nothing to remove`,\n createdFile: false,\n hash: \"\",\n },\n ];\n }\n let raw: string;\n try {\n raw = readFileSync(path, \"utf8\");\n } catch {\n return [\n {\n action: \"warn\",\n path,\n detail: `cannot read ${path}; managed blocks left in place`,\n createdFile: false,\n hash: \"\",\n },\n ];\n }\n\n const res = removeBlocksFromText(raw, match);\n if (!res.changed) {\n return [\n {\n action: \"skip\",\n path,\n detail: `no agent-connector blocks matching ${match.blockId ?? match.blockIdPrefix ?? \"?\"} in ${basename(path)}`,\n createdFile: false,\n hash: \"\",\n },\n ];\n }\n\n const changes: BlockFileChange[] = [];\n let backupPath: string | undefined;\n if (!opts.dryRun) {\n if (res.recovered) backupPath = backupFile(path) ?? undefined;\n if (res.fileNowEmpty && opts.deleteFileIfCreated) {\n rmSync(path, { force: true });\n } else {\n atomicWriteFile(path, res.text);\n }\n }\n for (const r of res.records) {\n changes.push({\n action: r.action,\n path,\n detail: r.detail,\n createdFile: false,\n hash: \"\",\n ...(backupPath && r.action === \"warn\" ? { backupPath } : {}),\n });\n }\n if (res.fileNowEmpty && opts.deleteFileIfCreated) {\n changes.push({\n action: \"remove\",\n path,\n detail: `${basename(path)} deleted (agent-connector created it; only whitespace remained)`,\n createdFile: false,\n hash: \"\",\n });\n }\n return changes;\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Memory ownership ledger — connectorDir(id)/memory-state.json\n// ─────────────────────────────────────────────────────────────────────────\n\nexport interface MemoryLedgerTarget {\n platform: string;\n scope: string;\n path: string;\n blockId: string;\n /** True when agent-connector CREATED the file (grants deletion rights). */\n createdFile: boolean;\n /** Inner-region hash we last wrote (doctor drift detection). */\n hash: string;\n}\n\nexport interface MemoryLedger {\n version: 1;\n targets: MemoryLedgerTarget[];\n}\n\nexport function memoryLedgerPath(connectorId: string): string {\n return join(connectorDir(connectorId), \"memory-state.json\");\n}\n\nexport function loadMemoryLedger(connectorId: string): MemoryLedger {\n const p = memoryLedgerPath(connectorId);\n if (!existsSync(p)) return { version: 1, targets: [] };\n try {\n const parsed = JSON.parse(readFileSync(p, \"utf8\")) as MemoryLedger;\n if (parsed && Array.isArray(parsed.targets)) return { version: 1, targets: parsed.targets };\n } catch {\n /* corrupt → fresh ledger; the markers remain the source of truth */\n }\n return { version: 1, targets: [] };\n}\n\n/** Persist the ledger; an EMPTY ledger deletes the file (no orphan state). */\nexport function saveMemoryLedger(connectorId: string, ledger: MemoryLedger): void {\n const p = memoryLedgerPath(connectorId);\n assertNoSymlinkInPath(p);\n if (ledger.targets.length === 0) {\n rmSync(p, { force: true });\n return;\n }\n ensureDir(dirname(p));\n writeFileSync(p, `${JSON.stringify(ledger, null, 2)}\\n`, \"utf8\");\n}\n\n/** True when the connector has any recorded memory targets (uninstall guard). */\nexport function hasMemoryLedger(connectorId: string): boolean {\n return loadMemoryLedger(connectorId).targets.length > 0;\n}\n\n/**\n * Upsert one ledger row (keyed by platform+scope+path+blockId). The\n * `createdFile` fact is STICKY: once we created the file, deletion rights\n * survive later syncs that found it present.\n */\nexport function recordMemoryTarget(ledger: MemoryLedger, t: MemoryLedgerTarget): void {\n const i = ledger.targets.findIndex(\n (x) =>\n x.platform === t.platform &&\n x.scope === t.scope &&\n x.path === t.path &&\n x.blockId === t.blockId,\n );\n if (i >= 0) {\n ledger.targets[i] = { ...t, createdFile: ledger.targets[i]!.createdFile || t.createdFile };\n } else {\n ledger.targets.push(t);\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
import {
|
|
9
9
|
BaseAdapter,
|
|
10
10
|
renderSkillMd
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-MGTDQLJJ.js";
|
|
12
12
|
import {
|
|
13
13
|
buildHomeBinHookCommand,
|
|
14
14
|
buildUsageEventCommand,
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
isHomeBinHookCommand,
|
|
17
17
|
isHostNativeUsageEnabled,
|
|
18
18
|
isUsageEventCommand
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-4NHXLXSD.js";
|
|
20
20
|
|
|
21
21
|
// src/adapters/antigravity/index.ts
|
|
22
22
|
import { existsSync } from "fs";
|
|
@@ -96,6 +96,18 @@ var AntigravityAdapter = class extends BaseAdapter {
|
|
|
96
96
|
confidence: installed ? "high" : "low"
|
|
97
97
|
};
|
|
98
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* The lifecycle hook events this host actually writes; every other normalized
|
|
101
|
+
* event warn-skips at install time. Defaults to the IDE's
|
|
102
|
+
* {@link SUPPORTED_EVENTS}. Overridable by forks whose underlying binary
|
|
103
|
+
* recognizes a DIFFERENT event set (e.g. the `agy` CLI, which does NOT
|
|
104
|
+
* recognize SessionStart). Kept in lock-step with the per-event capability
|
|
105
|
+
* flags so the docs hooks-matrix and the fleet-wide never-silent-drop contract
|
|
106
|
+
* stay consistent.
|
|
107
|
+
*/
|
|
108
|
+
supportedHookEvents() {
|
|
109
|
+
return SUPPORTED_EVENTS;
|
|
110
|
+
}
|
|
99
111
|
// ── Native paths ─────────────────────────────────────────────────────────
|
|
100
112
|
getConfigDir(ctx) {
|
|
101
113
|
if (ctx.scope === "project") return join(ctx.projectDir, ".agents");
|
|
@@ -251,8 +263,9 @@ var AntigravityAdapter = class extends BaseAdapter {
|
|
|
251
263
|
const hooks = file.hooks ??= {};
|
|
252
264
|
const changes = [];
|
|
253
265
|
let mutated = false;
|
|
266
|
+
const supportedEvents = this.supportedHookEvents();
|
|
254
267
|
for (const event of connector.hookEvents) {
|
|
255
|
-
if (!
|
|
268
|
+
if (!supportedEvents.has(event)) {
|
|
256
269
|
changes.push({
|
|
257
270
|
platform: this.id,
|
|
258
271
|
action: "warn",
|
|
@@ -674,4 +687,4 @@ export {
|
|
|
674
687
|
adapter,
|
|
675
688
|
antigravity_default
|
|
676
689
|
};
|
|
677
|
-
//# sourceMappingURL=chunk-
|
|
690
|
+
//# sourceMappingURL=chunk-XC5SJ35F.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/adapters/antigravity/index.ts"],"sourcesContent":["/**\n * adapters/antigravity — Google Antigravity (IDE) platform adapter.\n *\n * Antigravity is a Gemini-family host that, as of the 2.0 line, exposes a real\n * lifecycle-hook system on top of MCP — so this adapter is `json-stdio` (not the\n * old `mcp-only` framing): the host pipes a JSON payload to a hook command on\n * stdin and reads a JSON control object back, the same paradigm as Claude Code /\n * Gemini CLI. It installs the MCP server, lifecycle hooks, slash-command\n * Workflows, and Agent Skills.\n *\n * CONFIRMED-BY-INSTALL (2026-06-03, docs/research/antigravity-paths-confirmed.md):\n * a real machine with Antigravity IDE + `agy` CLI v1.0.0 shows the canonical user\n * customization root is `~/.gemini/antigravity/` — `~/.gemini/antigravity/mcp_config.json`\n * EXISTS and `~/.gemini/config/mcp_config.json` does NOT. So the fresh-install\n * default user MCP path is `~/.gemini/antigravity/mcp_config.json` (candidate[0]);\n * the `config/` and `antigravity-cli/` paths remain probed fallbacks only (honored\n * when a pre-existing config is found there, never the fresh default).\n *\n * STILL MEDIUM-CONFIDENCE / PATH-PROBING: hooks.json and the global skills dir were\n * NOT present on the observed install, so those locations stay corroborated-but-not-\n * byte-verified. Every user-scope path is PROBED at runtime — prefer a candidate\n * that already exists on disk, else fall back to the canonical path — and the doctor\n * flags each probed path with \"verify for your Antigravity version.\" We NEVER\n * hard-code a single guessed path, and any unsupported event or surface warn-skips\n * (never throws) at install time.\n *\n * Native config formats:\n * - MCP config (JSONC; we WRITE plain JSON), root key \"mcpServers\". stdio is\n * `{ command, args, env }`; a remote server is `{ serverUrl, headers }`\n * (NOTE: the key is `serverUrl`, NOT `url` and NOT Gemini CLI's `httpUrl`).\n * user scope → prefer existing of:\n * ~/.gemini/antigravity/mcp_config.json (CONFIRMED canonical)\n * ~/.gemini/config/mcp_config.json (probed fallback)\n * ~/.gemini/antigravity-cli/mcp_config.json (probed fallback)\n * else default to candidate[0] (antigravity/).\n * project scope → <projectDir>/.agents/mcp_config.json\n * - Hooks: a SEPARATE hooks.json in the customization dir (NOT the mcp_config),\n * project → <projectDir>/.agents/hooks.json\n * user → <resolvedUserConfigDir>/hooks.json\n * Shape: { hooks: { <Event>: [ { matcher, hooks:[{ type:\"command\", command }] } ] } }.\n * Supported events: PreToolUse, PostToolUse, SessionStart, Stop. All other\n * normalized events warn-skip. I/O fields are camelCase (see parse/format).\n * - Commands = \"Workflows\": markdown `.md` (body = the prompt; an optional\n * leading description line). Project prefer existing <proj>/.agent/workflows\n * or <proj>/.agents/workflows (default .agent/workflows per launch docs);\n * user ~/.gemini/antigravity/global_workflows.\n * - Skills = Agent Skills (uniform SKILL.md). Project\n * <proj>/.agents/skills/<name>/SKILL.md; user PROBE\n * ~/.gemini/antigravity-cli/skills then ~/.gemini/skills (NEVER\n * ~/.gemini/antigravity/skills — reportedly broken). NOTE: the global skills\n * dir was NOT present on the confirmed install, so it stays medium-confidence\n * + doctor \"verify for your version.\"\n * - Subagents: declarative subagents exist only inside a plugin bundle, which\n * agent-connector does not emit; supportsSubagents is false and the\n * BaseAdapter skip/warn default applies.\n *\n * Env handling: Antigravity (Gemini family) documents no `${env:VAR}` token of\n * the framework's syntax, so env/header/url refs are resolved to literals at\n * install time via resolveEnvRefsDeep — the safe default matching the Gemini CLI\n * adapter.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nimport { BaseAdapter } from \"../base.js\";\nimport type { Adapter, HookReply, InstallContext, NormalizedEvent } from \"../spi.js\";\nimport type {\n ChangeRecord,\n CommandDef,\n DetectedPlatform,\n HealthCheck,\n HookEventName,\n HookParadigm,\n HookResponse,\n PlatformCapabilities,\n PlatformId,\n PostToolUseEvent,\n PreToolUseEvent,\n ServerDef,\n SessionStartEvent,\n StopEvent,\n Transport,\n} from \"../../core/types.js\";\nimport { resolveEnvRefsDeep } from \"../../core/interpolate.js\";\nimport {\n buildHomeBinHookCommand,\n buildWrappedStdio,\n buildUsageEventCommand,\n isHomeBinHookCommand,\n isHostNativeUsageEnabled,\n isUsageEventCommand,\n} from \"../../core/spawn.js\";\nimport { renderSkillMd } from \"../claude-code/render.js\";\nimport { normalizeSessionSource } from \"../claude-code/wire.js\";\n\nconst HOST: PlatformId = \"antigravity\";\nconst MCP_ROOT_KEY = \"mcpServers\";\n\n/**\n * Known user-scope MCP config candidates, in preference order. We pick the first\n * that already exists on disk; otherwise we default to candidate[0]\n * (~/.gemini/antigravity/mcp_config.json — CONFIRMED canonical on a real install:\n * docs/research/antigravity-paths-confirmed.md). The `config/` and CLI-only\n * `antigravity-cli/` paths are kept ONLY as probed fallbacks so a pre-existing\n * config in either is still honored, but neither is ever the fresh-install default.\n */\nconst USER_CONFIG_CANDIDATES = [\n [\".gemini\", \"antigravity\", \"mcp_config.json\"],\n [\".gemini\", \"config\", \"mcp_config.json\"],\n [\".gemini\", \"antigravity-cli\", \"mcp_config.json\"],\n] as const;\n\n/**\n * Antigravity's supported lifecycle hook events. These happen to share the\n * normalized PascalCase names 1:1; everything else has no Antigravity equivalent\n * and is reported as a warn/skip at install time.\n */\nconst SUPPORTED_EVENTS: ReadonlySet<HookEventName> = new Set<HookEventName>([\n \"PreToolUse\",\n \"PostToolUse\",\n \"SessionStart\",\n \"Stop\",\n]);\n\n/**\n * Native hooks.json key for the OPT-IN host-native turn-usage hook (enricher 4a).\n * Antigravity shares the Gemini-family `AfterModel` model-turn hook, whose payload\n * carries `usageMetadata`. This is a host-native-only sink (no connector handler);\n * it is installed ONLY when host-native capture is enabled and records a DISTINCT\n * `model_turn` telemetry row that is never summed with the per-MCP `serve` rows.\n */\nconst USAGE_HOOK_EVENT = \"AfterModel\";\n\n/** A single Antigravity native hook registration entry (nested, Claude-shaped). */\ninterface AntigravityHookEntry {\n matcher: string;\n hooks: Array<{ type: \"command\"; command: string }>;\n}\n\n/** The shape of Antigravity's hooks.json (only the parts we touch). */\ninterface AntigravityHooksFile {\n hooks?: Record<string, AntigravityHookEntry[]>;\n [key: string]: unknown;\n}\n\n/**\n * Native MCP server entry shapes Antigravity accepts under `mcpServers`.\n * A stdio server is `{ command, args, env }`; a remote server is\n * `{ serverUrl, headers }` — the key is `serverUrl` (NOT `url`).\n */\ninterface AntigravityStdioServer {\n command: string;\n args?: string[];\n env?: Record<string, string>;\n}\ninterface AntigravityHttpServer {\n serverUrl: string;\n headers?: Record<string, string>;\n}\n\n/**\n * Raw Antigravity hook stdin payload (camelCase wire fields).\n *\n * SOURCE-VERIFIED against Google's official Antigravity hooks docs\n * (antigravity.google/docs/hooks) and corroborated by production integrations\n * (Cisco defenseclaw, camjac251/tool-gates, ntd4996/agentpet): Antigravity does\n * NOT use the flat Claude-Code shape. It carries no `hook_event_name`; the tool\n * descriptor is NESTED under `toolCall` (`toolCall.name` / `toolCall.args`); the\n * stable session id is `conversationId`; and the workspace roots are a string\n * array `workspacePaths` (first entry is the project dir). PostToolUse sends NO\n * tool fields — only `stepIdx`, an `error` string (empty/absent on success), and\n * the common fields.\n */\ninterface AntigravityToolCall {\n name?: string;\n args?: Record<string, unknown>;\n}\ninterface AntigravityWireInput {\n connector?: unknown;\n /** PreToolUse: nested tool descriptor (`toolCall.name`, `toolCall.args`). */\n toolCall?: AntigravityToolCall;\n toolOutput?: string;\n /** PostToolUse: runtime error message — empty/absent on success. */\n error?: string;\n /** Stable session id (the active agent conversation UUID). */\n conversationId?: string;\n /** Mounted workspace roots; the first entry is the project dir. */\n workspacePaths?: string[];\n source?: string;\n reason?: string;\n stopHookActive?: boolean;\n}\n\nexport class AntigravityAdapter extends BaseAdapter implements Adapter {\n readonly id: PlatformId = HOST;\n readonly name: string = \"Google Antigravity\";\n readonly paradigm: HookParadigm = \"json-stdio\";\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 // Antigravity 2.0 fires PreToolUse / PostToolUse / SessionStart / Stop.\n preToolUse: true,\n postToolUse: true,\n sessionStart: true,\n stop: true,\n // No documented equivalents — kept false; the corresponding normalized\n // events warn-skip at install time.\n preCompact: false,\n sessionEnd: false,\n userPromptSubmit: false,\n notification: false,\n // Newer events: no documented permission-dialog, tool-failure, or subagent\n // lifecycle hooks on Antigravity (IDE or `agy` CLI — the CLI adapter\n // inherits this surface), so permissionRequest / postToolUseFailure /\n // subagentStart / subagentStop stay unset — install reports the standard\n // skip-warn for them.\n // Transform-category hooks can rewrite tool input and tool output; the\n // SessionStart hook can inject additional context.\n canModifyArgs: true,\n canModifyOutput: true,\n canInjectSessionContext: true,\n // Antigravity registers stdio, SSE, and Streamable HTTP MCP servers.\n transports: [\"stdio\", \"sse\", \"http\"],\n // Content surfaces: Workflows (markdown commands) + Agent Skills (SKILL.md).\n // Declarative subagents exist only inside a plugin bundle (not emitted), so\n // subagents are unsupported and inherit the BaseAdapter skip/warn default.\n supportsCommands: true,\n supportsSkills: true,\n supportsSubagents: false,\n };\n\n // ── Detection ────────────────────────────────────────────────────────────\n\n detectInstalled(projectDir: string): DetectedPlatform {\n const userConfig = this.resolveUserConfigPath();\n const userDir = join(homedir(), \".gemini\");\n const projectConfig = join(projectDir, \".agents\", \"mcp_config.json\");\n\n const userInstalled =\n existsSync(userDir) ||\n this.userConfigCandidates().some((parts) => existsSync(join(homedir(), ...parts)));\n const projInstalled = existsSync(projectConfig);\n const installed = userInstalled || projInstalled;\n\n // Report the scope/path that actually matched, so a project-only install\n // isn't misreported as a (non-existent) user install.\n const scope = projInstalled && !userInstalled ? \"project\" : \"user\";\n const configPath = scope === \"project\" ? projectConfig : userConfig;\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 ? scope === \"project\"\n ? `found project Antigravity config at ${projectConfig}`\n : `found Antigravity config under ${userDir}`\n : `no Antigravity config at ${userDir} or ${projectConfig}`,\n confidence: installed ? \"high\" : \"low\",\n };\n }\n\n /**\n * The lifecycle hook events this host actually writes; every other normalized\n * event warn-skips at install time. Defaults to the IDE's\n * {@link SUPPORTED_EVENTS}. Overridable by forks whose underlying binary\n * recognizes a DIFFERENT event set (e.g. the `agy` CLI, which does NOT\n * recognize SessionStart). Kept in lock-step with the per-event capability\n * flags so the docs hooks-matrix and the fleet-wide never-silent-drop contract\n * stay consistent.\n */\n protected supportedHookEvents(): ReadonlySet<HookEventName> {\n return SUPPORTED_EVENTS;\n }\n\n // ── Native paths ─────────────────────────────────────────────────────────\n\n getConfigDir(ctx: InstallContext): string {\n if (ctx.scope === \"project\") return join(ctx.projectDir, \".agents\");\n // User scope: parent dir of the resolved user mcp_config.json.\n return dirname(this.resolveUserConfigPath());\n }\n\n getServerConfigPath(ctx: InstallContext): string {\n return ctx.scope === \"project\"\n ? join(ctx.projectDir, \".agents\", \"mcp_config.json\")\n : this.resolveUserConfigPath();\n }\n\n /**\n * Hooks live in a SEPARATE hooks.json in the customization dir — NOT the\n * mcp_config.json. Project → <proj>/.agents/hooks.json; user →\n * <resolvedUserConfigDir>/hooks.json (the dir holding the resolved user MCP\n * config). Path is medium-confidence and surfaced by the doctor.\n */\n getHookConfigPath(ctx: InstallContext): string {\n return join(this.getConfigDir(ctx), \"hooks.json\");\n }\n\n /**\n * The user-scope MCP config candidates, in preference order. Overridable by\n * forks (e.g. the Antigravity CLI) that resolve a different user-scope root\n * while reusing resolveUserConfigPath's prefer-existing-else-candidate[0] logic.\n */\n protected userConfigCandidates(): ReadonlyArray<readonly string[]> {\n return USER_CONFIG_CANDIDATES;\n }\n\n /**\n * Pick the user-scope mcp_config.json: prefer a candidate that already exists,\n * else default to candidate[0] (the CONFIRMED canonical ~/.gemini/antigravity path).\n */\n protected resolveUserConfigPath(): string {\n const home = homedir();\n const candidates = this.userConfigCandidates();\n for (const parts of candidates) {\n const p = join(home, ...parts);\n if (existsSync(p)) return p;\n }\n const fallback = candidates[0];\n if (fallback === undefined) {\n // Defensive: a non-empty candidate list is an invariant, but never throw.\n return join(home, \".gemini\", \"antigravity\", \"mcp_config.json\");\n }\n return join(home, ...fallback);\n }\n\n /**\n * Resolve the Workflows (slash-command) dir, prefer-existing-else-canonical.\n * project → prefer existing <proj>/.agent/workflows or <proj>/.agents/workflows;\n * default .agent/workflows (launch-era singular `.agent`).\n * user → ~/.gemini/antigravity/global_workflows.\n */\n protected resolveWorkflowsDir(ctx: InstallContext): string {\n if (ctx.scope === \"project\") {\n const singular = join(ctx.projectDir, \".agent\", \"workflows\");\n const plural = join(ctx.projectDir, \".agents\", \"workflows\");\n if (existsSync(singular)) return singular;\n if (existsSync(plural)) return plural;\n return singular;\n }\n return join(homedir(), \".gemini\", \"antigravity\", \"global_workflows\");\n }\n\n /**\n * Resolve the Agent Skills dir, prefer-existing-else-canonical.\n * project → <proj>/.agents/skills (plural — matches mcp/skills convention).\n * user → prefer existing ~/.gemini/antigravity-cli/skills, else\n * ~/.gemini/skills. NEVER ~/.gemini/antigravity/skills\n * (reportedly broken), so it is not a candidate.\n */\n protected resolveSkillsDir(ctx: InstallContext): string {\n if (ctx.scope === \"project\") {\n return join(ctx.projectDir, \".agents\", \"skills\");\n }\n const home = homedir();\n const cliSkills = join(home, \".gemini\", \"antigravity-cli\", \"skills\");\n const sharedSkills = join(home, \".gemini\", \"skills\");\n if (existsSync(cliSkills)) return cliSkills;\n if (existsSync(sharedSkills)) return sharedSkills;\n return cliSkills;\n }\n\n // ── MCP server install / uninstall ───────────────────────────────────────\n\n installServer(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n const override = connector.platforms[this.id]?.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 ${this.id}`\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 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 Antigravity's native mcpServers entry. */\n private renderServerEntry(\n ctx: InstallContext,\n server: ServerDef,\n ): AntigravityStdioServer | AntigravityHttpServer {\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> --scope <scope> -- <command> <args...>`.\n ({ command, args } = buildWrappedStdio(ctx, server, this.id, command, args));\n\n // Antigravity (Gemini family) has no documented native interpolation token,\n // so resolve every ${env:VAR} to a literal at install time.\n const entry: AntigravityStdioServer = { command: resolveEnvRefsDeep(command) };\n if (args.length > 0) entry.args = resolveEnvRefsDeep(args);\n const env = this.renderEnv(server.env);\n if (env) entry.env = env;\n return entry;\n }\n\n // sse / http (and any other remote transport) — Antigravity registers a URL\n // under the `serverUrl` key (NOT `url`).\n const entry: AntigravityHttpServer = { serverUrl: resolveEnvRefsDeep(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. Antigravity documents no native interpolation\n * token, so resolve `${env:VAR}` references to literals at install time.\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 return resolveEnvRefsDeep({ ...env });\n }\n\n // ── Hook install / uninstall ─────────────────────────────────────────────\n\n installHooks(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.platforms[this.id]?.hooks === false) {\n return [{ platform: this.id, action: \"skip\", detail: `hooks disabled for ${this.id}` }];\n }\n // The opt-in host-native usage hook (4a) needs no connector handler, so it may\n // be installed even when the connector declares no normalized hook events.\n const hostNative = isHostNativeUsageEnabled(connector.telemetry);\n if (connector.hookEvents.length === 0 && !hostNative) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no hooks\" }];\n }\n\n const hooksPath = this.getHookConfigPath(ctx);\n // OVERWRITE GUARD: never clobber a present-but-unparseable hooks.json.\n if (this.isPresentButUnparseable(hooksPath)) {\n return [\n {\n platform: this.id,\n action: \"warn\",\n path: hooksPath,\n detail: `existing ${hooksPath} is not parseable; left untouched (back it up / fix it, then re-run)`,\n },\n ];\n }\n\n const file = this.readJson<AntigravityHooksFile>(hooksPath) ?? {};\n const __skip = this.malformedHookRootSkip(hooksPath, (file as Record<string, unknown>).hooks);\n if (__skip) return [__skip];\n const hooks = (file.hooks ??= {});\n\n const changes: ChangeRecord[] = [];\n let mutated = false;\n\n const supportedEvents = this.supportedHookEvents();\n for (const event of connector.hookEvents) {\n if (!supportedEvents.has(event)) {\n // No Antigravity equivalent for this normalized event — report.\n changes.push({\n platform: this.id,\n action: \"warn\",\n path: hooksPath,\n detail: `${event} has no Antigravity hook equivalent — skipped`,\n });\n continue;\n }\n\n const command = buildHomeBinHookCommand(ctx.homeBinPath, this.id, event, connector.id);\n const matcher = connector.hooks[event]?.matcher ?? \"\";\n const entry: AntigravityHookEntry = {\n matcher,\n hooks: [{ type: \"command\", command }],\n };\n\n const bucket = (hooks[event] ??= []);\n const existingIdx = bucket.findIndex((e) => this.entryHasOurCommand(e, ctx));\n\n if (existingIdx >= 0) {\n if (JSON.stringify(bucket[existingIdx]) === JSON.stringify(entry)) {\n changes.push({\n platform: this.id,\n action: \"skip\",\n path: hooksPath,\n detail: `hooks.${event} already registered`,\n });\n continue;\n }\n bucket[existingIdx] = entry;\n changes.push({\n platform: this.id,\n action: \"update\",\n path: hooksPath,\n detail: `hooks.${event}`,\n });\n } else {\n bucket.push(entry);\n changes.push({\n platform: this.id,\n action: \"create\",\n path: hooksPath,\n detail: `hooks.${event}`,\n });\n }\n mutated = true;\n }\n\n // OPT-IN host-native usage hook (4a): register the AfterModel `usage-event`\n // sink when enabled. Records a DISTINCT `model_turn` row (whole-conversation),\n // never summed with the per-MCP `serve`-proxy rows.\n if (hostNative) {\n if (this.installUsageHook(hooks, ctx, hooksPath, changes)) mutated = true;\n }\n\n if (mutated) this.writeJson(hooksPath, file, ctx.dryRun);\n return changes;\n }\n\n /**\n * Register the opt-in AfterModel host-native usage hook (4a) into `hooks`.\n * Idempotent (byte-identical → skip, drift → update); returns true on mutation.\n * The command is the hidden `usage-event` entrypoint (NOT a connector hook), so\n * it carries an empty matcher. Reads `this.id` so the CLI fork installs its own\n * `usage-event antigravity-cli …` variant.\n */\n private installUsageHook(\n hooks: Record<string, AntigravityHookEntry[]>,\n ctx: InstallContext,\n hooksPath: string,\n changes: ChangeRecord[],\n ): boolean {\n const command = buildUsageEventCommand(ctx.homeBinPath, this.id, ctx.connector.id);\n const entry: AntigravityHookEntry = {\n matcher: \"\",\n hooks: [{ type: \"command\", command }],\n };\n const bucket = (hooks[USAGE_HOOK_EVENT] ??= []);\n const existingIdx = bucket.findIndex((e) =>\n (e.hooks ?? []).some((h) => isUsageEventCommand(h.command, ctx.homeBinPath, ctx.connector.id)),\n );\n\n if (existingIdx >= 0) {\n if (JSON.stringify(bucket[existingIdx]) === JSON.stringify(entry)) {\n changes.push({\n platform: this.id,\n action: \"skip\",\n path: hooksPath,\n detail: `hooks.${USAGE_HOOK_EVENT} (host-native usage) already registered`,\n });\n return false;\n }\n bucket[existingIdx] = entry;\n changes.push({\n platform: this.id,\n action: \"update\",\n path: hooksPath,\n detail: `hooks.${USAGE_HOOK_EVENT} (host-native usage)`,\n });\n } else {\n bucket.push(entry);\n changes.push({\n platform: this.id,\n action: \"create\",\n path: hooksPath,\n detail: `hooks.${USAGE_HOOK_EVENT} (host-native usage)`,\n });\n }\n return true;\n }\n\n uninstallHooks(ctx: InstallContext): ChangeRecord[] {\n const hooksPath = this.getHookConfigPath(ctx);\n const file = this.readJson<AntigravityHooksFile>(hooksPath);\n const hooks = file?.hooks;\n if (!file || !hooks) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n path: hooksPath,\n detail: \"no hooks section present\",\n },\n ];\n }\n\n const changes: ChangeRecord[] = [];\n let mutated = false;\n\n for (const event of Object.keys(hooks)) {\n const bucket = hooks[event];\n if (!Array.isArray(bucket)) continue;\n\n // Strip our hook command from each entry; drop entries left empty so we\n // never remove another connector's (or the user's own) hook commands.\n const next: AntigravityHookEntry[] = [];\n let removed = 0;\n for (const e of bucket) {\n const innerBefore = e.hooks?.length ?? 0;\n const inner = (e.hooks ?? []).filter((h) => !this.isOurCommand(h.command, ctx));\n removed += innerBefore - inner.length;\n if (inner.length > 0) next.push({ matcher: e.matcher ?? \"\", hooks: inner });\n }\n\n if (removed > 0) {\n if (next.length > 0) hooks[event] = next;\n else delete hooks[event];\n changes.push({\n platform: this.id,\n action: \"remove\",\n path: hooksPath,\n detail: `hooks.${event} (${removed})`,\n });\n mutated = true;\n }\n }\n\n if (mutated) this.writeJson(hooksPath, file, ctx.dryRun);\n if (changes.length === 0) {\n changes.push({\n platform: this.id,\n action: \"skip\",\n path: hooksPath,\n detail: \"no matching hook entries\",\n });\n }\n return changes;\n }\n\n private entryHasOurCommand(entry: AntigravityHookEntry, ctx: InstallContext): boolean {\n return (entry.hooks ?? []).some((h) => this.isOurCommand(h.command, ctx));\n }\n\n /**\n * True when a hook command is ONE OF OURS for this connector — the universal\n * `hook` dispatcher OR the opt-in `usage-event` sink. Both are anchored on the\n * connector id (see isHomeBinHookCommand) so a shared-prefix id can't collide,\n * and so uninstall reverses the AfterModel usage hook too.\n */\n private isOurCommand(command: string | undefined, ctx: InstallContext): boolean {\n return (\n isHomeBinHookCommand(command, ctx.homeBinPath, ctx.connector.id) ||\n isUsageEventCommand(command, ctx.homeBinPath, ctx.connector.id)\n );\n }\n\n // ── Content surfaces: commands (Workflows) / skills ───────────────────────\n // CONTENT-ONLY: pure native-file writers under the probed workflows / skills\n // dirs. No runtime dispatch, no home-bin pointer, no telemetry wrap. Each\n // method is idempotent (byte-identical → skip) via BaseAdapter.writeContentFile\n // and reversible via removeContentFile. Honors platforms[\"antigravity\"]\n // per-surface false to skip. Commands are markdown Workflows (NOT TOML, unlike\n // gemini-cli); skills are the uniform Claude-compatible SKILL.md. Subagents are\n // unsupported (plugin-bundle-only) and inherit the BaseAdapter skip/warn.\n\n /** Native Workflow file path: <workflowsDir>/<name>.md. */\n private commandPath(ctx: InstallContext, name: string): string {\n return join(this.resolveWorkflowsDir(ctx), `${name}.md`);\n }\n /** Native skill dir: <skillsDir>/<name>. */\n private skillDir(ctx: InstallContext, name: string): string {\n return join(this.resolveSkillsDir(ctx), name);\n }\n\n // ── Commands (Workflows) ──────────────────────────────────────────────────\n\n override installCommands(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.platforms[this.id]?.commands === false) {\n return [{ platform: this.id, action: \"skip\", detail: `commands disabled for ${this.id}` }];\n }\n if (connector.commands.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no commands\" }];\n }\n return connector.commands.map((cmd) =>\n this.writeContentFile(this.commandPath(ctx, cmd.name), this.renderCommand(cmd), ctx.dryRun),\n );\n }\n\n override uninstallCommands(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.commands.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no commands\" }];\n }\n return connector.commands.map((cmd) =>\n this.removeContentFile(this.commandPath(ctx, cmd.name), ctx.dryRun),\n );\n }\n\n /**\n * Render a command to an Antigravity Workflow: a plain markdown `.md` whose\n * body is the command prompt, optionally preceded by a leading description\n * line. No frontmatter / TOML (unlike gemini-cli).\n */\n private renderCommand(cmd: CommandDef): string {\n const body = cmd.prompt.endsWith(\"\\n\") ? cmd.prompt : `${cmd.prompt}\\n`;\n if (cmd.description !== undefined && cmd.description !== \"\") {\n return `${cmd.description}\\n\\n${body}`;\n }\n return body;\n }\n\n // ── Skills ────────────────────────────────────────────────────────────────\n\n override installSkills(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.platforms[this.id]?.skills === false) {\n return [{ platform: this.id, action: \"skip\", detail: `skills disabled for ${this.id}` }];\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\"), renderSkillMd(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 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 // ── Diagnostics ──────────────────────────────────────────────────────────\n\n override getHealthChecks(ctx: InstallContext): readonly HealthCheck[] {\n const mcpPath = this.getServerConfigPath(ctx);\n const hooksPath = this.getHookConfigPath(ctx);\n const connectorId = ctx.connector.id;\n const homeBin = ctx.homeBinPath;\n const hookEvents = ctx.connector.hookEvents;\n const workflowsDir = this.resolveWorkflowsDir(ctx);\n const skillsDir = this.resolveSkillsDir(ctx);\n\n const checks: HealthCheck[] = [\n {\n name: `${this.name}: mcp_config.json present`,\n check: () =>\n existsSync(mcpPath)\n ? { status: \"OK\", detail: `${mcpPath} (path probed; verify for your Antigravity version)` }\n : { status: \"FAIL\", detail: `not found: ${mcpPath} (path probed; verify for your Antigravity version)` },\n },\n {\n name: `${this.name}: server entry registered`,\n check: () => {\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> }>(mcpPath);\n const bucket = cfg?.[MCP_ROOT_KEY];\n if (!cfg || !bucket) {\n return { status: \"FAIL\", detail: `no ${MCP_ROOT_KEY} in ${mcpPath}` };\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 ${mcpPath}`,\n };\n },\n },\n {\n name: `${this.name}: hooks.json hook command registered`,\n check: () => {\n if (hookEvents.length === 0) {\n return { status: \"OK\", detail: \"no hooks declared\" };\n }\n const file = this.readJson<AntigravityHooksFile>(hooksPath);\n if (!file) {\n return {\n status: \"FAIL\",\n detail: `not found: ${hooksPath} (path probed; verify for your Antigravity version)`,\n };\n }\n const hooks = file.hooks ?? {};\n const registered = Object.values(hooks).some((entries) =>\n (entries ?? []).some((e) =>\n (e.hooks ?? []).some((h) =>\n isHomeBinHookCommand(h.command, homeBin, connectorId),\n ),\n ),\n );\n return registered\n ? { status: \"OK\", detail: `hook command present in ${hooksPath}` }\n : { status: \"FAIL\", detail: `no hook for ${connectorId} in ${hooksPath}` };\n },\n },\n ];\n\n // Content-surface checks: only assert presence of the files this connector\n // declares (skip silently for surfaces it never asked for). The probed dirs\n // are noted so doctor output makes the medium-confidence path explicit.\n for (const cmd of ctx.connector.commands) {\n const p = join(workflowsDir, `${cmd.name}.md`);\n checks.push({\n name: `${this.name}: workflow ${cmd.name} present`,\n check: () =>\n existsSync(p)\n ? { status: \"OK\", detail: `${p} (workflows dir probed; verify for your version)` }\n : { status: \"FAIL\", detail: `not found: ${p} (workflows dir probed; verify for your version)` },\n });\n }\n for (const skill of ctx.connector.skills) {\n const p = join(skillsDir, skill.name, \"SKILL.md\");\n checks.push({\n name: `${this.name}: skill ${skill.name} present`,\n check: () =>\n existsSync(p)\n ? { status: \"OK\", detail: `${p} (skills dir probed; verify for your version)` }\n : { status: \"FAIL\", detail: `not found: ${p} (skills dir probed; verify for your version)` },\n });\n }\n return checks;\n }\n\n // ── Runtime: parse Antigravity stdin JSON → normalized event ──────────────\n\n parseEvent(event: HookEventName, raw: unknown): NormalizedEvent {\n const input = (raw ?? {}) as AntigravityWireInput;\n const connectorId = typeof input.connector === \"string\" ? input.connector : \"\";\n // Stable session id is `conversationId` (NOT a flat `sessionId`).\n const sessionId = typeof input.conversationId === \"string\" ? input.conversationId : \"\";\n // Project dir is the first mounted workspace root (`workspacePaths[0]`), a\n // string array — NOT a flat `cwd` string.\n const projectDir =\n Array.isArray(input.workspacePaths) && typeof input.workspacePaths[0] === \"string\"\n ? input.workspacePaths[0]\n : undefined;\n\n const base = {\n hostPlatform: this.id,\n connectorId,\n sessionId,\n raw,\n ...(projectDir !== undefined ? { projectDir } : {}),\n } as const;\n\n switch (event) {\n case \"PreToolUse\": {\n // Tool descriptor is nested under `toolCall` (`.name` / `.args`).\n const ev: PreToolUseEvent = {\n ...base,\n toolName: input.toolCall?.name ?? \"\",\n toolInput: input.toolCall?.args ?? {},\n };\n return ev;\n }\n case \"PostToolUse\": {\n // Antigravity's PostToolUse carries no tool fields — only `stepIdx`,\n // an `error` string, and the common fields. Derive isError from a\n // non-empty error string and surface it as the failure output.\n const error = typeof input.error === \"string\" ? input.error : \"\";\n const ev: PostToolUseEvent = {\n ...base,\n toolName: \"\",\n toolInput: {},\n ...(error.length > 0\n ? { isError: true, toolOutput: error }\n : input.toolOutput !== undefined\n ? { toolOutput: input.toolOutput }\n : {}),\n };\n return ev;\n }\n case \"SessionStart\": {\n const ev: SessionStartEvent = {\n ...base,\n source: normalizeSessionSource(input.source),\n };\n return ev;\n }\n case \"Stop\": {\n const ev: StopEvent = {\n ...base,\n ...(typeof input.stopHookActive === \"boolean\"\n ? { stopHookActive: input.stopHookActive }\n : {}),\n };\n return ev;\n }\n default: {\n // Antigravity only delivers the four SUPPORTED_EVENTS. If the runtime\n // dispatches anything else, surface it loudly rather than mis-parse.\n throw new Error(`unsupported ${this.id} hook event: ${String(event)}`);\n }\n }\n }\n\n // ── Runtime: normalized response → Antigravity native hook reply ──────────\n\n formatReply(event: HookEventName, response: HookResponse): HookReply {\n const decision = response.decision ?? \"allow\";\n\n // deny → Antigravity blocks the action via a top-level `decision:\"deny\"` +\n // reason (the Decide category).\n if (decision === \"deny\") {\n return this.stdout({\n decision: \"deny\",\n reason: response.reason ?? \"Blocked by hook\",\n });\n }\n\n // ask → Antigravity has no native \"ask\"; degrade to deny to stay fail-safe.\n if (decision === \"ask\") {\n return this.stdout({\n decision: \"deny\",\n reason: response.reason ?? \"Action requires user confirmation (security policy)\",\n });\n }\n\n // modify → Transform category. camelCase: rewrite PreToolUse input via\n // updatedInput; rewrite PostToolUse output via updatedOutput.\n if (decision === \"modify\") {\n if (event === \"PreToolUse\" && response.updatedInput) {\n return this.stdout({ updatedInput: response.updatedInput });\n }\n if (event === \"PostToolUse\" && response.updatedOutput !== undefined) {\n return this.stdout({ updatedOutput: response.updatedOutput });\n }\n // Nothing to apply; fall through to allow.\n }\n\n // context → inject soft guidance via additionalContext (the SessionStart\n // context-injection path).\n if (decision === \"context\" && response.additionalContext) {\n return this.stdout({ additionalContext: response.additionalContext });\n }\n\n // allow / void / unsupported-degradation → pass through with exit 0.\n return { exitCode: 0 };\n }\n\n private stdout(payload: unknown): HookReply {\n return { exitCode: 0, stdout: JSON.stringify(payload) };\n }\n}\n\nexport const adapter = new AntigravityAdapter();\nexport default adapter;\n"],"mappings":"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","names":["entry"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
resolveSpawnCommand
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-4NHXLXSD.js";
|
|
5
5
|
|
|
6
6
|
// src/core/spawn-child.ts
|
|
7
7
|
import { spawn } from "child_process";
|
|
@@ -18,4 +18,4 @@ function spawnChild(command, args, options) {
|
|
|
18
18
|
export {
|
|
19
19
|
spawnChild
|
|
20
20
|
};
|
|
21
|
-
//# sourceMappingURL=chunk-
|
|
21
|
+
//# sourceMappingURL=chunk-Z2MRSS2I.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
ADAPTER_REGISTRY
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-SILKSP2Y.js";
|
|
5
5
|
|
|
6
6
|
// src/adapters/detect.ts
|
|
7
7
|
async function detectInstalledPlatforms(projectDir) {
|
|
@@ -85,4 +85,4 @@ export {
|
|
|
85
85
|
detectInstalledPlatforms,
|
|
86
86
|
detectRuntimeHost
|
|
87
87
|
};
|
|
88
|
-
//# sourceMappingURL=chunk-
|
|
88
|
+
//# sourceMappingURL=chunk-ZMAJ2XFD.js.map
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
readRegisteredMeta
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
6
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-KSPMSRVU.js";
|
|
5
|
+
import "./chunk-KJLFGQQM.js";
|
|
6
|
+
import "./chunk-SILKSP2Y.js";
|
|
7
7
|
import {
|
|
8
8
|
addLedgerOwner,
|
|
9
9
|
configPatchManualEdit,
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
loadConfigPatchLedger,
|
|
20
20
|
removeLedgerOwner,
|
|
21
21
|
saveConfigPatchLedger
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-NBYKLUF6.js";
|
|
23
23
|
import {
|
|
24
24
|
extractSessionId,
|
|
25
25
|
normalizeSessionSource,
|
|
@@ -34,13 +34,13 @@ import {
|
|
|
34
34
|
renderCommandMd,
|
|
35
35
|
renderSkillMd,
|
|
36
36
|
renderSubagentMd
|
|
37
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-MGTDQLJJ.js";
|
|
38
38
|
import {
|
|
39
39
|
buildHomeBinStatuslineCommand,
|
|
40
40
|
buildWrappedStdio,
|
|
41
41
|
isHomeBinHookCommand,
|
|
42
42
|
isHomeBinStatuslineCommand
|
|
43
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-4NHXLXSD.js";
|
|
44
44
|
import {
|
|
45
45
|
linesOutsideFences,
|
|
46
46
|
listManagedBlocks,
|
|
@@ -50,11 +50,11 @@ import {
|
|
|
50
50
|
removeManagedBlocksFile,
|
|
51
51
|
saveMemoryLedger,
|
|
52
52
|
upsertManagedBlockFile
|
|
53
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-UMQ6NBQR.js";
|
|
54
54
|
import {
|
|
55
55
|
backupsDir,
|
|
56
56
|
ensureDir
|
|
57
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-GZGLCCEE.js";
|
|
58
58
|
|
|
59
59
|
// src/adapters/claude-code/index.ts
|
|
60
60
|
import { copyFileSync, existsSync, lstatSync, readFileSync, realpathSync } from "fs";
|
|
@@ -1493,4 +1493,4 @@ export {
|
|
|
1493
1493
|
claudeSensitiveKeyViolation,
|
|
1494
1494
|
claude_code_default as default
|
|
1495
1495
|
};
|
|
1496
|
-
//# sourceMappingURL=claude-code-
|
|
1496
|
+
//# sourceMappingURL=claude-code-DUZNOAS2.js.map
|
package/dist/cli/sdk.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
main
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-OEADFFKO.js";
|
|
5
5
|
import {
|
|
6
6
|
loadConnectorFromPath
|
|
7
|
-
} from "../chunk-
|
|
8
|
-
import "../chunk-
|
|
9
|
-
import "../chunk-
|
|
10
|
-
import "../chunk-
|
|
11
|
-
import "../chunk-
|
|
12
|
-
import "../chunk-
|
|
7
|
+
} from "../chunk-KSPMSRVU.js";
|
|
8
|
+
import "../chunk-KJLFGQQM.js";
|
|
9
|
+
import "../chunk-SILKSP2Y.js";
|
|
10
|
+
import "../chunk-NBYKLUF6.js";
|
|
11
|
+
import "../chunk-UMQ6NBQR.js";
|
|
12
|
+
import "../chunk-GZGLCCEE.js";
|
|
13
13
|
|
|
14
14
|
// src/cli/sdk.ts
|
|
15
15
|
var CONFIG_PATH_COMMANDS = /* @__PURE__ */ new Set([
|
package/dist/cli.js
CHANGED
|
@@ -6,12 +6,12 @@ import {
|
|
|
6
6
|
BaseAdapter,
|
|
7
7
|
renderCommandMd,
|
|
8
8
|
renderSkillMd
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-MGTDQLJJ.js";
|
|
10
10
|
import {
|
|
11
11
|
buildWrappedStdio
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-
|
|
12
|
+
} from "./chunk-4NHXLXSD.js";
|
|
13
|
+
import "./chunk-UMQ6NBQR.js";
|
|
14
|
+
import "./chunk-GZGLCCEE.js";
|
|
15
15
|
|
|
16
16
|
// src/adapters/cline/index.ts
|
|
17
17
|
import { existsSync, statSync } from "fs";
|
|
@@ -405,4 +405,4 @@ export {
|
|
|
405
405
|
adapter,
|
|
406
406
|
cline_default as default
|
|
407
407
|
};
|
|
408
|
-
//# sourceMappingURL=cline-
|
|
408
|
+
//# sourceMappingURL=cline-25KW25IN.js.map
|
|
@@ -13,13 +13,13 @@ import {
|
|
|
13
13
|
renderCommandMd,
|
|
14
14
|
renderSkillMd,
|
|
15
15
|
renderSubagentMd
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-MGTDQLJJ.js";
|
|
17
17
|
import {
|
|
18
18
|
buildWrappedStdio,
|
|
19
19
|
isHomeBinHookCommand
|
|
20
|
-
} from "./chunk-
|
|
21
|
-
import "./chunk-
|
|
22
|
-
import "./chunk-
|
|
20
|
+
} from "./chunk-4NHXLXSD.js";
|
|
21
|
+
import "./chunk-UMQ6NBQR.js";
|
|
22
|
+
import "./chunk-GZGLCCEE.js";
|
|
23
23
|
|
|
24
24
|
// src/adapters/codebuddy/index.ts
|
|
25
25
|
import { existsSync } from "fs";
|
|
@@ -640,4 +640,4 @@ export {
|
|
|
640
640
|
adapter,
|
|
641
641
|
codebuddy_default as default
|
|
642
642
|
};
|
|
643
|
-
//# sourceMappingURL=codebuddy-
|
|
643
|
+
//# sourceMappingURL=codebuddy-ZNYQACMF.js.map
|
|
@@ -5,12 +5,12 @@ import {
|
|
|
5
5
|
import {
|
|
6
6
|
BaseAdapter,
|
|
7
7
|
renderSkillMd
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-MGTDQLJJ.js";
|
|
9
9
|
import {
|
|
10
10
|
buildWrappedStdio
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import "./chunk-
|
|
13
|
-
import "./chunk-
|
|
11
|
+
} from "./chunk-4NHXLXSD.js";
|
|
12
|
+
import "./chunk-UMQ6NBQR.js";
|
|
13
|
+
import "./chunk-GZGLCCEE.js";
|
|
14
14
|
|
|
15
15
|
// src/adapters/codebuff/index.ts
|
|
16
16
|
import { existsSync } from "fs";
|
|
@@ -417,4 +417,4 @@ export {
|
|
|
417
417
|
adapter,
|
|
418
418
|
codebuff_default as default
|
|
419
419
|
};
|
|
420
|
-
//# sourceMappingURL=codebuff-
|
|
420
|
+
//# sourceMappingURL=codebuff-VR6JUDIY.js.map
|
|
@@ -17,15 +17,15 @@ import {
|
|
|
17
17
|
renderCommandMd,
|
|
18
18
|
renderSkillMd,
|
|
19
19
|
upsertInObjectMap
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-MGTDQLJJ.js";
|
|
21
21
|
import {
|
|
22
22
|
buildHomeBinHookCommand,
|
|
23
23
|
buildWrappedStdio
|
|
24
|
-
} from "./chunk-
|
|
25
|
-
import "./chunk-
|
|
24
|
+
} from "./chunk-4NHXLXSD.js";
|
|
25
|
+
import "./chunk-UMQ6NBQR.js";
|
|
26
26
|
import {
|
|
27
27
|
ensureDir
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-GZGLCCEE.js";
|
|
29
29
|
|
|
30
30
|
// src/adapters/codex/index.ts
|
|
31
31
|
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
@@ -509,6 +509,12 @@ var CodexAdapter = class extends BaseAdapter {
|
|
|
509
509
|
* Render a subagent to a Codex agent TOML file:
|
|
510
510
|
* { name, description, developer_instructions: prompt, model }.
|
|
511
511
|
* model is omitted when undefined so Codex applies its default.
|
|
512
|
+
*
|
|
513
|
+
* Codex custom agent files are config layers, not a closed four-field
|
|
514
|
+
* manifest. The Codex manual documents required custom-agent keys, plus
|
|
515
|
+
* optional config keys such as nickname_candidates, model_reasoning_effort,
|
|
516
|
+
* sandbox_mode, mcp_servers, and skills.config. Keep `extra` as the
|
|
517
|
+
* author-controlled escape hatch for that native surface.
|
|
512
518
|
*/
|
|
513
519
|
renderSubagent(agent) {
|
|
514
520
|
const table = {
|
|
@@ -756,4 +762,4 @@ export {
|
|
|
756
762
|
adapter,
|
|
757
763
|
codex_default as default
|
|
758
764
|
};
|
|
759
|
-
//# sourceMappingURL=codex-
|
|
765
|
+
//# sourceMappingURL=codex-CPNKTXG3.js.map
|