@ken-jo/agent-connector 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/README.md +9 -2
  2. package/dist/chunk-44HUXXC6.js +284 -0
  3. package/dist/chunk-44HUXXC6.js.map +1 -0
  4. package/dist/{chunk-AKJGNTU3.js → chunk-DS3LUFVN.js} +21 -21
  5. package/dist/chunk-DS3LUFVN.js.map +1 -0
  6. package/dist/{chunk-KHO5WNTP.js → chunk-KVAAFYRR.js} +18 -2
  7. package/dist/chunk-KVAAFYRR.js.map +1 -0
  8. package/dist/{chunk-O2SBA5KR.js → chunk-NJU275US.js} +9 -9
  9. package/dist/{chunk-WCETQWWK.js → chunk-OP4KBXUO.js} +1 -17
  10. package/dist/chunk-OP4KBXUO.js.map +1 -0
  11. package/dist/chunk-QADSG2JY.js +1989 -0
  12. package/dist/chunk-QADSG2JY.js.map +1 -0
  13. package/dist/{package-O63K4S7T.js → chunk-WNREHWKL.js} +20 -114
  14. package/dist/chunk-WNREHWKL.js.map +1 -0
  15. package/dist/{chunk-4ML7SZ7R.js → chunk-ZAM4M7LI.js} +7 -7
  16. package/dist/cli/sdk.js +1 -1
  17. package/dist/cli.js +1 -1
  18. package/dist/{detect-JK7T46N6.js → detect-MNDHGLSV.js} +3 -3
  19. package/dist/{doctor-62BHIXOR.js → doctor-N5KZDD55.js} +35 -5
  20. package/dist/doctor-N5KZDD55.js.map +1 -0
  21. package/dist/{hook-AC7APC66.js → hook-7LUOKIXH.js} +6 -6
  22. package/dist/{install-DMW2C7SV.js → install-TQTT4F3I.js} +31 -7
  23. package/dist/install-TQTT4F3I.js.map +1 -0
  24. package/dist/kilo-PKAJCWPX.js +852 -0
  25. package/dist/kilo-PKAJCWPX.js.map +1 -0
  26. package/dist/{kilo-cli-2RNODHWY.js → kilo-cli-QWUVXG2O.js} +157 -6
  27. package/dist/kilo-cli-QWUVXG2O.js.map +1 -0
  28. package/dist/{kimi-Q5RG7CYT.js → kimi-EVD7YKXS.js} +79 -4
  29. package/dist/kimi-EVD7YKXS.js.map +1 -0
  30. package/dist/{kiro-EKTRW424.js → kiro-UQRY6EIO.js} +68 -3
  31. package/dist/kiro-UQRY6EIO.js.map +1 -0
  32. package/dist/{leaderboard-R5HRJHNU.js → leaderboard-MUJ7DURM.js} +2 -2
  33. package/dist/package-SYPA5POO.js +130 -0
  34. package/dist/package-SYPA5POO.js.map +1 -0
  35. package/dist/{pi-SJPIL4VE.js → pi-WMTUX6ES.js} +102 -23
  36. package/dist/pi-WMTUX6ES.js.map +1 -0
  37. package/dist/{qwen-code-IFCM6BJY.js → qwen-code-MRRIUQ3P.js} +78 -5
  38. package/dist/qwen-code-MRRIUQ3P.js.map +1 -0
  39. package/dist/runtime/index.js +4 -4
  40. package/dist/{serve-LFOUSZAD.js → serve-XJOSA7BY.js} +6 -6
  41. package/dist/{status-M7JLZVLC.js → status-DYSS6BOR.js} +16 -7
  42. package/dist/status-DYSS6BOR.js.map +1 -0
  43. package/dist/{telemetry-3NVEXPYX.js → telemetry-IJ4GP2Q3.js} +2 -2
  44. package/dist/uninstall-3DXIBRCV.js +162 -0
  45. package/dist/uninstall-3DXIBRCV.js.map +1 -0
  46. package/dist/{upgrade-76BQZBMA.js → upgrade-GJEB3ITY.js} +26 -8
  47. package/dist/upgrade-GJEB3ITY.js.map +1 -0
  48. package/dist/{usage-G3GSCX23.js → usage-2BJLM3GJ.js} +2 -2
  49. package/dist/{usage-event-QUTMNBS5.js → usage-event-472X3DOY.js} +5 -5
  50. package/dist/{warp-LLOSXR7A.js → warp-X6MB67NT.js} +81 -3
  51. package/dist/warp-X6MB67NT.js.map +1 -0
  52. package/dist/{zed-HYOITK7F.js → zed-NTCYW4V2.js} +68 -3
  53. package/dist/zed-NTCYW4V2.js.map +1 -0
  54. package/package.json +1 -1
  55. package/dist/chunk-AKJGNTU3.js.map +0 -1
  56. package/dist/chunk-KHO5WNTP.js.map +0 -1
  57. package/dist/chunk-WCETQWWK.js.map +0 -1
  58. package/dist/chunk-Z2BVYKZL.js +0 -369
  59. package/dist/chunk-Z2BVYKZL.js.map +0 -1
  60. package/dist/doctor-62BHIXOR.js.map +0 -1
  61. package/dist/install-DMW2C7SV.js.map +0 -1
  62. package/dist/kilo-ISR5FBBJ.js +0 -408
  63. package/dist/kilo-ISR5FBBJ.js.map +0 -1
  64. package/dist/kilo-cli-2RNODHWY.js.map +0 -1
  65. package/dist/kimi-Q5RG7CYT.js.map +0 -1
  66. package/dist/kiro-EKTRW424.js.map +0 -1
  67. package/dist/package-O63K4S7T.js.map +0 -1
  68. package/dist/pi-SJPIL4VE.js.map +0 -1
  69. package/dist/qwen-code-IFCM6BJY.js.map +0 -1
  70. package/dist/status-M7JLZVLC.js.map +0 -1
  71. package/dist/uninstall-H6FGMIHN.js +0 -73
  72. package/dist/uninstall-H6FGMIHN.js.map +0 -1
  73. package/dist/upgrade-76BQZBMA.js.map +0 -1
  74. package/dist/warp-LLOSXR7A.js.map +0 -1
  75. package/dist/zed-HYOITK7F.js.map +0 -1
  76. /package/dist/{chunk-O2SBA5KR.js.map → chunk-NJU275US.js.map} +0 -0
  77. /package/dist/{chunk-4ML7SZ7R.js.map → chunk-ZAM4M7LI.js.map} +0 -0
  78. /package/dist/{detect-JK7T46N6.js.map → detect-MNDHGLSV.js.map} +0 -0
  79. /package/dist/{hook-AC7APC66.js.map → hook-7LUOKIXH.js.map} +0 -0
  80. /package/dist/{leaderboard-R5HRJHNU.js.map → leaderboard-MUJ7DURM.js.map} +0 -0
  81. /package/dist/{serve-LFOUSZAD.js.map → serve-XJOSA7BY.js.map} +0 -0
  82. /package/dist/{telemetry-3NVEXPYX.js.map → telemetry-IJ4GP2Q3.js.map} +0 -0
  83. /package/dist/{usage-G3GSCX23.js.map → usage-2BJLM3GJ.js.map} +0 -0
  84. /package/dist/{usage-event-QUTMNBS5.js.map → usage-event-472X3DOY.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/commands/status.ts"],"sourcesContent":["/**\n * cli/commands/status — a light, glanceable install-state summary.\n *\n * There is NO MCP standard for \"which connectors are installed into which host\n * configs on this machine\" — distribution/wire standards (server.json, MCPB,\n * the lifecycle) cover publishing + the protocol, not local install state. So\n * `status` is purely agent-connector infrastructure, and we design it for the\n * everyday question it answers in one line per platform:\n *\n * \"which of my connectors are present on which hosts?\"\n *\n * It REUSES detect (host enumeration) + the adapters' own config-path resolvers\n * (a read-only presence check) — NO new adapter SPI methods. Unlike `doctor`\n * (deep health checks, non-zero exit on failure) and `doctor --probe` (a live\n * protocol probe that FAILs on a dead server), `status` ALWAYS exits 0: it\n * describes, it never gates. A connector being absent is informational.\n */\n\nimport { parseArgs } from \"node:util\";\nimport { readFileSync } from \"node:fs\";\n\nimport type { InstallScope, PlatformId, ResolvedConnector } from \"../../core/types.js\";\nimport type { InstallContext } from \"../../adapters/spi.js\";\nimport { detectInstalledPlatforms } from \"../../adapters/detect.js\";\nimport { loadAdapter } from \"../../adapters/registry.js\";\nimport {\n findConnectorConfig,\n listRegisteredConnectors,\n loadConnectorFromPath,\n} from \"../../core/load-connector.js\";\nimport { marketplaceEvidence } from \"../../core/marketplace-state.js\";\nimport { dataRoot, homeBinPath } from \"../../core/paths.js\";\nimport { fail, parseScope, print } from \"../app.js\";\n\n/**\n * Resolve which connector(s) status reports on: an explicit --connector path or\n * a local config first, else every connector registered under the data-root\n * (what is actually installed). Empty array when none — status still lists the\n * detected platforms.\n */\nasync function resolveConnectors(\n connectorPath: string | undefined,\n projectDir: string,\n): Promise<ResolvedConnector[]> {\n const configPath = connectorPath ?? findConnectorConfig(projectDir);\n if (configPath) {\n try {\n const { connector } = await loadConnectorFromPath(configPath);\n return [connector];\n } catch {\n /* fall through to the registry */\n }\n }\n return listRegisteredConnectors();\n}\n\nfunction buildContext(\n connector: ResolvedConnector,\n id: PlatformId,\n scope: InstallScope,\n projectDir: string,\n): InstallContext {\n return {\n connector,\n scope: connector.platforms[id]?.scope ?? scope,\n projectDir,\n homeBinPath: homeBinPath(),\n dataRoot: dataRoot(),\n dryRun: true,\n };\n}\n\n/** Read-only: does the file at `path` mention `needle`? Missing/unreadable → false. */\nfunction fileMentions(path: string, needle: string): boolean {\n try {\n return readFileSync(path, \"utf8\").includes(needle);\n } catch {\n return false;\n }\n}\n\ninterface ConnStatus {\n id: string;\n serverPresent: boolean;\n hooksPresent: boolean;\n /**\n * Delivery method actually present on this host: `direct` (managed entries in\n * the host config), `marketplace` (the host's own plugin state / our install\n * record), `both` (the double-install invariant is VIOLATED — doctor FAILs\n * it), or null when absent.\n */\n method: \"direct\" | \"marketplace\" | \"both\" | null;\n}\ninterface StatusRow {\n platform: PlatformId;\n scope: InstallScope;\n configPath: string;\n connectors: ConnStatus[];\n}\n\nexport async function run(argv: string[]): Promise<number> {\n const { values } = parseArgs({\n args: argv,\n options: {\n scope: { type: \"string\", default: \"user\" },\n connector: { type: \"string\" },\n project: { type: \"string\" },\n json: { type: \"boolean\", default: false },\n },\n allowPositionals: false,\n });\n\n const projectDir = values.project ?? process.cwd();\n const scope = parseScope(values.scope);\n if (scope == null) return fail(`invalid --scope \"${values.scope}\" (use user|project)`);\n\n const connectors = await resolveConnectors(values.connector, projectDir);\n const detected = await detectInstalledPlatforms(projectDir);\n\n const rows: StatusRow[] = [];\n for (const p of detected) {\n const adapter = await loadAdapter(p.id);\n if (!adapter) continue;\n const connStatuses: ConnStatus[] = connectors.map((connector) => {\n const ctx = buildContext(connector, p.id, scope, projectDir);\n let serverPath = \"\";\n let hookPath = \"\";\n try {\n serverPath = adapter.getServerConfigPath(ctx);\n } catch {\n /* adapter has no server config path */\n }\n try {\n hookPath = adapter.getHookConfigPath(ctx);\n } catch {\n /* adapter has no hook config path */\n }\n const serverPresent = serverPath\n ? fileMentions(serverPath, connector.id)\n : false;\n const hooksPresent = hookPath ? fileMentions(hookPath, connector.id) : false;\n const direct = serverPresent || hooksPresent;\n const viaMarketplace = marketplaceEvidence(connector.id, p.id) != null;\n return {\n id: connector.id,\n serverPresent,\n hooksPresent,\n method: direct && viaMarketplace\n ? (\"both\" as const)\n : direct\n ? (\"direct\" as const)\n : viaMarketplace\n ? (\"marketplace\" as const)\n : null,\n };\n });\n rows.push({\n platform: p.id,\n scope: p.scope,\n configPath: p.configPath,\n connectors: connStatuses,\n });\n }\n\n if (values.json) {\n print(JSON.stringify(rows, null, 2));\n return 0;\n }\n\n if (rows.length === 0) {\n print(\"status: no agent platforms detected.\");\n return 0;\n }\n if (connectors.length === 0) {\n print(\"status: no connectors found (pass --connector <path> or install one).\\n\");\n }\n\n for (const r of rows) {\n print(`${r.platform} [${r.scope}] ${r.configPath}`);\n if (r.connectors.length === 0) {\n print(\" (no connectors to check)\");\n } else {\n for (const c of r.connectors) {\n const mark = c.method != null ? \"[installed]\" : \"[absent ]\";\n const server = c.serverPresent ? \"server ✓\" : \"server ·\";\n const hooks = c.hooksPresent ? \"hooks ✓\" : \"hooks ·\";\n // `both(!)` flags a violated one-method-per-host invariant — doctor's\n // duplicate-registration check FAILs it with the fix.\n const method =\n c.method == null ? \"\" : c.method === \"both\" ? \" (both!)\" : ` (${c.method})`;\n print(` ${mark} ${c.id} ${server} ${hooks}${method}`);\n }\n }\n print(\"\");\n }\n\n // Always 0: status is descriptive (what is installed where), never a gate —\n // that contrast with doctor (non-zero on FAIL) is the reason it exists.\n return 0;\n}\n"],"mappings":"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","names":[]}
