@posthog/wizard 2.45.0 → 2.46.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.
Files changed (112) hide show
  1. package/README.md +5 -1
  2. package/dist/{add-mcp-server-to-clients-CNzZMSat.js → add-mcp-server-to-clients-Bv2CBSil.js} +53 -6
  3. package/dist/add-mcp-server-to-clients-Bv2CBSil.js.map +1 -0
  4. package/dist/{agent-interface-CF7GsdFf.js → agent-interface-B8roB2UP.js} +833 -8
  5. package/dist/agent-interface-B8roB2UP.js.map +1 -0
  6. package/dist/{agent-runner-B0LTVFfw.js → agent-runner-CV3qh_2p.js} +204 -48
  7. package/dist/agent-runner-CV3qh_2p.js.map +1 -0
  8. package/dist/analytics-D7vUZgzf.js +2 -0
  9. package/dist/{analytics-DQEuL6qS.js → analytics-k76OWsl0.js} +20 -6
  10. package/dist/analytics-k76OWsl0.js.map +1 -0
  11. package/dist/{api-uCMvDII5.js → api-CmIWcW-U.js} +3 -3
  12. package/dist/{api-uCMvDII5.js.map → api-CmIWcW-U.js.map} +1 -1
  13. package/dist/bin.js +228 -985
  14. package/dist/bin.js.map +1 -1
  15. package/dist/{ci-install-Bow8-f0j.js → ci-install-CNEJxdHf.js} +4 -4
  16. package/dist/{ci-install-Bow8-f0j.js.map → ci-install-CNEJxdHf.js.map} +1 -1
  17. package/dist/{commandments-CyB7Icr1.js → commandments-DSNrOeOC.js} +1 -1
  18. package/dist/{commandments-CyB7Icr1.js.map → commandments-DSNrOeOC.js.map} +1 -1
  19. package/dist/commandments-qTW7pwaT.js +2 -0
  20. package/dist/{debug-BixHZmHv.js → debug-BwIo7nwn.js} +1 -1
  21. package/dist/{debug-DBmxx59Q.js → debug-C9HmIrwx.js} +19 -5
  22. package/dist/debug-C9HmIrwx.js.map +1 -0
  23. package/dist/{defaults-8zjNjGGi.js → defaults-CtWMmC8s.js} +1 -1
  24. package/dist/{defaults-8zjNjGGi.js.map → defaults-CtWMmC8s.js.map} +1 -1
  25. package/dist/{env-api-key-AcC_tz8G.js → env-api-key-C3LzH8Lr.js} +1 -1
  26. package/dist/{env-api-key-AcC_tz8G.js.map → env-api-key-C3LzH8Lr.js.map} +1 -1
  27. package/dist/{environment-kZtkp7eG.js → environment-NJykOp33.js} +3 -3
  28. package/dist/{environment-kZtkp7eG.js.map → environment-NJykOp33.js.map} +1 -1
  29. package/dist/{file-utils-BAhYy5vC.js → file-utils-CLMcNIKi.js} +2 -2
  30. package/dist/{file-utils-BAhYy5vC.js.map → file-utils-CLMcNIKi.js.map} +1 -1
  31. package/dist/{file-watcher-BL-IRbR7.js → file-watcher-CBDCNQVV.js} +2 -2
  32. package/dist/{file-watcher-BL-IRbR7.js.map → file-watcher-CBDCNQVV.js.map} +1 -1
  33. package/dist/{headless-ui-DWmMyhaP.js → headless-ui-B3QKxbz8.js} +2 -2
  34. package/dist/{headless-ui-DWmMyhaP.js.map → headless-ui-B3QKxbz8.js.map} +1 -1
  35. package/dist/{interactive-Cyic0bGL.js → interactive-CIJRex02.js} +2 -2
  36. package/dist/{interactive-Cyic0bGL.js.map → interactive-CIJRex02.js.map} +1 -1
  37. package/dist/{mcp-prompt-streaming-C227vG1X.js → mcp-prompt-streaming-D6OgW3lC.js} +3 -3
  38. package/dist/{mcp-prompt-streaming-C227vG1X.js.map → mcp-prompt-streaming-D6OgW3lC.js.map} +1 -1
  39. package/dist/{mcp-BSGmEWjt.js → mcp-qTjKHqXN.js} +2 -2
  40. package/dist/{mcp-BSGmEWjt.js.map → mcp-qTjKHqXN.js.map} +1 -1
  41. package/dist/{non-interactive-DQA9vn9f.js → non-interactive-8Eypq_h-.js} +2 -2
  42. package/dist/{non-interactive-DQA9vn9f.js.map → non-interactive-8Eypq_h-.js.map} +1 -1
  43. package/dist/{orchestrator-tools-NuWONNkF.js → orchestrator-tools-DVXOV-kz.js} +3 -3
  44. package/dist/{orchestrator-tools-NuWONNkF.js.map → orchestrator-tools-DVXOV-kz.js.map} +1 -1
  45. package/dist/{package-manager-DKtR3xzM.js → package-manager-CAD9Uklp.js} +2 -2
  46. package/dist/{package-manager-DKtR3xzM.js.map → package-manager-CAD9Uklp.js.map} +1 -1
  47. package/dist/{pi-DJCln9jJ.js → pi-C9iHv5uG.js} +48 -32
  48. package/dist/pi-C9iHv5uG.js.map +1 -0
  49. package/dist/{playground-CbEndzc8.js → playground-C-9Q3ETa.js} +7 -7
  50. package/dist/{playground-CbEndzc8.js.map → playground-C-9Q3ETa.js.map} +1 -1
  51. package/dist/{posthog-DFyux4Vw.js → posthog-DZZbziJ1.js} +1 -1
  52. package/dist/{posthog-DFyux4Vw.js.map → posthog-DZZbziJ1.js.map} +1 -1
  53. package/dist/{posthog-integration-dmWJZ8mj.js → posthog-integration-Do997QON.js} +2006 -17
  54. package/dist/posthog-integration-Do997QON.js.map +1 -0
  55. package/dist/{provisioning-CcxCry5p.js → provisioning-DpqnGk3z.js} +3 -3
  56. package/dist/{provisioning-CcxCry5p.js.map → provisioning-DpqnGk3z.js.map} +1 -1
  57. package/dist/{queue-tools-Bw-AANLM.js → queue-tools-CTUgbOU8.js} +2 -2
  58. package/dist/{queue-tools-Bw-AANLM.js.map → queue-tools-CTUgbOU8.js.map} +1 -1
  59. package/dist/{registry-D2V88NoC.js → registry-DT58jEYr.js} +4 -4
  60. package/dist/{registry-D2V88NoC.js.map → registry-DT58jEYr.js.map} +1 -1
  61. package/dist/{security-DOtBCBvx.js → security-CTigdAWm.js} +10 -8
  62. package/dist/security-CTigdAWm.js.map +1 -0
  63. package/dist/{setup-utils-Qp-u6BZk.js → setup-utils-Cb5uACEO.js} +31 -9
  64. package/dist/setup-utils-Cb5uACEO.js.map +1 -0
  65. package/dist/{start-tui-DHa_9aiB.js → start-tui-Cwc-PFma.js} +36 -30
  66. package/dist/start-tui-Cwc-PFma.js.map +1 -0
  67. package/dist/{steps-D07HUQyE.js → steps-DyEKYM4I.js} +7 -7
  68. package/dist/{steps-D07HUQyE.js.map → steps-DyEKYM4I.js.map} +1 -1
  69. package/dist/{store-DSwsITKX.js → store-4sj-vWr5.js} +4 -4
  70. package/dist/{store-DSwsITKX.js.map → store-4sj-vWr5.js.map} +1 -1
  71. package/dist/{subagent-Dk4K5MDa.js → subagent-D8_yDgCB.js} +2 -2
  72. package/dist/{subagent-Dk4K5MDa.js.map → subagent-D8_yDgCB.js.map} +1 -1
  73. package/dist/{task-CQnV9Qd2.js → task-D8Y8pkzd.js} +12 -13
  74. package/dist/task-D8Y8pkzd.js.map +1 -0
  75. package/dist/{task-stream-B7qia9eW.js → task-stream-DQT3vjwS.js} +4 -4
  76. package/dist/{task-stream-B7qia9eW.js.map → task-stream-DQT3vjwS.js.map} +1 -1
  77. package/dist/{tasks-C7BQp659.js → tasks-D2WKssA5.js} +2 -2
  78. package/dist/{tasks-C7BQp659.js.map → tasks-D2WKssA5.js.map} +1 -1
  79. package/dist/{telemetry-DgahJGSx.js → telemetry-CYr4HgS2.js} +3 -3
  80. package/dist/{telemetry-DgahJGSx.js.map → telemetry-CYr4HgS2.js.map} +1 -1
  81. package/dist/{terminal-Bb6tZkf-.js → terminal-1RfyHQC2.js} +12 -12
  82. package/dist/{terminal-Bb6tZkf-.js.map → terminal-1RfyHQC2.js.map} +1 -1
  83. package/dist/tools-DQCUOQZX.js +199 -0
  84. package/dist/tools-DQCUOQZX.js.map +1 -0
  85. package/dist/{wizard-abort-DpDmuCfA.js → wizard-abort-D_-v1zvS.js} +1 -1
  86. package/dist/{wizard-abort-BxtdkgI-.js → wizard-abort-FuyIaI_0.js} +3 -3
  87. package/dist/{wizard-abort-BxtdkgI-.js.map → wizard-abort-FuyIaI_0.js.map} +1 -1
  88. package/dist/yara-hooks-6gNnPFPo.js +2 -0
  89. package/dist/{yara-hooks-pw86rZ8y.js → yara-hooks-DdYRRxfH.js} +82 -21
  90. package/dist/yara-hooks-DdYRRxfH.js.map +1 -0
  91. package/package.json +1 -1
  92. package/dist/add-mcp-server-to-clients-CNzZMSat.js.map +0 -1
  93. package/dist/agent-interface-CF7GsdFf.js.map +0 -1
  94. package/dist/agent-runner-B0LTVFfw.js.map +0 -1
  95. package/dist/analytics-DQEuL6qS.js.map +0 -1
  96. package/dist/analytics-YD3D38z2.js +0 -2
  97. package/dist/commandments-DguPfCX8.js +0 -2
  98. package/dist/debug-DBmxx59Q.js.map +0 -1
  99. package/dist/pi-DJCln9jJ.js.map +0 -1
  100. package/dist/posthog-integration-dmWJZ8mj.js.map +0 -1
  101. package/dist/security-DOtBCBvx.js.map +0 -1
  102. package/dist/setup-utils-Qp-u6BZk.js.map +0 -1
  103. package/dist/start-tui-DHa_9aiB.js.map +0 -1
  104. package/dist/task-CQnV9Qd2.js.map +0 -1
  105. package/dist/tools-BJEvSUWN.js +0 -122
  106. package/dist/tools-BJEvSUWN.js.map +0 -1
  107. package/dist/types-BRe_EzTW.js +0 -46
  108. package/dist/types-BRe_EzTW.js.map +0 -1
  109. package/dist/wizard-tools-Dg8o2lcH.js +0 -783
  110. package/dist/wizard-tools-Dg8o2lcH.js.map +0 -1
  111. package/dist/yara-hooks-CncaWRuC.js +0 -2
  112. package/dist/yara-hooks-pw86rZ8y.js.map +0 -1
