@posthog/wizard 2.78.0 → 2.79.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -11
- package/dist/PickerMenu-dG5DQCZA.js +758 -0
- package/dist/PickerMenu-dG5DQCZA.js.map +1 -0
- package/dist/{add-mcp-server-to-clients-JMv8LP-O.js → add-mcp-server-to-clients-DIaTRWMY.js} +7 -18
- package/dist/{add-mcp-server-to-clients-JMv8LP-O.js.map → add-mcp-server-to-clients-DIaTRWMY.js.map} +1 -1
- package/dist/add-mcp-server-to-clients-artmN7mz.js +2 -0
- package/dist/agent-BEjARD2a.js +6 -0
- package/dist/{agent-bCZ3i3fh.js → agent-BWFhuLgo.js} +131 -38
- package/dist/agent-BWFhuLgo.js.map +1 -0
- package/dist/{agent-interface-BAOIHuXS.js → agent-interface-FkbaBJwz.js} +66 -28
- package/dist/agent-interface-FkbaBJwz.js.map +1 -0
- package/dist/{agent-prompt-loader-7Pd4CfZO.js → agent-prompt-loader-D0weQ-7k.js} +5 -5
- package/dist/{agent-prompt-loader-7Pd4CfZO.js.map → agent-prompt-loader-D0weQ-7k.js.map} +1 -1
- package/dist/analytics-DFtbRjYh.js +2 -0
- package/dist/{analytics-CHCZ_qUR.js → analytics-DXK1gc12.js} +4 -4
- package/dist/{analytics-CHCZ_qUR.js.map → analytics-DXK1gc12.js.map} +1 -1
- package/dist/api-Cm9UtKZh.js +2 -0
- package/dist/{api-Diy_2fp8.js → api-CrbCIQOz.js} +4 -16
- package/dist/{api-Diy_2fp8.js.map → api-CrbCIQOz.js.map} +1 -1
- package/dist/bin.js +5 -2957
- package/dist/bin.js.map +1 -1
- package/dist/{bounded-fs-Bx9zTe6m.js → bounded-fs-vAq-T-K7.js} +3 -3
- package/dist/{bounded-fs-Bx9zTe6m.js.map → bounded-fs-vAq-T-K7.js.map} +1 -1
- package/dist/{ci-install-CDdQYsPe.js → ci-install-COcV8SY2.js} +8 -7
- package/dist/ci-install-COcV8SY2.js.map +1 -0
- package/dist/{constants-jFI2SaE1.js → constants-DHCBSfnx.js} +3 -3
- package/dist/{constants-jFI2SaE1.js.map → constants-DHCBSfnx.js.map} +1 -1
- package/dist/{debug-M2gV2iDq.js → debug-BuYHGr6_.js} +1 -1
- package/dist/{debug-Ch4BDOtD.js → debug-kAHwWGg7.js} +2 -2
- package/dist/{debug-Ch4BDOtD.js.map → debug-kAHwWGg7.js.map} +1 -1
- package/dist/{defaults-C6J7yL4O.js → defaults-a9TelDhJ.js} +1 -1
- package/dist/{defaults-C6J7yL4O.js.map → defaults-a9TelDhJ.js.map} +1 -1
- package/dist/emit-BSetXzDV.js +69 -0
- package/dist/emit-BSetXzDV.js.map +1 -0
- package/dist/{endpoints-DCVbM06L.js → endpoints-BVMYm9F4.js} +3 -3
- package/dist/{endpoints-DCVbM06L.js.map → endpoints-BVMYm9F4.js.map} +1 -1
- package/dist/{env-api-key-Qx8NnYHm.js → env-api-key-BP-NFFXt.js} +3 -5
- package/dist/{env-api-key-Qx8NnYHm.js.map → env-api-key-BP-NFFXt.js.map} +1 -1
- package/dist/env-api-key-CaWEDj_9.js +2 -0
- package/dist/{environment-B07Bmxae.js → environment-BATlQxcQ.js} +5 -10
- package/dist/{environment-B07Bmxae.js.map → environment-BATlQxcQ.js.map} +1 -1
- package/dist/environment-CwD8OPYj.js +2 -0
- package/dist/errors-C2domSkK.js +79 -0
- package/dist/errors-C2domSkK.js.map +1 -0
- package/dist/file-C5JMsyR1.js +2 -0
- package/dist/{file-BcLTjU16.js → file-DcRKycV8.js} +4 -4
- package/dist/file-DcRKycV8.js.map +1 -0
- package/dist/{file-watcher-DWc_bTs6.js → file-watcher-Brq2nnHV.js} +2 -2
- package/dist/{file-watcher-DWc_bTs6.js.map → file-watcher-Brq2nnHV.js.map} +1 -1
- package/dist/{gateway-CjoShdLa.js → gateway-C9-GlLO9.js} +39 -8
- package/dist/gateway-C9-GlLO9.js.map +1 -0
- package/dist/{headless-ui-BFFmYC4v.js → headless-ui-CqI2gXlD.js} +2 -2
- package/dist/{headless-ui-BFFmYC4v.js.map → headless-ui-CqI2gXlD.js.map} +1 -1
- package/dist/{interactive-D6zV7brJ.js → interactive-B_Ti_CsS.js} +3 -3
- package/dist/interactive-B_Ti_CsS.js.map +1 -0
- package/dist/{logging-ui-_TwoMNbG.js → logging-ui-Dza4D0MK.js} +5 -5
- package/dist/{logging-ui-_TwoMNbG.js.map → logging-ui-Dza4D0MK.js.map} +1 -1
- package/dist/main-CgKxbwMP.js +1396 -0
- package/dist/main-CgKxbwMP.js.map +1 -0
- package/dist/{mcp-DAgaoGk5.js → mcp-DnAyW0-w.js} +4 -4
- package/dist/{mcp-DAgaoGk5.js.map → mcp-DnAyW0-w.js.map} +1 -1
- package/dist/{mcp-prompt-streaming-I2U_X7BC.js → mcp-prompt-streaming-DDWQ-FCA.js} +6 -6
- package/dist/mcp-prompt-streaming-DDWQ-FCA.js.map +1 -0
- package/dist/{mint-failure-D4nd2XmZ.js → mint-failure-u8xQKNOn.js} +689 -126
- package/dist/mint-failure-u8xQKNOn.js.map +1 -0
- package/dist/{models-DDdBJKwT.js → models-WcwUnSKb.js} +2 -2
- package/dist/{models-DDdBJKwT.js.map → models-WcwUnSKb.js.map} +1 -1
- package/dist/{non-interactive-Dzow7YKY.js → non-interactive-DyVC1AGc.js} +4 -3
- package/dist/{non-interactive-Dzow7YKY.js.map → non-interactive-DyVC1AGc.js.map} +1 -1
- package/dist/{oauth-session-DJ8h6GFa.js → oauth-session-DYM2Hrl2.js} +2 -2
- package/dist/{oauth-session-DJ8h6GFa.js.map → oauth-session-DYM2Hrl2.js.map} +1 -1
- package/dist/{orchestrator-tools-szcdscwn.js → orchestrator-tools-DbgNBFGA.js} +3 -3
- package/dist/{orchestrator-tools-szcdscwn.js.map → orchestrator-tools-DbgNBFGA.js.map} +1 -1
- package/dist/{package-json-DY70kkNp.js → package-json-Atg34fa4.js} +2 -8
- package/dist/{package-json-DY70kkNp.js.map → package-json-Atg34fa4.js.map} +1 -1
- package/dist/package-json-D8Ga03tK.js +2 -0
- package/dist/{pi-D3h5Ok0i.js → pi-8KsYsPmM.js} +145 -45
- package/dist/pi-8KsYsPmM.js.map +1 -0
- package/dist/{playground-5AB4WgNF.js → playground-BlYRBMj7.js} +11 -11
- package/dist/playground-BlYRBMj7.js.map +1 -0
- package/dist/{posthog-DNn574nW.js → posthog-Bt0Aplb8.js} +4 -9
- package/dist/posthog-Bt0Aplb8.js.map +1 -0
- package/dist/posthog-CUgCEhH0.js +2 -0
- package/dist/{provisioning-B8uSqRZk.js → provisioning-Bo2NRxFz.js} +5 -11
- package/dist/{provisioning-B8uSqRZk.js.map → provisioning-Bo2NRxFz.js.map} +1 -1
- package/dist/provisioning-OGFGlzf7.js +2 -0
- package/dist/{queue-tools-9OOVx5TE.js → queue-tools-C8mXOh7e.js} +3 -3
- package/dist/{queue-tools-9OOVx5TE.js.map → queue-tools-C8mXOh7e.js.map} +1 -1
- package/dist/registry-C06e_x-p.js +2 -0
- package/dist/{registry-8YG-kuXk.js → registry-CD5RQt38.js} +51 -53
- package/dist/registry-CD5RQt38.js.map +1 -0
- package/dist/run-agent-legacy-ChacZImU.js +2 -0
- package/dist/{run-agent-legacy-d7rWlzQR.js → run-agent-legacy-DOlM6DQu.js} +823 -1022
- package/dist/run-agent-legacy-DOlM6DQu.js.map +1 -0
- package/dist/runners-ov3EXF1n.js +834 -0
- package/dist/runners-ov3EXF1n.js.map +1 -0
- package/dist/{security-Cg_4a7vB.js → security-C71pkwqH.js} +16 -6
- package/dist/security-C71pkwqH.js.map +1 -0
- package/dist/{setup-utils-CmTCTPkX.js → setup-utils-B26Lf2yF.js} +12 -22
- package/dist/setup-utils-B26Lf2yF.js.map +1 -0
- package/dist/setup-utils-CVS86NYR.js +2 -0
- package/dist/{start-tui-CB2PZs1x.js → start-tui-Bo2L0bar.js} +30 -28
- package/dist/start-tui-Bo2L0bar.js.map +1 -0
- package/dist/{steps-BZcXRJNY.js → steps-BPcg3_3Q.js} +7 -7
- package/dist/{steps-BZcXRJNY.js.map → steps-BPcg3_3Q.js.map} +1 -1
- package/dist/{store-UN7c-ASf.js → store-BTzcvRGT.js} +12 -18
- package/dist/store-BTzcvRGT.js.map +1 -0
- package/dist/store-BpqySPXm.js +5 -0
- package/dist/{subagent-BofIDK-O.js → subagent-D1TrTchE.js} +3 -3
- package/dist/{subagent-BofIDK-O.js.map → subagent-D1TrTchE.js.map} +1 -1
- package/dist/{task-r9t1UhQP.js → task-DqRlQBfs.js} +18 -16
- package/dist/task-DqRlQBfs.js.map +1 -0
- package/dist/{task-stream-CMUilu54.js → task-stream-Bw6JaLCX.js} +10 -10
- package/dist/task-stream-Bw6JaLCX.js.map +1 -0
- package/dist/{tasks-Bbv_lOBG.js → tasks-ChWufsdO.js} +1 -1
- package/dist/{tasks-Bbv_lOBG.js.map → tasks-ChWufsdO.js.map} +1 -1
- package/dist/{telemetry-D6ruCtnv.js → telemetry-B7zJdRmA.js} +3 -3
- package/dist/{telemetry-D6ruCtnv.js.map → telemetry-B7zJdRmA.js.map} +1 -1
- package/dist/{terminal-DrGyci_a.js → terminal-zgkEfoCL.js} +17 -17
- package/dist/terminal-zgkEfoCL.js.map +1 -0
- package/dist/{tools-Dyfh9aCD.js → tools-CkJ2y9Wt.js} +9 -9
- package/dist/tools-CkJ2y9Wt.js.map +1 -0
- package/dist/{ui-BBVuTM1v.js → ui-Q6-RvERF.js} +3 -3
- package/dist/{ui-BBVuTM1v.js.map → ui-Q6-RvERF.js.map} +1 -1
- package/dist/{version-aXxpgRKx.js → version-CHhJjz_H.js} +2 -2
- package/dist/{version-aXxpgRKx.js.map → version-CHhJjz_H.js.map} +1 -1
- package/dist/{wizard-abort-BBkiUxfS.js → wizard-abort-BPdv07np.js} +7 -6
- package/dist/{wizard-abort-BBkiUxfS.js.map → wizard-abort-BPdv07np.js.map} +1 -1
- package/dist/wizard-abort-Br1qMDNa.js +3 -0
- package/dist/wizard-session-2w4Ru-Wz.js.map +1 -1
- package/dist/{wizard-ui-DoyOZxK8.js → wizard-ui-DVqrYaOM.js} +1 -1
- package/dist/{wizard-ui-DoyOZxK8.js.map → wizard-ui-DVqrYaOM.js.map} +1 -1
- package/dist/{yara-hooks-DCeMDd1o.js → yara-hooks-BnxejtXK.js} +5 -5
- package/dist/{yara-hooks-DCeMDd1o.js.map → yara-hooks-BnxejtXK.js.map} +1 -1
- package/dist/yara-hooks-DSuExwb4.js +2 -0
- package/package.json +2 -1
- package/dist/agent-bCZ3i3fh.js.map +0 -1
- package/dist/agent-interface-BAOIHuXS.js.map +0 -1
- package/dist/analytics-BcV-WCM4.js +0 -2
- package/dist/ci-install-CDdQYsPe.js.map +0 -1
- package/dist/errors-CQ9kttJD.js +0 -185
- package/dist/errors-CQ9kttJD.js.map +0 -1
- package/dist/file-BcLTjU16.js.map +0 -1
- package/dist/gateway-CjoShdLa.js.map +0 -1
- package/dist/interactive-D6zV7brJ.js.map +0 -1
- package/dist/mcp-prompt-streaming-I2U_X7BC.js.map +0 -1
- package/dist/mint-failure-D4nd2XmZ.js.map +0 -1
- package/dist/pi-D3h5Ok0i.js.map +0 -1
- package/dist/playground-5AB4WgNF.js.map +0 -1
- package/dist/posthog-DNn574nW.js.map +0 -1
- package/dist/registry-8YG-kuXk.js.map +0 -1
- package/dist/rolldown-runtime-B_-DWIq7.js +0 -15
- package/dist/run-agent-legacy-d7rWlzQR.js.map +0 -1
- package/dist/security-Cg_4a7vB.js.map +0 -1
- package/dist/setup-utils-CmTCTPkX.js.map +0 -1
- package/dist/start-tui-CB2PZs1x.js.map +0 -1
- package/dist/store-UN7c-ASf.js.map +0 -1
- package/dist/task-r9t1UhQP.js.map +0 -1
- package/dist/task-stream-CMUilu54.js.map +0 -1
- package/dist/terminal-DrGyci_a.js.map +0 -1
- package/dist/tools-Dyfh9aCD.js.map +0 -1
- package/dist/wizard-abort-BU4aLyvh.js +0 -3
- package/dist/yara-hooks-DSGuCU9A.js +0 -2
|
@@ -0,0 +1,834 @@
|
|
|
1
|
+
import { m as isGrantRevoked } from "./agent-interface-FkbaBJwz.js";
|
|
2
|
+
import { n as ErrorCodes, t as emitWizardError } from "./emit-BSetXzDV.js";
|
|
3
|
+
import { a as getLogFilePath, s as logToFile, v as runtimeEnv } from "./debug-kAHwWGg7.js";
|
|
4
|
+
import { t as VERSION } from "./version-CHhJjz_H.js";
|
|
5
|
+
import { a as getLocalDev, i as checkLocalServices, r as POSTHOG_LOCAL_URL } from "./local-dev-McsurOC-.js";
|
|
6
|
+
import "./constants-DHCBSfnx.js";
|
|
7
|
+
import "./wizard-session-2w4Ru-Wz.js";
|
|
8
|
+
import { n as analytics } from "./analytics-DXK1gc12.js";
|
|
9
|
+
import { t as classifyRunFailure } from "./errors-C2domSkK.js";
|
|
10
|
+
import { t as LoggingUI } from "./logging-ui-Dza4D0MK.js";
|
|
11
|
+
import { n as setUI, t as getUI } from "./ui-Q6-RvERF.js";
|
|
12
|
+
import { n as registerShutdown, r as runCleanups } from "./wizard-abort-BPdv07np.js";
|
|
13
|
+
import { r as currentCredentials } from "./oauth-session-DYM2Hrl2.js";
|
|
14
|
+
import { d as authenticate, t as runProgramAgent, u as getAuditChecks } from "./run-agent-legacy-DOlM6DQu.js";
|
|
15
|
+
import { at as maybeStampAiSdkDetected, i as isRunFailure, u as getProgramConfig } from "./mint-failure-u8xQKNOn.js";
|
|
16
|
+
import { n as parseRetryAfter } from "./posthog-Bt0Aplb8.js";
|
|
17
|
+
import { valid } from "semver";
|
|
18
|
+
import { validate } from "uuid";
|
|
19
|
+
import { basename, join, resolve } from "node:path";
|
|
20
|
+
import { randomUUID } from "node:crypto";
|
|
21
|
+
//#region src/lib/runners/resolve-no-telemetry.ts
|
|
22
|
+
/**
|
|
23
|
+
* `--no-telemetry` flips `telemetry: false` via yargs negation;
|
|
24
|
+
* `POSTHOG_WIZARD_NO_TELEMETRY` is honoured separately so the env-var
|
|
25
|
+
* form documented in the README keeps working.
|
|
26
|
+
*/
|
|
27
|
+
function resolveNoTelemetry(options) {
|
|
28
|
+
if (options.telemetry === false) return true;
|
|
29
|
+
const env = process.env.POSTHOG_WIZARD_NO_TELEMETRY;
|
|
30
|
+
if (env == null || env === "") return false;
|
|
31
|
+
const norm = env.toLowerCase();
|
|
32
|
+
return norm !== "0" && norm !== "false";
|
|
33
|
+
}
|
|
34
|
+
//#endregion
|
|
35
|
+
//#region src/programs/task-stream/wizard-run-sync.ts
|
|
36
|
+
const STATUS = {
|
|
37
|
+
pending: "created",
|
|
38
|
+
in_progress: "running",
|
|
39
|
+
completed: "completed",
|
|
40
|
+
failed: "failed",
|
|
41
|
+
skipped: "completed"
|
|
42
|
+
};
|
|
43
|
+
var RunTaskNames = class {
|
|
44
|
+
names = /* @__PURE__ */ new Map();
|
|
45
|
+
used = /* @__PURE__ */ new Set();
|
|
46
|
+
snapshot(items) {
|
|
47
|
+
if (items.length > 100) throw new Error("task limit exceeded (100)");
|
|
48
|
+
const occurrences = /* @__PURE__ */ new Map();
|
|
49
|
+
const ids = /* @__PURE__ */ new Set();
|
|
50
|
+
return items.map((item) => {
|
|
51
|
+
const subject = item.label.trim();
|
|
52
|
+
if (!subject) throw new Error("blank task name");
|
|
53
|
+
const rawStatus = item.sourceStatus ?? item.status;
|
|
54
|
+
const status = STATUS[rawStatus];
|
|
55
|
+
if (!Object.hasOwn(STATUS, rawStatus)) throw new Error("invalid task status");
|
|
56
|
+
const occurrence = (occurrences.get(subject) ?? 0) + 1;
|
|
57
|
+
occurrences.set(subject, occurrence);
|
|
58
|
+
const id = item.id ? JSON.stringify([item.source, item.id]) : JSON.stringify([subject, occurrence]);
|
|
59
|
+
if (ids.has(id)) throw new Error("duplicate task identity");
|
|
60
|
+
ids.add(id);
|
|
61
|
+
let name = this.names.get(id);
|
|
62
|
+
if (!name) {
|
|
63
|
+
name = subject.slice(0, 255);
|
|
64
|
+
for (let n = 2; this.used.has(name); n++) {
|
|
65
|
+
const suffix = ` (${n})`;
|
|
66
|
+
name = subject.slice(0, 255 - suffix.length) + suffix;
|
|
67
|
+
}
|
|
68
|
+
this.names.set(id, name);
|
|
69
|
+
this.used.add(name);
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
name,
|
|
73
|
+
status
|
|
74
|
+
};
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
function createWizardRunSync(options) {
|
|
79
|
+
if (options.noTelemetry || options.mode === "ci") return;
|
|
80
|
+
if (options.mode === "headless" && options.assignedId === void 0) return;
|
|
81
|
+
return new WizardRunSync({
|
|
82
|
+
...options,
|
|
83
|
+
mode: options.assignedId !== void 0 ? "cloud" : "local"
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
var WizardRunSync = class {
|
|
87
|
+
names = new RunTaskNames();
|
|
88
|
+
tasksAbort = new AbortController();
|
|
89
|
+
reported = /* @__PURE__ */ new Set();
|
|
90
|
+
context;
|
|
91
|
+
queue = Promise.resolve();
|
|
92
|
+
lastBody;
|
|
93
|
+
stopped = false;
|
|
94
|
+
tasksDisabled = false;
|
|
95
|
+
authDisabled = false;
|
|
96
|
+
closing;
|
|
97
|
+
constructor(options) {
|
|
98
|
+
this.options = options;
|
|
99
|
+
}
|
|
100
|
+
capture(items) {
|
|
101
|
+
if (this.stopped || this.tasksDisabled || !items) return;
|
|
102
|
+
if (this.options.mode === "cloud" && !validate(this.options.assignedId ?? "")) {
|
|
103
|
+
this.tasksDisabled = true;
|
|
104
|
+
this.report("invalid cloud run assignment");
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const session = this.options.getSession();
|
|
108
|
+
if (session.runPhase === "idle") return;
|
|
109
|
+
if (!this.context) {
|
|
110
|
+
if (session.runPhase !== "running" || !session.credentials) return;
|
|
111
|
+
const { host, projectId } = session.credentials;
|
|
112
|
+
this.context = {
|
|
113
|
+
apiHost: host.appHost.replace(/\/$/, ""),
|
|
114
|
+
projectId,
|
|
115
|
+
programId: this.options.programId,
|
|
116
|
+
mode: this.options.mode,
|
|
117
|
+
id: this.options.assignedId
|
|
118
|
+
};
|
|
119
|
+
this.queue = this.initialize(session);
|
|
120
|
+
}
|
|
121
|
+
try {
|
|
122
|
+
const body = JSON.stringify({ tasks: this.names.snapshot(items) });
|
|
123
|
+
if (body === this.lastBody) return;
|
|
124
|
+
this.lastBody = body;
|
|
125
|
+
this.queue = this.queue.then(async () => {
|
|
126
|
+
if (this.tasksDisabled || this.tasksAbort.signal.aborted || !this.context?.id) return;
|
|
127
|
+
if (!await this.request("PUT", `${this.context.id}/tasks/`, body, this.tasksAbort.signal)) this.tasksDisabled = true;
|
|
128
|
+
});
|
|
129
|
+
} catch {
|
|
130
|
+
this.report("invalid task snapshot (names, statuses, identities or 100-task limit)");
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
shutdown(outcome, timeoutMs) {
|
|
134
|
+
if (this.closing) return this.closing;
|
|
135
|
+
this.stopped = true;
|
|
136
|
+
this.closing = this.finish(outcome, Math.max(0, timeoutMs));
|
|
137
|
+
return this.closing;
|
|
138
|
+
}
|
|
139
|
+
async initialize(session) {
|
|
140
|
+
const context = this.context;
|
|
141
|
+
if (!context || context.mode === "cloud") return;
|
|
142
|
+
const projectName = basename(resolve(session.installDir)).trim().slice(0, 255);
|
|
143
|
+
if (!projectName) {
|
|
144
|
+
this.tasksDisabled = true;
|
|
145
|
+
this.report("unsupported program or workspace configuration");
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
const body = JSON.stringify({
|
|
149
|
+
program_id: context.programId,
|
|
150
|
+
environment: "local",
|
|
151
|
+
workspace: {
|
|
152
|
+
type: "local_folder",
|
|
153
|
+
project_name: projectName
|
|
154
|
+
},
|
|
155
|
+
...valid("2.79.1") ? { wizard_version: VERSION } : {},
|
|
156
|
+
idempotency_key: randomUUID()
|
|
157
|
+
});
|
|
158
|
+
const result = await this.request("POST", "", body, this.tasksAbort.signal);
|
|
159
|
+
if (result && typeof result === "object" && "id" in result && typeof result.id === "string" && validate(result.id)) context.id = result.id;
|
|
160
|
+
else {
|
|
161
|
+
this.tasksDisabled = true;
|
|
162
|
+
this.report("local creation failed or returned an invalid ID; creation was not retried");
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
credentials(creds = this.options.getSession().credentials) {
|
|
166
|
+
const context = this.context;
|
|
167
|
+
if (!context) return;
|
|
168
|
+
if (!creds || creds.host.appHost.replace(/\/$/, "") !== context.apiHost || creds.projectId !== context.projectId) {
|
|
169
|
+
this.report("execution credentials changed host or project");
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
if (creds.missingScopes?.includes("wizard_run:write") || !creds.accessToken.startsWith("pha_")) {
|
|
173
|
+
this.authDisabled = true;
|
|
174
|
+
this.report("wizard_run:write OAuth grant required; authorize again");
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
return creds;
|
|
178
|
+
}
|
|
179
|
+
async request(method, suffix, body, signal) {
|
|
180
|
+
const context = this.context;
|
|
181
|
+
if (!context || this.authDisabled || signal.aborted) return;
|
|
182
|
+
let refreshed = false;
|
|
183
|
+
let rateLimited = false;
|
|
184
|
+
const attempts = method === "POST" ? 1 : 3;
|
|
185
|
+
for (let attempt = 0; attempt < attempts && !signal.aborted; attempt++) {
|
|
186
|
+
let retryMs = 500 * 2 ** attempt;
|
|
187
|
+
try {
|
|
188
|
+
const creds = this.credentials();
|
|
189
|
+
if (!creds) return;
|
|
190
|
+
const { res, data, current } = await this.bounded(async (requestSignal) => {
|
|
191
|
+
const current = this.credentials(await currentCredentials(creds));
|
|
192
|
+
if (!current) throw new Error("credentials unavailable");
|
|
193
|
+
const res = await (this.options.fetchImpl ?? fetch)(`${context.apiHost}/api/projects/${context.projectId}/wizard/runs/${suffix}`, {
|
|
194
|
+
method,
|
|
195
|
+
body,
|
|
196
|
+
signal: requestSignal,
|
|
197
|
+
headers: {
|
|
198
|
+
Authorization: `Bearer ${current.accessToken}`,
|
|
199
|
+
"Content-Type": "application/json"
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
return {
|
|
203
|
+
res,
|
|
204
|
+
data: method === "POST" && (res.status === 200 || res.status === 201) ? await res.json() : void 0,
|
|
205
|
+
current
|
|
206
|
+
};
|
|
207
|
+
}, signal, 5e3);
|
|
208
|
+
if (method === "POST" && [200, 201].includes(res.status) || method === "PUT" && res.status === 204 || method === "PATCH" && res.status === 200) return data ?? true;
|
|
209
|
+
if (res.status === 401 && current.refreshToken && !isGrantRevoked() && !refreshed && method !== "POST") {
|
|
210
|
+
refreshed = true;
|
|
211
|
+
if ((await this.bounded(() => currentCredentials(current, true), signal, 5e3)).accessToken === current.accessToken) {
|
|
212
|
+
this.authDisabled = true;
|
|
213
|
+
this.report("OAuth refresh could not recover the grant; authorize again");
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
if (res.status === 401 || res.status === 403) this.authDisabled = true;
|
|
219
|
+
if (res.status === 429 && !rateLimited) {
|
|
220
|
+
rateLimited = true;
|
|
221
|
+
retryMs = parseRetryAfter(res.headers.get("Retry-After"));
|
|
222
|
+
} else if (res.status < 500 || res.status >= 600) {
|
|
223
|
+
this.report(`${method} rejected (${res.status}); check assignment, grant and program configuration`);
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
} catch {
|
|
227
|
+
if (signal.aborted) return;
|
|
228
|
+
}
|
|
229
|
+
if (attempt + 1 < attempts) try {
|
|
230
|
+
await this.sleep(retryMs, signal);
|
|
231
|
+
} catch {
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
this.report(`${method} delivery exhausted`);
|
|
236
|
+
}
|
|
237
|
+
async finish(outcome, timeoutMs) {
|
|
238
|
+
const deadline = Date.now() + timeoutMs;
|
|
239
|
+
try {
|
|
240
|
+
await this.bounded(() => this.queue, new AbortController().signal, Math.floor(timeoutMs * .75));
|
|
241
|
+
} catch {
|
|
242
|
+
this.report("task drain timed out");
|
|
243
|
+
}
|
|
244
|
+
this.tasksAbort.abort();
|
|
245
|
+
if (this.context?.mode !== "local" || !this.context.id || this.authDisabled) return;
|
|
246
|
+
if (Date.now() >= deadline) {
|
|
247
|
+
this.report("terminal update budget exhausted");
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
const finalAbort = new AbortController();
|
|
251
|
+
const timer = setTimeout(() => finalAbort.abort(), Math.max(0, deadline - Date.now()));
|
|
252
|
+
try {
|
|
253
|
+
await this.request("PATCH", `${this.context.id}/`, JSON.stringify({ status: outcome }), finalAbort.signal);
|
|
254
|
+
} finally {
|
|
255
|
+
clearTimeout(timer);
|
|
256
|
+
finalAbort.abort();
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
async bounded(operation, parent, ms) {
|
|
260
|
+
const controller = new AbortController();
|
|
261
|
+
const abort = () => controller.abort();
|
|
262
|
+
parent.addEventListener("abort", abort, { once: true });
|
|
263
|
+
if (parent.aborted) controller.abort();
|
|
264
|
+
const timer = setTimeout(abort, ms);
|
|
265
|
+
let onAbort = () => void 0;
|
|
266
|
+
const cancelled = new Promise((_, reject) => {
|
|
267
|
+
onAbort = () => reject(/* @__PURE__ */ new Error("request cancelled"));
|
|
268
|
+
controller.signal.addEventListener("abort", onAbort, { once: true });
|
|
269
|
+
if (controller.signal.aborted) onAbort();
|
|
270
|
+
});
|
|
271
|
+
try {
|
|
272
|
+
return await Promise.race([operation(controller.signal), cancelled]);
|
|
273
|
+
} finally {
|
|
274
|
+
clearTimeout(timer);
|
|
275
|
+
parent.removeEventListener("abort", abort);
|
|
276
|
+
controller.signal.removeEventListener("abort", onAbort);
|
|
277
|
+
controller.abort();
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
sleep(ms, signal) {
|
|
281
|
+
return new Promise((resolve) => {
|
|
282
|
+
const finish = () => {
|
|
283
|
+
clearTimeout(timer);
|
|
284
|
+
signal.removeEventListener("abort", finish);
|
|
285
|
+
resolve();
|
|
286
|
+
};
|
|
287
|
+
const timer = setTimeout(finish, ms);
|
|
288
|
+
signal.addEventListener("abort", finish, { once: true });
|
|
289
|
+
if (signal.aborted) finish();
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
report(message) {
|
|
293
|
+
if (this.reported.has(message)) return;
|
|
294
|
+
this.reported.add(message);
|
|
295
|
+
(this.options.onError ?? ((m) => logToFile(`[wizard-run-sync] ${m}`)))(message);
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
//#endregion
|
|
299
|
+
//#region src/lib/runners/run-wizard.ts
|
|
300
|
+
const WIZARD_VERSION = VERSION;
|
|
301
|
+
/** The session a run step's agent runs in: scoped to the step's target dir
|
|
302
|
+
* (e.g. a monorepo sub-app) with its own framework context, after any prep.
|
|
303
|
+
* A step without `targetDir` runs in the live session, unchanged.
|
|
304
|
+
* The frameworkContext copy is shallow and unfiltered — name keys per owning program. */
|
|
305
|
+
async function prepareRunSession(step, live) {
|
|
306
|
+
const session = step.targetDir ? {
|
|
307
|
+
...live,
|
|
308
|
+
installDir: step.targetDir(live),
|
|
309
|
+
frameworkContext: { ...live.frameworkContext }
|
|
310
|
+
} : live;
|
|
311
|
+
if (step.onRunPrep) await step.onRunPrep(session);
|
|
312
|
+
return session;
|
|
313
|
+
}
|
|
314
|
+
/** Advance one step of a composed run to completion: the auth screen
|
|
315
|
+
* authenticates (every later run reuses it); a step carrying its own `run`
|
|
316
|
+
* thunk runs that agent in its dir and is recorded in `completedRuns`; the
|
|
317
|
+
* host program's own run screen runs `config.run`; any other screen waits for
|
|
318
|
+
* the user to satisfy `isComplete`. */
|
|
319
|
+
async function advanceStep(step, store, config) {
|
|
320
|
+
if (step.screenId === "auth") {
|
|
321
|
+
await authenticate(store.session, config.id);
|
|
322
|
+
maybeStampAiSdkDetected(store.session);
|
|
323
|
+
} else if (step.run) {
|
|
324
|
+
await step.run(await prepareRunSession(step, store.session));
|
|
325
|
+
store.completeRunStep(step.id);
|
|
326
|
+
} else if (step.screenId === "run") await runProgramAgent(config, await prepareRunSession(step, store.session));
|
|
327
|
+
else if (step.isComplete) await store.waitUntil(step.isComplete);
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Run a full wizard program in the TUI. Handles the full lifecycle: start TUI,
|
|
331
|
+
* build session, run detection, wait for intro gate, execute the
|
|
332
|
+
* agent pipeline, wait for outro dismissal, then exit.
|
|
333
|
+
*/
|
|
334
|
+
function runWizard(config, options) {
|
|
335
|
+
let tui = null;
|
|
336
|
+
let taskStream = null;
|
|
337
|
+
let onSignal = null;
|
|
338
|
+
let exitInProgress = false;
|
|
339
|
+
let signalled = false;
|
|
340
|
+
let unregisterShutdown;
|
|
341
|
+
(async () => {
|
|
342
|
+
try {
|
|
343
|
+
const installDir = options.installDir || process.cwd();
|
|
344
|
+
const { startTUI } = await import("./start-tui-Bo2L0bar.js");
|
|
345
|
+
const { buildSession, RunPhase } = await import("./wizard-session-DGaUHOF3.js");
|
|
346
|
+
const { TaskStreamPush } = await import("./task-stream-Bw6JaLCX.js");
|
|
347
|
+
const { PostHogDestination } = await import("./posthog-CUgCEhH0.js");
|
|
348
|
+
const { createFileDestination } = await import("./file-C5JMsyR1.js");
|
|
349
|
+
const local = getLocalDev();
|
|
350
|
+
const localServicesError = await checkLocalServices({
|
|
351
|
+
...local,
|
|
352
|
+
localPosthog: local.localPosthog && !options.baseUrl
|
|
353
|
+
});
|
|
354
|
+
if (localServicesError) {
|
|
355
|
+
const { wizardAbort } = await import("./wizard-abort-Br1qMDNa.js");
|
|
356
|
+
await wizardAbort({ message: localServicesError });
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
tui = startTUI(WIZARD_VERSION, config.id, () => onSignal?.());
|
|
360
|
+
const activeTui = tui;
|
|
361
|
+
const session = buildSession({
|
|
362
|
+
debug: options.debug,
|
|
363
|
+
localDev: options.localDev,
|
|
364
|
+
localMcp: options.localMcp,
|
|
365
|
+
localPosthog: options.localPosthog,
|
|
366
|
+
installDir,
|
|
367
|
+
ci: false,
|
|
368
|
+
signup: options.signup,
|
|
369
|
+
apiKey: options.apiKey,
|
|
370
|
+
projectId: options.projectId,
|
|
371
|
+
email: options.email,
|
|
372
|
+
baseUrl: options.baseUrl,
|
|
373
|
+
benchmark: options.benchmark,
|
|
374
|
+
yaraReport: options.yaraReport,
|
|
375
|
+
noTelemetry: resolveNoTelemetry(options),
|
|
376
|
+
harness: options.harness,
|
|
377
|
+
sequence: options.sequence,
|
|
378
|
+
model: options.model,
|
|
379
|
+
integrate: options.integrate,
|
|
380
|
+
captureAio: options.captureAio
|
|
381
|
+
});
|
|
382
|
+
session.programLabel = config.id;
|
|
383
|
+
if (options.skillId) session.skillId = options.skillId;
|
|
384
|
+
else if (config.skillId) session.skillId = config.skillId;
|
|
385
|
+
activeTui.store.session = session;
|
|
386
|
+
onSignal = () => {
|
|
387
|
+
if (signalled || exitInProgress) return;
|
|
388
|
+
signalled = true;
|
|
389
|
+
logToFile("[run-wizard] signal received, flushing task stream");
|
|
390
|
+
runCleanups();
|
|
391
|
+
if (activeTui.store.session.runPhase === RunPhase.Running) activeTui.store.setRunPhase(RunPhase.Error);
|
|
392
|
+
const teardown = () => {
|
|
393
|
+
unregisterShutdown?.();
|
|
394
|
+
if (onSignal) {
|
|
395
|
+
process.off("SIGINT", onSignal);
|
|
396
|
+
process.off("SIGTERM", onSignal);
|
|
397
|
+
}
|
|
398
|
+
try {
|
|
399
|
+
activeTui.unmount();
|
|
400
|
+
} catch {}
|
|
401
|
+
process.exit(130);
|
|
402
|
+
};
|
|
403
|
+
Promise.all([taskStream?.shutdown(2e3, "cancelled"), analytics.shutdown("cancelled")]).catch(() => logToFile("[run-wizard] cancellation shutdown failed")).finally(teardown);
|
|
404
|
+
};
|
|
405
|
+
process.on("SIGINT", onSignal);
|
|
406
|
+
process.on("SIGTERM", onSignal);
|
|
407
|
+
for (;;) {
|
|
408
|
+
await activeTui.store.runReadyHooks();
|
|
409
|
+
await activeTui.store.getGate("intro");
|
|
410
|
+
const active = activeTui.store.router.activeProgram;
|
|
411
|
+
if (active === config.id) break;
|
|
412
|
+
config = getProgramConfig(active);
|
|
413
|
+
}
|
|
414
|
+
const fileDestination = createFileDestination(options.taskStreamLog);
|
|
415
|
+
const destinations = [...session.noTelemetry ? [] : [new PostHogDestination({
|
|
416
|
+
getCredentials: () => activeTui.store.session.credentials,
|
|
417
|
+
onError: (err) => logToFile("[task-stream-push]", err.message)
|
|
418
|
+
})], ...fileDestination ? [fileDestination] : []];
|
|
419
|
+
const taskStreamEnabled = destinations.length > 0;
|
|
420
|
+
const activeStream = new TaskStreamPush({
|
|
421
|
+
store: activeTui.store,
|
|
422
|
+
getFlags: () => analytics.getCachedWizardFlags(),
|
|
423
|
+
programId: config.streamWorkflowId ?? config.id,
|
|
424
|
+
runSync: createWizardRunSync({
|
|
425
|
+
mode: "local",
|
|
426
|
+
programId: config.id,
|
|
427
|
+
assignedId: options.runId ?? runtimeEnv("POSTHOG_WIZARD_RUN_ID"),
|
|
428
|
+
noTelemetry: session.noTelemetry,
|
|
429
|
+
getSession: () => activeTui.store.session
|
|
430
|
+
}),
|
|
431
|
+
destinations,
|
|
432
|
+
eventPlanPath: config.eventPlanFile ? join(session.installDir, config.eventPlanFile) : void 0,
|
|
433
|
+
auditChecks: config.auditLedgerFile ? () => getAuditChecks(activeTui.store.session) : void 0,
|
|
434
|
+
enabled: taskStreamEnabled
|
|
435
|
+
});
|
|
436
|
+
taskStream = activeStream;
|
|
437
|
+
activeStream.attach();
|
|
438
|
+
unregisterShutdown = registerShutdown((outcome) => {
|
|
439
|
+
if (activeTui.store.session.runPhase === RunPhase.Running) activeTui.store.setRunPhase(RunPhase.Error);
|
|
440
|
+
return activeStream.shutdown(2e3, outcome);
|
|
441
|
+
});
|
|
442
|
+
await activeTui.store.getGate("integration-check");
|
|
443
|
+
await activeTui.store.getGate("health-check");
|
|
444
|
+
const skipAgent = config.run == null;
|
|
445
|
+
const shown = (s) => !s.show || s.show(activeTui.store.session);
|
|
446
|
+
if (config.steps.some((s) => s.run || s.targetDir)) for (const step of config.steps) {
|
|
447
|
+
if (step.screenId === "outro") break;
|
|
448
|
+
if (shown(step)) await advanceStep(step, activeTui.store, config);
|
|
449
|
+
}
|
|
450
|
+
else if (skipAgent) {
|
|
451
|
+
const { getOrAskForProjectData } = await import("./setup-utils-CVS86NYR.js");
|
|
452
|
+
const { projectApiKey, host, accessToken, projectId } = await getOrAskForProjectData({
|
|
453
|
+
signup: session.signup,
|
|
454
|
+
ci: session.ci,
|
|
455
|
+
apiKey: session.apiKey,
|
|
456
|
+
projectId: session.projectId,
|
|
457
|
+
baseUrl: session.baseUrl,
|
|
458
|
+
programId: config.id
|
|
459
|
+
});
|
|
460
|
+
activeTui.store.setCredentials({
|
|
461
|
+
accessToken,
|
|
462
|
+
projectApiKey,
|
|
463
|
+
host,
|
|
464
|
+
projectId
|
|
465
|
+
});
|
|
466
|
+
} else try {
|
|
467
|
+
await runProgramAgent(config, activeTui.store.session);
|
|
468
|
+
} catch (error) {
|
|
469
|
+
const failure = classifyRunFailure(error);
|
|
470
|
+
logToFile("[run-wizard] run failed, handing off:", error);
|
|
471
|
+
runCleanups();
|
|
472
|
+
analytics.captureException(error instanceof Error ? error : new Error(String(error)), { error_code: failure.code });
|
|
473
|
+
getUI().outroError({
|
|
474
|
+
kind: "error",
|
|
475
|
+
errorCode: failure.code,
|
|
476
|
+
message: failure.message
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
if (signalled) return;
|
|
480
|
+
const runFailed = isRunFailure(activeTui.store.session);
|
|
481
|
+
await activeStream.finishRun(runFailed ? "failed" : "completed");
|
|
482
|
+
await activeTui.store.waitUntil((s) => {
|
|
483
|
+
if (s.mintHandoff === "exit") return true;
|
|
484
|
+
if (skipAgent && !runFailed) return s.outroDismissed;
|
|
485
|
+
return s.skillsComplete;
|
|
486
|
+
});
|
|
487
|
+
exitInProgress = true;
|
|
488
|
+
await activeStream.shutdown(2e3);
|
|
489
|
+
unregisterShutdown?.();
|
|
490
|
+
process.off("SIGINT", onSignal);
|
|
491
|
+
process.off("SIGTERM", onSignal);
|
|
492
|
+
if (runFailed) await analytics.shutdown("error");
|
|
493
|
+
activeTui.unmount();
|
|
494
|
+
process.exit(runFailed ? 1 : 0);
|
|
495
|
+
} catch (err) {
|
|
496
|
+
if (signalled) return;
|
|
497
|
+
logToFile("[run-wizard] FATAL:", err);
|
|
498
|
+
runCleanups();
|
|
499
|
+
exitInProgress = true;
|
|
500
|
+
if (onSignal) {
|
|
501
|
+
process.off("SIGINT", onSignal);
|
|
502
|
+
process.off("SIGTERM", onSignal);
|
|
503
|
+
}
|
|
504
|
+
if (taskStream) try {
|
|
505
|
+
await taskStream.shutdown(2e3, "failed");
|
|
506
|
+
} catch {}
|
|
507
|
+
unregisterShutdown?.();
|
|
508
|
+
if (tui) try {
|
|
509
|
+
tui.unmount();
|
|
510
|
+
} catch {}
|
|
511
|
+
const failure = classifyRunFailure(err);
|
|
512
|
+
if (failure.coded) console.error(failure.message);
|
|
513
|
+
else console.error("Wizard run failed:", err);
|
|
514
|
+
console.error(`Full logs: ${getLogFilePath()}`);
|
|
515
|
+
emitWizardError({
|
|
516
|
+
code: failure.code,
|
|
517
|
+
message: failure.message
|
|
518
|
+
});
|
|
519
|
+
process.exit(1);
|
|
520
|
+
}
|
|
521
|
+
})();
|
|
522
|
+
}
|
|
523
|
+
//#endregion
|
|
524
|
+
//#region src/programs/detect-map.ts
|
|
525
|
+
const DETECT_CODES = {
|
|
526
|
+
"bad-directory": ErrorCodes.DetectBadDirectory,
|
|
527
|
+
"unsupported-platform": ErrorCodes.DetectUnsupportedPlatform,
|
|
528
|
+
"no-project-files": ErrorCodes.DetectNoProjectFiles,
|
|
529
|
+
"no-sources": ErrorCodes.DetectNoSources,
|
|
530
|
+
"no-package-json": ErrorCodes.DetectNoPackageJson,
|
|
531
|
+
"no-sdks": ErrorCodes.DetectNoSdks,
|
|
532
|
+
"missing-stripe": ErrorCodes.DetectMissingStripe,
|
|
533
|
+
"no-posthog-sdk": ErrorCodes.DetectNoPosthogSdk,
|
|
534
|
+
"no-posthog": ErrorCodes.DetectNoPosthogSdk,
|
|
535
|
+
"missing-posthog": ErrorCodes.DetectNoPosthogSdk
|
|
536
|
+
};
|
|
537
|
+
/**
|
|
538
|
+
* `kind` arrives as a bare string — `frameworkContext.detectError` is untyped
|
|
539
|
+
* storage — so the lookup can still miss. It falls back to a detect-group code
|
|
540
|
+
* with `retry: 'no'`, never to `InternalUnhandled`: an unrecognized precondition
|
|
541
|
+
* failure is still a precondition failure, and telling a sandbox to retry one
|
|
542
|
+
* costs it the whole budget.
|
|
543
|
+
*/
|
|
544
|
+
function detectErrorCode(kind) {
|
|
545
|
+
return DETECT_CODES[kind] ?? ErrorCodes.DetectUnclassified;
|
|
546
|
+
}
|
|
547
|
+
//#endregion
|
|
548
|
+
//#region src/lib/runners/run-non-interactive.ts
|
|
549
|
+
/** User-facing label for a non-interactive mode. */
|
|
550
|
+
function modeLabel(mode) {
|
|
551
|
+
return mode === "headless" ? "Headless" : "CI";
|
|
552
|
+
}
|
|
553
|
+
/** The credentials every non-interactive mode accepts, for error messages. */
|
|
554
|
+
const API_KEY_HINT = "personal API key phx_xxx or wizard-app OAuth access token pha_xxx";
|
|
555
|
+
/**
|
|
556
|
+
* The single non-interactive validation layer: requires api-key and
|
|
557
|
+
* install-dir. Every non-interactive entry point routes through
|
|
558
|
+
* `runNonInteractive`, so this is the one place these checks live. UI must be
|
|
559
|
+
* initialized before calling.
|
|
560
|
+
*/
|
|
561
|
+
function validateNonInteractiveOptions(options, mode) {
|
|
562
|
+
const label = modeLabel(mode);
|
|
563
|
+
if (!options.apiKey) {
|
|
564
|
+
getUI().intro("PostHog Wizard");
|
|
565
|
+
getUI().log.error(`${label} mode requires --api-key (${API_KEY_HINT})`);
|
|
566
|
+
emitWizardError({
|
|
567
|
+
code: ErrorCodes.ArgsMissingApiKey,
|
|
568
|
+
message: `${label} mode requires --api-key (${API_KEY_HINT})`
|
|
569
|
+
});
|
|
570
|
+
process.exit(1);
|
|
571
|
+
}
|
|
572
|
+
if (!options.installDir) {
|
|
573
|
+
getUI().intro("PostHog Wizard");
|
|
574
|
+
getUI().log.error(`${label} mode requires --install-dir (directory to install in)`);
|
|
575
|
+
emitWizardError({
|
|
576
|
+
code: ErrorCodes.ArgsMissingInstallDir,
|
|
577
|
+
message: `${label} mode requires --install-dir`
|
|
578
|
+
});
|
|
579
|
+
process.exit(1);
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
/**
|
|
583
|
+
* Non-interactive pipeline shared by CI (`runWizardCI`) and headless
|
|
584
|
+
* (`runWizardHeadless`) runs.
|
|
585
|
+
*
|
|
586
|
+
* Validates flags, builds a `ci:true` session, runs `config.ciPreRun` (or the
|
|
587
|
+
* program's `onReady` hooks by default), executes `runProgramAgent`, and routes any
|
|
588
|
+
* failure through `wizardAbort`. `wizardAbort` owns all exits — never add a
|
|
589
|
+
* raw `process.exit` here.
|
|
590
|
+
*
|
|
591
|
+
* `mode` is the only difference between the two callers today (it sets the
|
|
592
|
+
* analytics build tag and the user-facing label). Keeping it a parameter is
|
|
593
|
+
* what lets CI and headless share this body now and diverge later — branch on
|
|
594
|
+
* `mode` here, or stop sharing this function entirely.
|
|
595
|
+
*/
|
|
596
|
+
function runNonInteractive(config, options, mode) {
|
|
597
|
+
setUI(new LoggingUI());
|
|
598
|
+
validateNonInteractiveOptions(options, mode);
|
|
599
|
+
analytics.setTag("build", mode);
|
|
600
|
+
(async () => {
|
|
601
|
+
const path = await import("path");
|
|
602
|
+
const { buildSession, RunPhase, OutroKind } = await import("./wizard-session-DGaUHOF3.js");
|
|
603
|
+
const { readEnvironment } = await import("./environment-CwD8OPYj.js");
|
|
604
|
+
const { readApiKeyFromEnv } = await import("./env-api-key-CaWEDj_9.js");
|
|
605
|
+
const { configureLogFileFromEnvironment, logToFile } = await import("./debug-BuYHGr6_.js");
|
|
606
|
+
const { wizardAbort, WizardError } = await import("./wizard-abort-Br1qMDNa.js");
|
|
607
|
+
configureLogFileFromEnvironment();
|
|
608
|
+
const env = readEnvironment();
|
|
609
|
+
const apiKey = options.apiKey ?? readApiKeyFromEnv() ?? void 0;
|
|
610
|
+
const installDir = path.isAbsolute(options.installDir) ? options.installDir : path.join(process.cwd(), options.installDir);
|
|
611
|
+
const session = buildSession({
|
|
612
|
+
debug: options.debug,
|
|
613
|
+
installDir,
|
|
614
|
+
ci: true,
|
|
615
|
+
signup: options.signup,
|
|
616
|
+
localDev: options.localDev,
|
|
617
|
+
localMcp: options.localMcp,
|
|
618
|
+
localPosthog: options.localPosthog,
|
|
619
|
+
apiKey,
|
|
620
|
+
email: options.email,
|
|
621
|
+
projectId: options.projectId,
|
|
622
|
+
baseUrl: options.baseUrl,
|
|
623
|
+
benchmark: options.benchmark,
|
|
624
|
+
yaraReport: options.yaraReport,
|
|
625
|
+
noTelemetry: resolveNoTelemetry(options),
|
|
626
|
+
harness: options.harness,
|
|
627
|
+
sequence: options.sequence,
|
|
628
|
+
model: options.model,
|
|
629
|
+
captureAio: options.captureAio,
|
|
630
|
+
...env,
|
|
631
|
+
region: options.region ?? env.region
|
|
632
|
+
});
|
|
633
|
+
session.programLabel = config.id;
|
|
634
|
+
if (config.skillId) session.skillId = config.skillId;
|
|
635
|
+
const runDef = typeof config.run === "object" ? config.run : null;
|
|
636
|
+
getUI().intro("Welcome to the PostHog setup wizard");
|
|
637
|
+
getUI().log.info(`Running ${config.id} in ${modeLabel(mode)} mode`);
|
|
638
|
+
const localServicesError = await checkLocalServices({
|
|
639
|
+
...getLocalDev(),
|
|
640
|
+
localMcp: session.localMcp,
|
|
641
|
+
localPosthog: session.baseUrl === POSTHOG_LOCAL_URL
|
|
642
|
+
});
|
|
643
|
+
if (localServicesError) {
|
|
644
|
+
await wizardAbort({
|
|
645
|
+
code: ErrorCodes.EnvLocalServicesDown,
|
|
646
|
+
message: localServicesError
|
|
647
|
+
});
|
|
648
|
+
return;
|
|
649
|
+
}
|
|
650
|
+
let store = null;
|
|
651
|
+
let taskStream = null;
|
|
652
|
+
{
|
|
653
|
+
const { WizardStore } = await import("./store-BpqySPXm.js");
|
|
654
|
+
const { HeadlessUI } = await import("./headless-ui-CqI2gXlD.js");
|
|
655
|
+
const { TaskStreamPush, PostHogDestination, createFileDestination } = await import("./task-stream-Bw6JaLCX.js");
|
|
656
|
+
const fileDestination = createFileDestination(mode === "ci" ? options.taskStreamLog ?? "" : options.taskStreamLog);
|
|
657
|
+
const posthogDestination = mode === "headless" && !session.noTelemetry ? new PostHogDestination({
|
|
658
|
+
getCredentials: () => store?.session.credentials ?? session.credentials,
|
|
659
|
+
onError: (e) => logToFile("[headless task-stream]", e.message)
|
|
660
|
+
}) : null;
|
|
661
|
+
const destinations = [...posthogDestination ? [posthogDestination] : [], ...fileDestination ? [fileDestination] : []];
|
|
662
|
+
const headlessStore = new WizardStore(config.id);
|
|
663
|
+
store = headlessStore;
|
|
664
|
+
headlessStore.session = session;
|
|
665
|
+
setUI(new HeadlessUI(headlessStore));
|
|
666
|
+
taskStream = new TaskStreamPush({
|
|
667
|
+
store: headlessStore,
|
|
668
|
+
getFlags: () => analytics.getCachedWizardFlags(),
|
|
669
|
+
programId: config.streamWorkflowId ?? config.id,
|
|
670
|
+
runSync: createWizardRunSync({
|
|
671
|
+
mode,
|
|
672
|
+
programId: config.id,
|
|
673
|
+
assignedId: options.runId ?? runtimeEnv("POSTHOG_WIZARD_RUN_ID"),
|
|
674
|
+
noTelemetry: session.noTelemetry,
|
|
675
|
+
getSession: () => headlessStore.session
|
|
676
|
+
}),
|
|
677
|
+
destinations,
|
|
678
|
+
eventPlanPath: config.eventPlanFile ? join(session.installDir, config.eventPlanFile) : void 0,
|
|
679
|
+
auditChecks: config.auditLedgerFile ? () => getAuditChecks(headlessStore.session) : void 0,
|
|
680
|
+
enabled: destinations.length > 0
|
|
681
|
+
});
|
|
682
|
+
taskStream.attach();
|
|
683
|
+
if (fileDestination) logToFile(`[task-stream] ${mode} dump: ${fileDestination.path}`);
|
|
684
|
+
}
|
|
685
|
+
const settleStream = async (phase, outroData, outcome = phase === RunPhase.Completed ? "completed" : "failed") => {
|
|
686
|
+
if (!store || !taskStream) return;
|
|
687
|
+
if (outroData) store.setOutroData(outroData);
|
|
688
|
+
store.setRunPhase(phase);
|
|
689
|
+
await taskStream.shutdown(2e3, outcome);
|
|
690
|
+
process.off("SIGINT", onSignal);
|
|
691
|
+
process.off("SIGTERM", onSignal);
|
|
692
|
+
unregisterShutdown();
|
|
693
|
+
};
|
|
694
|
+
const unregisterShutdown = registerShutdown((outcome) => settleStream(RunPhase.Error, void 0, outcome));
|
|
695
|
+
let signalled = false;
|
|
696
|
+
const onSignal = () => {
|
|
697
|
+
if (signalled) return;
|
|
698
|
+
signalled = true;
|
|
699
|
+
runCleanups();
|
|
700
|
+
settleStream(RunPhase.Error, void 0, "cancelled").then(() => wizardAbort({ exitCode: 130 }));
|
|
701
|
+
};
|
|
702
|
+
process.on("SIGINT", onSignal);
|
|
703
|
+
process.on("SIGTERM", onSignal);
|
|
704
|
+
try {
|
|
705
|
+
if (mode === "ci") {
|
|
706
|
+
const { configureGatewayFromCIEnvironment } = await import("./agent-BEjARD2a.js");
|
|
707
|
+
configureGatewayFromCIEnvironment(Number(session.projectId), session.region ?? "us");
|
|
708
|
+
}
|
|
709
|
+
if (config.ciPreRun) await config.ciPreRun(session, { log: {
|
|
710
|
+
info: (message) => getUI().log.info(message),
|
|
711
|
+
warn: (message) => getUI().log.warn(message)
|
|
712
|
+
} });
|
|
713
|
+
else {
|
|
714
|
+
const readyCtx = {
|
|
715
|
+
session,
|
|
716
|
+
setFrameworkContext: (key, value) => {
|
|
717
|
+
session.frameworkContext[key] = value;
|
|
718
|
+
},
|
|
719
|
+
setFrameworkConfig: () => void 0,
|
|
720
|
+
setDetectedFramework: () => void 0,
|
|
721
|
+
setSkillId: (skillId) => {
|
|
722
|
+
session.skillId = skillId;
|
|
723
|
+
},
|
|
724
|
+
setUnsupportedVersion: (info) => {
|
|
725
|
+
session.unsupportedVersion = info;
|
|
726
|
+
},
|
|
727
|
+
addDiscoveredFeature: () => void 0,
|
|
728
|
+
setDetectionComplete: () => void 0,
|
|
729
|
+
setPosthogSdkDetected: (detected) => {
|
|
730
|
+
session.posthogSdkDetected = detected;
|
|
731
|
+
}
|
|
732
|
+
};
|
|
733
|
+
for (const step of config.steps) if (step.onReady) await step.onReady(readyCtx);
|
|
734
|
+
const detectError = session.frameworkContext.detectError;
|
|
735
|
+
if (session.unsupportedVersion) {
|
|
736
|
+
const { current, minimum, docsUrl } = session.unsupportedVersion;
|
|
737
|
+
const message = `Detected framework version ${current} is not supported. Minimum supported version is ${minimum}.`;
|
|
738
|
+
await settleStream(RunPhase.Error, {
|
|
739
|
+
kind: OutroKind.Error,
|
|
740
|
+
message,
|
|
741
|
+
errorCode: ErrorCodes.DetectUnsupportedVersion
|
|
742
|
+
});
|
|
743
|
+
await wizardAbort({
|
|
744
|
+
code: ErrorCodes.DetectUnsupportedVersion,
|
|
745
|
+
message: `${message}\n\nSee ${docsUrl}`,
|
|
746
|
+
error: new WizardError(`${config.id} unsupported framework version`, {
|
|
747
|
+
integration: config.id,
|
|
748
|
+
current,
|
|
749
|
+
minimum
|
|
750
|
+
}, ErrorCodes.DetectUnsupportedVersion)
|
|
751
|
+
});
|
|
752
|
+
}
|
|
753
|
+
if (detectError) {
|
|
754
|
+
const code = detectErrorCode(detectError.kind);
|
|
755
|
+
const detectKind = detectError.kind;
|
|
756
|
+
const detail = { ...detectError };
|
|
757
|
+
await settleStream(RunPhase.Error, {
|
|
758
|
+
kind: OutroKind.Error,
|
|
759
|
+
message: `Prerequisites not met: ${detectKind}`,
|
|
760
|
+
errorCode: code,
|
|
761
|
+
errorDetail: detail
|
|
762
|
+
});
|
|
763
|
+
await wizardAbort({
|
|
764
|
+
code,
|
|
765
|
+
detail,
|
|
766
|
+
message: `Prerequisites not met: ${detectKind}\n\nSee ${runDef?.docsUrl ?? "https://posthog.com/docs"}`,
|
|
767
|
+
error: new WizardError(`${config.id} prerequisites failed`, {
|
|
768
|
+
integration: config.id,
|
|
769
|
+
detect_error_kind: detectKind
|
|
770
|
+
}, code)
|
|
771
|
+
});
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
const { runProgramAgent } = await import("./run-agent-legacy-ChacZImU.js");
|
|
775
|
+
await runProgramAgent(config, session);
|
|
776
|
+
if (signalled) return;
|
|
777
|
+
await settleStream(RunPhase.Completed);
|
|
778
|
+
} catch (error) {
|
|
779
|
+
if (signalled) return;
|
|
780
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
781
|
+
const errorStack = error instanceof Error && error.stack ? error.stack : void 0;
|
|
782
|
+
logToFile(`[${mode}] ERROR: ${errorMessage}`);
|
|
783
|
+
if (errorStack) logToFile(`[${mode}] STACK: ${errorStack}`);
|
|
784
|
+
const debugInfo = session.debug && errorStack ? `\n\n${errorStack}` : "";
|
|
785
|
+
const docsUrl = session.frameworkConfig?.metadata.docsUrl ?? runDef?.docsUrl ?? "https://posthog.com/docs";
|
|
786
|
+
const failure = classifyRunFailure(error);
|
|
787
|
+
await settleStream(RunPhase.Error, {
|
|
788
|
+
kind: OutroKind.Error,
|
|
789
|
+
message: errorMessage,
|
|
790
|
+
errorCode: failure.code
|
|
791
|
+
});
|
|
792
|
+
await wizardAbort({
|
|
793
|
+
code: failure.code,
|
|
794
|
+
message: failure.coded ? `${errorMessage}${debugInfo}` : `Something went wrong: ${errorMessage}\n\nYou can read the documentation at ${docsUrl} to set up manually.${debugInfo}`,
|
|
795
|
+
error
|
|
796
|
+
});
|
|
797
|
+
}
|
|
798
|
+
})().catch((error) => {
|
|
799
|
+
emitWizardError({
|
|
800
|
+
code: ErrorCodes.InternalUnhandled,
|
|
801
|
+
message: error instanceof Error ? error.message : String(error)
|
|
802
|
+
});
|
|
803
|
+
process.exit(1);
|
|
804
|
+
});
|
|
805
|
+
}
|
|
806
|
+
//#endregion
|
|
807
|
+
//#region src/lib/runners/run-wizard-ci.ts
|
|
808
|
+
/**
|
|
809
|
+
* CI-mode entry point (`--ci`, dev/test builds). A thin shell over the shared
|
|
810
|
+
* non-interactive pipeline — see `runNonInteractive`. Kept as its own function
|
|
811
|
+
* so CI and headless (`runWizardHeadless`) can diverge without re-threading the
|
|
812
|
+
* many callers that route here.
|
|
813
|
+
*/
|
|
814
|
+
function runWizardCI(config, options) {
|
|
815
|
+
runNonInteractive(config, options, "ci");
|
|
816
|
+
}
|
|
817
|
+
//#endregion
|
|
818
|
+
//#region src/lib/runners/run-wizard-headless.ts
|
|
819
|
+
/**
|
|
820
|
+
* Headless entry point (the experimental published-build, non-interactive run
|
|
821
|
+
* path; see @lib/headless-mode). A thin shell over the shared non-interactive
|
|
822
|
+
* pipeline — see `runNonInteractive`. Today it behaves exactly like
|
|
823
|
+
* `runWizardCI`; it exists as a separate function so headless can diverge later
|
|
824
|
+
* (its own auth handling, telemetry, prompts, …) without touching CI or its
|
|
825
|
+
* callers. Diverge by branching on the mode inside `runNonInteractive`, or by
|
|
826
|
+
* giving this function its own body.
|
|
827
|
+
*/
|
|
828
|
+
function runWizardHeadless(config, options) {
|
|
829
|
+
runNonInteractive(config, options, "headless");
|
|
830
|
+
}
|
|
831
|
+
//#endregion
|
|
832
|
+
export { runWizard as i, runWizardCI as n, API_KEY_HINT as r, runWizardHeadless as t };
|
|
833
|
+
|
|
834
|
+
//# sourceMappingURL=runners-ov3EXF1n.js.map
|