@posthog/wizard 1.34.0 → 1.35.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/dist/bin.js +9 -0
  2. package/dist/bin.js.map +1 -1
  3. package/dist/src/javascript-node/javascript-node-wizard-agent.d.ts +4 -0
  4. package/dist/src/javascript-node/javascript-node-wizard-agent.js +61 -0
  5. package/dist/src/javascript-node/javascript-node-wizard-agent.js.map +1 -0
  6. package/dist/src/javascript-web/javascript-web-wizard-agent.d.ts +3 -0
  7. package/dist/src/javascript-web/javascript-web-wizard-agent.js +150 -0
  8. package/dist/src/javascript-web/javascript-web-wizard-agent.js.map +1 -0
  9. package/dist/src/javascript-web/utils.d.ts +23 -0
  10. package/dist/src/javascript-web/utils.js +99 -0
  11. package/dist/src/javascript-web/utils.js.map +1 -0
  12. package/dist/src/lib/__tests__/agent-interface.test.js +1 -0
  13. package/dist/src/lib/__tests__/agent-interface.test.js.map +1 -1
  14. package/dist/src/lib/agent-interface.d.ts +5 -0
  15. package/dist/src/lib/agent-interface.js +19 -2
  16. package/dist/src/lib/agent-interface.js.map +1 -1
  17. package/dist/src/lib/agent-runner.js +8 -4
  18. package/dist/src/lib/agent-runner.js.map +1 -1
  19. package/dist/src/lib/api.js +3 -0
  20. package/dist/src/lib/api.js.map +1 -1
  21. package/dist/src/lib/constants.d.ts +4 -1
  22. package/dist/src/lib/constants.js +13 -1
  23. package/dist/src/lib/constants.js.map +1 -1
  24. package/dist/src/lib/middleware/benchmark.d.ts +54 -0
  25. package/dist/src/lib/middleware/benchmark.js +49 -0
  26. package/dist/src/lib/middleware/benchmark.js.map +1 -0
  27. package/dist/src/lib/middleware/benchmarks/cache-tracker.d.ts +44 -0
  28. package/dist/src/lib/middleware/benchmarks/cache-tracker.js +81 -0
  29. package/dist/src/lib/middleware/benchmarks/cache-tracker.js.map +1 -0
  30. package/dist/src/lib/middleware/benchmarks/compaction-tracker.d.ts +29 -0
  31. package/dist/src/lib/middleware/benchmarks/compaction-tracker.js +60 -0
  32. package/dist/src/lib/middleware/benchmarks/compaction-tracker.js.map +1 -0
  33. package/dist/src/lib/middleware/benchmarks/context-size-tracker.d.ts +26 -0
  34. package/dist/src/lib/middleware/benchmarks/context-size-tracker.js +56 -0
  35. package/dist/src/lib/middleware/benchmarks/context-size-tracker.js.map +1 -0
  36. package/dist/src/lib/middleware/benchmarks/cost-tracker.d.ts +16 -0
  37. package/dist/src/lib/middleware/benchmarks/cost-tracker.js +76 -0
  38. package/dist/src/lib/middleware/benchmarks/cost-tracker.js.map +1 -0
  39. package/dist/src/lib/middleware/benchmarks/duration-tracker.d.ts +20 -0
  40. package/dist/src/lib/middleware/benchmarks/duration-tracker.js +40 -0
  41. package/dist/src/lib/middleware/benchmarks/duration-tracker.js.map +1 -0
  42. package/dist/src/lib/middleware/benchmarks/index.d.ts +9 -0
  43. package/dist/src/lib/middleware/benchmarks/index.js +60 -0
  44. package/dist/src/lib/middleware/benchmarks/index.js.map +1 -0
  45. package/dist/src/lib/middleware/benchmarks/json-writer.d.ts +15 -0
  46. package/dist/src/lib/middleware/benchmarks/json-writer.js +145 -0
  47. package/dist/src/lib/middleware/benchmarks/json-writer.js.map +1 -0
  48. package/dist/src/lib/middleware/benchmarks/summary.d.ts +9 -0
  49. package/dist/src/lib/middleware/benchmarks/summary.js +106 -0
  50. package/dist/src/lib/middleware/benchmarks/summary.js.map +1 -0
  51. package/dist/src/lib/middleware/benchmarks/token-tracker.d.ts +40 -0
  52. package/dist/src/lib/middleware/benchmarks/token-tracker.js +77 -0
  53. package/dist/src/lib/middleware/benchmarks/token-tracker.js.map +1 -0
  54. package/dist/src/lib/middleware/benchmarks/turn-counter.d.ts +34 -0
  55. package/dist/src/lib/middleware/benchmarks/turn-counter.js +59 -0
  56. package/dist/src/lib/middleware/benchmarks/turn-counter.js.map +1 -0
  57. package/dist/src/lib/middleware/config.d.ts +24 -0
  58. package/dist/src/lib/middleware/config.js +78 -0
  59. package/dist/src/lib/middleware/config.js.map +1 -0
  60. package/dist/src/lib/middleware/index.d.ts +11 -0
  61. package/dist/src/lib/middleware/index.js +18 -0
  62. package/dist/src/lib/middleware/index.js.map +1 -0
  63. package/dist/src/lib/middleware/phase-detector.d.ts +7 -0
  64. package/dist/src/lib/middleware/phase-detector.js +64 -0
  65. package/dist/src/lib/middleware/phase-detector.js.map +1 -0
  66. package/dist/src/lib/middleware/pipeline.d.ts +29 -0
  67. package/dist/src/lib/middleware/pipeline.js +82 -0
  68. package/dist/src/lib/middleware/pipeline.js.map +1 -0
  69. package/dist/src/lib/middleware/types.d.ts +40 -0
  70. package/dist/src/lib/middleware/types.js +9 -0
  71. package/dist/src/lib/middleware/types.js.map +1 -0
  72. package/dist/src/lib/registry.js +4 -0
  73. package/dist/src/lib/registry.js.map +1 -1
  74. package/dist/src/python/python-wizard-agent.js +1 -78
  75. package/dist/src/python/python-wizard-agent.js.map +1 -1
  76. package/dist/src/run.d.ts +2 -0
  77. package/dist/src/run.js +8 -0
  78. package/dist/src/run.js.map +1 -1
  79. package/dist/src/utils/clack-utils.d.ts +1 -1
  80. package/dist/src/utils/clack-utils.js +26 -7
  81. package/dist/src/utils/clack-utils.js.map +1 -1
  82. package/dist/src/utils/debug.d.ts +11 -3
  83. package/dist/src/utils/debug.js +25 -6
  84. package/dist/src/utils/debug.js.map +1 -1
  85. package/dist/src/utils/oauth.js +1 -0
  86. package/dist/src/utils/oauth.js.map +1 -1
  87. package/dist/src/utils/types.d.ts +11 -0
  88. package/dist/src/utils/types.js.map +1 -1
  89. package/package.json +1 -1
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Benchmark configuration loader.
3
+ *
4
+ * Loads .benchmark-config.json from the working directory with sensible defaults.
5
+ * All fields are optional — missing fields fall back to defaults.
6
+ */
7
+ export interface BenchmarkConfig {
8
+ /** Enable/disable individual metric plugins */
9
+ plugins: Record<string, boolean>;
10
+ output: {
11
+ /** Path for the benchmark JSON output file */
12
+ benchmarkPath: string;
13
+ /** Whether to write the benchmark JSON file */
14
+ benchmarkEnabled: boolean;
15
+ /** Path for the main wizard debug log file */
16
+ logPath: string;
17
+ /** Whether to write the main wizard debug log */
18
+ logEnabled: boolean;
19
+ /** Suppress benchmark console output (disables the summary plugin) */
20
+ suppressWizardLogs: boolean;
21
+ };
22
+ }
23
+ export declare function loadBenchmarkConfig(installDir: string): BenchmarkConfig;
24
+ export declare function getDefaultConfig(): BenchmarkConfig;
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ /**
3
+ * Benchmark configuration loader.
4
+ *
5
+ * Loads .benchmark-config.json from the working directory with sensible defaults.
6
+ * All fields are optional — missing fields fall back to defaults.
7
+ */
8
+ var __importDefault = (this && this.__importDefault) || function (mod) {
9
+ return (mod && mod.__esModule) ? mod : { "default": mod };
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.loadBenchmarkConfig = loadBenchmarkConfig;
13
+ exports.getDefaultConfig = getDefaultConfig;
14
+ const fs_1 = __importDefault(require("fs"));
15
+ const path_1 = __importDefault(require("path"));
16
+ const debug_1 = require("../../utils/debug");
17
+ const agent_interface_1 = require("../agent-interface");
18
+ const DEFAULT_CONFIG = {
19
+ plugins: {
20
+ tokens: true,
21
+ cache: true,
22
+ turns: true,
23
+ compactions: true,
24
+ contextSize: true,
25
+ cost: true,
26
+ duration: true,
27
+ summary: true,
28
+ jsonWriter: true,
29
+ },
30
+ output: {
31
+ benchmarkPath: '/tmp/posthog-wizard-benchmark.json',
32
+ benchmarkEnabled: true,
33
+ logPath: '/tmp/posthog-wizard.log',
34
+ logEnabled: true,
35
+ suppressWizardLogs: false,
36
+ },
37
+ };
38
+ function loadBenchmarkConfig(installDir) {
39
+ const configPath = process.env.POSTHOG_WIZARD_BENCHMARK_CONFIG ??
40
+ path_1.default.join(installDir, '.benchmark-config.json');
41
+ try {
42
+ const raw = fs_1.default.readFileSync(configPath, 'utf-8');
43
+ const parsed = JSON.parse(raw);
44
+ const config = {
45
+ plugins: { ...DEFAULT_CONFIG.plugins, ...parsed.plugins },
46
+ output: { ...DEFAULT_CONFIG.output, ...parsed.output },
47
+ };
48
+ // Env var overrides for parallel runs
49
+ if (process.env.POSTHOG_WIZARD_BENCHMARK_FILE) {
50
+ config.output.benchmarkPath = process.env.POSTHOG_WIZARD_BENCHMARK_FILE;
51
+ }
52
+ if (process.env.POSTHOG_WIZARD_LOG_FILE) {
53
+ config.output.logPath = process.env.POSTHOG_WIZARD_LOG_FILE;
54
+ }
55
+ // If benchmark output is disabled, disable the jsonWriter plugin
56
+ if (!config.output.benchmarkEnabled) {
57
+ config.plugins.jsonWriter = false;
58
+ }
59
+ (0, debug_1.logToFile)(`${agent_interface_1.AgentSignals.BENCHMARK} Loaded config from ${configPath}`);
60
+ return config;
61
+ }
62
+ catch {
63
+ // No config file or invalid JSON — use defaults
64
+ const config = structuredClone(DEFAULT_CONFIG);
65
+ // Env var overrides
66
+ if (process.env.POSTHOG_WIZARD_BENCHMARK_FILE) {
67
+ config.output.benchmarkPath = process.env.POSTHOG_WIZARD_BENCHMARK_FILE;
68
+ }
69
+ if (process.env.POSTHOG_WIZARD_LOG_FILE) {
70
+ config.output.logPath = process.env.POSTHOG_WIZARD_LOG_FILE;
71
+ }
72
+ return config;
73
+ }
74
+ }
75
+ function getDefaultConfig() {
76
+ return structuredClone(DEFAULT_CONFIG);
77
+ }
78
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../../src/lib/middleware/config.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;;;AA6CH,kDAyCC;AAED,4CAEC;AAxFD,4CAAoB;AACpB,gDAAwB;AACxB,6CAA8C;AAC9C,wDAAkD;AAmBlD,MAAM,cAAc,GAAoB;IACtC,OAAO,EAAE;QACP,MAAM,EAAE,IAAI;QACZ,KAAK,EAAE,IAAI;QACX,KAAK,EAAE,IAAI;QACX,WAAW,EAAE,IAAI;QACjB,WAAW,EAAE,IAAI;QACjB,IAAI,EAAE,IAAI;QACV,QAAQ,EAAE,IAAI;QACd,OAAO,EAAE,IAAI;QACb,UAAU,EAAE,IAAI;KACjB;IACD,MAAM,EAAE;QACN,aAAa,EAAE,oCAAoC;QACnD,gBAAgB,EAAE,IAAI;QACtB,OAAO,EAAE,yBAAyB;QAClC,UAAU,EAAE,IAAI;QAChB,kBAAkB,EAAE,KAAK;KAC1B;CACF,CAAC;AAEF,SAAgB,mBAAmB,CAAC,UAAkB;IACpD,MAAM,UAAU,GACd,OAAO,CAAC,GAAG,CAAC,+BAA+B;QAC3C,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,wBAAwB,CAAC,CAAC;IAClD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QACjD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/B,MAAM,MAAM,GAAoB;YAC9B,OAAO,EAAE,EAAE,GAAG,cAAc,CAAC,OAAO,EAAE,GAAG,MAAM,CAAC,OAAO,EAAE;YACzD,MAAM,EAAE,EAAE,GAAG,cAAc,CAAC,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE;SACvD,CAAC;QAEF,sCAAsC;QACtC,IAAI,OAAO,CAAC,GAAG,CAAC,6BAA6B,EAAE,CAAC;YAC9C,MAAM,CAAC,MAAM,CAAC,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC;QAC1E,CAAC;QACD,IAAI,OAAO,CAAC,GAAG,CAAC,uBAAuB,EAAE,CAAC;YACxC,MAAM,CAAC,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC;QAC9D,CAAC;QAED,iEAAiE;QACjE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC;YACpC,MAAM,CAAC,OAAO,CAAC,UAAU,GAAG,KAAK,CAAC;QACpC,CAAC;QAED,IAAA,iBAAS,EAAC,GAAG,8BAAY,CAAC,SAAS,uBAAuB,UAAU,EAAE,CAAC,CAAC;QACxE,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,gDAAgD;QAChD,MAAM,MAAM,GAAG,eAAe,CAAC,cAAc,CAAC,CAAC;QAE/C,oBAAoB;QACpB,IAAI,OAAO,CAAC,GAAG,CAAC,6BAA6B,EAAE,CAAC;YAC9C,MAAM,CAAC,MAAM,CAAC,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC;QAC1E,CAAC;QACD,IAAI,OAAO,CAAC,GAAG,CAAC,uBAAuB,EAAE,CAAC;YACxC,MAAM,CAAC,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC;QAC9D,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;AACH,CAAC;AAED,SAAgB,gBAAgB;IAC9B,OAAO,eAAe,CAAC,cAAc,CAAC,CAAC;AACzC,CAAC","sourcesContent":["/**\n * Benchmark configuration loader.\n *\n * Loads .benchmark-config.json from the working directory with sensible defaults.\n * All fields are optional — missing fields fall back to defaults.\n */\n\nimport fs from 'fs';\nimport path from 'path';\nimport { logToFile } from '../../utils/debug';\nimport { AgentSignals } from '../agent-interface';\n\nexport interface BenchmarkConfig {\n /** Enable/disable individual metric plugins */\n plugins: Record<string, boolean>;\n output: {\n /** Path for the benchmark JSON output file */\n benchmarkPath: string;\n /** Whether to write the benchmark JSON file */\n benchmarkEnabled: boolean;\n /** Path for the main wizard debug log file */\n logPath: string;\n /** Whether to write the main wizard debug log */\n logEnabled: boolean;\n /** Suppress benchmark console output (disables the summary plugin) */\n suppressWizardLogs: boolean;\n };\n}\n\nconst DEFAULT_CONFIG: BenchmarkConfig = {\n plugins: {\n tokens: true,\n cache: true,\n turns: true,\n compactions: true,\n contextSize: true,\n cost: true,\n duration: true,\n summary: true,\n jsonWriter: true,\n },\n output: {\n benchmarkPath: '/tmp/posthog-wizard-benchmark.json',\n benchmarkEnabled: true,\n logPath: '/tmp/posthog-wizard.log',\n logEnabled: true,\n suppressWizardLogs: false,\n },\n};\n\nexport function loadBenchmarkConfig(installDir: string): BenchmarkConfig {\n const configPath =\n process.env.POSTHOG_WIZARD_BENCHMARK_CONFIG ??\n path.join(installDir, '.benchmark-config.json');\n try {\n const raw = fs.readFileSync(configPath, 'utf-8');\n const parsed = JSON.parse(raw);\n const config: BenchmarkConfig = {\n plugins: { ...DEFAULT_CONFIG.plugins, ...parsed.plugins },\n output: { ...DEFAULT_CONFIG.output, ...parsed.output },\n };\n\n // Env var overrides for parallel runs\n if (process.env.POSTHOG_WIZARD_BENCHMARK_FILE) {\n config.output.benchmarkPath = process.env.POSTHOG_WIZARD_BENCHMARK_FILE;\n }\n if (process.env.POSTHOG_WIZARD_LOG_FILE) {\n config.output.logPath = process.env.POSTHOG_WIZARD_LOG_FILE;\n }\n\n // If benchmark output is disabled, disable the jsonWriter plugin\n if (!config.output.benchmarkEnabled) {\n config.plugins.jsonWriter = false;\n }\n\n logToFile(`${AgentSignals.BENCHMARK} Loaded config from ${configPath}`);\n return config;\n } catch {\n // No config file or invalid JSON — use defaults\n const config = structuredClone(DEFAULT_CONFIG);\n\n // Env var overrides\n if (process.env.POSTHOG_WIZARD_BENCHMARK_FILE) {\n config.output.benchmarkPath = process.env.POSTHOG_WIZARD_BENCHMARK_FILE;\n }\n if (process.env.POSTHOG_WIZARD_LOG_FILE) {\n config.output.logPath = process.env.POSTHOG_WIZARD_LOG_FILE;\n }\n\n return config;\n }\n}\n\nexport function getDefaultConfig(): BenchmarkConfig {\n return structuredClone(DEFAULT_CONFIG);\n}\n"]}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Middleware system for wizard agent runs.
3
+ */
4
+ export { MiddlewarePipeline } from './pipeline';
5
+ export { PhaseDetector } from './phase-detector';
6
+ export type { Middleware, MiddlewareContext, MiddlewareStore } from './types';
7
+ export { loadBenchmarkConfig, getDefaultConfig } from './config';
8
+ export type { BenchmarkConfig } from './config';
9
+ export { createBenchmarkPipeline } from './benchmark';
10
+ export type { BenchmarkData, StepUsage } from './benchmark';
11
+ export { createPluginsFromConfig } from './benchmarks';
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ /**
3
+ * Middleware system for wizard agent runs.
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createPluginsFromConfig = exports.createBenchmarkPipeline = exports.getDefaultConfig = exports.loadBenchmarkConfig = exports.PhaseDetector = exports.MiddlewarePipeline = void 0;
7
+ var pipeline_1 = require("./pipeline");
8
+ Object.defineProperty(exports, "MiddlewarePipeline", { enumerable: true, get: function () { return pipeline_1.MiddlewarePipeline; } });
9
+ var phase_detector_1 = require("./phase-detector");
10
+ Object.defineProperty(exports, "PhaseDetector", { enumerable: true, get: function () { return phase_detector_1.PhaseDetector; } });
11
+ var config_1 = require("./config");
12
+ Object.defineProperty(exports, "loadBenchmarkConfig", { enumerable: true, get: function () { return config_1.loadBenchmarkConfig; } });
13
+ Object.defineProperty(exports, "getDefaultConfig", { enumerable: true, get: function () { return config_1.getDefaultConfig; } });
14
+ var benchmark_1 = require("./benchmark");
15
+ Object.defineProperty(exports, "createBenchmarkPipeline", { enumerable: true, get: function () { return benchmark_1.createBenchmarkPipeline; } });
16
+ var benchmarks_1 = require("./benchmarks");
17
+ Object.defineProperty(exports, "createPluginsFromConfig", { enumerable: true, get: function () { return benchmarks_1.createPluginsFromConfig; } });
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/lib/middleware/index.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAEH,uCAAgD;AAAvC,8GAAA,kBAAkB,OAAA;AAC3B,mDAAiD;AAAxC,+GAAA,aAAa,OAAA;AAGtB,mCAAiE;AAAxD,6GAAA,mBAAmB,OAAA;AAAE,0GAAA,gBAAgB,OAAA;AAG9C,yCAAsD;AAA7C,oHAAA,uBAAuB,OAAA;AAGhC,2CAAuD;AAA9C,qHAAA,uBAAuB,OAAA","sourcesContent":["/**\n * Middleware system for wizard agent runs.\n */\n\nexport { MiddlewarePipeline } from './pipeline';\nexport { PhaseDetector } from './phase-detector';\nexport type { Middleware, MiddlewareContext, MiddlewareStore } from './types';\n\nexport { loadBenchmarkConfig, getDefaultConfig } from './config';\nexport type { BenchmarkConfig } from './config';\n\nexport { createBenchmarkPipeline } from './benchmark';\nexport type { BenchmarkData, StepUsage } from './benchmark';\n\nexport { createPluginsFromConfig } from './benchmarks';\n"]}
@@ -0,0 +1,7 @@
1
+ /** Phase transitions from [STATUS] in assistant text. Keep in sync with workflow "Status to report" bullets. */
2
+ export declare class PhaseDetector {
3
+ private currentPhase;
4
+ detect(message: any): string | null;
5
+ private getNextPhase;
6
+ reset(): void;
7
+ }
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ /** Phase transitions from [STATUS] in assistant text. Keep in sync with workflow "Status to report" bullets. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.PhaseDetector = void 0;
5
+ const PHASES_ORDER = [
6
+ '1.0-begin',
7
+ '1.1-edit',
8
+ '1.2-revise',
9
+ '1.3-conclude',
10
+ ];
11
+ const STATUS_PHRASES_BY_PHASE = {
12
+ '1.0-begin': [
13
+ 'Checking project structure',
14
+ 'Verifying PostHog dependencies',
15
+ 'Generating events based on project',
16
+ ],
17
+ '1.1-edit': ['Inserting PostHog capture code'],
18
+ '1.2-revise': [
19
+ 'Finding and correcting errors',
20
+ 'Report details of any errors you fix',
21
+ 'Linting, building and prettying',
22
+ ],
23
+ '1.3-conclude': ['Configured dashboard', 'Created setup report'],
24
+ };
25
+ class PhaseDetector {
26
+ currentPhase = 'setup';
27
+ detect(message) {
28
+ if (message.type !== 'assistant')
29
+ return null;
30
+ const nextPhase = this.getNextPhase();
31
+ if (nextPhase === null)
32
+ return null;
33
+ const content = message.message?.content;
34
+ if (!Array.isArray(content))
35
+ return null;
36
+ for (const block of content) {
37
+ if (block.type !== 'text' || typeof block.text !== 'string')
38
+ continue;
39
+ if (!block.text.includes('[STATUS]'))
40
+ continue;
41
+ const phrases = STATUS_PHRASES_BY_PHASE[nextPhase];
42
+ for (const phrase of phrases) {
43
+ if (block.text.includes(phrase)) {
44
+ this.currentPhase = nextPhase;
45
+ return nextPhase;
46
+ }
47
+ }
48
+ }
49
+ return null;
50
+ }
51
+ getNextPhase() {
52
+ if (this.currentPhase === 'setup')
53
+ return '1.0-begin';
54
+ const i = PHASES_ORDER.indexOf(this.currentPhase);
55
+ if (i < 0 || i >= PHASES_ORDER.length - 1)
56
+ return null;
57
+ return PHASES_ORDER[i + 1];
58
+ }
59
+ reset() {
60
+ this.currentPhase = 'setup';
61
+ }
62
+ }
63
+ exports.PhaseDetector = PhaseDetector;
64
+ //# sourceMappingURL=phase-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"phase-detector.js","sourceRoot":"","sources":["../../../../src/lib/middleware/phase-detector.ts"],"names":[],"mappings":";AAAA,gHAAgH;;;AAEhH,MAAM,YAAY,GAAG;IACnB,WAAW;IACX,UAAU;IACV,YAAY;IACZ,cAAc;CACN,CAAC;AAEX,MAAM,uBAAuB,GAC3B;IACE,WAAW,EAAE;QACX,4BAA4B;QAC5B,gCAAgC;QAChC,oCAAoC;KACrC;IACD,UAAU,EAAE,CAAC,gCAAgC,CAAC;IAC9C,YAAY,EAAE;QACZ,+BAA+B;QAC/B,sCAAsC;QACtC,iCAAiC;KAClC;IACD,cAAc,EAAE,CAAC,sBAAsB,EAAE,sBAAsB,CAAC;CACjE,CAAC;AAEJ,MAAa,aAAa;IAChB,YAAY,GAA4C,OAAO,CAAC;IAExE,MAAM,CAAC,OAAY;QACjB,IAAI,OAAO,CAAC,IAAI,KAAK,WAAW;YAAE,OAAO,IAAI,CAAC;QAE9C,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QACtC,IAAI,SAAS,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QAEpC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC;QACzC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;YAAE,OAAO,IAAI,CAAC;QAEzC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ;gBAAE,SAAS;YACtE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;gBAAE,SAAS;YAE/C,MAAM,OAAO,GAAG,uBAAuB,CAAC,SAAS,CAAC,CAAC;YACnD,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;gBAC7B,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;oBAChC,IAAI,CAAC,YAAY,GAAG,SAAS,CAAC;oBAC9B,OAAO,SAAS,CAAC;gBACnB,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,YAAY;QAClB,IAAI,IAAI,CAAC,YAAY,KAAK,OAAO;YAAE,OAAO,WAAW,CAAC;QACtD,MAAM,CAAC,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAClD,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;QACvD,OAAO,YAAY,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7B,CAAC;IAED,KAAK;QACH,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC;IAC9B,CAAC;CACF;AAtCD,sCAsCC","sourcesContent":["/** Phase transitions from [STATUS] in assistant text. Keep in sync with workflow \"Status to report\" bullets. */\n\nconst PHASES_ORDER = [\n '1.0-begin',\n '1.1-edit',\n '1.2-revise',\n '1.3-conclude',\n] as const;\n\nconst STATUS_PHRASES_BY_PHASE: Record<(typeof PHASES_ORDER)[number], string[]> =\n {\n '1.0-begin': [\n 'Checking project structure',\n 'Verifying PostHog dependencies',\n 'Generating events based on project',\n ],\n '1.1-edit': ['Inserting PostHog capture code'],\n '1.2-revise': [\n 'Finding and correcting errors',\n 'Report details of any errors you fix',\n 'Linting, building and prettying',\n ],\n '1.3-conclude': ['Configured dashboard', 'Created setup report'],\n };\n\nexport class PhaseDetector {\n private currentPhase: 'setup' | (typeof PHASES_ORDER)[number] = 'setup';\n\n detect(message: any): string | null {\n if (message.type !== 'assistant') return null;\n\n const nextPhase = this.getNextPhase();\n if (nextPhase === null) return null;\n\n const content = message.message?.content;\n if (!Array.isArray(content)) return null;\n\n for (const block of content) {\n if (block.type !== 'text' || typeof block.text !== 'string') continue;\n if (!block.text.includes('[STATUS]')) continue;\n\n const phrases = STATUS_PHRASES_BY_PHASE[nextPhase];\n for (const phrase of phrases) {\n if (block.text.includes(phrase)) {\n this.currentPhase = nextPhase;\n return nextPhase;\n }\n }\n }\n\n return null;\n }\n\n private getNextPhase(): (typeof PHASES_ORDER)[number] | null {\n if (this.currentPhase === 'setup') return '1.0-begin';\n const i = PHASES_ORDER.indexOf(this.currentPhase);\n if (i < 0 || i >= PHASES_ORDER.length - 1) return null;\n return PHASES_ORDER[i + 1];\n }\n\n reset(): void {\n this.currentPhase = 'setup';\n }\n}\n"]}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Middleware pipeline orchestrator.
3
+ *
4
+ * Implements the same { onMessage, finalize } interface that runAgent() expects,
5
+ * while internally dispatching to an ordered list of middleware plugins.
6
+ */
7
+ import { PhaseDetector } from './phase-detector';
8
+ import type { Middleware, SDKMessage } from './types';
9
+ export declare class MiddlewarePipeline {
10
+ private middlewares;
11
+ private store;
12
+ private phaseDetector;
13
+ private autoDetectPhases;
14
+ private _currentPhase;
15
+ private _currentPhaseFreshContext;
16
+ constructor(middlewares: Middleware[], opts?: {
17
+ phaseDetector?: PhaseDetector;
18
+ autoDetectPhases?: boolean;
19
+ });
20
+ /** Feed an SDK message through all middleware (satisfies tracker.onMessage) */
21
+ onMessage(message: SDKMessage): void;
22
+ /** Finalize the run (satisfies tracker.finalize) */
23
+ finalize(resultMessage: any, totalDurationMs: number): any;
24
+ /** Explicit phase start (for phased runner support) */
25
+ startPhase(name: string, freshContext: boolean): void;
26
+ private transitionPhase;
27
+ private createContext;
28
+ private createStore;
29
+ }
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ /**
3
+ * Middleware pipeline orchestrator.
4
+ *
5
+ * Implements the same { onMessage, finalize } interface that runAgent() expects,
6
+ * while internally dispatching to an ordered list of middleware plugins.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.MiddlewarePipeline = void 0;
10
+ const phase_detector_1 = require("./phase-detector");
11
+ class MiddlewarePipeline {
12
+ middlewares;
13
+ store = new Map();
14
+ phaseDetector;
15
+ autoDetectPhases;
16
+ _currentPhase = 'setup';
17
+ _currentPhaseFreshContext = true;
18
+ constructor(middlewares, opts) {
19
+ this.middlewares = middlewares;
20
+ this.phaseDetector = opts?.phaseDetector ?? new phase_detector_1.PhaseDetector();
21
+ this.autoDetectPhases = opts?.autoDetectPhases ?? true;
22
+ const ctx = this.createContext();
23
+ for (const mw of this.middlewares) {
24
+ mw.onInit?.(ctx);
25
+ }
26
+ }
27
+ /** Feed an SDK message through all middleware (satisfies tracker.onMessage) */
28
+ onMessage(message) {
29
+ // Phase detection first — updates context before middleware sees it
30
+ if (this.autoDetectPhases) {
31
+ const newPhase = this.phaseDetector.detect(message);
32
+ if (newPhase && newPhase !== this._currentPhase) {
33
+ this.transitionPhase(newPhase, false);
34
+ }
35
+ }
36
+ const ctx = this.createContext();
37
+ const storeHandle = this.createStore();
38
+ for (const mw of this.middlewares) {
39
+ mw.onMessage?.(message, ctx, storeHandle);
40
+ }
41
+ }
42
+ /** Finalize the run (satisfies tracker.finalize) */
43
+ finalize(resultMessage, totalDurationMs) {
44
+ const ctx = this.createContext();
45
+ const storeHandle = this.createStore();
46
+ let result;
47
+ for (const mw of this.middlewares) {
48
+ const r = mw.onFinalize?.(resultMessage, totalDurationMs, ctx, storeHandle);
49
+ if (r !== undefined)
50
+ result = r;
51
+ }
52
+ return result;
53
+ }
54
+ /** Explicit phase start (for phased runner support) */
55
+ startPhase(name, freshContext) {
56
+ this.transitionPhase(name, freshContext);
57
+ }
58
+ transitionPhase(newPhase, freshContext) {
59
+ const oldPhase = this._currentPhase;
60
+ this._currentPhase = newPhase;
61
+ this._currentPhaseFreshContext = freshContext;
62
+ const ctx = this.createContext();
63
+ const storeHandle = this.createStore();
64
+ for (const mw of this.middlewares) {
65
+ mw.onPhaseTransition?.(oldPhase, newPhase, ctx, storeHandle);
66
+ }
67
+ }
68
+ createContext() {
69
+ return {
70
+ currentPhase: this._currentPhase,
71
+ currentPhaseFreshContext: this._currentPhaseFreshContext,
72
+ get: (key) => this.store.get(key),
73
+ };
74
+ }
75
+ createStore() {
76
+ return {
77
+ set: (key, value) => this.store.set(key, value),
78
+ };
79
+ }
80
+ }
81
+ exports.MiddlewarePipeline = MiddlewarePipeline;
82
+ //# sourceMappingURL=pipeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../../../../src/lib/middleware/pipeline.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Middleware pipeline orchestrator.\n *\n * Implements the same { onMessage, finalize } interface that runAgent() expects,\n * while internally dispatching to an ordered list of middleware plugins.\n */\n\nimport { PhaseDetector } from './phase-detector';\nimport type {\n Middleware,\n MiddlewareContext,\n MiddlewareStore,\n SDKMessage,\n} from './types';\n\nexport class MiddlewarePipeline {\n private middlewares: Middleware[];\n private store = new Map<string, unknown>();\n private phaseDetector: PhaseDetector;\n private autoDetectPhases: boolean;\n private _currentPhase = 'setup';\n private _currentPhaseFreshContext = true;\n\n constructor(\n middlewares: Middleware[],\n opts?: { phaseDetector?: PhaseDetector; autoDetectPhases?: boolean },\n ) {\n this.middlewares = middlewares;\n this.phaseDetector = opts?.phaseDetector ?? new PhaseDetector();\n this.autoDetectPhases = opts?.autoDetectPhases ?? true;\n\n const ctx = this.createContext();\n for (const mw of this.middlewares) {\n mw.onInit?.(ctx);\n }\n }\n\n /** Feed an SDK message through all middleware (satisfies tracker.onMessage) */\n onMessage(message: SDKMessage): void {\n // Phase detection first — updates context before middleware sees it\n if (this.autoDetectPhases) {\n const newPhase = this.phaseDetector.detect(message);\n if (newPhase && newPhase !== this._currentPhase) {\n this.transitionPhase(newPhase, false);\n }\n }\n\n const ctx = this.createContext();\n const storeHandle = this.createStore();\n for (const mw of this.middlewares) {\n mw.onMessage?.(message, ctx, storeHandle);\n }\n }\n\n /** Finalize the run (satisfies tracker.finalize) */\n finalize(resultMessage: any, totalDurationMs: number): any {\n const ctx = this.createContext();\n const storeHandle = this.createStore();\n let result: any;\n for (const mw of this.middlewares) {\n const r = mw.onFinalize?.(\n resultMessage,\n totalDurationMs,\n ctx,\n storeHandle,\n );\n if (r !== undefined) result = r;\n }\n return result;\n }\n\n /** Explicit phase start (for phased runner support) */\n startPhase(name: string, freshContext: boolean): void {\n this.transitionPhase(name, freshContext);\n }\n\n private transitionPhase(newPhase: string, freshContext: boolean): void {\n const oldPhase = this._currentPhase;\n this._currentPhase = newPhase;\n this._currentPhaseFreshContext = freshContext;\n const ctx = this.createContext();\n const storeHandle = this.createStore();\n for (const mw of this.middlewares) {\n mw.onPhaseTransition?.(oldPhase, newPhase, ctx, storeHandle);\n }\n }\n\n private createContext(): MiddlewareContext {\n return {\n currentPhase: this._currentPhase,\n currentPhaseFreshContext: this._currentPhaseFreshContext,\n get: <T>(key: string) => this.store.get(key) as T | undefined,\n };\n }\n\n private createStore(): MiddlewareStore {\n return {\n set: (key: string, value: unknown) => this.store.set(key, value),\n };\n }\n}\n"]}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Middleware system types for wizard agent runs.
3
+ *
4
+ * Middleware receives lifecycle events (messages, phase transitions, finalize)
5
+ * and can publish data to a shared store for downstream middleware to read.
6
+ */
7
+ import type clack from '../../utils/clack';
8
+ export type SDKMessage = any;
9
+ /** Read-only shared state available to all middleware */
10
+ export interface MiddlewareContext {
11
+ /** Current detected phase name */
12
+ readonly currentPhase: string;
13
+ /** Whether the current phase started with fresh context (new query) */
14
+ readonly currentPhaseFreshContext: boolean;
15
+ /** Read a value from the shared store (published by upstream middleware) */
16
+ get<T>(key: string): T | undefined;
17
+ }
18
+ /** Write handle for middleware to publish data to the shared store */
19
+ export interface MiddlewareStore {
20
+ set(key: string, value: unknown): void;
21
+ }
22
+ /** Lifecycle hooks a middleware can implement */
23
+ export interface Middleware {
24
+ /** Unique name for this middleware (used in config and store keys) */
25
+ readonly name: string;
26
+ /** Called once when the pipeline initializes */
27
+ onInit?(ctx: MiddlewareContext): void;
28
+ /** Called for every SDK message */
29
+ onMessage?(message: SDKMessage, ctx: MiddlewareContext, store: MiddlewareStore): void;
30
+ /** Called when a phase transition is detected */
31
+ onPhaseTransition?(fromPhase: string, toPhase: string, ctx: MiddlewareContext, store: MiddlewareStore): void;
32
+ /** Called at the end of the agent run. Return value from last middleware is used. */
33
+ onFinalize?(resultMessage: any, totalDurationMs: number, ctx: MiddlewareContext, store: MiddlewareStore): any;
34
+ }
35
+ /** Options bag passed to middleware factories during construction */
36
+ export interface MiddlewareFactoryOptions {
37
+ spinner?: ReturnType<typeof clack.spinner>;
38
+ outputPath?: string;
39
+ phased?: boolean;
40
+ }
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ /**
3
+ * Middleware system types for wizard agent runs.
4
+ *
5
+ * Middleware receives lifecycle events (messages, phase transitions, finalize)
6
+ * and can publish data to a shared store for downstream middleware to read.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/lib/middleware/types.ts"],"names":[],"mappings":";AAAA;;;;;GAKG","sourcesContent":["/**\n * Middleware system types for wizard agent runs.\n *\n * Middleware receives lifecycle events (messages, phase transitions, finalize)\n * and can publish data to a shared store for downstream middleware to read.\n */\n\nimport type clack from '../../utils/clack';\n\nexport type SDKMessage = any;\n\n/** Read-only shared state available to all middleware */\nexport interface MiddlewareContext {\n /** Current detected phase name */\n readonly currentPhase: string;\n /** Whether the current phase started with fresh context (new query) */\n readonly currentPhaseFreshContext: boolean;\n /** Read a value from the shared store (published by upstream middleware) */\n get<T>(key: string): T | undefined;\n}\n\n/** Write handle for middleware to publish data to the shared store */\nexport interface MiddlewareStore {\n set(key: string, value: unknown): void;\n}\n\n/** Lifecycle hooks a middleware can implement */\nexport interface Middleware {\n /** Unique name for this middleware (used in config and store keys) */\n readonly name: string;\n /** Called once when the pipeline initializes */\n onInit?(ctx: MiddlewareContext): void;\n /** Called for every SDK message */\n onMessage?(\n message: SDKMessage,\n ctx: MiddlewareContext,\n store: MiddlewareStore,\n ): void;\n /** Called when a phase transition is detected */\n onPhaseTransition?(\n fromPhase: string,\n toPhase: string,\n ctx: MiddlewareContext,\n store: MiddlewareStore,\n ): void;\n /** Called at the end of the agent run. Return value from last middleware is used. */\n onFinalize?(\n resultMessage: any,\n totalDurationMs: number,\n ctx: MiddlewareContext,\n store: MiddlewareStore,\n ): any;\n}\n\n/** Options bag passed to middleware factories during construction */\nexport interface MiddlewareFactoryOptions {\n spinner?: ReturnType<typeof clack.spinner>;\n outputPath?: string;\n phased?: boolean;\n}\n"]}
@@ -21,6 +21,8 @@ const android_wizard_agent_1 = require("../android/android-wizard-agent");
21
21
  const rails_wizard_agent_1 = require("../rails/rails-wizard-agent");
22
22
  const python_wizard_agent_1 = require("../python/python-wizard-agent");
23
23
  const ruby_wizard_agent_1 = require("../ruby/ruby-wizard-agent");
24
+ const javascript_node_wizard_agent_1 = require("../javascript-node/javascript-node-wizard-agent");
25
+ const javascript_web_wizard_agent_1 = require("../javascript-web/javascript-web-wizard-agent");
24
26
  exports.FRAMEWORK_REGISTRY = {
25
27
  [constants_1.Integration.nextjs]: nextjs_wizard_agent_1.NEXTJS_AGENT_CONFIG,
26
28
  [constants_1.Integration.nuxt]: nuxt_wizard_agent_1.NUXT_AGENT_CONFIG,
@@ -41,5 +43,7 @@ exports.FRAMEWORK_REGISTRY = {
41
43
  [constants_1.Integration.rails]: rails_wizard_agent_1.RAILS_AGENT_CONFIG,
42
44
  [constants_1.Integration.python]: python_wizard_agent_1.PYTHON_AGENT_CONFIG,
43
45
  [constants_1.Integration.ruby]: ruby_wizard_agent_1.RUBY_AGENT_CONFIG,
46
+ [constants_1.Integration.javascriptNode]: javascript_node_wizard_agent_1.JAVASCRIPT_NODE_AGENT_CONFIG,
47
+ [constants_1.Integration.javascript_web]: javascript_web_wizard_agent_1.JAVASCRIPT_WEB_AGENT_CONFIG,
44
48
  };
45
49
  //# sourceMappingURL=registry.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/lib/registry.ts"],"names":[],"mappings":";;;AACA,2CAA0C;AAC1C,uEAAoE;AACpE,iEAA8D;AAC9D,8DAA2D;AAC3D,yFAAsF;AACtF,kGAA+F;AAC/F,+FAA4F;AAC5F,yFAAsF;AACtF,0EAAuE;AACvE,oEAAiE;AACjE,uEAAoE;AACpE,oEAAiE;AACjE,0EAAuE;AACvE,0EAAuE;AACvE,uEAAuE;AACvE,oEAAiE;AACjE,0EAAuE;AACvE,oEAAiE;AACjE,uEAAoE;AACpE,iEAA8D;AAEjD,QAAA,kBAAkB,GAAyC;IACtE,CAAC,uBAAW,CAAC,MAAM,CAAC,EAAE,yCAAmB;IACzC,CAAC,uBAAW,CAAC,IAAI,CAAC,EAAE,qCAAiB;IACrC,CAAC,uBAAW,CAAC,GAAG,CAAC,EAAE,mCAAgB;IACnC,CAAC,uBAAW,CAAC,aAAa,CAAC,EAAE,yDAA2B;IACxD,CAAC,uBAAW,CAAC,WAAW,CAAC,EAAE,qDAAyB;IACpD,CAAC,uBAAW,CAAC,cAAc,CAAC,EAAE,2DAA4B;IAC1D,CAAC,uBAAW,CAAC,WAAW,CAAC,EAAE,qDAAyB;IACpD,CAAC,uBAAW,CAAC,OAAO,CAAC,EAAE,2CAAoB;IAC3C,CAAC,uBAAW,CAAC,KAAK,CAAC,EAAE,uCAAkB;IACvC,CAAC,uBAAW,CAAC,MAAM,CAAC,EAAE,yCAAmB;IACzC,CAAC,uBAAW,CAAC,KAAK,CAAC,EAAE,uCAAkB;IACvC,CAAC,uBAAW,CAAC,OAAO,CAAC,EAAE,2CAAoB;IAC3C,CAAC,uBAAW,CAAC,OAAO,CAAC,EAAE,2CAAoB;IAC3C,CAAC,uBAAW,CAAC,SAAS,CAAC,EAAE,4CAAsB;IAC/C,CAAC,uBAAW,CAAC,KAAK,CAAC,EAAE,uCAAkB;IACvC,CAAC,uBAAW,CAAC,OAAO,CAAC,EAAE,2CAAoB;IAC3C,CAAC,uBAAW,CAAC,KAAK,CAAC,EAAE,uCAAkB;IACvC,CAAC,uBAAW,CAAC,MAAM,CAAC,EAAE,yCAAmB;IACzC,CAAC,uBAAW,CAAC,IAAI,CAAC,EAAE,qCAAiB;CACtC,CAAC","sourcesContent":["import type { FrameworkConfig } from './framework-config';\nimport { Integration } from './constants';\nimport { NEXTJS_AGENT_CONFIG } from '../nextjs/nextjs-wizard-agent';\nimport { NUXT_AGENT_CONFIG } from '../nuxt/nuxt-wizard-agent';\nimport { VUE_AGENT_CONFIG } from '../vue/vue-wizard-agent';\nimport { REACT_ROUTER_AGENT_CONFIG } from '../react-router/react-router-wizard-agent';\nimport { TANSTACK_ROUTER_AGENT_CONFIG } from '../tanstack-router/tanstack-router-wizard-agent';\nimport { TANSTACK_START_AGENT_CONFIG } from '../tanstack-start/tanstack-start-wizard-agent';\nimport { REACT_NATIVE_AGENT_CONFIG } from '../react-native/react-native-wizard-agent';\nimport { ANGULAR_AGENT_CONFIG } from '../angular/angular-wizard-agent';\nimport { ASTRO_AGENT_CONFIG } from '../astro/astro-wizard-agent';\nimport { DJANGO_AGENT_CONFIG } from '../django/django-wizard-agent';\nimport { FLASK_AGENT_CONFIG } from '../flask/flask-wizard-agent';\nimport { FASTAPI_AGENT_CONFIG } from '../fastapi/fastapi-wizard-agent';\nimport { LARAVEL_AGENT_CONFIG } from '../laravel/laravel-wizard-agent';\nimport { SVELTEKIT_AGENT_CONFIG } from '../svelte/svelte-wizard-agent';\nimport { SWIFT_AGENT_CONFIG } from '../swift/swift-wizard-agent';\nimport { ANDROID_AGENT_CONFIG } from '../android/android-wizard-agent';\nimport { RAILS_AGENT_CONFIG } from '../rails/rails-wizard-agent';\nimport { PYTHON_AGENT_CONFIG } from '../python/python-wizard-agent';\nimport { RUBY_AGENT_CONFIG } from '../ruby/ruby-wizard-agent';\n\nexport const FRAMEWORK_REGISTRY: Record<Integration, FrameworkConfig> = {\n [Integration.nextjs]: NEXTJS_AGENT_CONFIG,\n [Integration.nuxt]: NUXT_AGENT_CONFIG,\n [Integration.vue]: VUE_AGENT_CONFIG,\n [Integration.tanstackStart]: TANSTACK_START_AGENT_CONFIG,\n [Integration.reactRouter]: REACT_ROUTER_AGENT_CONFIG,\n [Integration.tanstackRouter]: TANSTACK_ROUTER_AGENT_CONFIG,\n [Integration.reactNative]: REACT_NATIVE_AGENT_CONFIG,\n [Integration.angular]: ANGULAR_AGENT_CONFIG,\n [Integration.astro]: ASTRO_AGENT_CONFIG,\n [Integration.django]: DJANGO_AGENT_CONFIG,\n [Integration.flask]: FLASK_AGENT_CONFIG,\n [Integration.fastapi]: FASTAPI_AGENT_CONFIG,\n [Integration.laravel]: LARAVEL_AGENT_CONFIG,\n [Integration.sveltekit]: SVELTEKIT_AGENT_CONFIG,\n [Integration.swift]: SWIFT_AGENT_CONFIG,\n [Integration.android]: ANDROID_AGENT_CONFIG,\n [Integration.rails]: RAILS_AGENT_CONFIG,\n [Integration.python]: PYTHON_AGENT_CONFIG,\n [Integration.ruby]: RUBY_AGENT_CONFIG,\n};\n"]}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/lib/registry.ts"],"names":[],"mappings":";;;AACA,2CAA0C;AAC1C,uEAAoE;AACpE,iEAA8D;AAC9D,8DAA2D;AAC3D,yFAAsF;AACtF,kGAA+F;AAC/F,+FAA4F;AAC5F,yFAAsF;AACtF,0EAAuE;AACvE,oEAAiE;AACjE,uEAAoE;AACpE,oEAAiE;AACjE,0EAAuE;AACvE,0EAAuE;AACvE,uEAAuE;AACvE,oEAAiE;AACjE,0EAAuE;AACvE,oEAAiE;AACjE,uEAAoE;AACpE,iEAA8D;AAC9D,kGAA+F;AAC/F,+FAA4F;AAE/E,QAAA,kBAAkB,GAAyC;IACtE,CAAC,uBAAW,CAAC,MAAM,CAAC,EAAE,yCAAmB;IACzC,CAAC,uBAAW,CAAC,IAAI,CAAC,EAAE,qCAAiB;IACrC,CAAC,uBAAW,CAAC,GAAG,CAAC,EAAE,mCAAgB;IACnC,CAAC,uBAAW,CAAC,aAAa,CAAC,EAAE,yDAA2B;IACxD,CAAC,uBAAW,CAAC,WAAW,CAAC,EAAE,qDAAyB;IACpD,CAAC,uBAAW,CAAC,cAAc,CAAC,EAAE,2DAA4B;IAC1D,CAAC,uBAAW,CAAC,WAAW,CAAC,EAAE,qDAAyB;IACpD,CAAC,uBAAW,CAAC,OAAO,CAAC,EAAE,2CAAoB;IAC3C,CAAC,uBAAW,CAAC,KAAK,CAAC,EAAE,uCAAkB;IACvC,CAAC,uBAAW,CAAC,MAAM,CAAC,EAAE,yCAAmB;IACzC,CAAC,uBAAW,CAAC,KAAK,CAAC,EAAE,uCAAkB;IACvC,CAAC,uBAAW,CAAC,OAAO,CAAC,EAAE,2CAAoB;IAC3C,CAAC,uBAAW,CAAC,OAAO,CAAC,EAAE,2CAAoB;IAC3C,CAAC,uBAAW,CAAC,SAAS,CAAC,EAAE,4CAAsB;IAC/C,CAAC,uBAAW,CAAC,KAAK,CAAC,EAAE,uCAAkB;IACvC,CAAC,uBAAW,CAAC,OAAO,CAAC,EAAE,2CAAoB;IAC3C,CAAC,uBAAW,CAAC,KAAK,CAAC,EAAE,uCAAkB;IACvC,CAAC,uBAAW,CAAC,MAAM,CAAC,EAAE,yCAAmB;IACzC,CAAC,uBAAW,CAAC,IAAI,CAAC,EAAE,qCAAiB;IACrC,CAAC,uBAAW,CAAC,cAAc,CAAC,EAAE,2DAA4B;IAC1D,CAAC,uBAAW,CAAC,cAAc,CAAC,EAAE,yDAA2B;CAC1D,CAAC","sourcesContent":["import type { FrameworkConfig } from './framework-config';\nimport { Integration } from './constants';\nimport { NEXTJS_AGENT_CONFIG } from '../nextjs/nextjs-wizard-agent';\nimport { NUXT_AGENT_CONFIG } from '../nuxt/nuxt-wizard-agent';\nimport { VUE_AGENT_CONFIG } from '../vue/vue-wizard-agent';\nimport { REACT_ROUTER_AGENT_CONFIG } from '../react-router/react-router-wizard-agent';\nimport { TANSTACK_ROUTER_AGENT_CONFIG } from '../tanstack-router/tanstack-router-wizard-agent';\nimport { TANSTACK_START_AGENT_CONFIG } from '../tanstack-start/tanstack-start-wizard-agent';\nimport { REACT_NATIVE_AGENT_CONFIG } from '../react-native/react-native-wizard-agent';\nimport { ANGULAR_AGENT_CONFIG } from '../angular/angular-wizard-agent';\nimport { ASTRO_AGENT_CONFIG } from '../astro/astro-wizard-agent';\nimport { DJANGO_AGENT_CONFIG } from '../django/django-wizard-agent';\nimport { FLASK_AGENT_CONFIG } from '../flask/flask-wizard-agent';\nimport { FASTAPI_AGENT_CONFIG } from '../fastapi/fastapi-wizard-agent';\nimport { LARAVEL_AGENT_CONFIG } from '../laravel/laravel-wizard-agent';\nimport { SVELTEKIT_AGENT_CONFIG } from '../svelte/svelte-wizard-agent';\nimport { SWIFT_AGENT_CONFIG } from '../swift/swift-wizard-agent';\nimport { ANDROID_AGENT_CONFIG } from '../android/android-wizard-agent';\nimport { RAILS_AGENT_CONFIG } from '../rails/rails-wizard-agent';\nimport { PYTHON_AGENT_CONFIG } from '../python/python-wizard-agent';\nimport { RUBY_AGENT_CONFIG } from '../ruby/ruby-wizard-agent';\nimport { JAVASCRIPT_NODE_AGENT_CONFIG } from '../javascript-node/javascript-node-wizard-agent';\nimport { JAVASCRIPT_WEB_AGENT_CONFIG } from '../javascript-web/javascript-web-wizard-agent';\n\nexport const FRAMEWORK_REGISTRY: Record<Integration, FrameworkConfig> = {\n [Integration.nextjs]: NEXTJS_AGENT_CONFIG,\n [Integration.nuxt]: NUXT_AGENT_CONFIG,\n [Integration.vue]: VUE_AGENT_CONFIG,\n [Integration.tanstackStart]: TANSTACK_START_AGENT_CONFIG,\n [Integration.reactRouter]: REACT_ROUTER_AGENT_CONFIG,\n [Integration.tanstackRouter]: TANSTACK_ROUTER_AGENT_CONFIG,\n [Integration.reactNative]: REACT_NATIVE_AGENT_CONFIG,\n [Integration.angular]: ANGULAR_AGENT_CONFIG,\n [Integration.astro]: ASTRO_AGENT_CONFIG,\n [Integration.django]: DJANGO_AGENT_CONFIG,\n [Integration.flask]: FLASK_AGENT_CONFIG,\n [Integration.fastapi]: FASTAPI_AGENT_CONFIG,\n [Integration.laravel]: LARAVEL_AGENT_CONFIG,\n [Integration.sveltekit]: SVELTEKIT_AGENT_CONFIG,\n [Integration.swift]: SWIFT_AGENT_CONFIG,\n [Integration.android]: ANDROID_AGENT_CONFIG,\n [Integration.rails]: RAILS_AGENT_CONFIG,\n [Integration.python]: PYTHON_AGENT_CONFIG,\n [Integration.ruby]: RUBY_AGENT_CONFIG,\n [Integration.javascriptNode]: JAVASCRIPT_NODE_AGENT_CONFIG,\n [Integration.javascript_web]: JAVASCRIPT_WEB_AGENT_CONFIG,\n};\n"]}
@@ -161,88 +161,11 @@ exports.PYTHON_AGENT_CONFIG = {
161
161
  const packageManagerName = context.packageManager
162
162
  ? (0, utils_1.getPackageManagerName)(context.packageManager)
163
163
  : 'unknown';
164
- const lines = [
164
+ return [
165
165
  `Package manager: ${packageManagerName}`,
166
166
  `Framework docs ID: python (use posthog://docs/frameworks/python for documentation)`,
167
167
  `Project type: Generic Python application (CLI, script, worker, data pipeline, etc.)`,
168
- ``,
169
- `## CRITICAL: Python PostHog Best Practices`,
170
- ``,
171
- `### 1. Use Instance-Based API (REQUIRED)`,
172
- `Always use the Posthog() class constructor instead of module-level posthog:`,
173
- ``,
174
- `CORRECT:`,
175
- `from posthog import Posthog`,
176
- `posthog_client = Posthog(`,
177
- ` api_key="your_api_key",`,
178
- ` host="https://us.i.posthog.com",`,
179
- ` debug=False,`,
180
- ` enable_exception_autocapture=True, # Auto-capture exceptions`,
181
- `)`,
182
- ``,
183
- `INCORRECT (DO NOT USE):`,
184
- `import posthog`,
185
- `posthog.api_key = "your_api_key" # Don't use module-level config`,
186
- ``,
187
- `### 2. Enable Exception Autocapture`,
188
- `ALWAYS include enable_exception_autocapture=True in the Posthog() initialization to automatically track exceptions.`,
189
- ``,
190
- `### 3. NEVER Send PII (Personally Identifiable Information)`,
191
- `DO NOT include in event properties:`,
192
- `- Email addresses`,
193
- `- Full names`,
194
- `- Phone numbers`,
195
- `- Physical addresses`,
196
- `- IP addresses`,
197
- `- Any user-generated content (messages, comments, form submissions)`,
198
- ``,
199
- `SAFE event properties:`,
200
- `posthog_client.capture('contact_form_submitted', properties={`,
201
- ` 'message_length': len(message), # Metadata is OK`,
202
- ` 'has_email': bool(email), # Boolean flags are OK`,
203
- ` 'form_type': 'contact' # Categories are OK`,
204
- `})`,
205
- ``,
206
- `UNSAFE (DO NOT DO THIS):`,
207
- `posthog_client.capture('form_submitted', properties={`,
208
- ` 'email': user_email, # NEVER send actual email`,
209
- ` 'message': message_content, # NEVER send user content`,
210
- ` 'name': user_name # NEVER send names`,
211
- `})`,
212
- ``,
213
- `### 4. Implement Graceful Shutdown`,
214
- `ALWAYS call posthog_client.shutdown() when your application exits to ensure all events are flushed:`,
215
- ``,
216
- `import atexit`,
217
- `atexit.register(posthog_client.shutdown) # Ensures events are sent on exit`,
218
- ``,
219
- `For Django, use AppConfig.ready() to register the shutdown handler.`,
220
- `For Flask, use @app.teardown_appcontext or atexit.`,
221
- `For scripts/workers, call shutdown() explicitly or use atexit.`,
222
- ``,
223
- `### 5. For Django Projects`,
224
- `Initialize PostHog in your AppConfig.ready() method:`,
225
- ``,
226
- `from django.apps import AppConfig`,
227
- `from posthog import Posthog`,
228
- ``,
229
- `class YourAppConfig(AppConfig):`,
230
- ` posthog_client = None`,
231
- ` `,
232
- ` def ready(self):`,
233
- ` if YourAppConfig.posthog_client is None:`,
234
- ` YourAppConfig.posthog_client = Posthog(`,
235
- ` settings.POSTHOG_API_KEY,`,
236
- ` host=settings.POSTHOG_HOST,`,
237
- ` debug=settings.DEBUG,`,
238
- ` enable_exception_autocapture=True,`,
239
- ` )`,
240
- ` import atexit`,
241
- ` atexit.register(YourAppConfig.posthog_client.shutdown)`,
242
- ``,
243
- `IMPORTANT: These best practices are MANDATORY. The implementation will fail review if they are not followed.`,
244
168
  ];
245
- return lines;
246
169
  },
247
170
  },
248
171
  ui: {
@@ -1 +1 @@
1
- {"version":3,"file":"python-wizard-agent.js","sourceRoot":"","sources":["../../../src/python/python-wizard-agent.ts"],"names":[],"mappings":"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","sourcesContent":["/* Generic Python language wizard using posthog-agent with PostHog MCP */\nimport type { WizardOptions } from '../utils/types';\nimport type { FrameworkConfig } from '../lib/framework-config';\nimport { PYTHON_PACKAGE_INSTALLATION } from '../lib/framework-config';\nimport { detectPythonPackageManagers } from '../lib/package-manager-detection';\nimport { Integration } from '../lib/constants';\nimport fg from 'fast-glob';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport {\n getPythonVersion,\n getPythonVersionBucket,\n detectPackageManager,\n getPackageManagerName,\n PythonPackageManager,\n} from './utils';\n\ntype PythonContext = {\n packageManager?: PythonPackageManager;\n};\n\nexport const PYTHON_AGENT_CONFIG: FrameworkConfig<PythonContext> = {\n metadata: {\n name: 'Python Language',\n integration: Integration.python,\n beta: true,\n docsUrl: 'https://posthog.com/docs/libraries/python',\n gatherContext: async (options: WizardOptions) => {\n const packageManager = await detectPackageManager(options);\n return { packageManager };\n },\n },\n\n detection: {\n packageName: 'python',\n packageDisplayName: 'Python',\n usesPackageJson: false,\n getVersion: () => undefined,\n getVersionBucket: getPythonVersionBucket,\n minimumVersion: '3.8.0',\n getInstalledVersion: (options: WizardOptions) =>\n Promise.resolve(getPythonVersion(options)),\n detect: async (options) => {\n const { installDir } = options;\n\n // Look for Python package management files\n const pythonConfigFiles = await fg(\n [\n '**/requirements*.txt',\n '**/pyproject.toml',\n '**/setup.py',\n '**/Pipfile',\n ],\n {\n cwd: installDir,\n ignore: ['**/venv/**', '**/.venv/**', '**/env/**', '**/.env/**'],\n },\n );\n\n if (pythonConfigFiles.length === 0) {\n return false;\n }\n\n // Make sure this isn't Django or Flask (those should be detected first)\n // Check for Django\n const managePyMatches = await fg('**/manage.py', {\n cwd: installDir,\n ignore: ['**/venv/**', '**/.venv/**', '**/env/**', '**/.env/**'],\n });\n\n for (const match of managePyMatches) {\n try {\n const content = fs.readFileSync(\n path.join(installDir, match),\n 'utf-8',\n );\n if (\n content.includes('django') ||\n content.includes('DJANGO_SETTINGS_MODULE')\n ) {\n return false; // Django detected, use django agent instead\n }\n } catch {\n continue;\n }\n }\n\n // Check for Flask\n for (const configFile of pythonConfigFiles) {\n try {\n const content = fs.readFileSync(\n path.join(installDir, configFile),\n 'utf-8',\n );\n if (\n /^flask([<>=~!]|$|\\s)/im.test(content) ||\n /[\"']flask[\"']/i.test(content)\n ) {\n return false; // Flask detected, use flask agent instead\n }\n } catch {\n continue;\n }\n }\n\n const pyFiles = await fg(\n ['**/app.py', '**/wsgi.py', '**/application.py', '**/__init__.py'],\n {\n cwd: installDir,\n ignore: [\n '**/venv/**',\n '**/.venv/**',\n '**/env/**',\n '**/.env/**',\n '**/__pycache__/**',\n ],\n },\n );\n\n for (const pyFile of pyFiles) {\n try {\n const content = fs.readFileSync(\n path.join(installDir, pyFile),\n 'utf-8',\n );\n if (\n content.includes('from flask import') ||\n content.includes('import flask') ||\n /Flask\\s*\\(/.test(content)\n ) {\n return false; // Flask detected, use flask agent instead\n }\n } catch {\n continue;\n }\n }\n\n // If we have Python config files but it's not Django or Flask, it's a generic Python project\n return true;\n },\n detectPackageManager: detectPythonPackageManagers,\n },\n\n environment: {\n uploadToHosting: false,\n getEnvVars: (apiKey: string, host: string) => ({\n POSTHOG_API_KEY: apiKey,\n POSTHOG_HOST: host,\n }),\n },\n\n analytics: {\n getTags: (context) => {\n const packageManagerName = context.packageManager\n ? getPackageManagerName(context.packageManager)\n : 'unknown';\n return {\n packageManager: packageManagerName,\n };\n },\n },\n\n prompts: {\n packageInstallation: PYTHON_PACKAGE_INSTALLATION,\n projectTypeDetection:\n 'This is a generic Python project. Look for requirements.txt, pyproject.toml, setup.py, or Pipfile to confirm.',\n getAdditionalContextLines: (context) => {\n const packageManagerName = context.packageManager\n ? getPackageManagerName(context.packageManager)\n : 'unknown';\n\n const lines = [\n `Package manager: ${packageManagerName}`,\n `Framework docs ID: python (use posthog://docs/frameworks/python for documentation)`,\n `Project type: Generic Python application (CLI, script, worker, data pipeline, etc.)`,\n ``,\n `## CRITICAL: Python PostHog Best Practices`,\n ``,\n `### 1. Use Instance-Based API (REQUIRED)`,\n `Always use the Posthog() class constructor instead of module-level posthog:`,\n ``,\n `CORRECT:`,\n `from posthog import Posthog`,\n `posthog_client = Posthog(`,\n ` api_key=\"your_api_key\",`,\n ` host=\"https://us.i.posthog.com\",`,\n ` debug=False,`,\n ` enable_exception_autocapture=True, # Auto-capture exceptions`,\n `)`,\n ``,\n `INCORRECT (DO NOT USE):`,\n `import posthog`,\n `posthog.api_key = \"your_api_key\" # Don't use module-level config`,\n ``,\n `### 2. Enable Exception Autocapture`,\n `ALWAYS include enable_exception_autocapture=True in the Posthog() initialization to automatically track exceptions.`,\n ``,\n `### 3. NEVER Send PII (Personally Identifiable Information)`,\n `DO NOT include in event properties:`,\n `- Email addresses`,\n `- Full names`,\n `- Phone numbers`,\n `- Physical addresses`,\n `- IP addresses`,\n `- Any user-generated content (messages, comments, form submissions)`,\n ``,\n `SAFE event properties:`,\n `posthog_client.capture('contact_form_submitted', properties={`,\n ` 'message_length': len(message), # Metadata is OK`,\n ` 'has_email': bool(email), # Boolean flags are OK`,\n ` 'form_type': 'contact' # Categories are OK`,\n `})`,\n ``,\n `UNSAFE (DO NOT DO THIS):`,\n `posthog_client.capture('form_submitted', properties={`,\n ` 'email': user_email, # NEVER send actual email`,\n ` 'message': message_content, # NEVER send user content`,\n ` 'name': user_name # NEVER send names`,\n `})`,\n ``,\n `### 4. Implement Graceful Shutdown`,\n `ALWAYS call posthog_client.shutdown() when your application exits to ensure all events are flushed:`,\n ``,\n `import atexit`,\n `atexit.register(posthog_client.shutdown) # Ensures events are sent on exit`,\n ``,\n `For Django, use AppConfig.ready() to register the shutdown handler.`,\n `For Flask, use @app.teardown_appcontext or atexit.`,\n `For scripts/workers, call shutdown() explicitly or use atexit.`,\n ``,\n `### 5. For Django Projects`,\n `Initialize PostHog in your AppConfig.ready() method:`,\n ``,\n `from django.apps import AppConfig`,\n `from posthog import Posthog`,\n ``,\n `class YourAppConfig(AppConfig):`,\n ` posthog_client = None`,\n ` `,\n ` def ready(self):`,\n ` if YourAppConfig.posthog_client is None:`,\n ` YourAppConfig.posthog_client = Posthog(`,\n ` settings.POSTHOG_API_KEY,`,\n ` host=settings.POSTHOG_HOST,`,\n ` debug=settings.DEBUG,`,\n ` enable_exception_autocapture=True,`,\n ` )`,\n ` import atexit`,\n ` atexit.register(YourAppConfig.posthog_client.shutdown)`,\n ``,\n `IMPORTANT: These best practices are MANDATORY. The implementation will fail review if they are not followed.`,\n ];\n\n return lines;\n },\n },\n\n ui: {\n successMessage: 'PostHog integration complete',\n estimatedDurationMinutes: 5,\n getOutroChanges: (context) => {\n const packageManagerName = context.packageManager\n ? getPackageManagerName(context.packageManager)\n : 'package manager';\n return [\n `Analyzed your Python project structure`,\n `Installed the PostHog Python package using ${packageManagerName}`,\n `Created PostHog initialization using instance-based API (Posthog class)`,\n `Configured exception autocapture and graceful shutdown`,\n `Added example code for events, feature flags, and error capture (without PII)`,\n ];\n },\n getOutroNextSteps: () => [\n 'Use Posthog() class (not module-level posthog) with enable_exception_autocapture=True',\n 'Call posthog_client.shutdown() on application exit (use atexit.register)',\n 'NEVER send PII in event properties (no emails, names, or user content)',\n 'Use posthog_client.capture() for events and posthog_client.identify() for users',\n 'Visit your PostHog dashboard to see incoming events',\n ],\n },\n};\n"]}
1
+ {"version":3,"file":"python-wizard-agent.js","sourceRoot":"","sources":["../../../src/python/python-wizard-agent.ts"],"names":[],"mappings":"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","sourcesContent":["/* Generic Python wizard using posthog-agent with PostHog MCP */\nimport type { WizardOptions } from '../utils/types';\nimport type { FrameworkConfig } from '../lib/framework-config';\nimport { PYTHON_PACKAGE_INSTALLATION } from '../lib/framework-config';\nimport { detectPythonPackageManagers } from '../lib/package-manager-detection';\nimport { Integration } from '../lib/constants';\nimport fg from 'fast-glob';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport {\n getPythonVersion,\n getPythonVersionBucket,\n detectPackageManager,\n getPackageManagerName,\n PythonPackageManager,\n} from './utils';\n\ntype PythonContext = {\n packageManager?: PythonPackageManager;\n};\n\nexport const PYTHON_AGENT_CONFIG: FrameworkConfig<PythonContext> = {\n metadata: {\n name: 'Python Language',\n integration: Integration.python,\n beta: true,\n docsUrl: 'https://posthog.com/docs/libraries/python',\n gatherContext: async (options: WizardOptions) => {\n const packageManager = await detectPackageManager(options);\n return { packageManager };\n },\n },\n\n detection: {\n packageName: 'python',\n packageDisplayName: 'Python',\n usesPackageJson: false,\n getVersion: () => undefined,\n getVersionBucket: getPythonVersionBucket,\n minimumVersion: '3.8.0',\n getInstalledVersion: (options: WizardOptions) =>\n Promise.resolve(getPythonVersion(options)),\n detect: async (options) => {\n const { installDir } = options;\n\n // Look for Python package management files\n const pythonConfigFiles = await fg(\n [\n '**/requirements*.txt',\n '**/pyproject.toml',\n '**/setup.py',\n '**/Pipfile',\n ],\n {\n cwd: installDir,\n ignore: ['**/venv/**', '**/.venv/**', '**/env/**', '**/.env/**'],\n },\n );\n\n if (pythonConfigFiles.length === 0) {\n return false;\n }\n\n // Make sure this isn't Django or Flask (those should be detected first)\n // Check for Django\n const managePyMatches = await fg('**/manage.py', {\n cwd: installDir,\n ignore: ['**/venv/**', '**/.venv/**', '**/env/**', '**/.env/**'],\n });\n\n for (const match of managePyMatches) {\n try {\n const content = fs.readFileSync(\n path.join(installDir, match),\n 'utf-8',\n );\n if (\n content.includes('django') ||\n content.includes('DJANGO_SETTINGS_MODULE')\n ) {\n return false; // Django detected, use django agent instead\n }\n } catch {\n continue;\n }\n }\n\n // Check for Flask\n for (const configFile of pythonConfigFiles) {\n try {\n const content = fs.readFileSync(\n path.join(installDir, configFile),\n 'utf-8',\n );\n if (\n /^flask([<>=~!]|$|\\s)/im.test(content) ||\n /[\"']flask[\"']/i.test(content)\n ) {\n return false; // Flask detected, use flask agent instead\n }\n } catch {\n continue;\n }\n }\n\n const pyFiles = await fg(\n ['**/app.py', '**/wsgi.py', '**/application.py', '**/__init__.py'],\n {\n cwd: installDir,\n ignore: [\n '**/venv/**',\n '**/.venv/**',\n '**/env/**',\n '**/.env/**',\n '**/__pycache__/**',\n ],\n },\n );\n\n for (const pyFile of pyFiles) {\n try {\n const content = fs.readFileSync(\n path.join(installDir, pyFile),\n 'utf-8',\n );\n if (\n content.includes('from flask import') ||\n content.includes('import flask') ||\n /Flask\\s*\\(/.test(content)\n ) {\n return false; // Flask detected, use flask agent instead\n }\n } catch {\n continue;\n }\n }\n\n // If we have Python config files but it's not Django or Flask, it's a generic Python project\n return true;\n },\n detectPackageManager: detectPythonPackageManagers,\n },\n\n environment: {\n uploadToHosting: false,\n getEnvVars: (apiKey: string, host: string) => ({\n POSTHOG_API_KEY: apiKey,\n POSTHOG_HOST: host,\n }),\n },\n\n analytics: {\n getTags: (context) => {\n const packageManagerName = context.packageManager\n ? getPackageManagerName(context.packageManager)\n : 'unknown';\n return {\n packageManager: packageManagerName,\n };\n },\n },\n\n prompts: {\n packageInstallation: PYTHON_PACKAGE_INSTALLATION,\n projectTypeDetection:\n 'This is a generic Python project. Look for requirements.txt, pyproject.toml, setup.py, or Pipfile to confirm.',\n getAdditionalContextLines: (context) => {\n const packageManagerName = context.packageManager\n ? getPackageManagerName(context.packageManager)\n : 'unknown';\n\n return [\n `Package manager: ${packageManagerName}`,\n `Framework docs ID: python (use posthog://docs/frameworks/python for documentation)`,\n `Project type: Generic Python application (CLI, script, worker, data pipeline, etc.)`,\n ];\n },\n },\n\n ui: {\n successMessage: 'PostHog integration complete',\n estimatedDurationMinutes: 5,\n getOutroChanges: (context) => {\n const packageManagerName = context.packageManager\n ? getPackageManagerName(context.packageManager)\n : 'package manager';\n return [\n `Analyzed your Python project structure`,\n `Installed the PostHog Python package using ${packageManagerName}`,\n `Created PostHog initialization using instance-based API (Posthog class)`,\n `Configured exception autocapture and graceful shutdown`,\n `Added example code for events, feature flags, and error capture (without PII)`,\n ];\n },\n getOutroNextSteps: () => [\n 'Use Posthog() class (not module-level posthog) with enable_exception_autocapture=True',\n 'Call posthog_client.shutdown() on application exit (use atexit.register)',\n 'NEVER send PII in event properties (no emails, names, or user content)',\n 'Use posthog_client.capture() for events and posthog_client.identify() for users',\n 'Visit your PostHog dashboard to see incoming events',\n ],\n },\n};\n"]}
package/dist/src/run.d.ts CHANGED
@@ -11,7 +11,9 @@ type Args = {
11
11
  localMcp?: boolean;
12
12
  ci?: boolean;
13
13
  apiKey?: string;
14
+ projectId?: string;
14
15
  menu?: boolean;
16
+ benchmark?: boolean;
15
17
  };
16
18
  export declare function runWizard(argv: Args): Promise<void>;
17
19
  export {};