@@ -1,18 +1,18 @@
1
- import { B as Integration, L as HAIKU_MODEL, O as DETECTION_TIMEOUT_MS, _ as evaluateWizardReadiness, _t as getSkillsBaseUrl, f as getUI, g as SIGNUP_WIZARD_READINESS_CONFIG, s as logToFile, st as WIZARD_INTERACTION_EVENT_NAME, v as getBlockingServiceKeys, x as AGENTIC_DETECTION_TIMEOUT_MS } from "./debug-DBmxx59Q.js";
2
- import { n as analytics } from "./analytics-DQEuL6qS.js";
3
- import { i as withUtm, n as openTrackedLink } from "./telemetry-DgahJGSx.js";
4
- import { i as tryGetPackageJson, n as isUsingTypeScript } from "./setup-utils-Qp-u6BZk.js";
5
- import { r as requestDeepLink } from "./provisioning-CcxCry5p.js";
1
+ import { B as Integration, L as HAIKU_MODEL, O as DETECTION_TIMEOUT_MS, _ as evaluateWizardReadiness, f as getUI, g as SIGNUP_WIZARD_READINESS_CONFIG, s as logToFile, st as WIZARD_INTERACTION_EVENT_NAME, v as getBlockingServiceKeys, vt as getSkillsBaseUrl, x as AGENTIC_DETECTION_TIMEOUT_MS } from "./debug-C9HmIrwx.js";
2
+ import { n as analytics } from "./analytics-k76OWsl0.js";
3
+ import { i as withUtm, n as openTrackedLink } from "./telemetry-CYr4HgS2.js";
4
+ import { i as tryGetPackageJson, n as isUsingTypeScript } from "./setup-utils-Cb5uACEO.js";
5
+ import { r as requestDeepLink } from "./provisioning-DpqnGk3z.js";
6
6
  import "./wizard-session-tp4Zdbwl.js";
7
- import { i as wizardAbort } from "./wizard-abort-BxtdkgI-.js";
8
- import { n as runAgent, o as authenticate } from "./agent-runner-B0LTVFfw.js";
9
- import { i as runAgent$1, p as AgentSignals, r as initializeAgent } from "./agent-interface-CF7GsdFf.js";
10
- import { t as WIZARD_TOOL_NAMES } from "./wizard-tools-Dg8o2lcH.js";
11
- import { m as EVENT_PLAN_FILE } from "./yara-hooks-pw86rZ8y.js";
12
- import { r as detectNodePackageManagers } from "./package-manager-DKtR3xzM.js";
13
- import { i as SPINNER_MESSAGE, t as FRAMEWORK_REGISTRY } from "./registry-D2V88NoC.js";
7
+ import { i as wizardAbort } from "./wizard-abort-FuyIaI_0.js";
8
+ import { n as runAgent, o as authenticate } from "./agent-runner-CV3qh_2p.js";
9
+ import { i as runAgent$1, p as AgentSignals, r as initializeAgent, v as WIZARD_TOOL_NAMES } from "./agent-interface-B8roB2UP.js";
10
+ import { m as EVENT_PLAN_FILE } from "./yara-hooks-DdYRRxfH.js";
11
+ import { r as detectNodePackageManagers } from "./package-manager-CAD9Uklp.js";
12
+ import { i as SPINNER_MESSAGE, t as FRAMEWORK_REGISTRY } from "./registry-DT58jEYr.js";
13
+ import { n as safeReadFile, r as walkProjectFiles } from "./file-utils-CLMcNIKi.js";
14
14
  import * as semver from "semver";
15
- import { readFileSync } from "fs";
15
+ import { existsSync, readFileSync, statSync } from "fs";
16
16
  import { isAbsolute, join, resolve, sep } from "path";
17
17
  import { Text } from "ink";
18
18
  import { useEffect, useMemo, useRef, useState } from "react";
@@ -516,6 +516,1926 @@ async function scopeInstallDirToProject(session) {
516
516
  getUI().log.info(`Continuing with ${project.path} (${project.framework}).`);
517
517
  }
518
518
  //#endregion
