@posthog/wizard 2.76.0 → 2.77.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/dist/README.md +16 -15
- package/dist/{add-mcp-server-to-clients-Exddicp2.js → add-mcp-server-to-clients-BnRyE4pw.js} +428 -114
- package/dist/add-mcp-server-to-clients-BnRyE4pw.js.map +1 -0
- package/dist/{agent-interface-CZWRgZMc.js → agent-interface-Avtr_5M5.js} +34 -10
- package/dist/agent-interface-Avtr_5M5.js.map +1 -0
- package/dist/{agent-prompt-loader-BobuLDIg.js → agent-prompt-loader-CHixNPgY.js} +23 -7
- package/dist/agent-prompt-loader-CHixNPgY.js.map +1 -0
- package/dist/{agent-runner-C_R1X_UT.js → agent-runner-COOIUJCP.js} +171 -83
- package/dist/agent-runner-COOIUJCP.js.map +1 -0
- package/dist/{analytics-C_RyE8fz.js → analytics-C67F2vee.js} +2 -2
- package/dist/{analytics-C_RyE8fz.js.map → analytics-C67F2vee.js.map} +1 -1
- package/dist/analytics-CJA1uLlk.js +2 -0
- package/dist/{api-k5aGQpIZ.js → api-Dj1yabTj.js} +3 -3
- package/dist/{api-k5aGQpIZ.js.map → api-Dj1yabTj.js.map} +1 -1
- package/dist/bin.js +41 -41
- package/dist/bin.js.map +1 -1
- package/dist/{bounded-fs-BHLy83N9.js → bounded-fs-CWRYuLAn.js} +3 -3
- package/dist/bounded-fs-CWRYuLAn.js.map +1 -0
- package/dist/{ci-install-CXt4c41q.js → ci-install-CvXL5h13.js} +5 -5
- package/dist/{ci-install-CXt4c41q.js.map → ci-install-CvXL5h13.js.map} +1 -1
- package/dist/{debug-C5Zz8hmm.js → debug-B4kzIZPi.js} +12 -9
- package/dist/debug-B4kzIZPi.js.map +1 -0
- package/dist/{debug-BxMMpepn.js → debug-CziFS0cA.js} +1 -1
- package/dist/{defaults-DulzMJpN.js → defaults-4c4YwTmW.js} +26 -3
- package/dist/defaults-4c4YwTmW.js.map +1 -0
- package/dist/{env-api-key-Ca-CrkgV.js → env-api-key-BZ5wE3Y4.js} +2 -2
- package/dist/{env-api-key-Ca-CrkgV.js.map → env-api-key-BZ5wE3Y4.js.map} +1 -1
- package/dist/{environment-B0uTamFf.js → environment-BEvsey6i.js} +4 -4
- package/dist/{environment-B0uTamFf.js.map → environment-BEvsey6i.js.map} +1 -1
- package/dist/{errors--OqLxmWR.js → errors-BoJvrdw8.js} +4 -2
- package/dist/errors-BoJvrdw8.js.map +1 -0
- package/dist/{file-CNstcW8F.js → file-BoD3REGB.js} +2 -2
- package/dist/{file-CNstcW8F.js.map → file-BoD3REGB.js.map} +1 -1
- package/dist/{file-watcher-CiT-oZpu.js → file-watcher-BPFazvG_.js} +2 -2
- package/dist/{file-watcher-CiT-oZpu.js.map → file-watcher-BPFazvG_.js.map} +1 -1
- package/dist/{gateway-session-BIVN_Xfr.js → gateway-session-C118uACz.js} +1 -1
- package/dist/{gateway-session-C3Uqwc4R.js → gateway-session-xPFv6p5c.js} +5 -5
- package/dist/{gateway-session-C3Uqwc4R.js.map → gateway-session-xPFv6p5c.js.map} +1 -1
- package/dist/{headless-ui-TpSp-F43.js → headless-ui-CsmQrDIl.js} +2 -2
- package/dist/{headless-ui-TpSp-F43.js.map → headless-ui-CsmQrDIl.js.map} +1 -1
- package/dist/{interactive-B72L-sO5.js → interactive-Dej-sxvR.js} +2 -2
- package/dist/{interactive-B72L-sO5.js.map → interactive-Dej-sxvR.js.map} +1 -1
- package/dist/{mcp-CNc6CLK0.js → mcp-Cbuw_xss.js} +2 -2
- package/dist/{mcp-CNc6CLK0.js.map → mcp-Cbuw_xss.js.map} +1 -1
- package/dist/{mcp-prompt-streaming-BvBNkzjv.js → mcp-prompt-streaming-BU_kuur_.js} +5 -5
- package/dist/{mcp-prompt-streaming-BvBNkzjv.js.map → mcp-prompt-streaming-BU_kuur_.js.map} +1 -1
- package/dist/{mint-failure-CZ5FZ0Jd.js → mint-failure-BrleGqMd.js} +72 -39
- package/dist/mint-failure-BrleGqMd.js.map +1 -0
- package/dist/{non-interactive-UeQlnU0U.js → non-interactive-DcOjH2fw.js} +3 -3
- package/dist/{non-interactive-UeQlnU0U.js.map → non-interactive-DcOjH2fw.js.map} +1 -1
- package/dist/{orchestrator-tools-CLADku26.js → orchestrator-tools-DXwr8Sp3.js} +4 -4
- package/dist/orchestrator-tools-DXwr8Sp3.js.map +1 -0
- package/dist/{package-manager-CppzeIgu.js → package-manager-DR23m5Jg.js} +2 -2
- package/dist/{package-manager-CppzeIgu.js.map → package-manager-DR23m5Jg.js.map} +1 -1
- package/dist/{pi-Bs1Tbt0C.js → pi-mY8I2XkG.js} +13 -13
- package/dist/{pi-Bs1Tbt0C.js.map → pi-mY8I2XkG.js.map} +1 -1
- package/dist/{playground-CZgZX4j0.js → playground-CDUUKLkC.js} +13 -9
- package/dist/playground-CDUUKLkC.js.map +1 -0
- package/dist/{posthog-BZ3NNCyh.js → posthog-Hc_-9wrr.js} +2 -2
- package/dist/{posthog-BZ3NNCyh.js.map → posthog-Hc_-9wrr.js.map} +1 -1
- package/dist/{provisioning-Ba7GWKzK.js → provisioning-xfdjhFtA.js} +3 -3
- package/dist/{provisioning-Ba7GWKzK.js.map → provisioning-xfdjhFtA.js.map} +1 -1
- package/dist/{queue-tools-D09PNS0X.js → queue-tools-C8y_xZJi.js} +8 -4
- package/dist/queue-tools-C8y_xZJi.js.map +1 -0
- package/dist/{registry-COcpEsMD.js → registry-DTmREJ-f.js} +5 -5
- package/dist/{registry-COcpEsMD.js.map → registry-DTmREJ-f.js.map} +1 -1
- package/dist/{security-CpAT0fZa.js → security-Dw2oFJjP.js} +5 -5
- package/dist/{security-CpAT0fZa.js.map → security-Dw2oFJjP.js.map} +1 -1
- package/dist/{setup-utils-BUAoRjw3.js → setup-utils-fjJTBhaB.js} +8 -8
- package/dist/setup-utils-fjJTBhaB.js.map +1 -0
- package/dist/{start-tui-Bz23_yym.js → start-tui-UNe2xQ0U.js} +25 -25
- package/dist/start-tui-UNe2xQ0U.js.map +1 -0
- package/dist/{steps-DbsDish5.js → steps-C2yqOk_h.js} +7 -7
- package/dist/{steps-DbsDish5.js.map → steps-C2yqOk_h.js.map} +1 -1
- package/dist/{store-D5ROpUje.js → store-Bic4Cr3L.js} +5 -32
- package/dist/store-Bic4Cr3L.js.map +1 -0
- package/dist/{subagent-CSBZnhgK.js → subagent-Dz41vV9j.js} +2 -2
- package/dist/{subagent-CSBZnhgK.js.map → subagent-Dz41vV9j.js.map} +1 -1
- package/dist/{task-D8sTR7jZ.js → task-5-fw_Vw3.js} +14 -14
- package/dist/{task-D8sTR7jZ.js.map → task-5-fw_Vw3.js.map} +1 -1
- package/dist/{task-stream-Dl0XEsZ9.js → task-stream-dVzl6b_q.js} +6 -6
- package/dist/{task-stream-Dl0XEsZ9.js.map → task-stream-dVzl6b_q.js.map} +1 -1
- package/dist/{tasks-BDt427kT.js → tasks-D1c2z1aw.js} +2 -2
- package/dist/{tasks-BDt427kT.js.map → tasks-D1c2z1aw.js.map} +1 -1
- package/dist/{telemetry-Dp6zjZBj.js → telemetry-BRnxBRWK.js} +3 -3
- package/dist/{telemetry-Dp6zjZBj.js.map → telemetry-BRnxBRWK.js.map} +1 -1
- package/dist/{terminal-pInlleVD.js → terminal-9bvRa4Qt.js} +38 -34
- package/dist/terminal-9bvRa4Qt.js.map +1 -0
- package/dist/{tools-MkyMOjQI.js → tools-Dp6i9k70.js} +8 -8
- package/dist/{tools-MkyMOjQI.js.map → tools-Dp6i9k70.js.map} +1 -1
- package/dist/{wizard-abort-BHLKVKLN.js → wizard-abort-CAcInAxg.js} +1 -1
- package/dist/{wizard-abort-BCnUgT9z.js → wizard-abort-lE6umflt.js} +4 -4
- package/dist/{wizard-abort-BCnUgT9z.js.map → wizard-abort-lE6umflt.js.map} +1 -1
- package/dist/{yara-hooks-BJWVgTpU.js → yara-hooks-BTNJ6MGW.js} +4 -4
- package/dist/{yara-hooks-BJWVgTpU.js.map → yara-hooks-BTNJ6MGW.js.map} +1 -1
- package/dist/yara-hooks-CFY4pGcW.js +2 -0
- package/package.json +8 -1
- package/dist/add-mcp-server-to-clients-Exddicp2.js.map +0 -1
- package/dist/agent-interface-CZWRgZMc.js.map +0 -1
- package/dist/agent-prompt-loader-BobuLDIg.js.map +0 -1
- package/dist/agent-runner-C_R1X_UT.js.map +0 -1
- package/dist/analytics-DXvdQqyp.js +0 -2
- package/dist/bounded-fs-BHLy83N9.js.map +0 -1
- package/dist/debug-C5Zz8hmm.js.map +0 -1
- package/dist/defaults-DulzMJpN.js.map +0 -1
- package/dist/errors--OqLxmWR.js.map +0 -1
- package/dist/mint-failure-CZ5FZ0Jd.js.map +0 -1
- package/dist/orchestrator-tools-CLADku26.js.map +0 -1
- package/dist/playground-CZgZX4j0.js.map +0 -1
- package/dist/queue-tools-D09PNS0X.js.map +0 -1
- package/dist/setup-utils-BUAoRjw3.js.map +0 -1
- package/dist/start-tui-Bz23_yym.js.map +0 -1
- package/dist/store-D5ROpUje.js.map +0 -1
- package/dist/terminal-pInlleVD.js.map +0 -1
- package/dist/yara-hooks-Dp82xJGd.js +0 -2
package/dist/{add-mcp-server-to-clients-Exddicp2.js → add-mcp-server-to-clients-BnRyE4pw.js}
RENAMED
|
@@ -1,18 +1,18 @@
|
|
|
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 { a as getNativeHTTPServerConfig,
|
|
2
|
+
import { Ct as runtimeEnv, p as getUI, r as debug } from "./debug-B4kzIZPi.js";
|
|
3
|
+
import { n as analytics } from "./analytics-C67F2vee.js";
|
|
4
|
+
import { n as openTrackedLink, t as withProgress } from "./telemetry-BRnxBRWK.js";
|
|
5
|
+
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-4c4YwTmW.js";
|
|
6
6
|
import * as fs$2 from "fs";
|
|
7
7
|
import * as path$3 from "path";
|
|
8
8
|
import * as os from "node:os";
|
|
9
9
|
import * as path$2 from "node:path";
|
|
10
|
-
import {
|
|
10
|
+
import { execFile, execSync } from "node:child_process";
|
|
11
11
|
import * as fs$1 from "node:fs";
|
|
12
12
|
import z$1 from "zod";
|
|
13
13
|
import * as os$1 from "os";
|
|
14
14
|
import * as jsonc from "jsonc-parser";
|
|
15
|
-
import { execSync as execSync$1 } from "child_process";
|
|
15
|
+
import { execFile as execFile$1, execSync as execSync$1 } from "child_process";
|
|
16
16
|
//#region src/steps/add-mcp-server-to-clients/MCPClient.ts
|
|
17
17
|
var MCPClient = class {
|
|
18
18
|
name;
|
|
@@ -129,6 +129,31 @@ var CursorMCPClient = class extends DefaultMCPClient {
|
|
|
129
129
|
};
|
|
130
130
|
//#endregion
|
|
131
131
|
//#region src/steps/add-mcp-server-to-clients/clients/claude-code.ts
|
|
132
|
+
const PLUGIN_NAME = "posthog";
|
|
133
|
+
const PLUGIN_MARKETPLACE$1 = "posthog";
|
|
134
|
+
const PLUGIN_MARKETPLACE_SOURCE$1 = "PostHog/ai-plugin";
|
|
135
|
+
const PLUGIN_REF$1 = `${PLUGIN_NAME}@${PLUGIN_MARKETPLACE$1}`;
|
|
136
|
+
/** The plugin is missing from every catalog the CLI can currently see. */
|
|
137
|
+
const NOT_IN_A_MARKETPLACE = /not found in/i;
|
|
138
|
+
/**
|
|
139
|
+
* `plugin marketplace add` clones a git repository, the slowest thing we run.
|
|
140
|
+
* Past this the command is not slow, it is stuck, and a clone waiting on a
|
|
141
|
+
* credential prompt would otherwise hang the wizard with the spinner frozen.
|
|
142
|
+
*/
|
|
143
|
+
const RUN_TIMEOUT_MS$1 = 12e4;
|
|
144
|
+
/**
|
|
145
|
+
* `execFile` kills the child once output passes this. The default is 1 MB,
|
|
146
|
+
* which a verbose clone can reach, and the kill then looks like Claude Code
|
|
147
|
+
* rejecting the install rather than us cutting it off.
|
|
148
|
+
*/
|
|
149
|
+
const MAX_OUTPUT_BYTES$1 = 16 * 1024 * 1024;
|
|
150
|
+
/**
|
|
151
|
+
* Our catalog, by name *and* repository. A marketplace merely called `posthog`
|
|
152
|
+
* may be someone else's, and neither installing from it nor removing it is
|
|
153
|
+
* ours to do. `repo` is absent on CLIs predating it, where the name is all
|
|
154
|
+
* there is.
|
|
155
|
+
*/
|
|
156
|
+
const isOurMarketplace = (m) => m?.name === PLUGIN_MARKETPLACE$1 && (m.repo === void 0 || m.repo.toLowerCase() === PLUGIN_MARKETPLACE_SOURCE$1.toLowerCase());
|
|
132
157
|
var ClaudeCodeMCPClient = class extends DefaultMCPClient {
|
|
133
158
|
name = "Claude Code";
|
|
134
159
|
claudeBinaryPath = null;
|
|
@@ -235,21 +260,39 @@ var ClaudeCodeMCPClient = class extends DefaultMCPClient {
|
|
|
235
260
|
success: false,
|
|
236
261
|
reason: "The claude CLI is no longer on your PATH."
|
|
237
262
|
};
|
|
238
|
-
|
|
263
|
+
const ids = await this.installedPluginIds(binary);
|
|
264
|
+
const marketplace = await this.ourMarketplaceRegistered(binary);
|
|
265
|
+
const nothingInstalled = ids?.length === 0 || ids === null && !await this.isPluginInstalled();
|
|
266
|
+
if (nothingInstalled && !marketplace) return {
|
|
239
267
|
success: true,
|
|
240
268
|
alreadyInstalled: true
|
|
241
269
|
};
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
};
|
|
270
|
+
const targets = nothingInstalled ? [] : ids?.length ? ids : [PLUGIN_NAME];
|
|
271
|
+
const failures = [];
|
|
272
|
+
for (const target of targets) {
|
|
273
|
+
const run = await this.runClaude(binary, [
|
|
274
|
+
"plugin",
|
|
275
|
+
"uninstall",
|
|
276
|
+
target
|
|
277
|
+
]);
|
|
278
|
+
if (!run.ok) failures.push(`${target}: ${run.output}`);
|
|
252
279
|
}
|
|
280
|
+
if (marketplace) {
|
|
281
|
+
const run = await this.runClaude(binary, [
|
|
282
|
+
"plugin",
|
|
283
|
+
"marketplace",
|
|
284
|
+
"remove",
|
|
285
|
+
PLUGIN_MARKETPLACE$1
|
|
286
|
+
]);
|
|
287
|
+
if (!run.ok) failures.push(`${PLUGIN_MARKETPLACE$1}: ${run.output}`);
|
|
288
|
+
}
|
|
289
|
+
if (failures.length === 0) return { success: true };
|
|
290
|
+
const reason = failures.join("; ");
|
|
291
|
+
analytics.captureException(/* @__PURE__ */ new Error(`Claude Code plugin uninstall failed: ${reason}`));
|
|
292
|
+
return {
|
|
293
|
+
success: false,
|
|
294
|
+
reason
|
|
295
|
+
};
|
|
253
296
|
}
|
|
254
297
|
removeServer(local) {
|
|
255
298
|
const claudeBinary = this.findClaudeBinary();
|
|
@@ -281,40 +324,134 @@ var ClaudeCodeMCPClient = class extends DefaultMCPClient {
|
|
|
281
324
|
supportsPlugin() {
|
|
282
325
|
return this.findClaudeBinary() !== null;
|
|
283
326
|
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
327
|
+
runClaude(binary, args) {
|
|
328
|
+
return new Promise((resolve) => {
|
|
329
|
+
execFile$1(binary, args, {
|
|
330
|
+
timeout: RUN_TIMEOUT_MS$1,
|
|
331
|
+
maxBuffer: MAX_OUTPUT_BYTES$1
|
|
332
|
+
}, (error, stdout) => {
|
|
333
|
+
if (!error) return resolve({
|
|
334
|
+
ok: true,
|
|
335
|
+
output: stdout?.toString() ?? ""
|
|
336
|
+
});
|
|
337
|
+
if (error.code === "ERR_CHILD_PROCESS_STDIO_MAXBUFFER") return resolve({
|
|
338
|
+
ok: false,
|
|
339
|
+
output: "claude produced more output than the wizard can hold, so it was stopped"
|
|
340
|
+
});
|
|
341
|
+
if (error.killed || error.signal) return resolve({
|
|
342
|
+
ok: false,
|
|
343
|
+
output: `claude did not finish within ${RUN_TIMEOUT_MS$1 / 1e3}s, so it was stopped`
|
|
344
|
+
});
|
|
345
|
+
resolve({
|
|
346
|
+
ok: false,
|
|
347
|
+
output: scrubHomePaths(redactSecrets(error.message))
|
|
348
|
+
});
|
|
349
|
+
});
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
/** Null when `--json` is unsupported, the command failed, or output didn't parse — never "nothing installed". */
|
|
353
|
+
async listJson(binary, args) {
|
|
354
|
+
const result = await this.runClaude(binary, [...args, "--json"]);
|
|
355
|
+
if (!result.ok) return null;
|
|
287
356
|
try {
|
|
288
|
-
const
|
|
289
|
-
return
|
|
357
|
+
const parsed = JSON.parse(result.output);
|
|
358
|
+
return Array.isArray(parsed) ? parsed : null;
|
|
290
359
|
} catch {
|
|
291
|
-
return
|
|
360
|
+
return null;
|
|
292
361
|
}
|
|
293
362
|
}
|
|
363
|
+
async installedPlugins(binary) {
|
|
364
|
+
const listed = await this.listJson(binary, ["plugin", "list"]);
|
|
365
|
+
if (!listed) return null;
|
|
366
|
+
return listed.filter((p) => typeof p?.id === "string" && p.id.split("@")[0] === PLUGIN_NAME);
|
|
367
|
+
}
|
|
368
|
+
async installedPluginIds(binary) {
|
|
369
|
+
return (await this.installedPlugins(binary))?.map((p) => p.id) ?? null;
|
|
370
|
+
}
|
|
371
|
+
async isPluginInstalled() {
|
|
372
|
+
const binary = this.findClaudeBinary();
|
|
373
|
+
if (!binary) return false;
|
|
374
|
+
const listed = await this.installedPlugins(binary);
|
|
375
|
+
if (listed) return listed.length > 0;
|
|
376
|
+
const plain = await this.runClaude(binary, ["plugin", "list"]);
|
|
377
|
+
return plain.ok && plain.output.toLowerCase().includes(PLUGIN_NAME);
|
|
378
|
+
}
|
|
294
379
|
async installPlugin() {
|
|
295
380
|
const binary = this.findClaudeBinary();
|
|
296
381
|
if (!binary) return {
|
|
297
382
|
success: false,
|
|
298
383
|
reason: "The claude CLI is no longer on your PATH."
|
|
299
384
|
};
|
|
300
|
-
|
|
385
|
+
const listed = await this.installedPlugins(binary);
|
|
386
|
+
if (listed ? listed.some((p) => p.enabled !== false) : await this.isPluginInstalled()) return {
|
|
301
387
|
success: true,
|
|
302
388
|
alreadyInstalled: true
|
|
303
389
|
};
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
390
|
+
const marketplaceFailure = await this.ensurePluginMarketplace(binary);
|
|
391
|
+
let result = await this.runClaude(binary, [
|
|
392
|
+
"plugin",
|
|
393
|
+
"install",
|
|
394
|
+
PLUGIN_REF$1
|
|
395
|
+
]);
|
|
396
|
+
if (!result.ok && NOT_IN_A_MARKETPLACE.test(result.output)) {
|
|
397
|
+
await this.runClaude(binary, [
|
|
398
|
+
"plugin",
|
|
399
|
+
"marketplace",
|
|
400
|
+
"update",
|
|
401
|
+
PLUGIN_MARKETPLACE$1
|
|
402
|
+
]);
|
|
403
|
+
result = await this.runClaude(binary, [
|
|
404
|
+
"plugin",
|
|
405
|
+
"install",
|
|
406
|
+
PLUGIN_REF$1
|
|
407
|
+
]);
|
|
408
|
+
}
|
|
409
|
+
if (!result.ok && NOT_IN_A_MARKETPLACE.test(result.output)) result = await this.runClaude(binary, [
|
|
410
|
+
"plugin",
|
|
411
|
+
"install",
|
|
412
|
+
PLUGIN_NAME
|
|
413
|
+
]);
|
|
414
|
+
if (result.ok) return { success: true };
|
|
415
|
+
const msg = result.output;
|
|
416
|
+
if (msg.includes("already installed") || msg.includes("already exists")) return {
|
|
417
|
+
success: true,
|
|
418
|
+
alreadyInstalled: true
|
|
419
|
+
};
|
|
420
|
+
const failure = /* @__PURE__ */ new Error(`Claude Code plugin install failed: ${msg}`);
|
|
421
|
+
if (marketplaceFailure) analytics.captureException(failure, { marketplaceFailure });
|
|
422
|
+
else analytics.captureException(failure);
|
|
423
|
+
return {
|
|
424
|
+
success: false,
|
|
425
|
+
reason: msg
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
/** Registered, and ours: a catalog merely named `posthog` is someone else's. */
|
|
429
|
+
async ourMarketplaceRegistered(binary) {
|
|
430
|
+
const listed = await this.listJson(binary, [
|
|
431
|
+
"plugin",
|
|
432
|
+
"marketplace",
|
|
433
|
+
"list"
|
|
434
|
+
]);
|
|
435
|
+
return listed ? listed.some(isOurMarketplace) : null;
|
|
436
|
+
}
|
|
437
|
+
async ensurePluginMarketplace(binary) {
|
|
438
|
+
if ((await this.listJson(binary, [
|
|
439
|
+
"plugin",
|
|
440
|
+
"marketplace",
|
|
441
|
+
"list"
|
|
442
|
+
]))?.some(isOurMarketplace)) {
|
|
443
|
+
debug(` Marketplace ${PLUGIN_MARKETPLACE$1} already registered`);
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
const added = await this.runClaude(binary, [
|
|
447
|
+
"plugin",
|
|
448
|
+
"marketplace",
|
|
449
|
+
"add",
|
|
450
|
+
PLUGIN_MARKETPLACE_SOURCE$1
|
|
451
|
+
]);
|
|
452
|
+
if (!added.ok) {
|
|
453
|
+
debug(` Marketplace add failed: ${added.output}`);
|
|
454
|
+
return added.output;
|
|
318
455
|
}
|
|
319
456
|
}
|
|
320
457
|
};
|
|
@@ -429,6 +566,163 @@ var ZedClient = class extends DefaultMCPClient {
|
|
|
429
566
|
};
|
|
430
567
|
//#endregion
|
|
431
568
|
//#region src/steps/add-mcp-server-to-clients/clients/codex.ts
|
|
569
|
+
const PLUGIN_MARKETPLACE = "posthog";
|
|
570
|
+
const PLUGIN_MARKETPLACE_SOURCE = "PostHog/ai-plugin";
|
|
571
|
+
const PLUGIN_REF = `posthog@${PLUGIN_MARKETPLACE}`;
|
|
572
|
+
/**
|
|
573
|
+
* The plugin's row in `codex plugin list`, whose STATUS column reads
|
|
574
|
+
* `installed, enabled` or `not installed`. Registering the marketplace only
|
|
575
|
+
* publishes the catalog, so the marketplace section in config.toml says nothing
|
|
576
|
+
* about whether the plugin itself is there.
|
|
577
|
+
*/
|
|
578
|
+
const listedAsInstalled = (stdout) => {
|
|
579
|
+
const row = new RegExp(`^${PLUGIN_REF}\\s+(.*)$`, "m").exec(stdout)?.[1];
|
|
580
|
+
return !!row && /\binstalled\b/.test(row) && !/\bnot installed\b/.test(row);
|
|
581
|
+
};
|
|
582
|
+
const PLUGIN_STAGES = [
|
|
583
|
+
"plugin install",
|
|
584
|
+
"plugin uninstall",
|
|
585
|
+
"marketplace add"
|
|
586
|
+
];
|
|
587
|
+
const MCP_STAGES = ["MCP add", "MCP remove"];
|
|
588
|
+
const ALL_STAGES = [...PLUGIN_STAGES, ...MCP_STAGES];
|
|
589
|
+
/**
|
|
590
|
+
* Failures in the user's own environment. Reporting them files issues nobody
|
|
591
|
+
* can action, so hand back a hint instead. Drawn from what the codex install
|
|
592
|
+
* path actually produced in the field.
|
|
593
|
+
*
|
|
594
|
+
* Every entry is scoped: a hint that fires on the wrong stage tells the user to
|
|
595
|
+
* run a command that has nothing to do with what just failed.
|
|
596
|
+
*/
|
|
597
|
+
const EXPECTED_FAILURES = [
|
|
598
|
+
{
|
|
599
|
+
match: /unexpected argument|unknown (command|option|argument)|Missing option/i,
|
|
600
|
+
stages: PLUGIN_STAGES,
|
|
601
|
+
hint: "your codex CLI is too old for plugins — update codex, then run `codex plugin marketplace add PostHog/ai-plugin`"
|
|
602
|
+
},
|
|
603
|
+
{
|
|
604
|
+
match: /unexpected argument|unknown (command|option|argument)|Missing option/i,
|
|
605
|
+
stages: MCP_STAGES,
|
|
606
|
+
hint: "your codex CLI is too old for this install — update codex, then run `npx @posthog/wizard mcp add` again"
|
|
607
|
+
},
|
|
608
|
+
{
|
|
609
|
+
match: /ENOENT|not found in PATH|spawn .* ENOENT/i,
|
|
610
|
+
stages: ALL_STAGES,
|
|
611
|
+
hint: "your codex install looks broken — reinstall codex, then run `codex plugin marketplace add PostHog/ai-plugin`"
|
|
612
|
+
},
|
|
613
|
+
{
|
|
614
|
+
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,
|
|
615
|
+
stages: ALL_STAGES,
|
|
616
|
+
unless: /ai-plugin|plugin\.toml|plugin\.json|marketplace\.toml|posthog@posthog/i,
|
|
617
|
+
hint: "codex could not read its own config — fix what it reports in ~/.codex/config.toml, then retry"
|
|
618
|
+
},
|
|
619
|
+
{
|
|
620
|
+
match: /EACCES|EPERM|permission denied|read-only file system|not permitted/i,
|
|
621
|
+
stages: ALL_STAGES,
|
|
622
|
+
unless: /permission denied \((?:publickey|password|gssapi)/i,
|
|
623
|
+
hint: "codex could not write to its config — fix the permissions on ~/.codex, then retry"
|
|
624
|
+
},
|
|
625
|
+
{
|
|
626
|
+
match: /ENOSPC|no space left/i,
|
|
627
|
+
stages: ALL_STAGES,
|
|
628
|
+
hint: "the disk is full — free some space, then retry"
|
|
629
|
+
},
|
|
630
|
+
{
|
|
631
|
+
match: /git clone .* failed|ENOTFOUND|ETIMEDOUT|ECONNREFUSED|could not resolve host/i,
|
|
632
|
+
stages: ALL_STAGES,
|
|
633
|
+
unless: /repository not found|not found|404|does not exist|authentication failed/i,
|
|
634
|
+
hint: "codex could not reach GitHub to download the plugin — check your network, then retry"
|
|
635
|
+
}
|
|
636
|
+
];
|
|
637
|
+
/**
|
|
638
|
+
* A clone of the plugin marketplace is the slowest thing we run. Past this the
|
|
639
|
+
* command is not slow, it is stuck, and the wizard should say so rather than
|
|
640
|
+
* wait forever.
|
|
641
|
+
*/
|
|
642
|
+
const RUN_TIMEOUT_MS = 12e4;
|
|
643
|
+
/**
|
|
644
|
+
* `execFile` kills the child once output passes this. The default is 1 MB,
|
|
645
|
+
* which a verbose clone can reach, and the kill then looks like codex rejecting
|
|
646
|
+
* the install rather than us cutting it off.
|
|
647
|
+
*/
|
|
648
|
+
const MAX_OUTPUT_BYTES = 16 * 1024 * 1024;
|
|
649
|
+
/**
|
|
650
|
+
* What `execFile` puts in `error.message` when the command itself never spoke:
|
|
651
|
+
* the full binary path and arguments. That path contains the user's home
|
|
652
|
+
* directory, so reporting it fingerprints one root cause per machine — the
|
|
653
|
+
* failure this reporting was built to stop. Never send it onward.
|
|
654
|
+
*/
|
|
655
|
+
const COMMAND_FAILED_PREAMBLE = /^Command failed:.*$/m;
|
|
656
|
+
/**
|
|
657
|
+
* The cause when neither stream carried one. `execFile` always sets a message,
|
|
658
|
+
* so there is no "empty error" case to fall through — the message just isn't
|
|
659
|
+
* usable as it stands.
|
|
660
|
+
*/
|
|
661
|
+
const describeExecFailure = (error) => {
|
|
662
|
+
if (error.code === "ERR_CHILD_PROCESS_STDIO_MAXBUFFER") return "codex produced more output than the wizard can hold, so it was stopped";
|
|
663
|
+
if (error.killed) return `codex did not finish within ${RUN_TIMEOUT_MS / 1e3}s, so it was stopped`;
|
|
664
|
+
if (error.signal) return `codex was killed by ${error.signal}`;
|
|
665
|
+
const said = error.message.replace(COMMAND_FAILED_PREAMBLE, "").trim();
|
|
666
|
+
if (said) return said;
|
|
667
|
+
if (typeof error.code === "number") return `codex exited with code ${error.code}`;
|
|
668
|
+
if (error.code) return `codex failed with ${error.code}`;
|
|
669
|
+
return "codex failed without reporting a reason";
|
|
670
|
+
};
|
|
671
|
+
/**
|
|
672
|
+
* One codex invocation. Async on purpose: `plugin marketplace add` and
|
|
673
|
+
* `plugin add` clone git repositories and take seconds, and a synchronous child
|
|
674
|
+
* process blocks the event loop, which freezes the TUI spinner on its first
|
|
675
|
+
* frame. Never throws; the caller decides what a failure means.
|
|
676
|
+
*
|
|
677
|
+
* A failure's cause is split across the error and the two streams, and none of
|
|
678
|
+
* them carries it when the process merely exits non-zero — reading one alone
|
|
679
|
+
* reported a blank reason and filed an exception carrying nothing.
|
|
680
|
+
*/
|
|
681
|
+
const runCodex = (binary, args, env) => new Promise((resolve) => {
|
|
682
|
+
execFile(binary, args, {
|
|
683
|
+
env,
|
|
684
|
+
timeout: RUN_TIMEOUT_MS,
|
|
685
|
+
maxBuffer: MAX_OUTPUT_BYTES
|
|
686
|
+
}, (error, stdout, stderr) => {
|
|
687
|
+
if (!error) return resolve({
|
|
688
|
+
ok: true,
|
|
689
|
+
output: stdout ?? ""
|
|
690
|
+
});
|
|
691
|
+
const said = [stderr, stdout].map((p) => p ? String(p).trim() : "").filter(Boolean).join("\n");
|
|
692
|
+
resolve({
|
|
693
|
+
ok: false,
|
|
694
|
+
output: redactSecrets(error.killed || !!error.signal || error.code === "ERR_CHILD_PROCESS_STDIO_MAXBUFFER" || !said ? describeExecFailure(error) : said)
|
|
695
|
+
});
|
|
696
|
+
}).stdin?.end();
|
|
697
|
+
});
|
|
698
|
+
/**
|
|
699
|
+
* Turn a failed spawn into a result: an expected local failure becomes a hint,
|
|
700
|
+
* anything else is reported under a constant message so one root cause stays
|
|
701
|
+
* one issue, with the varying detail in properties.
|
|
702
|
+
*/
|
|
703
|
+
const reportSpawnFailure = (stage, details) => {
|
|
704
|
+
const hint = expectedFailureHint(details, EXPECTED_FAILURES, stage);
|
|
705
|
+
if (hint) {
|
|
706
|
+
analytics.wizardCapture("mcp expected failure hinted", {
|
|
707
|
+
client: "Codex",
|
|
708
|
+
stage,
|
|
709
|
+
hint,
|
|
710
|
+
details: scrubHomePaths(details)
|
|
711
|
+
});
|
|
712
|
+
return {
|
|
713
|
+
success: false,
|
|
714
|
+
reason: hint
|
|
715
|
+
};
|
|
716
|
+
}
|
|
717
|
+
analytics.captureException(/* @__PURE__ */ new Error(`Codex ${stage} failed`), {
|
|
718
|
+
stage,
|
|
719
|
+
details: scrubHomePaths(details)
|
|
720
|
+
});
|
|
721
|
+
return {
|
|
722
|
+
success: false,
|
|
723
|
+
reason: details
|
|
724
|
+
};
|
|
725
|
+
};
|
|
432
726
|
/** Wording codex uses when the thing we're adding is already registered. */
|
|
433
727
|
const ALREADY_INSTALLED_PATTERN = /already (installed|exists|added|registered)/i;
|
|
434
728
|
/** Wording that means the opposite: a cache entry exists but the plugin doesn't. */
|
|
@@ -490,16 +784,16 @@ var CodexMCPClient = class extends DefaultMCPClient {
|
|
|
490
784
|
return Promise.resolve(false);
|
|
491
785
|
}
|
|
492
786
|
}
|
|
493
|
-
addServer(apiKey, selectedFeatures, local) {
|
|
787
|
+
async addServer(apiKey, selectedFeatures, local) {
|
|
494
788
|
const serverName = local ? "posthog-local" : "posthog";
|
|
495
789
|
const url = buildMCPUrl(selectedFeatures, local);
|
|
496
790
|
if (apiKey) {
|
|
497
791
|
const binary = this.findCodexBinary();
|
|
498
|
-
if (!binary) return
|
|
792
|
+
if (!binary) return {
|
|
499
793
|
success: false,
|
|
500
794
|
reason: "An API-key install into Codex needs the codex CLI."
|
|
501
|
-
}
|
|
502
|
-
const result =
|
|
795
|
+
};
|
|
796
|
+
const result = await runCodex(binary, [
|
|
503
797
|
"mcp",
|
|
504
798
|
"add",
|
|
505
799
|
serverName,
|
|
@@ -508,28 +802,19 @@ var CodexMCPClient = class extends DefaultMCPClient {
|
|
|
508
802
|
"--bearer-token-env-var",
|
|
509
803
|
"POSTHOG_AUTH_HEADER"
|
|
510
804
|
], {
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
...process.env,
|
|
514
|
-
POSTHOG_AUTH_HEADER: `Bearer ${apiKey}`
|
|
515
|
-
}
|
|
805
|
+
...process.env,
|
|
806
|
+
POSTHOG_AUTH_HEADER: `Bearer ${apiKey}`
|
|
516
807
|
});
|
|
517
|
-
if (result.
|
|
518
|
-
|
|
519
|
-
if (ALREADY_INSTALLED_PATTERN.test(stderr)) return Promise.resolve({
|
|
808
|
+
if (!result.ok) {
|
|
809
|
+
if (ALREADY_INSTALLED_PATTERN.test(result.output)) return {
|
|
520
810
|
success: true,
|
|
521
811
|
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
|
-
});
|
|
812
|
+
};
|
|
813
|
+
return reportSpawnFailure("MCP add", result.output);
|
|
529
814
|
}
|
|
530
|
-
return
|
|
815
|
+
return { success: true };
|
|
531
816
|
}
|
|
532
|
-
return
|
|
817
|
+
return this.writeServerSection(serverName, url);
|
|
533
818
|
}
|
|
534
819
|
/**
|
|
535
820
|
* Create or update the `[mcp_servers.<name>]` section in config.toml, editing
|
|
@@ -561,7 +846,7 @@ var CodexMCPClient = class extends DefaultMCPClient {
|
|
|
561
846
|
return { success: true };
|
|
562
847
|
} catch (error) {
|
|
563
848
|
const reason = error instanceof Error ? error.message : String(error);
|
|
564
|
-
analytics.captureException(/* @__PURE__ */ new Error(
|
|
849
|
+
analytics.captureException(/* @__PURE__ */ new Error("Codex config.toml write failed"), { details: scrubHomePaths(reason) });
|
|
565
850
|
return {
|
|
566
851
|
success: false,
|
|
567
852
|
reason
|
|
@@ -579,26 +864,19 @@ var CodexMCPClient = class extends DefaultMCPClient {
|
|
|
579
864
|
if (!this.findCodexBinary()) return null;
|
|
580
865
|
return `codex mcp login ${local ? "posthog-local" : "posthog"}`;
|
|
581
866
|
}
|
|
582
|
-
removeServer(local) {
|
|
867
|
+
async removeServer(local) {
|
|
583
868
|
const binary = this.findCodexBinary();
|
|
584
|
-
if (!binary) return
|
|
869
|
+
if (!binary) return {
|
|
585
870
|
success: false,
|
|
586
871
|
reason: "The codex CLI is no longer on your PATH."
|
|
587
|
-
}
|
|
588
|
-
const result =
|
|
872
|
+
};
|
|
873
|
+
const result = await runCodex(binary, [
|
|
589
874
|
"mcp",
|
|
590
875
|
"remove",
|
|
591
876
|
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 });
|
|
877
|
+
]);
|
|
878
|
+
if (!result.ok) return reportSpawnFailure("MCP remove", result.output);
|
|
879
|
+
return { success: true };
|
|
602
880
|
}
|
|
603
881
|
/** The codex marketplace plugin ships skills only — the MCP server needs its own entry. */
|
|
604
882
|
pluginBundlesMcpServer() {
|
|
@@ -607,13 +885,33 @@ var CodexMCPClient = class extends DefaultMCPClient {
|
|
|
607
885
|
supportsPlugin() {
|
|
608
886
|
return this.findCodexBinary() !== null;
|
|
609
887
|
}
|
|
610
|
-
|
|
611
|
-
|
|
888
|
+
/** The plugin itself, as the CLI reports it. The install decision's question. */
|
|
889
|
+
async isPluginPresent() {
|
|
890
|
+
const binary = this.findCodexBinary();
|
|
891
|
+
if (!binary) return false;
|
|
892
|
+
const result = await runCodex(binary, [
|
|
893
|
+
"plugin",
|
|
894
|
+
"list",
|
|
895
|
+
"-m",
|
|
896
|
+
PLUGIN_MARKETPLACE
|
|
897
|
+
]);
|
|
898
|
+
return result.ok && listedAsInstalled(result.output);
|
|
899
|
+
}
|
|
900
|
+
/**
|
|
901
|
+
* Anything of ours left on the machine, which is what `index.ts` asks before
|
|
902
|
+
* offering removal. A registered marketplace with no plugin is a state the
|
|
903
|
+
* wizard created — and the state this branch exists to correct — so removal
|
|
904
|
+
* has to see it, or `removePlugin` never runs and the catalog stays forever.
|
|
905
|
+
*/
|
|
906
|
+
async isPluginInstalled() {
|
|
907
|
+
return await this.isPluginPresent() || this.isMarketplaceRegistered();
|
|
908
|
+
}
|
|
909
|
+
/** The catalog, which the plugin is installed *from* — not the plugin. */
|
|
910
|
+
isMarketplaceRegistered() {
|
|
612
911
|
try {
|
|
613
|
-
|
|
614
|
-
return Promise.resolve(contents.toLowerCase().includes("[marketplaces.posthog]"));
|
|
912
|
+
return fs$1.readFileSync(this.configPath(), "utf-8").toLowerCase().includes(`[marketplaces.${PLUGIN_MARKETPLACE}]`);
|
|
615
913
|
} catch {
|
|
616
|
-
return
|
|
914
|
+
return false;
|
|
617
915
|
}
|
|
618
916
|
}
|
|
619
917
|
async removePlugin() {
|
|
@@ -622,23 +920,25 @@ var CodexMCPClient = class extends DefaultMCPClient {
|
|
|
622
920
|
success: false,
|
|
623
921
|
reason: "The codex CLI is no longer on your PATH."
|
|
624
922
|
};
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
923
|
+
const steps = [];
|
|
924
|
+
if (await this.isPluginPresent()) steps.push([
|
|
925
|
+
"plugin",
|
|
926
|
+
"remove",
|
|
927
|
+
PLUGIN_REF
|
|
928
|
+
]);
|
|
929
|
+
if (this.isMarketplaceRegistered()) steps.push([
|
|
630
930
|
"plugin",
|
|
631
931
|
"marketplace",
|
|
632
932
|
"remove",
|
|
633
|
-
|
|
634
|
-
]
|
|
635
|
-
if (
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
933
|
+
PLUGIN_MARKETPLACE
|
|
934
|
+
]);
|
|
935
|
+
if (steps.length === 0) return {
|
|
936
|
+
success: true,
|
|
937
|
+
alreadyInstalled: true
|
|
938
|
+
};
|
|
939
|
+
for (const args of steps) {
|
|
940
|
+
const result = await runCodex(binary, args);
|
|
941
|
+
if (!result.ok) return reportSpawnFailure("plugin uninstall", result.output);
|
|
642
942
|
}
|
|
643
943
|
return { success: true };
|
|
644
944
|
}
|
|
@@ -648,39 +948,53 @@ var CodexMCPClient = class extends DefaultMCPClient {
|
|
|
648
948
|
success: false,
|
|
649
949
|
reason: "The codex CLI is no longer on your PATH."
|
|
650
950
|
};
|
|
651
|
-
if (await this.
|
|
951
|
+
if (await this.isPluginPresent()) return {
|
|
652
952
|
success: true,
|
|
653
953
|
alreadyInstalled: true
|
|
654
954
|
};
|
|
655
|
-
const
|
|
955
|
+
const marketplace = this.isMarketplaceRegistered() ? null : await this.registerMarketplace(binary);
|
|
956
|
+
if (marketplace && !marketplace.success) return marketplace;
|
|
957
|
+
const result = await runCodex(binary, [
|
|
958
|
+
"plugin",
|
|
959
|
+
"add",
|
|
960
|
+
PLUGIN_REF
|
|
961
|
+
]);
|
|
962
|
+
if (!result.ok) {
|
|
963
|
+
if (ALREADY_INSTALLED_PATTERN.test(result.output)) return {
|
|
964
|
+
success: true,
|
|
965
|
+
alreadyInstalled: true
|
|
966
|
+
};
|
|
967
|
+
return reportSpawnFailure("plugin install", result.output);
|
|
968
|
+
}
|
|
969
|
+
return { success: true };
|
|
970
|
+
}
|
|
971
|
+
/**
|
|
972
|
+
* Add the catalog the plugin is published in. A stale cache directory with no
|
|
973
|
+
* config.toml entry reports the marketplace as added from a different source;
|
|
974
|
+
* clear it and retry once.
|
|
975
|
+
*/
|
|
976
|
+
async registerMarketplace(binary) {
|
|
977
|
+
const run = () => runCodex(binary, [
|
|
656
978
|
"plugin",
|
|
657
979
|
"marketplace",
|
|
658
980
|
"add",
|
|
659
|
-
|
|
660
|
-
]
|
|
661
|
-
let result = run();
|
|
662
|
-
if (result.
|
|
663
|
-
const staleDir = path$2.join(os.homedir(), ".codex", ".tmp", "marketplaces",
|
|
981
|
+
PLUGIN_MARKETPLACE_SOURCE
|
|
982
|
+
]);
|
|
983
|
+
let result = await run();
|
|
984
|
+
if (!result.ok && STALE_MARKETPLACE_CACHE.test(result.output)) {
|
|
985
|
+
const staleDir = path$2.join(os.homedir(), ".codex", ".tmp", "marketplaces", PLUGIN_MARKETPLACE);
|
|
664
986
|
try {
|
|
665
987
|
fs$1.rmSync(staleDir, {
|
|
666
988
|
recursive: true,
|
|
667
989
|
force: true
|
|
668
990
|
});
|
|
669
991
|
} catch {}
|
|
670
|
-
result = run();
|
|
992
|
+
result = await run();
|
|
671
993
|
}
|
|
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
|
-
};
|
|
994
|
+
if (!result.ok) {
|
|
995
|
+
const details = result.output;
|
|
996
|
+
if (ALREADY_INSTALLED_PATTERN.test(details) && !STALE_MARKETPLACE_CACHE.test(details)) return { success: true };
|
|
997
|
+
return reportSpawnFailure("marketplace add", details);
|
|
684
998
|
}
|
|
685
999
|
return { success: true };
|
|
686
1000
|
}
|
|
@@ -900,4 +1214,4 @@ const removeMCPServer = async (clients, local) => {
|
|
|
900
1214
|
//#endregion
|
|
901
1215
|
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
1216
|
|
|
903
|
-
//# sourceMappingURL=add-mcp-server-to-clients-
|
|
1217
|
+
//# sourceMappingURL=add-mcp-server-to-clients-BnRyE4pw.js.map
|