@ken-jo/agent-connector 0.3.0 → 0.3.1
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 +12 -8
- package/dist/{chunk-DS3LUFVN.js → chunk-3RBLIHPZ.js} +15 -15
- package/dist/{chunk-44HUXXC6.js → chunk-G5CQHVQG.js} +232 -5
- package/dist/chunk-G5CQHVQG.js.map +1 -0
- package/dist/{chunk-QADSG2JY.js → chunk-KMAKDD3Z.js} +1130 -109
- package/dist/chunk-KMAKDD3Z.js.map +1 -0
- package/dist/cli/sdk.js +1 -1
- package/dist/cli.js +1 -1
- package/dist/{detect-MNDHGLSV.js → detect-U3E7NVNW.js} +2 -2
- package/dist/{doctor-N5KZDD55.js → doctor-DZTWED4O.js} +4 -4
- package/dist/{hook-7LUOKIXH.js → hook-EVY7LOUQ.js} +2 -2
- package/dist/{install-TQTT4F3I.js → install-OWAS5UIE.js} +4 -4
- package/dist/{leaderboard-MUJ7DURM.js → leaderboard-CSWHI4UY.js} +2 -2
- package/dist/{package-SYPA5POO.js → package-WFOS4QVU.js} +2 -2
- package/dist/{serve-XJOSA7BY.js → serve-3C2VFPAY.js} +2 -2
- package/dist/{status-DYSS6BOR.js → status-MKQYX5MW.js} +3 -3
- package/dist/{telemetry-IJ4GP2Q3.js → telemetry-3DN6XGYB.js} +2 -2
- package/dist/{uninstall-3DXIBRCV.js → uninstall-WG6PFWF3.js} +4 -4
- package/dist/{upgrade-GJEB3ITY.js → upgrade-32NC2RKI.js} +4 -4
- package/dist/{usage-2BJLM3GJ.js → usage-CJOM2WQM.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-44HUXXC6.js.map +0 -1
- package/dist/chunk-QADSG2JY.js.map +0 -1
- /package/dist/{chunk-DS3LUFVN.js.map → chunk-3RBLIHPZ.js.map} +0 -0
- /package/dist/{detect-MNDHGLSV.js.map → detect-U3E7NVNW.js.map} +0 -0
- /package/dist/{doctor-N5KZDD55.js.map → doctor-DZTWED4O.js.map} +0 -0
- /package/dist/{hook-7LUOKIXH.js.map → hook-EVY7LOUQ.js.map} +0 -0
- /package/dist/{install-TQTT4F3I.js.map → install-OWAS5UIE.js.map} +0 -0
- /package/dist/{leaderboard-MUJ7DURM.js.map → leaderboard-CSWHI4UY.js.map} +0 -0
- /package/dist/{package-SYPA5POO.js.map → package-WFOS4QVU.js.map} +0 -0
- /package/dist/{serve-XJOSA7BY.js.map → serve-3C2VFPAY.js.map} +0 -0
- /package/dist/{status-DYSS6BOR.js.map → status-MKQYX5MW.js.map} +0 -0
- /package/dist/{telemetry-IJ4GP2Q3.js.map → telemetry-3DN6XGYB.js.map} +0 -0
- /package/dist/{uninstall-3DXIBRCV.js.map → uninstall-WG6PFWF3.js.map} +0 -0
- /package/dist/{upgrade-GJEB3ITY.js.map → upgrade-32NC2RKI.js.map} +0 -0
- /package/dist/{usage-2BJLM3GJ.js.map → usage-CJOM2WQM.js.map} +0 -0
package/dist/cli/sdk.js
CHANGED
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
print
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-3RBLIHPZ.js";
|
|
5
5
|
import {
|
|
6
6
|
detectInstalledPlatforms
|
|
7
7
|
} from "./chunk-NJU275US.js";
|
|
@@ -69,4 +69,4 @@ async function run(argv) {
|
|
|
69
69
|
export {
|
|
70
70
|
run
|
|
71
71
|
};
|
|
72
|
-
//# sourceMappingURL=detect-
|
|
72
|
+
//# sourceMappingURL=detect-U3E7NVNW.js.map
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
marketplaceDoctorChecks
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-KMAKDD3Z.js";
|
|
5
5
|
import "./chunk-WNREHWKL.js";
|
|
6
6
|
import {
|
|
7
7
|
readMarketplaceInstalls
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-G5CQHVQG.js";
|
|
9
9
|
import {
|
|
10
10
|
fail,
|
|
11
11
|
parseScope,
|
|
12
12
|
parseTargets,
|
|
13
13
|
print
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-3RBLIHPZ.js";
|
|
15
15
|
import {
|
|
16
16
|
LineBuffer,
|
|
17
17
|
idKey,
|
|
@@ -407,4 +407,4 @@ async function run(argv) {
|
|
|
407
407
|
export {
|
|
408
408
|
run
|
|
409
409
|
};
|
|
410
|
-
//# sourceMappingURL=doctor-
|
|
410
|
+
//# sourceMappingURL=doctor-DZTWED4O.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
fail
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-3RBLIHPZ.js";
|
|
5
5
|
import {
|
|
6
6
|
isNativeHookDeclared,
|
|
7
7
|
runHook,
|
|
@@ -87,4 +87,4 @@ function exitWithReply(reply) {
|
|
|
87
87
|
export {
|
|
88
88
|
run
|
|
89
89
|
};
|
|
90
|
-
//# sourceMappingURL=hook-
|
|
90
|
+
//# sourceMappingURL=hook-EVY7LOUQ.js.map
|
|
@@ -3,16 +3,16 @@ import {
|
|
|
3
3
|
installConnector,
|
|
4
4
|
installViaMarketplace,
|
|
5
5
|
parseInstallMethod
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-KMAKDD3Z.js";
|
|
7
7
|
import "./chunk-WNREHWKL.js";
|
|
8
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-G5CQHVQG.js";
|
|
9
9
|
import {
|
|
10
10
|
fail,
|
|
11
11
|
parseScope,
|
|
12
12
|
parseTargets,
|
|
13
13
|
print,
|
|
14
14
|
renderInstallResult
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-3RBLIHPZ.js";
|
|
16
16
|
import "./chunk-KVAAFYRR.js";
|
|
17
17
|
import "./chunk-NJU275US.js";
|
|
18
18
|
import {
|
|
@@ -86,4 +86,4 @@ async function run(argv) {
|
|
|
86
86
|
export {
|
|
87
87
|
run
|
|
88
88
|
};
|
|
89
|
-
//# sourceMappingURL=install-
|
|
89
|
+
//# sourceMappingURL=install-OWAS5UIE.js.map
|
|
@@ -15,7 +15,7 @@ import "./chunk-XD7MY6HB.js";
|
|
|
15
15
|
import {
|
|
16
16
|
fail,
|
|
17
17
|
print
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-3RBLIHPZ.js";
|
|
19
19
|
import "./chunk-BCHWFTV4.js";
|
|
20
20
|
import "./chunk-TRQKHP7D.js";
|
|
21
21
|
|
|
@@ -134,4 +134,4 @@ export {
|
|
|
134
134
|
parseSince,
|
|
135
135
|
run
|
|
136
136
|
};
|
|
137
|
-
//# sourceMappingURL=leaderboard-
|
|
137
|
+
//# sourceMappingURL=leaderboard-CSWHI4UY.js.map
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
import {
|
|
11
11
|
fail,
|
|
12
12
|
print
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-3RBLIHPZ.js";
|
|
14
14
|
import {
|
|
15
15
|
findConnectorConfig,
|
|
16
16
|
loadConnectorFromPath
|
|
@@ -127,4 +127,4 @@ async function run(argv) {
|
|
|
127
127
|
export {
|
|
128
128
|
run
|
|
129
129
|
};
|
|
130
|
-
//# sourceMappingURL=package-
|
|
130
|
+
//# sourceMappingURL=package-WFOS4QVU.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
fail
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-3RBLIHPZ.js";
|
|
5
5
|
import {
|
|
6
6
|
runServe
|
|
7
7
|
} from "./chunk-ZAM4M7LI.js";
|
|
@@ -63,4 +63,4 @@ async function run(argv) {
|
|
|
63
63
|
export {
|
|
64
64
|
run
|
|
65
65
|
};
|
|
66
|
-
//# sourceMappingURL=serve-
|
|
66
|
+
//# sourceMappingURL=serve-3C2VFPAY.js.map
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
marketplaceEvidence
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-G5CQHVQG.js";
|
|
5
5
|
import {
|
|
6
6
|
fail,
|
|
7
7
|
parseScope,
|
|
8
8
|
print
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-3RBLIHPZ.js";
|
|
10
10
|
import {
|
|
11
11
|
detectInstalledPlatforms,
|
|
12
12
|
loadAdapter
|
|
@@ -135,4 +135,4 @@ async function run(argv) {
|
|
|
135
135
|
export {
|
|
136
136
|
run
|
|
137
137
|
};
|
|
138
|
-
//# sourceMappingURL=status-
|
|
138
|
+
//# sourceMappingURL=status-MKQYX5MW.js.map
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
import {
|
|
13
13
|
fail,
|
|
14
14
|
print
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-3RBLIHPZ.js";
|
|
16
16
|
import {
|
|
17
17
|
openStore
|
|
18
18
|
} from "./chunk-BCHWFTV4.js";
|
|
@@ -347,4 +347,4 @@ export {
|
|
|
347
347
|
parseSince,
|
|
348
348
|
run
|
|
349
349
|
};
|
|
350
|
-
//# sourceMappingURL=telemetry-
|
|
350
|
+
//# sourceMappingURL=telemetry-3DN6XGYB.js.map
|
|
@@ -5,19 +5,19 @@ import {
|
|
|
5
5
|
resolveUninstallTargets,
|
|
6
6
|
uninstallConnector,
|
|
7
7
|
uninstallViaMarketplace
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-KMAKDD3Z.js";
|
|
9
9
|
import "./chunk-WNREHWKL.js";
|
|
10
10
|
import {
|
|
11
11
|
marketplaceEvidence,
|
|
12
12
|
readMarketplaceInstalls
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-G5CQHVQG.js";
|
|
14
14
|
import {
|
|
15
15
|
fail,
|
|
16
16
|
parseScope,
|
|
17
17
|
parseTargets,
|
|
18
18
|
print,
|
|
19
19
|
renderInstallResult
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-3RBLIHPZ.js";
|
|
21
21
|
import "./chunk-KVAAFYRR.js";
|
|
22
22
|
import "./chunk-NJU275US.js";
|
|
23
23
|
import {
|
|
@@ -159,4 +159,4 @@ async function run(argv) {
|
|
|
159
159
|
export {
|
|
160
160
|
run
|
|
161
161
|
};
|
|
162
|
-
//# sourceMappingURL=uninstall-
|
|
162
|
+
//# sourceMappingURL=uninstall-WG6PFWF3.js.map
|
|
@@ -4,16 +4,16 @@ import {
|
|
|
4
4
|
resolveCliEntry,
|
|
5
5
|
syncConnector,
|
|
6
6
|
upgradeViaMarketplace
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-KMAKDD3Z.js";
|
|
8
8
|
import "./chunk-WNREHWKL.js";
|
|
9
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-G5CQHVQG.js";
|
|
10
10
|
import {
|
|
11
11
|
fail,
|
|
12
12
|
parseScope,
|
|
13
13
|
parseTargets,
|
|
14
14
|
print,
|
|
15
15
|
renderInstallResult
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-3RBLIHPZ.js";
|
|
17
17
|
import "./chunk-KVAAFYRR.js";
|
|
18
18
|
import "./chunk-NJU275US.js";
|
|
19
19
|
import {
|
|
@@ -120,4 +120,4 @@ Refreshed home binary pointer: ${binPath}`);
|
|
|
120
120
|
export {
|
|
121
121
|
run
|
|
122
122
|
};
|
|
123
|
-
//# sourceMappingURL=upgrade-
|
|
123
|
+
//# sourceMappingURL=upgrade-32NC2RKI.js.map
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
import {
|
|
12
12
|
fail,
|
|
13
13
|
print
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-3RBLIHPZ.js";
|
|
15
15
|
|
|
16
16
|
// src/cli/commands/usage.ts
|
|
17
17
|
import { writeFileSync } from "fs";
|
|
@@ -321,4 +321,4 @@ export {
|
|
|
321
321
|
parseSince,
|
|
322
322
|
run
|
|
323
323
|
};
|
|
324
|
-
//# sourceMappingURL=usage-
|
|
324
|
+
//# sourceMappingURL=usage-CJOM2WQM.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ken-jo/agent-connector",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Write your MCP server + hooks once; agent-connector installs and adapts them across every AI-agent platform (Claude Code, Codex, Cursor, OpenCode, Copilot, Gemini, Warp, …) and gives you default, platform-independent per-tool token telemetry.",
|
|
6
6
|
"keywords": [
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/marketplace-state.ts"],"sourcesContent":["/**\n * core/marketplace-state — pure read/write helpers for MARKETPLACE-method\n * install state. A LEAF module (fs + paths only, no adapters, no spawning) so\n * the installer, the marketplace orchestration, doctor, and status can all\n * import it without cycles.\n *\n * Two kinds of state live here:\n *\n * 1. The per-connector state record `connectorDir(id)/marketplace-installs.json`\n * — one entry per platform a connector was marketplace-installed on\n * ({ format, bundleDir, marketplace, scope, version, contentHash,\n * installedAt }). It drives `uninstall --method auto`, upgrade staleness\n * warnings, doctor, and the double-install guard.\n *\n * 2. Read-only fs EVIDENCE probes of the hosts' own plugin state (e.g.\n * Claude Code's `$CLAUDE_CONFIG_DIR/plugins/installed_plugins.json`).\n * These catch installs the user performed manually from `package`'s\n * printed instructions, which the state record alone would miss. Probes\n * read undocumented host internals, so every reader degrades to null/false\n * on absence or parse failure — the guard convention is \"refuse only on\n * positive evidence\" (docs: design risk 4).\n */\n\nimport { createHash } from \"node:crypto\";\nimport {\n existsSync,\n readdirSync,\n readFileSync,\n rmSync,\n statSync,\n writeFileSync,\n} from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join, relative, resolve } from \"node:path\";\n\nimport TOML from \"@iarna/toml\";\n\nimport type { InstallScope, PlatformId } from \"./types.js\";\nimport type { PackageFormat } from \"./package.js\";\nimport { connectorDir, connectorsDir, dataRoot, ensureDir } from \"./paths.js\";\n\n// ─────────────────────────────────────────────────────────────────────────\n// State record: connectorDir(id)/marketplace-installs.json\n// ─────────────────────────────────────────────────────────────────────────\n\n/** The catalog name every staged local marketplace is registered under. */\nexport const MARKETPLACE_NAME = \"agent-connector\";\n\n/** One marketplace install of one connector on one platform. */\nexport interface MarketplaceInstallRecord {\n /** Bundle format that was staged + installed (e.g. \"claude-plugin\"). */\n format: PackageFormat;\n /** Absolute path of the staged plugin dir the host references/copied. */\n bundleDir: string;\n /** Marketplace/catalog name the install is keyed under ({@link MARKETPLACE_NAME}). */\n marketplace: string;\n /** Install scope (v1: always \"user\"). */\n scope: InstallScope;\n /** connector.version at install time (staleness warnings key off this). */\n version: string;\n /** sha256 over the staged plugin dir at install time (drift detection). */\n contentHash: string;\n /** ISO timestamp of the recorded install. */\n installedAt: string;\n}\n\n/** platform → record map persisted per connector. */\nexport type MarketplaceInstalls = Partial<\n Record<PlatformId, MarketplaceInstallRecord>\n>;\n\n/** Path of the per-connector marketplace state record. */\nexport function marketplaceInstallsPath(connectorId: string): string {\n return join(connectorDir(connectorId), \"marketplace-installs.json\");\n}\n\n/** Read the state record ({} on absence/parse failure — never throws). */\nexport function readMarketplaceInstalls(connectorId: string): MarketplaceInstalls {\n try {\n const raw = readFileSync(marketplaceInstallsPath(connectorId), \"utf8\");\n const parsed = JSON.parse(raw) as unknown;\n if (parsed && typeof parsed === \"object\" && !Array.isArray(parsed)) {\n return parsed as MarketplaceInstalls;\n }\n } catch {\n /* absent / unreadable → empty */\n }\n return {};\n}\n\n/** Write the state record; an empty map DELETES the file (uninstall leaves no husk). */\nexport function writeMarketplaceInstalls(\n connectorId: string,\n installs: MarketplaceInstalls,\n): void {\n const path = marketplaceInstallsPath(connectorId);\n if (Object.keys(installs).length === 0) {\n rmSync(path, { force: true });\n return;\n }\n ensureDir(dirname(path));\n writeFileSync(path, `${JSON.stringify(installs, null, 2)}\\n`, \"utf8\");\n}\n\n/** True when THIS connector has any recorded marketplace install. */\nexport function connectorHasMarketplaceRecords(connectorId: string): boolean {\n return Object.keys(readMarketplaceInstalls(connectorId)).length > 0;\n}\n\n/**\n * True when ANY registered connector (optionally excluding one) still records a\n * marketplace install. Guards home-bin removal on purge: an installed plugin's\n * hooks exec the home-bin OUTSIDE any adapter-managed config, so removing the\n * launcher while a marketplace install survives would silently kill its hooks.\n */\nexport function anyMarketplaceRecordsRemain(excludeConnectorId?: string): boolean {\n const dir = connectorsDir();\n if (!existsSync(dir)) return false;\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return false;\n }\n return entries.some(\n (id) => id !== excludeConnectorId && connectorHasMarketplaceRecords(id),\n );\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Staging roots — bundles staged by-reference must survive cwd changes and\n// `rm -rf dist-plugin`, so they live under the data-root, one shared root per\n// host family, holding every marketplace-installed connector's bundle plus ONE\n// regenerated catalog named \"agent-connector\" listing them all.\n// ─────────────────────────────────────────────────────────────────────────\n\n/** Root for every marketplace staging tree: <dataRoot>/marketplace. */\nexport function marketplaceRoot(): string {\n return join(dataRoot(), \"marketplace\");\n}\n\n/** Shared Claude-family staging root: <dataRoot>/marketplace/claude. */\nexport function claudeStagingRoot(): string {\n return join(marketplaceRoot(), \"claude\");\n}\n\n/** Shared Codex-family staging root: <dataRoot>/marketplace/codex. */\nexport function codexStagingRoot(): string {\n return join(marketplaceRoot(), \"codex\");\n}\n\n/** Shared agy (Antigravity) staging root: <dataRoot>/marketplace/agy. */\nexport function agyStagingRoot(): string {\n return join(marketplaceRoot(), \"agy\");\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Claude Code host-state readers ($CLAUDE_CONFIG_DIR || ~/.claude)\n// ─────────────────────────────────────────────────────────────────────────\n\n/** Claude Code's config dir, honoring the CLAUDE_CONFIG_DIR override. */\nexport function claudeConfigDir(): string {\n const override = process.env.CLAUDE_CONFIG_DIR;\n if (override && override.trim() !== \"\") return resolve(override);\n return join(homedir(), \".claude\");\n}\n\n/** The installed_plugins.json key our marketplace install creates for `id`. */\nexport function claudePluginKey(connectorId: string): string {\n return `${connectorId}@${MARKETPLACE_NAME}`;\n}\n\nfunction readJsonFile(path: string): Record<string, unknown> | null {\n try {\n const parsed = JSON.parse(readFileSync(path, \"utf8\")) as unknown;\n if (parsed && typeof parsed === \"object\" && !Array.isArray(parsed)) {\n return parsed as Record<string, unknown>;\n }\n } catch {\n /* absent / unreadable → null */\n }\n return null;\n}\n\n/** The `plugins` map from Claude's installed_plugins.json (null when unreadable). */\nexport function readClaudeInstalledPlugins(): Record<string, unknown> | null {\n const file = join(claudeConfigDir(), \"plugins\", \"installed_plugins.json\");\n const parsed = readJsonFile(file);\n const plugins = parsed?.plugins;\n if (plugins && typeof plugins === \"object\" && !Array.isArray(plugins)) {\n return plugins as Record<string, unknown>;\n }\n return null;\n}\n\n/** True when Claude's own state lists `<id>@agent-connector` as installed. */\nexport function claudePluginInstalled(connectorId: string): boolean {\n const plugins = readClaudeInstalledPlugins();\n if (!plugins) return false;\n const entry = plugins[claudePluginKey(connectorId)];\n return Array.isArray(entry) ? entry.length > 0 : entry != null;\n}\n\n/** True when ANY `*@agent-connector` plugin remains in Claude's state. */\nexport function anyClaudeAgentConnectorPlugins(): boolean {\n const plugins = readClaudeInstalledPlugins();\n if (!plugins) return false;\n return Object.entries(plugins).some(\n ([key, entry]) =>\n key.endsWith(`@${MARKETPLACE_NAME}`) &&\n (Array.isArray(entry) ? entry.length > 0 : entry != null),\n );\n}\n\n/**\n * The directory Claude's known_marketplaces.json records for `name`, or null\n * when not registered / unreadable. Used both as a presence probe and as the\n * NAME-COLLISION check: a registration pointing somewhere other than our\n * staging root belongs to the user and must never be touched.\n */\nexport function claudeKnownMarketplacePath(name: string): string | null {\n const file = join(claudeConfigDir(), \"plugins\", \"known_marketplaces.json\");\n const parsed = readJsonFile(file);\n const entry = parsed?.[name];\n if (!entry || typeof entry !== \"object\") return null;\n const e = entry as { installLocation?: unknown; source?: { path?: unknown } };\n if (typeof e.installLocation === \"string\") return e.installLocation;\n const sourcePath = e.source?.path;\n return typeof sourcePath === \"string\" ? sourcePath : null;\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Codex host-state readers ($CODEX_HOME || ~/.codex → config.toml)\n// ─────────────────────────────────────────────────────────────────────────\n\n/** Codex's config home, honoring the CODEX_HOME override (defaults to ~/.codex). */\nexport function codexConfigHome(): string {\n const env = process.env.CODEX_HOME;\n if (env && env.trim() !== \"\") {\n if (env.startsWith(\"~\")) return join(homedir(), env.replace(/^~[/\\\\]?/, \"\"));\n return resolve(env);\n }\n return join(homedir(), \".codex\");\n}\n\n/** The config.toml key our marketplace install creates for `id` (== claude's). */\nexport function codexPluginKey(connectorId: string): string {\n return `${connectorId}@${MARKETPLACE_NAME}`;\n}\n\n/** Parse <CODEX_HOME>/config.toml ({} on absence/parse failure — never throws). */\nfunction readCodexConfig(): Record<string, unknown> {\n const file = join(codexConfigHome(), \"config.toml\");\n try {\n return TOML.parse(readFileSync(file, \"utf8\")) as Record<string, unknown>;\n } catch {\n return {};\n }\n}\n\n/**\n * True when Codex's config.toml carries the `[plugins.\"<id>@agent-connector\"]`\n * table. The DEFINITIVE install probe — empty `plugins/cache/...` dirs linger\n * after uninstall, so the cache dir must NOT be used (docs: codex quirk).\n */\nexport function codexPluginInstalled(connectorId: string): boolean {\n const cfg = readCodexConfig();\n const plugins = cfg[\"plugins\"];\n if (!plugins || typeof plugins !== \"object\" || Array.isArray(plugins)) return false;\n return codexPluginKey(connectorId) in (plugins as Record<string, unknown>);\n}\n\n/** True when ANY `*@agent-connector` plugin remains in Codex's config.toml. */\nexport function anyCodexAgentConnectorPlugins(): boolean {\n const cfg = readCodexConfig();\n const plugins = cfg[\"plugins\"];\n if (!plugins || typeof plugins !== \"object\" || Array.isArray(plugins)) return false;\n return Object.keys(plugins as Record<string, unknown>).some((k) =>\n k.endsWith(`@${MARKETPLACE_NAME}`),\n );\n}\n\n/**\n * The directory config.toml records as `[marketplaces.agent-connector].source`,\n * or null when not registered / unreadable. Both a presence probe and the\n * NAME-COLLISION check: a registration pointing somewhere other than our\n * staging root belongs to the user and must never be touched.\n */\nexport function codexMarketplaceSource(name: string): string | null {\n const cfg = readCodexConfig();\n const marketplaces = cfg[\"marketplaces\"];\n if (!marketplaces || typeof marketplaces !== \"object\" || Array.isArray(marketplaces)) {\n return null;\n }\n const entry = (marketplaces as Record<string, unknown>)[name];\n if (!entry || typeof entry !== \"object\") return null;\n const source = (entry as { source?: unknown }).source;\n return typeof source === \"string\" ? source : null;\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// agy (Antigravity) host-state readers (~/.gemini/config/plugins, NO env)\n// ─────────────────────────────────────────────────────────────────────────\n\n/** agy's config dir: ~/.gemini/config (NO dedicated env — HOME isolation). */\nexport function agyConfigDir(): string {\n return join(homedir(), \".gemini\", \"config\");\n}\n\n/** agy's plugins dir: ~/.gemini/config/plugins. */\nexport function agyPluginsDir(): string {\n return join(agyConfigDir(), \"plugins\");\n}\n\n/**\n * Candidate `import_manifest.json` locations. agy 1.0.7 records the manifest at\n * `<config>/plugins/import_manifest.json` on POSIX but at\n * `<config>/import_manifest.json` on Windows (live-confirmed on the my-window\n * box) — both are probed, then the copied plugin dir is the final fallback.\n */\nexport function agyImportManifestPaths(): string[] {\n return [\n join(agyConfigDir(), \"import_manifest.json\"), // win32 location\n join(agyPluginsDir(), \"import_manifest.json\"), // posix location\n ];\n}\n\n/** @deprecated single-location accessor — prefer {@link agyImportManifestPaths}. */\nexport function agyImportManifestPath(): string {\n return join(agyPluginsDir(), \"import_manifest.json\");\n}\n\n/**\n * True when `id` is installed per agy's import manifest (`imports[].name`),\n * checking BOTH the win32 and posix manifest locations, with a fallback probe of\n * the copied plugin dir's plugin.json. agy's uninstall removes the plugin dir\n * and clears the manifest entry (live-verified on Windows: install → dir +\n * manifest present, uninstall → both gone, re-install idempotent).\n */\nexport function agyPluginInstalled(connectorId: string): boolean {\n for (const manifest of agyImportManifestPaths()) {\n try {\n const parsed = JSON.parse(readFileSync(manifest, \"utf8\")) as {\n imports?: unknown;\n };\n const imports = parsed.imports;\n if (\n Array.isArray(imports) &&\n imports.some(\n (e) =>\n e != null &&\n typeof e === \"object\" &&\n (e as { name?: unknown }).name === connectorId,\n )\n ) {\n return true;\n }\n } catch {\n /* absent / unreadable manifest → try the next candidate */\n }\n }\n return existsSync(join(agyPluginsDir(), connectorId, \"plugin.json\"));\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Cross-host marketplace-install EVIDENCE (the double-install guard's probe)\n// ─────────────────────────────────────────────────────────────────────────\n\n/**\n * Read-only evidence that `connectorId` is marketplace/plugin-installed on\n * `platform`: the state record first, then a cheap fs probe of the host's own\n * plugin state (catches manual installs from `package`'s printed instructions).\n * Returns a human-readable description of the evidence, or null when none.\n */\nexport function marketplaceEvidence(\n connectorId: string,\n platform: PlatformId,\n): string | null {\n if (readMarketplaceInstalls(connectorId)[platform]) {\n return \"recorded in marketplace-installs.json\";\n }\n switch (platform) {\n case \"claude-code\":\n if (claudePluginInstalled(connectorId)) {\n return `${claudePluginKey(connectorId)} listed in Claude's installed_plugins.json`;\n }\n return null;\n case \"gemini-cli\": {\n const dir = join(homedir(), \".gemini\", \"extensions\", connectorId);\n return existsSync(dir) ? `extension dir ${dir} exists` : null;\n }\n case \"antigravity\":\n case \"antigravity-cli\": {\n const dir = join(homedir(), \".gemini\", \"config\", \"plugins\", connectorId);\n return existsSync(dir) ? `plugin dir ${dir} exists` : null;\n }\n case \"codex\": {\n const codexHome =\n process.env.CODEX_HOME && process.env.CODEX_HOME.trim() !== \"\"\n ? resolve(process.env.CODEX_HOME)\n : join(homedir(), \".codex\");\n const dir = join(codexHome, \"plugins\", \"cache\", MARKETPLACE_NAME, connectorId);\n return existsSync(dir) ? `codex plugin cache ${dir} exists` : null;\n }\n default:\n return null;\n }\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Content hashing — staged-bundle drift detection\n// ─────────────────────────────────────────────────────────────────────────\n\n/**\n * Deterministic sha256 over every file under `dir` (sorted relative paths +\n * bytes). Empty string when the dir is missing/unreadable. Used to record the\n * staged bundle's content at install time and detect drift later (claude caches\n * a versioned COPY, so an edited connector goes silently stale without this).\n */\nexport function hashDirectory(dir: string): string {\n if (!existsSync(dir)) return \"\";\n const files: string[] = [];\n const walk = (d: string): void => {\n let entries: string[];\n try {\n entries = readdirSync(d);\n } catch {\n return;\n }\n for (const name of entries.sort()) {\n const full = join(d, name);\n let st;\n try {\n st = statSync(full);\n } catch {\n continue;\n }\n if (st.isDirectory()) walk(full);\n else if (st.isFile()) files.push(full);\n }\n };\n walk(dir);\n const hash = createHash(\"sha256\");\n for (const file of files.sort()) {\n hash.update(relative(dir, file).split(\"\\\\\").join(\"/\"));\n hash.update(\"\\0\");\n try {\n hash.update(readFileSync(file));\n } catch {\n /* unreadable file contributes only its path */\n }\n hash.update(\"\\0\");\n }\n return hash.digest(\"hex\");\n}\n"],"mappings":"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","names":[]}
|