@x-code-cli/core 0.2.9 → 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 (255) hide show
  1. package/dist/agent/compression.d.ts +12 -2
  2. package/dist/agent/compression.d.ts.map +1 -1
  3. package/dist/agent/compression.js +51 -2
  4. package/dist/agent/compression.js.map +1 -1
  5. package/dist/agent/file-ingest.js +2 -2
  6. package/dist/agent/file-ingest.js.map +1 -1
  7. package/dist/agent/loop-state.d.ts +3 -2
  8. package/dist/agent/loop-state.d.ts.map +1 -1
  9. package/dist/agent/loop-state.js.map +1 -1
  10. package/dist/agent/loop.d.ts.map +1 -1
  11. package/dist/agent/loop.js +140 -9
  12. package/dist/agent/loop.js.map +1 -1
  13. package/dist/agent/memory-extractor.js +5 -5
  14. package/dist/agent/memory-extractor.js.map +1 -1
  15. package/dist/agent/plan-storage.js +1 -1
  16. package/dist/agent/plan-storage.js.map +1 -1
  17. package/dist/agent/sub-agents/index.d.ts +2 -1
  18. package/dist/agent/sub-agents/index.d.ts.map +1 -1
  19. package/dist/agent/sub-agents/index.js +1 -1
  20. package/dist/agent/sub-agents/index.js.map +1 -1
  21. package/dist/agent/sub-agents/loader.d.ts +13 -3
  22. package/dist/agent/sub-agents/loader.d.ts.map +1 -1
  23. package/dist/agent/sub-agents/loader.js +36 -9
  24. package/dist/agent/sub-agents/loader.js.map +1 -1
  25. package/dist/agent/sub-agents/registry.d.ts +18 -1
  26. package/dist/agent/sub-agents/registry.d.ts.map +1 -1
  27. package/dist/agent/sub-agents/registry.js +38 -5
  28. package/dist/agent/sub-agents/registry.js.map +1 -1
  29. package/dist/agent/sub-agents/runner.d.ts.map +1 -1
  30. package/dist/agent/sub-agents/runner.js +45 -1
  31. package/dist/agent/sub-agents/runner.js.map +1 -1
  32. package/dist/agent/sub-agents/types.d.ts +4 -1
  33. package/dist/agent/sub-agents/types.d.ts.map +1 -1
  34. package/dist/agent/system-prompt.d.ts +21 -0
  35. package/dist/agent/system-prompt.d.ts.map +1 -1
  36. package/dist/agent/system-prompt.js +68 -2
  37. package/dist/agent/system-prompt.js.map +1 -1
  38. package/dist/agent/tool-execution.d.ts.map +1 -1
  39. package/dist/agent/tool-execution.js +220 -1
  40. package/dist/agent/tool-execution.js.map +1 -1
  41. package/dist/commands/index.d.ts +6 -0
  42. package/dist/commands/index.d.ts.map +1 -0
  43. package/dist/commands/index.js +3 -0
  44. package/dist/commands/index.js.map +1 -0
  45. package/dist/commands/loader.d.ts +13 -0
  46. package/dist/commands/loader.d.ts.map +1 -0
  47. package/dist/commands/loader.js +93 -0
  48. package/dist/commands/loader.js.map +1 -0
  49. package/dist/commands/registry.d.ts +44 -0
  50. package/dist/commands/registry.d.ts.map +1 -0
  51. package/dist/commands/registry.js +102 -0
  52. package/dist/commands/registry.js.map +1 -0
  53. package/dist/commands/types.d.ts +23 -0
  54. package/dist/commands/types.d.ts.map +1 -0
  55. package/dist/commands/types.js +26 -0
  56. package/dist/commands/types.js.map +1 -0
  57. package/dist/config/index.d.ts +9 -0
  58. package/dist/config/index.d.ts.map +1 -1
  59. package/dist/config/index.js +12 -10
  60. package/dist/config/index.js.map +1 -1
  61. package/dist/hooks/bus.d.ts +54 -0
  62. package/dist/hooks/bus.d.ts.map +1 -0
  63. package/dist/hooks/bus.js +165 -0
  64. package/dist/hooks/bus.js.map +1 -0
  65. package/dist/hooks/config-schema.d.ts +854 -0
  66. package/dist/hooks/config-schema.d.ts.map +1 -0
  67. package/dist/hooks/config-schema.js +79 -0
  68. package/dist/hooks/config-schema.js.map +1 -0
  69. package/dist/hooks/executor.d.ts +16 -0
  70. package/dist/hooks/executor.d.ts.map +1 -0
  71. package/dist/hooks/executor.js +183 -0
  72. package/dist/hooks/executor.js.map +1 -0
  73. package/dist/hooks/index.d.ts +10 -0
  74. package/dist/hooks/index.d.ts.map +1 -0
  75. package/dist/hooks/index.js +6 -0
  76. package/dist/hooks/index.js.map +1 -0
  77. package/dist/hooks/registry.d.ts +23 -0
  78. package/dist/hooks/registry.d.ts.map +1 -0
  79. package/dist/hooks/registry.js +49 -0
  80. package/dist/hooks/registry.js.map +1 -0
  81. package/dist/hooks/types.d.ts +165 -0
  82. package/dist/hooks/types.d.ts.map +1 -0
  83. package/dist/hooks/types.js +25 -0
  84. package/dist/hooks/types.js.map +1 -0
  85. package/dist/hooks/variables.d.ts +22 -0
  86. package/dist/hooks/variables.d.ts.map +1 -0
  87. package/dist/hooks/variables.js +80 -0
  88. package/dist/hooks/variables.js.map +1 -0
  89. package/dist/index.d.ts +56 -1
  90. package/dist/index.d.ts.map +1 -1
  91. package/dist/index.js +37 -1
  92. package/dist/index.js.map +1 -1
  93. package/dist/knowledge/auto-memory.d.ts +1 -1
  94. package/dist/knowledge/auto-memory.d.ts.map +1 -1
  95. package/dist/knowledge/auto-memory.js +10 -10
  96. package/dist/knowledge/auto-memory.js.map +1 -1
  97. package/dist/knowledge/loader.js +12 -12
  98. package/dist/knowledge/loader.js.map +1 -1
  99. package/dist/mcp/arg-parser.d.ts +49 -0
  100. package/dist/mcp/arg-parser.d.ts.map +1 -0
  101. package/dist/mcp/arg-parser.js +357 -0
  102. package/dist/mcp/arg-parser.js.map +1 -0
  103. package/dist/mcp/client.d.ts +73 -0
  104. package/dist/mcp/client.d.ts.map +1 -0
  105. package/dist/mcp/client.js +376 -0
  106. package/dist/mcp/client.js.map +1 -0
  107. package/dist/mcp/config-schema.d.ts +64 -0
  108. package/dist/mcp/config-schema.d.ts.map +1 -0
  109. package/dist/mcp/config-schema.js +86 -0
  110. package/dist/mcp/config-schema.js.map +1 -0
  111. package/dist/mcp/config-writer.d.ts +41 -0
  112. package/dist/mcp/config-writer.d.ts.map +1 -0
  113. package/dist/mcp/config-writer.js +138 -0
  114. package/dist/mcp/config-writer.js.map +1 -0
  115. package/dist/mcp/env-safety.d.ts +12 -0
  116. package/dist/mcp/env-safety.d.ts.map +1 -0
  117. package/dist/mcp/env-safety.js +80 -0
  118. package/dist/mcp/env-safety.js.map +1 -0
  119. package/dist/mcp/expand-env.d.ts +14 -0
  120. package/dist/mcp/expand-env.d.ts.map +1 -0
  121. package/dist/mcp/expand-env.js +52 -0
  122. package/dist/mcp/expand-env.js.map +1 -0
  123. package/dist/mcp/loader.d.ts +81 -0
  124. package/dist/mcp/loader.d.ts.map +1 -0
  125. package/dist/mcp/loader.js +223 -0
  126. package/dist/mcp/loader.js.map +1 -0
  127. package/dist/mcp/name-mangling.d.ts +11 -0
  128. package/dist/mcp/name-mangling.d.ts.map +1 -0
  129. package/dist/mcp/name-mangling.js +82 -0
  130. package/dist/mcp/name-mangling.js.map +1 -0
  131. package/dist/mcp/oauth/callback-server.d.ts +25 -0
  132. package/dist/mcp/oauth/callback-server.d.ts.map +1 -0
  133. package/dist/mcp/oauth/callback-server.js +118 -0
  134. package/dist/mcp/oauth/callback-server.js.map +1 -0
  135. package/dist/mcp/oauth/provider.d.ts +80 -0
  136. package/dist/mcp/oauth/provider.d.ts.map +1 -0
  137. package/dist/mcp/oauth/provider.js +292 -0
  138. package/dist/mcp/oauth/provider.js.map +1 -0
  139. package/dist/mcp/oauth/token-storage.d.ts +42 -0
  140. package/dist/mcp/oauth/token-storage.d.ts.map +1 -0
  141. package/dist/mcp/oauth/token-storage.js +121 -0
  142. package/dist/mcp/oauth/token-storage.js.map +1 -0
  143. package/dist/mcp/permissions.d.ts +28 -0
  144. package/dist/mcp/permissions.d.ts.map +1 -0
  145. package/dist/mcp/permissions.js +105 -0
  146. package/dist/mcp/permissions.js.map +1 -0
  147. package/dist/mcp/registry.d.ts +150 -0
  148. package/dist/mcp/registry.d.ts.map +1 -0
  149. package/dist/mcp/registry.js +334 -0
  150. package/dist/mcp/registry.js.map +1 -0
  151. package/dist/mcp/resources.d.ts +7 -0
  152. package/dist/mcp/resources.d.ts.map +1 -0
  153. package/dist/mcp/resources.js +40 -0
  154. package/dist/mcp/resources.js.map +1 -0
  155. package/dist/mcp/tool-bridge.d.ts +16 -0
  156. package/dist/mcp/tool-bridge.d.ts.map +1 -0
  157. package/dist/mcp/tool-bridge.js +56 -0
  158. package/dist/mcp/tool-bridge.js.map +1 -0
  159. package/dist/mcp/trust.d.ts +31 -0
  160. package/dist/mcp/trust.d.ts.map +1 -0
  161. package/dist/mcp/trust.js +103 -0
  162. package/dist/mcp/trust.js.map +1 -0
  163. package/dist/mcp/types.d.ts +73 -0
  164. package/dist/mcp/types.d.ts.map +1 -0
  165. package/dist/mcp/types.js +13 -0
  166. package/dist/mcp/types.js.map +1 -0
  167. package/dist/permissions/session-store.d.ts +13 -2
  168. package/dist/permissions/session-store.d.ts.map +1 -1
  169. package/dist/permissions/session-store.js +264 -62
  170. package/dist/permissions/session-store.js.map +1 -1
  171. package/dist/plugins/consent.d.ts +87 -0
  172. package/dist/plugins/consent.d.ts.map +1 -0
  173. package/dist/plugins/consent.js +181 -0
  174. package/dist/plugins/consent.js.map +1 -0
  175. package/dist/plugins/enable-state.d.ts +34 -0
  176. package/dist/plugins/enable-state.d.ts.map +1 -0
  177. package/dist/plugins/enable-state.js +159 -0
  178. package/dist/plugins/enable-state.js.map +1 -0
  179. package/dist/plugins/installer.d.ts +64 -0
  180. package/dist/plugins/installer.d.ts.map +1 -0
  181. package/dist/plugins/installer.js +416 -0
  182. package/dist/plugins/installer.js.map +1 -0
  183. package/dist/plugins/integration.d.ts +91 -0
  184. package/dist/plugins/integration.d.ts.map +1 -0
  185. package/dist/plugins/integration.js +233 -0
  186. package/dist/plugins/integration.js.map +1 -0
  187. package/dist/plugins/loader.d.ts +69 -0
  188. package/dist/plugins/loader.d.ts.map +1 -0
  189. package/dist/plugins/loader.js +243 -0
  190. package/dist/plugins/loader.js.map +1 -0
  191. package/dist/plugins/manifest.d.ts +23 -0
  192. package/dist/plugins/manifest.d.ts.map +1 -0
  193. package/dist/plugins/manifest.js +143 -0
  194. package/dist/plugins/manifest.js.map +1 -0
  195. package/dist/plugins/marketplace.d.ts +100 -0
  196. package/dist/plugins/marketplace.d.ts.map +1 -0
  197. package/dist/plugins/marketplace.js +529 -0
  198. package/dist/plugins/marketplace.js.map +1 -0
  199. package/dist/plugins/paths.d.ts +44 -0
  200. package/dist/plugins/paths.d.ts.map +1 -0
  201. package/dist/plugins/paths.js +89 -0
  202. package/dist/plugins/paths.js.map +1 -0
  203. package/dist/plugins/refresh.d.ts +61 -0
  204. package/dist/plugins/refresh.d.ts.map +1 -0
  205. package/dist/plugins/refresh.js +98 -0
  206. package/dist/plugins/refresh.js.map +1 -0
  207. package/dist/plugins/registry.d.ts +40 -0
  208. package/dist/plugins/registry.d.ts.map +1 -0
  209. package/dist/plugins/registry.js +80 -0
  210. package/dist/plugins/registry.js.map +1 -0
  211. package/dist/plugins/types.d.ts +225 -0
  212. package/dist/plugins/types.d.ts.map +1 -0
  213. package/dist/plugins/types.js +16 -0
  214. package/dist/plugins/types.js.map +1 -0
  215. package/dist/plugins/user-config.d.ts +22 -0
  216. package/dist/plugins/user-config.d.ts.map +1 -0
  217. package/dist/plugins/user-config.js +96 -0
  218. package/dist/plugins/user-config.js.map +1 -0
  219. package/dist/providers/cache-control.d.ts +9 -0
  220. package/dist/providers/cache-control.d.ts.map +1 -1
  221. package/dist/providers/cache-control.js +31 -4
  222. package/dist/providers/cache-control.js.map +1 -1
  223. package/dist/skills/loader.d.ts +19 -0
  224. package/dist/skills/loader.d.ts.map +1 -0
  225. package/dist/skills/loader.js +197 -0
  226. package/dist/skills/loader.js.map +1 -0
  227. package/dist/skills/registry.d.ts +74 -0
  228. package/dist/skills/registry.d.ts.map +1 -0
  229. package/dist/skills/registry.js +136 -0
  230. package/dist/skills/registry.js.map +1 -0
  231. package/dist/skills/settings.d.ts +13 -0
  232. package/dist/skills/settings.d.ts.map +1 -0
  233. package/dist/skills/settings.js +100 -0
  234. package/dist/skills/settings.js.map +1 -0
  235. package/dist/tools/activate-skill.d.ts +5 -0
  236. package/dist/tools/activate-skill.d.ts.map +1 -0
  237. package/dist/tools/activate-skill.js +33 -0
  238. package/dist/tools/activate-skill.js.map +1 -0
  239. package/dist/tools/index.d.ts +1 -1
  240. package/dist/tools/todo-write.d.ts +1 -1
  241. package/dist/tools/web-fetch.d.ts.map +1 -1
  242. package/dist/tools/web-fetch.js +2 -1
  243. package/dist/tools/web-fetch.js.map +1 -1
  244. package/dist/types/index.d.ts +46 -1
  245. package/dist/types/index.d.ts.map +1 -1
  246. package/dist/types/index.js.map +1 -1
  247. package/dist/utils.d.ts +23 -2
  248. package/dist/utils.d.ts.map +1 -1
  249. package/dist/utils.js +76 -20
  250. package/dist/utils.js.map +1 -1
  251. package/dist/version.d.ts +2 -0
  252. package/dist/version.d.ts.map +1 -0
  253. package/dist/version.js +47 -0
  254. package/dist/version.js.map +1 -0
  255. package/package.json +2 -1
