@posthog/agent 1.16.1 → 1.16.3

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/src/agent.ts CHANGED
@@ -31,7 +31,7 @@ export class Agent {
31
31
  private canUseTool?: CanUseTool;
32
32
  public debug: boolean;
33
33
 
34
- constructor(config: AgentConfig = {}) {
34
+ constructor(config: AgentConfig) {
35
35
  this.workingDirectory = config.workingDirectory || process.cwd();
36
36
  this.onEvent = config.onEvent;
37
37
  this.canUseTool = config.canUseTool;
@@ -81,6 +81,7 @@ export class Agent {
81
81
  this.posthogAPI = new PostHogAPIClient({
82
82
  apiUrl: config.posthogApiUrl,
83
83
  apiKey: config.posthogApiKey,
84
+ projectId: config.posthogProjectId,
84
85
  });
85
86
  }
86
87
 
@@ -91,7 +92,7 @@ export class Agent {
91
92
  logger: this.logger.child('PromptBuilder')
92
93
  });
93
94
  this.progressReporter = new TaskProgressReporter(this.posthogAPI, this.logger);
94
- this.extractor = new AISDKExtractor(this.logger.child('AISDKExtractor'));
95
+ this.extractor = new AISDKExtractor({apiKey: config.posthogApiKey, baseURL: config.posthogApiUrl, logger: this.logger.child('AISDKExtractor')});
95
96
  }
96
97
 
97
98
  /**
@@ -434,7 +435,7 @@ Generated by PostHog Agent`;
434
435
  }
435
436
 
436
437
  if (!this.extractor) {
437
- this.extractor = new AISDKExtractor(this.logger.child('AISDKExtractor'));
438
+ this.extractor = new AISDKExtractor({apiKey: resolvedToken || '', baseURL: resolvedBaseUrl || '', logger: this.logger.child('AISDKExtractor')});
438
439
  }
439
440
  }
440
441
 
@@ -68,20 +68,7 @@ export class PostHogAPIClient {
68
68
  }
69
69
 
70
70
  async getTeamId(): Promise<number> {
71
- if (this._teamId !== null) {
72
- return this._teamId;
73
- }
74
-
75
- // Fetch user info to get team ID (following Array's pattern)
76
- const userResponse = await this.apiRequest<any>('/api/users/@me/');
77
-
78
- if (!userResponse.team?.id) {
79
- throw new Error('No team found for user');
80
- }
81
-
82
- const teamId = Number(userResponse.team.id);
83
- this._teamId = teamId;
84
- return teamId;
71
+ return this.config.projectId;
85
72
  }
86
73
 
87
74
  getBaseUrl(): string {
@@ -1,7 +1,7 @@
1
1
  import { generateObject } from 'ai';
2
- import { anthropic } from '@ai-sdk/anthropic';
3
2
  import { z } from 'zod';
4
3
  import { Logger } from './utils/logger.js';
4
+ import { getAnthropicModel } from './utils/ai-sdk.js';
5
5
 
6
6
  export interface ExtractedQuestion {
7
7
  id: string;
@@ -41,27 +41,34 @@ export interface StructuredExtractor {
41
41
  extractQuestionsWithAnswers(researchContent: string): Promise<ExtractedQuestionWithAnswer[]>;
42
42
  }
43
43
 
44
+ export type StructuredExtractorConfig = {
45
+ apiKey: string;
46
+ baseURL: string;
47
+ modelName?: string;
48
+ logger?: Logger;
49
+ }
50
+
44
51
  export class AISDKExtractor implements StructuredExtractor {
45
52
  private logger: Logger;
46
53
  private model: any;
47
54
 
48
- constructor(logger?: Logger) {
49
- this.logger = logger || new Logger({ debug: false, prefix: '[AISDKExtractor]' });
50
-
51
- // Determine which provider to use based on environment variables
52
- // Priority: Anthropic (if ANTHROPIC_BASE_URL is set) > OpenAI
53
- const apiKey = process.env.ANTHROPIC_AUTH_TOKEN
54
- || process.env.ANTHROPIC_API_KEY
55
- || process.env.OPENAI_API_KEY;
55
+ constructor(config: StructuredExtractorConfig) {
56
+ this.logger = config.logger || new Logger({ debug: false, prefix: '[AISDKExtractor]' });
56
57
 
57
- if (!apiKey) {
58
+ if (!config.apiKey) {
58
59
  throw new Error('Missing API key for structured extraction. Ensure the LLM gateway is configured.');
59
60
  }
60
61
 
61
- const baseURL = process.env.ANTHROPIC_BASE_URL || process.env.OPENAI_BASE_URL;
62
- const modelName = 'claude-haiku-4-5';
63
- this.model = anthropic(modelName);
64
- this.logger.debug('Using Anthropic provider for structured extraction', { modelName, baseURL });
62
+ this.model = getAnthropicModel({
63
+ apiKey: config.apiKey,
64
+ baseURL: config.baseURL,
65
+ modelName: config.modelName || 'claude-haiku-4-5',
66
+ });
67
+
68
+ this.logger.debug('Using PostHog LLM gateway for structured extraction', {
69
+ modelName: config.modelName || 'claude-haiku-4-5',
70
+ baseURL: config.baseURL
71
+ });
65
72
  }
66
73
 
67
74
  async extractQuestions(researchContent: string): Promise<ExtractedQuestion[]> {
package/src/types.ts CHANGED
@@ -301,12 +301,14 @@ export interface AgentConfig {
301
301
  onEvent?: (event: AgentEvent) => void;
302
302
 
303
303
  // PostHog API configuration
304
- posthogApiUrl?: string;
305
- posthogApiKey?: string;
304
+ posthogApiUrl: string;
305
+ posthogApiKey: string;
306
+ posthogProjectId: number;
306
307
 
307
308
  // PostHog MCP configuration
308
309
  posthogMcpUrl?: string;
309
310
 
311
+
310
312
  // MCP Server configuration
311
313
  // Additional MCP servers (PostHog MCP is always included by default)
312
314
  // You can override the PostHog MCP config by providing mcpServers.posthog
@@ -323,6 +325,7 @@ export interface AgentConfig {
323
325
  export interface PostHogAPIConfig {
324
326
  apiUrl: string;
325
327
  apiKey: string;
328
+ projectId: number;
326
329
  }
327
330
 
328
331
  // URL mention types
@@ -0,0 +1,47 @@
1
+ import { createAnthropic } from '@ai-sdk/anthropic';
2
+
3
+ export interface PostHogGatewayConfig {
4
+ apiKey: string;
5
+ baseURL: string;
6
+ modelName?: string;
7
+ }
8
+
9
+ /**
10
+ * Creates an Anthropic model configured for PostHog LLM gateway.
11
+ *
12
+ * Handles two key differences between AI SDK and PostHog gateway:
13
+ * 1. Appends /v1 to baseURL (gateway expects /v1/messages, SDK appends /messages)
14
+ * 2. Converts x-api-key header to Authorization Bearer token
15
+ */
16
+ export function getAnthropicModel(config: PostHogGatewayConfig) {
17
+ const modelName = config.modelName || 'claude-haiku-4-5';
18
+
19
+ // PostHog gateway expects /v1/messages, but AI SDK appends /messages
20
+ // So we need to append /v1 to the baseURL
21
+ const baseURL = config.baseURL ? `${config.baseURL}/v1` : undefined;
22
+
23
+ // Custom fetch to convert x-api-key header to Authorization Bearer
24
+ // PostHog gateway expects Bearer token, but Anthropic SDK sends x-api-key
25
+ const customFetch = async (url: RequestInfo, init?: RequestInit): Promise<Response> => {
26
+ const headers = new Headers(init?.headers);
27
+
28
+ if (headers.has('x-api-key')) {
29
+ headers.delete('x-api-key');
30
+ headers.set('Authorization', `Bearer ${config.apiKey}`);
31
+ }
32
+
33
+ return fetch(url, {
34
+ ...init,
35
+ headers,
36
+ });
37
+ };
38
+
39
+ const anthropic = createAnthropic({
40
+ apiKey: config.apiKey,
41
+ baseURL,
42
+ //@ts-ignore
43
+ fetch: customFetch,
44
+ });
45
+
46
+ return anthropic(modelName);
47
+ }