519
+ //#region src/lib/warehouse-sources/registry.ts
520
+ const SOURCE_DETECTORS = [
521
+ {
522
+ kind: "Postgres",
523
+ label: "PostgreSQL",
524
+ mode: "in-cli",
525
+ signals: {
526
+ npm: [
527
+ "pg",
528
+ "postgres",
529
+ "postgres.js",
530
+ "knex",
531
+ "sequelize"
532
+ ],
533
+ python: [
534
+ "psycopg",
535
+ "psycopg2",
536
+ "psycopg2-binary",
537
+ "asyncpg"
538
+ ],
539
+ ruby: ["pg"],
540
+ envKeys: [
541
+ /^DATABASE_URL$/,
542
+ /^POSTGRES_/,
543
+ /^PG(HOST|DATABASE|USER|PORT)$/
544
+ ]
545
+ }
546
+ },
547
+ {
548
+ kind: "MySQL",
549
+ label: "MySQL",
550
+ mode: "in-cli",
551
+ signals: {
552
+ npm: ["mysql", "mysql2"],
553
+ python: [
554
+ "pymysql",
555
+ "mysqlclient",
556
+ "mysql-connector-python"
557
+ ],
558
+ ruby: ["mysql2"],
559
+ envKeys: [/^MYSQL_/]
560
+ }
561
+ },
562
+ {
563
+ kind: "MongoDB",
564
+ label: "MongoDB",
565
+ mode: "in-cli",
566
+ signals: {
567
+ npm: ["mongodb", "mongoose"],
568
+ python: ["pymongo", "motor"],
569
+ ruby: ["mongo", "mongoid"],
570
+ envKeys: [/^MONGO(DB)?_/]
571
+ }
572
+ },
573
+ {
574
+ kind: "Snowflake",
575
+ label: "Snowflake",
576
+ mode: "in-cli",
577
+ signals: {
578
+ npm: ["snowflake-sdk"],
579
+ python: ["snowflake-connector-python", "snowflake-sqlalchemy"],
580
+ envKeys: [/^SNOWFLAKE_/]
581
+ }
582
+ },
583
+ {
584
+ kind: "BigQuery",
585
+ label: "BigQuery",
586
+ mode: "in-cli",
587
+ signals: {
588
+ npm: ["@google-cloud/bigquery"],
589
+ python: ["google-cloud-bigquery"],
590
+ envKeys: [/^BIGQUERY_/]
591
+ }
592
+ },
593
+ {
594
+ kind: "Redshift",
595
+ label: "Redshift",
596
+ mode: "in-cli",
597
+ signals: {
598
+ npm: ["node-redshift"],
599
+ python: ["redshift-connector"],
600
+ envKeys: [/^REDSHIFT_/]
601
+ }
602
+ },
603
+ {
604
+ kind: "MSSQL",
605
+ label: "SQL Server",
606
+ mode: "in-cli",
607
+ signals: {
608
+ npm: ["mssql", "tedious"],
609
+ python: ["pyodbc", "pymssql"],
610
+ envKeys: [/^MSSQL_/]
611
+ }
612
+ },
613
+ {
614
+ kind: "Supabase",
615
+ label: "Supabase",
616
+ mode: "in-cli",
617
+ signals: {
618
+ npm: ["@supabase/supabase-js"],
619
+ python: ["supabase"],
620
+ envKeys: [/^SUPABASE_/]
621
+ }
622
+ },
623
+ {
624
+ kind: "ClickHouse",
625
+ label: "ClickHouse",
626
+ mode: "in-cli",
627
+ signals: {
628
+ npm: ["@clickhouse/client"],
629
+ python: ["clickhouse-connect", "clickhouse-driver"],
630
+ envKeys: [/^CLICKHOUSE_/]
631
+ }
632
+ },
633
+ {
634
+ kind: "Convex",
635
+ label: "Convex",
636
+ mode: "in-cli",
637
+ signals: {
638
+ npm: ["convex"],
639
+ python: ["convex"],
640
+ envKeys: [/^CONVEX_/, /^NEXT_PUBLIC_CONVEX_URL$/]
641
+ }
642
+ },
643
+ {
644
+ kind: "Stripe",
645
+ label: "Stripe",
646
+ mode: "in-cli",
647
+ signals: {
648
+ npm: [
649
+ "stripe",
650
+ "@stripe/stripe-js",
651
+ "@stripe/react-stripe-js"
652
+ ],
653
+ python: ["stripe"],
654
+ ruby: ["stripe"],
655
+ envKeys: [/^STRIPE_(SECRET|API)_KEY$/]
656
+ }
657
+ },
658
+ {
659
+ kind: "Clerk",
660
+ label: "Clerk",
661
+ mode: "in-cli",
662
+ signals: {
663
+ npm: [
664
+ "@clerk/nextjs",
665
+ "@clerk/clerk-react",
666
+ "@clerk/backend",
667
+ "@clerk/express",
668
+ "@clerk/fastify",
669
+ "@clerk/remix"
670
+ ],
671
+ envKeys: [/^CLERK_SECRET_KEY$/, /^NEXT_PUBLIC_CLERK_/]
672
+ }
673
+ },
674
+ {
675
+ kind: "Resend",
676
+ label: "Resend",
677
+ mode: "in-cli",
678
+ signals: {
679
+ npm: ["resend"],
680
+ python: ["resend"],
681
+ envKeys: [/^RESEND_API_KEY$/]
682
+ }
683
+ },
684
+ {
685
+ kind: "Shopify",
686
+ label: "Shopify",
687
+ mode: "in-cli",
688
+ signals: {
689
+ npm: ["@shopify/shopify-api", "shopify-api-node"],
690
+ python: ["shopifyapi"],
691
+ envKeys: [/^SHOPIFY_/]
692
+ }
693
+ },
694
+ {
695
+ kind: "Klaviyo",
696
+ label: "Klaviyo",
697
+ mode: "in-cli",
698
+ signals: {
699
+ npm: ["klaviyo-api"],
700
+ python: ["klaviyo-api"],
701
+ envKeys: [/^KLAVIYO_/]
702
+ }
703
+ },
704
+ {
705
+ kind: "Chargebee",
706
+ label: "Chargebee",
707
+ mode: "in-cli",
708
+ signals: {
709
+ npm: ["chargebee"],
710
+ python: ["chargebee"],
711
+ envKeys: [/^CHARGEBEE_/]
712
+ }
713
+ },
714
+ {
715
+ kind: "Paddle",
716
+ label: "Paddle",
717
+ mode: "in-cli",
718
+ signals: {
719
+ npm: ["@paddle/paddle-node-sdk", "@paddle/paddle-js"],
720
+ envKeys: [/^PADDLE_/]
721
+ }
722
+ },
723
+ {
724
+ kind: "Polar",
725
+ label: "Polar",
726
+ mode: "in-cli",
727
+ signals: {
728
+ npm: ["@polar-sh/sdk", "@polar-sh/nextjs"],
729
+ envKeys: [/^POLAR_/]
730
+ }
731
+ },
732
+ {
733
+ kind: "Mailchimp",
734
+ label: "Mailchimp",
735
+ mode: "in-cli",
736
+ signals: {
737
+ npm: ["@mailchimp/mailchimp_marketing"],
738
+ python: ["mailchimp-marketing"],
739
+ envKeys: [/^MAILCHIMP_/]
740
+ }
741
+ },
742
+ {
743
+ kind: "CustomerIO",
744
+ label: "Customer.io",
745
+ mode: "in-cli",
746
+ signals: {
747
+ npm: ["customerio-node"],
748
+ python: ["customerio"],
749
+ envKeys: [/^CUSTOMER_?IO_/]
750
+ }
751
+ },
752
+ {
753
+ kind: "Typeform",
754
+ label: "Typeform",
755
+ mode: "in-cli",
756
+ signals: {
757
+ npm: ["@typeform/api-client"],
758
+ envKeys: [/^TYPEFORM_/]
759
+ }
760
+ },
761
+ {
762
+ kind: "Sentry",
763
+ label: "Sentry",
764
+ mode: "in-cli",
765
+ signals: {
766
+ npm: [
767
+ "@sentry/node",
768
+ "@sentry/browser",
769
+ "@sentry/react",
770
+ "@sentry/nextjs"
771
+ ],
772
+ python: ["sentry-sdk"],
773
+ ruby: ["sentry-ruby"]
774
+ }
775
+ },
776
+ {
777
+ kind: "Plaid",
778
+ label: "Plaid",
779
+ mode: "in-cli",
780
+ signals: {
781
+ npm: ["plaid"],
782
+ python: ["plaid-python", "plaid"],
783
+ ruby: ["plaid"],
784
+ envKeys: [/^PLAID_/]
785
+ }
786
+ },
787
+ {
788
+ kind: "Braintree",
789
+ label: "Braintree",
790
+ mode: "in-cli",
791
+ signals: {
792
+ npm: ["braintree"],
793
+ python: ["braintree"],
794
+ ruby: ["braintree"],
795
+ envKeys: [/^BRAINTREE_/]
796
+ }
797
+ },
798
+ {
799
+ kind: "Square",
800
+ label: "Square",
801
+ mode: "in-cli",
802
+ signals: {
803
+ npm: ["square"],
804
+ python: ["squareup"],
805
+ ruby: ["square"],
806
+ envKeys: [/^SQUARE_/]
807
+ }
808
+ },
809
+ {
810
+ kind: "GoCardless",
811
+ label: "GoCardless",
812
+ mode: "in-cli",
813
+ signals: {
814
+ npm: ["gocardless-nodejs"],
815
+ python: ["gocardless-pro"],
816
+ ruby: ["gocardless_pro"],
817
+ envKeys: [/^GOCARDLESS_/]
818
+ }
819
+ },
820
+ {
821
+ kind: "Mollie",
822
+ label: "Mollie",
823
+ mode: "in-cli",
824
+ signals: {
825
+ npm: ["@mollie/api-client"],
826
+ python: ["mollie-api-python"],
827
+ envKeys: [/^MOLLIE_/]
828
+ }
829
+ },
830
+ {
831
+ kind: "CheckoutCom",
832
+ label: "Checkout.com",
833
+ mode: "in-cli",
834
+ signals: {
835
+ npm: ["checkout-sdk-node"],
836
+ python: ["checkout-sdk"],
837
+ envKeys: [/^CKO_/, /^CHECKOUT_COM_/]
838
+ }
839
+ },
840
+ {
841
+ kind: "Recurly",
842
+ label: "Recurly",
843
+ mode: "in-cli",
844
+ signals: {
845
+ npm: ["recurly"],
846
+ python: ["recurly"],
847
+ ruby: ["recurly"],
848
+ envKeys: [/^RECURLY_/]
849
+ }
850
+ },
851
+ {
852
+ kind: "RevenueCat",
853
+ label: "RevenueCat",
854
+ mode: "in-cli",
855
+ signals: {
856
+ npm: [
857
+ "@revenuecat/purchases-js",
858
+ "react-native-purchases",
859
+ "@revenuecat/purchases-capacitor"
860
+ ],
861
+ envKeys: [/^REVENUE_?CAT_/]
862
+ }
863
+ },
864
+ {
865
+ kind: "Twilio",
866
+ label: "Twilio",
867
+ mode: "in-cli",
868
+ signals: {
869
+ npm: ["twilio"],
870
+ python: ["twilio"],
871
+ ruby: ["twilio-ruby"],
872
+ envKeys: [/^TWILIO_/]
873
+ }
874
+ },
875
+ {
876
+ kind: "SendGrid",
877
+ label: "SendGrid",
878
+ mode: "in-cli",
879
+ signals: {
880
+ npm: ["@sendgrid/mail", "@sendgrid/client"],
881
+ python: ["sendgrid"],
882
+ ruby: ["sendgrid-ruby"],
883
+ envKeys: [/^SENDGRID_/]
884
+ }
885
+ },
886
+ {
887
+ kind: "Mailgun",
888
+ label: "Mailgun",
889
+ mode: "in-cli",
890
+ signals: {
891
+ npm: ["mailgun.js", "mailgun-js"],
892
+ python: ["mailgun"],
893
+ ruby: ["mailgun-ruby"],
894
+ envKeys: [/^MAILGUN_/]
895
+ }
896
+ },
897
+ {
898
+ kind: "Postmark",
899
+ label: "Postmark",
900
+ mode: "in-cli",
901
+ signals: {
902
+ npm: ["postmark"],
903
+ python: ["postmarker"],
904
+ ruby: ["postmark"],
905
+ envKeys: [/^POSTMARK_/]
906
+ }
907
+ },
908
+ {
909
+ kind: "Brevo",
910
+ label: "Brevo",
911
+ mode: "in-cli",
912
+ signals: {
913
+ npm: ["@getbrevo/brevo", "sib-api-v3-sdk"],
914
+ python: ["sib-api-v3-sdk"],
915
+ envKeys: [/^BREVO_/]
916
+ }
917
+ },
918
+ {
919
+ kind: "MailerLite",
920
+ label: "MailerLite",
921
+ mode: "in-cli",
922
+ signals: {
923
+ npm: ["@mailerlite/mailerlite-nodejs"],
924
+ python: ["mailerlite"],
925
+ envKeys: [/^MAILERLITE_/]
926
+ }
927
+ },
928
+ {
929
+ kind: "Mailjet",
930
+ label: "Mailjet",
931
+ mode: "in-cli",
932
+ signals: {
933
+ npm: ["node-mailjet"],
934
+ python: ["mailjet-rest"],
935
+ envKeys: [/^MAILJET_/, /^MJ_APIKEY_/]
936
+ }
937
+ },
938
+ {
939
+ kind: "LaunchDarkly",
940
+ label: "LaunchDarkly",
941
+ mode: "in-cli",
942
+ signals: {
943
+ npm: [
944
+ "launchdarkly-node-server-sdk",
945
+ "@launchdarkly/node-server-sdk",
946
+ "launchdarkly-js-client-sdk",
947
+ "launchdarkly-react-client-sdk"
948
+ ],
949
+ python: ["launchdarkly-server-sdk"],
950
+ ruby: ["launchdarkly-server-sdk"],
951
+ envKeys: [/^LAUNCHDARKLY_/, /^LD_SDK_KEY$/]
952
+ }
953
+ },
954
+ {
955
+ kind: "Optimizely",
956
+ label: "Optimizely",
957
+ mode: "in-cli",
958
+ signals: {
959
+ npm: ["@optimizely/optimizely-sdk"],
960
+ python: ["optimizely-sdk"],
961
+ envKeys: [/^OPTIMIZELY_/]
962
+ }
963
+ },
964
+ {
965
+ kind: "Braze",
966
+ label: "Braze",
967
+ mode: "in-cli",
968
+ signals: {
969
+ npm: ["@braze/web-sdk", "@braze/react-native-sdk"],
970
+ python: ["braze-client"],
971
+ envKeys: [/^BRAZE_/]
972
+ }
973
+ },
974
+ {
975
+ kind: "Rollbar",
976
+ label: "Rollbar",
977
+ mode: "in-cli",
978
+ signals: {
979
+ npm: ["rollbar"],
980
+ python: ["rollbar", "pyrollbar"],
981
+ ruby: ["rollbar"],
982
+ envKeys: [/^ROLLBAR_/]
983
+ }
984
+ },
985
+ {
986
+ kind: "Okta",
987
+ label: "Okta",
988
+ mode: "in-cli",
989
+ signals: {
990
+ npm: [
991
+ "@okta/okta-sdk-nodejs",
992
+ "@okta/okta-auth-js",
993
+ "@okta/okta-react"
994
+ ],
995
+ python: ["okta"],
996
+ envKeys: [/^OKTA_/]
997
+ }
998
+ },
999
+ {
1000
+ kind: "WorkOS",
1001
+ label: "WorkOS",
1002
+ mode: "in-cli",
1003
+ signals: {
1004
+ npm: ["@workos-inc/node"],
1005
+ python: ["workos"],
1006
+ envKeys: [/^WORKOS_/]
1007
+ }
1008
+ },
1009
+ {
1010
+ kind: "Notion",
1011
+ label: "Notion",
1012
+ mode: "in-cli",
1013
+ signals: {
1014
+ npm: ["@notionhq/client"],
1015
+ python: ["notion-client"],
1016
+ envKeys: [/^NOTION_/]
1017
+ }
1018
+ },
1019
+ {
1020
+ kind: "FullStory",
1021
+ label: "FullStory",
1022
+ mode: "in-cli",
1023
+ signals: {
1024
+ npm: ["@fullstory/browser", "@fullstory/react-native"],
1025
+ envKeys: [/^FULLSTORY_/]
1026
+ }
1027
+ },
1028
+ {
1029
+ kind: "Amplitude",
1030
+ label: "Amplitude",
1031
+ mode: "in-cli",
1032
+ signals: {
1033
+ npm: [
1034
+ "@amplitude/analytics-browser",
1035
+ "@amplitude/analytics-node",
1036
+ "@amplitude/analytics-react-native",
1037
+ "amplitude-js"
1038
+ ],
1039
+ python: ["amplitude-analytics"],
1040
+ envKeys: [/^AMPLITUDE_/]
1041
+ }
1042
+ },
1043
+ {
1044
+ kind: "Mixpanel",
1045
+ label: "Mixpanel",
1046
+ mode: "in-cli",
1047
+ signals: {
1048
+ npm: ["mixpanel", "mixpanel-browser"],
1049
+ python: ["mixpanel"],
1050
+ ruby: ["mixpanel-ruby"],
1051
+ envKeys: [/^MIXPANEL_/]
1052
+ }
1053
+ },
1054
+ {
1055
+ kind: "Pendo",
1056
+ label: "Pendo",
1057
+ mode: "in-cli",
1058
+ signals: {
1059
+ npm: ["@pendo/agent"],
1060
+ envKeys: [/^PENDO_/]
1061
+ }
1062
+ },
1063
+ {
1064
+ kind: "Salesforce",
1065
+ label: "Salesforce",
1066
+ mode: "deep-link",
1067
+ signals: {
1068
+ npm: ["jsforce"],
1069
+ python: ["simple-salesforce"],
1070
+ envKeys: [/^SALESFORCE_/]
1071
+ }
1072
+ },
1073
+ {
1074
+ kind: "Hubspot",
1075
+ label: "HubSpot",
1076
+ mode: "deep-link",
1077
+ signals: {
1078
+ npm: ["@hubspot/api-client"],
1079
+ python: ["hubspot-api-client"],
1080
+ envKeys: [/^HUBSPOT_/]
1081
+ }
1082
+ },
1083
+ {
1084
+ kind: "Zendesk",
1085
+ label: "Zendesk",
1086
+ mode: "deep-link",
1087
+ signals: {
1088
+ npm: ["node-zendesk"],
1089
+ python: ["zenpy"],
1090
+ envKeys: [/^ZENDESK_/]
1091
+ }
1092
+ },
1093
+ {
1094
+ kind: "Intercom",
1095
+ label: "Intercom",
1096
+ mode: "deep-link",
1097
+ signals: {
1098
+ npm: ["intercom-client", "@intercom/messenger-js-sdk"],
1099
+ python: ["python-intercom"],
1100
+ envKeys: [/^INTERCOM_/]
1101
+ }
1102
+ },
1103
+ {
1104
+ kind: "Linear",
1105
+ label: "Linear",
1106
+ mode: "deep-link",
1107
+ signals: {
1108
+ npm: ["@linear/sdk"],
1109
+ envKeys: [/^LINEAR_API_KEY$/]
1110
+ }
1111
+ },
1112
+ {
1113
+ kind: "Slack",
1114
+ label: "Slack",
1115
+ mode: "deep-link",
1116
+ signals: {
1117
+ npm: ["@slack/web-api", "@slack/bolt"],
1118
+ python: ["slack-sdk", "slack-bolt"],
1119
+ envKeys: [/^SLACK_(BOT|APP|SIGNING|CLIENT)_/]
1120
+ }
1121
+ },
1122
+ {
1123
+ kind: "Github",
1124
+ label: "GitHub",
1125
+ mode: "deep-link",
1126
+ signals: {
1127
+ npm: [
1128
+ "@octokit/rest",
1129
+ "@octokit/core",
1130
+ "@octokit/graphql",
1131
+ "octokit"
1132
+ ],
1133
+ python: ["pygithub"],
1134
+ ruby: ["octokit"]
1135
+ }
1136
+ },
1137
+ {
1138
+ kind: "OpenAI",
1139
+ label: "OpenAI",
1140
+ mode: "in-cli",
1141
+ signals: {
1142
+ npm: ["openai"],
1143
+ python: ["openai"],
1144
+ envKeys: [/^OPENAI_/]
1145
+ }
1146
+ },
1147
+ {
1148
+ kind: "Anthropic",
1149
+ label: "Anthropic",
1150
+ mode: "in-cli",
1151
+ signals: {
1152
+ npm: ["@anthropic-ai/sdk"],
1153
+ python: ["anthropic"],
1154
+ envKeys: [/^ANTHROPIC_/]
1155
+ }
1156
+ },
1157
+ {
1158
+ kind: "Cohere",
1159
+ label: "Cohere",
1160
+ mode: "in-cli",
1161
+ signals: {
1162
+ npm: ["cohere-ai"],
1163
+ python: ["cohere"],
1164
+ envKeys: [/^COHERE_/]
1165
+ }
1166
+ },
1167
+ {
1168
+ kind: "MistralAI",
1169
+ label: "Mistral AI",
1170
+ mode: "in-cli",
1171
+ signals: {
1172
+ npm: ["@mistralai/mistralai"],
1173
+ python: ["mistralai"],
1174
+ envKeys: [/^MISTRAL_/]
1175
+ }
1176
+ },
1177
+ {
1178
+ kind: "Groq",
1179
+ label: "Groq",
1180
+ mode: "in-cli",
1181
+ signals: {
1182
+ npm: ["groq-sdk"],
1183
+ python: ["groq"],
1184
+ envKeys: [/^GROQ_/]
1185
+ }
1186
+ },
1187
+ {
1188
+ kind: "TogetherAI",
1189
+ label: "Together AI",
1190
+ mode: "in-cli",
1191
+ signals: {
1192
+ npm: ["together-ai"],
1193
+ python: ["together"],
1194
+ envKeys: [/^TOGETHER_/]
1195
+ }
1196
+ },
1197
+ {
1198
+ kind: "FireworksAI",
1199
+ label: "Fireworks AI",
1200
+ mode: "in-cli",
1201
+ signals: {
1202
+ python: ["fireworks-ai"],
1203
+ envKeys: [/^FIREWORKS_/]
1204
+ }
1205
+ },
1206
+ {
1207
+ kind: "Replicate",
1208
+ label: "Replicate",
1209
+ mode: "in-cli",
1210
+ signals: {
1211
+ npm: ["replicate"],
1212
+ python: ["replicate"],
1213
+ envKeys: [/^REPLICATE_/]
1214
+ }
1215
+ },
1216
+ {
1217
+ kind: "HuggingFace",
1218
+ label: "Hugging Face",
1219
+ mode: "in-cli",
1220
+ signals: {
1221
+ npm: ["@huggingface/inference"],
1222
+ python: ["huggingface-hub"],
1223
+ envKeys: [/^HUGGINGFACE_/, /^HF_TOKEN$/]
1224
+ }
1225
+ },
1226
+ {
1227
+ kind: "ElevenLabs",
1228
+ label: "ElevenLabs",
1229
+ mode: "in-cli",
1230
+ signals: {
1231
+ npm: ["@elevenlabs/elevenlabs-js", "elevenlabs"],
1232
+ python: ["elevenlabs"],
1233
+ envKeys: [/^ELEVENLABS_/, /^ELEVEN_LABS_/]
1234
+ }
1235
+ },
1236
+ {
1237
+ kind: "Deepgram",
1238
+ label: "Deepgram",
1239
+ mode: "in-cli",
1240
+ signals: {
1241
+ npm: ["@deepgram/sdk"],
1242
+ python: ["deepgram-sdk"],
1243
+ envKeys: [/^DEEPGRAM_/]
1244
+ }
1245
+ },
1246
+ {
1247
+ kind: "AssemblyAI",
1248
+ label: "AssemblyAI",
1249
+ mode: "in-cli",
1250
+ signals: {
1251
+ npm: ["assemblyai"],
1252
+ python: ["assemblyai"],
1253
+ envKeys: [/^ASSEMBLYAI_/]
1254
+ }
1255
+ },
1256
+ {
1257
+ kind: "Langfuse",
1258
+ label: "Langfuse",
1259
+ mode: "in-cli",
1260
+ signals: {
1261
+ npm: ["langfuse"],
1262
+ python: ["langfuse"],
1263
+ envKeys: [/^LANGFUSE_/]
1264
+ }
1265
+ },
1266
+ {
1267
+ kind: "LangSmith",
1268
+ label: "LangSmith",
1269
+ mode: "in-cli",
1270
+ signals: {
1271
+ npm: ["langsmith"],
1272
+ python: ["langsmith"],
1273
+ envKeys: [/^LANGSMITH_/, /^LANGCHAIN_API_KEY$/]
1274
+ }
1275
+ },
1276
+ {
1277
+ kind: "Firecrawl",
1278
+ label: "Firecrawl",
1279
+ mode: "in-cli",
1280
+ signals: {
1281
+ npm: ["@mendable/firecrawl-js"],
1282
+ python: ["firecrawl-py"],
1283
+ envKeys: [/^FIRECRAWL_/]
1284
+ }
1285
+ },
1286
+ {
1287
+ kind: "Mem0",
1288
+ label: "Mem0",
1289
+ mode: "in-cli",
1290
+ signals: {
1291
+ npm: ["mem0ai"],
1292
+ python: ["mem0ai"],
1293
+ envKeys: [/^MEM0_/]
1294
+ }
1295
+ },
1296
+ {
1297
+ kind: "Vellum",
1298
+ label: "Vellum",
1299
+ mode: "in-cli",
1300
+ signals: {
1301
+ npm: ["vellum-ai"],
1302
+ python: ["vellum-ai"],
1303
+ envKeys: [/^VELLUM_/]
1304
+ }
1305
+ },
1306
+ {
1307
+ kind: "Helicone",
1308
+ label: "Helicone",
1309
+ mode: "in-cli",
1310
+ signals: {
1311
+ npm: ["@helicone/helpers"],
1312
+ envKeys: [/^HELICONE_/]
1313
+ }
1314
+ },
1315
+ {
1316
+ kind: "OpenRouter",
1317
+ label: "OpenRouter",
1318
+ mode: "in-cli",
1319
+ signals: {
1320
+ npm: ["@openrouter/ai-sdk-provider"],
1321
+ envKeys: [/^OPENROUTER_/]
1322
+ }
1323
+ },
1324
+ {
1325
+ kind: "Paystack",
1326
+ label: "Paystack",
1327
+ mode: "in-cli",
1328
+ signals: {
1329
+ python: ["paystackapi"],
1330
+ envKeys: [/^PAYSTACK_/]
1331
+ }
1332
+ },
1333
+ {
1334
+ kind: "Orb",
1335
+ label: "Orb",
1336
+ mode: "in-cli",
1337
+ signals: {
1338
+ npm: ["orb-billing"],
1339
+ python: ["orb-billing"],
1340
+ envKeys: [/^ORB_/]
1341
+ }
1342
+ },
1343
+ {
1344
+ kind: "Lago",
1345
+ label: "Lago",
1346
+ mode: "in-cli",
1347
+ signals: {
1348
+ npm: ["lago-javascript-client"],
1349
+ python: ["lago-python-client"],
1350
+ envKeys: [/^LAGO_/]
1351
+ }
1352
+ },
1353
+ {
1354
+ kind: "Zuora",
1355
+ label: "Zuora",
1356
+ mode: "in-cli",
1357
+ signals: { envKeys: [/^ZUORA_/] }
1358
+ },
1359
+ {
1360
+ kind: "Stigg",
1361
+ label: "Stigg",
1362
+ mode: "in-cli",
1363
+ signals: {
1364
+ npm: ["@stigg/node-server-sdk"],
1365
+ envKeys: [/^STIGG_/]
1366
+ }
1367
+ },
1368
+ {
1369
+ kind: "Ramp",
1370
+ label: "Ramp",
1371
+ mode: "in-cli",
1372
+ signals: { envKeys: [/^RAMP_/] }
1373
+ },
1374
+ {
1375
+ kind: "Brex",
1376
+ label: "Brex",
1377
+ mode: "in-cli",
1378
+ signals: { envKeys: [/^BREX_/] }
1379
+ },
1380
+ {
1381
+ kind: "Tremendous",
1382
+ label: "Tremendous",
1383
+ mode: "in-cli",
1384
+ signals: { envKeys: [/^TREMENDOUS_/] }
1385
+ },
1386
+ {
1387
+ kind: "Maxio",
1388
+ label: "Maxio",
1389
+ mode: "in-cli",
1390
+ signals: { envKeys: [/^MAXIO_/] }
1391
+ },
1392
+ {
1393
+ kind: "Chargify",
1394
+ label: "Chargify",
1395
+ mode: "in-cli",
1396
+ signals: { envKeys: [/^CHARGIFY_/] }
1397
+ },
1398
+ {
1399
+ kind: "Invoiced",
1400
+ label: "Invoiced",
1401
+ mode: "in-cli",
1402
+ signals: {
1403
+ npm: ["invoiced"],
1404
+ python: ["invoiced"],
1405
+ envKeys: [/^INVOICED_/]
1406
+ }
1407
+ },
1408
+ {
1409
+ kind: "SparkPost",
1410
+ label: "SparkPost",
1411
+ mode: "in-cli",
1412
+ signals: {
1413
+ npm: ["sparkpost"],
1414
+ python: ["sparkpost"],
1415
+ envKeys: [/^SPARKPOST_/]
1416
+ }
1417
+ },
1418
+ {
1419
+ kind: "MailerSend",
1420
+ label: "MailerSend",
1421
+ mode: "in-cli",
1422
+ signals: {
1423
+ npm: ["mailersend"],
1424
+ python: ["mailersend"],
1425
+ envKeys: [/^MAILERSEND_/]
1426
+ }
1427
+ },
1428
+ {
1429
+ kind: "Iterable",
1430
+ label: "Iterable",
1431
+ mode: "in-cli",
1432
+ signals: { envKeys: [/^ITERABLE_/] }
1433
+ },
1434
+ {
1435
+ kind: "ConvertKit",
1436
+ label: "ConvertKit",
1437
+ mode: "in-cli",
1438
+ signals: { envKeys: [/^CONVERTKIT_/] }
1439
+ },
1440
+ {
1441
+ kind: "Drip",
1442
+ label: "Drip",
1443
+ mode: "in-cli",
1444
+ signals: {
1445
+ npm: ["drip-nodejs"],
1446
+ envKeys: [/^DRIP_/]
1447
+ }
1448
+ },
1449
+ {
1450
+ kind: "Omnisend",
1451
+ label: "Omnisend",
1452
+ mode: "in-cli",
1453
+ signals: { envKeys: [/^OMNISEND_/] }
1454
+ },
1455
+ {
1456
+ kind: "EmailOctopus",
1457
+ label: "EmailOctopus",
1458
+ mode: "in-cli",
1459
+ signals: { envKeys: [/^EMAILOCTOPUS_/, /^EMAIL_OCTOPUS_/] }
1460
+ },
1461
+ {
1462
+ kind: "Elasticemail",
1463
+ label: "Elastic Email",
1464
+ mode: "in-cli",
1465
+ signals: { envKeys: [/^ELASTICEMAIL_/, /^ELASTIC_EMAIL_/] }
1466
+ },
1467
+ {
1468
+ kind: "CampaignMonitor",
1469
+ label: "Campaign Monitor",
1470
+ mode: "in-cli",
1471
+ signals: {
1472
+ npm: ["createsend-node"],
1473
+ envKeys: [/^CAMPAIGN_MONITOR_/, /^CREATESEND_/]
1474
+ }
1475
+ },
1476
+ {
1477
+ kind: "Lemlist",
1478
+ label: "Lemlist",
1479
+ mode: "in-cli",
1480
+ signals: { envKeys: [/^LEMLIST_/] }
1481
+ },
1482
+ {
1483
+ kind: "Segment",
1484
+ label: "Segment",
1485
+ mode: "in-cli",
1486
+ signals: {
1487
+ npm: ["@segment/analytics-node", "analytics-node"],
1488
+ python: ["segment-analytics-python", "analytics-python"],
1489
+ envKeys: [/^SEGMENT_/]
1490
+ }
1491
+ },
1492
+ {
1493
+ kind: "Snowplow",
1494
+ label: "Snowplow Analytics",
1495
+ mode: "in-cli",
1496
+ signals: {
1497
+ npm: ["@snowplow/node-tracker"],
1498
+ python: ["snowplow-tracker"],
1499
+ envKeys: [/^SNOWPLOW_/]
1500
+ }
1501
+ },
1502
+ {
1503
+ kind: "Matomo",
1504
+ label: "Matomo",
1505
+ mode: "in-cli",
1506
+ signals: {
1507
+ npm: ["matomo-tracker"],
1508
+ envKeys: [/^MATOMO_/]
1509
+ }
1510
+ },
1511
+ {
1512
+ kind: "Plausible",
1513
+ label: "Plausible",
1514
+ mode: "in-cli",
1515
+ signals: {
1516
+ npm: ["plausible-tracker"],
1517
+ envKeys: [/^PLAUSIBLE_/]
1518
+ }
1519
+ },
1520
+ {
1521
+ kind: "ConfigCat",
1522
+ label: "ConfigCat",
1523
+ mode: "in-cli",
1524
+ signals: {
1525
+ npm: ["configcat-node", "configcat-js"],
1526
+ python: ["configcat-client"],
1527
+ envKeys: [/^CONFIGCAT_/]
1528
+ }
1529
+ },
1530
+ {
1531
+ kind: "Flagsmith",
1532
+ label: "Flagsmith",
1533
+ mode: "in-cli",
1534
+ signals: {
1535
+ npm: ["flagsmith-nodejs", "flagsmith"],
1536
+ python: ["flagsmith"],
1537
+ envKeys: [/^FLAGSMITH_/]
1538
+ }
1539
+ },
1540
+ {
1541
+ kind: "Unleash",
1542
+ label: "Unleash",
1543
+ mode: "in-cli",
1544
+ signals: {
1545
+ npm: ["unleash-client"],
1546
+ python: ["unleashclient"],
1547
+ envKeys: [/^UNLEASH_/]
1548
+ }
1549
+ },
1550
+ {
1551
+ kind: "SplitIo",
1552
+ label: "Split.io",
1553
+ mode: "in-cli",
1554
+ signals: {
1555
+ npm: ["@splitsoftware/splitio"],
1556
+ python: ["splitio-client"],
1557
+ envKeys: [/^SPLITIO_/, /^SPLIT_IO_/]
1558
+ }
1559
+ },
1560
+ {
1561
+ kind: "Stytch",
1562
+ label: "Stytch",
1563
+ mode: "in-cli",
1564
+ signals: {
1565
+ npm: ["stytch"],
1566
+ python: ["stytch"],
1567
+ envKeys: [/^STYTCH_/]
1568
+ }
1569
+ },
1570
+ {
1571
+ kind: "Doppler",
1572
+ label: "Doppler",
1573
+ mode: "in-cli",
1574
+ signals: {
1575
+ npm: ["@dopplerhq/node-sdk"],
1576
+ envKeys: [/^DOPPLER_/]
1577
+ }
1578
+ },
1579
+ {
1580
+ kind: "Infisical",
1581
+ label: "Infisical",
1582
+ mode: "in-cli",
1583
+ signals: {
1584
+ npm: ["@infisical/sdk"],
1585
+ python: ["infisicalsdk"],
1586
+ envKeys: [/^INFISICAL_/]
1587
+ }
1588
+ },
1589
+ {
1590
+ kind: "OnePassword",
1591
+ label: "1Password",
1592
+ mode: "in-cli",
1593
+ signals: {
1594
+ npm: ["@1password/sdk"],
1595
+ python: ["onepassword-sdk"],
1596
+ envKeys: [/^ONEPASSWORD_/, /^OP_SERVICE_ACCOUNT_TOKEN$/]
1597
+ }
1598
+ },
1599
+ {
1600
+ kind: "Persona",
1601
+ label: "Persona",
1602
+ mode: "in-cli",
1603
+ signals: { envKeys: [/^PERSONA_/] }
1604
+ },
1605
+ {
1606
+ kind: "Svix",
1607
+ label: "Svix",
1608
+ mode: "in-cli",
1609
+ signals: {
1610
+ npm: ["svix"],
1611
+ python: ["svix"],
1612
+ envKeys: [/^SVIX_/]
1613
+ }
1614
+ },
1615
+ {
1616
+ kind: "Mux",
1617
+ label: "Mux",
1618
+ mode: "in-cli",
1619
+ signals: {
1620
+ npm: ["@mux/mux-node"],
1621
+ python: ["mux-python"],
1622
+ envKeys: [/^MUX_/]
1623
+ }
1624
+ },
1625
+ {
1626
+ kind: "Vapi",
1627
+ label: "Vapi",
1628
+ mode: "in-cli",
1629
+ signals: {
1630
+ npm: ["@vapi-ai/server-sdk"],
1631
+ python: ["vapi-server-sdk"],
1632
+ envKeys: [/^VAPI_/]
1633
+ }
1634
+ },
1635
+ {
1636
+ kind: "Aircall",
1637
+ label: "Aircall",
1638
+ mode: "in-cli",
1639
+ signals: { envKeys: [/^AIRCALL_/] }
1640
+ },
1641
+ {
1642
+ kind: "JustCall",
1643
+ label: "JustCall",
1644
+ mode: "in-cli",
1645
+ signals: { envKeys: [/^JUSTCALL_/] }
1646
+ },
1647
+ {
1648
+ kind: "WooCommerce",
1649
+ label: "WooCommerce",
1650
+ mode: "in-cli",
1651
+ signals: {
1652
+ npm: ["@woocommerce/woocommerce-rest-api"],
1653
+ python: ["woocommerce"],
1654
+ envKeys: [/^WOOCOMMERCE_/]
1655
+ }
1656
+ },
1657
+ {
1658
+ kind: "Recharge",
1659
+ label: "Recharge",
1660
+ mode: "in-cli",
1661
+ signals: { envKeys: [/^RECHARGE_/] }
1662
+ },
1663
+ {
1664
+ kind: "Commercetools",
1665
+ label: "commercetools",
1666
+ mode: "in-cli",
1667
+ signals: {
1668
+ npm: ["@commercetools/platform-sdk"],
1669
+ python: ["commercetools"],
1670
+ envKeys: [/^CTP_/, /^COMMERCETOOLS_/]
1671
+ }
1672
+ },
1673
+ {
1674
+ kind: "Webflow",
1675
+ label: "Webflow",
1676
+ mode: "in-cli",
1677
+ signals: {
1678
+ npm: ["webflow-api"],
1679
+ envKeys: [/^WEBFLOW_/]
1680
+ }
1681
+ },
1682
+ {
1683
+ kind: "Easypost",
1684
+ label: "EasyPost",
1685
+ mode: "in-cli",
1686
+ signals: {
1687
+ npm: ["@easypost/api"],
1688
+ python: ["easypost"],
1689
+ envKeys: [/^EASYPOST_/]
1690
+ }
1691
+ },
1692
+ {
1693
+ kind: "Shippo",
1694
+ label: "Shippo",
1695
+ mode: "in-cli",
1696
+ signals: {
1697
+ npm: ["shippo"],
1698
+ python: ["shippo"],
1699
+ envKeys: [/^SHIPPO_/]
1700
+ }
1701
+ },
1702
+ {
1703
+ kind: "ShipStation",
1704
+ label: "ShipStation",
1705
+ mode: "in-cli",
1706
+ signals: { envKeys: [/^SHIPSTATION_/] }
1707
+ },
1708
+ {
1709
+ kind: "Squarespace",
1710
+ label: "Squarespace",
1711
+ mode: "in-cli",
1712
+ signals: { envKeys: [/^SQUARESPACE_/] }
1713
+ },
1714
+ {
1715
+ kind: "Printify",
1716
+ label: "Printify",
1717
+ mode: "in-cli",
1718
+ signals: { envKeys: [/^PRINTIFY_/] }
1719
+ },
1720
+ {
1721
+ kind: "Freshdesk",
1722
+ label: "Freshdesk",
1723
+ mode: "in-cli",
1724
+ signals: {
1725
+ python: ["python-freshdesk"],
1726
+ envKeys: [/^FRESHDESK_/]
1727
+ }
1728
+ },
1729
+ {
1730
+ kind: "Front",
1731
+ label: "Front",
1732
+ mode: "in-cli",
1733
+ signals: { envKeys: [/^FRONTAPP_/, /^FRONT_API_/] }
1734
+ },
1735
+ {
1736
+ kind: "Gorgias",
1737
+ label: "Gorgias",
1738
+ mode: "in-cli",
1739
+ signals: { envKeys: [/^GORGIAS_/] }
1740
+ },
1741
+ {
1742
+ kind: "Chatwoot",
1743
+ label: "Chatwoot",
1744
+ mode: "in-cli",
1745
+ signals: { envKeys: [/^CHATWOOT_/] }
1746
+ },
1747
+ {
1748
+ kind: "Kustomer",
1749
+ label: "Kustomer",
1750
+ mode: "in-cli",
1751
+ signals: { envKeys: [/^KUSTOMER_/] }
1752
+ },
1753
+ {
1754
+ kind: "Plain",
1755
+ label: "Plain",
1756
+ mode: "in-cli",
1757
+ signals: {
1758
+ npm: ["@team-plain/typescript-sdk"],
1759
+ envKeys: [/^PLAIN_/]
1760
+ }
1761
+ },
1762
+ {
1763
+ kind: "Canny",
1764
+ label: "Canny",
1765
+ mode: "in-cli",
1766
+ signals: { envKeys: [/^CANNY_/] }
1767
+ },
1768
+ {
1769
+ kind: "Pylon",
1770
+ label: "Pylon",
1771
+ mode: "in-cli",
1772
+ signals: { envKeys: [/^PYLON_/] }
1773
+ },
1774
+ {
1775
+ kind: "GitLab",
1776
+ label: "GitLab",
1777
+ mode: "in-cli",
1778
+ signals: {
1779
+ npm: ["@gitbeaker/rest"],
1780
+ python: ["python-gitlab"],
1781
+ ruby: ["gitlab"],
1782
+ envKeys: [/^GITLAB_/]
1783
+ }
1784
+ },
1785
+ {
1786
+ kind: "Bitbucket",
1787
+ label: "Atlassian Bitbucket Cloud",
1788
+ mode: "in-cli",
1789
+ signals: {
1790
+ npm: ["bitbucket"],
1791
+ envKeys: [/^BITBUCKET_/]
1792
+ }
1793
+ },
1794
+ {
1795
+ kind: "Gitea",
1796
+ label: "Gitea",
1797
+ mode: "in-cli",
1798
+ signals: {
1799
+ npm: ["gitea-js"],
1800
+ envKeys: [/^GITEA_/]
1801
+ }
1802
+ },
1803
+ {
1804
+ kind: "Datadog",
1805
+ label: "Datadog",
1806
+ mode: "in-cli",
1807
+ signals: {
1808
+ npm: ["@datadog/datadog-api-client", "dd-trace"],
1809
+ python: ["datadog", "datadog-api-client"],
1810
+ ruby: ["dogapi"],
1811
+ envKeys: [
1812
+ /^DATADOG_/,
1813
+ /^DD_API_KEY$/,
1814
+ /^DD_APP_KEY$/
1815
+ ]
1816
+ }
1817
+ },
1818
+ {
1819
+ kind: "NewRelic",
1820
+ label: "New Relic",
1821
+ mode: "in-cli",
1822
+ signals: {
1823
+ npm: ["newrelic"],
1824
+ python: ["newrelic"],
1825
+ ruby: ["newrelic_rpm"],
1826
+ envKeys: [/^NEW_RELIC_/, /^NEWRELIC_/]
1827
+ }
1828
+ },
1829
+ {
1830
+ kind: "Cloudflare",
1831
+ label: "Cloudflare",
1832
+ mode: "in-cli",
1833
+ signals: {
1834
+ npm: ["cloudflare"],
1835
+ python: ["cloudflare"],
1836
+ envKeys: [/^CLOUDFLARE_/, /^CF_API_TOKEN$/]
1837
+ }
1838
+ },
1839
+ {
1840
+ kind: "Elasticsearch",
1841
+ label: "Elasticsearch",
1842
+ mode: "in-cli",
1843
+ signals: {
1844
+ npm: ["@elastic/elasticsearch"],
1845
+ python: ["elasticsearch"],
1846
+ ruby: ["elasticsearch"],
1847
+ envKeys: [/^ELASTICSEARCH_/]
1848
+ }
1849
+ },
1850
+ {
1851
+ kind: "Snyk",
1852
+ label: "Snyk",
1853
+ mode: "in-cli",
1854
+ signals: {
1855
+ npm: ["snyk"],
1856
+ python: ["pysnyk"],
1857
+ envKeys: [/^SNYK_/]
1858
+ }
1859
+ },
1860
+ {
1861
+ kind: "PagerDuty",
1862
+ label: "PagerDuty",
1863
+ mode: "in-cli",
1864
+ signals: {
1865
+ npm: ["@pagerduty/pdjs"],
1866
+ python: ["pdpyras"],
1867
+ envKeys: [/^PAGERDUTY_/, /^PD_API_KEY$/]
1868
+ }
1869
+ },
1870
+ {
1871
+ kind: "Opsgenie",
1872
+ label: "Opsgenie",
1873
+ mode: "in-cli",
1874
+ signals: { envKeys: [/^OPSGENIE_/] }
1875
+ },
1876
+ {
1877
+ kind: "IncidentIo",
1878
+ label: "incident.io",
1879
+ mode: "in-cli",
1880
+ signals: { envKeys: [/^INCIDENT_IO_/, /^INCIDENTIO_/] }
1881
+ },
1882
+ {
1883
+ kind: "Bugsnag",
1884
+ label: "Bugsnag",
1885
+ mode: "in-cli",
1886
+ signals: {
1887
+ npm: ["@bugsnag/js"],
1888
+ python: ["bugsnag"],
1889
+ ruby: ["bugsnag"],
1890
+ envKeys: [/^BUGSNAG_/]
1891
+ }
1892
+ },
1893
+ {
1894
+ kind: "Honeybadger",
1895
+ label: "Honeybadger",
1896
+ mode: "in-cli",
1897
+ signals: {
1898
+ npm: ["@honeybadger-io/js"],
1899
+ python: ["honeybadger"],
1900
+ ruby: ["honeybadger"],
1901
+ envKeys: [/^HONEYBADGER_/]
1902
+ }
1903
+ },
1904
+ {
1905
+ kind: "Raygun",
1906
+ label: "Raygun",
1907
+ mode: "in-cli",
1908
+ signals: {
1909
+ npm: ["raygun"],
1910
+ python: ["raygun4py"],
1911
+ ruby: ["raygun4ruby"],
1912
+ envKeys: [/^RAYGUN_/]
1913
+ }
1914
+ },
1915
+ {
1916
+ kind: "CircleCI",
1917
+ label: "CircleCI",
1918
+ mode: "in-cli",
1919
+ signals: { envKeys: [/^CIRCLECI_/, /^CIRCLE_TOKEN$/] }
1920
+ },
1921
+ {
1922
+ kind: "Upstash",
1923
+ label: "Upstash",
1924
+ mode: "in-cli",
1925
+ signals: {
1926
+ npm: ["@upstash/redis"],
1927
+ python: ["upstash-redis"],
1928
+ envKeys: [/^UPSTASH_/]
1929
+ }
1930
+ },
1931
+ {
1932
+ kind: "Vercel",
1933
+ label: "Vercel",
1934
+ mode: "in-cli",
1935
+ signals: {
1936
+ npm: ["@vercel/sdk"],
1937
+ envKeys: [/^VERCEL_API_TOKEN$/]
1938
+ }
1939
+ },
1940
+ {
1941
+ kind: "Pipedrive",
1942
+ label: "Pipedrive",
1943
+ mode: "in-cli",
1944
+ signals: {
1945
+ npm: ["pipedrive"],
1946
+ envKeys: [/^PIPEDRIVE_/]
1947
+ }
1948
+ },
1949
+ {
1950
+ kind: "Close",
1951
+ label: "Close",
1952
+ mode: "in-cli",
1953
+ signals: {
1954
+ python: ["closeio"],
1955
+ envKeys: [/^CLOSE_API_KEY$/]
1956
+ }
1957
+ },
1958
+ {
1959
+ kind: "Copper",
1960
+ label: "Copper",
1961
+ mode: "in-cli",
1962
+ signals: { envKeys: [/^COPPER_/] }
1963
+ },
1964
+ {
1965
+ kind: "Insightly",
1966
+ label: "Insightly",
1967
+ mode: "in-cli",
1968
+ signals: { envKeys: [/^INSIGHTLY_/] }
1969
+ },
1970
+ {
1971
+ kind: "Salesflare",
1972
+ label: "Salesflare",
1973
+ mode: "in-cli",
1974
+ signals: { envKeys: [/^SALESFLARE_/] }
1975
+ },
1976
+ {
1977
+ kind: "SalesLoft",
1978
+ label: "Salesloft",
1979
+ mode: "in-cli",
1980
+ signals: { envKeys: [/^SALESLOFT_/] }
1981
+ },
1982
+ {
1983
+ kind: "Attio",
1984
+ label: "Attio",
1985
+ mode: "in-cli",
1986
+ signals: {
1987
+ npm: ["attio"],
1988
+ envKeys: [/^ATTIO_/]
1989
+ }
1990
+ },
1991
+ {
1992
+ kind: "ActiveCampaign",
1993
+ label: "ActiveCampaign",
1994
+ mode: "in-cli",
1995
+ signals: { envKeys: [/^ACTIVECAMPAIGN_/, /^ACTIVE_CAMPAIGN_/] }
1996
+ },
1997
+ {
1998
+ kind: "Vitally",
1999
+ label: "Vitally",
2000
+ mode: "in-cli",
2001
+ signals: { envKeys: [/^VITALLY_/] }
2002
+ },
2003
+ {
2004
+ kind: "Asana",
2005
+ label: "Asana",
2006
+ mode: "in-cli",
2007
+ signals: {
2008
+ npm: ["asana"],
2009
+ python: ["asana"],
2010
+ envKeys: [/^ASANA_/]
2011
+ }
2012
+ },
2013
+ {
2014
+ kind: "Trello",
2015
+ label: "Trello",
2016
+ mode: "in-cli",
2017
+ signals: {
2018
+ npm: ["trello"],
2019
+ envKeys: [/^TRELLO_/]
2020
+ }
2021
+ },
2022
+ {
2023
+ kind: "Todoist",
2024
+ label: "Todoist",
2025
+ mode: "in-cli",
2026
+ signals: {
2027
+ npm: ["@doist/todoist-api-typescript"],
2028
+ python: ["todoist-api-python"],
2029
+ envKeys: [/^TODOIST_/]
2030
+ }
2031
+ },
2032
+ {
2033
+ kind: "Monday",
2034
+ label: "monday.com",
2035
+ mode: "in-cli",
2036
+ signals: {
2037
+ npm: ["@mondaydotcomorg/api"],
2038
+ envKeys: [/^MONDAY_/]
2039
+ }
2040
+ },
2041
+ {
2042
+ kind: "ClickUp",
2043
+ label: "ClickUp",
2044
+ mode: "in-cli",
2045
+ signals: { envKeys: [/^CLICKUP_/] }
2046
+ },
2047
+ {
2048
+ kind: "Height",
2049
+ label: "Height",
2050
+ mode: "in-cli",
2051
+ signals: { envKeys: [/^HEIGHT_API_KEY$/] }
2052
+ },
2053
+ {
2054
+ kind: "Shortcut",
2055
+ label: "Shortcut",
2056
+ mode: "in-cli",
2057
+ signals: {
2058
+ npm: ["@shortcut/client"],
2059
+ envKeys: [/^SHORTCUT_/]
2060
+ }
2061
+ },
2062
+ {
2063
+ kind: "Jira",
2064
+ label: "Jira",
2065
+ mode: "in-cli",
2066
+ signals: {
2067
+ npm: ["jira-client"],
2068
+ python: ["jira", "atlassian-python-api"],
2069
+ envKeys: [/^JIRA_/]
2070
+ }
2071
+ },
2072
+ {
2073
+ kind: "Confluence",
2074
+ label: "Confluence",
2075
+ mode: "in-cli",
2076
+ signals: { envKeys: [/^CONFLUENCE_/] }
2077
+ },
2078
+ {
2079
+ kind: "Airtable",
2080
+ label: "Airtable",
2081
+ mode: "in-cli",
2082
+ signals: {
2083
+ npm: ["airtable"],
2084
+ python: ["pyairtable"],
2085
+ envKeys: [/^AIRTABLE_/]
2086
+ }
2087
+ },
2088
+ {
2089
+ kind: "Smartsheet",
2090
+ label: "Smartsheet",
2091
+ mode: "in-cli",
2092
+ signals: {
2093
+ npm: ["smartsheet"],
2094
+ python: ["smartsheet-python-sdk"],
2095
+ envKeys: [/^SMARTSHEET_/]
2096
+ }
2097
+ },
2098
+ {
2099
+ kind: "Coda",
2100
+ label: "Coda",
2101
+ mode: "in-cli",
2102
+ signals: { envKeys: [/^CODA_API_/] }
2103
+ },
2104
+ {
2105
+ kind: "Productboard",
2106
+ label: "Productboard",
2107
+ mode: "in-cli",
2108
+ signals: { envKeys: [/^PRODUCTBOARD_/] }
2109
+ },
2110
+ {
2111
+ kind: "Calendly",
2112
+ label: "Calendly",
2113
+ mode: "in-cli",
2114
+ signals: { envKeys: [/^CALENDLY_/] }
2115
+ },
2116
+ {
2117
+ kind: "CalCom",
2118
+ label: "Cal.com",
2119
+ mode: "in-cli",
2120
+ signals: { envKeys: [/^CALCOM_/, /^CAL_API_KEY$/] }
2121
+ },
2122
+ {
2123
+ kind: "Eventbrite",
2124
+ label: "Eventbrite",
2125
+ mode: "in-cli",
2126
+ signals: {
2127
+ python: ["eventbrite"],
2128
+ envKeys: [/^EVENTBRITE_/]
2129
+ }
2130
+ },
2131
+ {
2132
+ kind: "BambooHR",
2133
+ label: "BambooHR",
2134
+ mode: "in-cli",
2135
+ signals: {
2136
+ python: ["pybamboohr"],
2137
+ envKeys: [/^BAMBOOHR_/, /^BAMBOO_HR_/]
2138
+ }
2139
+ },
2140
+ {
2141
+ kind: "Personio",
2142
+ label: "Personio",
2143
+ mode: "in-cli",
2144
+ signals: { envKeys: [/^PERSONIO_/] }
2145
+ },
2146
+ {
2147
+ kind: "Rippling",
2148
+ label: "Rippling",
2149
+ mode: "in-cli",
2150
+ signals: { envKeys: [/^RIPPLING_/] }
2151
+ },
2152
+ {
2153
+ kind: "Greenhouse",
2154
+ label: "Greenhouse",
2155
+ mode: "in-cli",
2156
+ signals: { envKeys: [/^GREENHOUSE_/] }
2157
+ },
2158
+ {
2159
+ kind: "Ashby",
2160
+ label: "Ashby",
2161
+ mode: "in-cli",
2162
+ signals: { envKeys: [/^ASHBY_/] }
2163
+ },
2164
+ {
2165
+ kind: "Workable",
2166
+ label: "Workable",
2167
+ mode: "in-cli",
2168
+ signals: { envKeys: [/^WORKABLE_/] }
2169
+ },
2170
+ {
2171
+ kind: "GoogleAds",
2172
+ label: "Google Ads",
2173
+ mode: "deep-link",
2174
+ signals: {
2175
+ npm: ["google-ads-api"],
2176
+ python: ["google-ads"],
2177
+ envKeys: [/^GOOGLE_ADS_/]
2178
+ }
2179
+ },
2180
+ {
2181
+ kind: "MetaAds",
2182
+ label: "Meta Ads",
2183
+ mode: "deep-link",
2184
+ signals: {
2185
+ npm: ["facebook-nodejs-business-sdk"],
2186
+ python: ["facebook-business"],
2187
+ envKeys: [/^META_ADS_/, /^FACEBOOK_ADS_/]
2188
+ }
2189
+ },
2190
+ {
2191
+ kind: "LinkedinAds",
2192
+ label: "LinkedIn Ads",
2193
+ mode: "deep-link",
2194
+ signals: { envKeys: [/^LINKEDIN_ADS_/] }
2195
+ },
2196
+ {
2197
+ kind: "TikTokAds",
2198
+ label: "TikTok Ads",
2199
+ mode: "deep-link",
2200
+ signals: { envKeys: [/^TIKTOK_ADS_/] }
2201
+ },
2202
+ {
2203
+ kind: "RedditAds",
2204
+ label: "Reddit Ads",
2205
+ mode: "deep-link",
2206
+ signals: { envKeys: [/^REDDIT_ADS_/] }
2207
+ },
2208
+ {
2209
+ kind: "PinterestAds",
2210
+ label: "Pinterest Ads",
2211
+ mode: "deep-link",
2212
+ signals: { envKeys: [/^PINTEREST_ADS_/] }
2213
+ },
2214
+ {
2215
+ kind: "BingAds",
2216
+ label: "Bing Ads",
2217
+ mode: "deep-link",
2218
+ signals: {
2219
+ python: ["bingads"],
2220
+ envKeys: [/^BING_ADS_/, /^MICROSOFT_ADS_/]
2221
+ }
2222
+ },
2223
+ {
2224
+ kind: "AmazonAds",
2225
+ label: "Amazon Ads",
2226
+ mode: "deep-link",
2227
+ signals: { envKeys: [/^AMAZON_ADS_/] }
2228
+ },
2229
+ {
2230
+ kind: "GoogleAnalytics",
2231
+ label: "Google Analytics",
2232
+ mode: "deep-link",
2233
+ signals: {
2234
+ npm: ["react-ga4"],
2235
+ python: ["google-analytics-data"],
2236
+ envKeys: [/^GOOGLE_ANALYTICS_/, /^GA4_/]
2237
+ }
2238
+ },
2239
+ {
2240
+ kind: "GoogleSearchConsole",
2241
+ label: "Google Search Console",
2242
+ mode: "deep-link",
2243
+ signals: { envKeys: [/^SEARCH_CONSOLE_/, /^GSC_/] }
2244
+ },
2245
+ {
2246
+ kind: "AppsFlyer",
2247
+ label: "AppsFlyer",
2248
+ mode: "in-cli",
2249
+ signals: {
2250
+ npm: ["react-native-appsflyer"],
2251
+ envKeys: [/^APPSFLYER_/]
2252
+ }
2253
+ }
2254
+ ];
2255
+ //#endregion
2256
+ //#region src/lib/warehouse-sources/detect.ts
2257
+ /**
2258
+ * Data warehouse source detection.
2259
+ *
2260
+ * Scans a project for codebase signals (npm/python/ruby deps, `.env` key
2261
+ * names) and matches them against the `SOURCE_DETECTORS` registry. Pure
2262
+ * function: no store mutations, no UI calls. Reads files locally — only the
2263
+ * wizard process does this; the agent never sees secret values.
2264
+ *
2265
+ * Note we only read `.env` KEY NAMES, never values.
2266
+ */
2267
+ const MAX_DEPTH = 3;
2268
+ /**
2269
+ * Detect which warehouse sources the project at `installDir` appears to use.
2270
+ * Returns one `DetectedSource` per matched registry entry (kinds are unique,
2271
+ * so the result is naturally deduped).
2272
+ */
2273
+ function detectWarehouseSources(installDir) {
2274
+ const signals = collectSignals(installDir);
2275
+ const detected = [];
2276
+ for (const detector of SOURCE_DETECTORS) {
2277
+ const match = matchDetector(detector, signals);
2278
+ if (match) detected.push({
2279
+ kind: detector.kind,
2280
+ label: detector.label,
2281
+ mode: detector.mode,
2282
+ matchedSignal: match
2283
+ });
2284
+ }
2285
+ return detected;
2286
+ }
2287
+ /** Returns a human-readable description of the first matching signal, or null. */
2288
+ function matchDetector(detector, signals) {
2289
+ const { npm, python, ruby, envKeys } = detector.signals;
2290
+ const npmHit = npm?.find((dep) => signals.npm.has(dep));
2291
+ if (npmHit) return `found \`${npmHit}\` in package.json`;
2292
+ const pyHit = python?.find((dep) => signals.python.has(dep));
2293
+ if (pyHit) return `found \`${pyHit}\` in Python dependencies`;
2294
+ const rubyHit = ruby?.find((gem) => signals.ruby.has(gem));
2295
+ if (rubyHit) return `found \`${rubyHit}\` in Gemfile`;
2296
+ if (envKeys) {
2297
+ for (const key of signals.envKeys) if (envKeys.some((re) => re.test(key))) return `found \`${key}\` in .env`;
2298
+ }
2299
+ return null;
2300
+ }
2301
+ function collectSignals(installDir) {
2302
+ const signals = {
2303
+ npm: /* @__PURE__ */ new Set(),
2304
+ python: /* @__PURE__ */ new Set(),
2305
+ ruby: /* @__PURE__ */ new Set(),
2306
+ envKeys: /* @__PURE__ */ new Set()
2307
+ };
2308
+ walkProjectFiles(installDir, (name, fullPath) => ingestFile(name, fullPath, signals), MAX_DEPTH);
2309
+ return signals;
2310
+ }
2311
+ /**
2312
+ * Route a file to the right parser BY NAME, reading its contents only when the
2313
+ * name matches one of the ~6 manifests we care about. Checking the name first
2314
+ * avoids slurping every file in the tree (lockfiles, binaries, assets) into
2315
+ * memory just to discard it.
2316
+ */
2317
+ function ingestFile(name, fullPath, signals) {
2318
+ const ingest = ingestorFor(name);
2319
+ if (!ingest) return;
2320
+ const content = safeReadFile(fullPath);
2321
+ if (content === null) return;
2322
+ ingest(content, signals);
2323
+ }
2324
+ /** Pick the parser for a manifest filename, or null if it's not one we read. */
2325
+ function ingestorFor(name) {
2326
+ if (name === "package.json") return addNpmDeps;
2327
+ if (name === "requirements.txt") return (c, s) => parseRequirementsTxt(c).forEach((d) => s.python.add(d));
2328
+ if (name === "pyproject.toml") return (c, s) => parsePyprojectToml(c).forEach((d) => s.python.add(d));
2329
+ if (name === "Pipfile") return (c, s) => parsePipfile(c).forEach((d) => s.python.add(d));
2330
+ if (name === "Gemfile") return (c, s) => parseGemfile(c).forEach((g) => s.ruby.add(g));
2331
+ if (name.startsWith(".env")) return (c, s) => parseEnvKeys(c).forEach((k) => s.envKeys.add(k));
2332
+ return null;
2333
+ }
2334
+ function addNpmDeps(content, signals) {
2335
+ try {
2336
+ const pkg = JSON.parse(content);
2337
+ for (const dep of Object.keys({
2338
+ ...pkg.dependencies,
2339
+ ...pkg.devDependencies
2340
+ })) signals.npm.add(dep);
2341
+ } catch (error) {
2342
+ analytics.captureException(error instanceof Error ? error : new Error(String(error)), { step: "detectWarehouseSources.parsePackageJson" });
2343
+ }
2344
+ }
2345
+ /** Extract gem names from `gem 'name'` declarations. */
2346
+ function parseGemfile(content) {
2347
+ const gems = [];
2348
+ for (const match of content.matchAll(/^\s*gem\s+['"]([^'"]+)['"]/gm)) gems.push(match[1]);
2349
+ return gems;
2350
+ }
2351
+ /** Extract KEY NAMES from a dotenv file. Values are intentionally discarded. */
2352
+ function parseEnvKeys(content) {
2353
+ const keys = [];
2354
+ for (const line of content.split("\n")) {
2355
+ const trimmed = line.trim();
2356
+ if (!trimmed || trimmed.startsWith("#")) continue;
2357
+ const match = trimmed.match(/^(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=/);
2358
+ if (match) keys.push(match[1]);
2359
+ }
2360
+ return keys;
2361
+ }
2362
+ //#endregion
2363
+ //#region src/lib/programs/warehouse-source/detect.ts
2364
+ /**
2365
+ * Warehouse-source program detection step.
2366
+ *
2367
+ * Thin adapter over `detectWarehouseSources` that writes results into
2368
+ * frameworkContext for the intro screen, plus the `[ABORT]` cases the
2369
+ * data-warehouse-source-setup skill can emit.
2370
+ */
2371
+ /** frameworkContext key holding the detected sources (set on success). */
2372
+ const DETECTED_WAREHOUSE_SOURCES_KEY = "detectedWarehouseSources";
2373
+ /**
2374
+ * Read the detected sources out of frameworkContext. Single accessor shared by
2375
+ * the intro screen and the prompt builder so the key + cast live in one place.
2376
+ */
2377
+ function getDetectedWarehouseSources(session) {
2378
+ return session.frameworkContext["detectedWarehouseSources"] ?? [];
2379
+ }
2380
+ /** `[ABORT] <reason>` cases the skill can emit. */
2381
+ const WAREHOUSE_ABORT_CASES = [{
2382
+ match: /^no data sources? detected\.?$/i,
2383
+ message: "No data source detected",
2384
+ 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.).",
2385
+ docsUrl: "https://posthog.com/docs/data-warehouse"
2386
+ }, {
2387
+ match: /^source creation failed\.?$/i,
2388
+ message: "Source creation failed",
2389
+ 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.",
2390
+ docsUrl: "https://posthog.com/docs/data-warehouse"
2391
+ }];
2392
+ /**
2393
+ * Scan `session.installDir` for warehouse-source signals. Writes the detected
2394
+ * sources (or a `detectError`) into frameworkContext for the intro screen.
2395
+ */
2396
+ function detectWarehousePrerequisites(session, setFrameworkContext) {
2397
+ const fail = (error) => setFrameworkContext("detectError", error);
2398
+ const installDir = session.installDir;
2399
+ if (!existsSync(installDir)) {
2400
+ fail({
2401
+ kind: "bad-directory",
2402
+ path: installDir,
2403
+ reason: "missing"
2404
+ });
2405
+ return;
2406
+ }
2407
+ try {
2408
+ if (!statSync(installDir).isDirectory()) {
2409
+ fail({
2410
+ kind: "bad-directory",
2411
+ path: installDir,
2412
+ reason: "not-dir"
2413
+ });
2414
+ return;
2415
+ }
2416
+ } catch (error) {
2417
+ analytics.captureException(error instanceof Error ? error : new Error(String(error)), {
2418
+ step: "detectWarehousePrerequisites.stat",
2419
+ path: installDir
2420
+ });
2421
+ fail({
2422
+ kind: "bad-directory",
2423
+ path: installDir,
2424
+ reason: "unreadable"
2425
+ });
2426
+ return;
2427
+ }
2428
+ const sources = detectWarehouseSources(installDir);
2429
+ if (sources.length === 0) {
2430
+ fail({ kind: "no-sources" });
2431
+ return;
2432
+ }
2433
+ analytics.setTag("warehouse_source_kinds", sources.map((s) => s.kind).join(","));
2434
+ analytics.setTag("warehouse_source_modes", sources.map((s) => `${s.kind}:${s.mode}`).join(","));
2435
+ analytics.setTag("warehouse_source_count", sources.length);
2436
+ setFrameworkContext(DETECTED_WAREHOUSE_SOURCES_KEY, sources);
2437
+ }
2438
+ //#endregion
519
2439
  //#region src/lib/programs/shared/health-check-step.ts