@@ -12,7 +12,7 @@ import {
12
12
  import {
13
13
  fail,
14
14
  print
15
- } from "./chunk-AKJGNTU3.js";
15
+ } from "./chunk-DS3LUFVN.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-3NVEXPYX.js.map
350
+ //# sourceMappingURL=telemetry-IJ4GP2Q3.js.map
@@ -0,0 +1,162 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ parseUninstallMethod,
4
+ purgeFrameworkState,
5
+ resolveUninstallTargets,
6
+ uninstallConnector,
7
+ uninstallViaMarketplace
8
+ } from "./chunk-QADSG2JY.js";
9
+ import "./chunk-WNREHWKL.js";
10
+ import {
11
+ marketplaceEvidence,
12
+ readMarketplaceInstalls
13
+ } from "./chunk-44HUXXC6.js";
14
+ import {
15
+ fail,
16
+ parseScope,
17
+ parseTargets,
18
+ print,
19
+ renderInstallResult
20
+ } from "./chunk-DS3LUFVN.js";
21
+ import "./chunk-KVAAFYRR.js";
22
+ import "./chunk-NJU275US.js";
23
+ import {
24
+ findConnectorConfig,
25
+ loadConnectorFromPath
26
+ } from "./chunk-3JCRUROU.js";
27
+ import "./chunk-GSGDG2BV.js";
28
+ import "./chunk-OPXAP3AC.js";
29
+ import "./chunk-7L6ITC4T.js";
30
+ import "./chunk-MEH7GC7R.js";
31
+ import "./chunk-N6HH7K6P.js";
32
+ import "./chunk-TRQKHP7D.js";
33
+
34
+ // src/cli/commands/uninstall.ts
35
+ import { parseArgs } from "util";
36
+ async function resolveConnectorId(explicitId, connectorPath, projectDir) {
37
+ if (explicitId && explicitId.trim() !== "") return explicitId;
38
+ const configPath = connectorPath ?? findConnectorConfig(projectDir);
39
+ if (!configPath) return null;
40
+ const { connector } = await loadConnectorFromPath(configPath);
41
+ return connector.id;
42
+ }
43
+ async function run(argv) {
44
+ const { values } = parseArgs({
45
+ args: argv,
46
+ options: {
47
+ method: { type: "string", default: "auto" },
48
+ scope: { type: "string", default: "user" },
49
+ targets: { type: "string" },
50
+ connector: { type: "string" },
51
+ "connector-id": { type: "string" },
52
+ project: { type: "string" },
53
+ "dry-run": { type: "boolean", default: false },
54
+ purge: { type: "boolean", default: false }
55
+ },
56
+ allowPositionals: false
57
+ });
58
+ const method = parseUninstallMethod(values.method);
59
+ if (method == null) {
60
+ return fail(`invalid --method "${values.method}" (use auto|direct|marketplace)`);
61
+ }
62
+ const projectDir = values.project ?? process.cwd();
63
+ const scope = parseScope(values.scope);
64
+ if (scope == null) return fail(`invalid --scope "${values.scope}" (use user|project)`);
65
+ const connectorId = await resolveConnectorId(
66
+ values["connector-id"],
67
+ values.connector,
68
+ projectDir
69
+ );
70
+ if (!connectorId) {
71
+ return fail(
72
+ "could not determine connector id. Pass --connector-id <id>, --connector <path>, or run inside a project with an agent-connector config."
73
+ );
74
+ }
75
+ const targets = parseTargets(values.targets);
76
+ const dryRun = values["dry-run"];
77
+ if (method === "marketplace") {
78
+ const result = await uninstallViaMarketplace({
79
+ connectorId,
80
+ projectDir,
81
+ dryRun,
82
+ purge: values.purge,
83
+ ...targets ? { targets } : {}
84
+ });
85
+ if (values.purge) purgeFrameworkState(connectorId, dryRun, result);
86
+ print(renderInstallResult(result, "uninstall"));
87
+ return result.changes.some((c) => c.action === "warn") ? 1 : 0;
88
+ }
89
+ let marketplaceTargets = [];
90
+ let directTargets = [];
91
+ if (method === "auto") {
92
+ const resolved = await resolveUninstallTargets(connectorId, targets, projectDir);
93
+ const recorded = targets ? [] : Object.keys(readMarketplaceInstalls(connectorId));
94
+ const candidates = [.../* @__PURE__ */ new Set([...resolved, ...recorded])];
95
+ marketplaceTargets = candidates.filter(
96
+ (id) => marketplaceEvidence(connectorId, id) != null
97
+ );
98
+ directTargets = resolved.filter((id) => !marketplaceTargets.includes(id));
99
+ }
100
+ if (marketplaceTargets.length === 0) {
101
+ const result = await uninstallConnector({
102
+ connectorId,
103
+ scope,
104
+ projectDir,
105
+ dryRun,
106
+ purge: values.purge,
107
+ ...targets ? { targets } : {}
108
+ });
109
+ print(renderInstallResult(result, "uninstall"));
110
+ return result.changes.some((c) => c.action === "warn") ? 1 : 0;
111
+ }
112
+ const results = [
113
+ await uninstallViaMarketplace({
114
+ connectorId,
115
+ projectDir,
116
+ targets: marketplaceTargets,
117
+ dryRun,
118
+ purge: values.purge
119
+ })
120
+ ];
121
+ if (directTargets.length > 0) {
122
+ results.push(
123
+ await uninstallConnector({
124
+ connectorId,
125
+ scope,
126
+ projectDir,
127
+ dryRun,
128
+ purge: values.purge,
129
+ targets: directTargets
130
+ })
131
+ );
132
+ } else if (values.purge) {
133
+ const purgeResult = {
134
+ connectorId,
135
+ dryRun,
136
+ changes: [],
137
+ warnings: []
138
+ };
139
+ if (dryRun) {
140
+ purgeResult.changes.push({
141
+ platform: connectorId,
142
+ action: "remove",
143
+ detail: "would purge framework state (connector record; home-bin when no connectors remain)"
144
+ });
145
+ } else {
146
+ purgeFrameworkState(connectorId, dryRun, purgeResult);
147
+ }
148
+ results.push(purgeResult);
149
+ }
150
+ const merged = {
151
+ connectorId,
152
+ dryRun,
153
+ changes: results.flatMap((r) => r.changes),
154
+ warnings: results.flatMap((r) => r.warnings)
155
+ };
156
+ print(renderInstallResult(merged, "uninstall"));
157
+ return merged.changes.some((c) => c.action === "warn") ? 1 : 0;
158
+ }
159
+ export {
160
+ run
161
+ };
162
+ //# sourceMappingURL=uninstall-3DXIBRCV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/commands/uninstall.ts"],"sourcesContent":["/**\n * cli/commands/uninstall — strip a connector's registrations, method-aware.\n *\n * The connector id is taken from --connector-id, or inferred from the local\n * connector config (--connector <path> / findConnectorConfig).\n *\n * --method auto (default) reverses WHATEVER is actually there, per target:\n * targets with marketplace evidence (the state record, or the host's own plugin\n * state) get the HOST plugin uninstall; everything else gets the existing\n * direct adapter strip. Install chooses a method (a user decision); uninstall\n * reverses what exists (a state decision) — and since the double-install guard\n * enforces exactly one method per (connector, host, scope), auto is\n * unambiguous. Explicit --method direct|marketplace forces one path for every\n * target. Config removal vs plugin uninstall is therefore method-resolved:\n * never both, never neither.\n *\n * --purge additionally removes the framework-state this connector left behind:\n * its DATA-dir connector record (connectorDir(id)), the empty marketplace\n * staging root, and, when no connectors remain, the shared home-bin launcher.\n * Without --purge those linger so the connector can be re-synced without\n * re-registering.\n */\n\nimport { parseArgs } from \"node:util\";\n\nimport {\n purgeFrameworkState,\n resolveUninstallTargets,\n uninstallConnector,\n} from \"../../core/installer.js\";\nimport {\n marketplaceEvidence,\n parseUninstallMethod,\n uninstallViaMarketplace,\n} from \"../../core/marketplace.js\";\nimport { readMarketplaceInstalls } from \"../../core/marketplace-state.js\";\nimport { findConnectorConfig, loadConnectorFromPath } from \"../../core/load-connector.js\";\nimport type { InstallResult, PlatformId } from \"../../core/types.js\";\nimport { fail, parseScope, parseTargets, print, renderInstallResult } from \"../app.js\";\n\n/** Resolve the connector id from flags, then from a local config file. */\nasync function resolveConnectorId(\n explicitId: string | undefined,\n connectorPath: string | undefined,\n projectDir: string,\n): Promise<string | null> {\n if (explicitId && explicitId.trim() !== \"\") return explicitId;\n const configPath = connectorPath ?? findConnectorConfig(projectDir);\n if (!configPath) return null;\n const { connector } = await loadConnectorFromPath(configPath);\n return connector.id;\n}\n\nexport async function run(argv: string[]): Promise<number> {\n const { values } = parseArgs({\n args: argv,\n options: {\n method: { type: \"string\", default: \"auto\" },\n scope: { type: \"string\", default: \"user\" },\n targets: { type: \"string\" },\n connector: { type: \"string\" },\n \"connector-id\": { type: \"string\" },\n project: { type: \"string\" },\n \"dry-run\": { type: \"boolean\", default: false },\n purge: { type: \"boolean\", default: false },\n },\n allowPositionals: false,\n });\n\n const method = parseUninstallMethod(values.method);\n if (method == null) {\n return fail(`invalid --method \"${values.method}\" (use auto|direct|marketplace)`);\n }\n\n const projectDir = values.project ?? process.cwd();\n\n const scope = parseScope(values.scope);\n if (scope == null) return fail(`invalid --scope \"${values.scope}\" (use user|project)`);\n\n const connectorId = await resolveConnectorId(\n values[\"connector-id\"],\n values.connector,\n projectDir,\n );\n if (!connectorId) {\n return fail(\n \"could not determine connector id. Pass --connector-id <id>, \" +\n \"--connector <path>, or run inside a project with an agent-connector config.\",\n );\n }\n\n const targets = parseTargets(values.targets);\n const dryRun = values[\"dry-run\"];\n\n // ── Explicit --method marketplace: every target goes to the marketplace path\n // (targets default to the recorded installs); framework purge runs here since\n // no direct pass follows.\n if (method === \"marketplace\") {\n const result = await uninstallViaMarketplace({\n connectorId,\n projectDir,\n dryRun,\n purge: values.purge,\n ...(targets ? { targets } : {}),\n });\n if (values.purge) purgeFrameworkState(connectorId, dryRun, result);\n print(renderInstallResult(result, \"uninstall\"));\n return result.changes.some((c) => c.action === \"warn\") ? 1 : 0;\n }\n\n // ── --method auto: partition the resolved targets by marketplace evidence.\n // (--method direct keeps every target on the adapter strip — today's path.)\n let marketplaceTargets: PlatformId[] = [];\n let directTargets: PlatformId[] = [];\n if (method === \"auto\") {\n const resolved = await resolveUninstallTargets(connectorId, targets, projectDir);\n // With no explicit --targets, recorded marketplace platforms are unioned\n // in: the state record IS the authority for what we installed, and host\n // detection can miss a host whose probe-able config dir was relocated.\n // An explicit --targets list is always respected as-is.\n const recorded = targets\n ? []\n : (Object.keys(readMarketplaceInstalls(connectorId)) as PlatformId[]);\n const candidates = [...new Set([...resolved, ...recorded])];\n marketplaceTargets = candidates.filter(\n (id) => marketplaceEvidence(connectorId, id) != null,\n );\n directTargets = resolved.filter((id) => !marketplaceTargets.includes(id));\n }\n\n // No marketplace evidence anywhere (or --method direct): exactly today's\n // single-orchestration path, byte-for-byte — zero behavior change for users\n // who never touched the marketplace method.\n if (marketplaceTargets.length === 0) {\n const result = await uninstallConnector({\n connectorId,\n scope,\n projectDir,\n dryRun,\n purge: values.purge,\n ...(targets ? { targets } : {}),\n });\n print(renderInstallResult(result, \"uninstall\"));\n return result.changes.some((c) => c.action === \"warn\") ? 1 : 0;\n }\n\n const results: InstallResult[] = [\n await uninstallViaMarketplace({\n connectorId,\n projectDir,\n targets: marketplaceTargets,\n dryRun,\n purge: values.purge,\n }),\n ];\n\n // The direct strip runs only for its partition (never both methods on one\n // target). When every target was marketplace-routed, --purge still runs the\n // framework purge (the marketplace records were just cleared, so it can\n // proceed to the connector record + home-bin).\n if (directTargets.length > 0) {\n results.push(\n await uninstallConnector({\n connectorId,\n scope,\n projectDir,\n dryRun,\n purge: values.purge,\n targets: directTargets,\n }),\n );\n } else if (values.purge) {\n const purgeResult: InstallResult = {\n connectorId,\n dryRun,\n changes: [],\n warnings: [],\n };\n if (dryRun) {\n // On a real run the marketplace records are removed BEFORE this purge;\n // calling purgeFrameworkState now would false-refuse on records that the\n // marketplace pass only PLANNED to remove. Report the plan instead.\n purgeResult.changes.push({\n platform: connectorId as PlatformId,\n action: \"remove\",\n detail:\n \"would purge framework state (connector record; home-bin when no connectors remain)\",\n });\n } else {\n purgeFrameworkState(connectorId, dryRun, purgeResult);\n }\n results.push(purgeResult);\n }\n\n const merged: InstallResult = {\n connectorId,\n dryRun,\n changes: results.flatMap((r) => r.changes),\n warnings: results.flatMap((r) => r.warnings),\n };\n print(renderInstallResult(merged, \"uninstall\"));\n return merged.changes.some((c) => c.action === \"warn\") ? 1 : 0;\n}\n"],"mappings":"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","names":[]}
@@ -1,22 +1,29 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ parseInstallMethod,
3
4
  resolveCliEntry,
