@posthog/wizard 1.15.0 → 1.16.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.
- package/dist/src/__tests__/run.test.js +1 -0
- package/dist/src/__tests__/run.test.js.map +1 -1
- package/dist/src/lib/agent-interface.d.ts +27 -0
- package/dist/src/lib/agent-interface.js +161 -0
- package/dist/src/lib/agent-interface.js.map +1 -0
- package/dist/src/lib/constants.d.ts +8 -0
- package/dist/src/lib/constants.js +11 -1
- package/dist/src/lib/constants.js.map +1 -1
- package/dist/src/nextjs/nextjs-wizard-agent.d.ts +5 -0
- package/dist/src/nextjs/nextjs-wizard-agent.js +146 -0
- package/dist/src/nextjs/nextjs-wizard-agent.js.map +1 -0
- package/dist/src/run.js +62 -1
- package/dist/src/run.js.map +1 -1
- package/dist/src/utils/__tests__/analytics.test.js +9 -0
- package/dist/src/utils/__tests__/analytics.test.js.map +1 -1
- package/dist/src/utils/analytics.d.ts +2 -0
- package/dist/src/utils/analytics.js +18 -1
- package/dist/src/utils/analytics.js.map +1 -1
- package/package.json +6 -2
|
@@ -5,6 +5,7 @@ const nextjs_wizard_1 = require("../nextjs/nextjs-wizard");
|
|
|
5
5
|
const analytics_1 = require("../utils/analytics");
|
|
6
6
|
const constants_1 = require("../lib/constants");
|
|
7
7
|
jest.mock('../nextjs/nextjs-wizard');
|
|
8
|
+
jest.mock('../nextjs/nextjs-wizard-agent');
|
|
8
9
|
jest.mock('../utils/analytics');
|
|
9
10
|
jest.mock('../utils/clack');
|
|
10
11
|
const mockRunNextjsWizard = nextjs_wizard_1.runNextjsWizard;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.test.js","sourceRoot":"","sources":["../../../src/__tests__/run.test.ts"],"names":[],"mappings":";;AAAA,gCAAmC;AACnC,2DAA0D;AAC1D,kDAA+C;AAC/C,gDAA+C;AAE/C,IAAI,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;AACrC,IAAI,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;AAChC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;AAE5B,MAAM,mBAAmB,GAAG,+BAE3B,CAAC;AACF,MAAM,aAAa,GAAG,qBAA0C,CAAC;AAEjE,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;IACxC,UAAU,CAAC,GAAG,EAAE;QACd,IAAI,CAAC,aAAa,EAAE,CAAC;QAErB,aAAa,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;QACjC,aAAa,CAAC,gBAAgB,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;QAC3C,aAAa,CAAC,QAAQ,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;QAEhE,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE;YAClD,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,eAAe,EAAE,CAAC;IACzB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iEAAiE,EAAE,KAAK,IAAI,EAAE;QAC/E,MAAM,SAAS,GAAG,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;QAC7C,MAAM,QAAQ,GAAG;YACf,WAAW,EAAE,uBAAW,CAAC,MAAM;YAC/B,KAAK,EAAE,IAAI;YACX,YAAY,EAAE,KAAK;SACpB,CAAC;QAEF,mBAAmB,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;QAEjD,MAAM,MAAM,CAAC,IAAA,eAAS,EAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC;QAEzE,MAAM,CAAC,aAAa,CAAC,gBAAgB,CAAC,CAAC,oBAAoB,CAAC,SAAS,EAAE;YACrE,WAAW,EAAE,uBAAW,CAAC,MAAM;YAC/B,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;SACpC,CAAC,CAAC;QAEH,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uDAAuD,EAAE,KAAK,IAAI,EAAE;QACrE,MAAM,QAAQ,GAAG,EAAE,WAAW,EAAE,uBAAW,CAAC,MAAM,EAAE,CAAC;QAErD,mBAAmB,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;QAEjD,MAAM,IAAA,eAAS,EAAC,QAAQ,CAAC,CAAC;QAE1B,MAAM,CAAC,aAAa,CAAC,gBAAgB,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QAC9D,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IACxD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { runWizard } from '../run';\nimport { runNextjsWizard } from '../nextjs/nextjs-wizard';\nimport { analytics } from '../utils/analytics';\nimport { Integration } from '../lib/constants';\n\njest.mock('../nextjs/nextjs-wizard');\njest.mock('../utils/analytics');\njest.mock('../utils/clack');\n\nconst mockRunNextjsWizard = runNextjsWizard as jest.MockedFunction<\n typeof runNextjsWizard\n>;\nconst mockAnalytics = analytics as jest.Mocked<typeof analytics>;\n\ndescribe('runWizard error handling', () => {\n beforeEach(() => {\n jest.clearAllMocks();\n\n mockAnalytics.setTag = jest.fn();\n mockAnalytics.captureException = jest.fn();\n mockAnalytics.shutdown = jest.fn().mockResolvedValue(undefined);\n\n jest.spyOn(process, 'exit').mockImplementation(() => {\n throw new Error('process.exit called');\n });\n });\n\n afterEach(() => {\n jest.restoreAllMocks();\n });\n\n it('should capture exception and shutdown analytics on wizard error', async () => {\n const testError = new Error('Wizard failed');\n const testArgs = {\n integration: Integration.nextjs,\n debug: true,\n forceInstall: false,\n };\n\n mockRunNextjsWizard.mockRejectedValue(testError);\n\n await expect(runWizard(testArgs)).rejects.toThrow('process.exit called');\n\n expect(mockAnalytics.captureException).toHaveBeenCalledWith(testError, {\n integration: Integration.nextjs,\n arguments: JSON.stringify(testArgs),\n });\n\n expect(mockAnalytics.shutdown).toHaveBeenCalledWith('error');\n });\n\n it('should not call captureException when wizard succeeds', async () => {\n const testArgs = { integration: Integration.nextjs };\n\n mockRunNextjsWizard.mockResolvedValue(undefined);\n\n await runWizard(testArgs);\n\n expect(mockAnalytics.captureException).not.toHaveBeenCalled();\n expect(mockAnalytics.shutdown).not.toHaveBeenCalled();\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"run.test.js","sourceRoot":"","sources":["../../../src/__tests__/run.test.ts"],"names":[],"mappings":";;AAAA,gCAAmC;AACnC,2DAA0D;AAC1D,kDAA+C;AAC/C,gDAA+C;AAE/C,IAAI,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;AACrC,IAAI,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;AAC3C,IAAI,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;AAChC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;AAE5B,MAAM,mBAAmB,GAAG,+BAE3B,CAAC;AACF,MAAM,aAAa,GAAG,qBAA0C,CAAC;AAEjE,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;IACxC,UAAU,CAAC,GAAG,EAAE;QACd,IAAI,CAAC,aAAa,EAAE,CAAC;QAErB,aAAa,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;QACjC,aAAa,CAAC,gBAAgB,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;QAC3C,aAAa,CAAC,QAAQ,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;QAEhE,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE;YAClD,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,eAAe,EAAE,CAAC;IACzB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iEAAiE,EAAE,KAAK,IAAI,EAAE;QAC/E,MAAM,SAAS,GAAG,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;QAC7C,MAAM,QAAQ,GAAG;YACf,WAAW,EAAE,uBAAW,CAAC,MAAM;YAC/B,KAAK,EAAE,IAAI;YACX,YAAY,EAAE,KAAK;SACpB,CAAC;QAEF,mBAAmB,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;QAEjD,MAAM,MAAM,CAAC,IAAA,eAAS,EAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC;QAEzE,MAAM,CAAC,aAAa,CAAC,gBAAgB,CAAC,CAAC,oBAAoB,CAAC,SAAS,EAAE;YACrE,WAAW,EAAE,uBAAW,CAAC,MAAM;YAC/B,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;SACpC,CAAC,CAAC;QAEH,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uDAAuD,EAAE,KAAK,IAAI,EAAE;QACrE,MAAM,QAAQ,GAAG,EAAE,WAAW,EAAE,uBAAW,CAAC,MAAM,EAAE,CAAC;QAErD,mBAAmB,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;QAEjD,MAAM,IAAA,eAAS,EAAC,QAAQ,CAAC,CAAC;QAE1B,MAAM,CAAC,aAAa,CAAC,gBAAgB,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QAC9D,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IACxD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { runWizard } from '../run';\nimport { runNextjsWizard } from '../nextjs/nextjs-wizard';\nimport { analytics } from '../utils/analytics';\nimport { Integration } from '../lib/constants';\n\njest.mock('../nextjs/nextjs-wizard');\njest.mock('../nextjs/nextjs-wizard-agent');\njest.mock('../utils/analytics');\njest.mock('../utils/clack');\n\nconst mockRunNextjsWizard = runNextjsWizard as jest.MockedFunction<\n typeof runNextjsWizard\n>;\nconst mockAnalytics = analytics as jest.Mocked<typeof analytics>;\n\ndescribe('runWizard error handling', () => {\n beforeEach(() => {\n jest.clearAllMocks();\n\n mockAnalytics.setTag = jest.fn();\n mockAnalytics.captureException = jest.fn();\n mockAnalytics.shutdown = jest.fn().mockResolvedValue(undefined);\n\n jest.spyOn(process, 'exit').mockImplementation(() => {\n throw new Error('process.exit called');\n });\n });\n\n afterEach(() => {\n jest.restoreAllMocks();\n });\n\n it('should capture exception and shutdown analytics on wizard error', async () => {\n const testError = new Error('Wizard failed');\n const testArgs = {\n integration: Integration.nextjs,\n debug: true,\n forceInstall: false,\n };\n\n mockRunNextjsWizard.mockRejectedValue(testError);\n\n await expect(runWizard(testArgs)).rejects.toThrow('process.exit called');\n\n expect(mockAnalytics.captureException).toHaveBeenCalledWith(testError, {\n integration: Integration.nextjs,\n arguments: JSON.stringify(testArgs),\n });\n\n expect(mockAnalytics.shutdown).toHaveBeenCalledWith('error');\n });\n\n it('should not call captureException when wizard succeeds', async () => {\n const testArgs = { integration: Integration.nextjs };\n\n mockRunNextjsWizard.mockResolvedValue(undefined);\n\n await runWizard(testArgs);\n\n expect(mockAnalytics.captureException).not.toHaveBeenCalled();\n expect(mockAnalytics.shutdown).not.toHaveBeenCalled();\n });\n});\n"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared agent interface for PostHog wizards
|
|
3
|
+
* Provides common agent initialization and event handling
|
|
4
|
+
*/
|
|
5
|
+
import { Agent } from '@posthog/agent';
|
|
6
|
+
import clack from '../utils/clack';
|
|
7
|
+
import type { WizardOptions } from '../utils/types';
|
|
8
|
+
export type AgentConfig = {
|
|
9
|
+
workingDirectory: string;
|
|
10
|
+
posthogMcpUrl: string;
|
|
11
|
+
posthogApiKey: string;
|
|
12
|
+
debug?: boolean;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Initialize a PostHog Agent instance with the provided configuration
|
|
16
|
+
*/
|
|
17
|
+
export declare function initializeAgent(config: AgentConfig, options: WizardOptions, spinner: ReturnType<typeof clack.spinner>): Agent;
|
|
18
|
+
/**
|
|
19
|
+
* Execute an agent with the provided prompt and options
|
|
20
|
+
* Handles the full lifecycle: spinner, execution, error handling
|
|
21
|
+
*/
|
|
22
|
+
export declare function runAgent(agent: Agent, prompt: string, options: WizardOptions, spinner: ReturnType<typeof clack.spinner>, config?: {
|
|
23
|
+
estimatedDurationMinutes?: number;
|
|
24
|
+
spinnerMessage?: string;
|
|
25
|
+
successMessage?: string;
|
|
26
|
+
errorMessage?: string;
|
|
27
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Shared agent interface for PostHog wizards
|
|
4
|
+
* Provides common agent initialization and event handling
|
|
5
|
+
*/
|
|
6
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
7
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
|
+
};
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.initializeAgent = initializeAgent;
|
|
11
|
+
exports.runAgent = runAgent;
|
|
12
|
+
// @ts-ignore - posthog-agent is ESM, wizard is CommonJS. Works at runtime via local link.
|
|
13
|
+
const agent_1 = require("@posthog/agent");
|
|
14
|
+
const clack_1 = __importDefault(require("../utils/clack"));
|
|
15
|
+
const debug_1 = require("../utils/debug");
|
|
16
|
+
const analytics_1 = require("../utils/analytics");
|
|
17
|
+
const constants_1 = require("./constants");
|
|
18
|
+
// TODO: Remove these if/when posthog/agent exports an enum for events
|
|
19
|
+
const EventType = {
|
|
20
|
+
RAW_SDK_EVENT: 'raw_sdk_event',
|
|
21
|
+
TOKEN: 'token',
|
|
22
|
+
TOOL_CALL: 'tool_call',
|
|
23
|
+
TOOL_RESULT: 'tool_result',
|
|
24
|
+
ERROR: 'error',
|
|
25
|
+
DONE: 'done',
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Initialize a PostHog Agent instance with the provided configuration
|
|
29
|
+
*/
|
|
30
|
+
function initializeAgent(config, options, spinner) {
|
|
31
|
+
clack_1.default.log.step('Initializing PostHog agent...');
|
|
32
|
+
try {
|
|
33
|
+
const agentConfig = {
|
|
34
|
+
workingDirectory: config.workingDirectory,
|
|
35
|
+
posthogMcpUrl: config.posthogMcpUrl,
|
|
36
|
+
posthogApiKey: config.posthogApiKey,
|
|
37
|
+
onEvent: (event) => {
|
|
38
|
+
handleAgentEvent(event, options, spinner);
|
|
39
|
+
},
|
|
40
|
+
debug: config.debug ?? false,
|
|
41
|
+
};
|
|
42
|
+
if (options.debug) {
|
|
43
|
+
(0, debug_1.debug)('Agent config:', {
|
|
44
|
+
workingDirectory: agentConfig.workingDirectory,
|
|
45
|
+
posthogMcpUrl: agentConfig.posthogMcpUrl,
|
|
46
|
+
posthogApiKeyPresent: !!agentConfig.posthogApiKey,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
const agent = new agent_1.Agent(agentConfig);
|
|
50
|
+
clack_1.default.log.success("Agent initialized. Let's get cooking!");
|
|
51
|
+
return agent;
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
clack_1.default.log.error(`Failed to initialize agent: ${error.message}`);
|
|
55
|
+
(0, debug_1.debug)('Agent initialization error:', error);
|
|
56
|
+
throw error;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Handle agent events and provide user feedback
|
|
61
|
+
* This function processes events from the agent SDK and provides appropriate
|
|
62
|
+
* user feedback through the CLI spinner and logging
|
|
63
|
+
*/
|
|
64
|
+
function handleAgentEvent(event, options, spinner) {
|
|
65
|
+
if (options.debug) {
|
|
66
|
+
(0, debug_1.debug)(`Event type: ${event.type}`, JSON.stringify(event, null, 2));
|
|
67
|
+
}
|
|
68
|
+
// Only show [STATUS] events to the user - everything else goes to debug log
|
|
69
|
+
switch (event.type) {
|
|
70
|
+
case EventType.RAW_SDK_EVENT:
|
|
71
|
+
if (event.sdkMessage?.type === 'assistant') {
|
|
72
|
+
const message = event.sdkMessage.message;
|
|
73
|
+
if (message?.content && Array.isArray(message.content)) {
|
|
74
|
+
const textContent = message.content
|
|
75
|
+
.filter((block) => block.type === 'text')
|
|
76
|
+
.map((block) => block.text)
|
|
77
|
+
.join('\n');
|
|
78
|
+
// Check if the text contains a [STATUS] marker
|
|
79
|
+
const statusMatch = textContent.match(/^.*\[STATUS\]\s*(.+?)$/m);
|
|
80
|
+
if (statusMatch) {
|
|
81
|
+
// Stop spinner, log the status step, restart spinner
|
|
82
|
+
// This creates the progress list as the agent proceeds
|
|
83
|
+
spinner.stop(statusMatch[1].trim());
|
|
84
|
+
spinner.start('Integrating PostHog...');
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
break;
|
|
89
|
+
case EventType.TOKEN:
|
|
90
|
+
if (options.debug) {
|
|
91
|
+
(0, debug_1.debug)(event.content);
|
|
92
|
+
}
|
|
93
|
+
break;
|
|
94
|
+
case EventType.TOOL_CALL:
|
|
95
|
+
if (options.debug) {
|
|
96
|
+
(0, debug_1.debug)(`Tool: ${event.toolName}`);
|
|
97
|
+
(0, debug_1.debug)(' Args:', JSON.stringify(event.args, null, 2));
|
|
98
|
+
}
|
|
99
|
+
break;
|
|
100
|
+
case EventType.TOOL_RESULT:
|
|
101
|
+
if (options.debug) {
|
|
102
|
+
(0, debug_1.debug)(`✅ ${event.toolName} completed`);
|
|
103
|
+
const resultStr = typeof event.result === 'string'
|
|
104
|
+
? event.result
|
|
105
|
+
: JSON.stringify(event.result, null, 2);
|
|
106
|
+
const truncated = resultStr.length > 500
|
|
107
|
+
? `${resultStr.substring(0, 500)}...`
|
|
108
|
+
: resultStr;
|
|
109
|
+
(0, debug_1.debug)(' Result:', truncated);
|
|
110
|
+
}
|
|
111
|
+
break;
|
|
112
|
+
case EventType.ERROR:
|
|
113
|
+
// Always show errors to user
|
|
114
|
+
clack_1.default.log.error(`Error: ${event.message}`);
|
|
115
|
+
if (options.debug && event.error) {
|
|
116
|
+
(0, debug_1.debug)('Error details:', event.error);
|
|
117
|
+
}
|
|
118
|
+
if (event.error instanceof Error) {
|
|
119
|
+
analytics_1.analytics.captureException(event.error, {
|
|
120
|
+
event_type: event.type,
|
|
121
|
+
message: event.message,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
break;
|
|
125
|
+
case EventType.DONE:
|
|
126
|
+
if (event.durationMs) {
|
|
127
|
+
if (options.debug) {
|
|
128
|
+
(0, debug_1.debug)(`Completed in ${Math.round(event.durationMs / 1000)}s`);
|
|
129
|
+
}
|
|
130
|
+
analytics_1.analytics.capture(constants_1.WIZARD_INTERACTION_EVENT_NAME, {
|
|
131
|
+
action: 'agent integration completed',
|
|
132
|
+
duration_ms: event.durationMs,
|
|
133
|
+
duration_seconds: Math.round(event.durationMs / 1000),
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Execute an agent with the provided prompt and options
|
|
141
|
+
* Handles the full lifecycle: spinner, execution, error handling
|
|
142
|
+
*/
|
|
143
|
+
async function runAgent(agent, prompt, options, spinner, config) {
|
|
144
|
+
const { estimatedDurationMinutes = 8, spinnerMessage = 'Customizing your PostHog setup...', successMessage = 'PostHog integration complete', errorMessage = 'Integration failed', } = config ?? {};
|
|
145
|
+
clack_1.default.log.step(`This whole process should take about ${estimatedDurationMinutes} minutes including error checking and fixes.\n\nGrab some coffee!`);
|
|
146
|
+
spinner.start(spinnerMessage);
|
|
147
|
+
try {
|
|
148
|
+
await agent.run(prompt, {
|
|
149
|
+
repositoryPath: options.installDir,
|
|
150
|
+
permissionMode: agent_1.PermissionMode.ACCEPT_EDITS,
|
|
151
|
+
});
|
|
152
|
+
spinner.stop(successMessage);
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
spinner.stop(errorMessage);
|
|
156
|
+
clack_1.default.log.error(`Error: ${error.message}`);
|
|
157
|
+
(0, debug_1.debug)('Full error:', error);
|
|
158
|
+
throw error;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=agent-interface.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-interface.js","sourceRoot":"","sources":["../../../src/lib/agent-interface.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared agent interface for PostHog wizards\n * Provides common agent initialization and event handling\n */\n\n// @ts-ignore - posthog-agent is ESM, wizard is CommonJS. Works at runtime via local link.\nimport { Agent, PermissionMode, type AgentEvent } from '@posthog/agent';\nimport clack from '../utils/clack';\nimport { debug } from '../utils/debug';\nimport type { WizardOptions } from '../utils/types';\nimport { analytics } from '../utils/analytics';\nimport { WIZARD_INTERACTION_EVENT_NAME } from './constants';\n\n// TODO: Remove these if/when posthog/agent exports an enum for events\nconst EventType = {\n RAW_SDK_EVENT: 'raw_sdk_event',\n TOKEN: 'token',\n TOOL_CALL: 'tool_call',\n TOOL_RESULT: 'tool_result',\n ERROR: 'error',\n DONE: 'done',\n} as const;\n\nexport type AgentConfig = {\n workingDirectory: string;\n posthogMcpUrl: string;\n posthogApiKey: string;\n debug?: boolean;\n};\n\n/**\n * Initialize a PostHog Agent instance with the provided configuration\n */\nexport function initializeAgent(\n config: AgentConfig,\n options: WizardOptions,\n spinner: ReturnType<typeof clack.spinner>,\n): Agent {\n clack.log.step('Initializing PostHog agent...');\n\n try {\n const agentConfig = {\n workingDirectory: config.workingDirectory,\n posthogMcpUrl: config.posthogMcpUrl,\n posthogApiKey: config.posthogApiKey,\n onEvent: (event: AgentEvent) => {\n handleAgentEvent(event, options, spinner);\n },\n debug: config.debug ?? false,\n };\n\n if (options.debug) {\n debug('Agent config:', {\n workingDirectory: agentConfig.workingDirectory,\n posthogMcpUrl: agentConfig.posthogMcpUrl,\n posthogApiKeyPresent: !!agentConfig.posthogApiKey,\n });\n }\n\n const agent = new Agent(agentConfig);\n clack.log.success(\"Agent initialized. Let's get cooking!\");\n return agent;\n } catch (error) {\n clack.log.error(`Failed to initialize agent: ${(error as Error).message}`);\n debug('Agent initialization error:', error);\n throw error;\n }\n}\n\n/**\n * Handle agent events and provide user feedback\n * This function processes events from the agent SDK and provides appropriate\n * user feedback through the CLI spinner and logging\n */\nfunction handleAgentEvent(\n event: AgentEvent,\n options: WizardOptions,\n spinner: ReturnType<typeof clack.spinner>,\n): void {\n if (options.debug) {\n debug(`Event type: ${event.type}`, JSON.stringify(event, null, 2));\n }\n\n // Only show [STATUS] events to the user - everything else goes to debug log\n switch (event.type) {\n case EventType.RAW_SDK_EVENT:\n if (event.sdkMessage?.type === 'assistant') {\n const message = event.sdkMessage.message;\n if (message?.content && Array.isArray(message.content)) {\n const textContent = message.content\n .filter((block: any) => block.type === 'text')\n .map((block: any) => block.text)\n .join('\\n');\n\n // Check if the text contains a [STATUS] marker\n const statusMatch = textContent.match(/^.*\\[STATUS\\]\\s*(.+?)$/m);\n if (statusMatch) {\n // Stop spinner, log the status step, restart spinner\n // This creates the progress list as the agent proceeds\n spinner.stop(statusMatch[1].trim());\n spinner.start('Integrating PostHog...');\n }\n }\n }\n break;\n\n case EventType.TOKEN:\n if (options.debug) {\n debug(event.content);\n }\n break;\n\n case EventType.TOOL_CALL:\n if (options.debug) {\n debug(`Tool: ${event.toolName}`);\n debug(' Args:', JSON.stringify(event.args, null, 2));\n }\n break;\n\n case EventType.TOOL_RESULT:\n if (options.debug) {\n debug(`✅ ${event.toolName} completed`);\n const resultStr: string =\n typeof event.result === 'string'\n ? event.result\n : JSON.stringify(event.result, null, 2);\n const truncated =\n resultStr.length > 500\n ? `${resultStr.substring(0, 500)}...`\n : resultStr;\n debug(' Result:', truncated);\n }\n break;\n\n case EventType.ERROR:\n // Always show errors to user\n clack.log.error(`Error: ${event.message}`);\n if (options.debug && event.error) {\n debug('Error details:', event.error);\n }\n if (event.error instanceof Error) {\n analytics.captureException(event.error, {\n event_type: event.type,\n message: event.message,\n });\n }\n break;\n\n case EventType.DONE:\n if (event.durationMs) {\n if (options.debug) {\n debug(`Completed in ${Math.round(event.durationMs / 1000)}s`);\n }\n analytics.capture(WIZARD_INTERACTION_EVENT_NAME, {\n action: 'agent integration completed',\n duration_ms: event.durationMs,\n duration_seconds: Math.round(event.durationMs / 1000),\n });\n }\n break;\n }\n}\n\n/**\n * Execute an agent with the provided prompt and options\n * Handles the full lifecycle: spinner, execution, error handling\n */\nexport async function runAgent(\n agent: Agent,\n prompt: string,\n options: WizardOptions,\n spinner: ReturnType<typeof clack.spinner>,\n config?: {\n estimatedDurationMinutes?: number;\n spinnerMessage?: string;\n successMessage?: string;\n errorMessage?: string;\n },\n): Promise<void> {\n const {\n estimatedDurationMinutes = 8,\n spinnerMessage = 'Customizing your PostHog setup...',\n successMessage = 'PostHog integration complete',\n errorMessage = 'Integration failed',\n } = config ?? {};\n\n clack.log.step(\n `This whole process should take about ${estimatedDurationMinutes} minutes including error checking and fixes.\\n\\nGrab some coffee!`,\n );\n\n spinner.start(spinnerMessage);\n\n try {\n await agent.run(prompt, {\n repositoryPath: options.installDir,\n permissionMode: PermissionMode.ACCEPT_EDITS,\n });\n spinner.stop(successMessage);\n } catch (error) {\n spinner.stop(errorMessage);\n clack.log.error(`Error: ${(error as Error).message}`);\n debug('Full error:', error);\n throw error;\n }\n}\n"]}
|
|
@@ -5,6 +5,13 @@ export declare enum Integration {
|
|
|
5
5
|
reactNative = "react-native",
|
|
6
6
|
astro = "astro"
|
|
7
7
|
}
|
|
8
|
+
export declare enum FeatureFlagDefinition {
|
|
9
|
+
NextV2 = "wizard-next-v2"
|
|
10
|
+
}
|
|
11
|
+
export declare enum WizardVariant {
|
|
12
|
+
Legacy = "legacy",
|
|
13
|
+
Agent = "agent"
|
|
14
|
+
}
|
|
8
15
|
export declare function getIntegrationDescription(type: string): string;
|
|
9
16
|
type IntegrationChoice = {
|
|
10
17
|
name: string;
|
|
@@ -27,4 +34,5 @@ export declare const POSTHOG_US_CLIENT_ID = "c4Rdw8DIxgtQfA80IiSnGKlNX8QN00cFWF0
|
|
|
27
34
|
export declare const POSTHOG_EU_CLIENT_ID = "bx2C5sZRN03TkdjraCcetvQFPGH6N2Y9vRLkcKEy";
|
|
28
35
|
export declare const POSTHOG_DEV_CLIENT_ID = "DC5uRLVbGI02YQ82grxgnK6Qn12SXWpCqdPb60oZ";
|
|
29
36
|
export declare const OAUTH_PORT = 8239;
|
|
37
|
+
export declare const WIZARD_INTERACTION_EVENT_NAME = "wizard interaction";
|
|
30
38
|
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.OAUTH_PORT = exports.POSTHOG_DEV_CLIENT_ID = exports.POSTHOG_EU_CLIENT_ID = exports.POSTHOG_US_CLIENT_ID = exports.DUMMY_PROJECT_API_KEY = exports.ANALYTICS_HOST_URL = exports.ANALYTICS_POSTHOG_PUBLIC_PROJECT_WRITE_KEY = exports.DEFAULT_HOST_URL = exports.ISSUES_URL = exports.DEFAULT_URL = exports.DEBUG = exports.IS_DEV = exports.Integration = void 0;
|
|
3
|
+
exports.WIZARD_INTERACTION_EVENT_NAME = exports.OAUTH_PORT = exports.POSTHOG_DEV_CLIENT_ID = exports.POSTHOG_EU_CLIENT_ID = exports.POSTHOG_US_CLIENT_ID = exports.DUMMY_PROJECT_API_KEY = exports.ANALYTICS_HOST_URL = exports.ANALYTICS_POSTHOG_PUBLIC_PROJECT_WRITE_KEY = exports.DEFAULT_HOST_URL = exports.ISSUES_URL = exports.DEFAULT_URL = exports.DEBUG = exports.IS_DEV = exports.WizardVariant = exports.FeatureFlagDefinition = exports.Integration = void 0;
|
|
4
4
|
exports.getIntegrationDescription = getIntegrationDescription;
|
|
5
5
|
exports.getIntegrationChoices = getIntegrationChoices;
|
|
6
6
|
var Integration;
|
|
@@ -11,6 +11,15 @@ var Integration;
|
|
|
11
11
|
Integration["reactNative"] = "react-native";
|
|
12
12
|
Integration["astro"] = "astro";
|
|
13
13
|
})(Integration || (exports.Integration = Integration = {}));
|
|
14
|
+
var FeatureFlagDefinition;
|
|
15
|
+
(function (FeatureFlagDefinition) {
|
|
16
|
+
FeatureFlagDefinition["NextV2"] = "wizard-next-v2";
|
|
17
|
+
})(FeatureFlagDefinition || (exports.FeatureFlagDefinition = FeatureFlagDefinition = {}));
|
|
18
|
+
var WizardVariant;
|
|
19
|
+
(function (WizardVariant) {
|
|
20
|
+
WizardVariant["Legacy"] = "legacy";
|
|
21
|
+
WizardVariant["Agent"] = "agent";
|
|
22
|
+
})(WizardVariant || (exports.WizardVariant = WizardVariant = {}));
|
|
14
23
|
function getIntegrationDescription(type) {
|
|
15
24
|
switch (type) {
|
|
16
25
|
case Integration.nextjs:
|
|
@@ -49,4 +58,5 @@ exports.POSTHOG_US_CLIENT_ID = 'c4Rdw8DIxgtQfA80IiSnGKlNX8QN00cFWF00QQhM';
|
|
|
49
58
|
exports.POSTHOG_EU_CLIENT_ID = 'bx2C5sZRN03TkdjraCcetvQFPGH6N2Y9vRLkcKEy';
|
|
50
59
|
exports.POSTHOG_DEV_CLIENT_ID = 'DC5uRLVbGI02YQ82grxgnK6Qn12SXWpCqdPb60oZ';
|
|
51
60
|
exports.OAUTH_PORT = 8239;
|
|
61
|
+
exports.WIZARD_INTERACTION_EVENT_NAME = 'wizard interaction';
|
|
52
62
|
//# sourceMappingURL=constants.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/lib/constants.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/lib/constants.ts"],"names":[],"mappings":";;;AAiBA,8DAeC;AAOD,sDAKC;AA5CD,IAAY,WAMX;AAND,WAAY,WAAW;IACrB,gCAAiB,CAAA;IACjB,8BAAe,CAAA;IACf,gCAAiB,CAAA;IACjB,2CAA4B,CAAA;IAC5B,8BAAe,CAAA;AACjB,CAAC,EANW,WAAW,2BAAX,WAAW,QAMtB;AAED,IAAY,qBAEX;AAFD,WAAY,qBAAqB;IAC/B,kDAAyB,CAAA;AAC3B,CAAC,EAFW,qBAAqB,qCAArB,qBAAqB,QAEhC;AAED,IAAY,aAGX;AAHD,WAAY,aAAa;IACvB,kCAAiB,CAAA;IACjB,gCAAe,CAAA;AACjB,CAAC,EAHW,aAAa,6BAAb,aAAa,QAGxB;AAED,SAAgB,yBAAyB,CAAC,IAAY;IACpD,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,WAAW,CAAC,MAAM;YACrB,OAAO,SAAS,CAAC;QACnB,KAAK,WAAW,CAAC,KAAK;YACpB,OAAO,OAAO,CAAC;QACjB,KAAK,WAAW,CAAC,WAAW;YAC1B,OAAO,cAAc,CAAC;QACxB,KAAK,WAAW,CAAC,MAAM;YACrB,OAAO,QAAQ,CAAC;QAClB,KAAK,WAAW,CAAC,KAAK;YACpB,OAAO,OAAO,CAAC;QACjB;YACE,MAAM,IAAI,KAAK,CAAC,uBAAuB,IAAI,EAAE,CAAC,CAAC;IACnD,CAAC;AACH,CAAC;AAOD,SAAgB,qBAAqB;IACnC,OAAO,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC;QACrD,IAAI,EAAE,yBAAyB,CAAC,IAAI,CAAC;QACrC,KAAK,EAAE,IAAI;KACZ,CAAC,CAAC,CAAC;AACN,CAAC;AAOY,QAAA,MAAM,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,QAAQ,CACpD,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAC3B,CAAC;AAEW,QAAA,KAAK,GAAG,KAAK,CAAC;AAEd,QAAA,WAAW,GAAG,cAAM;IAC/B,CAAC,CAAC,uBAAuB;IACzB,CAAC,CAAC,wBAAwB,CAAC;AAChB,QAAA,UAAU,GAAG,0CAA0C,CAAC;AACxD,QAAA,gBAAgB,GAAG,cAAM;IACpC,CAAC,CAAC,uBAAuB;IACzB,CAAC,CAAC,0BAA0B,CAAC;AAClB,QAAA,0CAA0C,GAAG,gBAAgB,CAAC;AAC9D,QAAA,kBAAkB,GAAG,gCAAgC,CAAC;AACtD,QAAA,qBAAqB,GAAG,gCAAgC,CAAC;AAEzD,QAAA,oBAAoB,GAAG,0CAA0C,CAAC;AAClE,QAAA,oBAAoB,GAAG,0CAA0C,CAAC;AAClE,QAAA,qBAAqB,GAAG,0CAA0C,CAAC;AACnE,QAAA,UAAU,GAAG,IAAI,CAAC;AAElB,QAAA,6BAA6B,GAAG,oBAAoB,CAAC","sourcesContent":["export enum Integration {\n nextjs = 'nextjs',\n react = 'react',\n svelte = 'svelte',\n reactNative = 'react-native',\n astro = 'astro',\n}\n\nexport enum FeatureFlagDefinition {\n NextV2 = 'wizard-next-v2',\n}\n\nexport enum WizardVariant {\n Legacy = 'legacy',\n Agent = 'agent',\n}\n\nexport function getIntegrationDescription(type: string): string {\n switch (type) {\n case Integration.nextjs:\n return 'Next.js';\n case Integration.react:\n return 'React';\n case Integration.reactNative:\n return 'React Native';\n case Integration.svelte:\n return 'Svelte';\n case Integration.astro:\n return 'Astro';\n default:\n throw new Error(`Unknown integration ${type}`);\n }\n}\n\ntype IntegrationChoice = {\n name: string;\n value: string;\n};\n\nexport function getIntegrationChoices(): IntegrationChoice[] {\n return Object.keys(Integration).map((type: string) => ({\n name: getIntegrationDescription(type),\n value: type,\n }));\n}\n\nexport interface Args {\n debug: boolean;\n integration: Integration;\n}\n\nexport const IS_DEV = ['test', 'development'].includes(\n process.env.NODE_ENV ?? '',\n);\n\nexport const DEBUG = false;\n\nexport const DEFAULT_URL = IS_DEV\n ? 'http://localhost:8010'\n : 'https://us.posthog.com';\nexport const ISSUES_URL = 'https://github.com/posthog/wizard/issues';\nexport const DEFAULT_HOST_URL = IS_DEV\n ? 'http://localhost:8010'\n : 'https://us.i.posthog.com';\nexport const ANALYTICS_POSTHOG_PUBLIC_PROJECT_WRITE_KEY = 'sTMFPsFhdP1Ssg';\nexport const ANALYTICS_HOST_URL = 'https://internal-j.posthog.com';\nexport const DUMMY_PROJECT_API_KEY = '_YOUR_POSTHOG_PROJECT_API_KEY_';\n\nexport const POSTHOG_US_CLIENT_ID = 'c4Rdw8DIxgtQfA80IiSnGKlNX8QN00cFWF00QQhM';\nexport const POSTHOG_EU_CLIENT_ID = 'bx2C5sZRN03TkdjraCcetvQFPGH6N2Y9vRLkcKEy';\nexport const POSTHOG_DEV_CLIENT_ID = 'DC5uRLVbGI02YQ82grxgnK6Qn12SXWpCqdPb60oZ';\nexport const OAUTH_PORT = 8239;\n\nexport const WIZARD_INTERACTION_EVENT_NAME = 'wizard interaction';\n"]}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.runNextjsWizardAgent = runNextjsWizardAgent;
|
|
7
|
+
/* Simplified Next.js wizard using posthog-agent with PostHog MCP */
|
|
8
|
+
const clack_utils_1 = require("../utils/clack-utils");
|
|
9
|
+
const package_json_1 = require("../utils/package-json");
|
|
10
|
+
const utils_1 = require("./utils");
|
|
11
|
+
const clack_1 = __importDefault(require("../utils/clack"));
|
|
12
|
+
const constants_1 = require("../lib/constants");
|
|
13
|
+
const analytics_1 = require("../utils/analytics");
|
|
14
|
+
const clack_utils_2 = require("../utils/clack-utils");
|
|
15
|
+
const urls_1 = require("../utils/urls");
|
|
16
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
17
|
+
const steps_1 = require("../steps");
|
|
18
|
+
const debug_1 = require("../utils/debug");
|
|
19
|
+
const agent_interface_1 = require("../lib/agent-interface");
|
|
20
|
+
/**
|
|
21
|
+
* Simplified Next.js wizard that delegates to PostHog MCP's /integrate command
|
|
22
|
+
*/
|
|
23
|
+
async function runNextjsWizardAgent(options) {
|
|
24
|
+
if (options.debug) {
|
|
25
|
+
(0, debug_1.enableDebugLogs)();
|
|
26
|
+
}
|
|
27
|
+
(0, clack_utils_1.printWelcome)({
|
|
28
|
+
wizardName: 'PostHog Next.js wizard (agent-powered)',
|
|
29
|
+
});
|
|
30
|
+
clack_1.default.log.info('🧙 The wizard has chosen you to try the next-generation agent integration for Next.js.\n\nStand by for the good stuff, and let me know how it goes:\n\ndanilo@posthog.com');
|
|
31
|
+
const aiConsent = await (0, clack_utils_1.askForAIConsent)(options);
|
|
32
|
+
if (!aiConsent) {
|
|
33
|
+
await (0, clack_utils_1.abort)('This wizard uses an LLM agent to intelligently modify your project. Please view the docs to setup Next.js manually instead: https://posthog.com/docs/libraries/next-js', 0);
|
|
34
|
+
}
|
|
35
|
+
const cloudRegion = options.cloudRegion ?? (await (0, clack_utils_2.askForCloudRegion)());
|
|
36
|
+
const typeScriptDetected = (0, clack_utils_1.isUsingTypeScript)(options);
|
|
37
|
+
await (0, clack_utils_1.confirmContinueIfNoOrDirtyGitRepo)(options);
|
|
38
|
+
const packageJson = await (0, clack_utils_1.getPackageDotJson)(options);
|
|
39
|
+
await (0, clack_utils_1.ensurePackageIsInstalled)(packageJson, 'next', 'Next.js');
|
|
40
|
+
const nextVersion = (0, package_json_1.getPackageVersion)('next', packageJson);
|
|
41
|
+
analytics_1.analytics.setTag('nextjs-version', (0, utils_1.getNextJsVersionBucket)(nextVersion));
|
|
42
|
+
analytics_1.analytics.capture(constants_1.WIZARD_INTERACTION_EVENT_NAME, {
|
|
43
|
+
action: 'started agent integration',
|
|
44
|
+
});
|
|
45
|
+
const { projectApiKey, host, accessToken } = await (0, clack_utils_1.getOrAskForProjectData)({
|
|
46
|
+
...options,
|
|
47
|
+
cloudRegion,
|
|
48
|
+
});
|
|
49
|
+
const router = await (0, utils_1.getNextJsRouter)(options);
|
|
50
|
+
const routerType = router === utils_1.NextJsRouter.APP_ROUTER ? 'app' : 'pages';
|
|
51
|
+
const spinner = clack_1.default.spinner();
|
|
52
|
+
const agent = (0, agent_interface_1.initializeAgent)({
|
|
53
|
+
workingDirectory: options.installDir,
|
|
54
|
+
posthogMcpUrl: 'https://mcp.posthog.com/mcp',
|
|
55
|
+
posthogApiKey: accessToken,
|
|
56
|
+
debug: false,
|
|
57
|
+
}, options, spinner);
|
|
58
|
+
const integrationPrompt = buildIntegrationPrompt({
|
|
59
|
+
framework: 'Next.js',
|
|
60
|
+
version: nextVersion || 'latest',
|
|
61
|
+
router: routerType,
|
|
62
|
+
typescript: typeScriptDetected,
|
|
63
|
+
projectApiKey,
|
|
64
|
+
host,
|
|
65
|
+
});
|
|
66
|
+
await (0, agent_interface_1.runAgent)(agent, integrationPrompt, options, spinner, {
|
|
67
|
+
estimatedDurationMinutes: 8,
|
|
68
|
+
spinnerMessage: 'Writing your PostHog setup with events, error capture and more...',
|
|
69
|
+
successMessage: 'PostHog integration complete',
|
|
70
|
+
errorMessage: 'Integration failed',
|
|
71
|
+
});
|
|
72
|
+
const { relativeEnvFilePath, addedEnvVariables } = await (0, steps_1.addOrUpdateEnvironmentVariablesStep)({
|
|
73
|
+
variables: {
|
|
74
|
+
NEXT_PUBLIC_POSTHOG_KEY: projectApiKey,
|
|
75
|
+
NEXT_PUBLIC_POSTHOG_HOST: host,
|
|
76
|
+
},
|
|
77
|
+
installDir: options.installDir,
|
|
78
|
+
integration: constants_1.Integration.nextjs,
|
|
79
|
+
});
|
|
80
|
+
const uploadedEnvVars = await (0, steps_1.uploadEnvironmentVariablesStep)({
|
|
81
|
+
NEXT_PUBLIC_POSTHOG_KEY: projectApiKey,
|
|
82
|
+
NEXT_PUBLIC_POSTHOG_HOST: host,
|
|
83
|
+
}, {
|
|
84
|
+
integration: constants_1.Integration.nextjs,
|
|
85
|
+
options,
|
|
86
|
+
});
|
|
87
|
+
await (0, steps_1.addMCPServerToClientsStep)({
|
|
88
|
+
cloudRegion,
|
|
89
|
+
integration: constants_1.Integration.nextjs,
|
|
90
|
+
});
|
|
91
|
+
const continueUrl = options.signup
|
|
92
|
+
? `${(0, urls_1.getCloudUrlFromRegion)(cloudRegion)}/products?source=wizard`
|
|
93
|
+
: undefined;
|
|
94
|
+
const changes = [
|
|
95
|
+
addedEnvVariables
|
|
96
|
+
? `Added your Project API key to your ${relativeEnvFilePath} file`
|
|
97
|
+
: '',
|
|
98
|
+
uploadedEnvVars.length > 0
|
|
99
|
+
? `Uploaded your Project API key to your hosting provider`
|
|
100
|
+
: '',
|
|
101
|
+
].filter(Boolean);
|
|
102
|
+
const nextSteps = [
|
|
103
|
+
uploadedEnvVars.length === 0
|
|
104
|
+
? `Upload your Project API key to your hosting provider`
|
|
105
|
+
: '',
|
|
106
|
+
].filter(Boolean);
|
|
107
|
+
const outroMessage = `
|
|
108
|
+
${chalk_1.default.green('Successfully installed PostHog!')}
|
|
109
|
+
|
|
110
|
+
${chalk_1.default.cyan('What the agent did:')}
|
|
111
|
+
• Analyzed your Next.js project structure (${routerType} router)
|
|
112
|
+
• Created and configured PostHog initializers
|
|
113
|
+
• Integrated PostHog into your application
|
|
114
|
+
${changes.map((change) => `• ${change}`).join('\n')}
|
|
115
|
+
|
|
116
|
+
${chalk_1.default.yellow('Next steps:')}
|
|
117
|
+
• Start your development server to see PostHog in action
|
|
118
|
+
• Visit your PostHog dashboard to see incoming events
|
|
119
|
+
${nextSteps.map((step) => `• ${step}`).join('\n')}
|
|
120
|
+
|
|
121
|
+
Learn more about PostHog + Next.js: ${chalk_1.default.cyan('https://posthog.com/docs/libraries/next-js')}
|
|
122
|
+
${continueUrl ? `\nContinue onboarding: ${chalk_1.default.cyan(continueUrl)}\n` : ``}
|
|
123
|
+
${chalk_1.default.dim('Note: This wizard uses an LLM agent to analyze and modify your project. Please review the changes made.')}
|
|
124
|
+
|
|
125
|
+
${chalk_1.default.dim(`How did this work for you? Drop me a line: danilo@posthog.com`)}`;
|
|
126
|
+
clack_1.default.outro(outroMessage);
|
|
127
|
+
await analytics_1.analytics.shutdown('success');
|
|
128
|
+
}
|
|
129
|
+
function buildIntegrationPrompt(context) {
|
|
130
|
+
return `You have access to the PostHog MCP server which provides an integration resource to integrate PostHog into this ${context.framework} project.
|
|
131
|
+
|
|
132
|
+
Project context:
|
|
133
|
+
- Framework: ${context.framework} ${context.version}
|
|
134
|
+
- Router: ${context.router}
|
|
135
|
+
- TypeScript: ${context.typescript ? 'Yes' : 'No'}
|
|
136
|
+
- PostHog API Key: ${context.projectApiKey}
|
|
137
|
+
- PostHog Host: ${context.host}
|
|
138
|
+
|
|
139
|
+
Instructions:
|
|
140
|
+
1. Call the PostHog MCP's resource for setup: posthog://integration/workflow/setup/begin
|
|
141
|
+
2. Follow all instructions provided
|
|
142
|
+
|
|
143
|
+
The PostHog MCP will provide specific integration code and instructions. Please follow them carefully. Be sure to look for lockfiles to determine the appropriate package manager to use when installing PostHog. Do not manually edit the package.json file.
|
|
144
|
+
`;
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=nextjs-wizard-agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nextjs-wizard-agent.js","sourceRoot":"","sources":["../../../src/nextjs/nextjs-wizard-agent.ts"],"names":[],"mappings":"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","sourcesContent":["/* Simplified Next.js wizard using posthog-agent with PostHog MCP */\nimport {\n abort,\n askForAIConsent,\n confirmContinueIfNoOrDirtyGitRepo,\n ensurePackageIsInstalled,\n getOrAskForProjectData,\n getPackageDotJson,\n isUsingTypeScript,\n printWelcome,\n} from '../utils/clack-utils';\nimport { getPackageVersion } from '../utils/package-json';\nimport { getNextJsRouter, getNextJsVersionBucket, NextJsRouter } from './utils';\nimport clack from '../utils/clack';\nimport { Integration, WIZARD_INTERACTION_EVENT_NAME } from '../lib/constants';\nimport { analytics } from '../utils/analytics';\nimport type { WizardOptions } from '../utils/types';\nimport { askForCloudRegion } from '../utils/clack-utils';\nimport { getCloudUrlFromRegion } from '../utils/urls';\nimport chalk from 'chalk';\nimport {\n addOrUpdateEnvironmentVariablesStep,\n addMCPServerToClientsStep,\n uploadEnvironmentVariablesStep,\n} from '../steps';\nimport { enableDebugLogs } from '../utils/debug';\nimport { initializeAgent, runAgent } from '../lib/agent-interface';\n\n/**\n * Simplified Next.js wizard that delegates to PostHog MCP's /integrate command\n */\nexport async function runNextjsWizardAgent(\n options: WizardOptions,\n): Promise<void> {\n if (options.debug) {\n enableDebugLogs();\n }\n\n printWelcome({\n wizardName: 'PostHog Next.js wizard (agent-powered)',\n });\n\n clack.log.info(\n '🧙 The wizard has chosen you to try the next-generation agent integration for Next.js.\\n\\nStand by for the good stuff, and let me know how it goes:\\n\\ndanilo@posthog.com',\n );\n\n const aiConsent = await askForAIConsent(options);\n\n if (!aiConsent) {\n await abort(\n 'This wizard uses an LLM agent to intelligently modify your project. Please view the docs to setup Next.js manually instead: https://posthog.com/docs/libraries/next-js',\n 0,\n );\n }\n\n const cloudRegion = options.cloudRegion ?? (await askForCloudRegion());\n const typeScriptDetected = isUsingTypeScript(options);\n\n await confirmContinueIfNoOrDirtyGitRepo(options);\n\n const packageJson = await getPackageDotJson(options);\n await ensurePackageIsInstalled(packageJson, 'next', 'Next.js');\n\n const nextVersion = getPackageVersion('next', packageJson);\n analytics.setTag('nextjs-version', getNextJsVersionBucket(nextVersion));\n\n analytics.capture(WIZARD_INTERACTION_EVENT_NAME, {\n action: 'started agent integration',\n });\n\n const { projectApiKey, host, accessToken } = await getOrAskForProjectData({\n ...options,\n cloudRegion,\n });\n\n const router = await getNextJsRouter(options);\n const routerType = router === NextJsRouter.APP_ROUTER ? 'app' : 'pages';\n\n const spinner = clack.spinner();\n\n const agent = initializeAgent(\n {\n workingDirectory: options.installDir,\n posthogMcpUrl: 'https://mcp.posthog.com/mcp',\n posthogApiKey: accessToken,\n debug: false,\n },\n options,\n spinner,\n );\n\n const integrationPrompt = buildIntegrationPrompt({\n framework: 'Next.js',\n version: nextVersion || 'latest',\n router: routerType,\n typescript: typeScriptDetected,\n projectApiKey,\n host,\n });\n\n await runAgent(agent, integrationPrompt, options, spinner, {\n estimatedDurationMinutes: 8,\n spinnerMessage:\n 'Writing your PostHog setup with events, error capture and more...',\n successMessage: 'PostHog integration complete',\n errorMessage: 'Integration failed',\n });\n\n const { relativeEnvFilePath, addedEnvVariables } =\n await addOrUpdateEnvironmentVariablesStep({\n variables: {\n NEXT_PUBLIC_POSTHOG_KEY: projectApiKey,\n NEXT_PUBLIC_POSTHOG_HOST: host,\n },\n installDir: options.installDir,\n integration: Integration.nextjs,\n });\n\n const uploadedEnvVars = await uploadEnvironmentVariablesStep(\n {\n NEXT_PUBLIC_POSTHOG_KEY: projectApiKey,\n NEXT_PUBLIC_POSTHOG_HOST: host,\n },\n {\n integration: Integration.nextjs,\n options,\n },\n );\n\n await addMCPServerToClientsStep({\n cloudRegion,\n integration: Integration.nextjs,\n });\n\n const continueUrl = options.signup\n ? `${getCloudUrlFromRegion(cloudRegion)}/products?source=wizard`\n : undefined;\n\n const changes = [\n addedEnvVariables\n ? `Added your Project API key to your ${relativeEnvFilePath} file`\n : '',\n uploadedEnvVars.length > 0\n ? `Uploaded your Project API key to your hosting provider`\n : '',\n ].filter(Boolean);\n\n const nextSteps = [\n uploadedEnvVars.length === 0\n ? `Upload your Project API key to your hosting provider`\n : '',\n ].filter(Boolean);\n\n const outroMessage = `\n${chalk.green('Successfully installed PostHog!')}\n\n${chalk.cyan('What the agent did:')}\n• Analyzed your Next.js project structure (${routerType} router)\n• Created and configured PostHog initializers\n• Integrated PostHog into your application\n${changes.map((change) => `• ${change}`).join('\\n')}\n\n${chalk.yellow('Next steps:')}\n• Start your development server to see PostHog in action\n• Visit your PostHog dashboard to see incoming events\n${nextSteps.map((step) => `• ${step}`).join('\\n')}\n\nLearn more about PostHog + Next.js: ${chalk.cyan(\n 'https://posthog.com/docs/libraries/next-js',\n )}\n${continueUrl ? `\\nContinue onboarding: ${chalk.cyan(continueUrl)}\\n` : ``}\n${chalk.dim(\n 'Note: This wizard uses an LLM agent to analyze and modify your project. Please review the changes made.',\n)}\n\n${chalk.dim(`How did this work for you? Drop me a line: danilo@posthog.com`)}`;\n\n clack.outro(outroMessage);\n\n await analytics.shutdown('success');\n}\n\nfunction buildIntegrationPrompt(context: {\n framework: string;\n version: string;\n router: string;\n typescript: boolean;\n projectApiKey: string;\n host: string;\n}): string {\n return `You have access to the PostHog MCP server which provides an integration resource to integrate PostHog into this ${\n context.framework\n } project.\n\nProject context:\n- Framework: ${context.framework} ${context.version}\n- Router: ${context.router}\n- TypeScript: ${context.typescript ? 'Yes' : 'No'}\n- PostHog API Key: ${context.projectApiKey}\n- PostHog Host: ${context.host}\n\nInstructions:\n1. Call the PostHog MCP's resource for setup: posthog://integration/workflow/setup/begin\n2. Follow all instructions provided\n\nThe PostHog MCP will provide specific integration code and instructions. Please follow them carefully. Be sure to look for lockfiles to determine the appropriate package manager to use when installing PostHog. Do not manually edit the package.json file.\n`;\n}\n"]}
|
package/dist/src/run.js
CHANGED
|
@@ -1,4 +1,37 @@
|
|
|
1
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
|
+
})();
|
|
2
35
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
37
|
};
|
|
@@ -6,6 +39,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
39
|
exports.runWizard = runWizard;
|
|
7
40
|
const clack_utils_1 = require("./utils/clack-utils");
|
|
8
41
|
const nextjs_wizard_1 = require("./nextjs/nextjs-wizard");
|
|
42
|
+
const nextjs_wizard_agent_1 = require("./nextjs/nextjs-wizard-agent");
|
|
9
43
|
const constants_1 = require("./lib/constants");
|
|
10
44
|
const environment_1 = require("./utils/environment");
|
|
11
45
|
const clack_1 = __importDefault(require("./utils/clack"));
|
|
@@ -19,6 +53,8 @@ const astro_wizard_1 = require("./astro/astro-wizard");
|
|
|
19
53
|
const events_1 = require("events");
|
|
20
54
|
const chalk_1 = __importDefault(require("chalk"));
|
|
21
55
|
const errors_1 = require("./utils/errors");
|
|
56
|
+
const package_json_1 = require("./utils/package-json");
|
|
57
|
+
const semver = __importStar(require("semver"));
|
|
22
58
|
events_1.EventEmitter.defaultMaxListeners = 50;
|
|
23
59
|
async function runWizard(argv) {
|
|
24
60
|
const finalArgs = {
|
|
@@ -51,7 +87,7 @@ async function runWizard(argv) {
|
|
|
51
87
|
try {
|
|
52
88
|
switch (integration) {
|
|
53
89
|
case constants_1.Integration.nextjs:
|
|
54
|
-
await (
|
|
90
|
+
await chooseNextjsWizard(wizardOptions);
|
|
55
91
|
break;
|
|
56
92
|
case constants_1.Integration.react:
|
|
57
93
|
await (0, react_wizard_1.runReactWizard)(wizardOptions);
|
|
@@ -112,4 +148,29 @@ async function getIntegrationForSetup(options) {
|
|
|
112
148
|
}));
|
|
113
149
|
return integration;
|
|
114
150
|
}
|
|
151
|
+
async function chooseNextjsWizard(options) {
|
|
152
|
+
try {
|
|
153
|
+
const packageJson = await (0, clack_utils_1.getPackageDotJson)(options);
|
|
154
|
+
const nextVersion = (0, package_json_1.getPackageVersion)('next', packageJson);
|
|
155
|
+
// If Next.js < 15, use legacy wizard
|
|
156
|
+
if (nextVersion) {
|
|
157
|
+
const coercedVersion = semver.coerce(nextVersion);
|
|
158
|
+
if (coercedVersion && semver.lt(coercedVersion, '15.3.0')) {
|
|
159
|
+
await (0, nextjs_wizard_1.runNextjsWizard)(options);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
// Next.js >= 15 - check feature flag to determine which wizard to use
|
|
164
|
+
const flagValue = await analytics_1.analytics.getFeatureFlag(constants_1.FeatureFlagDefinition.NextV2);
|
|
165
|
+
if (flagValue === constants_1.WizardVariant.Agent) {
|
|
166
|
+
await (0, nextjs_wizard_agent_1.runNextjsWizardAgent)(options);
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
await (0, nextjs_wizard_1.runNextjsWizard)(options);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
await (0, nextjs_wizard_1.runNextjsWizard)(options);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
115
176
|
//# sourceMappingURL=run.js.map
|
package/dist/src/run.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/run.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/run.ts"],"names":[],"mappings":"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","sourcesContent":["import { abortIfCancelled, getPackageDotJson } from './utils/clack-utils';\n\nimport { runNextjsWizard } from './nextjs/nextjs-wizard';\nimport { runNextjsWizardAgent } from './nextjs/nextjs-wizard-agent';\nimport type { CloudRegion, WizardOptions } from './utils/types';\n\nimport {\n getIntegrationDescription,\n Integration,\n FeatureFlagDefinition,\n WizardVariant,\n} from './lib/constants';\nimport { readEnvironment } from './utils/environment';\nimport clack from './utils/clack';\nimport path from 'path';\nimport { INTEGRATION_CONFIG, INTEGRATION_ORDER } from './lib/config';\nimport { runReactWizard } from './react/react-wizard';\nimport { analytics } from './utils/analytics';\nimport { runSvelteWizard } from './svelte/svelte-wizard';\nimport { runReactNativeWizard } from './react-native/react-native-wizard';\nimport { runAstroWizard } from './astro/astro-wizard';\nimport { EventEmitter } from 'events';\nimport chalk from 'chalk';\nimport { RateLimitError } from './utils/errors';\nimport { getPackageVersion } from './utils/package-json';\nimport * as semver from 'semver';\n\nEventEmitter.defaultMaxListeners = 50;\n\ntype Args = {\n integration?: Integration;\n debug?: boolean;\n forceInstall?: boolean;\n installDir?: string;\n region?: CloudRegion;\n default?: boolean;\n signup?: boolean;\n};\n\nexport async function runWizard(argv: Args) {\n const finalArgs = {\n ...argv,\n ...readEnvironment(),\n };\n\n let resolvedInstallDir: string;\n if (finalArgs.installDir) {\n if (path.isAbsolute(finalArgs.installDir)) {\n resolvedInstallDir = finalArgs.installDir;\n } else {\n resolvedInstallDir = path.join(process.cwd(), finalArgs.installDir);\n }\n } else {\n resolvedInstallDir = process.cwd();\n }\n\n const wizardOptions: WizardOptions = {\n debug: finalArgs.debug ?? false,\n forceInstall: finalArgs.forceInstall ?? false,\n installDir: resolvedInstallDir,\n cloudRegion: finalArgs.region ?? undefined,\n default: finalArgs.default ?? false,\n signup: finalArgs.signup ?? false,\n };\n\n clack.intro(`Welcome to the PostHog setup wizard ✨`);\n\n const integration =\n finalArgs.integration ?? (await getIntegrationForSetup(wizardOptions));\n\n analytics.setTag('integration', integration);\n\n try {\n switch (integration) {\n case Integration.nextjs:\n await chooseNextjsWizard(wizardOptions);\n break;\n case Integration.react:\n await runReactWizard(wizardOptions);\n break;\n case Integration.svelte:\n await runSvelteWizard(wizardOptions);\n break;\n case Integration.reactNative:\n await runReactNativeWizard(wizardOptions);\n break;\n case Integration.astro:\n await runAstroWizard(wizardOptions);\n break;\n default:\n clack.log.error('No setup wizard selected!');\n }\n } catch (error) {\n analytics.captureException(error as Error, {\n integration,\n arguments: JSON.stringify(finalArgs),\n });\n\n await analytics.shutdown('error');\n\n if (error instanceof RateLimitError) {\n clack.log.error('Wizard usage limit reached. Please try again later.');\n } else {\n clack.log.error(\n `Something went wrong. You can read the documentation at ${chalk.cyan(\n `${INTEGRATION_CONFIG[integration].docsUrl}`,\n )} to set up PostHog manually.`,\n );\n }\n process.exit(1);\n }\n}\n\nasync function detectIntegration(\n options: Pick<WizardOptions, 'installDir'>,\n): Promise<Integration | undefined> {\n const integrationConfigs = Object.entries(INTEGRATION_CONFIG).sort(\n ([a], [b]) =>\n INTEGRATION_ORDER.indexOf(a as Integration) -\n INTEGRATION_ORDER.indexOf(b as Integration),\n );\n\n for (const [integration, config] of integrationConfigs) {\n const detected = await config.detect(options);\n if (detected) {\n return integration as Integration;\n }\n }\n}\n\nasync function getIntegrationForSetup(\n options: Pick<WizardOptions, 'installDir'>,\n) {\n const detectedIntegration = await detectIntegration(options);\n\n if (detectedIntegration) {\n clack.log.success(\n `Detected integration: ${getIntegrationDescription(detectedIntegration)}`,\n );\n return detectedIntegration;\n }\n\n const integration: Integration = await abortIfCancelled(\n clack.select({\n message: 'What do you want to set up?',\n options: [\n { value: Integration.nextjs, label: 'Next.js' },\n { value: Integration.astro, label: 'Astro' },\n { value: Integration.react, label: 'React' },\n { value: Integration.svelte, label: 'Svelte' },\n { value: Integration.reactNative, label: 'React Native' },\n ],\n }),\n );\n\n return integration;\n}\n\nasync function chooseNextjsWizard(options: WizardOptions): Promise<void> {\n try {\n const packageJson = await getPackageDotJson(options);\n const nextVersion = getPackageVersion('next', packageJson);\n\n // If Next.js < 15, use legacy wizard\n if (nextVersion) {\n const coercedVersion = semver.coerce(nextVersion);\n if (coercedVersion && semver.lt(coercedVersion, '15.3.0')) {\n await runNextjsWizard(options);\n return;\n }\n }\n\n // Next.js >= 15 - check feature flag to determine which wizard to use\n const flagValue = await analytics.getFeatureFlag(\n FeatureFlagDefinition.NextV2,\n );\n\n if (flagValue === WizardVariant.Agent) {\n await runNextjsWizardAgent(options);\n } else {\n await runNextjsWizard(options);\n }\n } catch (error) {\n await runNextjsWizard(options);\n }\n}\n"]}
|
|
@@ -29,6 +29,7 @@ describe('Analytics', () => {
|
|
|
29
29
|
analytics.captureException(error, properties);
|
|
30
30
|
expect(mockPostHogInstance.captureException).toHaveBeenCalledWith(error, 'test-uuid', {
|
|
31
31
|
team: 'growth',
|
|
32
|
+
$app_name: 'wizard',
|
|
32
33
|
...properties,
|
|
33
34
|
});
|
|
34
35
|
});
|
|
@@ -39,6 +40,7 @@ describe('Analytics', () => {
|
|
|
39
40
|
analytics.captureException(error, properties);
|
|
40
41
|
expect(mockPostHogInstance.captureException).toHaveBeenCalledWith(error, 'test-uuid', {
|
|
41
42
|
team: 'growth',
|
|
43
|
+
$app_name: 'wizard',
|
|
42
44
|
testTag: 'testValue',
|
|
43
45
|
...properties,
|
|
44
46
|
});
|
|
@@ -50,6 +52,7 @@ describe('Analytics', () => {
|
|
|
50
52
|
analytics.captureException(error);
|
|
51
53
|
expect(mockPostHogInstance.captureException).toHaveBeenCalledWith(error, distinctId, {
|
|
52
54
|
team: 'growth',
|
|
55
|
+
$app_name: 'wizard',
|
|
53
56
|
});
|
|
54
57
|
});
|
|
55
58
|
it('should capture exception without properties when not provided', () => {
|
|
@@ -57,6 +60,7 @@ describe('Analytics', () => {
|
|
|
57
60
|
analytics.captureException(error);
|
|
58
61
|
expect(mockPostHogInstance.captureException).toHaveBeenCalledWith(error, 'test-uuid', {
|
|
59
62
|
team: 'growth',
|
|
63
|
+
$app_name: 'wizard',
|
|
60
64
|
});
|
|
61
65
|
});
|
|
62
66
|
it('should merge tags with provided properties', () => {
|
|
@@ -67,6 +71,7 @@ describe('Analytics', () => {
|
|
|
67
71
|
analytics.captureException(error, properties);
|
|
68
72
|
expect(mockPostHogInstance.captureException).toHaveBeenCalledWith(error, 'test-uuid', {
|
|
69
73
|
team: 'growth',
|
|
74
|
+
$app_name: 'wizard',
|
|
70
75
|
environment: 'test',
|
|
71
76
|
version: '1.0.0',
|
|
72
77
|
integration: 'nextjs',
|
|
@@ -80,6 +85,7 @@ describe('Analytics', () => {
|
|
|
80
85
|
analytics.captureException(error, properties);
|
|
81
86
|
expect(mockPostHogInstance.captureException).toHaveBeenCalledWith(error, 'test-uuid', {
|
|
82
87
|
team: 'growth',
|
|
88
|
+
$app_name: 'wizard',
|
|
83
89
|
integration: 'react',
|
|
84
90
|
});
|
|
85
91
|
});
|
|
@@ -88,6 +94,7 @@ describe('Analytics', () => {
|
|
|
88
94
|
analytics.captureException(error);
|
|
89
95
|
expect(mockPostHogInstance.captureException).toHaveBeenCalledWith(error, 'test-uuid', {
|
|
90
96
|
team: 'growth',
|
|
97
|
+
$app_name: 'wizard',
|
|
91
98
|
});
|
|
92
99
|
});
|
|
93
100
|
});
|
|
@@ -103,6 +110,7 @@ describe('Analytics', () => {
|
|
|
103
110
|
});
|
|
104
111
|
expect(mockPostHogInstance.captureException).toHaveBeenCalledWith(error, 'test-uuid', {
|
|
105
112
|
team: 'growth',
|
|
113
|
+
$app_name: 'wizard',
|
|
106
114
|
integration: 'nextjs',
|
|
107
115
|
forceInstall: true,
|
|
108
116
|
debug: false,
|
|
@@ -118,6 +126,7 @@ describe('Analytics', () => {
|
|
|
118
126
|
analytics.captureException(error);
|
|
119
127
|
expect(mockPostHogInstance.captureException).toHaveBeenCalledWith(error, distinctId, {
|
|
120
128
|
team: 'growth',
|
|
129
|
+
$app_name: 'wizard',
|
|
121
130
|
integration: 'svelte',
|
|
122
131
|
});
|
|
123
132
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analytics.test.js","sourceRoot":"","sources":["../../../../src/utils/__tests__/analytics.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { Analytics } from '../analytics';\nimport { PostHog } from 'posthog-node';\nimport { v4 as uuidv4 } from 'uuid';\n\njest.mock('posthog-node');\njest.mock('uuid');\n\nconst mockUuidv4 = uuidv4 as jest.MockedFunction<typeof uuidv4>;\nconst MockedPostHog = PostHog as jest.MockedClass<typeof PostHog>;\n\ndescribe('Analytics', () => {\n let analytics: Analytics;\n let mockPostHogInstance: jest.Mocked<PostHog>;\n\n beforeEach(() => {\n jest.clearAllMocks();\n mockUuidv4.mockReturnValue('test-uuid' as any);\n\n mockPostHogInstance = {\n capture: jest.fn(),\n captureException: jest.fn(),\n alias: jest.fn(),\n shutdown: jest.fn().mockResolvedValue(undefined),\n } as any;\n\n MockedPostHog.mockImplementation(() => mockPostHogInstance);\n\n analytics = new Analytics();\n });\n\n describe('captureException', () => {\n it('should capture exception with error object and properties', () => {\n const error = new Error('Test error');\n const properties = { integration: 'nextjs' };\n\n analytics.captureException(error, properties);\n\n expect(mockPostHogInstance.captureException).toHaveBeenCalledWith(\n error,\n 'test-uuid',\n {\n team: 'growth',\n ...properties,\n },\n );\n });\n\n it('should capture exception with tags included in properties', () => {\n const error = new Error('Test error');\n const properties = { integration: 'nextjs' };\n\n analytics.setTag('testTag', 'testValue');\n analytics.captureException(error, properties);\n\n expect(mockPostHogInstance.captureException).toHaveBeenCalledWith(\n error,\n 'test-uuid',\n {\n team: 'growth',\n testTag: 'testValue',\n ...properties,\n },\n );\n });\n\n it('should capture exception with distinct ID when set', () => {\n const error = new Error('Test error');\n const distinctId = 'user-123';\n\n analytics.setDistinctId(distinctId);\n analytics.captureException(error);\n\n expect(mockPostHogInstance.captureException).toHaveBeenCalledWith(\n error,\n distinctId,\n {\n team: 'growth',\n },\n );\n });\n\n it('should capture exception without properties when not provided', () => {\n const error = new Error('Test error');\n\n analytics.captureException(error);\n\n expect(mockPostHogInstance.captureException).toHaveBeenCalledWith(\n error,\n 'test-uuid',\n {\n team: 'growth',\n },\n );\n });\n\n it('should merge tags with provided properties', () => {\n const error = new Error('Test error');\n const properties = { integration: 'nextjs', step: 'installation' };\n\n analytics.setTag('environment', 'test');\n analytics.setTag('version', '1.0.0');\n analytics.captureException(error, properties);\n\n expect(mockPostHogInstance.captureException).toHaveBeenCalledWith(\n error,\n 'test-uuid',\n {\n team: 'growth',\n environment: 'test',\n version: '1.0.0',\n integration: 'nextjs',\n step: 'installation',\n },\n );\n });\n\n it('should override tags with properties when keys conflict', () => {\n const error = new Error('Test error');\n const properties = { integration: 'react' };\n\n analytics.setTag('integration', 'nextjs');\n analytics.captureException(error, properties);\n\n expect(mockPostHogInstance.captureException).toHaveBeenCalledWith(\n error,\n 'test-uuid',\n {\n team: 'growth',\n integration: 'react',\n },\n );\n });\n\n it('should always include team:growth property in exceptions', () => {\n const error = new Error('Test error');\n\n analytics.captureException(error);\n\n expect(mockPostHogInstance.captureException).toHaveBeenCalledWith(\n error,\n 'test-uuid',\n {\n team: 'growth',\n },\n );\n });\n });\n\n describe('integration with other methods', () => {\n it('should work correctly with setTag and captureException', () => {\n const error = new Error('Test error');\n\n analytics.setTag('integration', 'nextjs');\n analytics.setTag('forceInstall', true);\n analytics.setTag('debug', false);\n\n analytics.captureException(error, {\n arguments: JSON.stringify({ installDir: '/test' }),\n step: 'wizard-execution',\n });\n\n expect(mockPostHogInstance.captureException).toHaveBeenCalledWith(\n error,\n 'test-uuid',\n {\n team: 'growth',\n integration: 'nextjs',\n forceInstall: true,\n debug: false,\n arguments: JSON.stringify({ installDir: '/test' }),\n step: 'wizard-execution',\n },\n );\n });\n\n it('should work correctly with setDistinctId and captureException', () => {\n const error = new Error('Test error');\n const distinctId = 'user-456';\n\n analytics.setDistinctId(distinctId);\n analytics.setTag('integration', 'svelte');\n analytics.captureException(error);\n\n expect(mockPostHogInstance.captureException).toHaveBeenCalledWith(\n error,\n distinctId,\n {\n team: 'growth',\n integration: 'svelte',\n },\n );\n });\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"analytics.test.js","sourceRoot":"","sources":["../../../../src/utils/__tests__/analytics.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { Analytics } from '../analytics';\nimport { PostHog } from 'posthog-node';\nimport { v4 as uuidv4 } from 'uuid';\n\njest.mock('posthog-node');\njest.mock('uuid');\n\nconst mockUuidv4 = uuidv4 as jest.MockedFunction<typeof uuidv4>;\nconst MockedPostHog = PostHog as jest.MockedClass<typeof PostHog>;\n\ndescribe('Analytics', () => {\n let analytics: Analytics;\n let mockPostHogInstance: jest.Mocked<PostHog>;\n\n beforeEach(() => {\n jest.clearAllMocks();\n mockUuidv4.mockReturnValue('test-uuid' as any);\n\n mockPostHogInstance = {\n capture: jest.fn(),\n captureException: jest.fn(),\n alias: jest.fn(),\n shutdown: jest.fn().mockResolvedValue(undefined),\n } as any;\n\n MockedPostHog.mockImplementation(() => mockPostHogInstance);\n\n analytics = new Analytics();\n });\n\n describe('captureException', () => {\n it('should capture exception with error object and properties', () => {\n const error = new Error('Test error');\n const properties = { integration: 'nextjs' };\n\n analytics.captureException(error, properties);\n\n expect(mockPostHogInstance.captureException).toHaveBeenCalledWith(\n error,\n 'test-uuid',\n {\n team: 'growth',\n $app_name: 'wizard',\n ...properties,\n },\n );\n });\n\n it('should capture exception with tags included in properties', () => {\n const error = new Error('Test error');\n const properties = { integration: 'nextjs' };\n\n analytics.setTag('testTag', 'testValue');\n analytics.captureException(error, properties);\n\n expect(mockPostHogInstance.captureException).toHaveBeenCalledWith(\n error,\n 'test-uuid',\n {\n team: 'growth',\n $app_name: 'wizard',\n testTag: 'testValue',\n ...properties,\n },\n );\n });\n\n it('should capture exception with distinct ID when set', () => {\n const error = new Error('Test error');\n const distinctId = 'user-123';\n\n analytics.setDistinctId(distinctId);\n analytics.captureException(error);\n\n expect(mockPostHogInstance.captureException).toHaveBeenCalledWith(\n error,\n distinctId,\n {\n team: 'growth',\n $app_name: 'wizard',\n },\n );\n });\n\n it('should capture exception without properties when not provided', () => {\n const error = new Error('Test error');\n\n analytics.captureException(error);\n\n expect(mockPostHogInstance.captureException).toHaveBeenCalledWith(\n error,\n 'test-uuid',\n {\n team: 'growth',\n $app_name: 'wizard',\n },\n );\n });\n\n it('should merge tags with provided properties', () => {\n const error = new Error('Test error');\n const properties = { integration: 'nextjs', step: 'installation' };\n\n analytics.setTag('environment', 'test');\n analytics.setTag('version', '1.0.0');\n analytics.captureException(error, properties);\n\n expect(mockPostHogInstance.captureException).toHaveBeenCalledWith(\n error,\n 'test-uuid',\n {\n team: 'growth',\n $app_name: 'wizard',\n environment: 'test',\n version: '1.0.0',\n integration: 'nextjs',\n step: 'installation',\n },\n );\n });\n\n it('should override tags with properties when keys conflict', () => {\n const error = new Error('Test error');\n const properties = { integration: 'react' };\n\n analytics.setTag('integration', 'nextjs');\n analytics.captureException(error, properties);\n\n expect(mockPostHogInstance.captureException).toHaveBeenCalledWith(\n error,\n 'test-uuid',\n {\n team: 'growth',\n $app_name: 'wizard',\n integration: 'react',\n },\n );\n });\n\n it('should always include team:growth property in exceptions', () => {\n const error = new Error('Test error');\n\n analytics.captureException(error);\n\n expect(mockPostHogInstance.captureException).toHaveBeenCalledWith(\n error,\n 'test-uuid',\n {\n team: 'growth',\n $app_name: 'wizard',\n },\n );\n });\n });\n\n describe('integration with other methods', () => {\n it('should work correctly with setTag and captureException', () => {\n const error = new Error('Test error');\n\n analytics.setTag('integration', 'nextjs');\n analytics.setTag('forceInstall', true);\n analytics.setTag('debug', false);\n\n analytics.captureException(error, {\n arguments: JSON.stringify({ installDir: '/test' }),\n step: 'wizard-execution',\n });\n\n expect(mockPostHogInstance.captureException).toHaveBeenCalledWith(\n error,\n 'test-uuid',\n {\n team: 'growth',\n $app_name: 'wizard',\n integration: 'nextjs',\n forceInstall: true,\n debug: false,\n arguments: JSON.stringify({ installDir: '/test' }),\n step: 'wizard-execution',\n },\n );\n });\n\n it('should work correctly with setDistinctId and captureException', () => {\n const error = new Error('Test error');\n const distinctId = 'user-456';\n\n analytics.setDistinctId(distinctId);\n analytics.setTag('integration', 'svelte');\n analytics.captureException(error);\n\n expect(mockPostHogInstance.captureException).toHaveBeenCalledWith(\n error,\n distinctId,\n {\n team: 'growth',\n $app_name: 'wizard',\n integration: 'svelte',\n },\n );\n });\n });\n});\n"]}
|
|
@@ -3,11 +3,13 @@ export declare class Analytics {
|
|
|
3
3
|
private tags;
|
|
4
4
|
private distinctId?;
|
|
5
5
|
private anonymousId;
|
|
6
|
+
private appName;
|
|
6
7
|
constructor();
|
|
7
8
|
setDistinctId(distinctId: string): void;
|
|
8
9
|
setTag(key: string, value: string | boolean | number | null | undefined): void;
|
|
9
10
|
captureException(error: Error, properties?: Record<string, unknown>): void;
|
|
10
11
|
capture(eventName: string, properties?: Record<string, unknown>): void;
|
|
12
|
+
getFeatureFlag(flagKey: string): Promise<string | boolean | undefined>;
|
|
11
13
|
shutdown(status: 'success' | 'error' | 'cancelled'): Promise<void>;
|
|
12
14
|
}
|
|
13
15
|
export declare const analytics: Analytics;
|
|
@@ -4,11 +4,13 @@ exports.analytics = exports.Analytics = void 0;
|
|
|
4
4
|
const posthog_node_1 = require("posthog-node");
|
|
5
5
|
const constants_1 = require("../lib/constants");
|
|
6
6
|
const uuid_1 = require("uuid");
|
|
7
|
+
const debug_1 = require("./debug");
|
|
7
8
|
class Analytics {
|
|
8
9
|
client;
|
|
9
10
|
tags = {};
|
|
10
11
|
distinctId;
|
|
11
12
|
anonymousId;
|
|
13
|
+
appName = 'wizard';
|
|
12
14
|
constructor() {
|
|
13
15
|
this.client = new posthog_node_1.PostHog(constants_1.ANALYTICS_POSTHOG_PUBLIC_PROJECT_WRITE_KEY, {
|
|
14
16
|
host: constants_1.ANALYTICS_HOST_URL,
|
|
@@ -16,7 +18,7 @@ class Analytics {
|
|
|
16
18
|
flushInterval: 0,
|
|
17
19
|
enableExceptionAutocapture: true,
|
|
18
20
|
});
|
|
19
|
-
this.tags = {};
|
|
21
|
+
this.tags = { $app_name: this.appName };
|
|
20
22
|
this.anonymousId = (0, uuid_1.v4)();
|
|
21
23
|
this.distinctId = undefined;
|
|
22
24
|
}
|
|
@@ -47,6 +49,21 @@ class Analytics {
|
|
|
47
49
|
},
|
|
48
50
|
});
|
|
49
51
|
}
|
|
52
|
+
async getFeatureFlag(flagKey) {
|
|
53
|
+
try {
|
|
54
|
+
const distinctId = this.distinctId ?? this.anonymousId;
|
|
55
|
+
return await this.client.getFeatureFlag(flagKey, distinctId, {
|
|
56
|
+
sendFeatureFlagEvents: true,
|
|
57
|
+
personProperties: {
|
|
58
|
+
$app_name: this.appName,
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
(0, debug_1.debug)('Failed to get feature flag:', flagKey, error);
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
50
67
|
async shutdown(status) {
|
|
51
68
|
if (Object.keys(this.tags).length === 0) {
|
|
52
69
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analytics.js","sourceRoot":"","sources":["../../../src/utils/analytics.ts"],"names":[],"mappings":";;;AAAA,+CAAuC;AACvC,gDAG0B;AAC1B,+BAAoC;AACpC,MAAa,SAAS;IACZ,MAAM,CAAU;IAChB,IAAI,GACV,EAAE,CAAC;IACG,UAAU,CAAU;IACpB,WAAW,CAAS;
|
|
1
|
+
{"version":3,"file":"analytics.js","sourceRoot":"","sources":["../../../src/utils/analytics.ts"],"names":[],"mappings":"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","sourcesContent":["import { PostHog } from 'posthog-node';\nimport {\n ANALYTICS_HOST_URL,\n ANALYTICS_POSTHOG_PUBLIC_PROJECT_WRITE_KEY,\n} from '../lib/constants';\nimport { v4 as uuidv4 } from 'uuid';\nimport { debug } from './debug';\nexport class Analytics {\n private client: PostHog;\n private tags: Record<string, string | boolean | number | null | undefined> =\n {};\n private distinctId?: string;\n private anonymousId: string;\n private appName = 'wizard';\n\n constructor() {\n this.client = new PostHog(ANALYTICS_POSTHOG_PUBLIC_PROJECT_WRITE_KEY, {\n host: ANALYTICS_HOST_URL,\n flushAt: 1,\n flushInterval: 0,\n enableExceptionAutocapture: true,\n });\n\n this.tags = { $app_name: this.appName };\n\n this.anonymousId = uuidv4();\n\n this.distinctId = undefined;\n }\n\n setDistinctId(distinctId: string) {\n this.distinctId = distinctId;\n this.client.alias({\n distinctId,\n alias: this.anonymousId,\n });\n }\n\n setTag(key: string, value: string | boolean | number | null | undefined) {\n this.tags[key] = value;\n }\n\n captureException(error: Error, properties: Record<string, unknown> = {}) {\n this.client.captureException(error, this.distinctId ?? this.anonymousId, {\n team: 'growth',\n ...this.tags,\n ...properties,\n });\n }\n\n capture(eventName: string, properties?: Record<string, unknown>) {\n this.client.capture({\n distinctId: this.distinctId ?? this.anonymousId,\n event: eventName,\n properties: {\n ...this.tags,\n ...properties,\n },\n });\n }\n\n async getFeatureFlag(flagKey: string): Promise<string | boolean | undefined> {\n try {\n const distinctId = this.distinctId ?? this.anonymousId;\n return await this.client.getFeatureFlag(flagKey, distinctId, {\n sendFeatureFlagEvents: true,\n personProperties: {\n $app_name: this.appName,\n },\n });\n } catch (error) {\n debug('Failed to get feature flag:', flagKey, error);\n return undefined;\n }\n }\n\n async shutdown(status: 'success' | 'error' | 'cancelled') {\n if (Object.keys(this.tags).length === 0) {\n return;\n }\n\n this.client.capture({\n distinctId: this.distinctId ?? this.anonymousId,\n event: 'setup wizard finished',\n properties: {\n status,\n tags: this.tags,\n },\n });\n\n await this.client.shutdown();\n }\n}\n\nexport const analytics = new Analytics();\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@posthog/wizard",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.16.1",
|
|
4
4
|
"homepage": "https://github.com/posthog/wizard",
|
|
5
5
|
"repository": "https://github.com/posthog/wizard",
|
|
6
6
|
"description": "The PostHog wizard helps you to configure your project",
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"@clack/core": "^0.3.4",
|
|
36
36
|
"@clack/prompts": "0.7.0",
|
|
37
37
|
"@langchain/core": "^0.3.40",
|
|
38
|
+
"@posthog/agent": "1.11.0",
|
|
38
39
|
"axios": "1.7.4",
|
|
39
40
|
"chalk": "^2.4.1",
|
|
40
41
|
"fast-glob": "^3.3.3",
|
|
@@ -114,7 +115,10 @@
|
|
|
114
115
|
"\\.no-jest\\.(jsx?|tsx?)$",
|
|
115
116
|
"/e2e-tests/"
|
|
116
117
|
],
|
|
117
|
-
"testEnvironment": "node"
|
|
118
|
+
"testEnvironment": "node",
|
|
119
|
+
"moduleNameMapper": {
|
|
120
|
+
"^@posthog/agent$": "<rootDir>/__mocks__/@posthog/agent.ts"
|
|
121
|
+
}
|
|
118
122
|
},
|
|
119
123
|
"lint-staged": {
|
|
120
124
|
"*.{js,ts,tsx,jsx}": "pnpm fix"
|