520
2440
  function healthCheckReady(session) {
521
2441
  if (!session.readinessResult) return false;
@@ -574,8 +2494,41 @@ async function detectPostHogIntegration(ctx) {
574
2494
  if (versionResult.supported !== true) ctx.setUnsupportedVersion(versionResult.supported);
575
2495
  }
576
2496
  for (const feature of discoverFeatures(installDir)) ctx.addDiscoveredFeature(feature);
2497
+ detectWarehouseSourcesForSuggestion(ctx, installDir);
577
2498
  ctx.setDetectionComplete();
578
2499
  }
2500
+ /**
2501
+ * Scan for data warehouse source signals (Postgres, Stripe, Hubspot, …) and,
2502
+ * when found, stash them for a `wizard warehouse` suggestion on the outro.
2503
+ *
2504
+ * Deliberately a suggestion, not an inline agent run: a second credential-
2505
+ * collecting agent run before the outro could `process.exit()` on any of its
2506
+ * failure paths and cost the user the success outro on a run where PostHog
2507
+ * installed fine.
2508
+ *
2509
+ * Calls `detectWarehouseSources` (a pure scan) rather than the warehouse
2510
+ * program's `detectWarehousePrerequisites`, which writes a `detectError` when
2511
+ * it finds nothing — that's right for `wizard warehouse` but here would show a
2512
+ * spurious error and trip the CI prerequisites abort. No sources is a no-op.
2513
+ *
2514
+ * Best-effort: never let a scan failure break the surrounding detect step.
2515
+ */
2516
+ function detectWarehouseSourcesForSuggestion(ctx, installDir) {
2517
+ try {
2518
+ const sources = detectWarehouseSources(installDir);
2519
+ analytics.wizardCapture("warehouse sources detected", {
2520
+ warehouse_source_count: sources.length,
2521
+ warehouse_source_kinds: sources.map((s) => s.kind),
2522
+ warehouse_source_modes: sources.map((s) => s.mode)
2523
+ });
2524
+ if (sources.length === 0) return;
2525
+ analytics.setTag("warehouse_source_kinds", sources.map((s) => s.kind).join(","));
2526
+ analytics.setTag("warehouse_source_count", sources.length);
2527
+ ctx.setFrameworkContext(DETECTED_WAREHOUSE_SOURCES_KEY, sources);
2528
+ } catch (error) {
2529
+ analytics.captureException(error instanceof Error ? error : new Error(String(error)), { step: "detectWarehouseSourcesForSuggestion" });
2530
+ }
2531
+ }
579
2532
  //#endregion
