@posthog/wizard 2.76.1 → 2.78.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -15
- package/dist/README.md +16 -15
- package/dist/{add-mcp-server-to-clients-4yHaRvOo.js → add-mcp-server-to-clients-JMv8LP-O.js} +429 -114
- package/dist/add-mcp-server-to-clients-JMv8LP-O.js.map +1 -0
- package/dist/agent-bCZ3i3fh.js +3085 -0
- package/dist/agent-bCZ3i3fh.js.map +1 -0
- package/dist/{agent-interface-DPaPdIjS.js → agent-interface-BAOIHuXS.js} +452 -377
- package/dist/agent-interface-BAOIHuXS.js.map +1 -0
- package/dist/{agent-prompt-loader-BlhabNM2.js → agent-prompt-loader-7Pd4CfZO.js} +24 -8
- package/dist/agent-prompt-loader-7Pd4CfZO.js.map +1 -0
- package/dist/analytics-BcV-WCM4.js +2 -0
- package/dist/{analytics-DSVyjIVF.js → analytics-CHCZ_qUR.js} +10 -6
- package/dist/analytics-CHCZ_qUR.js.map +1 -0
- package/dist/{api-Ci0dZWLR.js → api-Diy_2fp8.js} +4 -17
- package/dist/api-Diy_2fp8.js.map +1 -0
- package/dist/bin.js +410 -68
- package/dist/bin.js.map +1 -1
- package/dist/{bounded-fs-FbZJ_vJ_.js → bounded-fs-Bx9zTe6m.js} +4 -4
- package/dist/bounded-fs-Bx9zTe6m.js.map +1 -0
- package/dist/check-screens.tsx +1 -1
- package/dist/{ci-install-CEVCqahf.js → ci-install-CDdQYsPe.js} +6 -5
- package/dist/ci-install-CDdQYsPe.js.map +1 -0
- package/dist/constants-jFI2SaE1.js +260 -0
- package/dist/constants-jFI2SaE1.js.map +1 -0
- package/dist/debug-Ch4BDOtD.js +171 -0
- package/dist/debug-Ch4BDOtD.js.map +1 -0
- package/dist/{debug-C6KWXbQi.js → debug-M2gV2iDq.js} +1 -1
- package/dist/{defaults-DulzMJpN.js → defaults-C6J7yL4O.js} +26 -3
- package/dist/defaults-C6J7yL4O.js.map +1 -0
- package/dist/endpoints-DCVbM06L.js +108 -0
- package/dist/endpoints-DCVbM06L.js.map +1 -0
- package/dist/{env-api-key-DwmkB3fm.js → env-api-key-Qx8NnYHm.js} +3 -3
- package/dist/env-api-key-Qx8NnYHm.js.map +1 -0
- package/dist/{environment-1wA7uwAS.js → environment-B07Bmxae.js} +6 -6
- package/dist/environment-B07Bmxae.js.map +1 -0
- package/dist/{errors--OqLxmWR.js → errors-CQ9kttJD.js} +30 -35
- package/dist/errors-CQ9kttJD.js.map +1 -0
- package/dist/{file-C3HGL1IM.js → file-BcLTjU16.js} +2 -2
- package/dist/{file-C3HGL1IM.js.map → file-BcLTjU16.js.map} +1 -1
- package/dist/{file-watcher-D8s0b-VT.js → file-watcher-DWc_bTs6.js} +2 -2
- package/dist/{file-watcher-D8s0b-VT.js.map → file-watcher-DWc_bTs6.js.map} +1 -1
- package/dist/{gateway-session-OqzCMpZ9.js → gateway-CjoShdLa.js} +175 -20
- package/dist/gateway-CjoShdLa.js.map +1 -0
- package/dist/generate-version.cjs +1 -1
- package/dist/{headless-ui-DRGWDg9Z.js → headless-ui-BFFmYC4v.js} +13 -2
- package/dist/headless-ui-BFFmYC4v.js.map +1 -0
- package/dist/{interactive-B6OlvhSf.js → interactive-D6zV7brJ.js} +2 -2
- package/dist/{interactive-B6OlvhSf.js.map → interactive-D6zV7brJ.js.map} +1 -1
- package/dist/{local-dev-DPZiIPCK.js → local-dev-McsurOC-.js} +2 -2
- package/dist/local-dev-McsurOC-.js.map +1 -0
- package/dist/logging-ui-_TwoMNbG.js +226 -0
- package/dist/logging-ui-_TwoMNbG.js.map +1 -0
- package/dist/mcp-DAgaoGk5.js +97 -0
- package/dist/mcp-DAgaoGk5.js.map +1 -0
- package/dist/{mcp-prompt-streaming-E1d8DJcX.js → mcp-prompt-streaming-I2U_X7BC.js} +7 -6
- package/dist/mcp-prompt-streaming-I2U_X7BC.js.map +1 -0
- package/dist/{mint-failure-C82j0RMC.js → mint-failure-D4nd2XmZ.js} +134 -48
- package/dist/mint-failure-D4nd2XmZ.js.map +1 -0
- package/dist/models-DDdBJKwT.js +83 -0
- package/dist/models-DDdBJKwT.js.map +1 -0
- package/dist/{non-interactive-DGT2H_n4.js → non-interactive-Dzow7YKY.js} +3 -3
- package/dist/non-interactive-Dzow7YKY.js.map +1 -0
- package/dist/oauth-session-DJ8h6GFa.js +74 -0
- package/dist/oauth-session-DJ8h6GFa.js.map +1 -0
- package/dist/{orchestrator-tools-BBBNV1z5.js → orchestrator-tools-szcdscwn.js} +5 -5
- package/dist/orchestrator-tools-szcdscwn.js.map +1 -0
- package/dist/{package-json-xt3eeyBI.js → package-json-DY70kkNp.js} +2 -2
- package/dist/package-json-DY70kkNp.js.map +1 -0
- package/dist/{pi-fG5fT50Y.js → pi-D3h5Ok0i.js} +329 -65
- package/dist/pi-D3h5Ok0i.js.map +1 -0
- package/dist/{playground-UFSHP-Yn.js → playground-5AB4WgNF.js} +18 -10
- package/dist/playground-5AB4WgNF.js.map +1 -0
- package/dist/{posthog-O9kKcnda.js → posthog-DNn574nW.js} +8 -3
- package/dist/posthog-DNn574nW.js.map +1 -0
- package/dist/{provisioning-B-tzjG4r.js → provisioning-B8uSqRZk.js} +6 -5
- package/dist/provisioning-B8uSqRZk.js.map +1 -0
- package/dist/{queue-tools-7Oso-fpt.js → queue-tools-9OOVx5TE.js} +11 -86
- package/dist/queue-tools-9OOVx5TE.js.map +1 -0
- package/dist/{registry-D1L5e-WQ.js → registry-8YG-kuXk.js} +265 -6
- package/dist/registry-8YG-kuXk.js.map +1 -0
- package/dist/run-agent-legacy-d7rWlzQR.js +3739 -0
- package/dist/run-agent-legacy-d7rWlzQR.js.map +1 -0
- package/dist/{security-n3-xdINN.js → security-Cg_4a7vB.js} +6 -6
- package/dist/security-Cg_4a7vB.js.map +1 -0
- package/dist/{setup-utils-Bj0gejEf.js → setup-utils-CmTCTPkX.js} +46 -18
- package/dist/setup-utils-CmTCTPkX.js.map +1 -0
- package/dist/smoke-test.sh +1 -1
- package/dist/{start-tui-BowrTPXm.js → start-tui-CB2PZs1x.js} +42 -48
- package/dist/start-tui-CB2PZs1x.js.map +1 -0
- package/dist/{steps-CpNTGu9N.js → steps-BZcXRJNY.js} +7 -7
- package/dist/{steps-CpNTGu9N.js.map → steps-BZcXRJNY.js.map} +1 -1
- package/dist/{store-CVkJKlny.js → store-UN7c-ASf.js} +18 -55
- package/dist/store-UN7c-ASf.js.map +1 -0
- package/dist/{subagent-SxmvfDfp.js → subagent-BofIDK-O.js} +8 -3
- package/dist/subagent-BofIDK-O.js.map +1 -0
- package/dist/{task-nF7Ry8ff.js → task-r9t1UhQP.js} +124 -36
- package/dist/task-r9t1UhQP.js.map +1 -0
- package/dist/{task-stream-C9BLiAhz.js → task-stream-CMUilu54.js} +45 -15
- package/dist/task-stream-CMUilu54.js.map +1 -0
- package/dist/{tasks-BEEVIBcT.js → tasks-Bbv_lOBG.js} +17 -13
- package/dist/tasks-Bbv_lOBG.js.map +1 -0
- package/dist/{telemetry-PD7bhcda.js → telemetry-D6ruCtnv.js} +5 -5
- package/dist/telemetry-D6ruCtnv.js.map +1 -0
- package/dist/{terminal-NhNl-BIA.js → terminal-DrGyci_a.js} +63 -94
- package/dist/terminal-DrGyci_a.js.map +1 -0
- package/dist/{tools-BBdpgcIf.js → tools-Dyfh9aCD.js} +11 -11
- package/dist/tools-Dyfh9aCD.js.map +1 -0
- package/dist/ui-BBVuTM1v.js +15 -0
- package/dist/ui-BBVuTM1v.js.map +1 -0
- package/dist/version-aXxpgRKx.js +6 -0
- package/dist/version-aXxpgRKx.js.map +1 -0
- package/dist/warlock-smoke-test.ts +2 -2
- package/dist/{wizard-abort-hqHF-9xD.js → wizard-abort-BBkiUxfS.js} +23 -20
- package/dist/wizard-abort-BBkiUxfS.js.map +1 -0
- package/dist/wizard-abort-BU4aLyvh.js +3 -0
- package/dist/{wizard-session-FSJCkTcP.js → wizard-session-2w4Ru-Wz.js} +12 -16
- package/dist/wizard-session-2w4Ru-Wz.js.map +1 -0
- package/dist/wizard-session-DGaUHOF3.js +2 -0
- package/dist/wizard-ui-DoyOZxK8.js +16 -0
- package/dist/wizard-ui-DoyOZxK8.js.map +1 -0
- package/dist/{yara-hooks-BaPKsm-B.js → yara-hooks-DCeMDd1o.js} +19 -68
- package/dist/yara-hooks-DCeMDd1o.js.map +1 -0
- package/dist/yara-hooks-DSGuCU9A.js +2 -0
- package/package.json +8 -1
- package/dist/add-mcp-server-to-clients-4yHaRvOo.js.map +0 -1
- package/dist/agent-interface-DPaPdIjS.js.map +0 -1
- package/dist/agent-prompt-loader-BlhabNM2.js.map +0 -1
- package/dist/agent-runner-JFwQQj2k.js +0 -6100
- package/dist/agent-runner-JFwQQj2k.js.map +0 -1
- package/dist/analytics-CcHoyhE_.js +0 -2
- package/dist/analytics-DSVyjIVF.js.map +0 -1
- package/dist/api-Ci0dZWLR.js.map +0 -1
- package/dist/bounded-fs-FbZJ_vJ_.js.map +0 -1
- package/dist/ci-install-CEVCqahf.js.map +0 -1
- package/dist/debug-DWYDVp0B.js +0 -750
- package/dist/debug-DWYDVp0B.js.map +0 -1
- package/dist/defaults-DulzMJpN.js.map +0 -1
- package/dist/env-api-key-DwmkB3fm.js.map +0 -1
- package/dist/environment-1wA7uwAS.js.map +0 -1
- package/dist/errors--OqLxmWR.js.map +0 -1
- package/dist/gateway-session-OqzCMpZ9.js.map +0 -1
- package/dist/gateway-session-s1xr8b48.js +0 -2
- package/dist/headless-ui-DRGWDg9Z.js.map +0 -1
- package/dist/local-dev-DPZiIPCK.js.map +0 -1
- package/dist/mcp-BprhJJ2c.js +0 -64
- package/dist/mcp-BprhJJ2c.js.map +0 -1
- package/dist/mcp-prompt-streaming-E1d8DJcX.js.map +0 -1
- package/dist/mint-failure-C82j0RMC.js.map +0 -1
- package/dist/non-interactive-DGT2H_n4.js.map +0 -1
- package/dist/orchestrator-tools-BBBNV1z5.js.map +0 -1
- package/dist/package-json-xt3eeyBI.js.map +0 -1
- package/dist/package-manager-DU3aVif4.js +0 -290
- package/dist/package-manager-DU3aVif4.js.map +0 -1
- package/dist/pi-fG5fT50Y.js.map +0 -1
- package/dist/playground-UFSHP-Yn.js.map +0 -1
- package/dist/posthog-O9kKcnda.js.map +0 -1
- package/dist/provisioning-B-tzjG4r.js.map +0 -1
- package/dist/queue-tools-7Oso-fpt.js.map +0 -1
- package/dist/registry-D1L5e-WQ.js.map +0 -1
- package/dist/security-n3-xdINN.js.map +0 -1
- package/dist/setup-utils-Bj0gejEf.js.map +0 -1
- package/dist/start-tui-BowrTPXm.js.map +0 -1
- package/dist/store-CVkJKlny.js.map +0 -1
- package/dist/subagent-SxmvfDfp.js.map +0 -1
- package/dist/task-nF7Ry8ff.js.map +0 -1
- package/dist/task-stream-C9BLiAhz.js.map +0 -1
- package/dist/tasks-BEEVIBcT.js.map +0 -1
- package/dist/telemetry-PD7bhcda.js.map +0 -1
- package/dist/terminal-NhNl-BIA.js.map +0 -1
- package/dist/tools-BBdpgcIf.js.map +0 -1
- package/dist/wizard-abort-D3YA1hXX.js +0 -2
- package/dist/wizard-abort-hqHF-9xD.js.map +0 -1
- package/dist/wizard-session-CYvyYnti.js +0 -2
- package/dist/wizard-session-FSJCkTcP.js.map +0 -1
- package/dist/yara-hooks-BaPKsm-B.js.map +0 -1
- package/dist/yara-hooks-CwfQuEl3.js +0 -2
package/dist/{add-mcp-server-to-clients-4yHaRvOo.js → add-mcp-server-to-clients-JMv8LP-O.js}
RENAMED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-B_-DWIq7.js";
|
|
2
|
-
import {
|
|
3
|
-
import { n as analytics } from "./analytics-
|
|
4
|
-
import { n as openTrackedLink, t as withProgress } from "./telemetry-
|
|
5
|
-
import {
|
|
2
|
+
import { r as debug, v as runtimeEnv } from "./debug-Ch4BDOtD.js";
|
|
3
|
+
import { n as analytics } from "./analytics-CHCZ_qUR.js";
|
|
4
|
+
import { n as openTrackedLink, t as withProgress } from "./telemetry-D6ruCtnv.js";
|
|
5
|
+
import { t as getUI } from "./ui-BBVuTM1v.js";
|
|
6
|
+
import { a as getNativeHTTPServerConfig, d as scrubHomePaths, i as getDefaultServerConfig, l as namesWithStatus, p as toClientResult, r as buildMCPUrl, s as expectedFailureHint, t as ALL_FEATURE_VALUES, u as redactSecrets } from "./defaults-C6J7yL4O.js";
|
|
6
7
|
import * as fs$2 from "fs";
|
|
7
8
|
import * as path$3 from "path";
|
|
8
9
|
import * as os from "node:os";
|
|
9
10
|
import * as path$2 from "node:path";
|
|
10
|
-
import {
|
|
11
|
+
import { execFile, execSync } from "node:child_process";
|
|
11
12
|
import * as fs$1 from "node:fs";
|
|
12
13
|
import z$1 from "zod";
|
|
13
14
|
import * as os$1 from "os";
|
|
14
15
|
import * as jsonc from "jsonc-parser";
|
|
15
|
-
import { execSync as execSync$1 } from "child_process";
|
|
16
|
+
import { execFile as execFile$1, execSync as execSync$1 } from "child_process";
|
|
16
17
|
//#region src/steps/add-mcp-server-to-clients/MCPClient.ts
|
|
17
18
|
var MCPClient = class {
|
|
18
19
|
name;
|
|
@@ -129,6 +130,31 @@ var CursorMCPClient = class extends DefaultMCPClient {
|
|
|
129
130
|
};
|
|
130
131
|
//#endregion
|
|
131
132
|
//#region src/steps/add-mcp-server-to-clients/clients/claude-code.ts
|
|
133
|
+
const PLUGIN_NAME = "posthog";
|
|
134
|
+
const PLUGIN_MARKETPLACE$1 = "posthog";
|
|
135
|
+
const PLUGIN_MARKETPLACE_SOURCE$1 = "PostHog/ai-plugin";
|
|
136
|
+
const PLUGIN_REF$1 = `${PLUGIN_NAME}@${PLUGIN_MARKETPLACE$1}`;
|
|
137
|
+
/** The plugin is missing from every catalog the CLI can currently see. */
|
|
138
|
+
const NOT_IN_A_MARKETPLACE = /not found in/i;
|
|
139
|
+
/**
|
|
140
|
+
* `plugin marketplace add` clones a git repository, the slowest thing we run.
|
|
141
|
+
* Past this the command is not slow, it is stuck, and a clone waiting on a
|
|
142
|
+
* credential prompt would otherwise hang the wizard with the spinner frozen.
|
|
143
|
+
*/
|
|
144
|
+
const RUN_TIMEOUT_MS$1 = 12e4;
|
|
145
|
+
/**
|
|
146
|
+
* `execFile` kills the child once output passes this. The default is 1 MB,
|
|
147
|
+
* which a verbose clone can reach, and the kill then looks like Claude Code
|
|
148
|
+
* rejecting the install rather than us cutting it off.
|
|
149
|
+
*/
|
|
150
|
+
const MAX_OUTPUT_BYTES$1 = 16 * 1024 * 1024;
|
|
151
|
+
/**
|
|
152
|
+
* Our catalog, by name *and* repository. A marketplace merely called `posthog`
|
|
153
|
+
* may be someone else's, and neither installing from it nor removing it is
|
|
154
|
+
* ours to do. `repo` is absent on CLIs predating it, where the name is all
|
|
155
|
+
* there is.
|
|
156
|
+
*/
|
|
157
|
+
const isOurMarketplace = (m) => m?.name === PLUGIN_MARKETPLACE$1 && (m.repo === void 0 || m.repo.toLowerCase() === PLUGIN_MARKETPLACE_SOURCE$1.toLowerCase());
|
|
132
158
|
var ClaudeCodeMCPClient = class extends DefaultMCPClient {
|
|
133
159
|
name = "Claude Code";
|
|
134
160
|
claudeBinaryPath = null;
|
|
@@ -235,21 +261,39 @@ var ClaudeCodeMCPClient = class extends DefaultMCPClient {
|
|
|
235
261
|
success: false,
|
|
236
262
|
reason: "The claude CLI is no longer on your PATH."
|
|
237
263
|
};
|
|
238
|
-
|
|
264
|
+
const ids = await this.installedPluginIds(binary);
|
|
265
|
+
const marketplace = await this.ourMarketplaceRegistered(binary);
|
|
266
|
+
const nothingInstalled = ids?.length === 0 || ids === null && !await this.isPluginInstalled();
|
|
267
|
+
if (nothingInstalled && !marketplace) return {
|
|
239
268
|
success: true,
|
|
240
269
|
alreadyInstalled: true
|
|
241
270
|
};
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
};
|
|
271
|
+
const targets = nothingInstalled ? [] : ids?.length ? ids : [PLUGIN_NAME];
|
|
272
|
+
const failures = [];
|
|
273
|
+
for (const target of targets) {
|
|
274
|
+
const run = await this.runClaude(binary, [
|
|
275
|
+
"plugin",
|
|
276
|
+
"uninstall",
|
|
277
|
+
target
|
|
278
|
+
]);
|
|
279
|
+
if (!run.ok) failures.push(`${target}: ${run.output}`);
|
|
252
280
|
}
|
|
281
|
+
if (marketplace) {
|
|
282
|
+
const run = await this.runClaude(binary, [
|
|
283
|
+
"plugin",
|
|
284
|
+
"marketplace",
|
|
285
|
+
"remove",
|
|
286
|
+
PLUGIN_MARKETPLACE$1
|
|
287
|
+
]);
|
|
288
|
+
if (!run.ok) failures.push(`${PLUGIN_MARKETPLACE$1}: ${run.output}`);
|
|
289
|
+
}
|
|
290
|
+
if (failures.length === 0) return { success: true };
|
|
291
|
+
const reason = failures.join("; ");
|
|
292
|
+
analytics.captureException(/* @__PURE__ */ new Error(`Claude Code plugin uninstall failed: ${reason}`));
|
|
293
|
+
return {
|
|
294
|
+
success: false,
|
|
295
|
+
reason
|
|
296
|
+
};
|
|
253
297
|
}
|
|
254
298
|
removeServer(local) {
|
|
255
299
|
const claudeBinary = this.findClaudeBinary();
|
|
@@ -281,40 +325,134 @@ var ClaudeCodeMCPClient = class extends DefaultMCPClient {
|
|
|
281
325
|
supportsPlugin() {
|
|
282
326
|
return this.findClaudeBinary() !== null;
|
|
283
327
|
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
328
|
+
runClaude(binary, args) {
|
|
329
|
+
return new Promise((resolve) => {
|
|
330
|
+
execFile$1(binary, args, {
|
|
331
|
+
timeout: RUN_TIMEOUT_MS$1,
|
|
332
|
+
maxBuffer: MAX_OUTPUT_BYTES$1
|
|
333
|
+
}, (error, stdout) => {
|
|
334
|
+
if (!error) return resolve({
|
|
335
|
+
ok: true,
|
|
336
|
+
output: stdout?.toString() ?? ""
|
|
337
|
+
});
|
|
338
|
+
if (error.code === "ERR_CHILD_PROCESS_STDIO_MAXBUFFER") return resolve({
|
|
339
|
+
ok: false,
|
|
340
|
+
output: "claude produced more output than the wizard can hold, so it was stopped"
|
|
341
|
+
});
|
|
342
|
+
if (error.killed || error.signal) return resolve({
|
|
343
|
+
ok: false,
|
|
344
|
+
output: `claude did not finish within ${RUN_TIMEOUT_MS$1 / 1e3}s, so it was stopped`
|
|
345
|
+
});
|
|
346
|
+
resolve({
|
|
347
|
+
ok: false,
|
|
348
|
+
output: scrubHomePaths(redactSecrets(error.message))
|
|
349
|
+
});
|
|
350
|
+
});
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
/** Null when `--json` is unsupported, the command failed, or output didn't parse — never "nothing installed". */
|
|
354
|
+
async listJson(binary, args) {
|
|
355
|
+
const result = await this.runClaude(binary, [...args, "--json"]);
|
|
356
|
+
if (!result.ok) return null;
|
|
287
357
|
try {
|
|
288
|
-
const
|
|
289
|
-
return
|
|
358
|
+
const parsed = JSON.parse(result.output);
|
|
359
|
+
return Array.isArray(parsed) ? parsed : null;
|
|
290
360
|
} catch {
|
|
291
|
-
return
|
|
361
|
+
return null;
|
|
292
362
|
}
|
|
293
363
|
}
|
|
364
|
+
async installedPlugins(binary) {
|
|
365
|
+
const listed = await this.listJson(binary, ["plugin", "list"]);
|
|
366
|
+
if (!listed) return null;
|
|
367
|
+
return listed.filter((p) => typeof p?.id === "string" && p.id.split("@")[0] === PLUGIN_NAME);
|
|
368
|
+
}
|
|
369
|
+
async installedPluginIds(binary) {
|
|
370
|
+
return (await this.installedPlugins(binary))?.map((p) => p.id) ?? null;
|
|
371
|
+
}
|
|
372
|
+
async isPluginInstalled() {
|
|
373
|
+
const binary = this.findClaudeBinary();
|
|
374
|
+
if (!binary) return false;
|
|
375
|
+
const listed = await this.installedPlugins(binary);
|
|
376
|
+
if (listed) return listed.length > 0;
|
|
377
|
+
const plain = await this.runClaude(binary, ["plugin", "list"]);
|
|
378
|
+
return plain.ok && plain.output.toLowerCase().includes(PLUGIN_NAME);
|
|
379
|
+
}
|
|
294
380
|
async installPlugin() {
|
|
295
381
|
const binary = this.findClaudeBinary();
|
|
296
382
|
if (!binary) return {
|
|
297
383
|
success: false,
|
|
298
384
|
reason: "The claude CLI is no longer on your PATH."
|
|
299
385
|
};
|
|
300
|
-
|
|
386
|
+
const listed = await this.installedPlugins(binary);
|
|
387
|
+
if (listed ? listed.some((p) => p.enabled !== false) : await this.isPluginInstalled()) return {
|
|
301
388
|
success: true,
|
|
302
389
|
alreadyInstalled: true
|
|
303
390
|
};
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
391
|
+
const marketplaceFailure = await this.ensurePluginMarketplace(binary);
|
|
392
|
+
let result = await this.runClaude(binary, [
|
|
393
|
+
"plugin",
|
|
394
|
+
"install",
|
|
395
|
+
PLUGIN_REF$1
|
|
396
|
+
]);
|
|
397
|
+
if (!result.ok && NOT_IN_A_MARKETPLACE.test(result.output)) {
|
|
398
|
+
await this.runClaude(binary, [
|
|
399
|
+
"plugin",
|
|
400
|
+
"marketplace",
|
|
401
|
+
"update",
|
|
402
|
+
PLUGIN_MARKETPLACE$1
|
|
403
|
+
]);
|
|
404
|
+
result = await this.runClaude(binary, [
|
|
405
|
+
"plugin",
|
|
406
|
+
"install",
|
|
407
|
+
PLUGIN_REF$1
|
|
408
|
+
]);
|
|
409
|
+
}
|
|
410
|
+
if (!result.ok && NOT_IN_A_MARKETPLACE.test(result.output)) result = await this.runClaude(binary, [
|
|
411
|
+
"plugin",
|
|
412
|
+
"install",
|
|
413
|
+
PLUGIN_NAME
|
|
414
|
+
]);
|
|
415
|
+
if (result.ok) return { success: true };
|
|
416
|
+
const msg = result.output;
|
|
417
|
+
if (msg.includes("already installed") || msg.includes("already exists")) return {
|
|
418
|
+
success: true,
|
|
419
|
+
alreadyInstalled: true
|
|
420
|
+
};
|
|
421
|
+
const failure = /* @__PURE__ */ new Error(`Claude Code plugin install failed: ${msg}`);
|
|
422
|
+
if (marketplaceFailure) analytics.captureException(failure, { marketplaceFailure });
|
|
423
|
+
else analytics.captureException(failure);
|
|
424
|
+
return {
|
|
425
|
+
success: false,
|
|
426
|
+
reason: msg
|
|
427
|
+
};
|
|
428
|
+
}
|
|
429
|
+
/** Registered, and ours: a catalog merely named `posthog` is someone else's. */
|
|
430
|
+
async ourMarketplaceRegistered(binary) {
|
|
431
|
+
const listed = await this.listJson(binary, [
|
|
432
|
+
"plugin",
|
|
433
|
+
"marketplace",
|
|
434
|
+
"list"
|
|
435
|
+
]);
|
|
436
|
+
return listed ? listed.some(isOurMarketplace) : null;
|
|
437
|
+
}
|
|
438
|
+
async ensurePluginMarketplace(binary) {
|
|
439
|
+
if ((await this.listJson(binary, [
|
|
440
|
+
"plugin",
|
|
441
|
+
"marketplace",
|
|
442
|
+
"list"
|
|
443
|
+
]))?.some(isOurMarketplace)) {
|
|
444
|
+
debug(` Marketplace ${PLUGIN_MARKETPLACE$1} already registered`);
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
const added = await this.runClaude(binary, [
|
|
448
|
+
"plugin",
|
|
449
|
+
"marketplace",
|
|
450
|
+
"add",
|
|
451
|
+
PLUGIN_MARKETPLACE_SOURCE$1
|
|
452
|
+
]);
|
|
453
|
+
if (!added.ok) {
|
|
454
|
+
debug(` Marketplace add failed: ${added.output}`);
|
|
455
|
+
return added.output;
|
|
318
456
|
}
|
|
319
457
|
}
|
|
320
458
|
};
|
|
@@ -429,6 +567,163 @@ var ZedClient = class extends DefaultMCPClient {
|
|
|
429
567
|
};
|
|
430
568
|
//#endregion
|
|
431
569
|
//#region src/steps/add-mcp-server-to-clients/clients/codex.ts
|
|
570
|
+
const PLUGIN_MARKETPLACE = "posthog";
|
|
571
|
+
const PLUGIN_MARKETPLACE_SOURCE = "PostHog/ai-plugin";
|
|
572
|
+
const PLUGIN_REF = `posthog@${PLUGIN_MARKETPLACE}`;
|
|
573
|
+
/**
|
|
574
|
+
* The plugin's row in `codex plugin list`, whose STATUS column reads
|
|
575
|
+
* `installed, enabled` or `not installed`. Registering the marketplace only
|
|
576
|
+
* publishes the catalog, so the marketplace section in config.toml says nothing
|
|
577
|
+
* about whether the plugin itself is there.
|
|
578
|
+
*/
|
|
579
|
+
const listedAsInstalled = (stdout) => {
|
|
580
|
+
const row = new RegExp(`^${PLUGIN_REF}\\s+(.*)$`, "m").exec(stdout)?.[1];
|
|
581
|
+
return !!row && /\binstalled\b/.test(row) && !/\bnot installed\b/.test(row);
|
|
582
|
+
};
|
|
583
|
+
const PLUGIN_STAGES = [
|
|
584
|
+
"plugin install",
|
|
585
|
+
"plugin uninstall",
|
|
586
|
+
"marketplace add"
|
|
587
|
+
];
|
|
588
|
+
const MCP_STAGES = ["MCP add", "MCP remove"];
|
|
589
|
+
const ALL_STAGES = [...PLUGIN_STAGES, ...MCP_STAGES];
|
|
590
|
+
/**
|
|
591
|
+
* Failures in the user's own environment. Reporting them files issues nobody
|
|
592
|
+
* can action, so hand back a hint instead. Drawn from what the codex install
|
|
593
|
+
* path actually produced in the field.
|
|
594
|
+
*
|
|
595
|
+
* Every entry is scoped: a hint that fires on the wrong stage tells the user to
|
|
596
|
+
* run a command that has nothing to do with what just failed.
|
|
597
|
+
*/
|
|
598
|
+
const EXPECTED_FAILURES = [
|
|
599
|
+
{
|
|
600
|
+
match: /unexpected argument|unknown (command|option|argument)|Missing option/i,
|
|
601
|
+
stages: PLUGIN_STAGES,
|
|
602
|
+
hint: "your codex CLI is too old for plugins — update codex, then run `codex plugin marketplace add PostHog/ai-plugin`"
|
|
603
|
+
},
|
|
604
|
+
{
|
|
605
|
+
match: /unexpected argument|unknown (command|option|argument)|Missing option/i,
|
|
606
|
+
stages: MCP_STAGES,
|
|
607
|
+
hint: "your codex CLI is too old for this install — update codex, then run `npx @posthog/wizard mcp add` again"
|
|
608
|
+
},
|
|
609
|
+
{
|
|
610
|
+
match: /ENOENT|not found in PATH|spawn .* ENOENT/i,
|
|
611
|
+
stages: ALL_STAGES,
|
|
612
|
+
hint: "your codex install looks broken — reinstall codex, then run `codex plugin marketplace add PostHog/ai-plugin`"
|
|
613
|
+
},
|
|
614
|
+
{
|
|
615
|
+
match: /failed to load (bootstrap )?configuration|OPENAI_API_KEY|Missing OpenAI API key|(?=[\s\S]*config\.toml)[\s\S]*(invalid type|unknown field|is no longer supported|must contain at least one)/i,
|
|
616
|
+
stages: ALL_STAGES,
|
|
617
|
+
unless: /ai-plugin|plugin\.toml|plugin\.json|marketplace\.toml|posthog@posthog/i,
|
|
618
|
+
hint: "codex could not read its own config — fix what it reports in ~/.codex/config.toml, then retry"
|
|
619
|
+
},
|
|
620
|
+
{
|
|
621
|
+
match: /EACCES|EPERM|permission denied|read-only file system|not permitted/i,
|
|
622
|
+
stages: ALL_STAGES,
|
|
623
|
+
unless: /permission denied \((?:publickey|password|gssapi)/i,
|
|
624
|
+
hint: "codex could not write to its config — fix the permissions on ~/.codex, then retry"
|
|
625
|
+
},
|
|
626
|
+
{
|
|
627
|
+
match: /ENOSPC|no space left/i,
|
|
628
|
+
stages: ALL_STAGES,
|
|
629
|
+
hint: "the disk is full — free some space, then retry"
|
|
630
|
+
},
|
|
631
|
+
{
|
|
632
|
+
match: /git clone .* failed|ENOTFOUND|ETIMEDOUT|ECONNREFUSED|could not resolve host/i,
|
|
633
|
+
stages: ALL_STAGES,
|
|
634
|
+
unless: /repository not found|not found|404|does not exist|authentication failed/i,
|
|
635
|
+
hint: "codex could not reach GitHub to download the plugin — check your network, then retry"
|
|
636
|
+
}
|
|
637
|
+
];
|
|
638
|
+
/**
|
|
639
|
+
* A clone of the plugin marketplace is the slowest thing we run. Past this the
|
|
640
|
+
* command is not slow, it is stuck, and the wizard should say so rather than
|
|
641
|
+
* wait forever.
|
|
642
|
+
*/
|
|
643
|
+
const RUN_TIMEOUT_MS = 12e4;
|
|
644
|
+
/**
|
|
645
|
+
* `execFile` kills the child once output passes this. The default is 1 MB,
|
|
646
|
+
* which a verbose clone can reach, and the kill then looks like codex rejecting
|
|
647
|
+
* the install rather than us cutting it off.
|
|
648
|
+
*/
|
|
649
|
+
const MAX_OUTPUT_BYTES = 16 * 1024 * 1024;
|
|
650
|
+
/**
|
|
651
|
+
* What `execFile` puts in `error.message` when the command itself never spoke:
|
|
652
|
+
* the full binary path and arguments. That path contains the user's home
|
|
653
|
+
* directory, so reporting it fingerprints one root cause per machine — the
|
|
654
|
+
* failure this reporting was built to stop. Never send it onward.
|
|
655
|
+
*/
|
|
656
|
+
const COMMAND_FAILED_PREAMBLE = /^Command failed:.*$/m;
|
|
657
|
+
/**
|
|
658
|
+
* The cause when neither stream carried one. `execFile` always sets a message,
|
|
659
|
+
* so there is no "empty error" case to fall through — the message just isn't
|
|
660
|
+
* usable as it stands.
|
|
661
|
+
*/
|
|
662
|
+
const describeExecFailure = (error) => {
|
|
663
|
+
if (error.code === "ERR_CHILD_PROCESS_STDIO_MAXBUFFER") return "codex produced more output than the wizard can hold, so it was stopped";
|
|
664
|
+
if (error.killed) return `codex did not finish within ${RUN_TIMEOUT_MS / 1e3}s, so it was stopped`;
|
|
665
|
+
if (error.signal) return `codex was killed by ${error.signal}`;
|
|
666
|
+
const said = error.message.replace(COMMAND_FAILED_PREAMBLE, "").trim();
|
|
667
|
+
if (said) return said;
|
|
668
|
+
if (typeof error.code === "number") return `codex exited with code ${error.code}`;
|
|
669
|
+
if (error.code) return `codex failed with ${error.code}`;
|
|
670
|
+
return "codex failed without reporting a reason";
|
|
671
|
+
};
|
|
672
|
+
/**
|
|
673
|
+
* One codex invocation. Async on purpose: `plugin marketplace add` and
|
|
674
|
+
* `plugin add` clone git repositories and take seconds, and a synchronous child
|
|
675
|
+
* process blocks the event loop, which freezes the TUI spinner on its first
|
|
676
|
+
* frame. Never throws; the caller decides what a failure means.
|
|
677
|
+
*
|
|
678
|
+
* A failure's cause is split across the error and the two streams, and none of
|
|
679
|
+
* them carries it when the process merely exits non-zero — reading one alone
|
|
680
|
+
* reported a blank reason and filed an exception carrying nothing.
|
|
681
|
+
*/
|
|
682
|
+
const runCodex = (binary, args, env) => new Promise((resolve) => {
|
|
683
|
+
execFile(binary, args, {
|
|
684
|
+
env,
|
|
685
|
+
timeout: RUN_TIMEOUT_MS,
|
|
686
|
+
maxBuffer: MAX_OUTPUT_BYTES
|
|
687
|
+
}, (error, stdout, stderr) => {
|
|
688
|
+
if (!error) return resolve({
|
|
689
|
+
ok: true,
|
|
690
|
+
output: stdout ?? ""
|
|
691
|
+
});
|
|
692
|
+
const said = [stderr, stdout].map((p) => p ? String(p).trim() : "").filter(Boolean).join("\n");
|
|
693
|
+
resolve({
|
|
694
|
+
ok: false,
|
|
695
|
+
output: redactSecrets(error.killed || !!error.signal || error.code === "ERR_CHILD_PROCESS_STDIO_MAXBUFFER" || !said ? describeExecFailure(error) : said)
|
|
696
|
+
});
|
|
697
|
+
}).stdin?.end();
|
|
698
|
+
});
|
|
699
|
+
/**
|
|
700
|
+
* Turn a failed spawn into a result: an expected local failure becomes a hint,
|
|
701
|
+
* anything else is reported under a constant message so one root cause stays
|
|
702
|
+
* one issue, with the varying detail in properties.
|
|
703
|
+
*/
|
|
704
|
+
const reportSpawnFailure = (stage, details) => {
|
|
705
|
+
const hint = expectedFailureHint(details, EXPECTED_FAILURES, stage);
|
|
706
|
+
if (hint) {
|
|
707
|
+
analytics.wizardCapture("mcp expected failure hinted", {
|
|
708
|
+
client: "Codex",
|
|
709
|
+
stage,
|
|
710
|
+
hint,
|
|
711
|
+
details: scrubHomePaths(details)
|
|
712
|
+
});
|
|
713
|
+
return {
|
|
714
|
+
success: false,
|
|
715
|
+
reason: hint
|
|
716
|
+
};
|
|
717
|
+
}
|
|
718
|
+
analytics.captureException(/* @__PURE__ */ new Error(`Codex ${stage} failed`), {
|
|
719
|
+
stage,
|
|
720
|
+
details: scrubHomePaths(details)
|
|
721
|
+
});
|
|
722
|
+
return {
|
|
723
|
+
success: false,
|
|
724
|
+
reason: details
|
|
725
|
+
};
|
|
726
|
+
};
|
|
432
727
|
/** Wording codex uses when the thing we're adding is already registered. */
|
|
433
728
|
const ALREADY_INSTALLED_PATTERN = /already (installed|exists|added|registered)/i;
|
|
434
729
|
/** Wording that means the opposite: a cache entry exists but the plugin doesn't. */
|
|
@@ -490,16 +785,16 @@ var CodexMCPClient = class extends DefaultMCPClient {
|
|
|
490
785
|
return Promise.resolve(false);
|
|
491
786
|
}
|
|
492
787
|
}
|
|
493
|
-
addServer(apiKey, selectedFeatures, local) {
|
|
788
|
+
async addServer(apiKey, selectedFeatures, local) {
|
|
494
789
|
const serverName = local ? "posthog-local" : "posthog";
|
|
495
790
|
const url = buildMCPUrl(selectedFeatures, local);
|
|
496
791
|
if (apiKey) {
|
|
497
792
|
const binary = this.findCodexBinary();
|
|
498
|
-
if (!binary) return
|
|
793
|
+
if (!binary) return {
|
|
499
794
|
success: false,
|
|
500
795
|
reason: "An API-key install into Codex needs the codex CLI."
|
|
501
|
-
}
|
|
502
|
-
const result =
|
|
796
|
+
};
|
|
797
|
+
const result = await runCodex(binary, [
|
|
503
798
|
"mcp",
|
|
504
799
|
"add",
|
|
505
800
|
serverName,
|
|
@@ -508,28 +803,19 @@ var CodexMCPClient = class extends DefaultMCPClient {
|
|
|
508
803
|
"--bearer-token-env-var",
|
|
509
804
|
"POSTHOG_AUTH_HEADER"
|
|
510
805
|
], {
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
...process.env,
|
|
514
|
-
POSTHOG_AUTH_HEADER: `Bearer ${apiKey}`
|
|
515
|
-
}
|
|
806
|
+
...process.env,
|
|
807
|
+
POSTHOG_AUTH_HEADER: `Bearer ${apiKey}`
|
|
516
808
|
});
|
|
517
|
-
if (result.
|
|
518
|
-
|
|
519
|
-
if (ALREADY_INSTALLED_PATTERN.test(stderr)) return Promise.resolve({
|
|
809
|
+
if (!result.ok) {
|
|
810
|
+
if (ALREADY_INSTALLED_PATTERN.test(result.output)) return {
|
|
520
811
|
success: true,
|
|
521
812
|
alreadyInstalled: true
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
analytics.captureException(/* @__PURE__ */ new Error(`Codex MCP add failed: ${reason}`));
|
|
525
|
-
return Promise.resolve({
|
|
526
|
-
success: false,
|
|
527
|
-
reason
|
|
528
|
-
});
|
|
813
|
+
};
|
|
814
|
+
return reportSpawnFailure("MCP add", result.output);
|
|
529
815
|
}
|
|
530
|
-
return
|
|
816
|
+
return { success: true };
|
|
531
817
|
}
|
|
532
|
-
return
|
|
818
|
+
return this.writeServerSection(serverName, url);
|
|
533
819
|
}
|
|
534
820
|
/**
|
|
535
821
|
* Create or update the `[mcp_servers.<name>]` section in config.toml, editing
|
|
@@ -561,7 +847,7 @@ var CodexMCPClient = class extends DefaultMCPClient {
|
|
|
561
847
|
return { success: true };
|
|
562
848
|
} catch (error) {
|
|
563
849
|
const reason = error instanceof Error ? error.message : String(error);
|
|
564
|
-
analytics.captureException(/* @__PURE__ */ new Error(
|
|
850
|
+
analytics.captureException(/* @__PURE__ */ new Error("Codex config.toml write failed"), { details: scrubHomePaths(reason) });
|
|
565
851
|
return {
|
|
566
852
|
success: false,
|
|
567
853
|
reason
|
|
@@ -579,26 +865,19 @@ var CodexMCPClient = class extends DefaultMCPClient {
|
|
|
579
865
|
if (!this.findCodexBinary()) return null;
|
|
580
866
|
return `codex mcp login ${local ? "posthog-local" : "posthog"}`;
|
|
581
867
|
}
|
|
582
|
-
removeServer(local) {
|
|
868
|
+
async removeServer(local) {
|
|
583
869
|
const binary = this.findCodexBinary();
|
|
584
|
-
if (!binary) return
|
|
870
|
+
if (!binary) return {
|
|
585
871
|
success: false,
|
|
586
872
|
reason: "The codex CLI is no longer on your PATH."
|
|
587
|
-
}
|
|
588
|
-
const result =
|
|
873
|
+
};
|
|
874
|
+
const result = await runCodex(binary, [
|
|
589
875
|
"mcp",
|
|
590
876
|
"remove",
|
|
591
877
|
local ? "posthog-local" : "posthog"
|
|
592
|
-
]
|
|
593
|
-
if (result.
|
|
594
|
-
|
|
595
|
-
analytics.captureException(/* @__PURE__ */ new Error(`Failed to remove server from Codex CLI: ${reason}`));
|
|
596
|
-
return Promise.resolve({
|
|
597
|
-
success: false,
|
|
598
|
-
reason
|
|
599
|
-
});
|
|
600
|
-
}
|
|
601
|
-
return Promise.resolve({ success: true });
|
|
878
|
+
]);
|
|
879
|
+
if (!result.ok) return reportSpawnFailure("MCP remove", result.output);
|
|
880
|
+
return { success: true };
|
|
602
881
|
}
|
|
603
882
|
/** The codex marketplace plugin ships skills only — the MCP server needs its own entry. */
|
|
604
883
|
pluginBundlesMcpServer() {
|
|
@@ -607,13 +886,33 @@ var CodexMCPClient = class extends DefaultMCPClient {
|
|
|
607
886
|
supportsPlugin() {
|
|
608
887
|
return this.findCodexBinary() !== null;
|
|
609
888
|
}
|
|
610
|
-
|
|
611
|
-
|
|
889
|
+
/** The plugin itself, as the CLI reports it. The install decision's question. */
|
|
890
|
+
async isPluginPresent() {
|
|
891
|
+
const binary = this.findCodexBinary();
|
|
892
|
+
if (!binary) return false;
|
|
893
|
+
const result = await runCodex(binary, [
|
|
894
|
+
"plugin",
|
|
895
|
+
"list",
|
|
896
|
+
"-m",
|
|
897
|
+
PLUGIN_MARKETPLACE
|
|
898
|
+
]);
|
|
899
|
+
return result.ok && listedAsInstalled(result.output);
|
|
900
|
+
}
|
|
901
|
+
/**
|
|
902
|
+
* Anything of ours left on the machine, which is what `index.ts` asks before
|
|
903
|
+
* offering removal. A registered marketplace with no plugin is a state the
|
|
904
|
+
* wizard created — and the state this branch exists to correct — so removal
|
|
905
|
+
* has to see it, or `removePlugin` never runs and the catalog stays forever.
|
|
906
|
+
*/
|
|
907
|
+
async isPluginInstalled() {
|
|
908
|
+
return await this.isPluginPresent() || this.isMarketplaceRegistered();
|
|
909
|
+
}
|
|
910
|
+
/** The catalog, which the plugin is installed *from* — not the plugin. */
|
|
911
|
+
isMarketplaceRegistered() {
|
|
612
912
|
try {
|
|
613
|
-
|
|
614
|
-
return Promise.resolve(contents.toLowerCase().includes("[marketplaces.posthog]"));
|
|
913
|
+
return fs$1.readFileSync(this.configPath(), "utf-8").toLowerCase().includes(`[marketplaces.${PLUGIN_MARKETPLACE}]`);
|
|
615
914
|
} catch {
|
|
616
|
-
return
|
|
915
|
+
return false;
|
|
617
916
|
}
|
|
618
917
|
}
|
|
619
918
|
async removePlugin() {
|
|
@@ -622,23 +921,25 @@ var CodexMCPClient = class extends DefaultMCPClient {
|
|
|
622
921
|
success: false,
|
|
623
922
|
reason: "The codex CLI is no longer on your PATH."
|
|
624
923
|
};
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
924
|
+
const steps = [];
|
|
925
|
+
if (await this.isPluginPresent()) steps.push([
|
|
926
|
+
"plugin",
|
|
927
|
+
"remove",
|
|
928
|
+
PLUGIN_REF
|
|
929
|
+
]);
|
|
930
|
+
if (this.isMarketplaceRegistered()) steps.push([
|
|
630
931
|
"plugin",
|
|
631
932
|
"marketplace",
|
|
632
933
|
"remove",
|
|
633
|
-
|
|
634
|
-
]
|
|
635
|
-
if (
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
934
|
+
PLUGIN_MARKETPLACE
|
|
935
|
+
]);
|
|
936
|
+
if (steps.length === 0) return {
|
|
937
|
+
success: true,
|
|
938
|
+
alreadyInstalled: true
|
|
939
|
+
};
|
|
940
|
+
for (const args of steps) {
|
|
941
|
+
const result = await runCodex(binary, args);
|
|
942
|
+
if (!result.ok) return reportSpawnFailure("plugin uninstall", result.output);
|
|
642
943
|
}
|
|
643
944
|
return { success: true };
|
|
644
945
|
}
|
|
@@ -648,39 +949,53 @@ var CodexMCPClient = class extends DefaultMCPClient {
|
|
|
648
949
|
success: false,
|
|
649
950
|
reason: "The codex CLI is no longer on your PATH."
|
|
650
951
|
};
|
|
651
|
-
if (await this.
|
|
952
|
+
if (await this.isPluginPresent()) return {
|
|
652
953
|
success: true,
|
|
653
954
|
alreadyInstalled: true
|
|
654
955
|
};
|
|
655
|
-
const
|
|
956
|
+
const marketplace = this.isMarketplaceRegistered() ? null : await this.registerMarketplace(binary);
|
|
957
|
+
if (marketplace && !marketplace.success) return marketplace;
|
|
958
|
+
const result = await runCodex(binary, [
|
|
959
|
+
"plugin",
|
|
960
|
+
"add",
|
|
961
|
+
PLUGIN_REF
|
|
962
|
+
]);
|
|
963
|
+
if (!result.ok) {
|
|
964
|
+
if (ALREADY_INSTALLED_PATTERN.test(result.output)) return {
|
|
965
|
+
success: true,
|
|
966
|
+
alreadyInstalled: true
|
|
967
|
+
};
|
|
968
|
+
return reportSpawnFailure("plugin install", result.output);
|
|
969
|
+
}
|
|
970
|
+
return { success: true };
|
|
971
|
+
}
|
|
972
|
+
/**
|
|
973
|
+
* Add the catalog the plugin is published in. A stale cache directory with no
|
|
974
|
+
* config.toml entry reports the marketplace as added from a different source;
|
|
975
|
+
* clear it and retry once.
|
|
976
|
+
*/
|
|
977
|
+
async registerMarketplace(binary) {
|
|
978
|
+
const run = () => runCodex(binary, [
|
|
656
979
|
"plugin",
|
|
657
980
|
"marketplace",
|
|
658
981
|
"add",
|
|
659
|
-
|
|
660
|
-
]
|
|
661
|
-
let result = run();
|
|
662
|
-
if (result.
|
|
663
|
-
const staleDir = path$2.join(os.homedir(), ".codex", ".tmp", "marketplaces",
|
|
982
|
+
PLUGIN_MARKETPLACE_SOURCE
|
|
983
|
+
]);
|
|
984
|
+
let result = await run();
|
|
985
|
+
if (!result.ok && STALE_MARKETPLACE_CACHE.test(result.output)) {
|
|
986
|
+
const staleDir = path$2.join(os.homedir(), ".codex", ".tmp", "marketplaces", PLUGIN_MARKETPLACE);
|
|
664
987
|
try {
|
|
665
988
|
fs$1.rmSync(staleDir, {
|
|
666
989
|
recursive: true,
|
|
667
990
|
force: true
|
|
668
991
|
});
|
|
669
992
|
} catch {}
|
|
670
|
-
result = run();
|
|
993
|
+
result = await run();
|
|
671
994
|
}
|
|
672
|
-
if (result.
|
|
673
|
-
const
|
|
674
|
-
if (ALREADY_INSTALLED_PATTERN.test(
|
|
675
|
-
|
|
676
|
-
alreadyInstalled: true
|
|
677
|
-
};
|
|
678
|
-
const reason = redactSecrets(stderr);
|
|
679
|
-
analytics.captureException(/* @__PURE__ */ new Error(`Codex plugin install failed: ${reason}`));
|
|
680
|
-
return {
|
|
681
|
-
success: false,
|
|
682
|
-
reason
|
|
683
|
-
};
|
|
995
|
+
if (!result.ok) {
|
|
996
|
+
const details = result.output;
|
|
997
|
+
if (ALREADY_INSTALLED_PATTERN.test(details) && !STALE_MARKETPLACE_CACHE.test(details)) return { success: true };
|
|
998
|
+
return reportSpawnFailure("marketplace add", details);
|
|
684
999
|
}
|
|
685
1000
|
return { success: true };
|
|
686
1001
|
}
|
|
@@ -900,4 +1215,4 @@ const removeMCPServer = async (clients, local) => {
|
|
|
900
1215
|
//#endregion
|
|
901
1216
|
export { getSupportedClients as a, removeMCPServer as c, getInstalledClients as i, removeMCPServerFromClientsStep as l, addMCPServerToClientsStep as n, getSupportedPluginClients as o, add_mcp_server_to_clients_exports as r, installPlugins as s, addMCPServer as t, isPluginCapable as u };
|
|
902
1217
|
|
|
903
|
-
//# sourceMappingURL=add-mcp-server-to-clients-
|
|
1218
|
+
//# sourceMappingURL=add-mcp-server-to-clients-JMv8LP-O.js.map
|