@posthog/wizard 2.25.0 → 2.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -1
- package/dist/{add-mcp-server-to-clients-t0xe8gn1.js → add-mcp-server-to-clients-D2XNlVgw.js} +4 -4
- package/dist/{add-mcp-server-to-clients-t0xe8gn1.js.map → add-mcp-server-to-clients-D2XNlVgw.js.map} +1 -1
- package/dist/{agent-interface-BsuUUPle.js → agent-interface-DpkR1mbC.js} +39 -12
- package/dist/agent-interface-DpkR1mbC.js.map +1 -0
- package/dist/{agent-runner-L_-kJ3y3.js → agent-runner-D7hIITUf.js} +176 -167
- package/dist/agent-runner-D7hIITUf.js.map +1 -0
- package/dist/{analytics-CDOujOSQ.js → analytics-B7-uRKIJ.js} +2 -2
- package/dist/{analytics-CDOujOSQ.js.map → analytics-B7-uRKIJ.js.map} +1 -1
- package/dist/{api-DNS-L-1U.js → api-2zPZQONC.js} +9 -5
- package/dist/api-2zPZQONC.js.map +1 -0
- package/dist/bin.js +1160 -120
- package/dist/bin.js.map +1 -1
- package/dist/{ci-install-_9A7tL36.js → ci-install-CpGSFNDi.js} +5 -5
- package/dist/{ci-install-_9A7tL36.js.map → ci-install-CpGSFNDi.js.map} +1 -1
- package/dist/{debug-BwC7UkGH.js → debug-Br_xCc9s.js} +3 -2
- package/dist/{debug-BwC7UkGH.js.map → debug-Br_xCc9s.js.map} +1 -1
- package/dist/{debug-CZQcMAJT.js → debug-CDLYQOQh.js} +1 -1
- package/dist/{environment-DQPoj9sU.js → environment-CFXsie0G.js} +3 -3
- package/dist/{environment-DQPoj9sU.js.map → environment-CFXsie0G.js.map} +1 -1
- package/dist/file-utils-CHAj73KM.js +116 -0
- package/dist/file-utils-CHAj73KM.js.map +1 -0
- package/dist/{interactive-DT5dLd7N.js → interactive-lfAs6vF7.js} +3 -3
- package/dist/{interactive-DT5dLd7N.js.map → interactive-lfAs6vF7.js.map} +1 -1
- package/dist/{mcp-prompt-streaming-CBMr458Q.js → mcp-prompt-streaming-BHdAwwob.js} +4 -4
- package/dist/{mcp-prompt-streaming-CBMr458Q.js.map → mcp-prompt-streaming-BHdAwwob.js.map} +1 -1
- package/dist/{non-interactive-csP4yGdA.js → non-interactive--4CK1bkn.js} +2 -2
- package/dist/{non-interactive-csP4yGdA.js.map → non-interactive--4CK1bkn.js.map} +1 -1
- package/dist/{package-manager-CB4c2euf.js → package-manager-BlogZvIK.js} +2 -2
- package/dist/{package-manager-CB4c2euf.js.map → package-manager-BlogZvIK.js.map} +1 -1
- package/dist/{playground-C-lpKoKC.js → playground-De_BxaCh.js} +145 -48
- package/dist/playground-De_BxaCh.js.map +1 -0
- package/dist/{posthog-integration-BL8-vC0V.js → posthog-integration-DWs8JM8J.js} +12 -12
- package/dist/{posthog-integration-BL8-vC0V.js.map → posthog-integration-DWs8JM8J.js.map} +1 -1
- package/dist/{provisioning-DLOiFSM9.js → provisioning-CUwxxByi.js} +10 -6
- package/dist/{provisioning-DLOiFSM9.js.map → provisioning-CUwxxByi.js.map} +1 -1
- package/dist/{registry-BbRzCV5l.js → registry-CIjJsxDE.js} +4 -4
- package/dist/{registry-BbRzCV5l.js.map → registry-CIjJsxDE.js.map} +1 -1
- package/dist/{setup-utils-D87CyNkw.js → setup-utils-CjKjaKcG.js} +81 -16
- package/dist/setup-utils-CjKjaKcG.js.map +1 -0
- package/dist/{start-tui-DnAG57vY.js → start-tui-Cbw0kVr3.js} +471 -54
- package/dist/start-tui-Cbw0kVr3.js.map +1 -0
- package/dist/{steps-JaxH6u0f.js → steps-DUz5lHWu.js} +7 -6
- package/dist/{steps-JaxH6u0f.js.map → steps-DUz5lHWu.js.map} +1 -1
- package/dist/{telemetry-DL28cCwY.js → telemetry-D3CnLknq.js} +3 -3
- package/dist/{telemetry-DL28cCwY.js.map → telemetry-D3CnLknq.js.map} +1 -1
- package/dist/{AiOptInRequiredScreen-C-D9tN6r.js → terminal-DwAdsRPX.js} +1047 -85
- package/dist/terminal-DwAdsRPX.js.map +1 -0
- package/dist/{urls-vkJ5c0ix.js → urls-JN8mo6lU.js} +2 -2
- package/dist/{urls-vkJ5c0ix.js.map → urls-JN8mo6lU.js.map} +1 -1
- package/dist/{wizard-abort-BRXKRL4F.js → wizard-abort-BPr0xo7i.js} +1 -1
- package/dist/{wizard-abort-CLGgMAEe.js → wizard-abort-gHZ7kHYo.js} +3 -3
- package/dist/{wizard-abort-CLGgMAEe.js.map → wizard-abort-gHZ7kHYo.js.map} +1 -1
- package/dist/wizard-session-G3VWD6hv.js.map +1 -1
- package/dist/wizard-ui-WZ48rUgr.js.map +1 -1
- package/package.json +1 -1
- package/dist/AiOptInRequiredScreen-C-D9tN6r.js.map +0 -1
- package/dist/agent-interface-BsuUUPle.js.map +0 -1
- package/dist/agent-runner-L_-kJ3y3.js.map +0 -1
- package/dist/api-DNS-L-1U.js.map +0 -1
- package/dist/file-utils-VAXoyXVA.js +0 -38
- package/dist/file-utils-VAXoyXVA.js.map +0 -1
- package/dist/playground-C-lpKoKC.js.map +0 -1
- package/dist/setup-utils-D87CyNkw.js.map +0 -1
- package/dist/start-tui-DnAG57vY.js.map +0 -1
package/dist/bin.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { $ as getSkillsBaseUrl, P as POSTHOG_DOCS_URL, X as WIZARD_USER_AGENT, _ as SIGNUP_WIZARD_READINESS_CONFIG, a as getLogFilePath, et as VERSION, h as LoggingUI, m as setUI, p as getUI, r as debug, s as logToFile, v as evaluateWizardReadiness, y as getBlockingServiceKeys } from "./debug-
|
|
3
|
-
import { t as analytics } from "./analytics-
|
|
4
|
-
import { r as setEntryCommand } from "./telemetry-
|
|
5
|
-
import { n as isUsingTypeScript } from "./setup-utils-
|
|
6
|
-
import { a as getUiHostFromHost, n as getCloudUrlFromRegion } from "./urls-
|
|
7
|
-
import { o as handleApiError } from "./api-
|
|
2
|
+
import { $ as getSkillsBaseUrl, P as POSTHOG_DOCS_URL, X as WIZARD_USER_AGENT, _ as SIGNUP_WIZARD_READINESS_CONFIG, a as getLogFilePath, et as VERSION, h as LoggingUI, m as setUI, p as getUI, r as debug, s as logToFile, v as evaluateWizardReadiness, y as getBlockingServiceKeys } from "./debug-Br_xCc9s.js";
|
|
3
|
+
import { t as analytics } from "./analytics-B7-uRKIJ.js";
|
|
4
|
+
import { r as setEntryCommand } from "./telemetry-D3CnLknq.js";
|
|
5
|
+
import { n as isUsingTypeScript } from "./setup-utils-CjKjaKcG.js";
|
|
6
|
+
import { a as getUiHostFromHost, n as getCloudUrlFromRegion } from "./urls-JN8mo6lU.js";
|
|
7
|
+
import { o as handleApiError } from "./api-2zPZQONC.js";
|
|
8
8
|
import "./wizard-session-G3VWD6hv.js";
|
|
9
|
-
import { r as runCleanups } from "./wizard-abort-
|
|
10
|
-
import { n as isNonInteractiveEnvironment } from "./environment-
|
|
11
|
-
import { S as AUDIT_REPORT_FILE, b as AUDIT_CHECKS_FILE, c as recoverOrphanedSettingsBackups, h as fetchSkillMenu, p as WIZARD_TOOL_NAMES, u as AgentSignals, x as AUDIT_CHECKS_KEY } from "./agent-interface-
|
|
12
|
-
import { i as SPINNER_MESSAGE } from "./registry-
|
|
13
|
-
import { a as PRODUCT_SUITE_BLOCK, f as Colors, i as LINE_CHART_BLOCK, l as isClearBlock, m as HEALTH_CHECK_STEP, n as posthogIntegrationConfig, o as StatusPeekTrigger, p as Icons, r as FUNNEL_BLOCK } from "./posthog-integration-
|
|
14
|
-
import { t as IGNORED_DIRS } from "./file-utils-
|
|
9
|
+
import { r as runCleanups } from "./wizard-abort-gHZ7kHYo.js";
|
|
10
|
+
import { n as isNonInteractiveEnvironment } from "./environment-CFXsie0G.js";
|
|
11
|
+
import { S as AUDIT_REPORT_FILE, b as AUDIT_CHECKS_FILE, c as recoverOrphanedSettingsBackups, h as fetchSkillMenu, p as WIZARD_TOOL_NAMES, u as AgentSignals, x as AUDIT_CHECKS_KEY } from "./agent-interface-DpkR1mbC.js";
|
|
12
|
+
import { i as SPINNER_MESSAGE } from "./registry-CIjJsxDE.js";
|
|
13
|
+
import { _ as parseRequirementsTxt, a as PRODUCT_SUITE_BLOCK, f as Colors, g as parsePyprojectToml, h as parsePipfile, i as LINE_CHART_BLOCK, l as isClearBlock, m as HEALTH_CHECK_STEP, n as posthogIntegrationConfig, o as StatusPeekTrigger, p as Icons, r as FUNNEL_BLOCK } from "./posthog-integration-DWs8JM8J.js";
|
|
14
|
+
import { n as safeReadFile, r as walkProjectFiles, t as IGNORED_DIRS } from "./file-utils-CHAj73KM.js";
|
|
15
15
|
import { n as readApiKeyFromEnv } from "./env-api-key-MlzJYAvt.js";
|
|
16
16
|
import { satisfies } from "semver";
|
|
17
17
|
import yargs from "yargs";
|
|
@@ -27,6 +27,7 @@ import { z } from "zod";
|
|
|
27
27
|
import { Box, Text, render, useInput } from "ink";
|
|
28
28
|
import { createContext, createElement, useCallback, useContext, useEffect, useRef, useState } from "react";
|
|
29
29
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
30
|
+
import { access, rm } from "node:fs/promises";
|
|
30
31
|
import * as readline from "node:readline/promises";
|
|
31
32
|
//#region src/commands/command.ts
|
|
32
33
|
/** Extract the bare command word(s) from a yargs name spec, dropping positionals and aliases' arg syntax. */
|
|
@@ -189,7 +190,7 @@ function runProvision(argv) {
|
|
|
189
190
|
}
|
|
190
191
|
async function provision({ email, region, name, jsonMode }) {
|
|
191
192
|
try {
|
|
192
|
-
const { provisionNewAccount } = await import("./provisioning-
|
|
193
|
+
const { provisionNewAccount } = await import("./provisioning-CUwxxByi.js").then((n) => n.n);
|
|
193
194
|
if (!jsonMode) getUI().log.info(`Provisioning account for ${email} in ${region}...`);
|
|
194
195
|
emitResult(await provisionNewAccount(email, name, region), jsonMode);
|
|
195
196
|
process.exit(0);
|
|
@@ -254,18 +255,18 @@ const basicIntegrationCommand = {
|
|
|
254
255
|
setEntryCommand("integrate");
|
|
255
256
|
(async () => {
|
|
256
257
|
if (argv.ci) {
|
|
257
|
-
const { runCIInstall } = await import("./ci-install-
|
|
258
|
+
const { runCIInstall } = await import("./ci-install-CpGSFNDi.js");
|
|
258
259
|
return runCIInstall(argv);
|
|
259
260
|
}
|
|
260
261
|
if (isNonInteractiveEnvironment()) {
|
|
261
|
-
const { failNonInteractive } = await import("./non-interactive
|
|
262
|
+
const { failNonInteractive } = await import("./non-interactive--4CK1bkn.js");
|
|
262
263
|
return failNonInteractive();
|
|
263
264
|
}
|
|
264
265
|
if (argv.playground) {
|
|
265
|
-
const { runPlayground } = await import("./playground-
|
|
266
|
+
const { runPlayground } = await import("./playground-De_BxaCh.js");
|
|
266
267
|
return runPlayground();
|
|
267
268
|
}
|
|
268
|
-
const { runInteractive } = await import("./interactive-
|
|
269
|
+
const { runInteractive } = await import("./interactive-lfAs6vF7.js");
|
|
269
270
|
runInteractive(argv);
|
|
270
271
|
})();
|
|
271
272
|
}
|
|
@@ -508,6 +509,571 @@ const revenueAnalyticsConfig = {
|
|
|
508
509
|
requires: ["posthog-integration"]
|
|
509
510
|
};
|
|
510
511
|
//#endregion
|
|
512
|
+
//#region src/lib/warehouse-sources/registry.ts
|
|
513
|
+
const SOURCE_DETECTORS = [
|
|
514
|
+
{
|
|
515
|
+
kind: "Postgres",
|
|
516
|
+
label: "PostgreSQL",
|
|
517
|
+
mode: "in-cli",
|
|
518
|
+
signals: {
|
|
519
|
+
npm: [
|
|
520
|
+
"pg",
|
|
521
|
+
"postgres",
|
|
522
|
+
"postgres.js",
|
|
523
|
+
"knex",
|
|
524
|
+
"sequelize"
|
|
525
|
+
],
|
|
526
|
+
python: [
|
|
527
|
+
"psycopg",
|
|
528
|
+
"psycopg2",
|
|
529
|
+
"psycopg2-binary",
|
|
530
|
+
"asyncpg"
|
|
531
|
+
],
|
|
532
|
+
ruby: ["pg"],
|
|
533
|
+
envKeys: [
|
|
534
|
+
/^DATABASE_URL$/,
|
|
535
|
+
/^POSTGRES_/,
|
|
536
|
+
/^PG(HOST|DATABASE|USER|PORT)$/
|
|
537
|
+
]
|
|
538
|
+
}
|
|
539
|
+
},
|
|
540
|
+
{
|
|
541
|
+
kind: "MySQL",
|
|
542
|
+
label: "MySQL",
|
|
543
|
+
mode: "in-cli",
|
|
544
|
+
signals: {
|
|
545
|
+
npm: ["mysql", "mysql2"],
|
|
546
|
+
python: [
|
|
547
|
+
"pymysql",
|
|
548
|
+
"mysqlclient",
|
|
549
|
+
"mysql-connector-python"
|
|
550
|
+
],
|
|
551
|
+
ruby: ["mysql2"],
|
|
552
|
+
envKeys: [/^MYSQL_/]
|
|
553
|
+
}
|
|
554
|
+
},
|
|
555
|
+
{
|
|
556
|
+
kind: "MongoDB",
|
|
557
|
+
label: "MongoDB",
|
|
558
|
+
mode: "in-cli",
|
|
559
|
+
signals: {
|
|
560
|
+
npm: ["mongodb", "mongoose"],
|
|
561
|
+
python: ["pymongo", "motor"],
|
|
562
|
+
ruby: ["mongo", "mongoid"],
|
|
563
|
+
envKeys: [/^MONGO(DB)?_/]
|
|
564
|
+
}
|
|
565
|
+
},
|
|
566
|
+
{
|
|
567
|
+
kind: "Snowflake",
|
|
568
|
+
label: "Snowflake",
|
|
569
|
+
mode: "in-cli",
|
|
570
|
+
signals: {
|
|
571
|
+
npm: ["snowflake-sdk"],
|
|
572
|
+
python: ["snowflake-connector-python", "snowflake-sqlalchemy"],
|
|
573
|
+
envKeys: [/^SNOWFLAKE_/]
|
|
574
|
+
}
|
|
575
|
+
},
|
|
576
|
+
{
|
|
577
|
+
kind: "BigQuery",
|
|
578
|
+
label: "BigQuery",
|
|
579
|
+
mode: "in-cli",
|
|
580
|
+
signals: {
|
|
581
|
+
npm: ["@google-cloud/bigquery"],
|
|
582
|
+
python: ["google-cloud-bigquery"],
|
|
583
|
+
envKeys: [/^BIGQUERY_/]
|
|
584
|
+
}
|
|
585
|
+
},
|
|
586
|
+
{
|
|
587
|
+
kind: "Redshift",
|
|
588
|
+
label: "Redshift",
|
|
589
|
+
mode: "in-cli",
|
|
590
|
+
signals: {
|
|
591
|
+
npm: ["node-redshift"],
|
|
592
|
+
python: ["redshift-connector"],
|
|
593
|
+
envKeys: [/^REDSHIFT_/]
|
|
594
|
+
}
|
|
595
|
+
},
|
|
596
|
+
{
|
|
597
|
+
kind: "MSSQL",
|
|
598
|
+
label: "SQL Server",
|
|
599
|
+
mode: "in-cli",
|
|
600
|
+
signals: {
|
|
601
|
+
npm: ["mssql", "tedious"],
|
|
602
|
+
python: ["pyodbc", "pymssql"],
|
|
603
|
+
envKeys: [/^MSSQL_/]
|
|
604
|
+
}
|
|
605
|
+
},
|
|
606
|
+
{
|
|
607
|
+
kind: "Supabase",
|
|
608
|
+
label: "Supabase",
|
|
609
|
+
mode: "in-cli",
|
|
610
|
+
signals: {
|
|
611
|
+
npm: ["@supabase/supabase-js"],
|
|
612
|
+
python: ["supabase"],
|
|
613
|
+
envKeys: [/^SUPABASE_/]
|
|
614
|
+
}
|
|
615
|
+
},
|
|
616
|
+
{
|
|
617
|
+
kind: "ClickHouse",
|
|
618
|
+
label: "ClickHouse",
|
|
619
|
+
mode: "in-cli",
|
|
620
|
+
signals: {
|
|
621
|
+
npm: ["@clickhouse/client"],
|
|
622
|
+
python: ["clickhouse-connect", "clickhouse-driver"],
|
|
623
|
+
envKeys: [/^CLICKHOUSE_/]
|
|
624
|
+
}
|
|
625
|
+
},
|
|
626
|
+
{
|
|
627
|
+
kind: "Convex",
|
|
628
|
+
label: "Convex",
|
|
629
|
+
mode: "in-cli",
|
|
630
|
+
signals: {
|
|
631
|
+
npm: ["convex"],
|
|
632
|
+
python: ["convex"],
|
|
633
|
+
envKeys: [/^CONVEX_/, /^NEXT_PUBLIC_CONVEX_URL$/]
|
|
634
|
+
}
|
|
635
|
+
},
|
|
636
|
+
{
|
|
637
|
+
kind: "Stripe",
|
|
638
|
+
label: "Stripe",
|
|
639
|
+
mode: "in-cli",
|
|
640
|
+
signals: {
|
|
641
|
+
npm: [
|
|
642
|
+
"stripe",
|
|
643
|
+
"@stripe/stripe-js",
|
|
644
|
+
"@stripe/react-stripe-js"
|
|
645
|
+
],
|
|
646
|
+
python: ["stripe"],
|
|
647
|
+
ruby: ["stripe"],
|
|
648
|
+
envKeys: [/^STRIPE_(SECRET|API)_KEY$/]
|
|
649
|
+
}
|
|
650
|
+
},
|
|
651
|
+
{
|
|
652
|
+
kind: "Clerk",
|
|
653
|
+
label: "Clerk",
|
|
654
|
+
mode: "in-cli",
|
|
655
|
+
signals: {
|
|
656
|
+
npm: [
|
|
657
|
+
"@clerk/nextjs",
|
|
658
|
+
"@clerk/clerk-react",
|
|
659
|
+
"@clerk/backend",
|
|
660
|
+
"@clerk/express",
|
|
661
|
+
"@clerk/fastify",
|
|
662
|
+
"@clerk/remix"
|
|
663
|
+
],
|
|
664
|
+
envKeys: [/^CLERK_SECRET_KEY$/, /^NEXT_PUBLIC_CLERK_/]
|
|
665
|
+
}
|
|
666
|
+
},
|
|
667
|
+
{
|
|
668
|
+
kind: "Resend",
|
|
669
|
+
label: "Resend",
|
|
670
|
+
mode: "in-cli",
|
|
671
|
+
signals: {
|
|
672
|
+
npm: ["resend"],
|
|
673
|
+
python: ["resend"],
|
|
674
|
+
envKeys: [/^RESEND_API_KEY$/]
|
|
675
|
+
}
|
|
676
|
+
},
|
|
677
|
+
{
|
|
678
|
+
kind: "Shopify",
|
|
679
|
+
label: "Shopify",
|
|
680
|
+
mode: "in-cli",
|
|
681
|
+
signals: {
|
|
682
|
+
npm: ["@shopify/shopify-api", "shopify-api-node"],
|
|
683
|
+
python: ["shopifyapi"],
|
|
684
|
+
envKeys: [/^SHOPIFY_/]
|
|
685
|
+
}
|
|
686
|
+
},
|
|
687
|
+
{
|
|
688
|
+
kind: "Klaviyo",
|
|
689
|
+
label: "Klaviyo",
|
|
690
|
+
mode: "in-cli",
|
|
691
|
+
signals: {
|
|
692
|
+
npm: ["klaviyo-api"],
|
|
693
|
+
python: ["klaviyo-api"],
|
|
694
|
+
envKeys: [/^KLAVIYO_/]
|
|
695
|
+
}
|
|
696
|
+
},
|
|
697
|
+
{
|
|
698
|
+
kind: "Chargebee",
|
|
699
|
+
label: "Chargebee",
|
|
700
|
+
mode: "in-cli",
|
|
701
|
+
signals: {
|
|
702
|
+
npm: ["chargebee"],
|
|
703
|
+
python: ["chargebee"],
|
|
704
|
+
envKeys: [/^CHARGEBEE_/]
|
|
705
|
+
}
|
|
706
|
+
},
|
|
707
|
+
{
|
|
708
|
+
kind: "Paddle",
|
|
709
|
+
label: "Paddle",
|
|
710
|
+
mode: "in-cli",
|
|
711
|
+
signals: {
|
|
712
|
+
npm: ["@paddle/paddle-node-sdk", "@paddle/paddle-js"],
|
|
713
|
+
envKeys: [/^PADDLE_/]
|
|
714
|
+
}
|
|
715
|
+
},
|
|
716
|
+
{
|
|
717
|
+
kind: "Polar",
|
|
718
|
+
label: "Polar",
|
|
719
|
+
mode: "in-cli",
|
|
720
|
+
signals: {
|
|
721
|
+
npm: ["@polar-sh/sdk", "@polar-sh/nextjs"],
|
|
722
|
+
envKeys: [/^POLAR_/]
|
|
723
|
+
}
|
|
724
|
+
},
|
|
725
|
+
{
|
|
726
|
+
kind: "Mailchimp",
|
|
727
|
+
label: "Mailchimp",
|
|
728
|
+
mode: "in-cli",
|
|
729
|
+
signals: {
|
|
730
|
+
npm: ["@mailchimp/mailchimp_marketing"],
|
|
731
|
+
python: ["mailchimp-marketing"],
|
|
732
|
+
envKeys: [/^MAILCHIMP_/]
|
|
733
|
+
}
|
|
734
|
+
},
|
|
735
|
+
{
|
|
736
|
+
kind: "CustomerIO",
|
|
737
|
+
label: "Customer.io",
|
|
738
|
+
mode: "in-cli",
|
|
739
|
+
signals: {
|
|
740
|
+
npm: ["customerio-node"],
|
|
741
|
+
python: ["customerio"],
|
|
742
|
+
envKeys: [/^CUSTOMER_?IO_/]
|
|
743
|
+
}
|
|
744
|
+
},
|
|
745
|
+
{
|
|
746
|
+
kind: "Typeform",
|
|
747
|
+
label: "Typeform",
|
|
748
|
+
mode: "in-cli",
|
|
749
|
+
signals: {
|
|
750
|
+
npm: ["@typeform/api-client"],
|
|
751
|
+
envKeys: [/^TYPEFORM_/]
|
|
752
|
+
}
|
|
753
|
+
},
|
|
754
|
+
{
|
|
755
|
+
kind: "Sentry",
|
|
756
|
+
label: "Sentry",
|
|
757
|
+
mode: "in-cli",
|
|
758
|
+
signals: {
|
|
759
|
+
npm: [
|
|
760
|
+
"@sentry/node",
|
|
761
|
+
"@sentry/browser",
|
|
762
|
+
"@sentry/react",
|
|
763
|
+
"@sentry/nextjs"
|
|
764
|
+
],
|
|
765
|
+
python: ["sentry-sdk"],
|
|
766
|
+
ruby: ["sentry-ruby"]
|
|
767
|
+
}
|
|
768
|
+
},
|
|
769
|
+
{
|
|
770
|
+
kind: "Salesforce",
|
|
771
|
+
label: "Salesforce",
|
|
772
|
+
mode: "deep-link",
|
|
773
|
+
signals: {
|
|
774
|
+
npm: ["jsforce"],
|
|
775
|
+
python: ["simple-salesforce"],
|
|
776
|
+
envKeys: [/^SALESFORCE_/]
|
|
777
|
+
}
|
|
778
|
+
},
|
|
779
|
+
{
|
|
780
|
+
kind: "Hubspot",
|
|
781
|
+
label: "HubSpot",
|
|
782
|
+
mode: "deep-link",
|
|
783
|
+
signals: {
|
|
784
|
+
npm: ["@hubspot/api-client"],
|
|
785
|
+
python: ["hubspot-api-client"],
|
|
786
|
+
envKeys: [/^HUBSPOT_/]
|
|
787
|
+
}
|
|
788
|
+
},
|
|
789
|
+
{
|
|
790
|
+
kind: "Zendesk",
|
|
791
|
+
label: "Zendesk",
|
|
792
|
+
mode: "deep-link",
|
|
793
|
+
signals: {
|
|
794
|
+
npm: ["node-zendesk"],
|
|
795
|
+
python: ["zenpy"],
|
|
796
|
+
envKeys: [/^ZENDESK_/]
|
|
797
|
+
}
|
|
798
|
+
},
|
|
799
|
+
{
|
|
800
|
+
kind: "Intercom",
|
|
801
|
+
label: "Intercom",
|
|
802
|
+
mode: "deep-link",
|
|
803
|
+
signals: {
|
|
804
|
+
npm: ["intercom-client", "@intercom/messenger-js-sdk"],
|
|
805
|
+
python: ["python-intercom"],
|
|
806
|
+
envKeys: [/^INTERCOM_/]
|
|
807
|
+
}
|
|
808
|
+
},
|
|
809
|
+
{
|
|
810
|
+
kind: "Linear",
|
|
811
|
+
label: "Linear",
|
|
812
|
+
mode: "deep-link",
|
|
813
|
+
signals: {
|
|
814
|
+
npm: ["@linear/sdk"],
|
|
815
|
+
envKeys: [/^LINEAR_API_KEY$/]
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
];
|
|
819
|
+
//#endregion
|
|
820
|
+
//#region src/lib/warehouse-sources/detect.ts
|
|
821
|
+
/**
|
|
822
|
+
* Data warehouse source detection.
|
|
823
|
+
*
|
|
824
|
+
* Scans a project for codebase signals (npm/python/ruby deps, `.env` key
|
|
825
|
+
* names) and matches them against the `SOURCE_DETECTORS` registry. Pure
|
|
826
|
+
* function: no store mutations, no UI calls. Reads files locally — only the
|
|
827
|
+
* wizard process does this; the agent never sees secret values.
|
|
828
|
+
*
|
|
829
|
+
* Note we only read `.env` KEY NAMES, never values.
|
|
830
|
+
*/
|
|
831
|
+
const MAX_DEPTH = 3;
|
|
832
|
+
/**
|
|
833
|
+
* Detect which warehouse sources the project at `installDir` appears to use.
|
|
834
|
+
* Returns one `DetectedSource` per matched registry entry (kinds are unique,
|
|
835
|
+
* so the result is naturally deduped).
|
|
836
|
+
*/
|
|
837
|
+
function detectWarehouseSources(installDir) {
|
|
838
|
+
const signals = collectSignals$1(installDir);
|
|
839
|
+
const detected = [];
|
|
840
|
+
for (const detector of SOURCE_DETECTORS) {
|
|
841
|
+
const match = matchDetector(detector, signals);
|
|
842
|
+
if (match) detected.push({
|
|
843
|
+
kind: detector.kind,
|
|
844
|
+
label: detector.label,
|
|
845
|
+
mode: detector.mode,
|
|
846
|
+
matchedSignal: match
|
|
847
|
+
});
|
|
848
|
+
}
|
|
849
|
+
return detected;
|
|
850
|
+
}
|
|
851
|
+
/** Returns a human-readable description of the first matching signal, or null. */
|
|
852
|
+
function matchDetector(detector, signals) {
|
|
853
|
+
const { npm, python, ruby, envKeys } = detector.signals;
|
|
854
|
+
const npmHit = npm?.find((dep) => signals.npm.has(dep));
|
|
855
|
+
if (npmHit) return `found \`${npmHit}\` in package.json`;
|
|
856
|
+
const pyHit = python?.find((dep) => signals.python.has(dep));
|
|
857
|
+
if (pyHit) return `found \`${pyHit}\` in Python dependencies`;
|
|
858
|
+
const rubyHit = ruby?.find((gem) => signals.ruby.has(gem));
|
|
859
|
+
if (rubyHit) return `found \`${rubyHit}\` in Gemfile`;
|
|
860
|
+
if (envKeys) {
|
|
861
|
+
for (const key of signals.envKeys) if (envKeys.some((re) => re.test(key))) return `found \`${key}\` in .env`;
|
|
862
|
+
}
|
|
863
|
+
return null;
|
|
864
|
+
}
|
|
865
|
+
function collectSignals$1(installDir) {
|
|
866
|
+
const signals = {
|
|
867
|
+
npm: /* @__PURE__ */ new Set(),
|
|
868
|
+
python: /* @__PURE__ */ new Set(),
|
|
869
|
+
ruby: /* @__PURE__ */ new Set(),
|
|
870
|
+
envKeys: /* @__PURE__ */ new Set()
|
|
871
|
+
};
|
|
872
|
+
walkProjectFiles(installDir, (name, fullPath) => ingestFile(name, fullPath, signals), MAX_DEPTH);
|
|
873
|
+
return signals;
|
|
874
|
+
}
|
|
875
|
+
/**
|
|
876
|
+
* Route a file to the right parser BY NAME, reading its contents only when the
|
|
877
|
+
* name matches one of the ~6 manifests we care about. Checking the name first
|
|
878
|
+
* avoids slurping every file in the tree (lockfiles, binaries, assets) into
|
|
879
|
+
* memory just to discard it.
|
|
880
|
+
*/
|
|
881
|
+
function ingestFile(name, fullPath, signals) {
|
|
882
|
+
const ingest = ingestorFor(name);
|
|
883
|
+
if (!ingest) return;
|
|
884
|
+
const content = safeReadFile(fullPath);
|
|
885
|
+
if (content === null) return;
|
|
886
|
+
ingest(content, signals);
|
|
887
|
+
}
|
|
888
|
+
/** Pick the parser for a manifest filename, or null if it's not one we read. */
|
|
889
|
+
function ingestorFor(name) {
|
|
890
|
+
if (name === "package.json") return addNpmDeps;
|
|
891
|
+
if (name === "requirements.txt") return (c, s) => parseRequirementsTxt(c).forEach((d) => s.python.add(d));
|
|
892
|
+
if (name === "pyproject.toml") return (c, s) => parsePyprojectToml(c).forEach((d) => s.python.add(d));
|
|
893
|
+
if (name === "Pipfile") return (c, s) => parsePipfile(c).forEach((d) => s.python.add(d));
|
|
894
|
+
if (name === "Gemfile") return (c, s) => parseGemfile(c).forEach((g) => s.ruby.add(g));
|
|
895
|
+
if (name.startsWith(".env")) return (c, s) => parseEnvKeys(c).forEach((k) => s.envKeys.add(k));
|
|
896
|
+
return null;
|
|
897
|
+
}
|
|
898
|
+
function addNpmDeps(content, signals) {
|
|
899
|
+
try {
|
|
900
|
+
const pkg = JSON.parse(content);
|
|
901
|
+
for (const dep of Object.keys({
|
|
902
|
+
...pkg.dependencies,
|
|
903
|
+
...pkg.devDependencies
|
|
904
|
+
})) signals.npm.add(dep);
|
|
905
|
+
} catch (error) {
|
|
906
|
+
analytics.captureException(error instanceof Error ? error : new Error(String(error)), { step: "detectWarehouseSources.parsePackageJson" });
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
/** Extract gem names from `gem 'name'` declarations. */
|
|
910
|
+
function parseGemfile(content) {
|
|
911
|
+
const gems = [];
|
|
912
|
+
for (const match of content.matchAll(/^\s*gem\s+['"]([^'"]+)['"]/gm)) gems.push(match[1]);
|
|
913
|
+
return gems;
|
|
914
|
+
}
|
|
915
|
+
/** Extract KEY NAMES from a dotenv file. Values are intentionally discarded. */
|
|
916
|
+
function parseEnvKeys(content) {
|
|
917
|
+
const keys = [];
|
|
918
|
+
for (const line of content.split("\n")) {
|
|
919
|
+
const trimmed = line.trim();
|
|
920
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
921
|
+
const match = trimmed.match(/^(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=/);
|
|
922
|
+
if (match) keys.push(match[1]);
|
|
923
|
+
}
|
|
924
|
+
return keys;
|
|
925
|
+
}
|
|
926
|
+
//#endregion
|
|
927
|
+
//#region src/lib/programs/warehouse-source/detect.ts
|
|
928
|
+
/**
|
|
929
|
+
* Warehouse-source program detection step.
|
|
930
|
+
*
|
|
931
|
+
* Thin adapter over `detectWarehouseSources` that writes results into
|
|
932
|
+
* frameworkContext for the intro screen, plus the `[ABORT]` cases the
|
|
933
|
+
* data-warehouse-source-setup skill can emit.
|
|
934
|
+
*/
|
|
935
|
+
/** frameworkContext key holding the detected sources (set on success). */
|
|
936
|
+
const DETECTED_WAREHOUSE_SOURCES_KEY = "detectedWarehouseSources";
|
|
937
|
+
/**
|
|
938
|
+
* Read the detected sources out of frameworkContext. Single accessor shared by
|
|
939
|
+
* the intro screen and the prompt builder so the key + cast live in one place.
|
|
940
|
+
*/
|
|
941
|
+
function getDetectedWarehouseSources(session) {
|
|
942
|
+
return session.frameworkContext["detectedWarehouseSources"] ?? [];
|
|
943
|
+
}
|
|
944
|
+
/** `[ABORT] <reason>` cases the skill can emit. */
|
|
945
|
+
const WAREHOUSE_ABORT_CASES = [{
|
|
946
|
+
match: /^no data sources? detected\.?$/i,
|
|
947
|
+
message: "No data source detected",
|
|
948
|
+
body: "The agent could not confirm a data warehouse source to connect. Run this command from a project that uses a supported source (a database, Stripe, etc.).",
|
|
949
|
+
docsUrl: "https://posthog.com/docs/data-warehouse"
|
|
950
|
+
}, {
|
|
951
|
+
match: /^source creation failed\.?$/i,
|
|
952
|
+
message: "Source creation failed",
|
|
953
|
+
body: "PostHog could not create the data warehouse source with the credentials provided. Double-check the connection details and try again, or set the source up directly in the PostHog app.",
|
|
954
|
+
docsUrl: "https://posthog.com/docs/data-warehouse"
|
|
955
|
+
}];
|
|
956
|
+
/**
|
|
957
|
+
* Scan `session.installDir` for warehouse-source signals. Writes the detected
|
|
958
|
+
* sources (or a `detectError`) into frameworkContext for the intro screen.
|
|
959
|
+
*/
|
|
960
|
+
function detectWarehousePrerequisites(session, setFrameworkContext) {
|
|
961
|
+
const fail = (error) => setFrameworkContext("detectError", error);
|
|
962
|
+
const installDir = session.installDir;
|
|
963
|
+
if (!existsSync(installDir)) {
|
|
964
|
+
fail({
|
|
965
|
+
kind: "bad-directory",
|
|
966
|
+
path: installDir,
|
|
967
|
+
reason: "missing"
|
|
968
|
+
});
|
|
969
|
+
return;
|
|
970
|
+
}
|
|
971
|
+
try {
|
|
972
|
+
if (!statSync(installDir).isDirectory()) {
|
|
973
|
+
fail({
|
|
974
|
+
kind: "bad-directory",
|
|
975
|
+
path: installDir,
|
|
976
|
+
reason: "not-dir"
|
|
977
|
+
});
|
|
978
|
+
return;
|
|
979
|
+
}
|
|
980
|
+
} catch (error) {
|
|
981
|
+
analytics.captureException(error instanceof Error ? error : new Error(String(error)), {
|
|
982
|
+
step: "detectWarehousePrerequisites.stat",
|
|
983
|
+
path: installDir
|
|
984
|
+
});
|
|
985
|
+
fail({
|
|
986
|
+
kind: "bad-directory",
|
|
987
|
+
path: installDir,
|
|
988
|
+
reason: "unreadable"
|
|
989
|
+
});
|
|
990
|
+
return;
|
|
991
|
+
}
|
|
992
|
+
const sources = detectWarehouseSources(installDir);
|
|
993
|
+
if (sources.length === 0) {
|
|
994
|
+
fail({ kind: "no-sources" });
|
|
995
|
+
return;
|
|
996
|
+
}
|
|
997
|
+
setFrameworkContext(DETECTED_WAREHOUSE_SOURCES_KEY, sources);
|
|
998
|
+
}
|
|
999
|
+
//#endregion
|
|
1000
|
+
//#region src/lib/programs/warehouse-source/steps.ts
|
|
1001
|
+
const WAREHOUSE_SOURCE_PROGRAM = [
|
|
1002
|
+
{
|
|
1003
|
+
id: "detect",
|
|
1004
|
+
label: "Detecting data sources",
|
|
1005
|
+
onReady: (ctx) => detectWarehousePrerequisites(ctx.session, ctx.setFrameworkContext)
|
|
1006
|
+
},
|
|
1007
|
+
{
|
|
1008
|
+
id: "intro",
|
|
1009
|
+
label: "Welcome",
|
|
1010
|
+
screenId: "warehouse-intro",
|
|
1011
|
+
gate: (session) => session.setupConfirmed
|
|
1012
|
+
},
|
|
1013
|
+
{
|
|
1014
|
+
id: "auth",
|
|
1015
|
+
label: "Authentication",
|
|
1016
|
+
screenId: "auth",
|
|
1017
|
+
isComplete: (session) => session.credentials !== null
|
|
1018
|
+
},
|
|
1019
|
+
{
|
|
1020
|
+
id: "run",
|
|
1021
|
+
label: "Data warehouse",
|
|
1022
|
+
screenId: "run",
|
|
1023
|
+
isComplete: (session) => session.runPhase === "completed" || session.runPhase === "error"
|
|
1024
|
+
},
|
|
1025
|
+
{
|
|
1026
|
+
id: "outro",
|
|
1027
|
+
label: "Done",
|
|
1028
|
+
screenId: "outro",
|
|
1029
|
+
isComplete: (session) => session.outroDismissed
|
|
1030
|
+
},
|
|
1031
|
+
{
|
|
1032
|
+
id: "skills",
|
|
1033
|
+
label: "Skills",
|
|
1034
|
+
screenId: "keep-skills"
|
|
1035
|
+
}
|
|
1036
|
+
];
|
|
1037
|
+
//#endregion
|
|
1038
|
+
//#region src/lib/programs/warehouse-source/index.ts
|
|
1039
|
+
/**
|
|
1040
|
+
* Inject the detected sources (and their creation mode) into the prompt so the
|
|
1041
|
+
* skill knows what to set up. The *how* — in-CLI creation vs deep-link, field
|
|
1042
|
+
* collection, validation — lives in the skill, not here.
|
|
1043
|
+
*/
|
|
1044
|
+
function buildPrompt(session) {
|
|
1045
|
+
const sources = getDetectedWarehouseSources(session);
|
|
1046
|
+
if (sources.length === 0) return "Set up a data warehouse source for this project.";
|
|
1047
|
+
return [
|
|
1048
|
+
"The wizard detected the following data warehouse sources in this project:",
|
|
1049
|
+
...sources.map((s) => `- ${s.label} (kind: ${s.kind}, mode: ${s.mode}) — ${s.matchedSignal}`),
|
|
1050
|
+
"",
|
|
1051
|
+
"Set these up in PostHog following the skill instructions: create `in-cli` sources directly via the PostHog MCP after collecting credentials; for `deep-link` sources, provide the user the pre-filled new-source URL."
|
|
1052
|
+
].join("\n");
|
|
1053
|
+
}
|
|
1054
|
+
const warehouseSourceConfig = {
|
|
1055
|
+
command: "warehouse",
|
|
1056
|
+
description: "Detect and connect a data warehouse source (Postgres, Stripe, …)",
|
|
1057
|
+
id: "warehouse-source",
|
|
1058
|
+
skillId: "data-warehouse-source-setup",
|
|
1059
|
+
steps: WAREHOUSE_SOURCE_PROGRAM,
|
|
1060
|
+
getContentBlocks: getContentBlocks$2,
|
|
1061
|
+
reportFile: "posthog-warehouse-report.md",
|
|
1062
|
+
allowedTools: ["Agent"],
|
|
1063
|
+
run: (session) => Promise.resolve({
|
|
1064
|
+
skillId: "data-warehouse-source-setup",
|
|
1065
|
+
integrationLabel: "data-warehouse-source-setup",
|
|
1066
|
+
customPrompt: () => buildPrompt(session),
|
|
1067
|
+
successMessage: "Data warehouse source connected!",
|
|
1068
|
+
reportFile: "posthog-warehouse-report.md",
|
|
1069
|
+
docsUrl: "https://posthog.com/docs/data-warehouse",
|
|
1070
|
+
spinnerMessage: "Connecting your data source...",
|
|
1071
|
+
estimatedDurationMinutes: 5,
|
|
1072
|
+
abortCases: WAREHOUSE_ABORT_CASES
|
|
1073
|
+
}),
|
|
1074
|
+
requires: ["posthog-integration"]
|
|
1075
|
+
};
|
|
1076
|
+
//#endregion
|
|
511
1077
|
//#region src/lib/programs/agent-skill/steps.ts
|
|
512
1078
|
const AGENT_SKILL_STEPS = [
|
|
513
1079
|
{
|
|
@@ -846,7 +1412,7 @@ const EVENTS_AUDIT_SEED_CHECKS = [
|
|
|
846
1412
|
//#endregion
|
|
847
1413
|
//#region src/lib/programs/events-audit/index.ts
|
|
848
1414
|
const SETUP_REPORT_FILE = "posthog-events-audit-report.md";
|
|
849
|
-
const DOCS_URL$
|
|
1415
|
+
const DOCS_URL$3 = "https://posthog.com/docs/product-analytics/best-practices";
|
|
850
1416
|
const eventsAuditConfig = {
|
|
851
1417
|
command: "events-audit",
|
|
852
1418
|
description: "Audit PostHog event tracking in this project",
|
|
@@ -868,7 +1434,7 @@ const eventsAuditConfig = {
|
|
|
868
1434
|
successMessage: "Events audit complete! You can view the report at ./posthog-events-audit-report.md",
|
|
869
1435
|
estimatedDurationMinutes: 5,
|
|
870
1436
|
reportFile: SETUP_REPORT_FILE,
|
|
871
|
-
docsUrl: DOCS_URL$
|
|
1437
|
+
docsUrl: DOCS_URL$3,
|
|
872
1438
|
errorMessage: "Events audit failed",
|
|
873
1439
|
additionalFeatureQueue: session.additionalFeatureQueue,
|
|
874
1440
|
customPrompt: (ctx) => `Audit PostHog event capture in this project. Do not modify any project files — produce a read-only report only.
|
|
@@ -886,7 +1452,7 @@ Project context:
|
|
|
886
1452
|
message: "Your events audit was successful",
|
|
887
1453
|
reportFile: SETUP_REPORT_FILE,
|
|
888
1454
|
changes: [],
|
|
889
|
-
docsUrl: DOCS_URL$
|
|
1455
|
+
docsUrl: DOCS_URL$3,
|
|
890
1456
|
continueUrl: sess.signup && cloudUrl ? `${cloudUrl}/products?source=wizard` : void 0,
|
|
891
1457
|
dashboardUrl: sess.dashboardUrl ?? (cloudUrl ? `${cloudUrl}/dashboard` : void 0),
|
|
892
1458
|
notebookUrl: sess.notebookUrl ?? void 0
|
|
@@ -2415,15 +2981,15 @@ const getContentBlocks = (store) => pace([
|
|
|
2415
2981
|
]);
|
|
2416
2982
|
//#endregion
|
|
2417
2983
|
//#region src/lib/programs/error-tracking-upload-source-maps/index.ts
|
|
2418
|
-
const REPORT_FILE = "posthog-source-maps-report.md";
|
|
2419
|
-
const DOCS_URL = "https://posthog.com/docs/error-tracking/upload-source-maps";
|
|
2984
|
+
const REPORT_FILE$1 = "posthog-source-maps-report.md";
|
|
2985
|
+
const DOCS_URL$1 = "https://posthog.com/docs/error-tracking/upload-source-maps";
|
|
2420
2986
|
const errorTrackingUploadSourceMapsConfig = {
|
|
2421
2987
|
command: "upload-source-maps",
|
|
2422
2988
|
description: "Upload source maps to PostHog Error Tracking",
|
|
2423
2989
|
id: "error-tracking-upload-source-maps",
|
|
2424
2990
|
requiresAi: true,
|
|
2425
2991
|
steps: ERROR_TRACKING_UPLOAD_SOURCE_MAPS_PROGRAM,
|
|
2426
|
-
reportFile: REPORT_FILE,
|
|
2992
|
+
reportFile: REPORT_FILE$1,
|
|
2427
2993
|
getContentBlocks,
|
|
2428
2994
|
requires: ["posthog-integration"],
|
|
2429
2995
|
run: (session) => {
|
|
@@ -2433,8 +2999,8 @@ const errorTrackingUploadSourceMapsConfig = {
|
|
|
2433
2999
|
return Promise.resolve({
|
|
2434
3000
|
integrationLabel: "error-tracking-upload-source-maps",
|
|
2435
3001
|
successMessage: "Source maps wired up!",
|
|
2436
|
-
reportFile: REPORT_FILE,
|
|
2437
|
-
docsUrl: DOCS_URL,
|
|
3002
|
+
reportFile: REPORT_FILE$1,
|
|
3003
|
+
docsUrl: DOCS_URL$1,
|
|
2438
3004
|
spinnerMessage: "Wiring up source maps...",
|
|
2439
3005
|
estimatedDurationMinutes: 3,
|
|
2440
3006
|
abortCases: SOURCE_MAPS_ABORT_CASES,
|
|
@@ -2460,14 +3026,363 @@ const errorTrackingUploadSourceMapsConfig = {
|
|
|
2460
3026
|
return {
|
|
2461
3027
|
kind: "success",
|
|
2462
3028
|
message: "Source maps wired up!",
|
|
2463
|
-
reportFile: REPORT_FILE,
|
|
2464
|
-
docsUrl: DOCS_URL
|
|
3029
|
+
reportFile: REPORT_FILE$1,
|
|
3030
|
+
docsUrl: DOCS_URL$1
|
|
2465
3031
|
};
|
|
2466
3032
|
}
|
|
2467
3033
|
});
|
|
2468
3034
|
}
|
|
2469
3035
|
};
|
|
2470
3036
|
//#endregion
|
|
3037
|
+
//#region src/lib/programs/self-driving/detect.ts
|
|
3038
|
+
/**
|
|
3039
|
+
* Self-driving prerequisite detection + abort vocabulary.
|
|
3040
|
+
*
|
|
3041
|
+
* The only thing worth verifying before auth is local and cheap: that
|
|
3042
|
+
* `session.installDir` is a real, readable directory. We deliberately do
|
|
3043
|
+
* NOT require the base posthog-integration report to be present — it is a
|
|
3044
|
+
* report many users never commit, and `requires: ['posthog-integration']`
|
|
3045
|
+
* is metadata, not a hard runtime gate. Real readiness (integration state
|
|
3046
|
+
* + beta access) is established by the agent's STEP 1 Signals API probe at
|
|
3047
|
+
* the start of the run. The beta gates (the `product-autonomy` access flag
|
|
3048
|
+
* and `signals-scout` enrollment — PostHog-side flag names, unchanged by
|
|
3049
|
+
* the wizard-side "self-driving" rename) are PostHog-internal flags with no
|
|
3050
|
+
* customer-facing read API, which is why that probe lives in the run and
|
|
3051
|
+
* emits a structured `[ABORT]` when the product is not available.
|
|
3052
|
+
*/
|
|
3053
|
+
/**
|
|
3054
|
+
* `[ABORT] <reason>` cases the self-driving skill can emit. The
|
|
3055
|
+
* reason strings are part of the skill contract — the context-mill
|
|
3056
|
+
* `self-driving-setup` skill emits these exact strings.
|
|
3057
|
+
*/
|
|
3058
|
+
const SELF_DRIVING_ABORT_CASES = [
|
|
3059
|
+
{
|
|
3060
|
+
match: /^self-driving is not available for this project$/i,
|
|
3061
|
+
message: "PostHog Self-driving is not available for this project",
|
|
3062
|
+
body: "Self-driving is in beta and is enabled per team by PostHog. This project does not appear to have access yet. Reach out to your PostHog contact (or wizard@posthog.com) to join the beta, then run the wizard again."
|
|
3063
|
+
},
|
|
3064
|
+
{
|
|
3065
|
+
match: /^github connection declined$/i,
|
|
3066
|
+
message: "GitHub connection required",
|
|
3067
|
+
body: "Self-driving needs GitHub access to research issues in your code and open fixes, so setup cannot finish without it. Nothing was left half-configured. When you are ready to install the PostHog GitHub App, run the wizard again."
|
|
3068
|
+
},
|
|
3069
|
+
{
|
|
3070
|
+
match: /^requires-interactive-mode$/i,
|
|
3071
|
+
message: "Interactive terminal required",
|
|
3072
|
+
body: "Self-driving setup asks questions along the way (GitHub and issue trackers), so it needs an interactive terminal. Run the wizard outside CI / non-interactive mode."
|
|
3073
|
+
},
|
|
3074
|
+
{
|
|
3075
|
+
match: /^requirements-incomplete$/i,
|
|
3076
|
+
message: "Setup needs your input",
|
|
3077
|
+
body: "The wizard could not collect the answers this setup needs (the environment was non-interactive, or the question budget ran out). Nothing was left half-configured. Run the wizard again in an interactive terminal."
|
|
3078
|
+
}
|
|
3079
|
+
];
|
|
3080
|
+
/**
|
|
3081
|
+
* Verify `session.installDir` is a readable directory. Writes a
|
|
3082
|
+
* `SelfDrivingDetectError` to frameworkContext on failure — the intro
|
|
3083
|
+
* screen renders it and blocks.
|
|
3084
|
+
*/
|
|
3085
|
+
function detectSelfDrivingPrerequisites(session, setFrameworkContext) {
|
|
3086
|
+
const fail = (error) => setFrameworkContext("detectError", error);
|
|
3087
|
+
const installDir = session.installDir;
|
|
3088
|
+
if (!existsSync(installDir)) {
|
|
3089
|
+
fail({
|
|
3090
|
+
kind: "bad-directory",
|
|
3091
|
+
path: installDir,
|
|
3092
|
+
reason: "missing"
|
|
3093
|
+
});
|
|
3094
|
+
return;
|
|
3095
|
+
}
|
|
3096
|
+
try {
|
|
3097
|
+
if (!statSync(installDir).isDirectory()) {
|
|
3098
|
+
fail({
|
|
3099
|
+
kind: "bad-directory",
|
|
3100
|
+
path: installDir,
|
|
3101
|
+
reason: "not-dir"
|
|
3102
|
+
});
|
|
3103
|
+
return;
|
|
3104
|
+
}
|
|
3105
|
+
} catch {
|
|
3106
|
+
fail({
|
|
3107
|
+
kind: "bad-directory",
|
|
3108
|
+
path: installDir,
|
|
3109
|
+
reason: "unreadable"
|
|
3110
|
+
});
|
|
3111
|
+
return;
|
|
3112
|
+
}
|
|
3113
|
+
}
|
|
3114
|
+
//#endregion
|
|
3115
|
+
//#region src/lib/programs/self-driving/steps.ts
|
|
3116
|
+
const SELF_DRIVING_PROGRAM = [
|
|
3117
|
+
{
|
|
3118
|
+
id: "detect",
|
|
3119
|
+
label: "Detecting prerequisites",
|
|
3120
|
+
onReady: (ctx) => detectSelfDrivingPrerequisites(ctx.session, ctx.setFrameworkContext)
|
|
3121
|
+
},
|
|
3122
|
+
{
|
|
3123
|
+
id: "intro",
|
|
3124
|
+
label: "Welcome",
|
|
3125
|
+
screenId: "self-driving-intro",
|
|
3126
|
+
gate: (session) => session.setupConfirmed
|
|
3127
|
+
},
|
|
3128
|
+
HEALTH_CHECK_STEP,
|
|
3129
|
+
{
|
|
3130
|
+
id: "auth",
|
|
3131
|
+
label: "Authentication",
|
|
3132
|
+
screenId: "auth",
|
|
3133
|
+
isComplete: (session) => session.credentials !== null
|
|
3134
|
+
},
|
|
3135
|
+
{
|
|
3136
|
+
id: "run",
|
|
3137
|
+
label: "Self-driving",
|
|
3138
|
+
screenId: "run",
|
|
3139
|
+
isComplete: (session) => session.runPhase === "completed" || session.runPhase === "error"
|
|
3140
|
+
},
|
|
3141
|
+
{
|
|
3142
|
+
id: "outro",
|
|
3143
|
+
label: "Done",
|
|
3144
|
+
screenId: "outro",
|
|
3145
|
+
isComplete: (session) => session.outroDismissed
|
|
3146
|
+
}
|
|
3147
|
+
];
|
|
3148
|
+
//#endregion
|
|
3149
|
+
//#region src/lib/programs/self-driving/prompt.ts
|
|
3150
|
+
/**
|
|
3151
|
+
* Build the self-driving run prompt. The installed
|
|
3152
|
+
* `self-driving-setup` skill is the source of truth for the HOW of
|
|
3153
|
+
* every step (which MCP tools to call, which sources/scouts apply, how
|
|
3154
|
+
* to verify); this prompt carries the order, the wizard-specific
|
|
3155
|
+
* mechanics (wizard_ask, abort signals), and the project URLs.
|
|
3156
|
+
*/
|
|
3157
|
+
function buildSelfDrivingPrompt(ctx) {
|
|
3158
|
+
const uiHost = getUiHostFromHost(ctx.host).replace(/\/$/, "");
|
|
3159
|
+
const projectBase = `${uiHost}/project/${ctx.projectId}`;
|
|
3160
|
+
const integrationsSettingsUrl = `${projectBase}/settings/environment-integrations`;
|
|
3161
|
+
const orgAiSettingsUrl = `${uiHost}/settings/organization#organization-ai-consent`;
|
|
3162
|
+
const newWarehouseSourceUrl = `${projectBase}/pipeline/new/source`;
|
|
3163
|
+
const inboxUrl = `${projectBase}/inbox`;
|
|
3164
|
+
const optIn = (value) => value === true ? "ON" : value === false ? "OFF" : "unknown";
|
|
3165
|
+
const optIns = ctx.teamProductOptIns;
|
|
3166
|
+
return `You are setting up PostHog Self-driving for this project: you will enable the right signal sources, make sure GitHub is connected, tune the scout fleet, design custom scouts for what this product uniquely needs, and hand the user a configured inbox.
|
|
3167
|
+
|
|
3168
|
+
Project URLs:
|
|
3169
|
+
- Integrations settings (GitHub App install): ${integrationsSettingsUrl}
|
|
3170
|
+
- Organization AI settings: ${orgAiSettingsUrl}
|
|
3171
|
+
- New data warehouse source (Linear / Zendesk / GitHub issues / pganalyze): ${newWarehouseSourceUrl}
|
|
3172
|
+
- Self-driving inbox: ${inboxUrl}
|
|
3173
|
+
|
|
3174
|
+
Project state read at auth time (PostHog project settings — authoritative
|
|
3175
|
+
for whether a product is enabled, regardless of what this repo
|
|
3176
|
+
instruments; products are often instrumented from other repos or the
|
|
3177
|
+
snippet, so repo evidence may rule a product IN but never OUT):
|
|
3178
|
+
- Session replay recording: ${optIn(optIns?.sessionReplay)}
|
|
3179
|
+
- Exception autocapture (error tracking): ${optIn(optIns?.exceptionAutocapture)}
|
|
3180
|
+
- Surveys: ${optIn(optIns?.surveys)}
|
|
3181
|
+
|
|
3182
|
+
The installed skill is the source of truth for the HOW of every step:
|
|
3183
|
+
which MCP tools to call, which sources and scouts apply to this product,
|
|
3184
|
+
and how to verify each change. The STEPS below give the order and the
|
|
3185
|
+
wizard-specific mechanics — read the matching skill reference before
|
|
3186
|
+
doing the work, and do not invent steps the skill doesn't describe.
|
|
3187
|
+
|
|
3188
|
+
Before doing any work, create your FULL task list in a single TaskCreate
|
|
3189
|
+
call so the user can follow your progress in the TUI. Use exactly these
|
|
3190
|
+
tasks, in this order:
|
|
3191
|
+
1. Check Self-driving access
|
|
3192
|
+
2. Read project and current Self-driving state
|
|
3193
|
+
3. Connect GitHub (required)
|
|
3194
|
+
4. Enable signal sources
|
|
3195
|
+
5. Offer issue-tracker integrations
|
|
3196
|
+
6. Configure the scout fleet
|
|
3197
|
+
7. Design custom scouts
|
|
3198
|
+
8. Write report and hand off
|
|
3199
|
+
Drive the list with TaskUpdate — mark a task in_progress when you start
|
|
3200
|
+
it and completed when done. If a step turns out to be a no-op (e.g.
|
|
3201
|
+
GitHub is already connected), still mark its task completed.
|
|
3202
|
+
|
|
3203
|
+
Wizard mechanics:
|
|
3204
|
+
- Ask the user things ONLY with the wizard_ask MCP tool, and batch
|
|
3205
|
+
related questions (e.g. one multi-select for all issue trackers, not
|
|
3206
|
+
one ask per tool). The per-run ask budget is limited.
|
|
3207
|
+
- If wizard_ask is unavailable (CI / non-interactive), emit
|
|
3208
|
+
${AgentSignals.ABORT} requires-interactive-mode and halt.
|
|
3209
|
+
- When a step requires the user to do something in the browser, give
|
|
3210
|
+
them the exact URL inside the wizard_ask prompt text — do not try to
|
|
3211
|
+
open a browser yourself.
|
|
3212
|
+
- Emit ${AgentSignals.STATUS} lines as you complete each step so the
|
|
3213
|
+
user sees progress.
|
|
3214
|
+
|
|
3215
|
+
Follow these steps IN ORDER. Do not skip or reorder.
|
|
3216
|
+
|
|
3217
|
+
STEP 1 — Check Self-driving access. (skill: "Check access")
|
|
3218
|
+
Probe the Signals API as the skill describes. If the API is not
|
|
3219
|
+
available for this project (permission or not-found errors), emit
|
|
3220
|
+
${AgentSignals.ABORT} self-driving is not available for this project
|
|
3221
|
+
and halt.
|
|
3222
|
+
|
|
3223
|
+
STEP 2 — Read project and current Signals state. (skill: "Read context")
|
|
3224
|
+
If ./posthog-setup-report.md exists, read it as a strong hint for what
|
|
3225
|
+
THIS repo instruments — but it is often absent (users frequently don't
|
|
3226
|
+
commit it), so do NOT depend on it. Combine whatever you find with the
|
|
3227
|
+
project-state block above and the skill's server-side usage probes —
|
|
3228
|
+
repo evidence rules products in, never out. Do a light scan ONLY for
|
|
3229
|
+
what neither covers. List the currently enabled signal sources so every
|
|
3230
|
+
later write is idempotent.
|
|
3231
|
+
|
|
3232
|
+
STEP 3 — Connect GitHub. REQUIRED. (skill: "Connect GitHub")
|
|
3233
|
+
Signals cannot research or fix issues without code access. Check for
|
|
3234
|
+
an existing GitHub integration first; if absent, send the user to
|
|
3235
|
+
${integrationsSettingsUrl} via wizard_ask and verify the connection
|
|
3236
|
+
after they confirm. If the user cannot connect now, emit
|
|
3237
|
+
${AgentSignals.ABORT} github connection declined
|
|
3238
|
+
and halt — never finish setup without GitHub.
|
|
3239
|
+
|
|
3240
|
+
STEP 4 — Enable signal sources. (skill: "Enable sources")
|
|
3241
|
+
Enable the sources that match what this product actually uses, per
|
|
3242
|
+
the skill. Never enable a source for a tool the user hasn't
|
|
3243
|
+
confirmed they use.
|
|
3244
|
+
|
|
3245
|
+
STEP 5 — Offer issue-tracker integrations. (skill: "Connected tools")
|
|
3246
|
+
One batched multi-select wizard_ask for the external tools the skill
|
|
3247
|
+
lists. The run auto-connects the ones it can (GitHub Issues, and
|
|
3248
|
+
Linear via a one-click OAuth link), verifying each with a single
|
|
3249
|
+
silent check — never nudge. It arms the rest as dormant responders to
|
|
3250
|
+
finish later: for tools it can't auto-connect (Zendesk, pganalyze) it
|
|
3251
|
+
never sends the user to paste credentials and never re-prompts. Enable
|
|
3252
|
+
a source only for a tool the user picked.
|
|
3253
|
+
|
|
3254
|
+
STEP 6 — Configure the scout fleet. (skill: "Scouts")
|
|
3255
|
+
Materialize the fleet and disable the scouts whose product surface
|
|
3256
|
+
this project lacks, per the skill.
|
|
3257
|
+
|
|
3258
|
+
STEP 7 — Design custom scouts for this product. (skill: "Custom scouts")
|
|
3259
|
+
You are the only actor that has read this repo — turn that into
|
|
3260
|
+
coverage per the skill: a real gap analysis of the project's
|
|
3261
|
+
watchable surfaces against what the canonical fleet already covers,
|
|
3262
|
+
then custom scouts for the uncovered ones. Keep scout bodies
|
|
3263
|
+
high-level: describe the behavior and signal conditions to watch,
|
|
3264
|
+
referencing repo evidence by file/function name — never paste raw
|
|
3265
|
+
source, secrets, env values, or customer data into a scout body.
|
|
3266
|
+
Never edit canonical scout bodies. Propose all candidates in ONE
|
|
3267
|
+
batched wizard_ask
|
|
3268
|
+
before creating anything; the user declining everything (or finding
|
|
3269
|
+
no gap at all) is a valid outcome, not an abort. Mark the task
|
|
3270
|
+
completed either way.
|
|
3271
|
+
|
|
3272
|
+
STEP 8 — Write the report and hand off. (skill: "Report")
|
|
3273
|
+
Write the report per the skill, including follow-ups for anything
|
|
3274
|
+
deferred. Tell the user findings will start appearing in their inbox
|
|
3275
|
+
at ${inboxUrl} within about 30 minutes.`;
|
|
3276
|
+
}
|
|
3277
|
+
//#endregion
|
|
3278
|
+
//#region src/lib/programs/self-driving/content/tips.ts
|
|
3279
|
+
const SELF_DRIVING_TIPS = [
|
|
3280
|
+
{
|
|
3281
|
+
id: "what-is-a-signal-source",
|
|
3282
|
+
title: "What's a signal source?",
|
|
3283
|
+
description: "A signal source is a PostHog product or connected tool — errors, session replays, support, GitHub or Linear issues — that feeds findings into your Self-driving inbox."
|
|
3284
|
+
},
|
|
3285
|
+
{
|
|
3286
|
+
id: "what-is-a-scout",
|
|
3287
|
+
title: "What's a scout?",
|
|
3288
|
+
description: "Scouts are scheduled checks that scan your data and flag issues — a spike in errors, a dropping funnel — straight to your inbox."
|
|
3289
|
+
},
|
|
3290
|
+
{
|
|
3291
|
+
id: "findings-in-inbox",
|
|
3292
|
+
title: "Findings land in your inbox",
|
|
3293
|
+
description: "Once setup finishes, PostHog starts scanning within ~30 minutes and surfaces what it finds in your Self-driving inbox — grouped, researched, and ready to act on."
|
|
3294
|
+
}
|
|
3295
|
+
];
|
|
3296
|
+
const getTips = () => SELF_DRIVING_TIPS;
|
|
3297
|
+
//#endregion
|
|
3298
|
+
//#region src/lib/programs/self-driving/index.ts
|
|
3299
|
+
const SELF_DRIVING_SKILL_ID = "self-driving-setup";
|
|
3300
|
+
const REPORT_FILE = "posthog-self-driving-report.md";
|
|
3301
|
+
const DOCS_URL = "https://posthog.com/docs";
|
|
3302
|
+
const SUCCESS_MESSAGE = "Self-driving is on! PostHog will start scanning within ~30 minutes and surface findings in your inbox.";
|
|
3303
|
+
const WIZARD_MARKER = ".posthog-wizard";
|
|
3304
|
+
/**
|
|
3305
|
+
* Remove the installed setup skill. It is transient orchestration
|
|
3306
|
+
* knowledge (unlike integration skills such as the Next.js one, which
|
|
3307
|
+
* are worth keeping for the user's coding agents), so the program
|
|
3308
|
+
* cleans it up instead of showing the keep-skills prompt. Marker-
|
|
3309
|
+
* guarded: only directories the wizard installed are touched.
|
|
3310
|
+
*/
|
|
3311
|
+
async function removeInstalledSkill(installDir) {
|
|
3312
|
+
const skillDir = join(installDir, ".claude", "skills", SELF_DRIVING_SKILL_ID);
|
|
3313
|
+
try {
|
|
3314
|
+
await access(join(skillDir, WIZARD_MARKER));
|
|
3315
|
+
} catch {
|
|
3316
|
+
return;
|
|
3317
|
+
}
|
|
3318
|
+
await rm(skillDir, {
|
|
3319
|
+
recursive: true,
|
|
3320
|
+
force: true
|
|
3321
|
+
}).catch(() => void 0);
|
|
3322
|
+
}
|
|
3323
|
+
const run = {
|
|
3324
|
+
skillId: SELF_DRIVING_SKILL_ID,
|
|
3325
|
+
integrationLabel: SELF_DRIVING_SKILL_ID,
|
|
3326
|
+
customPrompt: buildSelfDrivingPrompt,
|
|
3327
|
+
successMessage: SUCCESS_MESSAGE,
|
|
3328
|
+
reportFile: REPORT_FILE,
|
|
3329
|
+
docsUrl: DOCS_URL,
|
|
3330
|
+
spinnerMessage: "Setting up PostHog Self-driving...",
|
|
3331
|
+
estimatedDurationMinutes: 10,
|
|
3332
|
+
abortCases: SELF_DRIVING_ABORT_CASES,
|
|
3333
|
+
maxQuestions: 13,
|
|
3334
|
+
richLinks: true,
|
|
3335
|
+
askTimeoutMs: 1800 * 1e3,
|
|
3336
|
+
postRun: async (session) => {
|
|
3337
|
+
await removeInstalledSkill(session.installDir);
|
|
3338
|
+
},
|
|
3339
|
+
buildOutroData: (_session, credentials) => {
|
|
3340
|
+
return {
|
|
3341
|
+
kind: "success",
|
|
3342
|
+
message: "Self-driving is on. PostHog is scanning your project — first findings hit your inbox within ~30 minutes.",
|
|
3343
|
+
primaryLink: {
|
|
3344
|
+
label: "Your Self-driving inbox",
|
|
3345
|
+
url: `${getUiHostFromHost(credentials.host).replace(/\/$/, "")}/project/${credentials.projectId}/inbox`
|
|
3346
|
+
},
|
|
3347
|
+
nextSteps: {
|
|
3348
|
+
heading: "In your inbox you can:",
|
|
3349
|
+
items: [
|
|
3350
|
+
"Review the findings PostHog surfaces",
|
|
3351
|
+
"Triage what matters and dismiss the noise",
|
|
3352
|
+
"Kick off fixes and open issues"
|
|
3353
|
+
]
|
|
3354
|
+
},
|
|
3355
|
+
reportFile: REPORT_FILE
|
|
3356
|
+
};
|
|
3357
|
+
}
|
|
3358
|
+
};
|
|
3359
|
+
const selfDrivingConfig = {
|
|
3360
|
+
...createSkillProgram({
|
|
3361
|
+
skillId: SELF_DRIVING_SKILL_ID,
|
|
3362
|
+
command: "self-driving",
|
|
3363
|
+
id: "self-driving",
|
|
3364
|
+
description: "Set up PostHog Self-driving for this project",
|
|
3365
|
+
integrationLabel: SELF_DRIVING_SKILL_ID,
|
|
3366
|
+
successMessage: SUCCESS_MESSAGE,
|
|
3367
|
+
reportFile: REPORT_FILE,
|
|
3368
|
+
docsUrl: DOCS_URL,
|
|
3369
|
+
spinnerMessage: "Setting up PostHog Self-driving...",
|
|
3370
|
+
estimatedDurationMinutes: 10,
|
|
3371
|
+
requires: ["posthog-integration"],
|
|
3372
|
+
abortCases: SELF_DRIVING_ABORT_CASES
|
|
3373
|
+
}),
|
|
3374
|
+
steps: SELF_DRIVING_PROGRAM,
|
|
3375
|
+
run,
|
|
3376
|
+
getTips,
|
|
3377
|
+
getContentBlocks: (store) => {
|
|
3378
|
+
const blocks = getContentBlocks$2(store);
|
|
3379
|
+
return blocks.map((b, i) => i === blocks.length - 1 && typeof b === "object" ? {
|
|
3380
|
+
...b,
|
|
3381
|
+
pause: 5e3
|
|
3382
|
+
} : b);
|
|
3383
|
+
}
|
|
3384
|
+
};
|
|
3385
|
+
//#endregion
|
|
2471
3386
|
//#region src/lib/programs/mcp/index.ts
|
|
2472
3387
|
const mcpAddConfig = {
|
|
2473
3388
|
id: "mcp-add",
|
|
@@ -2583,12 +3498,14 @@ const agentSkillConfig = {
|
|
|
2583
3498
|
const PROGRAM_REGISTRY = [
|
|
2584
3499
|
posthogIntegrationConfig,
|
|
2585
3500
|
revenueAnalyticsConfig,
|
|
3501
|
+
warehouseSourceConfig,
|
|
2586
3502
|
errorTrackingUploadSourceMapsConfig,
|
|
2587
3503
|
auditConfig,
|
|
2588
3504
|
eventsAuditConfig,
|
|
2589
3505
|
posthogDoctorConfig,
|
|
2590
3506
|
webAnalyticsDoctorConfig,
|
|
2591
3507
|
migrationConfig,
|
|
3508
|
+
selfDrivingConfig,
|
|
2592
3509
|
agentSkillConfig,
|
|
2593
3510
|
mcpAddConfig,
|
|
2594
3511
|
mcpRemoveConfig,
|
|
@@ -2603,12 +3520,14 @@ const PROGRAM_REGISTRY = [
|
|
|
2603
3520
|
const Program = {
|
|
2604
3521
|
PostHogIntegration: posthogIntegrationConfig.id,
|
|
2605
3522
|
RevenueAnalyticsSetup: revenueAnalyticsConfig.id,
|
|
3523
|
+
WarehouseSource: warehouseSourceConfig.id,
|
|
2606
3524
|
ErrorTrackingUploadSourceMaps: errorTrackingUploadSourceMapsConfig.id,
|
|
2607
3525
|
Migration: migrationConfig.id,
|
|
2608
3526
|
Audit: auditConfig.id,
|
|
2609
3527
|
EventsAudit: eventsAuditConfig.id,
|
|
2610
3528
|
PosthogDoctor: posthogDoctorConfig.id,
|
|
2611
3529
|
WebAnalyticsDoctor: webAnalyticsDoctorConfig.id,
|
|
3530
|
+
SelfDriving: selfDrivingConfig.id,
|
|
2612
3531
|
AgentSkill: agentSkillConfig.id,
|
|
2613
3532
|
McpAdd: mcpAddConfig.id,
|
|
2614
3533
|
McpRemove: mcpRemoveConfig.id,
|
|
@@ -2653,7 +3572,7 @@ function runMcpAdd(argv) {
|
|
|
2653
3572
|
const debug = argv.debug;
|
|
2654
3573
|
const localMcp = argv.local;
|
|
2655
3574
|
try {
|
|
2656
|
-
const { startTUI } = await import("./start-tui-
|
|
3575
|
+
const { startTUI } = await import("./start-tui-Cbw0kVr3.js");
|
|
2657
3576
|
const { buildSession } = await import("./wizard-session-wPJtNl4c.js");
|
|
2658
3577
|
const tui = startTUI(VERSION, Program.McpAdd);
|
|
2659
3578
|
tui.store.session = buildSession({
|
|
@@ -2665,7 +3584,7 @@ function runMcpAdd(argv) {
|
|
|
2665
3584
|
} catch (error) {
|
|
2666
3585
|
if (!isTUIUnavailable(error)) throw error;
|
|
2667
3586
|
setUI(new LoggingUI());
|
|
2668
|
-
const { addMCPServerToClientsStep } = await import("./add-mcp-server-to-clients-
|
|
3587
|
+
const { addMCPServerToClientsStep } = await import("./add-mcp-server-to-clients-D2XNlVgw.js").then((n) => n.r);
|
|
2669
3588
|
await addMCPServerToClientsStep({
|
|
2670
3589
|
local: localMcp,
|
|
2671
3590
|
features,
|
|
@@ -2704,7 +3623,7 @@ function runMcpRemove(argv) {
|
|
|
2704
3623
|
const debug = argv.debug;
|
|
2705
3624
|
const localMcp = argv.local;
|
|
2706
3625
|
try {
|
|
2707
|
-
const { startTUI } = await import("./start-tui-
|
|
3626
|
+
const { startTUI } = await import("./start-tui-Cbw0kVr3.js");
|
|
2708
3627
|
const { buildSession } = await import("./wizard-session-wPJtNl4c.js");
|
|
2709
3628
|
const tui = startTUI(VERSION, Program.McpRemove);
|
|
2710
3629
|
tui.store.session = buildSession({
|
|
@@ -2713,7 +3632,7 @@ function runMcpRemove(argv) {
|
|
|
2713
3632
|
});
|
|
2714
3633
|
} catch {
|
|
2715
3634
|
setUI(new LoggingUI());
|
|
2716
|
-
const { removeMCPServerFromClientsStep } = await import("./add-mcp-server-to-clients-
|
|
3635
|
+
const { removeMCPServerFromClientsStep } = await import("./add-mcp-server-to-clients-D2XNlVgw.js").then((n) => n.r);
|
|
2717
3636
|
await removeMCPServerFromClientsStep({ local: localMcp });
|
|
2718
3637
|
}
|
|
2719
3638
|
})();
|
|
@@ -2735,7 +3654,7 @@ function runMcpTutorial(argv) {
|
|
|
2735
3654
|
const debug = argv.debug;
|
|
2736
3655
|
const localMcp = argv.local;
|
|
2737
3656
|
try {
|
|
2738
|
-
const { startTUI } = await import("./start-tui-
|
|
3657
|
+
const { startTUI } = await import("./start-tui-Cbw0kVr3.js");
|
|
2739
3658
|
const { buildSession } = await import("./wizard-session-wPJtNl4c.js");
|
|
2740
3659
|
const tui = startTUI(VERSION, Program.McpTutorial);
|
|
2741
3660
|
tui.store.session = buildSession({
|
|
@@ -2790,7 +3709,7 @@ function runWizard(config, options) {
|
|
|
2790
3709
|
(async () => {
|
|
2791
3710
|
try {
|
|
2792
3711
|
const installDir = options.installDir || process.cwd();
|
|
2793
|
-
const { startTUI } = await import("./start-tui-
|
|
3712
|
+
const { startTUI } = await import("./start-tui-Cbw0kVr3.js");
|
|
2794
3713
|
const { buildSession, RunPhase } = await import("./wizard-session-wPJtNl4c.js");
|
|
2795
3714
|
const { TaskStreamPush } = await import("./task-stream-BQNSp0qR.js");
|
|
2796
3715
|
const { PostHogDestination } = await import("./posthog-Cr37rnla.js");
|
|
@@ -2846,7 +3765,7 @@ function runWizard(config, options) {
|
|
|
2846
3765
|
await activeTui.store.getGate("health-check");
|
|
2847
3766
|
const skipAgent = config.run == null;
|
|
2848
3767
|
if (skipAgent) {
|
|
2849
|
-
const { getOrAskForProjectData } = await import("./setup-utils-
|
|
3768
|
+
const { getOrAskForProjectData } = await import("./setup-utils-CjKjaKcG.js").then((n) => n.r);
|
|
2850
3769
|
const { projectApiKey, host, accessToken, projectId } = await getOrAskForProjectData({
|
|
2851
3770
|
signup: session.signup,
|
|
2852
3771
|
ci: session.ci,
|
|
@@ -2861,7 +3780,7 @@ function runWizard(config, options) {
|
|
|
2861
3780
|
projectId
|
|
2862
3781
|
});
|
|
2863
3782
|
} else {
|
|
2864
|
-
const { runAgent } = await import("./agent-runner-
|
|
3783
|
+
const { runAgent } = await import("./agent-runner-D7hIITUf.js");
|
|
2865
3784
|
await runAgent(config, activeTui.store.session);
|
|
2866
3785
|
}
|
|
2867
3786
|
const isDone = () => skipAgent ? activeTui.store.session.outroDismissed : activeTui.store.session.skillsComplete;
|
|
@@ -2938,10 +3857,10 @@ function runWizardCI(config, options) {
|
|
|
2938
3857
|
(async () => {
|
|
2939
3858
|
const path = await import("path");
|
|
2940
3859
|
const { buildSession } = await import("./wizard-session-wPJtNl4c.js");
|
|
2941
|
-
const { readEnvironment } = await import("./environment-
|
|
3860
|
+
const { readEnvironment } = await import("./environment-CFXsie0G.js").then((n) => n.t);
|
|
2942
3861
|
const { readApiKeyFromEnv } = await import("./env-api-key-MlzJYAvt.js").then((n) => n.t);
|
|
2943
|
-
const { configureLogFileFromEnvironment, logToFile } = await import("./debug-
|
|
2944
|
-
const { wizardAbort, WizardError } = await import("./wizard-abort-
|
|
3862
|
+
const { configureLogFileFromEnvironment, logToFile } = await import("./debug-CDLYQOQh.js");
|
|
3863
|
+
const { wizardAbort, WizardError } = await import("./wizard-abort-BPr0xo7i.js");
|
|
2945
3864
|
configureLogFileFromEnvironment();
|
|
2946
3865
|
const env = readEnvironment();
|
|
2947
3866
|
const apiKey = options.apiKey ?? readApiKeyFromEnv() ?? void 0;
|
|
@@ -2992,7 +3911,7 @@ function runWizardCI(config, options) {
|
|
|
2992
3911
|
})
|
|
2993
3912
|
});
|
|
2994
3913
|
}
|
|
2995
|
-
const { runAgent } = await import("./agent-runner-
|
|
3914
|
+
const { runAgent } = await import("./agent-runner-D7hIITUf.js");
|
|
2996
3915
|
await runAgent(config, session);
|
|
2997
3916
|
} catch (error) {
|
|
2998
3917
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
@@ -3210,6 +4129,34 @@ const PromptLabel = ({ message }) => {
|
|
|
3210
4129
|
}) });
|
|
3211
4130
|
};
|
|
3212
4131
|
//#endregion
|
|
4132
|
+
//#region src/ui/tui/primitives/ConfirmButton.tsx
|
|
4133
|
+
/**
|
|
4134
|
+
* ConfirmButton — the confirm row used to submit a selection.
|
|
4135
|
+
*
|
|
4136
|
+
* Pure render. Multi-select menus (PickerMenu mode="multi", GroupedPickerMenu)
|
|
4137
|
+
* append this below their options as the final focusable row: the user toggles
|
|
4138
|
+
* options with enter, then arrows down onto this row and presses enter to
|
|
4139
|
+
* submit. This replaces the older "enter anywhere submits" pattern, which
|
|
4140
|
+
* confused people who expected enter to toggle the focused item.
|
|
4141
|
+
*
|
|
4142
|
+
* Renders flat, mirroring the option rows — a focus triangle and the label,
|
|
4143
|
+
* accent and bold when focused, dimmed otherwise — so it lines up under the
|
|
4144
|
+
* options instead of sitting in a separate boxed target.
|
|
4145
|
+
*/
|
|
4146
|
+
const ConfirmButton = ({ label = "Confirm", focused, count }) => {
|
|
4147
|
+
const text = count && count > 0 ? `${label} (${count})` : label;
|
|
4148
|
+
return /* @__PURE__ */ jsxs(Text, {
|
|
4149
|
+
color: focused ? Colors.accent : void 0,
|
|
4150
|
+
bold: focused,
|
|
4151
|
+
dimColor: !focused,
|
|
4152
|
+
children: [
|
|
4153
|
+
focused ? Icons.triangleSmallRight : " ",
|
|
4154
|
+
" ",
|
|
4155
|
+
text
|
|
4156
|
+
]
|
|
4157
|
+
});
|
|
4158
|
+
};
|
|
4159
|
+
//#endregion
|
|
3213
4160
|
//#region src/ui/tui/hooks/keyboard-hints-utils.ts
|
|
3214
4161
|
/** Default priorities by key type. */
|
|
3215
4162
|
const DEFAULT_PRIORITY = {
|
|
@@ -3345,8 +4292,10 @@ function useKeyBindings(id, bindings) {
|
|
|
3345
4292
|
//#region src/ui/tui/primitives/PickerMenu.tsx
|
|
3346
4293
|
/**
|
|
3347
4294
|
* PickerMenu — Single and multi select.
|
|
3348
|
-
* Single mode: custom renderer with small triangle indicator.
|
|
3349
|
-
* Multi mode: checkbox glyphs with
|
|
4295
|
+
* Single mode: custom renderer with small triangle indicator; enter selects.
|
|
4296
|
+
* Multi mode: checkbox glyphs toggled with enter, plus a focusable
|
|
4297
|
+
* Confirm button below the options. The cursor moves onto the button and
|
|
4298
|
+
* enter submits — see MultiPickerMenu for the rationale.
|
|
3350
4299
|
*
|
|
3351
4300
|
* Key bindings are declared via useKeyBindings, which auto-registers
|
|
3352
4301
|
* hints in the KeyboardHintsBar.
|
|
@@ -3372,6 +4321,12 @@ function firstEnabled(options) {
|
|
|
3372
4321
|
const idx = options.findIndex((o) => !o.disabled);
|
|
3373
4322
|
return idx === -1 ? 0 : idx;
|
|
3374
4323
|
}
|
|
4324
|
+
/** Index of the last enabled option, for wrapping from the button onto
|
|
4325
|
+
* the bottom of the grid. */
|
|
4326
|
+
function lastEnabled(options) {
|
|
4327
|
+
for (let i = options.length - 1; i >= 0; i--) if (!options[i]?.disabled) return i;
|
|
4328
|
+
return options.length - 1;
|
|
4329
|
+
}
|
|
3375
4330
|
const PickerMenu = ({ message, options, mode = "single", centered = false, columns = 1, optionMarginBottom = 0, onSelect }) => {
|
|
3376
4331
|
if (mode === "multi") return /* @__PURE__ */ jsx(MultiPickerMenu, {
|
|
3377
4332
|
message,
|
|
@@ -3475,60 +4430,90 @@ const SinglePickerMenu = ({ message, options, centered = false, columns = 1, opt
|
|
|
3475
4430
|
})]
|
|
3476
4431
|
});
|
|
3477
4432
|
};
|
|
3478
|
-
/**
|
|
4433
|
+
/**
|
|
4434
|
+
* Custom multi-select with checkbox glyphs and accent highlight.
|
|
4435
|
+
*
|
|
4436
|
+
* Interaction model (shared with GroupedPickerMenu):
|
|
4437
|
+
* - \u2191\u2193 move the cursor through the options AND onto the Confirm button,
|
|
4438
|
+
* which lives just past the last option.
|
|
4439
|
+
* - enter toggles the focused option (no more "space toggles but enter
|
|
4440
|
+
* advances" split that tripped people up). Space is kept as an
|
|
4441
|
+
* undocumented alias, but the hints bar advertises only enter.
|
|
4442
|
+
* - moving onto the Confirm button and pressing enter submits the
|
|
4443
|
+
* current selection.
|
|
4444
|
+
*/
|
|
3479
4445
|
const MultiPickerMenu = ({ message, options, centered = false, columns = 1, optionMarginBottom = 0, onSelect }) => {
|
|
3480
4446
|
const [focused, setFocused] = useState(() => firstEnabled(options));
|
|
4447
|
+
const [onButton, setOnButton] = useState(false);
|
|
3481
4448
|
const [selected, setSelected] = useState(/* @__PURE__ */ new Set());
|
|
3482
4449
|
const rows = Math.ceil(options.length / columns);
|
|
3483
4450
|
useEffect(() => {
|
|
3484
4451
|
if (focused >= options.length || options[focused]?.disabled) setFocused(firstEnabled(options));
|
|
3485
4452
|
}, [options, focused]);
|
|
3486
|
-
const
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
4453
|
+
const confirm = () => {
|
|
4454
|
+
onSelect([...selected].sort((a, b) => a - b).map((i) => options[i].value));
|
|
4455
|
+
};
|
|
4456
|
+
const bindings = [{
|
|
4457
|
+
match: ["upArrow", "downArrow"],
|
|
4458
|
+
label: "↑↓",
|
|
4459
|
+
action: "navigate",
|
|
4460
|
+
handler: (_input, key) => {
|
|
4461
|
+
if (key.upArrow) {
|
|
4462
|
+
if (onButton) {
|
|
4463
|
+
setOnButton(false);
|
|
4464
|
+
setFocused(lastEnabled(options));
|
|
4465
|
+
return;
|
|
4466
|
+
}
|
|
4467
|
+
const col = Math.floor(focused / rows);
|
|
4468
|
+
let r = focused % rows - 1;
|
|
4469
|
+
while (r >= 0 && options[col * rows + r]?.disabled) r--;
|
|
4470
|
+
if (r >= 0) setFocused(col * rows + r);
|
|
4471
|
+
else setOnButton(true);
|
|
3494
4472
|
}
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
if (options[focused]?.exclusive) return new Set([focused]);
|
|
3509
|
-
for (const i of next) if (options[i]?.exclusive) next.delete(i);
|
|
3510
|
-
next.add(focused);
|
|
3511
|
-
return next;
|
|
3512
|
-
});
|
|
4473
|
+
if (key.downArrow) {
|
|
4474
|
+
if (onButton) {
|
|
4475
|
+
setOnButton(false);
|
|
4476
|
+
setFocused(firstEnabled(options));
|
|
4477
|
+
return;
|
|
4478
|
+
}
|
|
4479
|
+
const col = Math.floor(focused / rows);
|
|
4480
|
+
const row = focused % rows;
|
|
4481
|
+
const colLen = Math.min(rows, options.length - col * rows);
|
|
4482
|
+
let r = row + 1;
|
|
4483
|
+
while (r < colLen && options[col * rows + r]?.disabled) r++;
|
|
4484
|
+
if (r < colLen) setFocused(col * rows + r);
|
|
4485
|
+
else setOnButton(true);
|
|
3513
4486
|
}
|
|
3514
|
-
}
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
} else onSelect([...selected].sort().map((i) => options[i].value));
|
|
4487
|
+
}
|
|
4488
|
+
}, {
|
|
4489
|
+
match: ["space", "return"],
|
|
4490
|
+
label: "enter",
|
|
4491
|
+
action: "select",
|
|
4492
|
+
handler: () => {
|
|
4493
|
+
if (onButton) {
|
|
4494
|
+
confirm();
|
|
4495
|
+
return;
|
|
3524
4496
|
}
|
|
4497
|
+
if (options[focused]?.disabled) return;
|
|
4498
|
+
setSelected((prev) => {
|
|
4499
|
+
const next = new Set(prev);
|
|
4500
|
+
if (next.has(focused)) {
|
|
4501
|
+
next.delete(focused);
|
|
4502
|
+
return next;
|
|
4503
|
+
}
|
|
4504
|
+
if (options[focused]?.exclusive) return new Set([focused]);
|
|
4505
|
+
for (const i of next) if (options[i]?.exclusive) next.delete(i);
|
|
4506
|
+
next.add(focused);
|
|
4507
|
+
return next;
|
|
4508
|
+
});
|
|
3525
4509
|
}
|
|
3526
|
-
];
|
|
4510
|
+
}];
|
|
3527
4511
|
if (columns > 1) bindings.splice(1, 0, {
|
|
3528
4512
|
match: ["leftArrow", "rightArrow"],
|
|
3529
4513
|
label: "←→",
|
|
3530
4514
|
action: "navigate",
|
|
3531
4515
|
handler: (_input, key) => {
|
|
4516
|
+
if (onButton) return;
|
|
3532
4517
|
const col = Math.floor(focused / rows);
|
|
3533
4518
|
const row = focused % rows;
|
|
3534
4519
|
let next = focused;
|
|
@@ -3550,43 +4535,65 @@ const MultiPickerMenu = ({ message, options, centered = false, columns = 1, opti
|
|
|
3550
4535
|
return /* @__PURE__ */ jsxs(Box, {
|
|
3551
4536
|
flexDirection: "column",
|
|
3552
4537
|
alignItems: centered ? "center" : void 0,
|
|
3553
|
-
children: [
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
children:
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
children:
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
4538
|
+
children: [
|
|
4539
|
+
/* @__PURE__ */ jsx(PromptLabel, { message }),
|
|
4540
|
+
/* @__PURE__ */ jsx(Box, {
|
|
4541
|
+
flexDirection: "row",
|
|
4542
|
+
gap: 4,
|
|
4543
|
+
marginLeft: centered ? 0 : 2,
|
|
4544
|
+
marginTop: 1,
|
|
4545
|
+
children: columnArrays.map((colOpts, colIdx) => /* @__PURE__ */ jsx(Box, {
|
|
4546
|
+
flexDirection: "column",
|
|
4547
|
+
children: colOpts.map((opt, rowIdx) => {
|
|
4548
|
+
const flatIdx = colIdx * rows + rowIdx;
|
|
4549
|
+
const isFocused = !onButton && flatIdx === focused;
|
|
4550
|
+
const isSelected = selected.has(flatIdx);
|
|
4551
|
+
const label = opt.hint ? `${opt.label} (${opt.hint})` : opt.label;
|
|
4552
|
+
const checkbox = isSelected ? Icons.squareFilled : Icons.squareOpen;
|
|
4553
|
+
return /* @__PURE__ */ jsxs(Box, {
|
|
4554
|
+
flexDirection: "column",
|
|
4555
|
+
marginBottom: optionMarginBottom,
|
|
4556
|
+
children: [/* @__PURE__ */ jsxs(Box, {
|
|
4557
|
+
gap: 1,
|
|
4558
|
+
children: [
|
|
4559
|
+
/* @__PURE__ */ jsx(Text, {
|
|
4560
|
+
color: isSelected ? "white" : Colors.muted,
|
|
4561
|
+
dimColor: !isFocused && !isSelected,
|
|
4562
|
+
children: checkbox
|
|
4563
|
+
}),
|
|
4564
|
+
opt.icon && /* @__PURE__ */ jsx(Text, {
|
|
4565
|
+
color: opt.icon.color,
|
|
4566
|
+
children: opt.icon.glyph
|
|
4567
|
+
}),
|
|
4568
|
+
/* @__PURE__ */ jsx(Text, {
|
|
4569
|
+
color: opt.disabled ? Colors.muted : isFocused ? Colors.accent : void 0,
|
|
4570
|
+
bold: isFocused && !opt.disabled,
|
|
4571
|
+
dimColor: !isFocused || opt.disabled,
|
|
4572
|
+
children: label
|
|
4573
|
+
})
|
|
4574
|
+
]
|
|
4575
|
+
}), opt.description && /* @__PURE__ */ jsx(Box, {
|
|
4576
|
+
marginLeft: 4,
|
|
4577
|
+
width: 56,
|
|
4578
|
+
children: /* @__PURE__ */ jsx(Text, {
|
|
4579
|
+
dimColor: true,
|
|
4580
|
+
wrap: "wrap",
|
|
4581
|
+
children: opt.description
|
|
4582
|
+
})
|
|
4583
|
+
})]
|
|
4584
|
+
}, flatIdx);
|
|
4585
|
+
})
|
|
4586
|
+
}, colIdx))
|
|
4587
|
+
}),
|
|
4588
|
+
/* @__PURE__ */ jsx(Box, {
|
|
4589
|
+
marginTop: 1,
|
|
4590
|
+
marginLeft: centered ? 0 : 2,
|
|
4591
|
+
children: /* @__PURE__ */ jsx(ConfirmButton, {
|
|
4592
|
+
focused: onButton,
|
|
4593
|
+
count: selected.size
|
|
3587
4594
|
})
|
|
3588
|
-
}
|
|
3589
|
-
|
|
4595
|
+
})
|
|
4596
|
+
]
|
|
3590
4597
|
});
|
|
3591
4598
|
};
|
|
3592
4599
|
//#endregion
|
|
@@ -3771,7 +4778,7 @@ async function runDoctorCI(options) {
|
|
|
3771
4778
|
getUI().intro("Welcome to the PostHog setup wizard");
|
|
3772
4779
|
getUI().log.info("Running posthog-doctor in CI mode");
|
|
3773
4780
|
try {
|
|
3774
|
-
const { getOrAskForProjectData } = await import("./setup-utils-
|
|
4781
|
+
const { getOrAskForProjectData } = await import("./setup-utils-CjKjaKcG.js").then((n) => n.r);
|
|
3775
4782
|
const { host, accessToken, projectId } = await getOrAskForProjectData({
|
|
3776
4783
|
signup: false,
|
|
3777
4784
|
ci: true,
|
|
@@ -3788,7 +4795,7 @@ async function runDoctorCI(options) {
|
|
|
3788
4795
|
for (const issue of sorted) getUI().log.info(` • [${issue.severity}] ${getKindMeta(issue.kind).title}`);
|
|
3789
4796
|
process.exit(1);
|
|
3790
4797
|
} catch (error) {
|
|
3791
|
-
const { ApiError } = await import("./api-
|
|
4798
|
+
const { ApiError } = await import("./api-2zPZQONC.js").then((n) => n.n);
|
|
3792
4799
|
const message = error instanceof ApiError && error.statusCode === 401 ? "Your PostHog API key is invalid or expired." : error instanceof Error ? error.message : String(error);
|
|
3793
4800
|
getUI().log.error(`Doctor failed: ${message}`);
|
|
3794
4801
|
process.exit(1);
|
|
@@ -3836,6 +4843,39 @@ const migrateCommand = nativeCommandFactory(migrationConfig);
|
|
|
3836
4843
|
*/
|
|
3837
4844
|
const revenueCommand = nativeCommandFactory(revenueAnalyticsConfig);
|
|
3838
4845
|
//#endregion
|
|
4846
|
+
//#region src/commands/warehouse.ts
|
|
4847
|
+
/**
|
|
4848
|
+
* `wizard warehouse` — detect and connect a data warehouse source.
|
|
4849
|
+
*
|
|
4850
|
+
* Mirrors `revenue-analytics`: flat skill command driven by the
|
|
4851
|
+
* warehouse-source program.
|
|
4852
|
+
*/
|
|
4853
|
+
const warehouseCommand = nativeCommandFactory(warehouseSourceConfig);
|
|
4854
|
+
//#endregion
|
|
4855
|
+
//#region src/commands/self-driving.ts
|
|
4856
|
+
const selfDrivingCommand = {
|
|
4857
|
+
name: "self-driving",
|
|
4858
|
+
description: selfDrivingConfig.description,
|
|
4859
|
+
options: {
|
|
4860
|
+
...skillProgramOptions,
|
|
4861
|
+
...selfDrivingConfig.cliOptions ?? {}
|
|
4862
|
+
},
|
|
4863
|
+
check: (argv) => {
|
|
4864
|
+
if (argv.signup) throw new Error("`self-driving` cannot run with --signup. It builds on an existing PostHog integration — run the base `wizard` to create your account and set up PostHog first, then run `wizard self-driving`.");
|
|
4865
|
+
if (argv.ci) throw new Error("`self-driving` cannot run in CI mode — it requires interactive steps (GitHub connect, issue-tracker selection, custom-scout approval).");
|
|
4866
|
+
return true;
|
|
4867
|
+
},
|
|
4868
|
+
handler: (argv) => {
|
|
4869
|
+
const extras = selfDrivingConfig.mapCliOptions?.(argv) ?? {};
|
|
4870
|
+
const options = {
|
|
4871
|
+
...argv,
|
|
4872
|
+
...extras
|
|
4873
|
+
};
|
|
4874
|
+
if (options.ci) runWizardCI(selfDrivingConfig, options);
|
|
4875
|
+
else runWizard(selfDrivingConfig, options);
|
|
4876
|
+
}
|
|
4877
|
+
};
|
|
4878
|
+
//#endregion
|
|
3839
4879
|
//#region src/commands/slack.ts
|
|
3840
4880
|
const slackCommand = {
|
|
3841
4881
|
name: "slack",
|
|
@@ -3851,7 +4891,7 @@ function runSlackConnect(argv) {
|
|
|
3851
4891
|
(async () => {
|
|
3852
4892
|
const debug = argv.debug;
|
|
3853
4893
|
try {
|
|
3854
|
-
const { startTUI } = await import("./start-tui-
|
|
4894
|
+
const { startTUI } = await import("./start-tui-Cbw0kVr3.js");
|
|
3855
4895
|
const { buildSession } = await import("./wizard-session-wPJtNl4c.js");
|
|
3856
4896
|
const tui = startTUI(VERSION, Program.SlackConnect);
|
|
3857
4897
|
tui.store.session = buildSession({ debug });
|
|
@@ -4228,8 +5268,8 @@ function resolveInstallDir() {
|
|
|
4228
5268
|
if (inline) return inline.slice(14);
|
|
4229
5269
|
return process.env.POSTHOG_WIZARD_INSTALL_DIR ?? process.cwd();
|
|
4230
5270
|
}
|
|
4231
|
-
Wizard.use(basicIntegrationCommand).use(mcpCommand).use(cliCommand).use(auditCommand).use(doctorCommand).use(migrateCommand).use(revenueCommand).use(slackCommand).use(uploadSourcemapsCommand).use(skillCommand).init();
|
|
5271
|
+
Wizard.use(basicIntegrationCommand).use(mcpCommand).use(cliCommand).use(auditCommand).use(doctorCommand).use(migrateCommand).use(revenueCommand).use(warehouseCommand).use(selfDrivingCommand).use(slackCommand).use(uploadSourcemapsCommand).use(skillCommand).init();
|
|
4232
5272
|
//#endregion
|
|
4233
|
-
export {
|
|
5273
|
+
export { getContentBlocks$2 as _, ConfirmButton as a, runWizard as c, getProgramConfig as d, DISPLAY_NAME as f, getDetectedWarehouseSources as g, fetchHealthIssues as h, useKeyboardHintsContext as i, PROGRAM_REGISTRY as l, getKindMeta as m, useKeyBindings as n, PromptLabel as o, SOURCE_MAPS_CONTEXT_KEYS as p, KeyboardHintsProvider as r, runWizardCI as s, PickerMenu as t, Program as u, POSTHOG_SDKS$1 as v, STRIPE_SDKS as y };
|
|
4234
5274
|
|
|
4235
5275
|
//# sourceMappingURL=bin.js.map
|