@@ -0,0 +1,416 @@
1
+ // @x-code-cli/core — Plugin installer
2
+ //
3
+ // Three supported source kinds:
4
+ //
5
+ // - 'local' filesystem directory → copied recursively into cache
6
+ // (skipping .git / node_modules / OS junk)
7
+ // - 'git' arbitrary git URL → shallow-cloned (depth 1, optional ref)
8
+ // - 'github' github:owner/repo → shallow-cloned via resolveCloneUrl
9
+ // Monorepo `subdir` supported: whole repo is shallow-cloned,
10
+ // the named subdir is copied into a fresh temp dir, the rest
11
+ // discarded.
12
+ //
13
+ // Install flow:
14
+ // 1. Fetch source into a temp dir
15
+ // 2. Discover + parse manifest (reject Gemini-only sources here)
16
+ // 3. Compute final cache path: cache/<marketplace>/<plugin>/<version>/
17
+ // 4. Wipe any existing install at that path (re-install / same-version upgrade)
18
+ // 5. Move temp → final (rename when possible, copy+rm fallback for EXDEV)
19
+ // 6. Append/update installed_plugins.json
20
+ //
21
+ // AbortSignal threads through git clone (via execa's `signal`) and the
22
+ // recursive copy (cooperative check between entries) so Esc during a long
23
+ // install cleanly cancels in-flight work.
24
+ //
25
+ // Cache layout is deliberately per-version so `/plugin update` can install
26
+ // a new version side-by-side and atomically switch (a later improvement);
27
+ // today we just overwrite same-version installs.
28
+ import { execa } from 'execa';
29
+ import fs from 'node:fs/promises';
30
+ import os from 'node:os';
31
+ import path from 'node:path';
32
+ import { debugLog } from '../utils.js';
33
+ import { buildConsentPreview, probePluginRoot } from './consent.js';
34
+ import { ManifestParseError, discoverManifest, parseManifest } from './manifest.js';
35
+ import { RESERVED_MARKETPLACE_NAMES, readKnownMarketplaces, resolveCloneUrl } from './marketplace.js';
36
+ import { installedPluginsPath, pluginCacheDir, pluginCacheParent } from './paths.js';
37
+ import { setPluginUserConfig } from './user-config.js';
38
+ export class InstallError extends Error {
39
+ constructor(message) {
40
+ super(message);
41
+ this.name = 'InstallError';
42
+ }
43
+ }
44
+ export async function installPlugin(req) {
45
+ // ── Pre-flight policy checks (cheap, fail-fast) ──
46
+ // `strictKnownMarketplaces` and `blockedPlugins` come from
47
+ // ~/.x-code/plugins/known_marketplaces.json. When the admin
48
+ // (typically enterprise) has opted into strict mode, every install
49
+ // must come from a subscribed marketplace — direct git / github /
50
+ // local installs are denied. `blockedPlugins` is checked after the
51
+ // manifest is parsed (we need the canonical id).
52
+ const km = await readKnownMarketplaces();
53
+ if (km.strictKnownMarketplaces) {
54
+ const subscribed = km.marketplaces.some((m) => m.name === req.marketplace);
55
+ if (!subscribed) {
56
+ throw new InstallError(`strict marketplace mode is enabled (known_marketplaces.json:strictKnownMarketplaces=true) — ` +
57
+ `plugins can only be installed from a subscribed marketplace, but "${req.marketplace}" is not one. ` +
58
+ `Either subscribe it first (\`xc plugin marketplace add\`) or turn strict mode off.`);
59
+ }
60
+ }
61
+ const tempDir = await fetchToTemp(req.source, req.signal);
62
+ try {
63
+ const discovery = await discoverManifest(tempDir);
64
+ if (!discovery) {
65
+ throw new InstallError('no plugin manifest found in source (looked for .x-code-plugin/plugin.json, .claude-plugin/plugin.json, plugin.json)');
66
+ }
67
+ if (discovery.format === 'gemini') {
68
+ throw new InstallError('this is a Gemini extension (gemini-extension.json) — x-code-cli does not support Gemini extensions; see docs/plugins.md');
69
+ }
70
+ let manifest;
71
+ try {
72
+ manifest = await parseManifest(discovery.manifestPath);
73
+ }
74
+ catch (err) {
75
+ if (err instanceof ManifestParseError)
76
+ throw new InstallError(err.message);
77
+ throw err;
78
+ }
79
+ if (req.expectedName && manifest.name !== req.expectedName) {
80
+ throw new InstallError(`manifest name "${manifest.name}" does not match expected "${req.expectedName}"`);
81
+ }
82
+ // Now that we know the canonical plugin id, run the second
83
+ // policy check: blockedPlugins from known_marketplaces.json. This
84
+ // is an admin-style force-disable list — an install attempt for
85
+ // a blocked id is rejected regardless of marketplace / consent.
86
+ // Two match forms are accepted:
87
+ // - Fully-qualified id `name@marketplace` — precise (admin can
88
+ // block one marketplace's variant without affecting forks)
89
+ // - Bare name `name` — broad (admin can block every marketplace's
90
+ // plugin with that name in one shot; matches the npm `--ignore`
91
+ // style some admins expect)
92
+ const earlyId = `${manifest.name}@${req.marketplace}`;
93
+ const blocked = km.blockedPlugins?.find((b) => b === earlyId || b === manifest.name);
94
+ if (blocked) {
95
+ throw new InstallError(`plugin "${earlyId}" is on the blockedPlugins list in known_marketplaces.json ` +
96
+ `(matched entry: "${blocked}") — remove it from that list (or use a different plugin) to install.`);
97
+ }
98
+ // ── Consent gate ──
99
+ // Built from the parsed manifest so the caller can render a
100
+ // preview of what the plugin will contribute (hooks, mcp, scopes)
101
+ // and ask the user explicitly. Skipping the prompt (callback
102
+ // absent) is intentional for non-interactive paths — the CLI
103
+ // implements `--yes` by simply not passing `consent`.
104
+ if (req.consent) {
105
+ const rootProbe = await probePluginRoot(tempDir);
106
+ const preview = buildConsentPreview({
107
+ pluginId: `${manifest.name}@${req.marketplace}`,
108
+ manifest,
109
+ source: req.source,
110
+ marketplace: req.marketplace,
111
+ verified: req.verified,
112
+ fromReservedMarketplace: req.marketplace in RESERVED_MARKETPLACE_NAMES,
113
+ rootProbe,
114
+ });
115
+ const accepted = await req.consent(preview);
116
+ if (!accepted) {
117
+ throw new InstallError('install cancelled by user (consent declined)');
118
+ }
119
+ }
120
+ // ── userConfig prompt (post-consent, pre-commit) ──
121
+ // Only fires when the manifest declares userConfig fields AND the
122
+ // caller wired a prompt callback. Non-interactive paths (--yes, CI)
123
+ // skip the prompt — fields stay unset and the plugin sees empty env
124
+ // vars at hook / mcp launch time, same as before this feature.
125
+ // Returning null from the prompt aborts the install (treated like
126
+ // consent denial); a non-null object is persisted via setPluginUserConfig.
127
+ if (manifest.userConfig && manifest.userConfig.length > 0 && req.userConfigPrompt) {
128
+ const collected = await req.userConfigPrompt(manifest.userConfig);
129
+ if (collected === null) {
130
+ throw new InstallError('install cancelled by user (userConfig prompt aborted)');
131
+ }
132
+ // Persist BEFORE moving the temp dir to cache so a crash between
133
+ // the two phases leaves the user with no broken plugin and no
134
+ // orphaned secret. The settings file is keyed by plugin id and
135
+ // overwrites cleanly on reinstall.
136
+ const pluginIdForConfig = `${manifest.name}@${req.marketplace}`;
137
+ await setPluginUserConfig(pluginIdForConfig, collected);
138
+ }
139
+ const finalDir = pluginCacheDir(req.marketplace, manifest.name, manifest.version);
140
+ // Same-version reinstall: wipe existing install first. Skipping this
141
+ // would leave stale files mixed with new ones if the new version drops
142
+ // a file the old version had.
143
+ await fs.rm(finalDir, { recursive: true, force: true });
144
+ await fs.mkdir(path.dirname(finalDir), { recursive: true });
145
+ await moveOrCopy(tempDir, finalDir, req.signal);
146
+ const pluginId = `${manifest.name}@${req.marketplace}`;
147
+ const record = {
148
+ id: pluginId,
149
+ name: manifest.name,
150
+ marketplace: req.marketplace,
151
+ version: manifest.version,
152
+ source: req.source,
153
+ installedAt: new Date().toISOString(),
154
+ installScope: req.scope ?? 'user',
155
+ };
156
+ await recordInstallation(record);
157
+ return { pluginId, rootDir: finalDir, manifest, manifestFormat: discovery.format, record };
158
+ }
159
+ catch (err) {
160
+ // Best-effort cleanup of the temp dir on any failure mid-install. The
161
+ // moveOrCopy success path renames the temp away, so this only fires
162
+ // when something went wrong before the move.
163
+ await fs.rm(tempDir, { recursive: true, force: true }).catch(() => {
164
+ /* nothing useful to do */
165
+ });
166
+ if (err instanceof InstallError || err instanceof ManifestParseError)
167
+ throw err;
168
+ throw new InstallError(err instanceof Error ? err.message : String(err));
169
+ }
170
+ }
171
+ // ── Source → temp dir ───────────────────────────────────────────────────
172
+ async function fetchToTemp(source, signal) {
173
+ const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'xc-plugin-install-'));
174
+ if (source.kind === 'local') {
175
+ const resolved = path.resolve(source.path);
176
+ const stat = await fs.stat(resolved).catch(() => null);
177
+ if (!stat || !stat.isDirectory()) {
178
+ await fs.rm(tempDir, { recursive: true, force: true }).catch(() => { });
179
+ // Surface cwd in the error: relative paths get resolved against
180
+ // process.cwd(), and when xc is launched via `pnpm dev` the cwd
181
+ // is `packages/cli/`, not the repo root — that mismatch confuses
182
+ // users typing `./foo` in the slash command. Showing both the
183
+ // resolved absolute path and the cwd makes the cause obvious.
184
+ const isRelative = !path.isAbsolute(source.path);
185
+ const cwdHint = isRelative ? ` (resolved relative to cwd: ${process.cwd()})` : '';
186
+ throw new InstallError(`local source is not a directory: ${resolved}${cwdHint}`);
187
+ }
188
+ await copyDirFiltered(resolved, tempDir, signal);
189
+ return tempDir;
190
+ }
191
+ if (source.kind === 'git' || source.kind === 'github') {
192
+ const cloneUrl = source.kind === 'git' ? source.url : resolveCloneUrl(`github:${source.owner}/${source.repo}`);
193
+ const args = ['clone', '--depth', '1'];
194
+ if (source.ref)
195
+ args.push('--branch', source.ref);
196
+ // For subdir installs we still shallow-clone the whole repo. Real
197
+ // sparse-checkout would be faster on huge monorepos but the
198
+ // `--depth 1 --filter=blob:none --sparse` sequence is fragile across
199
+ // git versions; a depth-1 clone of even a large monorepo is usually
200
+ // <100 MB. Revisit if it becomes a pain point.
201
+ args.push(cloneUrl, tempDir);
202
+ try {
203
+ await execa('git', args, { signal, stdio: 'pipe' });
204
+ }
205
+ catch (err) {
206
+ await fs.rm(tempDir, { recursive: true, force: true }).catch(() => { });
207
+ throw new InstallError(`git clone failed: ${err instanceof Error ? err.message : String(err)}`);
208
+ }
209
+ // Integrity check: when the marketplace.json pinned a `sha`, verify
210
+ // that the commit we actually cloned matches it. Defends against the
211
+ // upstream ref being force-pushed or the repo being compromised
212
+ // between marketplace review and end-user install. Must run BEFORE
213
+ // we drop `.git` below (rev-parse needs the repo metadata).
214
+ //
215
+ // Prefix-match semantics: declared sha can be a short sha (≥7 hex)
216
+ // and still validate against the full 40-char HEAD — same tolerance
217
+ // as `git checkout <short-sha>` and what real marketplaces produce
218
+ // (anthropics/claude-plugins-official sometimes ships 7-char shas).
219
+ //
220
+ // Why hard fail and not warn: a sha mismatch is by definition either
221
+ // a misconfigured marketplace.json (author bug) or a real
222
+ // supply-chain anomaly. Either way the user shouldn't end up with
223
+ // unreviewed code on disk. Better to surface a loud error pointing
224
+ // at the marketplace author than to silently install whatever HEAD
225
+ // happens to be.
226
+ if (source.expectedSha) {
227
+ try {
228
+ const result = await execa('git', ['rev-parse', 'HEAD'], { cwd: tempDir, stdio: 'pipe', signal });
229
+ const actualSha = result.stdout.trim().toLowerCase();
230
+ const expected = source.expectedSha.toLowerCase();
231
+ if (!actualSha.startsWith(expected)) {
232
+ await fs.rm(tempDir, { recursive: true, force: true }).catch(() => { });
233
+ throw new InstallError(`sha integrity check failed for ${cloneUrl}${source.ref ? `@${source.ref}` : ''}: ` +
234
+ `marketplace.json declared sha=${expected}, actual HEAD=${actualSha}. ` +
235
+ `The upstream ref may have been force-pushed or the repo compromised. ` +
236
+ `Contact the marketplace author or pin to a different version.`);
237
+ }
238
+ }
239
+ catch (err) {
240
+ if (err instanceof InstallError)
241
+ throw err;
242
+ // rev-parse failed (shouldn't happen on a fresh clone) — treat
243
+ // as integrity failure so we don't silently install unchecked.
244
+ await fs.rm(tempDir, { recursive: true, force: true }).catch(() => { });
245
+ throw new InstallError(`failed to verify sha for ${cloneUrl}: ${err instanceof Error ? err.message : String(err)}`);
246
+ }
247
+ }
248
+ // Drop the .git dir — we never need it after install and it would
249
+ // bloat the cache significantly for large-history repos.
250
+ await fs.rm(path.join(tempDir, '.git'), { recursive: true, force: true }).catch(() => { });
251
+ // Subdir handling: the plugin actually lives at <tempDir>/<subdir>.
252
+ // Re-stage so the rest of the install flow (manifest discovery +
253
+ // moveOrCopy to cache) operates on just that subdir. Simplest
254
+ // approach: copy the subdir into a fresh temp dir, discard the
255
+ // original clone.
256
+ const subdir = source.subdir;
257
+ if (subdir) {
258
+ const subdirPath = path.join(tempDir, subdir);
259
+ const stat = await fs.stat(subdirPath).catch(() => null);
260
+ if (!stat || !stat.isDirectory()) {
261
+ await fs.rm(tempDir, { recursive: true, force: true }).catch(() => { });
262
+ throw new InstallError(`subdir "${subdir}" not found in cloned repo ${cloneUrl}`);
263
+ }
264
+ const subdirTemp = await fs.mkdtemp(path.join(os.tmpdir(), 'xc-plugin-subdir-'));
265
+ try {
266
+ await copyDirFiltered(subdirPath, subdirTemp, signal);
267
+ }
268
+ catch (err) {
269
+ await fs.rm(subdirTemp, { recursive: true, force: true }).catch(() => { });
270
+ await fs.rm(tempDir, { recursive: true, force: true }).catch(() => { });
271
+ throw new InstallError(`failed to extract subdir: ${err instanceof Error ? err.message : String(err)}`);
272
+ }
273
+ await fs.rm(tempDir, { recursive: true, force: true }).catch(() => { });
274
+ return subdirTemp;
275
+ }
276
+ return tempDir;
277
+ }
278
+ await fs.rm(tempDir, { recursive: true, force: true }).catch(() => { });
279
+ throw new InstallError(`unknown source kind: ${source.kind}`);
280
+ }
281
+ /** Names we never copy through. `node_modules` is excluded because a
282
+ * bundled-deps plugin should reinstall on the user's machine; if a
283
+ * plugin genuinely needs node_modules we'll revisit. */
284
+ const COPY_SKIP = new Set(['.git', 'node_modules', '.DS_Store', 'Thumbs.db']);
285
+ async function copyDirFiltered(src, dst, signal, root) {
286
+ // `root` is captured on the first (non-recursive) call so the symlink
287
+ // escape check below validates against the original plugin source, not
288
+ // the current recursion's `src` (which moves with each subdir).
289
+ const rootDir = root ?? src;
290
+ await fs.mkdir(dst, { recursive: true });
291
+ const entries = await fs.readdir(src, { withFileTypes: true });
292
+ for (const entry of entries) {
293
+ signal?.throwIfAborted();
294
+ if (COPY_SKIP.has(entry.name))
295
+ continue;
296
+ const s = path.join(src, entry.name);
297
+ const d = path.join(dst, entry.name);
298
+ if (entry.isDirectory()) {
299
+ await copyDirFiltered(s, d, signal, rootDir);
300
+ }
301
+ else if (entry.isFile()) {
302
+ await fs.copyFile(s, d);
303
+ }
304
+ else if (entry.isSymbolicLink()) {
305
+ // Resolve the symlink target relative to its containing directory.
306
+ // If the resolved target escapes the plugin source root, drop the
307
+ // symlink rather than preserve it: on POSIX a `evil -> /etc/passwd`
308
+ // in the plugin tree would put a host-file pointer in the cache for
309
+ // loader / hooks to deref at runtime; on Windows the fallback below
310
+ // would copy `/etc/passwd`-equivalents straight into the cache.
311
+ // We don't follow the symlink to validate that the target exists —
312
+ // a broken-but-in-bounds symlink is still safe to preserve.
313
+ const target = await fs.readlink(s);
314
+ const resolved = path.resolve(path.dirname(s), target);
315
+ const rel = path.relative(rootDir, resolved);
316
+ if (rel === '' || rel.startsWith('..') || path.isAbsolute(rel)) {
317
+ debugLog('plugins.copy-symlink-escape', `${s} -> ${target} (resolved ${resolved}, outside ${rootDir})`);
318
+ continue;
319
+ }
320
+ try {
321
+ await fs.symlink(target, d);
322
+ }
323
+ catch {
324
+ // Windows without symlink privilege: fall back to copying the
325
+ // resolved file. Best effort — broken symlinks just get dropped.
326
+ await fs.copyFile(s, d).catch(() => { });
327
+ }
328
+ }
329
+ }
330
+ }
331
+ /** Move from temp → final dir. Rename is atomic + cheap when src and dst
332
+ * are on the same filesystem; otherwise (EXDEV on Windows mostly) we
333
+ * fall back to copy + rm. */
334
+ async function moveOrCopy(src, dst, signal) {
335
+ try {
336
+ await fs.rename(src, dst);
337
+ return;
338
+ }
339
+ catch (err) {
340
+ const code = err.code;
341
+ if (code !== 'EXDEV' && code !== 'EPERM' && code !== 'ENOTEMPTY') {
342
+ // Surfacing the original error here would block install for transient
343
+ // weirdness; the copy fallback below succeeds in all the cases we've
344
+ // seen in the wild. Still log for postmortem.
345
+ debugLog('plugins.install-rename-fallback', String(err));
346
+ }
347
+ }
348
+ await copyDirFiltered(src, dst, signal);
349
+ await fs.rm(src, { recursive: true, force: true }).catch(() => { });
350
+ }
351
+ // ── installed_plugins.json bookkeeping ──────────────────────────────────
352
+ async function readInstalledPlugins() {
353
+ const file = installedPluginsPath();
354
+ try {
355
+ const raw = await fs.readFile(file, 'utf-8');
356
+ const parsed = JSON.parse(raw);
357
+ if (!parsed || typeof parsed !== 'object' || !Array.isArray(parsed.plugins)) {
358
+ return { schemaVersion: '1', plugins: [] };
359
+ }
360
+ return { schemaVersion: parsed.schemaVersion ?? '1', plugins: parsed.plugins };
361
+ }
362
+ catch {
363
+ return { schemaVersion: '1', plugins: [] };
364
+ }
365
+ }
366
+ async function writeInstalledPlugins(data) {
367
+ const file = installedPluginsPath();
368
+ await fs.mkdir(path.dirname(file), { recursive: true });
369
+ await fs.writeFile(file, JSON.stringify(data, null, 2) + '\n', 'utf-8');
370
+ }
371
+ async function recordInstallation(record) {
372
+ const data = await readInstalledPlugins();
373
+ const idx = data.plugins.findIndex((p) => p.id === record.id);
374
+ if (idx >= 0)
375
+ data.plugins[idx] = record;
376
+ else
377
+ data.plugins.push(record);
378
+ await writeInstalledPlugins(data);
379
+ }
380
+ export async function listInstalledPlugins() {
381
+ const data = await readInstalledPlugins();
382
+ return data.plugins;
383
+ }
384
+ export async function findInstalledPlugin(id) {
385
+ const data = await readInstalledPlugins();
386
+ return data.plugins.find((p) => p.id === id);
387
+ }
388
+ /** Remove all cached versions of a plugin + drop its
389
+ * installed_plugins.json record. Leaves the data dir
390
+ * (`~/.x-code/plugins/data/<id>/`) intact so the user doesn't lose
391
+ * state if they reinstall later. */
392
+ export async function uninstallPlugin(id) {
393
+ const record = await findInstalledPlugin(id);
394
+ const result = { removedVersions: [], removedRecord: false };
395
+ if (record) {
396
+ const parent = pluginCacheParent(record.marketplace, record.name);
397
+ try {
398
+ const versions = await fs.readdir(parent);
399
+ result.removedVersions = versions;
400
+ await fs.rm(parent, { recursive: true, force: true });
401
+ }
402
+ catch {
403
+ // No cache entries — the record might be stale. Removing the record
404
+ // below still happens.
405
+ }
406
+ }
407
+ const data = await readInstalledPlugins();
408
+ const before = data.plugins.length;
409
+ data.plugins = data.plugins.filter((p) => p.id !== id);
410
+ if (data.plugins.length !== before) {
411
+ await writeInstalledPlugins(data);
412
+ result.removedRecord = true;
413
+ }
414
+ return result;
415
+ }
416
+ //# sourceMappingURL=installer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installer.js","sourceRoot":"","sources":["../../src/plugins/installer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,91 @@
1
+ import { HookBus } from '../hooks/bus.js';
2
+ import { HookRegistry } from '../hooks/registry.js';
3
+ import type { McpServerConfig } from '../mcp/types.js';
4
+ import { loadAllPlugins } from './loader.js';
5
+ import type { LoadResult } from './loader.js';
6
+ export interface PluginIntegrationOutput {
7
+ /** Extra skill directories the skill loader should scan, with the
8
+ * owning plugin id stamped on each. Only enabled plugins included. */
9
+ skillsDirs: Array<{
10
+ dir: string;
11
+ pluginId: string;
12
+ }>;
13
+ /** Same as above for sub-agent .md files. */
14
+ agentsDirs: Array<{
15
+ dir: string;
16
+ pluginId: string;
17
+ }>;
18
+ /** Same as above for slash command `*.md` files. Each entry carries
19
+ * the owning plugin's rootDir so the command body can substitute
20
+ * `${CLAUDE_PLUGIN_ROOT}` at activation time. */
21
+ commandsDirs: Array<{
22
+ dir: string;
23
+ pluginId: string;
24
+ pluginRoot: string;
25
+ }>;
26
+ /** Merged `mcpServers` block from every enabled plugin. Name
27
+ * collisions resolved first-wins; the losers are recorded in
28
+ * `mcpCollisions`. */
29
+ mcpServers: Record<string, McpServerConfig>;
30
+ /** Hook registry built from every enabled plugin's `hooks` config.
31
+ * Empty when no plugin declared any hooks. Hand this to
32
+ * `new HookBus(...)` to wire the agent loop's emit-sites. */
33
+ hookRegistry: HookRegistry;
34
+ /** Ready-to-use bus over `hookRegistry`. Convenience for the CLI
35
+ * startup wiring — `AgentOptions.hookBus = integration.hookBus`. */
36
+ hookBus: HookBus;
37
+ /** Per-plugin summary of which event names had hooks — used by
38
+ * `/plugin doctor` and `/plugin info` UI. */
39
+ pluginHooks: Array<{
40
+ pluginId: string;
41
+ events: string[];
42
+ }>;
43
+ /** mcpServers entries dropped due to name collision with an earlier
44
+ * plugin. `{ name, droppedFrom, keptFrom }`. */
45
+ mcpCollisions: Array<{
46
+ name: string;
47
+ droppedFrom: string;
48
+ keptFrom: string;
49
+ }>;
50
+ /** mcpServers parse / read errors per plugin — these don't block
51
+ * startup, they surface in `/plugin doctor`. */
52
+ mcpErrors: Array<{
53
+ pluginId: string;
54
+ message: string;
55
+ }>;
56
+ /** Hooks parse / read errors per plugin. */
57
+ hookErrors: Array<{
58
+ pluginId: string;
59
+ message: string;
60
+ }>;
61
+ }
62
+ export declare function buildPluginIntegration(load: LoadResult): Promise<PluginIntegrationOutput>;
63
+ /** Extract the `name → cfg` block from the contents of a `.mcp.json`
64
+ * file. Two shapes are accepted:
65
+ *
66
+ * - Wrapped: `{ "mcpServers": { "name": cfg, ... } }`
67
+ * - Flat: `{ "name": cfg, ... }` (no wrapper key)
68
+ *
69
+ * Claude Code's official plugins (e.g. linear@anthropic-marketplace)
70
+ * ship the flat form; the wrapped form matches our own config.json
71
+ * layout. The detection rule is: if the parsed object has a
72
+ * `mcpServers` key at all, treat it as wrapped (and pass through the
73
+ * value as-is so the schema parser produces a clean error on
74
+ * misshape). Otherwise treat the whole object as the flat block. */
75
+ export declare function extractMcpServersBlock(parsed: unknown): unknown;
76
+ /** Convenience: log non-fatal integration diagnostics to debug.log so
77
+ * `/plugin doctor` and ad-hoc support can find them. CLI startup calls
78
+ * this after `buildPluginIntegration` returns. */
79
+ export declare function debugLogIntegrationDiagnostics(integration: PluginIntegrationOutput): void;
80
+ /** Re-scan plugins from disk and return just the merged plugin-contributed
81
+ * mcpServers block. Used by `/mcp refresh` to include plugin servers in
82
+ * the merged map (so they aren't silently dropped on standalone MCP
83
+ * refresh) and by `/plugin refresh` indirectly via buildPluginIntegration.
84
+ *
85
+ * Returns `{}` (not undefined) so callers can spread it unconditionally.
86
+ * Scan failures degrade to `{}` + debug log — callers shouldn't have an
87
+ * MCP-only refresh fail because of a plugin-system hiccup. */
88
+ export declare function getPluginMcpServersFromDisk(cwd: string): Promise<Record<string, McpServerConfig>>;
89
+ export type { LoadResult, ResolvedContributions } from './loader.js';
90
+ export { loadAllPlugins };
91
+ //# sourceMappingURL=integration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integration.d.ts","sourceRoot":"","sources":["../../src/plugins/integration.ts"],"names":[],"mappings":"AAoCA,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAEzC,OAAO,EAAE,YAAY,EAAqB,MAAM,sBAAsB,CAAA;AAItE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEtD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAyB,MAAM,aAAa,CAAA;AAIpE,MAAM,WAAW,uBAAuB;IACtC;2EACuE;IACvE,UAAU,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACpD,6CAA6C;IAC7C,UAAU,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACpD;;sDAEkD;IAClD,YAAY,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAC1E;;2BAEuB;IACvB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;IAC3C;;kEAE8D;IAC9D,YAAY,EAAE,YAAY,CAAA;IAC1B;yEACqE;IACrE,OAAO,EAAE,OAAO,CAAA;IAChB;kDAC8C;IAC9C,WAAW,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAA;IAC1D;qDACiD;IACjD,aAAa,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAC7E;qDACiD;IACjD,SAAS,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACvD,4CAA4C;IAC5C,UAAU,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CACzD;AAED,wBAAsB,sBAAsB,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAuD/F;AAiCD;;;;;;;;;;;qEAWqE;AACrE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAK/D;AAsDD;;mDAEmD;AACnD,wBAAgB,8BAA8B,CAAC,WAAW,EAAE,uBAAuB,GAAG,IAAI,CAgBzF;AAED;;;;;;;+DAO+D;AAC/D,wBAAsB,2BAA2B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,CASvG;AAID,YAAY,EAAE,UAAU,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AACpE,OAAO,EAAE,cAAc,EAAE,CAAA"}