@posthog/wizard 2.50.0 → 2.52.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/{add-mcp-server-to-clients-Bd8XRxzi.js → add-mcp-server-to-clients-DJyWMMGj.js} +5 -5
- package/dist/{add-mcp-server-to-clients-Bd8XRxzi.js.map → add-mcp-server-to-clients-DJyWMMGj.js.map} +1 -1
- package/dist/{agent-interface-C_aRBziP.js → agent-interface-DoFVHRFh.js} +30 -69
- package/dist/agent-interface-DoFVHRFh.js.map +1 -0
- package/dist/agent-prompt-loader-D-cPVoL5.js +275 -0
- package/dist/agent-prompt-loader-D-cPVoL5.js.map +1 -0
- package/dist/{agent-runner-NzzrOB02.js → agent-runner-B1qCtjid.js} +100 -318
- package/dist/agent-runner-B1qCtjid.js.map +1 -0
- package/dist/{analytics-CArgq7XO.js → analytics-BXz4SIuS.js} +33 -20
- package/dist/analytics-BXz4SIuS.js.map +1 -0
- package/dist/analytics-D2xds3nw.js +2 -0
- package/dist/{api-CX1g-14-.js → api-BaacjH-Y.js} +3 -3
- package/dist/{api-CX1g-14-.js.map → api-BaacjH-Y.js.map} +1 -1
- package/dist/bin.js +97 -91
- package/dist/bin.js.map +1 -1
- package/dist/bounded-fs-Cx-8nk-1.js +242 -0
- package/dist/bounded-fs-Cx-8nk-1.js.map +1 -0
- package/dist/{ci-install-BYThh_Gl.js → ci-install-D1Mum8Ah.js} +4 -4
- package/dist/{ci-install-BYThh_Gl.js.map → ci-install-D1Mum8Ah.js.map} +1 -1
- package/dist/commandments-BagyrYRW.js +2 -0
- package/dist/{commandments-DSNrOeOC.js → commandments-DiMtIz1o.js} +1 -1
- package/dist/{commandments-DSNrOeOC.js.map → commandments-DiMtIz1o.js.map} +1 -1
- package/dist/{debug-dX5JKcxf.js → debug-C3ZR1TVF.js} +14 -29
- package/dist/debug-C3ZR1TVF.js.map +1 -0
- package/dist/{debug-CdScMjI7.js → debug-DsSCOPe8.js} +1 -1
- package/dist/{defaults-CtWMmC8s.js → defaults-DAE9_QMn.js} +1 -1
- package/dist/{defaults-CtWMmC8s.js.map → defaults-DAE9_QMn.js.map} +1 -1
- package/dist/{env-api-key-C3LzH8Lr.js → env-api-key-DDVkPQmo.js} +1 -1
- package/dist/{env-api-key-C3LzH8Lr.js.map → env-api-key-DDVkPQmo.js.map} +1 -1
- package/dist/{environment-D-xSv8Xv.js → environment-Bi-zynk6.js} +4 -4
- package/dist/environment-Bi-zynk6.js.map +1 -0
- package/dist/{file-watcher-Z28w46F3.js → file-watcher-PmRIDAfM.js} +2 -2
- package/dist/{file-watcher-Z28w46F3.js.map → file-watcher-PmRIDAfM.js.map} +1 -1
- package/dist/{headless-ui-T-cv04Ne.js → headless-ui-C4X9lAOY.js} +2 -2
- package/dist/{headless-ui-T-cv04Ne.js.map → headless-ui-C4X9lAOY.js.map} +1 -1
- package/dist/{interactive-uhGISvkt.js → interactive-HM71vLQe.js} +2 -2
- package/dist/{interactive-uhGISvkt.js.map → interactive-HM71vLQe.js.map} +1 -1
- package/dist/mcp-D0Hpb_nk.js +64 -0
- package/dist/mcp-D0Hpb_nk.js.map +1 -0
- package/dist/{mcp-prompt-streaming-ByofAot4.js → mcp-prompt-streaming-Crk8qFlQ.js} +3 -3
- package/dist/{mcp-prompt-streaming-ByofAot4.js.map → mcp-prompt-streaming-Crk8qFlQ.js.map} +1 -1
- package/dist/{non-interactive-dGAp1rES.js → non-interactive-DdUe8lqX.js} +2 -2
- package/dist/{non-interactive-dGAp1rES.js.map → non-interactive-DdUe8lqX.js.map} +1 -1
- package/dist/{orchestrator-tools-9D5vTenD.js → orchestrator-tools-CpRruqZl.js} +3 -3
- package/dist/{orchestrator-tools-9D5vTenD.js.map → orchestrator-tools-CpRruqZl.js.map} +1 -1
- package/dist/{package-json-DCuoye-H.js → package-json-CDs1ZVKu.js} +1 -1
- package/dist/{package-json-DCuoye-H.js.map → package-json-CDs1ZVKu.js.map} +1 -1
- package/dist/{package-manager-D3M_H5Pk.js → package-manager-wkSzPJqW.js} +2 -2
- package/dist/{package-manager-D3M_H5Pk.js.map → package-manager-wkSzPJqW.js.map} +1 -1
- package/dist/{pi--w-M8eD-.js → pi-CGPjm4oE.js} +91 -140
- package/dist/pi-CGPjm4oE.js.map +1 -0
- package/dist/{playground-GURThvy5.js → playground-lg7h9GHG.js} +7 -7
- package/dist/{playground-GURThvy5.js.map → playground-lg7h9GHG.js.map} +1 -1
- package/dist/{posthog-integration-Dk1hbtRQ.js → posthog-integration-pnxhTbxw.js} +45 -38
- package/dist/posthog-integration-pnxhTbxw.js.map +1 -0
- package/dist/{posthog-DZZbziJ1.js → posthog-mgz-FQlS.js} +1 -1
- package/dist/{posthog-DZZbziJ1.js.map → posthog-mgz-FQlS.js.map} +1 -1
- package/dist/{provisioning-CJQwMFVo.js → provisioning-T4jtJqBa.js} +3 -3
- package/dist/{provisioning-CJQwMFVo.js.map → provisioning-T4jtJqBa.js.map} +1 -1
- package/dist/{queue-tools-DW-pUVKK.js → queue-tools-D7ctuzyo.js} +97 -10
- package/dist/queue-tools-D7ctuzyo.js.map +1 -0
- package/dist/{registry-CYNjgbAh.js → registry-CsFuKtXn.js} +272 -429
- package/dist/registry-CsFuKtXn.js.map +1 -0
- package/dist/{security-D9TV_nIO.js → security-YAaZfmHs.js} +4 -4
- package/dist/{security-D9TV_nIO.js.map → security-YAaZfmHs.js.map} +1 -1
- package/dist/{setup-utils-D5RLhAEe.js → setup-utils-DDzEnDxJ.js} +14 -17
- package/dist/setup-utils-DDzEnDxJ.js.map +1 -0
- package/dist/smoke-test.sh +1 -1
- package/dist/{start-tui-Dvk-0lGv.js → start-tui-pCi7WVAK.js} +72 -87
- package/dist/start-tui-pCi7WVAK.js.map +1 -0
- package/dist/{steps-CcRX3kDT.js → steps-DmsrBqb9.js} +7 -7
- package/dist/{steps-CcRX3kDT.js.map → steps-DmsrBqb9.js.map} +1 -1
- package/dist/{store-DkQLlZF9.js → store-BCRdtfOH.js} +5 -5
- package/dist/{store-DkQLlZF9.js.map → store-BCRdtfOH.js.map} +1 -1
- package/dist/{subagent-Dxh0Pwgv.js → subagent-jNXS8IPU.js} +2 -2
- package/dist/{subagent-Dxh0Pwgv.js.map → subagent-jNXS8IPU.js.map} +1 -1
- package/dist/{task-C-r2xQvb.js → task-CSmrfyNf.js} +30 -46
- package/dist/task-CSmrfyNf.js.map +1 -0
- package/dist/{task-stream-_e6Mf24V.js → task-stream-BZOjOhKu.js} +5 -5
- package/dist/{task-stream-_e6Mf24V.js.map → task-stream-BZOjOhKu.js.map} +1 -1
- package/dist/{tasks-BqpaakPz.js → tasks-BMgQt251.js} +2 -2
- package/dist/{tasks-BqpaakPz.js.map → tasks-BMgQt251.js.map} +1 -1
- package/dist/{telemetry-CeQm0f0H.js → telemetry-qeKIGkte.js} +3 -3
- package/dist/{telemetry-CeQm0f0H.js.map → telemetry-qeKIGkte.js.map} +1 -1
- package/dist/{terminal-2gT6ezna.js → terminal-tbxhJGlI.js} +13 -13
- package/dist/{terminal-2gT6ezna.js.map → terminal-tbxhJGlI.js.map} +1 -1
- package/dist/{tools-C5Lsz2zR.js → tools-DVnBIYFn.js} +10 -8
- package/dist/tools-DVnBIYFn.js.map +1 -0
- package/dist/{wizard-abort-D_Xcbesm.js → wizard-abort-AEhoDJ4P.js} +4 -4
- package/dist/{wizard-abort-D_Xcbesm.js.map → wizard-abort-AEhoDJ4P.js.map} +1 -1
- package/dist/{wizard-abort-CaKAS9_Z.js → wizard-abort-DHC_XStW.js} +1 -1
- package/dist/{wizard-session-tp4Zdbwl.js → wizard-session-BAZql11N.js} +1 -1
- package/dist/{wizard-session-tp4Zdbwl.js.map → wizard-session-BAZql11N.js.map} +1 -1
- package/dist/{wizard-session-DWHe83uk.js → wizard-session-C5lZPPEc.js} +1 -1
- package/dist/{yara-hooks-CGzlyuQA.js → yara-hooks-CKsVxWiN.js} +139 -56
- package/dist/yara-hooks-CKsVxWiN.js.map +1 -0
- package/dist/yara-hooks-DWRdZQuG.js +2 -0
- package/package.json +7 -7
- package/dist/agent-interface-C_aRBziP.js.map +0 -1
- package/dist/agent-runner-NzzrOB02.js.map +0 -1
- package/dist/analytics-C7QE7PWl.js +0 -2
- package/dist/analytics-CArgq7XO.js.map +0 -1
- package/dist/commandments-qTW7pwaT.js +0 -2
- package/dist/debug-dX5JKcxf.js.map +0 -1
- package/dist/environment-D-xSv8Xv.js.map +0 -1
- package/dist/file-utils-BpTQ4NFR.js +0 -140
- package/dist/file-utils-BpTQ4NFR.js.map +0 -1
- package/dist/mcp-B9NosVx4.js +0 -104
- package/dist/mcp-B9NosVx4.js.map +0 -1
- package/dist/pi--w-M8eD-.js.map +0 -1
- package/dist/posthog-integration-Dk1hbtRQ.js.map +0 -1
- package/dist/queue-tools-DW-pUVKK.js.map +0 -1
- package/dist/registry-CYNjgbAh.js.map +0 -1
- package/dist/setup-utils-D5RLhAEe.js.map +0 -1
- package/dist/start-tui-Dvk-0lGv.js.map +0 -1
- package/dist/task-C-r2xQvb.js.map +0 -1
- package/dist/tools-C5Lsz2zR.js.map +0 -1
- package/dist/yara-hooks-CGzlyuQA.js.map +0 -1
- package/dist/yara-hooks-CQaKM0f4.js +0 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analytics-BXz4SIuS.js","names":["uuidv4"],"sources":["../src/utils/ci-flag-overrides.ts","../src/utils/analytics.ts"],"sourcesContent":["/**\n * CI-only feature-flag overrides.\n *\n * CI must route deterministically: a run that tests the orchestrator arm says\n * so explicitly instead of depending on a live feature flag someone can edit\n * mid-week. The override env var (see the allowlist in `env.ts`) is a JSON\n * object of flag key → value, merged over whatever PostHog returned.\n *\n * The override path exists only in CI builds (`pnpm build:ci`). Published\n * builds inline NODE_ENV as the literal \"production\", the guards collapse,\n * and tsdown strips the rest from the bundle — and the smoke test asserts the\n * env var names are physically absent from production output (which is also\n * why no comment in this file may spell them out), so this can never quietly\n * become a production surface.\n */\nimport { runtimeEnv } from '@env';\nimport { logToFile } from './debug';\n\nexport function applyCiFlagOverrides(\n flags: Record<string, string>,\n payloads: Record<string, unknown> = {},\n): { flags: Record<string, string>; payloads: Record<string, unknown> } {\n // Compared inline (not via env.ts's IS_PRODUCTION_BUILD) so tsdown replaces\n // it with a literal right here and the bundler can prove the rest of this\n // function unreachable in production builds. The smoke test enforces that.\n if (process.env.NODE_ENV === 'production') return { flags, payloads };\n\n const raw = runtimeEnv('WIZARD_CI_FLAG_OVERRIDES');\n if (!raw) return { flags, payloads };\n\n let overrides: Record<string, unknown>;\n try {\n overrides = JSON.parse(raw) as Record<string, unknown>;\n } catch {\n // A malformed override is a CI misconfiguration. Fail the run loudly\n // rather than silently testing whatever the live flags happen to say.\n throw new Error(\n 'The CI flag-override env var is not valid JSON (expected {\"flag-key\": value, ...}).',\n );\n }\n\n const mergedFlags = { ...flags };\n const mergedPayloads = { ...payloads };\n for (const [key, value] of Object.entries(overrides)) {\n // An object/array override is a flag payload: the flag reads 'true' and\n // the value rides the payload channel, matching a payload-carrying flag.\n if (typeof value === 'object' && value !== null) {\n mergedFlags[key] = 'true';\n mergedPayloads[key] = value;\n } else {\n mergedFlags[key] = String(value);\n }\n }\n logToFile('[flags] CI overrides applied', overrides);\n return { flags: mergedFlags, payloads: mergedPayloads };\n}\n\n/**\n * Task types excluded from this run. The exclusion env var (see the allowlist\n * in `env.ts`) is a comma-separated list (e.g. `dashboard`), set by the CI\n * harness that owns the policy — the wizard and the served content stay\n * run-mode agnostic. CI-build only, same as the flag overrides: published\n * builds strip this path.\n */\nexport function ciExcludedTaskTypes(): readonly string[] {\n if (process.env.NODE_ENV === 'production') return [];\n\n const raw = runtimeEnv('WIZARD_CI_EXCLUDE_TASKS');\n if (!raw) return [];\n const types = raw\n .split(',')\n .map((t) => t.trim())\n .filter(Boolean);\n if (types.length > 0) logToFile('[flags] CI task exclusions', types);\n return types;\n}\n","import { PostHog } from 'posthog-node';\nimport {\n ANALYTICS_HOST_URL,\n ANALYTICS_POSTHOG_PUBLIC_PROJECT_WRITE_KEY,\n ANALYTICS_TEAM_TAG,\n WIZARD_FLAG_KEYS,\n} from '@lib/constants';\nimport type { WizardSession } from '@lib/wizard-session';\nimport type { ApiUser } from '@lib/api';\nimport { v4 as uuidv4 } from 'uuid';\nimport { IS_PRODUCTION_BUILD, RUN_SURFACE } from '@env';\nimport { VERSION } from '@lib/version';\nimport { debug, logToFile } from './debug';\nimport { applyCiFlagOverrides } from './ci-flag-overrides';\n\n/**\n * The invocation, reduced to flag-safe strings: the command word (first\n * positional, 'default' for the bare flow) and the sorted option NAMES.\n * Option values never leave the machine — they carry paths, emails, keys.\n */\nfunction invocationProperties(): { command: string; cli_flags: string } {\n const args = process.argv.slice(2);\n const command = args.find((a) => !a.startsWith('-')) ?? 'default';\n const flags = [\n ...new Set(\n args\n .filter((a) => a.startsWith('--'))\n .map((a) => a.slice(2).split('=')[0]),\n ),\n ].sort();\n return { command, cli_flags: flags.join(',') };\n}\n\n/**\n * Extract a standard property bag from the current session.\n * Used by store-level analytics and available for ad-hoc captures.\n */\nexport function sessionProperties(\n session: WizardSession,\n): Record<string, unknown> {\n return {\n integration: session.integration,\n detected_framework: session.detectedFrameworkLabel,\n typescript: session.typescript,\n project_id: session.credentials?.projectId,\n discovered_features: session.discoveredFeatures,\n additional_features: session.additionalFeatureQueue,\n run_phase: session.runPhase,\n };\n}\n\nexport function groupsFromUser(\n user: ApiUser | null,\n host: string,\n): Record<string, string> {\n const groups: Record<string, string> = { instance: host };\n if (!user) return groups;\n\n const organizationId = user.organization?.id;\n if (organizationId) groups.organization = organizationId;\n\n const customerId = user.organization?.customer_id;\n if (customerId) groups.customer = customerId;\n\n const projectUuid = user.team?.uuid;\n if (projectUuid) groups.project = projectUuid;\n\n return groups;\n}\n\nconst WIZARD_FLAGS: ReadonlySet<string> = new Set(WIZARD_FLAG_KEYS);\n\n// Widen back to the SDK's shape — a filter on `true` never matches `'true'`.\nfunction flagResponseValue(value: string): string | boolean {\n if (value === 'true') return true;\n if (value === 'false') return false;\n return value;\n}\n\nexport class Analytics {\n private client: PostHog;\n private tags: Record<string, string | boolean | number | null | undefined> =\n {};\n private distinctId?: string;\n private anonymousId: string;\n private _runId: string;\n private sessionId: string | null = null;\n private appName = 'wizard';\n private activeFlags: Record<string, string> | null = null;\n private activeFlagPayloads: Record<string, unknown> = {};\n private groups: Record<string, string> = {};\n private personProperties: Record<string, string> = {};\n private terminalEventSent = false;\n\n constructor() {\n this.client = new PostHog(ANALYTICS_POSTHOG_PUBLIC_PROJECT_WRITE_KEY, {\n host: ANALYTICS_HOST_URL,\n flushAt: 1,\n flushInterval: 0,\n enableExceptionAutocapture: true,\n before_send: (event) => {\n if (!event) return event;\n if (Object.keys(this.groups).length > 0) {\n event.groups = { ...this.groups, ...event.groups };\n }\n // Autocaptured exceptions arrive with a random uuid and\n // `$process_person_profile: false` — reattach the run's identity\n // and tags so they land on the same person as everything else.\n if (event.event === '$exception') {\n event.distinctId = this.distinctId ?? this.anonymousId;\n const { $process_person_profile, ...properties } =\n event.properties ?? {};\n void $process_person_profile;\n event.properties = { ...this.tags, ...properties };\n }\n // The SDK captures this one itself, bypassing capture(), so tags merge here.\n if (event.event === '$feature_flag_called') {\n event.properties = { ...this.tags, ...(event.properties ?? {}) };\n }\n return event;\n },\n });\n\n this.tags = { $app_name: this.appName };\n // Tag every run with its build type so prod / dev / ci / headless segment\n // cleanly in analytics. tsdown inlines IS_PRODUCTION_BUILD to `true` in\n // published builds and `false` for dev/tsx/test runs. Non-interactive runs\n // upgrade this in runWizardCI: dev `--ci` runs to 'ci', published headless\n // runs to 'headless'.\n this.tags.build = IS_PRODUCTION_BUILD ? 'prod' : 'dev';\n\n this.tags.run_surface = RUN_SURFACE;\n\n this.anonymousId = uuidv4();\n\n // One id per process = one id per wizard run, registered in the tag bag\n // so it rides on every capture, exception, and autocaptured exception\n // (all of which merge `this.tags`). Lets you separate two runs by the\n // same logged-in user, who otherwise share one distinct id. Distinct\n // from `anonymousId`, the pre-login *person* id that gets aliased onto\n // the real user at login. `$session_id` is intentionally not set here —\n // it stays null until OAuth completes (see identifyUser).\n this._runId = uuidv4();\n this.tags.run_id = this._runId;\n\n this.distinctId = undefined;\n }\n\n /** Per-process run id, tagged on every event and gateway trace. */\n get runId(): string {\n return this._runId;\n }\n\n /** Build type for this run ('prod' | 'dev' | 'ci' | 'headless') — the same value tagged on every analytics event. */\n get build(): string {\n return String(this.tags.build ?? 'dev');\n }\n\n /**\n * Associate the run with the logged-in user, once per id. Identifies them\n * (email, name) and records those person properties so events carry them and\n * feature flags can target the individual user — without the email here the\n * wizard only sends `$app_name`, so email-targeted flags never match. Opens\n * the analytics session on first login, then aliases the run's anonymous id\n * onto the identified person so pre-login events merge in.\n */\n identifyUser(user: ApiUser) {\n const distinctId = user.distinct_id;\n if (this.distinctId === distinctId || distinctId === this.anonymousId) {\n return;\n }\n this.distinctId = distinctId;\n // Open the analytics session on first login. Null until here, so\n // pre-OAuth events carry only `run_id`; from now on every event also\n // carries `$session_id` and PostHog groups the authenticated run into a\n // native Session. Stored in the tag bag so it rides on every subsequent\n // capture and exception.\n if (!this.sessionId) {\n this.sessionId = uuidv4();\n this.tags.$session_id = this.sessionId;\n }\n const props: Record<string, string> = {};\n if (user.email) props.email = user.email;\n const name = [user.first_name, user.last_name]\n .filter(Boolean)\n .join(' ')\n .trim();\n if (name) props.name = name;\n this.personProperties = props;\n this.client.identify({ distinctId, properties: { $set: props } });\n this.client.alias({\n distinctId,\n alias: this.anonymousId,\n });\n // The flag snapshot is per identity. Anything evaluated before login (the\n // intro screen reads the tools-menu flag) was anonymous — drop it so the\n // next read re-evaluates as this user.\n this.activeFlags = null;\n this.activeFlagPayloads = {};\n }\n\n /** Person properties sent with flag evaluation: app name plus the user's. */\n private flagPersonProperties(): Record<string, string> {\n // Environment facts flag conditions can scope on — evaluation-time only,\n // never persisted onto the person. `version` gates an experiment to\n // releases that implement it (a condition on a property older builds\n // don't send silently never matches them); `run_surface`/`build` scope\n // by invocation surface; `command`/`cli_flags` by subcommand; `os`/\n // `node_major` by platform.\n return {\n $app_name: this.appName,\n version: VERSION,\n run_surface: RUN_SURFACE,\n build: String(this.tags.build ?? 'dev'),\n os: process.platform,\n node_major: process.versions.node.split('.')[0],\n ...invocationProperties(),\n ...this.personProperties,\n };\n }\n\n setTag(key: string, value: string | boolean | number | null | undefined) {\n this.tags[key] = value;\n }\n\n setGroups(groups: Record<string, string>) {\n this.groups = groups;\n }\n\n captureException(error: Error, properties: Record<string, unknown> = {}) {\n this.client.captureException(error, this.distinctId ?? this.anonymousId, {\n team: ANALYTICS_TEAM_TAG,\n ...this.tags,\n ...properties,\n });\n }\n\n capture(eventName: string, properties?: Record<string, unknown>) {\n this.client.capture({\n distinctId: this.distinctId ?? this.anonymousId,\n event: eventName,\n properties: {\n ...this.tags,\n ...this.wizardFlagFeatureProperties(),\n ...properties,\n },\n });\n }\n\n // Built from the resolved map, not the SDK snapshot: a CI-forced variant must own its events.\n private wizardFlagFeatureProperties(): Record<string, unknown> {\n if (this.activeFlags === null) return {};\n const props: Record<string, unknown> = {};\n const active: string[] = [];\n for (const [key, value] of Object.entries(this.activeFlags)) {\n if (!WIZARD_FLAGS.has(key)) continue;\n const resolved = flagResponseValue(value);\n props[`$feature/${key}`] = resolved;\n if (resolved !== false) active.push(key);\n }\n if (active.length > 0) props.$active_feature_flags = active.sort();\n return props;\n }\n\n /**\n * Capture a wizard-specific event. Automatically prepends \"wizard: \" to the event name.\n * All new wizard analytics should use this method instead of capture() directly.\n */\n wizardCapture(eventName: string, properties?: Record<string, unknown>): void {\n this.capture(`wizard: ${eventName}`, properties);\n }\n\n /**\n * Flush pending events without firing the \"setup wizard finished\" terminal\n * event. Use this from CLI error paths that exit before any wizard run\n * starts — `shutdown()` would inflate the run count with a \"finished\" event\n * for a parse error that never actually ran the wizard.\n */\n async flush(): Promise<void> {\n await this.client.shutdown();\n }\n\n /**\n * Evaluate all feature flags for the current user at the start of a run.\n * Result is cached; subsequent calls in the same run return the same map.\n * Returns flag key -> string value (booleans become 'true'/'false').\n */\n // Only a getFlag read records an exposure; the bulk response records none.\n async getAllFlagsForWizard(): Promise<Record<string, string>> {\n if (this.activeFlags !== null) {\n return this.activeFlags;\n }\n const out: Record<string, string> = {};\n const payloads: Record<string, unknown> = {};\n try {\n const distinctId = this.distinctId ?? this.anonymousId;\n logToFile('[flags] evaluating as', {\n distinctId,\n identified: this.distinctId !== undefined,\n personProperties: this.flagPersonProperties(),\n });\n const evaluation = await this.client.evaluateFlags(distinctId, {\n personProperties: this.flagPersonProperties(),\n });\n for (const key of WIZARD_FLAG_KEYS) {\n const value = evaluation.getFlag(key);\n if (value === undefined) continue;\n out[key] = String(value);\n const payload = evaluation.getFlagPayload(key);\n if (payload !== undefined) payloads[key] = payload;\n }\n } catch (error) {\n debug('Failed to get all feature flags:', error);\n this.captureException(\n error instanceof Error ? error : new Error(String(error)),\n { step: 'get_all_flags' },\n );\n }\n // Outside the fetch guard on purpose: a malformed CI override must fail\n // the run loudly, and a valid one applies even when the fetch failed —\n // CI routing stays deterministic either way.\n const merged = applyCiFlagOverrides(out, payloads);\n this.activeFlags = merged.flags;\n this.activeFlagPayloads = merged.payloads;\n logToFile('[flags] evaluated', this.activeFlags);\n return this.activeFlags;\n }\n\n /** Flag payloads from the same snapshot; empty until the flags are fetched. */\n getWizardFlagPayloads(): Record<string, unknown> {\n return this.activeFlagPayloads;\n }\n\n async shutdown(status: 'success' | 'error' | 'cancelled') {\n if (Object.keys(this.tags).length === 0) {\n return;\n }\n\n // First status wins. The interrupt fallback in start-tui fires\n // shutdown('cancelled') on every TUI teardown; without this guard a run\n // that already reported 'success' would emit a second, contradicting\n // terminal event when the user dismisses the outro.\n if (this.terminalEventSent) {\n return;\n }\n this.terminalEventSent = true;\n\n this.client.capture({\n distinctId: this.distinctId ?? this.anonymousId,\n event: 'setup wizard finished',\n properties: {\n // Flat for filtering; the nested `tags` snapshot stays for back-compat.\n ...this.tags,\n run_id: this._runId,\n ...(this.sessionId ? { $session_id: this.sessionId } : {}),\n status,\n tags: this.tags,\n },\n });\n\n await this.client.shutdown();\n }\n}\n\nexport const analytics = new Analytics();\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-B_-DWIq7.js";
|
|
2
|
-
import {
|
|
3
|
-
import { n as analytics } from "./analytics-
|
|
2
|
+
import { dt as WIZARD_USER_AGENT } from "./debug-C3ZR1TVF.js";
|
|
3
|
+
import { n as analytics } from "./analytics-BXz4SIuS.js";
|
|
4
4
|
import axios from "axios";
|
|
5
5
|
import { z } from "zod";
|
|
6
6
|
//#region src/lib/api.ts
|
|
@@ -170,4 +170,4 @@ function handleApiError(error, operation) {
|
|
|
170
170
|
//#endregion
|
|
171
171
|
export { fetchUserData as a, fetchSlackConnected as i, api_exports as n, handleApiError as o, fetchProjectData as r, ApiError as t };
|
|
172
172
|
|
|
173
|
-
//# sourceMappingURL=api-
|
|
173
|
+
//# sourceMappingURL=api-BaacjH-Y.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-CX1g-14-.js","names":[],"sources":["../src/lib/api.ts"],"sourcesContent":["import axios, { AxiosError } from 'axios';\nimport { z } from 'zod';\nimport { analytics } from '@utils/analytics';\nimport { WIZARD_USER_AGENT } from './constants';\n\n/**\n * User payload from `/api/users/@me/`. Schema typed for the fields the\n * wizard actually reads + passthrough on everything else so the full\n * upstream response rides through to the session for downstream features\n * (account-aware copy, plan-gated flows, org/team metadata, etc.).\n *\n * Top-level uses `.passthrough()` so unknown fields aren't stripped;\n * the few nested objects we care about (team, organization,\n * organizations[]) do the same so their additional fields survive too.\n *\n * Keep `distinct_id` required — analytics depends on it. Everything\n * else added here is nullish so partial responses don't fail parsing.\n */\nexport const ApiUserSchema = z\n .object({\n // Identifiers\n distinct_id: z.string(),\n uuid: z.string().nullish(),\n id: z.number().nullish(),\n\n // Profile\n email: z.string().nullish(),\n first_name: z.string().nullish(),\n last_name: z.string().nullish(),\n date_joined: z.string().nullish(),\n is_email_verified: z.boolean().nullish(),\n is_2fa_enabled: z.boolean().nullish(),\n is_staff: z.boolean().nullish(),\n\n // Preferences\n theme_mode: z.string().nullish(),\n toolbar_mode: z.string().nullish(),\n hide_mcp_hints: z.boolean().nullish(),\n\n // Optional / nullable on the backend — pre-onboarding signup paths\n // return null and older accounts may not have it set. Treat as a\n // hint, never a guarantee.\n role_at_organization: z.string().nullish(),\n\n // Current team + organization (objects from the API, kept typed on\n // the fields the wizard uses; passthrough preserves the rest).\n team: z\n .object({\n id: z.number(),\n uuid: z.string().nullish(),\n organization: z.string().uuid(),\n api_token: z.string().nullish(),\n project_id: z.number().nullish(),\n name: z.string().nullish(),\n timezone: z.string().nullish(),\n })\n .passthrough(),\n organization: z\n .object({\n id: z.string().uuid(),\n name: z.string().nullish(),\n slug: z.string().nullish(),\n membership_level: z.number().nullish(),\n customer_id: z.string().nullish(),\n // Org-level AI consent gate. Signals drops all findings while\n // this is not true. Null on older orgs (pre-2026-05 default\n // flip) — treat null as \"unknown\", not \"off\".\n is_ai_data_processing_approved: z.boolean().nullish(),\n })\n .passthrough(),\n organizations: z.array(\n z\n .object({\n id: z.string().uuid(),\n name: z.string().nullish(),\n membership_level: z.number().nullish(),\n })\n .passthrough(),\n ),\n })\n .passthrough();\n\n/**\n * Single activity log entry the wizard cares about. The PostHog endpoint\n * returns much more — schema kept minimal so changes upstream don't break us.\n *\n * @unused — no current caller after the Phase 6 streaming-agent pivot\n * dropped activity_log polling. Deliberately retained: this is a thin,\n * well-typed wrapper around a stable PostHog endpoint, and we're likely\n * to want it again for a future feature (e.g. \"what changed in your\n * project recently\"). Re-deriving the schema is more work than letting\n * it sit dormant.\n */\nexport const ActivityLogEntrySchema = z\n .object({\n scope: z.string().nullish(),\n activity: z.string().nullish(),\n created_at: z.string().nullish(),\n })\n .passthrough();\n\n/** @unused — see ActivityLogEntrySchema. */\nexport const ActivityLogResponseSchema = z.object({\n results: z.array(ActivityLogEntrySchema),\n});\n\n/** @unused — see ActivityLogEntrySchema. */\nexport type ActivityLogEntry = z.infer<typeof ActivityLogEntrySchema>;\n\nexport const ApiProjectSchema = z.object({\n id: z.number(),\n uuid: z.string().uuid(),\n organization: z.string().uuid(),\n api_token: z.string(),\n name: z.string(),\n // Product opt-ins (TeamSerializer-compat fields on /api/projects/:id).\n // Project-level truth for \"is this product enabled\" — a product can be\n // instrumented from another repo or the snippet, so these settings\n // override repo-local evidence. Null/absent = unknown. Only the\n // opt-ins a signals decision consumes: replay + exception autocapture\n // feed signal-source choices; surveys feeds the surveys-scout tuning.\n session_recording_opt_in: z.boolean().nullish(),\n autocapture_exceptions_opt_in: z.boolean().nullish(),\n surveys_opt_in: z.boolean().nullish(),\n});\n\nexport type ApiUser = z.infer<typeof ApiUserSchema>;\nexport type ApiProject = z.infer<typeof ApiProjectSchema>;\n\nexport class ApiError extends Error {\n constructor(\n message: string,\n public readonly statusCode?: number,\n public readonly endpoint?: string,\n ) {\n super(message);\n this.name = 'ApiError';\n }\n}\n\nexport async function fetchUserData(\n accessToken: string,\n baseUrl: string,\n): Promise<ApiUser> {\n try {\n const response = await axios.get(`${baseUrl}/api/users/@me/`, {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'User-Agent': WIZARD_USER_AGENT,\n },\n });\n\n return ApiUserSchema.parse(response.data);\n } catch (error) {\n const apiError = handleApiError(error, 'fetch user data');\n analytics.captureException(apiError, {\n endpoint: '/api/users/@me/',\n baseUrl,\n });\n throw apiError;\n }\n}\n\n/**\n * Best-effort fetch of recent activity log entries. Returns [] on any error\n * so callers can treat absence of results as \"haven't detected anything yet\"\n * rather than a hard failure.\n *\n * @unused — no current caller after the Phase 6 streaming-agent pivot\n * dropped activity_log polling from McpSuggestedPromptsScreen.\n * Deliberately retained for future features that want a soft signal of\n * recent project changes (e.g. dashboards, audit summaries). See the\n * ActivityLogEntrySchema doc comment for the keep-vs-delete rationale.\n */\nexport async function fetchRecentActivity(\n accessToken: string,\n projectId: number,\n baseUrl: string,\n since: Date,\n): Promise<ActivityLogEntry[]> {\n try {\n const response = await axios.get(\n `${baseUrl}/api/projects/${projectId}/activity_log/`,\n {\n params: { limit: 10 },\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'User-Agent': WIZARD_USER_AGENT,\n },\n // Short timeout — best-effort probe, not a critical path.\n timeout: 4000,\n },\n );\n const parsed = ActivityLogResponseSchema.safeParse(response.data);\n if (!parsed.success) return [];\n const sinceMs = since.getTime();\n return parsed.data.results.filter((entry) => {\n if (!entry.created_at) return false;\n const t = Date.parse(entry.created_at);\n return Number.isFinite(t) && t >= sinceMs;\n });\n } catch {\n return [];\n }\n}\n\nexport async function fetchProjectData(\n accessToken: string,\n projectId: number,\n baseUrl: string,\n): Promise<ApiProject> {\n try {\n const response = await axios.get(`${baseUrl}/api/projects/${projectId}/`, {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'User-Agent': WIZARD_USER_AGENT,\n },\n });\n\n return ApiProjectSchema.parse(response.data);\n } catch (error) {\n const apiError = handleApiError(error, 'fetch project data');\n analytics.captureException(apiError, {\n endpoint: `/api/projects/${projectId}/`,\n baseUrl,\n projectId,\n });\n throw apiError;\n }\n}\n\n/** Minimal shape of `/api/projects/:id/integrations/` — we only read `kind`. */\nconst IntegrationsResponseSchema = z.object({\n results: z.array(z.object({ kind: z.string().nullish() }).passthrough()),\n});\n\n/**\n * Check whether the project already has a Slack integration connected.\n * Requires the `integration:read` scope. Throws on failure — callers\n * (including the SlackConnectScreen poll) decide how to degrade and\n * are responsible for capturing the error exactly once.\n */\nexport async function fetchSlackConnected(\n accessToken: string,\n projectId: number,\n baseUrl: string,\n signal?: AbortSignal,\n): Promise<boolean> {\n const response = await axios.get(\n `${baseUrl}/api/projects/${projectId}/integrations/`,\n {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'User-Agent': WIZARD_USER_AGENT,\n },\n signal,\n },\n );\n const parsed = IntegrationsResponseSchema.safeParse(response.data);\n if (!parsed.success) return false;\n return parsed.data.results.some((i) => i.kind === 'slack');\n}\n\nexport function handleApiError(error: unknown, operation: string): ApiError {\n if (axios.isAxiosError(error)) {\n const axiosError = error as AxiosError<{ detail?: string }>;\n const status = axiosError.response?.status;\n const detail = axiosError.response?.data?.detail;\n const endpoint = axiosError.config?.url;\n\n if (status === 401) {\n return new ApiError(\n `Authentication failed while trying to ${operation}`,\n status,\n endpoint,\n );\n }\n\n if (status === 403) {\n return new ApiError(\n `Access denied while trying to ${operation}`,\n status,\n endpoint,\n );\n }\n\n if (status === 404) {\n return new ApiError(\n `Resource not found while trying to ${operation}`,\n status,\n endpoint,\n );\n }\n\n const message = detail || `Failed to ${operation}`;\n return new ApiError(message, status, endpoint);\n }\n\n if (error instanceof z.ZodError) {\n return new ApiError(`Invalid response format while trying to ${operation}`);\n }\n\n return new ApiError(\n `Unexpected error while trying to ${operation}: ${\n error instanceof Error ? error.message : 'Unknown error'\n }`,\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"api-BaacjH-Y.js","names":[],"sources":["../src/lib/api.ts"],"sourcesContent":["import axios, { AxiosError } from 'axios';\nimport { z } from 'zod';\nimport { analytics } from '@utils/analytics';\nimport { WIZARD_USER_AGENT } from './constants';\n\n/**\n * User payload from `/api/users/@me/`. Schema typed for the fields the\n * wizard actually reads + passthrough on everything else so the full\n * upstream response rides through to the session for downstream features\n * (account-aware copy, plan-gated flows, org/team metadata, etc.).\n *\n * Top-level uses `.passthrough()` so unknown fields aren't stripped;\n * the few nested objects we care about (team, organization,\n * organizations[]) do the same so their additional fields survive too.\n *\n * Keep `distinct_id` required — analytics depends on it. Everything\n * else added here is nullish so partial responses don't fail parsing.\n */\nexport const ApiUserSchema = z\n .object({\n // Identifiers\n distinct_id: z.string(),\n uuid: z.string().nullish(),\n id: z.number().nullish(),\n\n // Profile\n email: z.string().nullish(),\n first_name: z.string().nullish(),\n last_name: z.string().nullish(),\n date_joined: z.string().nullish(),\n is_email_verified: z.boolean().nullish(),\n is_2fa_enabled: z.boolean().nullish(),\n is_staff: z.boolean().nullish(),\n\n // Preferences\n theme_mode: z.string().nullish(),\n toolbar_mode: z.string().nullish(),\n hide_mcp_hints: z.boolean().nullish(),\n\n // Optional / nullable on the backend — pre-onboarding signup paths\n // return null and older accounts may not have it set. Treat as a\n // hint, never a guarantee.\n role_at_organization: z.string().nullish(),\n\n // Current team + organization (objects from the API, kept typed on\n // the fields the wizard uses; passthrough preserves the rest).\n team: z\n .object({\n id: z.number(),\n uuid: z.string().nullish(),\n organization: z.string().uuid(),\n api_token: z.string().nullish(),\n project_id: z.number().nullish(),\n name: z.string().nullish(),\n timezone: z.string().nullish(),\n })\n .passthrough(),\n organization: z\n .object({\n id: z.string().uuid(),\n name: z.string().nullish(),\n slug: z.string().nullish(),\n membership_level: z.number().nullish(),\n customer_id: z.string().nullish(),\n // Org-level AI consent gate. Signals drops all findings while\n // this is not true. Null on older orgs (pre-2026-05 default\n // flip) — treat null as \"unknown\", not \"off\".\n is_ai_data_processing_approved: z.boolean().nullish(),\n })\n .passthrough(),\n organizations: z.array(\n z\n .object({\n id: z.string().uuid(),\n name: z.string().nullish(),\n membership_level: z.number().nullish(),\n })\n .passthrough(),\n ),\n })\n .passthrough();\n\n/**\n * Single activity log entry the wizard cares about. The PostHog endpoint\n * returns much more — schema kept minimal so changes upstream don't break us.\n *\n * @unused — no current caller after the Phase 6 streaming-agent pivot\n * dropped activity_log polling. Deliberately retained: this is a thin,\n * well-typed wrapper around a stable PostHog endpoint, and we're likely\n * to want it again for a future feature (e.g. \"what changed in your\n * project recently\"). Re-deriving the schema is more work than letting\n * it sit dormant.\n */\nexport const ActivityLogEntrySchema = z\n .object({\n scope: z.string().nullish(),\n activity: z.string().nullish(),\n created_at: z.string().nullish(),\n })\n .passthrough();\n\n/** @unused — see ActivityLogEntrySchema. */\nexport const ActivityLogResponseSchema = z.object({\n results: z.array(ActivityLogEntrySchema),\n});\n\n/** @unused — see ActivityLogEntrySchema. */\nexport type ActivityLogEntry = z.infer<typeof ActivityLogEntrySchema>;\n\nexport const ApiProjectSchema = z.object({\n id: z.number(),\n uuid: z.string().uuid(),\n organization: z.string().uuid(),\n api_token: z.string(),\n name: z.string(),\n // Product opt-ins (TeamSerializer-compat fields on /api/projects/:id).\n // Project-level truth for \"is this product enabled\" — a product can be\n // instrumented from another repo or the snippet, so these settings\n // override repo-local evidence. Null/absent = unknown. Only the\n // opt-ins a signals decision consumes: replay + exception autocapture\n // feed signal-source choices; surveys feeds the surveys-scout tuning.\n session_recording_opt_in: z.boolean().nullish(),\n autocapture_exceptions_opt_in: z.boolean().nullish(),\n surveys_opt_in: z.boolean().nullish(),\n});\n\nexport type ApiUser = z.infer<typeof ApiUserSchema>;\nexport type ApiProject = z.infer<typeof ApiProjectSchema>;\n\nexport class ApiError extends Error {\n constructor(\n message: string,\n public readonly statusCode?: number,\n public readonly endpoint?: string,\n ) {\n super(message);\n this.name = 'ApiError';\n }\n}\n\nexport async function fetchUserData(\n accessToken: string,\n baseUrl: string,\n): Promise<ApiUser> {\n try {\n const response = await axios.get(`${baseUrl}/api/users/@me/`, {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'User-Agent': WIZARD_USER_AGENT,\n },\n });\n\n return ApiUserSchema.parse(response.data);\n } catch (error) {\n const apiError = handleApiError(error, 'fetch user data');\n analytics.captureException(apiError, {\n endpoint: '/api/users/@me/',\n baseUrl,\n });\n throw apiError;\n }\n}\n\n/**\n * Best-effort fetch of recent activity log entries. Returns [] on any error\n * so callers can treat absence of results as \"haven't detected anything yet\"\n * rather than a hard failure.\n *\n * @unused — no current caller after the Phase 6 streaming-agent pivot\n * dropped activity_log polling from McpSuggestedPromptsScreen.\n * Deliberately retained for future features that want a soft signal of\n * recent project changes (e.g. dashboards, audit summaries). See the\n * ActivityLogEntrySchema doc comment for the keep-vs-delete rationale.\n */\nexport async function fetchRecentActivity(\n accessToken: string,\n projectId: number,\n baseUrl: string,\n since: Date,\n): Promise<ActivityLogEntry[]> {\n try {\n const response = await axios.get(\n `${baseUrl}/api/projects/${projectId}/activity_log/`,\n {\n params: { limit: 10 },\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'User-Agent': WIZARD_USER_AGENT,\n },\n // Short timeout — best-effort probe, not a critical path.\n timeout: 4000,\n },\n );\n const parsed = ActivityLogResponseSchema.safeParse(response.data);\n if (!parsed.success) return [];\n const sinceMs = since.getTime();\n return parsed.data.results.filter((entry) => {\n if (!entry.created_at) return false;\n const t = Date.parse(entry.created_at);\n return Number.isFinite(t) && t >= sinceMs;\n });\n } catch {\n return [];\n }\n}\n\nexport async function fetchProjectData(\n accessToken: string,\n projectId: number,\n baseUrl: string,\n): Promise<ApiProject> {\n try {\n const response = await axios.get(`${baseUrl}/api/projects/${projectId}/`, {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'User-Agent': WIZARD_USER_AGENT,\n },\n });\n\n return ApiProjectSchema.parse(response.data);\n } catch (error) {\n const apiError = handleApiError(error, 'fetch project data');\n analytics.captureException(apiError, {\n endpoint: `/api/projects/${projectId}/`,\n baseUrl,\n projectId,\n });\n throw apiError;\n }\n}\n\n/** Minimal shape of `/api/projects/:id/integrations/` — we only read `kind`. */\nconst IntegrationsResponseSchema = z.object({\n results: z.array(z.object({ kind: z.string().nullish() }).passthrough()),\n});\n\n/**\n * Check whether the project already has a Slack integration connected.\n * Requires the `integration:read` scope. Throws on failure — callers\n * (including the SlackConnectScreen poll) decide how to degrade and\n * are responsible for capturing the error exactly once.\n */\nexport async function fetchSlackConnected(\n accessToken: string,\n projectId: number,\n baseUrl: string,\n signal?: AbortSignal,\n): Promise<boolean> {\n const response = await axios.get(\n `${baseUrl}/api/projects/${projectId}/integrations/`,\n {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'User-Agent': WIZARD_USER_AGENT,\n },\n signal,\n },\n );\n const parsed = IntegrationsResponseSchema.safeParse(response.data);\n if (!parsed.success) return false;\n return parsed.data.results.some((i) => i.kind === 'slack');\n}\n\nexport function handleApiError(error: unknown, operation: string): ApiError {\n if (axios.isAxiosError(error)) {\n const axiosError = error as AxiosError<{ detail?: string }>;\n const status = axiosError.response?.status;\n const detail = axiosError.response?.data?.detail;\n const endpoint = axiosError.config?.url;\n\n if (status === 401) {\n return new ApiError(\n `Authentication failed while trying to ${operation}`,\n status,\n endpoint,\n );\n }\n\n if (status === 403) {\n return new ApiError(\n `Access denied while trying to ${operation}`,\n status,\n endpoint,\n );\n }\n\n if (status === 404) {\n return new ApiError(\n `Resource not found while trying to ${operation}`,\n status,\n endpoint,\n );\n }\n\n const message = detail || `Failed to ${operation}`;\n return new ApiError(message, status, endpoint);\n }\n\n if (error instanceof z.ZodError) {\n return new ApiError(`Invalid response format while trying to ${operation}`);\n }\n\n return new ApiError(\n `Unexpected error while trying to ${operation}: ${\n error instanceof Error ? error.message : 'Unknown error'\n }`,\n );\n}\n"],"mappings":"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"}
|
package/dist/bin.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import { n as analytics } from "./analytics-
|
|
4
|
-
import { r as setEntryCommand } from "./telemetry-
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import "./
|
|
8
|
-
import
|
|
9
|
-
import {
|
|
10
|
-
import { n as
|
|
11
|
-
import {
|
|
12
|
-
import { _ as
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import { n as readApiKeyFromEnv } from "./env-api-key-
|
|
2
|
+
import { H as POSTHOG_DOCS_URL, I as Integration, a as getLogFilePath, bt as regionOption, dt as WIZARD_USER_AGENT, f as getUI, ft as getSkillsBaseUrl, m as LoggingUI, mt as VERSION, p as setUI, r as debug, s as logToFile, vt as headlessOption, yt as isHeadless } from "./debug-C3ZR1TVF.js";
|
|
3
|
+
import { n as analytics } from "./analytics-BXz4SIuS.js";
|
|
4
|
+
import { r as setEntryCommand } from "./telemetry-qeKIGkte.js";
|
|
5
|
+
import { a as walkProjectFiles, i as safeReadFile } from "./bounded-fs-Cx-8nk-1.js";
|
|
6
|
+
import { n as isUsingTypeScript } from "./setup-utils-DDzEnDxJ.js";
|
|
7
|
+
import { o as handleApiError } from "./api-BaacjH-Y.js";
|
|
8
|
+
import "./wizard-session-BAZql11N.js";
|
|
9
|
+
import { r as runCleanups } from "./wizard-abort-AEhoDJ4P.js";
|
|
10
|
+
import { n as isNonInteractiveEnvironment } from "./environment-Bi-zynk6.js";
|
|
11
|
+
import { n as runAgent, o as authenticate } from "./agent-runner-B1qCtjid.js";
|
|
12
|
+
import { _ as WIZARD_TOOL_NAMES, b as fetchSkillMenu, l as recoverOrphanedSettingsBackups, p as AgentSignals } from "./agent-interface-DoFVHRFh.js";
|
|
13
|
+
import { S as SETUP_REPORT_FILE, _ as AUDIT_CHECKS_KEY, g as AUDIT_CHECKS_FILE, v as AUDIT_REPORT_FILE } from "./yara-hooks-CKsVxWiN.js";
|
|
14
|
+
import { i as SPINNER_MESSAGE } from "./registry-CsFuKtXn.js";
|
|
15
|
+
import { S as gatherFrameworkContext, _ as detectWarehousePrerequisites, a as LINE_CHART_BLOCK, g as WAREHOUSE_ABORT_CASES, h as HEALTH_CHECK_STEP, i as FUNNEL_BLOCK, m as Icons, n as integrationRunStep, o as PRODUCT_SUITE_BLOCK, p as Colors, r as posthogIntegrationConfig, s as StatusPeekTrigger, u as isClearBlock, v as getDetectedWarehouseSources, x as resolveProjectDir, y as detectIntegrationProjects } from "./posthog-integration-pnxhTbxw.js";
|
|
16
|
+
import { n as readApiKeyFromEnv } from "./env-api-key-DDVkPQmo.js";
|
|
17
17
|
import { satisfies } from "semver";
|
|
18
18
|
import yargs from "yargs";
|
|
19
19
|
import { hideBin } from "yargs/helpers";
|
|
@@ -200,7 +200,7 @@ function runProvision(argv) {
|
|
|
200
200
|
}
|
|
201
201
|
async function provision({ email, region, name, baseUrl, jsonMode }) {
|
|
202
202
|
try {
|
|
203
|
-
const { provisionNewAccount } = await import("./provisioning-
|
|
203
|
+
const { provisionNewAccount } = await import("./provisioning-T4jtJqBa.js").then((n) => n.n);
|
|
204
204
|
if (!jsonMode) getUI().log.info(`Provisioning account for ${email} in ${region}...`);
|
|
205
205
|
emitResult(await provisionNewAccount(email, name, region, { baseUrl }), jsonMode);
|
|
206
206
|
process.exit(0);
|
|
@@ -267,73 +267,64 @@ const basicIntegrationCommand = {
|
|
|
267
267
|
setEntryCommand("integrate");
|
|
268
268
|
(async () => {
|
|
269
269
|
if (isHeadless(argv)) {
|
|
270
|
-
const { runHeadlessInstall } = await import("./ci-install-
|
|
270
|
+
const { runHeadlessInstall } = await import("./ci-install-D1Mum8Ah.js");
|
|
271
271
|
return runHeadlessInstall(argv);
|
|
272
272
|
}
|
|
273
273
|
if (argv.ci) {
|
|
274
|
-
const { runCIInstall } = await import("./ci-install-
|
|
274
|
+
const { runCIInstall } = await import("./ci-install-D1Mum8Ah.js");
|
|
275
275
|
return runCIInstall(argv);
|
|
276
276
|
}
|
|
277
277
|
if (isNonInteractiveEnvironment()) {
|
|
278
|
-
const { failNonInteractive } = await import("./non-interactive-
|
|
278
|
+
const { failNonInteractive } = await import("./non-interactive-DdUe8lqX.js");
|
|
279
279
|
return failNonInteractive();
|
|
280
280
|
}
|
|
281
281
|
if (argv.playground) {
|
|
282
|
-
const { runPlayground } = await import("./playground-
|
|
282
|
+
const { runPlayground } = await import("./playground-lg7h9GHG.js");
|
|
283
283
|
return runPlayground();
|
|
284
284
|
}
|
|
285
|
-
const { runInteractive } = await import("./interactive-
|
|
285
|
+
const { runInteractive } = await import("./interactive-HM71vLQe.js");
|
|
286
286
|
runInteractive(argv);
|
|
287
287
|
})();
|
|
288
288
|
}
|
|
289
289
|
};
|
|
290
290
|
//#endregion
|
|
291
291
|
//#region src/lib/programs/shared/package-scanning.ts
|
|
292
|
-
const POSTHOG_SDKS = [
|
|
292
|
+
const POSTHOG_SDKS = new Set([
|
|
293
293
|
"posthog-js",
|
|
294
294
|
"posthog-node",
|
|
295
295
|
"posthog-react-native",
|
|
296
296
|
"posthog-android",
|
|
297
297
|
"posthog-ios"
|
|
298
|
-
];
|
|
299
|
-
const STRIPE_SDKS = [
|
|
298
|
+
]);
|
|
299
|
+
const STRIPE_SDKS = new Set([
|
|
300
300
|
"stripe",
|
|
301
301
|
"@stripe/stripe-js",
|
|
302
302
|
"@stripe/react-stripe-js"
|
|
303
|
-
];
|
|
303
|
+
]);
|
|
304
|
+
const MAX_PACKAGE_MATCHES = 500;
|
|
304
305
|
/**
|
|
305
|
-
*
|
|
306
|
-
*
|
|
306
|
+
* Find all package.json files under installDir via the shared bounded walk
|
|
307
|
+
* (depth cap, ignored dirs, symlink-loop protection, per-dir entry cap).
|
|
308
|
+
* Returns matches with detected SDKs.
|
|
307
309
|
*/
|
|
308
310
|
function findPackageJsons(installDir, maxDepth = 3) {
|
|
309
311
|
const matches = [];
|
|
310
|
-
|
|
311
|
-
if (
|
|
312
|
-
|
|
312
|
+
walkProjectFiles(installDir, (name, fullPath) => {
|
|
313
|
+
if (name !== "package.json" || matches.length >= MAX_PACKAGE_MATCHES) return;
|
|
314
|
+
const content = safeReadFile(fullPath);
|
|
315
|
+
if (content === null) return;
|
|
313
316
|
try {
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
const posthogSdks = depNames.filter((d) => POSTHOG_SDKS.includes(d));
|
|
326
|
-
const stripeSdks = depNames.filter((d) => STRIPE_SDKS.includes(d));
|
|
327
|
-
matches.push({
|
|
328
|
-
path: relative(installDir, fullPath) || "package.json",
|
|
329
|
-
posthogSdks,
|
|
330
|
-
stripeSdks
|
|
331
|
-
});
|
|
332
|
-
} catch {}
|
|
333
|
-
else if (entry.isDirectory()) scan(fullPath, depth + 1);
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
scan(installDir, 0);
|
|
317
|
+
const pkg = JSON.parse(content);
|
|
318
|
+
const depNames = [...Object.keys(pkg.dependencies ?? {}), ...Object.keys(pkg.devDependencies ?? {})];
|
|
319
|
+
const posthogSdks = depNames.filter((d) => POSTHOG_SDKS.has(d));
|
|
320
|
+
const stripeSdks = depNames.filter((d) => STRIPE_SDKS.has(d));
|
|
321
|
+
matches.push({
|
|
322
|
+
path: relative(installDir, fullPath) || "package.json",
|
|
323
|
+
posthogSdks,
|
|
324
|
+
stripeSdks
|
|
325
|
+
});
|
|
326
|
+
} catch {}
|
|
327
|
+
}, maxDepth);
|
|
337
328
|
return matches;
|
|
338
329
|
}
|
|
339
330
|
//#endregion
|
|
@@ -1797,13 +1788,14 @@ const DISPLAY_NAME = {
|
|
|
1797
1788
|
rollup: "Rollup"
|
|
1798
1789
|
};
|
|
1799
1790
|
/**
|
|
1800
|
-
* Variants the wizard can wire up source-map upload for automatically.
|
|
1801
|
-
*
|
|
1802
|
-
*
|
|
1791
|
+
* Variants the wizard can wire up source-map upload for automatically. React
|
|
1792
|
+
* Native is recognised but not yet automatable, so the agentic picker treats
|
|
1793
|
+
* it as non-instrumentable.
|
|
1803
1794
|
*/
|
|
1804
1795
|
const AUTOMATABLE_VARIANTS = [
|
|
1805
1796
|
"android",
|
|
1806
1797
|
"ios",
|
|
1798
|
+
"flutter",
|
|
1807
1799
|
"web",
|
|
1808
1800
|
"nextjs",
|
|
1809
1801
|
"node",
|
|
@@ -1816,9 +1808,16 @@ const AUTOMATABLE_VARIANTS = [
|
|
|
1816
1808
|
];
|
|
1817
1809
|
/**
|
|
1818
1810
|
* Variants the wizard pre-installs a machine-global `posthog-cli` for — their
|
|
1819
|
-
* build shells out to it with no npx / local-dep fallback. JS variants stay
|
|
1811
|
+
* build shells out to it with no npx / local-dep fallback. JS variants stay
|
|
1812
|
+
* out. Flutter counts here despite emitting plain `.js.map` files: a Flutter
|
|
1813
|
+
* project has no `package.json`, so there is no npx or local dependency to
|
|
1814
|
+
* fall back to when the post-build step invokes the CLI.
|
|
1820
1815
|
*/
|
|
1821
|
-
const VARIANTS_REQUIRING_POSTHOG_CLI = new Set([
|
|
1816
|
+
const VARIANTS_REQUIRING_POSTHOG_CLI = new Set([
|
|
1817
|
+
"ios",
|
|
1818
|
+
"android",
|
|
1819
|
+
"flutter"
|
|
1820
|
+
]);
|
|
1822
1821
|
/** `[ABORT] <reason>` cases the source maps skill can emit. */
|
|
1823
1822
|
const SOURCE_MAPS_ABORT_CASES = [{
|
|
1824
1823
|
match: /^no posthog sdk detected$/i,
|
|
@@ -2663,23 +2662,30 @@ const WALK_MAX_DEPTH = 2;
|
|
|
2663
2662
|
*/
|
|
2664
2663
|
function scanDirs(installDir) {
|
|
2665
2664
|
const rels = new Set(POSTHOG_DIRS);
|
|
2666
|
-
const
|
|
2665
|
+
const stack = [{
|
|
2666
|
+
rel: ".",
|
|
2667
|
+
depth: 0
|
|
2668
|
+
}];
|
|
2669
|
+
while (stack.length > 0) {
|
|
2670
|
+
const { rel, depth } = stack.pop();
|
|
2667
2671
|
rels.add(rel);
|
|
2668
|
-
if (depth >= WALK_MAX_DEPTH)
|
|
2672
|
+
if (depth >= WALK_MAX_DEPTH) continue;
|
|
2669
2673
|
let entries;
|
|
2670
2674
|
try {
|
|
2671
2675
|
entries = readdirSync(join(installDir, rel), { withFileTypes: true });
|
|
2672
2676
|
} catch {
|
|
2673
|
-
|
|
2677
|
+
continue;
|
|
2674
2678
|
}
|
|
2675
2679
|
for (const e of entries) {
|
|
2676
2680
|
if (!e.isDirectory()) continue;
|
|
2677
2681
|
if (e.name.startsWith(".") || WALK_SKIP_DIRS.has(e.name)) continue;
|
|
2678
2682
|
if (e.name.endsWith(".xcodeproj") || e.name.endsWith(".xcworkspace")) continue;
|
|
2679
|
-
|
|
2683
|
+
stack.push({
|
|
2684
|
+
rel: rel === "." ? e.name : `${rel}/${e.name}`,
|
|
2685
|
+
depth: depth + 1
|
|
2686
|
+
});
|
|
2680
2687
|
}
|
|
2681
|
-
}
|
|
2682
|
-
walk(".", 0);
|
|
2688
|
+
}
|
|
2683
2689
|
return [...rels];
|
|
2684
2690
|
}
|
|
2685
2691
|
/**
|
|
@@ -3787,13 +3793,13 @@ const mcpAddCommand = {
|
|
|
3787
3793
|
function runMcpAdd(argv) {
|
|
3788
3794
|
const features = parseFeatures(argv.features);
|
|
3789
3795
|
(async () => {
|
|
3790
|
-
const { readApiKeyFromEnv } = await import("./env-api-key-
|
|
3796
|
+
const { readApiKeyFromEnv } = await import("./env-api-key-DDVkPQmo.js").then((n) => n.t);
|
|
3791
3797
|
const apiKey = argv.apiKey || readApiKeyFromEnv();
|
|
3792
3798
|
const debug = argv.debug;
|
|
3793
3799
|
const localMcp = argv.local;
|
|
3794
3800
|
try {
|
|
3795
|
-
const { startTUI } = await import("./start-tui-
|
|
3796
|
-
const { buildSession } = await import("./wizard-session-
|
|
3801
|
+
const { startTUI } = await import("./start-tui-pCi7WVAK.js");
|
|
3802
|
+
const { buildSession } = await import("./wizard-session-C5lZPPEc.js");
|
|
3797
3803
|
const tui = startTUI(VERSION, Program.McpAdd);
|
|
3798
3804
|
tui.store.session = buildSession({
|
|
3799
3805
|
debug,
|
|
@@ -3805,7 +3811,7 @@ function runMcpAdd(argv) {
|
|
|
3805
3811
|
} catch (error) {
|
|
3806
3812
|
if (!isTUIUnavailable(error)) throw error;
|
|
3807
3813
|
setUI(new LoggingUI());
|
|
3808
|
-
const { addMCPServerToClientsStep } = await import("./add-mcp-server-to-clients-
|
|
3814
|
+
const { addMCPServerToClientsStep } = await import("./add-mcp-server-to-clients-DJyWMMGj.js").then((n) => n.r);
|
|
3809
3815
|
await addMCPServerToClientsStep({
|
|
3810
3816
|
local: localMcp,
|
|
3811
3817
|
features,
|
|
@@ -3844,8 +3850,8 @@ function runMcpRemove(argv) {
|
|
|
3844
3850
|
const debug = argv.debug;
|
|
3845
3851
|
const localMcp = argv.local;
|
|
3846
3852
|
try {
|
|
3847
|
-
const { startTUI } = await import("./start-tui-
|
|
3848
|
-
const { buildSession } = await import("./wizard-session-
|
|
3853
|
+
const { startTUI } = await import("./start-tui-pCi7WVAK.js");
|
|
3854
|
+
const { buildSession } = await import("./wizard-session-C5lZPPEc.js");
|
|
3849
3855
|
const tui = startTUI(VERSION, Program.McpRemove);
|
|
3850
3856
|
tui.store.session = buildSession({
|
|
3851
3857
|
debug,
|
|
@@ -3854,7 +3860,7 @@ function runMcpRemove(argv) {
|
|
|
3854
3860
|
});
|
|
3855
3861
|
} catch {
|
|
3856
3862
|
setUI(new LoggingUI());
|
|
3857
|
-
const { removeMCPServerFromClientsStep } = await import("./add-mcp-server-to-clients-
|
|
3863
|
+
const { removeMCPServerFromClientsStep } = await import("./add-mcp-server-to-clients-DJyWMMGj.js").then((n) => n.r);
|
|
3858
3864
|
await removeMCPServerFromClientsStep({ local: localMcp });
|
|
3859
3865
|
}
|
|
3860
3866
|
})();
|
|
@@ -3876,8 +3882,8 @@ function runMcpTutorial(argv) {
|
|
|
3876
3882
|
const debug = argv.debug;
|
|
3877
3883
|
const localMcp = argv.local;
|
|
3878
3884
|
try {
|
|
3879
|
-
const { startTUI } = await import("./start-tui-
|
|
3880
|
-
const { buildSession } = await import("./wizard-session-
|
|
3885
|
+
const { startTUI } = await import("./start-tui-pCi7WVAK.js");
|
|
3886
|
+
const { buildSession } = await import("./wizard-session-C5lZPPEc.js");
|
|
3881
3887
|
const tui = startTUI(VERSION, Program.McpTutorial);
|
|
3882
3888
|
tui.store.session = buildSession({
|
|
3883
3889
|
debug,
|
|
@@ -3957,10 +3963,10 @@ function runWizard(config, options) {
|
|
|
3957
3963
|
(async () => {
|
|
3958
3964
|
try {
|
|
3959
3965
|
const installDir = options.installDir || process.cwd();
|
|
3960
|
-
const { startTUI } = await import("./start-tui-
|
|
3961
|
-
const { buildSession, RunPhase } = await import("./wizard-session-
|
|
3962
|
-
const { TaskStreamPush } = await import("./task-stream-
|
|
3963
|
-
const { PostHogDestination } = await import("./posthog-
|
|
3966
|
+
const { startTUI } = await import("./start-tui-pCi7WVAK.js");
|
|
3967
|
+
const { buildSession, RunPhase } = await import("./wizard-session-C5lZPPEc.js");
|
|
3968
|
+
const { TaskStreamPush } = await import("./task-stream-BZOjOhKu.js");
|
|
3969
|
+
const { PostHogDestination } = await import("./posthog-mgz-FQlS.js");
|
|
3964
3970
|
tui = startTUI(WIZARD_VERSION, config.id);
|
|
3965
3971
|
const activeTui = tui;
|
|
3966
3972
|
const session = buildSession({
|
|
@@ -4025,7 +4031,7 @@ function runWizard(config, options) {
|
|
|
4025
4031
|
if (shown(step)) await advanceStep(step, activeTui.store, config);
|
|
4026
4032
|
}
|
|
4027
4033
|
else if (skipAgent) {
|
|
4028
|
-
const { getOrAskForProjectData } = await import("./setup-utils-
|
|
4034
|
+
const { getOrAskForProjectData } = await import("./setup-utils-DDzEnDxJ.js").then((n) => n.r);
|
|
4029
4035
|
const { projectApiKey, host, accessToken, projectId } = await getOrAskForProjectData({
|
|
4030
4036
|
signup: session.signup,
|
|
4031
4037
|
ci: session.ci,
|
|
@@ -4126,11 +4132,11 @@ function runNonInteractive(config, options, mode) {
|
|
|
4126
4132
|
analytics.setTag("build", mode);
|
|
4127
4133
|
(async () => {
|
|
4128
4134
|
const path = await import("path");
|
|
4129
|
-
const { buildSession, RunPhase, OutroKind } = await import("./wizard-session-
|
|
4130
|
-
const { readEnvironment } = await import("./environment-
|
|
4131
|
-
const { readApiKeyFromEnv } = await import("./env-api-key-
|
|
4132
|
-
const { configureLogFileFromEnvironment, logToFile } = await import("./debug-
|
|
4133
|
-
const { wizardAbort, WizardError } = await import("./wizard-abort-
|
|
4135
|
+
const { buildSession, RunPhase, OutroKind } = await import("./wizard-session-C5lZPPEc.js");
|
|
4136
|
+
const { readEnvironment } = await import("./environment-Bi-zynk6.js").then((n) => n.t);
|
|
4137
|
+
const { readApiKeyFromEnv } = await import("./env-api-key-DDVkPQmo.js").then((n) => n.t);
|
|
4138
|
+
const { configureLogFileFromEnvironment, logToFile } = await import("./debug-DsSCOPe8.js");
|
|
4139
|
+
const { wizardAbort, WizardError } = await import("./wizard-abort-DHC_XStW.js");
|
|
4134
4140
|
configureLogFileFromEnvironment();
|
|
4135
4141
|
const env = readEnvironment();
|
|
4136
4142
|
const apiKey = options.apiKey ?? readApiKeyFromEnv() ?? void 0;
|
|
@@ -4162,9 +4168,9 @@ function runNonInteractive(config, options, mode) {
|
|
|
4162
4168
|
let store = null;
|
|
4163
4169
|
let taskStream = null;
|
|
4164
4170
|
if (mode === "headless") {
|
|
4165
|
-
const { WizardStore } = await import("./store-
|
|
4166
|
-
const { HeadlessUI } = await import("./headless-ui-
|
|
4167
|
-
const { TaskStreamPush, PostHogDestination } = await import("./task-stream-
|
|
4171
|
+
const { WizardStore } = await import("./store-BCRdtfOH.js").then((n) => n.n);
|
|
4172
|
+
const { HeadlessUI } = await import("./headless-ui-C4X9lAOY.js");
|
|
4173
|
+
const { TaskStreamPush, PostHogDestination } = await import("./task-stream-BZOjOhKu.js");
|
|
4168
4174
|
store = new WizardStore(config.id);
|
|
4169
4175
|
store.session = session;
|
|
4170
4176
|
setUI(new HeadlessUI(store));
|
|
@@ -4220,7 +4226,7 @@ function runNonInteractive(config, options, mode) {
|
|
|
4220
4226
|
});
|
|
4221
4227
|
}
|
|
4222
4228
|
}
|
|
4223
|
-
const { runAgent } = await import("./agent-runner-
|
|
4229
|
+
const { runAgent } = await import("./agent-runner-B1qCtjid.js").then((n) => n.t);
|
|
4224
4230
|
await runAgent(config, session);
|
|
4225
4231
|
await settleStream(RunPhase.Completed);
|
|
4226
4232
|
} catch (error) {
|
|
@@ -5163,7 +5169,7 @@ async function runDoctorCI(options) {
|
|
|
5163
5169
|
getUI().intro("Welcome to the PostHog setup wizard");
|
|
5164
5170
|
getUI().log.info("Running posthog-doctor in CI mode");
|
|
5165
5171
|
try {
|
|
5166
|
-
const { getOrAskForProjectData } = await import("./setup-utils-
|
|
5172
|
+
const { getOrAskForProjectData } = await import("./setup-utils-DDzEnDxJ.js").then((n) => n.r);
|
|
5167
5173
|
const { host, accessToken, projectId } = await getOrAskForProjectData({
|
|
5168
5174
|
signup: false,
|
|
5169
5175
|
ci: true,
|
|
@@ -5181,7 +5187,7 @@ async function runDoctorCI(options) {
|
|
|
5181
5187
|
for (const issue of sorted) getUI().log.info(` • [${issue.severity}] ${getKindMeta(issue.kind).title}`);
|
|
5182
5188
|
process.exit(1);
|
|
5183
5189
|
} catch (error) {
|
|
5184
|
-
const { ApiError } = await import("./api-
|
|
5190
|
+
const { ApiError } = await import("./api-BaacjH-Y.js").then((n) => n.n);
|
|
5185
5191
|
const message = error instanceof ApiError && error.statusCode === 401 ? "Your PostHog API key is invalid or expired." : error instanceof Error ? error.message : String(error);
|
|
5186
5192
|
getUI().log.error(`Doctor failed: ${message}`);
|
|
5187
5193
|
process.exit(1);
|
|
@@ -5263,8 +5269,8 @@ function runSlackConnect(argv) {
|
|
|
5263
5269
|
(async () => {
|
|
5264
5270
|
const debug = argv.debug;
|
|
5265
5271
|
try {
|
|
5266
|
-
const { startTUI } = await import("./start-tui-
|
|
5267
|
-
const { buildSession } = await import("./wizard-session-
|
|
5272
|
+
const { startTUI } = await import("./start-tui-pCi7WVAK.js");
|
|
5273
|
+
const { buildSession } = await import("./wizard-session-C5lZPPEc.js");
|
|
5268
5274
|
const tui = startTUI(VERSION, Program.SlackConnect);
|
|
5269
5275
|
tui.store.session = buildSession({
|
|
5270
5276
|
debug,
|