@posthog/wizard 1.29.0 → 1.31.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.
@@ -0,0 +1,5 @@
1
+ import type { WizardOptions } from '../utils/types';
2
+ /**
3
+ * Laravel wizard powered by the universal agent runner.
4
+ */
5
+ export declare function runLaravelWizardAgent(options: WizardOptions): Promise<void>;
@@ -0,0 +1,183 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.runLaravelWizardAgent = runLaravelWizardAgent;
40
+ const debug_1 = require("../utils/debug");
41
+ const agent_runner_1 = require("../lib/agent-runner");
42
+ const constants_1 = require("../lib/constants");
43
+ const clack_1 = __importDefault(require("../utils/clack"));
44
+ const chalk_1 = __importDefault(require("chalk"));
45
+ const semver = __importStar(require("semver"));
46
+ const utils_1 = require("./utils");
47
+ /**
48
+ * Laravel framework configuration for the universal agent runner
49
+ */
50
+ const MINIMUM_LARAVEL_VERSION = '9.0.0';
51
+ const LARAVEL_AGENT_CONFIG = {
52
+ metadata: {
53
+ name: 'Laravel',
54
+ integration: constants_1.Integration.laravel,
55
+ docsUrl: 'https://posthog.com/docs/libraries/php',
56
+ unsupportedVersionDocsUrl: 'https://posthog.com/docs/libraries/php',
57
+ gatherContext: async (options) => {
58
+ const projectType = await (0, utils_1.getLaravelProjectType)(options);
59
+ const serviceProvider = await (0, utils_1.findLaravelServiceProvider)(options);
60
+ const bootstrapFile = (0, utils_1.findLaravelBootstrapFile)(options);
61
+ const laravelStructure = (0, utils_1.detectLaravelStructure)(options);
62
+ return {
63
+ projectType,
64
+ serviceProvider,
65
+ bootstrapFile,
66
+ laravelStructure,
67
+ };
68
+ },
69
+ },
70
+ detection: {
71
+ packageName: 'laravel/framework',
72
+ packageDisplayName: 'Laravel',
73
+ usesPackageJson: false,
74
+ getVersion: (_packageJson) => {
75
+ // For Laravel, we don't use package.json. Version is extracted separately
76
+ // from composer.json in the wizard entry point
77
+ return undefined;
78
+ },
79
+ getVersionBucket: utils_1.getLaravelVersionBucket,
80
+ },
81
+ environment: {
82
+ uploadToHosting: false,
83
+ getEnvVars: (apiKey, host) => ({
84
+ POSTHOG_API_KEY: apiKey,
85
+ POSTHOG_HOST: host,
86
+ }),
87
+ },
88
+ analytics: {
89
+ getTags: (context) => {
90
+ const projectType = context.projectType;
91
+ return {
92
+ projectType: projectType || 'unknown',
93
+ laravelStructure: context.laravelStructure || 'unknown',
94
+ };
95
+ },
96
+ },
97
+ prompts: {
98
+ projectTypeDetection: 'This is a PHP/Laravel project. Look for composer.json, artisan CLI, and app/ directory structure to confirm. Check for Laravel-specific packages like laravel/framework.',
99
+ packageInstallation: 'Use Composer to install packages. Run `composer require posthog/posthog-php` without pinning a specific version.',
100
+ getAdditionalContextLines: (context) => {
101
+ const projectType = context.projectType;
102
+ const projectTypeName = projectType
103
+ ? (0, utils_1.getLaravelProjectTypeName)(projectType)
104
+ : 'unknown';
105
+ const lines = [
106
+ `Project type: ${projectTypeName}`,
107
+ `Framework docs ID: php (use posthog://docs/frameworks/php for documentation)`,
108
+ `Laravel structure: ${context.laravelStructure} (affects where to add configuration)`,
109
+ ];
110
+ if (context.serviceProvider) {
111
+ lines.push(`Service provider: ${context.serviceProvider}`);
112
+ }
113
+ if (context.bootstrapFile) {
114
+ lines.push(`Bootstrap file: ${context.bootstrapFile}`);
115
+ }
116
+ // Add Laravel-specific guidance based on version structure
117
+ if (context.laravelStructure === 'latest') {
118
+ lines.push('Note: Laravel 11+ uses simplified bootstrap/app.php for middleware and providers');
119
+ }
120
+ else {
121
+ lines.push('Note: Use app/Http/Kernel.php for middleware, app/Providers for service providers');
122
+ }
123
+ return lines;
124
+ },
125
+ },
126
+ ui: {
127
+ successMessage: 'PostHog integration complete',
128
+ estimatedDurationMinutes: 5,
129
+ getOutroChanges: (context) => {
130
+ const projectType = context.projectType;
131
+ const projectTypeName = projectType
132
+ ? (0, utils_1.getLaravelProjectTypeName)(projectType)
133
+ : 'Laravel';
134
+ const changes = [
135
+ `Analyzed your ${projectTypeName} project structure`,
136
+ `Installed the PostHog PHP package via Composer`,
137
+ `Configured PostHog in your Laravel application`,
138
+ ];
139
+ if (context.laravelStructure === 'latest') {
140
+ changes.push('Added PostHog initialization to bootstrap/app.php');
141
+ }
142
+ else {
143
+ changes.push('Created a PostHog service provider for initialization');
144
+ }
145
+ if (projectType === utils_1.LaravelProjectType.INERTIA) {
146
+ changes.push('Configured PostHog to work with Inertia.js');
147
+ }
148
+ if (projectType === utils_1.LaravelProjectType.LIVEWIRE) {
149
+ changes.push('Configured PostHog to work with Livewire');
150
+ }
151
+ return changes;
152
+ },
153
+ getOutroNextSteps: () => [
154
+ 'Start your Laravel development server with `php artisan serve`',
155
+ 'Visit your PostHog dashboard to see incoming events',
156
+ 'Use PostHog::capture() to track custom events',
157
+ 'Use PostHog::identify() to associate events with users',
158
+ ],
159
+ },
160
+ };
161
+ /**
162
+ * Laravel wizard powered by the universal agent runner.
163
+ */
164
+ async function runLaravelWizardAgent(options) {
165
+ if (options.debug) {
166
+ (0, debug_1.enableDebugLogs)();
167
+ }
168
+ // Check Laravel version - agent wizard requires >= 9.0.0
169
+ const laravelVersion = (0, utils_1.getLaravelVersion)(options);
170
+ if (laravelVersion) {
171
+ const coercedVersion = semver.coerce(laravelVersion);
172
+ if (coercedVersion && semver.lt(coercedVersion, MINIMUM_LARAVEL_VERSION)) {
173
+ const docsUrl = LARAVEL_AGENT_CONFIG.metadata.unsupportedVersionDocsUrl ??
174
+ LARAVEL_AGENT_CONFIG.metadata.docsUrl;
175
+ clack_1.default.log.warn(`Sorry: the wizard can't help you with Laravel ${laravelVersion}. Upgrade to Laravel ${MINIMUM_LARAVEL_VERSION} or later, or check out the manual setup guide.`);
176
+ clack_1.default.log.info(`Setup Laravel manually: ${chalk_1.default.cyan(docsUrl)}`);
177
+ clack_1.default.outro('PostHog wizard will see you next time!');
178
+ return;
179
+ }
180
+ }
181
+ await (0, agent_runner_1.runAgentWizard)(LARAVEL_AGENT_CONFIG, options);
182
+ }
183
+ //# sourceMappingURL=laravel-wizard-agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"laravel-wizard-agent.js","sourceRoot":"","sources":["../../../src/laravel/laravel-wizard-agent.ts"],"names":[],"mappings":"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","sourcesContent":["/* Laravel wizard using posthog-agent with PostHog MCP */\nimport type { WizardOptions } from '../utils/types';\nimport type { FrameworkConfig } from '../lib/framework-config';\nimport { enableDebugLogs } from '../utils/debug';\nimport { runAgentWizard } from '../lib/agent-runner';\nimport { Integration } from '../lib/constants';\nimport clack from '../utils/clack';\nimport chalk from 'chalk';\nimport * as semver from 'semver';\nimport {\n getLaravelVersion,\n getLaravelProjectType,\n getLaravelProjectTypeName,\n getLaravelVersionBucket,\n LaravelProjectType,\n findLaravelServiceProvider,\n findLaravelBootstrapFile,\n detectLaravelStructure,\n} from './utils';\n\n/**\n * Laravel framework configuration for the universal agent runner\n */\nconst MINIMUM_LARAVEL_VERSION = '9.0.0';\n\nconst LARAVEL_AGENT_CONFIG: FrameworkConfig = {\n metadata: {\n name: 'Laravel',\n integration: Integration.laravel,\n docsUrl: 'https://posthog.com/docs/libraries/php',\n unsupportedVersionDocsUrl: 'https://posthog.com/docs/libraries/php',\n gatherContext: async (options: WizardOptions) => {\n const projectType = await getLaravelProjectType(options);\n const serviceProvider = await findLaravelServiceProvider(options);\n const bootstrapFile = findLaravelBootstrapFile(options);\n const laravelStructure = detectLaravelStructure(options);\n\n return {\n projectType,\n serviceProvider,\n bootstrapFile,\n laravelStructure,\n };\n },\n },\n\n detection: {\n packageName: 'laravel/framework',\n packageDisplayName: 'Laravel',\n usesPackageJson: false,\n getVersion: (_packageJson: any) => {\n // For Laravel, we don't use package.json. Version is extracted separately\n // from composer.json in the wizard entry point\n return undefined;\n },\n getVersionBucket: getLaravelVersionBucket,\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: any) => {\n const projectType = context.projectType as LaravelProjectType;\n return {\n projectType: projectType || 'unknown',\n laravelStructure: context.laravelStructure || 'unknown',\n };\n },\n },\n\n prompts: {\n projectTypeDetection:\n 'This is a PHP/Laravel project. Look for composer.json, artisan CLI, and app/ directory structure to confirm. Check for Laravel-specific packages like laravel/framework.',\n packageInstallation:\n 'Use Composer to install packages. Run `composer require posthog/posthog-php` without pinning a specific version.',\n getAdditionalContextLines: (context: any) => {\n const projectType = context.projectType as LaravelProjectType;\n const projectTypeName = projectType\n ? getLaravelProjectTypeName(projectType)\n : 'unknown';\n\n const lines = [\n `Project type: ${projectTypeName}`,\n `Framework docs ID: php (use posthog://docs/frameworks/php for documentation)`,\n `Laravel structure: ${context.laravelStructure} (affects where to add configuration)`,\n ];\n\n if (context.serviceProvider) {\n lines.push(`Service provider: ${context.serviceProvider}`);\n }\n\n if (context.bootstrapFile) {\n lines.push(`Bootstrap file: ${context.bootstrapFile}`);\n }\n\n // Add Laravel-specific guidance based on version structure\n if (context.laravelStructure === 'latest') {\n lines.push(\n 'Note: Laravel 11+ uses simplified bootstrap/app.php for middleware and providers',\n );\n } else {\n lines.push(\n 'Note: Use app/Http/Kernel.php for middleware, app/Providers for service providers',\n );\n }\n\n return lines;\n },\n },\n\n ui: {\n successMessage: 'PostHog integration complete',\n estimatedDurationMinutes: 5,\n getOutroChanges: (context: any) => {\n const projectType = context.projectType as LaravelProjectType;\n const projectTypeName = projectType\n ? getLaravelProjectTypeName(projectType)\n : 'Laravel';\n\n const changes = [\n `Analyzed your ${projectTypeName} project structure`,\n `Installed the PostHog PHP package via Composer`,\n `Configured PostHog in your Laravel application`,\n ];\n\n if (context.laravelStructure === 'latest') {\n changes.push('Added PostHog initialization to bootstrap/app.php');\n } else {\n changes.push('Created a PostHog service provider for initialization');\n }\n\n if (projectType === LaravelProjectType.INERTIA) {\n changes.push('Configured PostHog to work with Inertia.js');\n }\n\n if (projectType === LaravelProjectType.LIVEWIRE) {\n changes.push('Configured PostHog to work with Livewire');\n }\n\n return changes;\n },\n getOutroNextSteps: () => [\n 'Start your Laravel development server with `php artisan serve`',\n 'Visit your PostHog dashboard to see incoming events',\n 'Use PostHog::capture() to track custom events',\n 'Use PostHog::identify() to associate events with users',\n ],\n },\n};\n\n/**\n * Laravel wizard powered by the universal agent runner.\n */\nexport async function runLaravelWizardAgent(\n options: WizardOptions,\n): Promise<void> {\n if (options.debug) {\n enableDebugLogs();\n }\n\n // Check Laravel version - agent wizard requires >= 9.0.0\n const laravelVersion = getLaravelVersion(options);\n\n if (laravelVersion) {\n const coercedVersion = semver.coerce(laravelVersion);\n if (coercedVersion && semver.lt(coercedVersion, MINIMUM_LARAVEL_VERSION)) {\n const docsUrl =\n LARAVEL_AGENT_CONFIG.metadata.unsupportedVersionDocsUrl ??\n LARAVEL_AGENT_CONFIG.metadata.docsUrl;\n\n clack.log.warn(\n `Sorry: the wizard can't help you with Laravel ${laravelVersion}. Upgrade to Laravel ${MINIMUM_LARAVEL_VERSION} or later, or check out the manual setup guide.`,\n );\n clack.log.info(`Setup Laravel manually: ${chalk.cyan(docsUrl)}`);\n clack.outro('PostHog wizard will see you next time!');\n return;\n }\n }\n\n await runAgentWizard(LARAVEL_AGENT_CONFIG, options);\n}\n"]}
@@ -0,0 +1,38 @@
1
+ import type { WizardOptions } from '../utils/types';
2
+ export declare enum LaravelProjectType {
3
+ STANDARD = "standard",// Basic Laravel app
4
+ INERTIA = "inertia",// Inertia.js (Vue/React SPA) - may need JS SDK too
5
+ LIVEWIRE = "livewire"
6
+ }
7
+ /**
8
+ * Get Laravel version bucket for analytics
9
+ */
10
+ export declare function getLaravelVersionBucket(version: string | undefined): string;
11
+ /**
12
+ * Read and parse composer.json
13
+ */
14
+ export declare function getComposerJson(options: Pick<WizardOptions, 'installDir'>): Record<string, any> | undefined;
15
+ /**
16
+ * Get Laravel version from composer.json
17
+ */
18
+ export declare function getLaravelVersion(options: Pick<WizardOptions, 'installDir'>): string | undefined;
19
+ /**
20
+ * Get human-readable name for Laravel project type
21
+ */
22
+ export declare function getLaravelProjectTypeName(projectType: LaravelProjectType): string;
23
+ /**
24
+ * Detect Laravel project type
25
+ */
26
+ export declare function getLaravelProjectType(options: WizardOptions): Promise<LaravelProjectType>;
27
+ /**
28
+ * Find the main service provider file
29
+ */
30
+ export declare function findLaravelServiceProvider(options: Pick<WizardOptions, 'installDir'>): Promise<string | undefined>;
31
+ /**
32
+ * Find the bootstrap file (differs between Laravel versions)
33
+ */
34
+ export declare function findLaravelBootstrapFile(options: Pick<WizardOptions, 'installDir'>): string | undefined;
35
+ /**
36
+ * Detect Laravel version structure for configuration guidance
37
+ */
38
+ export declare function detectLaravelStructure(options: Pick<WizardOptions, 'installDir'>): 'legacy' | 'modern' | 'latest';
@@ -0,0 +1,257 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.LaravelProjectType = void 0;
40
+ exports.getLaravelVersionBucket = getLaravelVersionBucket;
41
+ exports.getComposerJson = getComposerJson;
42
+ exports.getLaravelVersion = getLaravelVersion;
43
+ exports.getLaravelProjectTypeName = getLaravelProjectTypeName;
44
+ exports.getLaravelProjectType = getLaravelProjectType;
45
+ exports.findLaravelServiceProvider = findLaravelServiceProvider;
46
+ exports.findLaravelBootstrapFile = findLaravelBootstrapFile;
47
+ exports.detectLaravelStructure = detectLaravelStructure;
48
+ const semver_1 = require("semver");
49
+ const fast_glob_1 = __importDefault(require("fast-glob"));
50
+ const clack_1 = __importDefault(require("../utils/clack"));
51
+ const fs = __importStar(require("node:fs"));
52
+ const path = __importStar(require("node:path"));
53
+ var LaravelProjectType;
54
+ (function (LaravelProjectType) {
55
+ LaravelProjectType["STANDARD"] = "standard";
56
+ LaravelProjectType["INERTIA"] = "inertia";
57
+ LaravelProjectType["LIVEWIRE"] = "livewire";
58
+ })(LaravelProjectType || (exports.LaravelProjectType = LaravelProjectType = {}));
59
+ /**
60
+ * Ignore patterns for Laravel projects
61
+ */
62
+ const LARAVEL_IGNORE_PATTERNS = [
63
+ '**/node_modules/**',
64
+ '**/vendor/**',
65
+ '**/storage/**',
66
+ '**/bootstrap/cache/**',
67
+ '**/.phpunit.cache/**',
68
+ '**/public/build/**',
69
+ '**/public/hot/**',
70
+ ];
71
+ /**
72
+ * Get Laravel version bucket for analytics
73
+ */
74
+ function getLaravelVersionBucket(version) {
75
+ if (!version) {
76
+ return 'none';
77
+ }
78
+ try {
79
+ const minVer = (0, semver_1.minVersion)(version);
80
+ if (!minVer) {
81
+ return 'invalid';
82
+ }
83
+ const majorVersion = (0, semver_1.major)(minVer);
84
+ if (majorVersion >= 9) {
85
+ return `${majorVersion}.x`;
86
+ }
87
+ return '<9.0.0';
88
+ }
89
+ catch {
90
+ return 'unknown';
91
+ }
92
+ }
93
+ /**
94
+ * Read and parse composer.json
95
+ */
96
+ function getComposerJson(options) {
97
+ const { installDir } = options;
98
+ const composerPath = path.join(installDir, 'composer.json');
99
+ try {
100
+ const content = fs.readFileSync(composerPath, 'utf-8');
101
+ return JSON.parse(content);
102
+ }
103
+ catch {
104
+ return undefined;
105
+ }
106
+ }
107
+ /**
108
+ * Check if a package is installed (present in composer.json)
109
+ */
110
+ function hasComposerPackage(packageName, options) {
111
+ const composer = getComposerJson(options);
112
+ if (!composer)
113
+ return false;
114
+ return !!(composer.require?.[packageName] || composer['require-dev']?.[packageName]);
115
+ }
116
+ /**
117
+ * Extract version for a package from composer.json
118
+ */
119
+ function getComposerPackageVersion(packageName, options) {
120
+ const composer = getComposerJson(options);
121
+ if (!composer)
122
+ return undefined;
123
+ const version = composer.require?.[packageName] || composer['require-dev']?.[packageName];
124
+ if (version) {
125
+ // Clean version string (remove ^, ~, >=, etc.)
126
+ return version.replace(/^[\^~>=<]+/, '');
127
+ }
128
+ return undefined;
129
+ }
130
+ /**
131
+ * Check if a pattern exists in PHP source files
132
+ */
133
+ async function hasLaravelCodePattern(pattern, options, filePatterns = ['**/*.php']) {
134
+ const { installDir } = options;
135
+ const phpFiles = await (0, fast_glob_1.default)(filePatterns, {
136
+ cwd: installDir,
137
+ ignore: LARAVEL_IGNORE_PATTERNS,
138
+ });
139
+ const searchPattern = typeof pattern === 'string' ? new RegExp(pattern) : pattern;
140
+ for (const phpFile of phpFiles) {
141
+ try {
142
+ const content = fs.readFileSync(path.join(installDir, phpFile), 'utf-8');
143
+ if (searchPattern.test(content))
144
+ return true;
145
+ }
146
+ catch {
147
+ continue;
148
+ }
149
+ }
150
+ return false;
151
+ }
152
+ /**
153
+ * Get Laravel version from composer.json
154
+ */
155
+ function getLaravelVersion(options) {
156
+ return getComposerPackageVersion('laravel/framework', options);
157
+ }
158
+ /**
159
+ * Get human-readable name for Laravel project type
160
+ */
161
+ function getLaravelProjectTypeName(projectType) {
162
+ switch (projectType) {
163
+ case LaravelProjectType.STANDARD:
164
+ return 'Standard Laravel';
165
+ case LaravelProjectType.INERTIA:
166
+ return 'Laravel with Inertia.js';
167
+ case LaravelProjectType.LIVEWIRE:
168
+ return 'Laravel with Livewire';
169
+ default:
170
+ return 'Laravel';
171
+ }
172
+ }
173
+ /**
174
+ * Check for Inertia.js
175
+ */
176
+ async function hasInertia(options) {
177
+ return (hasComposerPackage('inertiajs/inertia-laravel', options) ||
178
+ (await hasLaravelCodePattern(/Inertia::render|inertia\(/, options)));
179
+ }
180
+ /**
181
+ * Check for Livewire
182
+ */
183
+ async function hasLivewire(options) {
184
+ return (hasComposerPackage('livewire/livewire', options) ||
185
+ (await hasLaravelCodePattern(/extends\s+Component|@livewire/, options)));
186
+ }
187
+ /**
188
+ * Detect Laravel project type
189
+ */
190
+ async function getLaravelProjectType(options) {
191
+ // Check for SPA/Reactive frameworks (important to detect - affects SDK needs)
192
+ if (await hasInertia(options)) {
193
+ clack_1.default.log.info('Detected Laravel with Inertia.js');
194
+ return LaravelProjectType.INERTIA;
195
+ }
196
+ if (await hasLivewire(options)) {
197
+ clack_1.default.log.info('Detected Laravel with Livewire');
198
+ return LaravelProjectType.LIVEWIRE;
199
+ }
200
+ // Default to standard
201
+ clack_1.default.log.info('Detected standard Laravel project');
202
+ return LaravelProjectType.STANDARD;
203
+ }
204
+ /**
205
+ * Find the main service provider file
206
+ */
207
+ async function findLaravelServiceProvider(options) {
208
+ const { installDir } = options;
209
+ // Look for AppServiceProvider first (most common place for setup)
210
+ const appServiceProvider = path.join(installDir, 'app/Providers/AppServiceProvider.php');
211
+ if (fs.existsSync(appServiceProvider)) {
212
+ return 'app/Providers/AppServiceProvider.php';
213
+ }
214
+ // Fall back to searching for any service provider
215
+ const providers = await (0, fast_glob_1.default)(['**/app/Providers/*ServiceProvider.php'], {
216
+ cwd: installDir,
217
+ ignore: LARAVEL_IGNORE_PATTERNS,
218
+ });
219
+ return providers[0];
220
+ }
221
+ /**
222
+ * Find the bootstrap file (differs between Laravel versions)
223
+ */
224
+ function findLaravelBootstrapFile(options) {
225
+ const { installDir } = options;
226
+ // Laravel 11+ uses bootstrap/app.php with new structure
227
+ const bootstrapApp = path.join(installDir, 'bootstrap/app.php');
228
+ if (fs.existsSync(bootstrapApp)) {
229
+ return 'bootstrap/app.php';
230
+ }
231
+ // Older Laravel uses app/Http/Kernel.php
232
+ const httpKernel = path.join(installDir, 'app/Http/Kernel.php');
233
+ if (fs.existsSync(httpKernel)) {
234
+ return 'app/Http/Kernel.php';
235
+ }
236
+ return undefined;
237
+ }
238
+ /**
239
+ * Detect Laravel version structure for configuration guidance
240
+ */
241
+ function detectLaravelStructure(options) {
242
+ const version = getLaravelVersion(options);
243
+ if (!version)
244
+ return 'modern';
245
+ try {
246
+ const majorVersion = parseInt(version.split('.')[0], 10);
247
+ if (majorVersion >= 11)
248
+ return 'latest'; // Laravel 11+ (new structure)
249
+ if (majorVersion >= 9)
250
+ return 'modern'; // Laravel 9-10
251
+ return 'legacy'; // Laravel 8 and below
252
+ }
253
+ catch {
254
+ return 'modern';
255
+ }
256
+ }
257
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/laravel/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { major, minVersion } from 'semver';\nimport fg from 'fast-glob';\nimport clack from '../utils/clack';\nimport type { WizardOptions } from '../utils/types';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nexport enum LaravelProjectType {\n STANDARD = 'standard', // Basic Laravel app\n INERTIA = 'inertia', // Inertia.js (Vue/React SPA) - may need JS SDK too\n LIVEWIRE = 'livewire', // Livewire (reactive components, includes Filament)\n}\n\n/**\n * Ignore patterns for Laravel projects\n */\nconst LARAVEL_IGNORE_PATTERNS = [\n '**/node_modules/**',\n '**/vendor/**',\n '**/storage/**',\n '**/bootstrap/cache/**',\n '**/.phpunit.cache/**',\n '**/public/build/**',\n '**/public/hot/**',\n];\n\n/**\n * Get Laravel version bucket for analytics\n */\nexport function getLaravelVersionBucket(version: string | undefined): string {\n if (!version) {\n return 'none';\n }\n\n try {\n const minVer = minVersion(version);\n if (!minVer) {\n return 'invalid';\n }\n const majorVersion = major(minVer);\n if (majorVersion >= 9) {\n return `${majorVersion}.x`;\n }\n return '<9.0.0';\n } catch {\n return 'unknown';\n }\n}\n\n/**\n * Read and parse composer.json\n */\nexport function getComposerJson(\n options: Pick<WizardOptions, 'installDir'>,\n): Record<string, any> | undefined {\n const { installDir } = options;\n\n const composerPath = path.join(installDir, 'composer.json');\n try {\n const content = fs.readFileSync(composerPath, 'utf-8');\n return JSON.parse(content);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Check if a package is installed (present in composer.json)\n */\nfunction hasComposerPackage(\n packageName: string,\n options: Pick<WizardOptions, 'installDir'>,\n): boolean {\n const composer = getComposerJson(options);\n if (!composer) return false;\n\n return !!(\n composer.require?.[packageName] || composer['require-dev']?.[packageName]\n );\n}\n\n/**\n * Extract version for a package from composer.json\n */\nfunction getComposerPackageVersion(\n packageName: string,\n options: Pick<WizardOptions, 'installDir'>,\n): string | undefined {\n const composer = getComposerJson(options);\n if (!composer) return undefined;\n\n const version =\n composer.require?.[packageName] || composer['require-dev']?.[packageName];\n if (version) {\n // Clean version string (remove ^, ~, >=, etc.)\n return version.replace(/^[\\^~>=<]+/, '');\n }\n\n return undefined;\n}\n\n/**\n * Check if a pattern exists in PHP source files\n */\nasync function hasLaravelCodePattern(\n pattern: RegExp | string,\n options: Pick<WizardOptions, 'installDir'>,\n filePatterns: string[] = ['**/*.php'],\n): Promise<boolean> {\n const { installDir } = options;\n\n const phpFiles = await fg(filePatterns, {\n cwd: installDir,\n ignore: LARAVEL_IGNORE_PATTERNS,\n });\n\n const searchPattern =\n typeof pattern === 'string' ? new RegExp(pattern) : pattern;\n\n for (const phpFile of phpFiles) {\n try {\n const content = fs.readFileSync(path.join(installDir, phpFile), 'utf-8');\n if (searchPattern.test(content)) return true;\n } catch {\n continue;\n }\n }\n\n return false;\n}\n\n/**\n * Get Laravel version from composer.json\n */\nexport function getLaravelVersion(\n options: Pick<WizardOptions, 'installDir'>,\n): string | undefined {\n return getComposerPackageVersion('laravel/framework', options);\n}\n\n/**\n * Get human-readable name for Laravel project type\n */\nexport function getLaravelProjectTypeName(\n projectType: LaravelProjectType,\n): string {\n switch (projectType) {\n case LaravelProjectType.STANDARD:\n return 'Standard Laravel';\n case LaravelProjectType.INERTIA:\n return 'Laravel with Inertia.js';\n case LaravelProjectType.LIVEWIRE:\n return 'Laravel with Livewire';\n default:\n return 'Laravel';\n }\n}\n\n/**\n * Check for Inertia.js\n */\nasync function hasInertia(\n options: Pick<WizardOptions, 'installDir'>,\n): Promise<boolean> {\n return (\n hasComposerPackage('inertiajs/inertia-laravel', options) ||\n (await hasLaravelCodePattern(/Inertia::render|inertia\\(/, options))\n );\n}\n\n/**\n * Check for Livewire\n */\nasync function hasLivewire(\n options: Pick<WizardOptions, 'installDir'>,\n): Promise<boolean> {\n return (\n hasComposerPackage('livewire/livewire', options) ||\n (await hasLaravelCodePattern(/extends\\s+Component|@livewire/, options))\n );\n}\n\n/**\n * Detect Laravel project type\n */\nexport async function getLaravelProjectType(\n options: WizardOptions,\n): Promise<LaravelProjectType> {\n // Check for SPA/Reactive frameworks (important to detect - affects SDK needs)\n if (await hasInertia(options)) {\n clack.log.info('Detected Laravel with Inertia.js');\n return LaravelProjectType.INERTIA;\n }\n if (await hasLivewire(options)) {\n clack.log.info('Detected Laravel with Livewire');\n return LaravelProjectType.LIVEWIRE;\n }\n\n // Default to standard\n clack.log.info('Detected standard Laravel project');\n return LaravelProjectType.STANDARD;\n}\n\n/**\n * Find the main service provider file\n */\nexport async function findLaravelServiceProvider(\n options: Pick<WizardOptions, 'installDir'>,\n): Promise<string | undefined> {\n const { installDir } = options;\n\n // Look for AppServiceProvider first (most common place for setup)\n const appServiceProvider = path.join(\n installDir,\n 'app/Providers/AppServiceProvider.php',\n );\n\n if (fs.existsSync(appServiceProvider)) {\n return 'app/Providers/AppServiceProvider.php';\n }\n\n // Fall back to searching for any service provider\n const providers = await fg(['**/app/Providers/*ServiceProvider.php'], {\n cwd: installDir,\n ignore: LARAVEL_IGNORE_PATTERNS,\n });\n\n return providers[0];\n}\n\n/**\n * Find the bootstrap file (differs between Laravel versions)\n */\nexport function findLaravelBootstrapFile(\n options: Pick<WizardOptions, 'installDir'>,\n): string | undefined {\n const { installDir } = options;\n\n // Laravel 11+ uses bootstrap/app.php with new structure\n const bootstrapApp = path.join(installDir, 'bootstrap/app.php');\n if (fs.existsSync(bootstrapApp)) {\n return 'bootstrap/app.php';\n }\n\n // Older Laravel uses app/Http/Kernel.php\n const httpKernel = path.join(installDir, 'app/Http/Kernel.php');\n if (fs.existsSync(httpKernel)) {\n return 'app/Http/Kernel.php';\n }\n\n return undefined;\n}\n\n/**\n * Detect Laravel version structure for configuration guidance\n */\nexport function detectLaravelStructure(\n options: Pick<WizardOptions, 'installDir'>,\n): 'legacy' | 'modern' | 'latest' {\n const version = getLaravelVersion(options);\n if (!version) return 'modern';\n\n try {\n const majorVersion = parseInt(version.split('.')[0], 10);\n if (majorVersion >= 11) return 'latest'; // Laravel 11+ (new structure)\n if (majorVersion >= 9) return 'modern'; // Laravel 9-10\n return 'legacy'; // Laravel 8 and below\n } catch {\n return 'modern';\n }\n}\n"]}
@@ -12,6 +12,8 @@ export declare const AgentSignals: {
12
12
  readonly ERROR_MCP_MISSING: "[ERROR-MCP-MISSING]";
13
13
  /** Signal emitted when the agent cannot access the setup resource */
14
14
  readonly ERROR_RESOURCE_MISSING: "[ERROR-RESOURCE-MISSING]";
15
+ /** Signal emitted when the agent provides a remark about its run */
16
+ readonly WIZARD_REMARK: "[WIZARD-REMARK]";
15
17
  };
16
18
  export type AgentSignal = (typeof AgentSignals)[keyof typeof AgentSignals];
17
19
  /**
@@ -42,6 +42,8 @@ exports.AgentSignals = {
42
42
  ERROR_MCP_MISSING: '[ERROR-MCP-MISSING]',
43
43
  /** Signal emitted when the agent cannot access the setup resource */
44
44
  ERROR_RESOURCE_MISSING: '[ERROR-RESOURCE-MISSING]',
45
+ /** Signal emitted when the agent provides a remark about its run */
46
+ WIZARD_REMARK: '[WIZARD-REMARK]',
45
47
  };
46
48
  /**
47
49
  * Error types that can be returned from agent execution.
@@ -339,6 +341,16 @@ async function runAgent(agentConfig, prompt, options, spinner, config) {
339
341
  else {
340
342
  (0, debug_1.logToFile)(`Agent run completed in ${durationSeconds}s`);
341
343
  }
344
+ // Extract and capture the agent's reflection on the run
345
+ const outputText = collectedText.join('\n');
346
+ const remarkRegex = new RegExp(`${exports.AgentSignals.WIZARD_REMARK.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\s*(.+?)(?:\\n|$)`, 's');
347
+ const remarkMatch = outputText.match(remarkRegex);
348
+ if (remarkMatch && remarkMatch[1]) {
349
+ const remark = remarkMatch[1].trim();
350
+ if (remark) {
351
+ analytics_1.analytics.capture(constants_1.WIZARD_REMARK_EVENT_NAME, { remark });
352
+ }
353
+ }
342
354
  analytics_1.analytics.capture(constants_1.WIZARD_INTERACTION_EVENT_NAME, {
343
355
  action: 'agent integration completed',
344
356
  duration_ms: durationMs,
@@ -395,6 +407,31 @@ async function runAgent(agentConfig, prompt, options, spinner, config) {
395
407
  (0, debug_1.debug)('CLI stderr:', data);
396
408
  }
397
409
  },
410
+ // Stop hook to have the agent reflect on its run
411
+ hooks: {
412
+ Stop: [
413
+ {
414
+ hooks: [
415
+ (input) => {
416
+ (0, debug_1.logToFile)('Stop hook triggered', {
417
+ stop_hook_active: input.stop_hook_active,
418
+ });
419
+ // Only ask for reflection on first stop (not after reflection is provided)
420
+ if (input.stop_hook_active) {
421
+ (0, debug_1.logToFile)('Stop hook: allowing stop (already reflected)');
422
+ return {}; // Allow stopping
423
+ }
424
+ (0, debug_1.logToFile)('Stop hook: requesting reflection');
425
+ return {
426
+ decision: 'block',
427
+ reason: `Before concluding, provide a brief remark about what information or guidance would have been useful to have in the integration prompt or documentation for this run. Specifically cite anything that would have prevented tool failures, erroneous edits, or other wasted turns. Format your response exactly as: ${exports.AgentSignals.WIZARD_REMARK} Your remark here`,
428
+ };
429
+ },
430
+ ],
431
+ timeout: 30,
432
+ },
433
+ ],
434
+ },
398
435
  },
399
436
  });
400
437
  // Process the async generator