4
- syncConnector
5
- } from "./chunk-Z2BVYKZL.js";
5
+ syncConnector,
6
+ upgradeViaMarketplace
7
+ } from "./chunk-QADSG2JY.js";
8
+ import "./chunk-WNREHWKL.js";
9
+ import "./chunk-44HUXXC6.js";
6
10
  import {
7
11
  fail,
8
12
  parseScope,
9
13
  parseTargets,
10
14
  print,
11
15
  renderInstallResult
12
- } from "./chunk-AKJGNTU3.js";
13
- import "./chunk-KHO5WNTP.js";
14
- import "./chunk-O2SBA5KR.js";
16
+ } from "./chunk-DS3LUFVN.js";
17
+ import "./chunk-KVAAFYRR.js";
18
+ import "./chunk-NJU275US.js";
15
19
  import {
16
20
  findConnectorConfig,
17
21
  loadConnectorFromPath
18
22
  } from "./chunk-3JCRUROU.js";
19
23
  import "./chunk-GSGDG2BV.js";
24
+ import "./chunk-OPXAP3AC.js";
25
+ import "./chunk-7L6ITC4T.js";
26
+ import "./chunk-MEH7GC7R.js";
20
27
  import "./chunk-N6HH7K6P.js";
21
28
  import {
22
29
  ensureHomeBin,
@@ -34,6 +41,7 @@ async function run(argv) {
34
41
  args: argv,
35
42
  options: {
36
43
  channel: { type: "string", default: "stable" },
44
+ method: { type: "string", default: "direct" },
37
45
  scope: { type: "string", default: "user" },
38
46
  targets: { type: "string" },
39
47
  connector: { type: "string" },
@@ -47,22 +55,32 @@ async function run(argv) {
47
55
  return fail(`invalid --channel "${channel}" (use stable|latest)`);
48
56
  }
49
57
  const ch = channel;
58
+ const method = parseInstallMethod(values.method);
59
+ if (method == null) {
60
+ return fail(`invalid --method "${values.method}" (use direct|marketplace)`);
61
+ }
50
62
  const scope = parseScope(values.scope);
51
63
  if (scope == null) return fail(`invalid --scope "${values.scope}" (use user|project)`);
64
+ if (method === "marketplace" && scope !== "user") {
65
+ return fail(
66
+ "--method marketplace supports --scope user only (project-scope plugin installs are deferred)"
67
+ );
68
+ }
52
69
  let hadWarn = false;
53
70
  const projectDir = values.project ?? process.cwd();
54
71
  const configPath = values.connector ?? findConnectorConfig(projectDir);
55
72
  if (configPath) {
56
73
  const { connector, modulePath } = await loadConnectorFromPath(configPath);
57
74
  const targets = parseTargets(values.targets);
58
- const result = await syncConnector({
75
+ const opts = {
59
76
  connector,
60
77
  modulePath,
61
78
  scope,
62
79
  projectDir,
63
80
  dryRun: values["dry-run"],
64
81
  ...targets ? { targets } : {}
65
- });
82
+ };
83
+ const result = method === "marketplace" ? await upgradeViaMarketplace(opts) : await syncConnector(opts);
66
84
  print(renderInstallResult(result, "upgrade"));
67
85
  if (result.changes.some((c) => c.action === "warn")) hadWarn = true;
68
86
  print("");
@@ -102,4 +120,4 @@ Refreshed home binary pointer: ${binPath}`);
102
120
  export {
103
121
  run
104
122
  };
105
- //# sourceMappingURL=upgrade-76BQZBMA.js.map
123
+ //# sourceMappingURL=upgrade-GJEB3ITY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/commands/upgrade.ts"],"sourcesContent":["/**\n * cli/commands/upgrade — bring an agent-connector install current.\n *\n * `upgrade` (aliases: `update`, `sync`) consolidates the two former verbs into\n * ONE the way npm/brew pair `install` + `upgrade`, so there is a single verb to\n * learn for \"make everything current\". It:\n *\n * 1. re-renders the connector's config into every target host idempotently\n * (identical entries report \"skip\"), exactly like the old `sync` — this is\n * also the self-heal path: run `upgrade` to repair a drifted install; then\n * 2. refreshes the stable home-bin pointer and prints managed (never-silent)\n * update guidance for the chosen channel, exactly like the old `update`.\n *\n * When no connector config is resolvable it still does step 2, so `upgrade`\n * works as a pure tool-refresh from anywhere. By design agent-connector NEVER\n * silently auto-updates (docs/ARCHITECTURE.md §3 R1).\n */\n\nimport { parseArgs } from \"node:util\";\n\nimport { resolveCliEntry, syncConnector } from \"../../core/installer.js\";\nimport { parseInstallMethod, upgradeViaMarketplace } from \"../../core/marketplace.js\";\nimport { findConnectorConfig, loadConnectorFromPath } from \"../../core/load-connector.js\";\nimport { ensureHomeBin, homeBinPath } from \"../../core/paths.js\";\nimport { fail, parseScope, parseTargets, print, renderInstallResult } from \"../app.js\";\n\ntype Channel = \"stable\" | \"latest\";\n\n/** Heuristic: does the running CLI live under an npm-style node_modules tree? */\nfunction looksNpmManaged(): boolean {\n const entry = resolveCliEntry().replace(/\\\\/g, \"/\");\n return entry.includes(\"/node_modules/\");\n}\n\nexport async function run(argv: string[]): Promise<number> {\n const { values } = parseArgs({\n args: argv,\n options: {\n channel: { type: \"string\", default: \"stable\" },\n method: { type: \"string\", default: \"direct\" },\n scope: { type: \"string\", default: \"user\" },\n targets: { type: \"string\" },\n connector: { type: \"string\" },\n project: { type: \"string\" },\n \"dry-run\": { type: \"boolean\", default: false },\n },\n allowPositionals: false,\n });\n\n const channel = values.channel;\n if (channel !== \"stable\" && channel !== \"latest\") {\n return fail(`invalid --channel \"${channel}\" (use stable|latest)`);\n }\n const ch: Channel = channel;\n\n const method = parseInstallMethod(values.method);\n if (method == null) {\n return fail(`invalid --method \"${values.method}\" (use direct|marketplace)`);\n }\n\n const scope = parseScope(values.scope);\n if (scope == null) return fail(`invalid --scope \"${values.scope}\" (use user|project)`);\n if (method === \"marketplace\" && scope !== \"user\") {\n return fail(\n \"--method marketplace supports --scope user only (project-scope plugin installs are deferred)\",\n );\n }\n\n let hadWarn = false;\n\n // ── Step 1: bring the connector's deploys current (former `sync`):\n // direct — idempotent re-render into every target host.\n // marketplace — re-stage the bundle + catalog in place, then drive the\n // host's update verb (claude `plugin update`, with a recorded\n // uninstall+install fallback); warns when connector.version is\n // unchanged since the recorded install (Claude caches a\n // versioned copy, so a same-version update silently no-ops).\n const projectDir = values.project ?? process.cwd();\n const configPath = values.connector ?? findConnectorConfig(projectDir);\n if (configPath) {\n const { connector, modulePath } = await loadConnectorFromPath(configPath);\n const targets = parseTargets(values.targets);\n const opts = {\n connector,\n modulePath,\n scope,\n projectDir,\n dryRun: values[\"dry-run\"],\n ...(targets ? { targets } : {}),\n };\n const result =\n method === \"marketplace\"\n ? await upgradeViaMarketplace(opts)\n : await syncConnector(opts);\n print(renderInstallResult(result, \"upgrade\"));\n if (result.changes.some((c) => c.action === \"warn\")) hadWarn = true;\n print(\"\");\n } else {\n print(\"upgrade: no connector config found — refreshing the tool only.\");\n print(\n \"(pass --connector <path> or run inside a project to also re-render host config.)\\n\",\n );\n }\n\n // ── Step 2: managed update guidance + home-bin pointer refresh (former `update`). ──\n print(\"agent-connector uses managed (explicit) updates — never silent\");\n print(\"auto-update — so one bad release can't break every project at once.\\n\");\n\n const dist = ch === \"stable\" ? \"latest\" : \"next\";\n if (looksNpmManaged()) {\n print(`To update the ${ch} channel, run:`);\n print(` npm i -g @ken-jo/agent-connector@${dist}`);\n } else {\n print(\n `This install does not look npm-managed. Update it the way you installed it,`,\n );\n print(`then re-run \\`agent-connector upgrade\\` to refresh the home pointer.`);\n print(`(npm installs would use: npm i -g @ken-jo/agent-connector@${dist})`);\n }\n\n // Refresh the stable home-bin pointer so hosts keep execing a working CLI.\n if (!values[\"dry-run\"]) {\n try {\n const binPath = ensureHomeBin(resolveCliEntry());\n print(`\\nRefreshed home binary pointer: ${binPath}`);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n print(`\\n[warn] could not refresh home binary at ${homeBinPath()}: ${message}`);\n return 1;\n }\n }\n\n return hadWarn ? 1 : 0;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkBA,SAAS,iBAAiB;AAW1B,SAAS,kBAA2B;AAClC,QAAM,QAAQ,gBAAgB,EAAE,QAAQ,OAAO,GAAG;AAClD,SAAO,MAAM,SAAS,gBAAgB;AACxC;AAEA,eAAsB,IAAI,MAAiC;AACzD,QAAM,EAAE,OAAO,IAAI,UAAU;AAAA,IAC3B,MAAM;AAAA,IACN,SAAS;AAAA,MACP,SAAS,EAAE,MAAM,UAAU,SAAS,SAAS;AAAA,MAC7C,QAAQ,EAAE,MAAM,UAAU,SAAS,SAAS;AAAA,MAC5C,OAAO,EAAE,MAAM,UAAU,SAAS,OAAO;AAAA,MACzC,SAAS,EAAE,MAAM,SAAS;AAAA,MAC1B,WAAW,EAAE,MAAM,SAAS;AAAA,MAC5B,SAAS,EAAE,MAAM,SAAS;AAAA,MAC1B,WAAW,EAAE,MAAM,WAAW,SAAS,MAAM;AAAA,IAC/C;AAAA,IACA,kBAAkB;AAAA,EACpB,CAAC;AAED,QAAM,UAAU,OAAO;AACvB,MAAI,YAAY,YAAY,YAAY,UAAU;AAChD,WAAO,KAAK,sBAAsB,OAAO,uBAAuB;AAAA,EAClE;AACA,QAAM,KAAc;AAEpB,QAAM,SAAS,mBAAmB,OAAO,MAAM;AAC/C,MAAI,UAAU,MAAM;AAClB,WAAO,KAAK,qBAAqB,OAAO,MAAM,4BAA4B;AAAA,EAC5E;AAEA,QAAM,QAAQ,WAAW,OAAO,KAAK;AACrC,MAAI,SAAS,KAAM,QAAO,KAAK,oBAAoB,OAAO,KAAK,sBAAsB;AACrF,MAAI,WAAW,iBAAiB,UAAU,QAAQ;AAChD,WAAO;AAAA,MACL;AAAA,IACF;AAAA,EACF;AAEA,MAAI,UAAU;AASd,QAAM,aAAa,OAAO,WAAW,QAAQ,IAAI;AACjD,QAAM,aAAa,OAAO,aAAa,oBAAoB,UAAU;AACrE,MAAI,YAAY;AACd,UAAM,EAAE,WAAW,WAAW,IAAI,MAAM,sBAAsB,UAAU;AACxE,UAAM,UAAU,aAAa,OAAO,OAAO;AAC3C,UAAM,OAAO;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ,OAAO,SAAS;AAAA,MACxB,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC/B;AACA,UAAM,SACJ,WAAW,gBACP,MAAM,sBAAsB,IAAI,IAChC,MAAM,cAAc,IAAI;AAC9B,UAAM,oBAAoB,QAAQ,SAAS,CAAC;AAC5C,QAAI,OAAO,QAAQ,KAAK,CAAC,MAAM,EAAE,WAAW,MAAM,EAAG,WAAU;AAC/D,UAAM,EAAE;AAAA,EACV,OAAO;AACL,UAAM,qEAAgE;AACtE;AAAA,MACE;AAAA,IACF;AAAA,EACF;AAGA,QAAM,qEAAgE;AACtE,QAAM,4EAAuE;AAE7E,QAAM,OAAO,OAAO,WAAW,WAAW;AAC1C,MAAI,gBAAgB,GAAG;AACrB,UAAM,iBAAiB,EAAE,gBAAgB;AACzC,UAAM,sCAAsC,IAAI,EAAE;AAAA,EACpD,OAAO;AACL;AAAA,MACE;AAAA,IACF;AACA,UAAM,sEAAsE;AAC5E,UAAM,6DAA6D,IAAI,GAAG;AAAA,EAC5E;AAGA,MAAI,CAAC,OAAO,SAAS,GAAG;AACtB,QAAI;AACF,YAAM,UAAU,cAAc,gBAAgB,CAAC;AAC/C,YAAM;AAAA,iCAAoC,OAAO,EAAE;AAAA,IACrD,SAAS,KAAK;AACZ,YAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,YAAM;AAAA,0CAA6C,YAAY,CAAC,KAAK,OAAO,EAAE;AAC9E,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO,UAAU,IAAI;AACvB;","names":[]}
@@ -11,7 +11,7 @@ import {
11
11
  import {
12
12
  fail,
13
13
  print
14
- } from "./chunk-AKJGNTU3.js";
14
+ } from "./chunk-DS3LUFVN.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-G3GSCX23.js.map
324
+ //# sourceMappingURL=usage-2BJLM3GJ.js.map
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runUsageEvent
4
- } from "./chunk-4ML7SZ7R.js";
4
+ } from "./chunk-ZAM4M7LI.js";
5
5
  import "./chunk-BCHWFTV4.js";
6
- import "./chunk-KHO5WNTP.js";
7
- import "./chunk-WCETQWWK.js";
8
- import "./chunk-O2SBA5KR.js";
6
+ import "./chunk-OP4KBXUO.js";
7
+ import "./chunk-KVAAFYRR.js";
8
+ import "./chunk-NJU275US.js";
9
9
  import "./chunk-3JCRUROU.js";
10
10
  import "./chunk-GSGDG2BV.js";
11
11
  import "./chunk-MEH7GC7R.js";
@@ -46,4 +46,4 @@ async function run(argv) {
46
46
  export {
47
47
  run
48
48
  };
49
- //# sourceMappingURL=usage-event-QUTMNBS5.js.map
49
+ //# sourceMappingURL=usage-event-472X3DOY.js.map
@@ -5,7 +5,9 @@ import {
5
5
  import {
6
6
  BaseAdapter
7
7
  } from "./chunk-PD4VFEBY.js";
8
- import "./chunk-7L6ITC4T.js";
8
+ import {
9
+ renderSkillMd
10
+ } from "./chunk-7L6ITC4T.js";
9
11
  import {
10
12
  buildServeWrapperCommand,
11
13
  isHomeBinHookCommand,
@@ -42,7 +44,10 @@ var WarpAdapter = class extends BaseAdapter {
42
44
  canModifyOutput: false,
43
45
  canInjectSessionContext: false,
44
46
  // Warp registers stdio, SSE, and Streamable HTTP MCP servers.
45
- transports: ["stdio", "sse", "http"]
47
+ transports: ["stdio", "sse", "http"],
48
+ // Skills: Warp reads SKILL.md from .agents/skills/<name>/SKILL.md (project
49
+ // scope only; user-scope skills dir is not documented for Warp).
50
+ supportsSkills: true
46
51
  };
47
52
  // ── Detection ────────────────────────────────────────────────────────────
48
53
  detectInstalled(projectDir) {
@@ -160,6 +165,79 @@ var WarpAdapter = class extends BaseAdapter {
160
165
  if (!env || Object.keys(env).length === 0) return void 0;
161
166
  return resolveEnvRefsDeep({ ...env });
162
167
  }
168
+ // ── Skills surface ───────────────────────────────────────────────────────
169
+ // Warp reads SKILL.md files from `.agents/skills/<name>/SKILL.md`.
170
+ // Skills double as slash-commands in Warp's UI (/name).
171
+ // Only project scope is documented; user-scope install skips with a warn
172
+ // (Warp Drive manages user rules in the cloud — no local user skills dir).
173
+ skillsDir(ctx) {
174
+ return join(ctx.projectDir, ".agents", "skills");
175
+ }
176
+ skillDir(ctx, name) {
177
+ return join(this.skillsDir(ctx), name);
178
+ }
179
+ installSkills(ctx) {
180
+ const { connector } = ctx;
181
+ if (connector.platforms[HOST]?.skills === false) {
182
+ return [{ platform: this.id, action: "skip", detail: "skills disabled for warp" }];
183
+ }
184
+ if (connector.skills.length === 0) {
185
+ return [{ platform: this.id, action: "skip", detail: "connector declares no skills" }];
186
+ }
187
+ if (ctx.scope !== "project") {
188
+ return [
189
+ {
190
+ platform: this.id,
191
+ action: "warn",
192
+ detail: "warp skills are project-scoped only (no documented user-scope skills dir); skipped"
193
+ }
194
+ ];
195
+ }
196
+ const changes = [];
197
+ for (const skill of connector.skills) {
198
+ const dir = this.skillDir(ctx, skill.name);
199
+ changes.push(
200
+ this.writeContentFile(join(dir, "SKILL.md"), this.renderSkill(skill), ctx.dryRun)
201
+ );
202
+ for (const [rel, contents] of Object.entries(skill.resources ?? {})) {
203
+ const target = this.resolveWithin(dir, rel);
204
+ if (target === null) {
205
+ changes.push({
206
+ platform: this.id,
207
+ action: "warn",
208
+ detail: `skill resource "${rel}" escapes the skill dir; skipped`
209
+ });
210
+ continue;
211
+ }
212
+ changes.push(this.writeContentFile(target, contents, ctx.dryRun));
213
+ }
214
+ }
215
+ return changes;
216
+ }
217
+ uninstallSkills(ctx) {
218
+ const { connector } = ctx;
219
+ if (connector.skills.length === 0) {
220
+ return [{ platform: this.id, action: "skip", detail: "connector declares no skills" }];
221
+ }
222
+ if (ctx.scope !== "project") {
223
+ return [{ platform: this.id, action: "skip", detail: "warp skills are project-scoped only" }];
224
+ }
225
+ const changes = [];
226
+ for (const skill of connector.skills) {
227
+ const dir = this.skillDir(ctx, skill.name);
228
+ changes.push(this.removeContentFile(join(dir, "SKILL.md"), ctx.dryRun));
229
+ for (const rel of Object.keys(skill.resources ?? {})) {
230
+ const target = this.resolveWithin(dir, rel);
231
+ if (target === null) continue;
232
+ changes.push(this.removeContentFile(target, ctx.dryRun));
233
+ }
234
+ changes.push(this.removeDirIfEmpty(dir, ctx.dryRun));
235
+ }
236
+ return changes;
237
+ }
238
+ renderSkill(skill) {
239
+ return renderSkillMd(skill);
240
+ }
163
241
  // ── Hooks (unavailable — Warp is mcp-only) ───────────────────────────────
164
242
  installHooks(_ctx) {
165
243
  return [
@@ -224,4 +302,4 @@ export {
224
302
  adapter,
225
303
  warp_default as default
226
304
  };
227
- //# sourceMappingURL=warp-LLOSXR7A.js.map
305
+ //# sourceMappingURL=warp-X6MB67NT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/adapters/warp/index.ts"],"sourcesContent":["/**\n * adapters/warp — Warp (Warp.dev) platform adapter for agent-connector.\n *\n * Warp is an **mcp-only** host: it has NO lifecycle hook system (open FR #7834),\n * and MCP *is* its extensibility mechanism (\"MCP servers act as plugins\"). This\n * adapter therefore installs only the MCP server and reports hooks as\n * unavailable — it is the reference path that validates the `mcp-only` paradigm\n * end-to-end through the framework.\n *\n * MCP config (report §2 / §5.3):\n * - user scope → ~/.warp/.mcp.json\n * - project scope → <projectDir>/.warp/.mcp.json\n * Both are JSON, root key \"mcpServers\", and are the SAME file used for the\n * (non-existent) hook registration — there is no separate hook file here.\n *\n * QUIRK: a stdio server entry uses `working_directory` (NOT `cwd`) for its\n * working directory. Everything else mirrors the Claude/Cursor stdio shape.\n *\n * Warp documents no native `${env:VAR}` interpolation token, so env/header/url\n * refs are resolved to literals at install time (the no-native-token path).\n *\n * Skills surface: Warp reads SKILL.md files from `.agents/skills/<name>/SKILL.md`\n * (project scope). Skills double as slash-commands in Warp's UI — a skill named\n * \"pdf-tools\" is invocable as `/pdf-tools`. No user-scope skills dir is\n * documented for Warp; user-scope install reports a skip-warn.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport { BaseAdapter } from \"../base.js\";\nimport type { Adapter, InstallContext, MemoryTarget } from \"../spi.js\";\nimport type {\n ChangeRecord,\n DetectedPlatform,\n HealthCheck,\n HookParadigm,\n PlatformCapabilities,\n PlatformId,\n ServerDef,\n SkillDef,\n Transport,\n} from \"../../core/types.js\";\nimport { resolveEnvRefsDeep } from \"../../core/interpolate.js\";\nimport {\n buildServeWrapperCommand,\n isHomeBinHookCommand,\n shouldWrapForTelemetry,\n} from \"../../core/spawn.js\";\nimport { renderSkillMd } from \"../claude-code/render.js\";\n\nconst HOST: PlatformId = \"warp\";\nconst MCP_ROOT_KEY = \"mcpServers\";\n\n/**\n * Native MCP server entry shapes Warp accepts under `mcpServers`.\n * Note the working-directory key: Warp uses `working_directory`, not `cwd`.\n */\ninterface WarpStdioServer {\n command: string;\n args?: string[];\n env?: Record<string, string>;\n working_directory?: string;\n}\ninterface WarpHttpServer {\n url: string;\n headers?: Record<string, string>;\n}\n\nexport class WarpAdapter extends BaseAdapter implements Adapter {\n readonly id: PlatformId = HOST;\n readonly name = \"Warp\";\n readonly paradigm: HookParadigm = \"mcp-only\";\n\n readonly capabilities: PlatformCapabilities = {\n // Memory surface: AGENTS.md-first managed block. memoryTargets below probes\n // for a legacy WARP.md (it takes priority over AGENTS.md in the same dir);\n // user-scope rules live in Warp Drive (cloud) → standard skip-warn.\n supportsMemory: true,\n // Warp has no lifecycle hook system — every hook capability is false.\n preToolUse: false,\n postToolUse: false,\n preCompact: false,\n sessionStart: false,\n sessionEnd: false,\n userPromptSubmit: false,\n stop: false,\n notification: false,\n canModifyArgs: false,\n canModifyOutput: false,\n canInjectSessionContext: false,\n // Warp registers stdio, SSE, and Streamable HTTP MCP servers.\n transports: [\"stdio\", \"sse\", \"http\"],\n // Skills: Warp reads SKILL.md from .agents/skills/<name>/SKILL.md (project\n // scope only; user-scope skills dir is not documented for Warp).\n supportsSkills: true,\n };\n\n // ── Detection ────────────────────────────────────────────────────────────\n\n detectInstalled(projectDir: string): DetectedPlatform {\n const userDir = join(homedir(), \".warp\");\n const userMcp = join(userDir, \".mcp.json\");\n const projectMcp = join(projectDir, \".warp\", \".mcp.json\");\n const installed = existsSync(userDir) || existsSync(userMcp) || existsSync(projectMcp);\n return {\n id: this.id,\n name: this.name,\n installed,\n paradigm: this.paradigm,\n capabilities: this.capabilities,\n configPath: userMcp,\n scope: \"user\",\n reason: installed\n ? `found Warp config under ${userDir}`\n : `no Warp config at ${userDir}`,\n confidence: installed ? \"high\" : \"low\",\n };\n }\n\n // ── Memory surface: WARP.md shadow probe (project scope) ────────────────\n // AGENTS.md is Warp's DEFAULT project rules file, but a legacy WARP.md in\n // the same directory still takes priority — a block in AGENTS.md beside an\n // existing WARP.md would be shadowed, so the probe targets the file Warp\n // actually reads. User scope has no row in the base map (Warp Drive rules\n // are cloud-managed) → the standard skip-warn.\n protected override memoryTargets(ctx: InstallContext): MemoryTarget[] {\n if (this.memoryOverride(ctx)?.path || ctx.scope !== \"project\") {\n return super.memoryTargets(ctx);\n }\n const warpMd = join(ctx.projectDir, \"WARP.md\");\n if (existsSync(warpMd)) {\n return [\n { path: warpMd, reason: \"WARP.md takes priority over AGENTS.md in the same dir on warp\" },\n ];\n }\n return [\n { path: join(ctx.projectDir, \"AGENTS.md\"), reason: \"AGENTS.md (warp's default rules file)\" },\n ];\n }\n\n // ── Native paths ─────────────────────────────────────────────────────────\n\n getConfigDir(ctx: InstallContext): string {\n return ctx.scope === \"project\"\n ? join(ctx.projectDir, \".warp\")\n : join(homedir(), \".warp\");\n }\n\n getServerConfigPath(ctx: InstallContext): string {\n return join(this.getConfigDir(ctx), \".mcp.json\");\n }\n\n /**\n * Warp has no hook file — hooks are not a thing here. The hook \"config path\"\n * is the same .mcp.json so the generic doctor/backup behave sensibly.\n */\n getHookConfigPath(ctx: InstallContext): string {\n return this.getServerConfigPath(ctx);\n }\n\n // ── MCP server install / uninstall ───────────────────────────────────────\n\n installServer(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n const override = connector.platforms[HOST]?.server;\n if (!connector.server || override === false) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail: connector.server\n ? \"server registration disabled for warp\"\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 Warp's native mcpServers entry. */\n private renderServerEntry(\n ctx: InstallContext,\n server: ServerDef,\n ): WarpStdioServer | WarpHttpServer {\n const transport: Transport = server.transport;\n\n if (transport === \"stdio\") {\n let command = server.command ?? \"\";\n let args = [...(server.args ?? [])];\n\n // Transparent telemetry wrapping: route the real command through\n // `<homeBin> serve --connector <id> -- <command> <args...>`.\n if (shouldWrapForTelemetry(server, ctx.connector.telemetry)) {\n const wrapped = buildServeWrapperCommand(\n ctx.homeBinPath,\n ctx.connector.id,\n command,\n args,\n ctx.scope,\n this.id,\n );\n command = wrapped.command;\n args = wrapped.args;\n }\n\n // Warp has no documented native interpolation token, so resolve every\n // ${env:VAR} to a literal at install time.\n const entry: WarpStdioServer = { 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 // QUIRK: Warp keys the working directory as `working_directory`, not `cwd`.\n if (server.cwd) entry.working_directory = resolveEnvRefsDeep(server.cwd);\n return entry;\n }\n\n // sse / http (and any other remote transport) — Warp registers a URL.\n const entry: WarpHttpServer = { url: 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. Warp documents no native interpolation token, so\n * 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 // ── Skills surface ───────────────────────────────────────────────────────\n // Warp reads SKILL.md files from `.agents/skills/<name>/SKILL.md`.\n // Skills double as slash-commands in Warp's UI (/name).\n // Only project scope is documented; user-scope install skips with a warn\n // (Warp Drive manages user rules in the cloud — no local user skills dir).\n\n private skillsDir(ctx: InstallContext): string {\n return join(ctx.projectDir, \".agents\", \"skills\");\n }\n\n private skillDir(ctx: InstallContext, name: string): string {\n return join(this.skillsDir(ctx), name);\n }\n\n override installSkills(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.platforms[HOST]?.skills === false) {\n return [{ platform: this.id, action: \"skip\", detail: \"skills disabled for warp\" }];\n }\n if (connector.skills.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\n }\n if (ctx.scope !== \"project\") {\n return [\n {\n platform: this.id,\n action: \"warn\",\n detail: \"warp skills are project-scoped only (no documented user-scope skills dir); skipped\",\n },\n ];\n }\n const changes: ChangeRecord[] = [];\n for (const skill of connector.skills) {\n const dir = this.skillDir(ctx, skill.name);\n changes.push(\n this.writeContentFile(join(dir, \"SKILL.md\"), this.renderSkill(skill), ctx.dryRun),\n );\n 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 if (ctx.scope !== \"project\") {\n return [{ platform: this.id, action: \"skip\", detail: \"warp skills are project-scoped only\" }];\n }\n const changes: ChangeRecord[] = [];\n for (const skill of connector.skills) {\n const dir = this.skillDir(ctx, skill.name);\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;\n changes.push(this.removeContentFile(target, ctx.dryRun));\n }\n changes.push(this.removeDirIfEmpty(dir, ctx.dryRun));\n }\n return changes;\n }\n\n private renderSkill(skill: SkillDef): string {\n return renderSkillMd(skill);\n }\n\n // ── Hooks (unavailable — Warp is mcp-only) ───────────────────────────────\n\n installHooks(_ctx: InstallContext): ChangeRecord[] {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail: \"hooks unavailable (Warp is mcp-only)\",\n },\n ];\n }\n\n uninstallHooks(_ctx: InstallContext): ChangeRecord[] {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail: \"hooks unavailable (Warp is mcp-only)\",\n },\n ];\n }\n\n /**\n * True when a hook command references our home binary AND this connector id\n * (anchored so a shared-prefix id can't collide — see isHomeBinHookCommand).\n * Warp installs no hooks, but this guard keeps any future shared-file edit\n * from removing another connector's entries.\n */\n private isOurCommand(command: string | undefined, ctx: InstallContext): boolean {\n return isHomeBinHookCommand(command, ctx.homeBinPath, ctx.connector.id);\n }\n\n // ── Diagnostics ──────────────────────────────────────────────────────────\n\n override getHealthChecks(ctx: InstallContext): readonly HealthCheck[] {\n const mcpPath = this.getServerConfigPath(ctx);\n const connectorId = ctx.connector.id;\n return [\n {\n name: `${this.name}: .mcp.json present`,\n check: () =>\n existsSync(mcpPath)\n ? { status: \"OK\", detail: mcpPath }\n : { status: \"FAIL\", detail: `not found: ${mcpPath}` },\n },\n {\n name: `${this.name}: server entry registered`,\n check: () => {\n // Only assert what the connector declares: a server-less connector —\n // e.g. a catalog-only bundle of agents/skills/commands — never writes\n // an mcpServers entry, so its absence is healthy.\n if (!ctx.connector.server) {\n return { status: \"OK\", detail: \"no MCP server declared\" };\n }\n const cfg = this.readJson<{ [k: string]: Record<string, unknown> }>(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 }\n}\n\nexport const adapter = new WarpAdapter();\nexport default adapter;\n"],"mappings":"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","names":["entry"]}
@@ -5,7 +5,9 @@ import {
5
5
  import {
6
6
  BaseAdapter
7
7
  } from "./chunk-PD4VFEBY.js";
8
- import "./chunk-7L6ITC4T.js";
8
+ import {
9
+ renderSkillMd
10
+ } from "./chunk-7L6ITC4T.js";
9
11
  import {
10
12
  buildServeWrapperCommand,
11
13
  shouldWrapForTelemetry
@@ -42,7 +44,10 @@ var ZedAdapter = class _ZedAdapter extends BaseAdapter {
42
44
  canModifyOutput: false,
43
45
  canInjectSessionContext: false,
44
46
  // Zed registers stdio context servers; remote URLs are also accepted.
45
- transports: ["stdio", "sse", "http"]
47
+ transports: ["stdio", "sse", "http"],
48
+ // Skills: Zed reads SKILL.md from .agents/skills/<name>/SKILL.md (project)
49
+ // and ~/.agents/skills/<name>/SKILL.md (user).
50
+ supportsSkills: true
46
51
  };
47
52
  // ── Detection ────────────────────────────────────────────────────────────
48
53
  detectInstalled(projectDir) {
@@ -201,6 +206,66 @@ var ZedAdapter = class _ZedAdapter extends BaseAdapter {
201
206
  if (!env || Object.keys(env).length === 0) return void 0;
202
207
  return resolveEnvRefsDeep({ ...env });
203
208
  }
209
+ // ── Skills surface ───────────────────────────────────────────────────────
210
+ // Zed reads SKILL.md files from:
211
+ // project scope → <projectDir>/.agents/skills/<name>/SKILL.md
212
+ // user scope → ~/.agents/skills/<name>/SKILL.md
213
+ skillsDir(ctx) {
214
+ return ctx.scope === "project" ? join(ctx.projectDir, ".agents", "skills") : join(homedir(), ".agents", "skills");
215
+ }
216
+ skillDir(ctx, name) {
217
+ return join(this.skillsDir(ctx), name);
218
+ }
219
+ installSkills(ctx) {
220
+ const { connector } = ctx;
221
+ if (connector.platforms[HOST]?.skills === false) {
222
+ return [{ platform: this.id, action: "skip", detail: "skills disabled for zed" }];
223
+ }
224
+ if (connector.skills.length === 0) {
225
+ return [{ platform: this.id, action: "skip", detail: "connector declares no skills" }];
226
+ }
227
+ const changes = [];
228
+ for (const skill of connector.skills) {
229
+ const dir = this.skillDir(ctx, skill.name);
230
+ changes.push(
231
+ this.writeContentFile(join(dir, "SKILL.md"), this.renderSkill(skill), ctx.dryRun)
232
+ );
233
+ for (const [rel, contents] of Object.entries(skill.resources ?? {})) {
234
+ const target = this.resolveWithin(dir, rel);
235
+ if (target === null) {
236
+ changes.push({
237
+ platform: this.id,
238
+ action: "warn",
239
+ detail: `skill resource "${rel}" escapes the skill dir; skipped`
240
+ });
241
+ continue;
242
+ }
243
+ changes.push(this.writeContentFile(target, contents, ctx.dryRun));
244
+ }
245
+ }
246
+ return changes;
247
+ }
248
+ uninstallSkills(ctx) {
249
+ const { connector } = ctx;
250
+ if (connector.skills.length === 0) {
251
+ return [{ platform: this.id, action: "skip", detail: "connector declares no skills" }];
252
+ }
253
+ const changes = [];
254
+ for (const skill of connector.skills) {
255
+ const dir = this.skillDir(ctx, skill.name);
256
+ changes.push(this.removeContentFile(join(dir, "SKILL.md"), ctx.dryRun));
257
+ for (const rel of Object.keys(skill.resources ?? {})) {
258
+ const target = this.resolveWithin(dir, rel);
259
+ if (target === null) continue;
260
+ changes.push(this.removeContentFile(target, ctx.dryRun));
261
+ }
262
+ changes.push(this.removeDirIfEmpty(dir, ctx.dryRun));
263
+ }
264
+ return changes;
265
+ }
266
+ renderSkill(skill) {
267
+ return renderSkillMd(skill);
268
+ }
204
269
  // ── Hooks (unavailable — Zed is mcp-only) ────────────────────────────────
205
270
  installHooks(_ctx) {
206
271
  return [
@@ -256,4 +321,4 @@ export {
256
321
  adapter,
257
322
  zed_default as default
258
323
  };
259
- //# sourceMappingURL=zed-HYOITK7F.js.map
324
+ //# sourceMappingURL=zed-NTCYW4V2.js.map