580
2533
  //#region src/lib/programs/posthog-integration/steps.ts
581
2534
  function needsSetup(session) {
@@ -1662,6 +3615,41 @@ function resolveContinueUrl(sess, host, deepLink) {
1662
3615
  if (typeof deepLink === "string" && deepLink) return deepLink;
1663
3616
  return withUtm(`${host.appHost}/products?source=wizard`, "outro-continue");
1664
3617
  }
3618
+ /**
3619
+ * Outro suggestion for data sources found in the project but not connected.
3620
+ *
3621
+ * A pointer at `wizard warehouse`, not an inline flow. Connecting a source
3622
+ * needs interactive credential collection, and chaining that as a second agent
3623
+ * run before the outro would let any of its terminal failure paths
3624
+ * `process.exit()` — costing the user the success outro and the post-outro
3625
+ * MCP / Slack steps on a run where PostHog installed fine.
3626
+ *
3627
+ * Returns undefined when nothing was detected, so the outro is unchanged for
3628
+ * projects with no connectable source.
3629
+ */
3630
+ function buildWarehouseNextSteps(sess) {
3631
+ const sources = getDetectedWarehouseSources(sess);
3632
+ if (sources.length === 0) return void 0;
3633
+ return {
3634
+ heading: "Query your other data in PostHog:",
3635
+ items: [`Found in this project: ${sources.map((s) => s.label).join(", ")}`, "Import it into the data warehouse with: npx @posthog/wizard warehouse"]
3636
+ };
3637
+ }
3638
+ /**
3639
+ * Prompt fragment asking the agent to note the detected data sources in the
3640
+ * setup report's checklist.
3641
+ *
3642
+ * Empty string when nothing was detected, so the prompt is byte-identical to
3643
+ * today for projects with no connectable source. Best-effort by nature — the
3644
+ * agent may word it differently or skip it. That is acceptable here precisely
3645
+ * because it is a note in a report: the outro `nextSteps` bullet carries the
3646
+ * same information deterministically, so nothing is lost if the agent drops it.
3647
+ */
3648
+ function warehouseReportInstruction(sess) {
3649
+ const sources = getDetectedWarehouseSources(sess);
3650
+ if (sources.length === 0) return "";
3651
+ return `Finally: this project also contains data sources PostHog can import (${sources.map((s) => s.label).join(", ")}). In the setup report's "Verify before merging" checklist, add one item noting these were found and that \`npx @posthog/wizard warehouse\` will connect them to PostHog's data warehouse. Do not attempt to set them up yourself in this run.`;
3652
+ }
1665
3653
  const SETUP_REPORT_FILE = "posthog-setup-report.md";
1666
3654
  const posthogIntegrationConfig = {
1667
3655
  command: "integrate",
@@ -1766,13 +3754,13 @@ STEP 5: Set up environment variables for PostHog using the wizard-tools MCP serv
1766
3754
 
1767
3755
  Important: Use the detect_package_manager tool (from the wizard-tools MCP server) to determine which package manager the project uses, then run its install command to add the SDK. Do not manually search for lockfiles or config files. If a file already EXISTS, read it immediately before you edit or overwrite it — writing from a stale read causes a tool failure. Creating a brand-new file needs no prior read: never read a path that does not exist yet; just write it.
1768
3756
 
1769
-
3757
+ ${warehouseReportInstruction(session)}
1770
3758
  `;
1771
3759
  },
1772
3760
  postRun: async (sess, credentials) => {
1773
3761
  const envVars = config.environment.getEnvVars(credentials.projectApiKey, credentials.host.apiHost);
1774
3762
  if (config.environment.uploadToHosting) {
1775
- const { uploadEnvironmentVariablesStep } = await import("./steps-D07HUQyE.js");
3763
+ const { uploadEnvironmentVariablesStep } = await import("./steps-DyEKYM4I.js");
1776
3764
  const uploadedEnvVars = await uploadEnvironmentVariablesStep(envVars, {
1777
3765
  integration: config.metadata.integration,
1778
3766
  session: sess
@@ -1804,6 +3792,7 @@ Important: Use the detect_package_manager tool (from the wizard-tools MCP server
1804
3792
  changes: [...config.ui.getOutroChanges(frameworkContext), Object.keys(envVars).length > 0 ? "Added environment variables to .env file" : ""].filter(Boolean),
1805
3793
  docsUrl: config.metadata.docsUrl,
1806
3794
  continueUrl,
3795
+ nextSteps: buildWarehouseNextSteps(sess),
1807
3796
  notebookUrl: sess.notebookUrl ?? void 0,
1808
3797
  handoffPrompt: buildCodingAgentPrompt(SETUP_REPORT_FILE)
1809
3798
  };
@@ -1826,6 +3815,6 @@ const integrationRunStep = {
1826
3815
  isComplete: (session) => session.runPhase === "completed" || session.runPhase === "error"
1827
3816
  };
1828
3817
  //#endregion
1829
- export { parseRequirementsTxt as S, detectProjectsWithAgent as _, LINE_CHART_BLOCK as a, parsePipfile as b, TextBlock as c, isLinesBlock as d, isObjectBlock as f, detectIntegrationProjects as g, HEALTH_CHECK_STEP as h, FUNNEL_BLOCK as i, computeVisibleRange as l, Icons as m, integrationRunStep as n, PRODUCT_SUITE_BLOCK as o, Colors as p, posthogIntegrationConfig as r, StatusPeekTrigger as s, SETUP_REPORT_FILE as t, isClearBlock as u, resolveProjectDir as v, parsePyprojectToml as x, gatherFrameworkContext as y };
3818
+ export { gatherFrameworkContext as S, detectWarehousePrerequisites as _, LINE_CHART_BLOCK as a, detectProjectsWithAgent as b, TextBlock as c, isLinesBlock as d, isObjectBlock as f, WAREHOUSE_ABORT_CASES as g, HEALTH_CHECK_STEP as h, FUNNEL_BLOCK as i, computeVisibleRange as l, Icons as m, integrationRunStep as n, PRODUCT_SUITE_BLOCK as o, Colors as p, posthogIntegrationConfig as r, StatusPeekTrigger as s, SETUP_REPORT_FILE as t, isClearBlock as u, getDetectedWarehouseSources as v, resolveProjectDir as x, detectIntegrationProjects as y };
1830
3819
 
1831
- //# sourceMappingURL=posthog-integration-dmWJZ8mj.js.map
3820
+ //# sourceMappingURL=posthog-integration-Do997QON.js.map