@posthog/agent 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/CLAUDE.md +296 -0
  2. package/README.md +142 -0
  3. package/dist/example.d.ts +3 -0
  4. package/dist/example.d.ts.map +1 -0
  5. package/dist/example.js +49 -0
  6. package/dist/example.js.map +1 -0
  7. package/dist/index.d.ts +7 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +5 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/src/agent-registry.d.ts +16 -0
  12. package/dist/src/agent-registry.d.ts.map +1 -0
  13. package/dist/src/agent-registry.js +54 -0
  14. package/dist/src/agent-registry.js.map +1 -0
  15. package/dist/src/agent.d.ts +60 -0
  16. package/dist/src/agent.d.ts.map +1 -0
  17. package/dist/src/agent.js +371 -0
  18. package/dist/src/agent.js.map +1 -0
  19. package/dist/src/agents/execution.d.ts +2 -0
  20. package/dist/src/agents/execution.d.ts.map +1 -0
  21. package/dist/src/agents/execution.js +54 -0
  22. package/dist/src/agents/execution.js.map +1 -0
  23. package/dist/src/agents/planning.d.ts +2 -0
  24. package/dist/src/agents/planning.d.ts.map +1 -0
  25. package/dist/src/agents/planning.js +68 -0
  26. package/dist/src/agents/planning.js.map +1 -0
  27. package/dist/src/event-transformer.d.ts +7 -0
  28. package/dist/src/event-transformer.d.ts.map +1 -0
  29. package/dist/src/event-transformer.js +174 -0
  30. package/dist/src/event-transformer.js.map +1 -0
  31. package/dist/src/file-manager.d.ts +30 -0
  32. package/dist/src/file-manager.d.ts.map +1 -0
  33. package/dist/src/file-manager.js +181 -0
  34. package/dist/src/file-manager.js.map +1 -0
  35. package/dist/src/git-manager.d.ts +49 -0
  36. package/dist/src/git-manager.d.ts.map +1 -0
  37. package/dist/src/git-manager.js +278 -0
  38. package/dist/src/git-manager.js.map +1 -0
  39. package/dist/src/posthog-api.d.ts +48 -0
  40. package/dist/src/posthog-api.d.ts.map +1 -0
  41. package/dist/src/posthog-api.js +110 -0
  42. package/dist/src/posthog-api.js.map +1 -0
  43. package/dist/src/prompt-builder.d.ts +17 -0
  44. package/dist/src/prompt-builder.d.ts.map +1 -0
  45. package/dist/src/prompt-builder.js +75 -0
  46. package/dist/src/prompt-builder.js.map +1 -0
  47. package/dist/src/stage-executor.d.ts +16 -0
  48. package/dist/src/stage-executor.d.ts.map +1 -0
  49. package/dist/src/stage-executor.js +119 -0
  50. package/dist/src/stage-executor.js.map +1 -0
  51. package/dist/src/task-manager.d.ts +25 -0
  52. package/dist/src/task-manager.d.ts.map +1 -0
  53. package/dist/src/task-manager.js +119 -0
  54. package/dist/src/task-manager.js.map +1 -0
  55. package/dist/src/template-manager.d.ts +30 -0
  56. package/dist/src/template-manager.d.ts.map +1 -0
  57. package/dist/src/template-manager.js +118 -0
  58. package/dist/src/template-manager.js.map +1 -0
  59. package/dist/src/types.d.ts +163 -0
  60. package/dist/src/types.d.ts.map +1 -0
  61. package/dist/src/types.js +9 -0
  62. package/dist/src/types.js.map +1 -0
  63. package/dist/src/utils/logger.d.ts +29 -0
  64. package/dist/src/utils/logger.d.ts.map +1 -0
  65. package/dist/src/utils/logger.js +66 -0
  66. package/dist/src/utils/logger.js.map +1 -0
  67. package/dist/src/utils/mcp.d.ts +10 -0
  68. package/dist/src/utils/mcp.d.ts.map +1 -0
  69. package/dist/src/utils/mcp.js +16 -0
  70. package/dist/src/utils/mcp.js.map +1 -0
  71. package/dist/src/workflow-registry.d.ts +11 -0
  72. package/dist/src/workflow-registry.d.ts.map +1 -0
  73. package/dist/src/workflow-registry.js +26 -0
  74. package/dist/src/workflow-registry.js.map +1 -0
  75. package/dist/src/workflow-types.d.ts +45 -0
  76. package/dist/src/workflow-types.d.ts.map +1 -0
  77. package/dist/src/workflow-types.js +2 -0
  78. package/dist/src/workflow-types.js.map +1 -0
  79. package/package.json +61 -0
  80. package/src/agent-registry.ts +60 -0
  81. package/src/agent.ts +428 -0
  82. package/src/agents/execution.ts +53 -0
  83. package/src/agents/planning.ts +67 -0
  84. package/src/event-transformer.ts +189 -0
  85. package/src/file-manager.ts +204 -0
  86. package/src/git-manager.ts +344 -0
  87. package/src/posthog-api.ts +169 -0
  88. package/src/prompt-builder.ts +93 -0
  89. package/src/stage-executor.ts +137 -0
  90. package/src/task-manager.ts +155 -0
  91. package/src/template-manager.ts +149 -0
  92. package/src/templates/plan-template.md +45 -0
  93. package/src/types.ts +223 -0
  94. package/src/utils/logger.ts +79 -0
  95. package/src/utils/mcp.ts +15 -0
  96. package/src/workflow-registry.ts +31 -0
  97. package/src/workflow-types.ts +53 -0
@@ -0,0 +1,137 @@
1
+ import { query } from '@anthropic-ai/claude-agent-sdk';
2
+ import { Logger } from './utils/logger';
3
+ import { EventTransformer } from './event-transformer';
4
+ import { AgentRegistry } from './agent-registry';
5
+ import type { Task } from './types';
6
+ import type { WorkflowStage, WorkflowStageExecutionResult, WorkflowExecutionOptions } from './workflow-types';
7
+ import { PLANNING_SYSTEM_PROMPT } from './agents/planning';
8
+ import { EXECUTION_SYSTEM_PROMPT } from './agents/execution';
9
+ import { PromptBuilder } from './prompt-builder';
10
+ import { POSTHOG_MCP } from './utils/mcp';
11
+
12
+ export class StageExecutor {
13
+ private registry: AgentRegistry;
14
+ private logger: Logger;
15
+ private eventTransformer: EventTransformer;
16
+ private promptBuilder: PromptBuilder;
17
+
18
+ constructor(registry: AgentRegistry, logger: Logger, promptBuilder?: PromptBuilder) {
19
+ this.registry = registry;
20
+ this.logger = logger.child('StageExecutor');
21
+ this.eventTransformer = new EventTransformer();
22
+ this.promptBuilder = promptBuilder || new PromptBuilder({
23
+ getTaskFiles: async () => [],
24
+ generatePlanTemplate: async () => '',
25
+ logger,
26
+ });
27
+ }
28
+
29
+ async execute(task: Task, stage: WorkflowStage, options: WorkflowExecutionOptions): Promise<WorkflowStageExecutionResult> {
30
+ const isManual = stage.is_manual_only === true;
31
+ if (isManual) {
32
+ this.logger.info('Manual stage detected; skipping agent execution', { stage: stage.key });
33
+ return { results: [] };
34
+ }
35
+
36
+ const inferredAgent = stage.key.toLowerCase().includes('plan') ? 'planning_basic' : 'code_generation';
37
+ const agentName = stage.agent_name || inferredAgent;
38
+ const agent = this.registry.getAgent(agentName);
39
+ if (!agent) {
40
+ throw new Error(`Unknown agent '${agentName}' for stage '${stage.key}'`);
41
+ }
42
+
43
+ const permissionMode = (options.permissionMode as any) || 'acceptEdits';
44
+ const cwd = options.repositoryPath || process.cwd();
45
+
46
+ switch (agent.agent_type) {
47
+ case 'planning':
48
+ return this.runPlanning(task, cwd, options, stage.key);
49
+ case 'execution':
50
+ return this.runExecution(task, cwd, permissionMode, options, stage.key);
51
+ case 'review': // TODO: Implement review
52
+ case 'testing': // TODO: Implement testing
53
+ default:
54
+ // throw new Error(`Unsupported agent type: ${agent.agent_type}`);
55
+ console.warn(`Unsupported agent type: ${agent.agent_type}`);
56
+ return { results: [] };
57
+ }
58
+ }
59
+
60
+ private async runPlanning(task: Task, cwd: string, options: WorkflowExecutionOptions, stageKey: string): Promise<WorkflowStageExecutionResult> {
61
+ const contextPrompt = await this.promptBuilder.buildPlanningPrompt(task);
62
+ let prompt = PLANNING_SYSTEM_PROMPT + '\n\n' + contextPrompt;
63
+
64
+ const stageOverrides = options.stageOverrides?.[stageKey] || options.stageOverrides?.['plan'];
65
+ const mergedOverrides = {
66
+ ...(options.queryOverrides || {}),
67
+ ...(stageOverrides?.queryOverrides || {}),
68
+ } as Record<string, any>;
69
+
70
+ const baseOptions: Record<string, any> = {
71
+ model: 'claude-sonnet-4-5-20250929',
72
+ cwd,
73
+ permissionMode: 'plan',
74
+ settingSources: ['local'],
75
+ mcpServers: {
76
+ ...POSTHOG_MCP
77
+ }
78
+ };
79
+
80
+ const response = query({
81
+ prompt,
82
+ options: { ...baseOptions, ...mergedOverrides },
83
+ });
84
+
85
+ let plan = '';
86
+ for await (const message of response) {
87
+ const transformed = this.eventTransformer.transform(message);
88
+ if (transformed && transformed.type !== 'token') {
89
+ this.logger.debug('Planning event', { type: transformed.type });
90
+ }
91
+ if (message.type === 'assistant' && message.message?.content) {
92
+ for (const c of message.message.content) {
93
+ if (c.type === 'text' && c.text) plan += c.text + '\n';
94
+ }
95
+ }
96
+ }
97
+
98
+ return { plan: plan.trim() };
99
+ }
100
+
101
+ private async runExecution(task: Task, cwd: string, permissionMode: WorkflowExecutionOptions['permissionMode'], options: WorkflowExecutionOptions, stageKey: string): Promise<WorkflowStageExecutionResult> {
102
+ const contextPrompt = await this.promptBuilder.buildExecutionPrompt(task);
103
+ let prompt = EXECUTION_SYSTEM_PROMPT + '\n\n' + contextPrompt;
104
+
105
+ const stageOverrides = options.stageOverrides?.[stageKey];
106
+ const mergedOverrides = {
107
+ ...(options.queryOverrides || {}),
108
+ ...(stageOverrides?.queryOverrides || {}),
109
+ } as Record<string, any>;
110
+
111
+ const baseOptions: Record<string, any> = {
112
+ model: 'claude-sonnet-4-5-20250929',
113
+ cwd,
114
+ permissionMode,
115
+ settingSources: ['local'],
116
+ mcpServers: {
117
+ ...POSTHOG_MCP
118
+ }
119
+ };
120
+
121
+ const response = query({
122
+ prompt,
123
+ options: { ...baseOptions, ...mergedOverrides },
124
+ });
125
+ const results: any[] = [];
126
+ for await (const message of response) {
127
+ const transformed = this.eventTransformer.transform(message);
128
+ if (transformed && transformed.type !== 'token') {
129
+ this.logger.debug('Execution event', { type: transformed.type });
130
+ }
131
+ results.push(message);
132
+ }
133
+ return { results };
134
+ }
135
+ }
136
+
137
+
@@ -0,0 +1,155 @@
1
+ import { randomBytes } from 'crypto';
2
+
3
+ export interface TaskExecutionState {
4
+ taskId: string;
5
+ status: 'running' | 'completed' | 'failed' | 'canceled' | 'timeout';
6
+ mode: 'plan_only' | 'plan_and_build' | 'build_only';
7
+ result?: any;
8
+ startedAt: number;
9
+ completedAt?: number;
10
+ abortController?: AbortController;
11
+ }
12
+
13
+ export class TaskManager {
14
+ private executionStates = new Map<string, TaskExecutionState>();
15
+ private defaultTimeout = 10 * 60 * 1000; // 10 minutes
16
+
17
+ generateExecutionId(): string {
18
+ return randomBytes(16).toString('hex');
19
+ }
20
+
21
+ startExecution(
22
+ taskId: string,
23
+ mode: 'plan_only' | 'plan_and_build' | 'build_only',
24
+ executionId: string = this.generateExecutionId()
25
+ ): TaskExecutionState {
26
+ const executionState: TaskExecutionState = {
27
+ taskId,
28
+ status: 'running',
29
+ mode,
30
+ startedAt: Date.now(),
31
+ abortController: new AbortController(),
32
+ };
33
+
34
+ this.executionStates.set(executionId, executionState);
35
+ this.scheduleTimeout(executionId);
36
+
37
+ return executionState;
38
+ }
39
+
40
+ async waitForCompletion(executionId: string): Promise<any> {
41
+ const execution = this.executionStates.get(executionId);
42
+ if (!execution) {
43
+ throw new Error(`Execution ${executionId} not found`);
44
+ }
45
+
46
+ if (execution.result && execution.status === 'completed') {
47
+ return execution.result;
48
+ }
49
+
50
+ return new Promise((resolve, reject) => {
51
+ const checkInterval = setInterval(() => {
52
+ const currentExecution = this.executionStates.get(executionId);
53
+ if (!currentExecution) {
54
+ clearInterval(checkInterval);
55
+ reject(new Error(`Execution ${executionId} disappeared`));
56
+ return;
57
+ }
58
+
59
+ if (currentExecution.status === 'completed' && currentExecution.result) {
60
+ clearInterval(checkInterval);
61
+ resolve(currentExecution.result);
62
+ } else if (
63
+ currentExecution.status === 'failed' ||
64
+ currentExecution.status === 'canceled' ||
65
+ currentExecution.status === 'timeout'
66
+ ) {
67
+ clearInterval(checkInterval);
68
+ reject(new Error(`Execution ${executionId} ${currentExecution.status}`));
69
+ }
70
+ }, 100);
71
+ });
72
+ }
73
+
74
+ completeExecution(executionId: string, result: any): void {
75
+ const execution = this.executionStates.get(executionId);
76
+ if (!execution) {
77
+ throw new Error(`Execution ${executionId} not found`);
78
+ }
79
+
80
+ execution.status = 'completed';
81
+ execution.result = result;
82
+ execution.completedAt = Date.now();
83
+ }
84
+
85
+ failExecution(executionId: string, error: Error): void {
86
+ const execution = this.executionStates.get(executionId);
87
+ if (!execution) {
88
+ throw new Error(`Execution ${executionId} not found`);
89
+ }
90
+
91
+ execution.status = 'failed';
92
+ execution.completedAt = Date.now();
93
+ execution.result = {
94
+ error: error.message,
95
+ status: 'failed',
96
+ };
97
+ }
98
+
99
+ cancelExecution(executionId: string): void {
100
+ const execution = this.executionStates.get(executionId);
101
+ if (!execution) {
102
+ throw new Error(`Execution ${executionId} not found`);
103
+ }
104
+
105
+ execution.status = 'canceled';
106
+ execution.completedAt = Date.now();
107
+ execution.abortController?.abort();
108
+
109
+ if (!execution.result) {
110
+ execution.result = {
111
+ status: 'canceled',
112
+ message: 'Execution was canceled',
113
+ };
114
+ }
115
+ }
116
+
117
+ getExecution(executionId: string): TaskExecutionState | undefined {
118
+ return this.executionStates.get(executionId);
119
+ }
120
+
121
+ getAbortSignal(executionId: string): AbortSignal | undefined {
122
+ return this.executionStates.get(executionId)?.abortController?.signal;
123
+ }
124
+
125
+ getAbortController(executionId: string): AbortController | undefined {
126
+ return this.executionStates.get(executionId)?.abortController;
127
+ }
128
+
129
+ private scheduleTimeout(executionId: string, timeout: number = this.defaultTimeout): void {
130
+ setTimeout(() => {
131
+ const execution = this.executionStates.get(executionId);
132
+ if (execution && execution.status === 'running') {
133
+ execution.status = 'timeout';
134
+ execution.completedAt = Date.now();
135
+ execution.abortController?.abort();
136
+
137
+ if (!execution.result) {
138
+ execution.result = {
139
+ status: 'timeout',
140
+ message: 'Execution timed out',
141
+ };
142
+ }
143
+ }
144
+ }, timeout);
145
+ }
146
+
147
+ cleanup(olderThan: number = 60 * 60 * 1000): void {
148
+ const cutoff = Date.now() - olderThan;
149
+ for (const [executionId, execution] of this.executionStates) {
150
+ if (execution.completedAt && execution.completedAt < cutoff) {
151
+ this.executionStates.delete(executionId);
152
+ }
153
+ }
154
+ }
155
+ }
@@ -0,0 +1,149 @@
1
+ import { promises as fs } from 'fs';
2
+ import { join, dirname } from 'path';
3
+ import { fileURLToPath } from 'url';
4
+
5
+ export interface TemplateVariables {
6
+ task_id: string;
7
+ task_title: string;
8
+ task_description?: string;
9
+ date: string;
10
+ repository?: string;
11
+ [key: string]: string | undefined;
12
+ }
13
+
14
+ export class TemplateManager {
15
+ private templatesDir: string;
16
+
17
+ constructor() {
18
+ const __filename = fileURLToPath(import.meta.url);
19
+ const __dirname = dirname(__filename);
20
+ this.templatesDir = join(__dirname, 'templates');
21
+ }
22
+
23
+ private async loadTemplate(templateName: string): Promise<string> {
24
+ try {
25
+ const templatePath = join(this.templatesDir, templateName);
26
+ return await fs.readFile(templatePath, 'utf8');
27
+ } catch (error) {
28
+ throw new Error(`Failed to load template ${templateName}: ${error}`);
29
+ }
30
+ }
31
+
32
+ private substituteVariables(template: string, variables: TemplateVariables): string {
33
+ let result = template;
34
+
35
+ for (const [key, value] of Object.entries(variables)) {
36
+ if (value !== undefined) {
37
+ const placeholder = new RegExp(`{{${key}}}`, 'g');
38
+ result = result.replace(placeholder, value);
39
+ }
40
+ }
41
+
42
+ result = result.replace(/{{[^}]+}}/g, '[PLACEHOLDER]');
43
+
44
+ return result;
45
+ }
46
+
47
+ async generatePlan(variables: TemplateVariables): Promise<string> {
48
+ const template = await this.loadTemplate('plan-template.md');
49
+ return this.substituteVariables(template, {
50
+ ...variables,
51
+ date: variables.date || new Date().toISOString().split('T')[0]
52
+ });
53
+ }
54
+
55
+
56
+ async generateCustomFile(templateName: string, variables: TemplateVariables): Promise<string> {
57
+ const template = await this.loadTemplate(templateName);
58
+ return this.substituteVariables(template, {
59
+ ...variables,
60
+ date: variables.date || new Date().toISOString().split('T')[0]
61
+ });
62
+ }
63
+
64
+ async createTaskStructure(taskId: string, taskTitle: string, options?: {
65
+ includePlan?: boolean;
66
+ additionalFiles?: Array<{
67
+ name: string;
68
+ template?: string;
69
+ content?: string;
70
+ }>;
71
+ }): Promise<Array<{ name: string; content: string; type: 'plan' | 'context' | 'reference' | 'output' }>> {
72
+ const files: Array<{ name: string; content: string; type: 'plan' | 'context' | 'reference' | 'output' }> = [];
73
+
74
+ const variables: TemplateVariables = {
75
+ task_id: taskId,
76
+ task_title: taskTitle,
77
+ date: new Date().toISOString().split('T')[0]
78
+ };
79
+
80
+ // Generate plan file if requested
81
+ if (options?.includePlan !== false) {
82
+ const planContent = await this.generatePlan(variables);
83
+ files.push({
84
+ name: 'plan.md',
85
+ content: planContent,
86
+ type: 'plan'
87
+ });
88
+ }
89
+
90
+
91
+ if (options?.additionalFiles) {
92
+ for (const file of options.additionalFiles) {
93
+ let content: string;
94
+
95
+ if (file.template) {
96
+ content = await this.generateCustomFile(file.template, variables);
97
+ } else if (file.content) {
98
+ content = this.substituteVariables(file.content, variables);
99
+ } else {
100
+ content = `# ${file.name}\n\nPlaceholder content for ${file.name}`;
101
+ }
102
+
103
+ files.push({
104
+ name: file.name,
105
+ content,
106
+ type: file.name.includes('context') ? 'context' : 'reference'
107
+ });
108
+ }
109
+ }
110
+
111
+ return files;
112
+ }
113
+
114
+ generatePostHogReadme(): string {
115
+ return `# PostHog Task Files
116
+
117
+ This directory contains task-related files generated by the PostHog Agent.
118
+
119
+ ## Structure
120
+
121
+ Each task has its own subdirectory: \`.posthog/{task-id}/\`
122
+
123
+ ### Common Files
124
+
125
+ - **plan.md** - Implementation plan generated during planning phase
126
+ - **Supporting files** - Any additional files added for task context
127
+ - **artifacts/** - Generated files, outputs, and temporary artifacts
128
+
129
+ ### Usage
130
+
131
+ These files are:
132
+ - Version controlled alongside your code
133
+ - Used by the PostHog Agent for context
134
+ - Available for review in pull requests
135
+ - Organized by task ID for easy reference
136
+
137
+ ### Gitignore
138
+
139
+ Customize \`.posthog/.gitignore\` to control which files are committed:
140
+ - Include plans and documentation by default
141
+ - Exclude temporary files and sensitive data
142
+ - Customize based on your team's workflow
143
+
144
+ ---
145
+
146
+ *Generated by PostHog Agent*
147
+ `;
148
+ }
149
+ }
@@ -0,0 +1,45 @@
1
+ # Implementation Plan: {{task_title}}
2
+
3
+ **Task ID:** {{task_id}}
4
+ **Generated:** {{date}}
5
+
6
+ ## Summary
7
+
8
+ Brief description of what will be implemented and the overall approach.
9
+
10
+ ## Implementation Steps
11
+
12
+ ### 1. Analysis
13
+ - [ ] Identify relevant files and components
14
+ - [ ] Review existing patterns and constraints
15
+
16
+ ### 2. Changes Required
17
+ - [ ] Files to create/modify
18
+ - [ ] Dependencies to add/update
19
+
20
+ ### 3. Implementation
21
+ - [ ] Core functionality changes
22
+ - [ ] Tests and validation
23
+ - [ ] Documentation updates
24
+
25
+ ## File Changes
26
+
27
+ ### New Files
28
+ ```
29
+ path/to/new/file.ts - Purpose
30
+ ```
31
+
32
+ ### Modified Files
33
+ ```
34
+ path/to/existing/file.ts - Changes needed
35
+ ```
36
+
37
+ ## Considerations
38
+
39
+ - Key architectural decisions
40
+ - Potential risks and mitigation
41
+ - Testing approach
42
+
43
+ ---
44
+
45
+ *Generated by PostHog Agent*
package/src/types.ts ADDED
@@ -0,0 +1,223 @@
1
+ // PostHog Task model (matches Array's OpenAPI schema)
2
+ export interface Task {
3
+ id: string;
4
+ title: string;
5
+ description: string;
6
+ origin_product: 'error_tracking' | 'eval_clusters' | 'user_created' | 'support_queue' | 'session_summaries';
7
+ position?: number;
8
+ workflow?: string | null;
9
+ current_stage?: string | null;
10
+ github_integration?: number | null;
11
+ repository_config?: unknown; // JSONField
12
+ repository_list: string;
13
+ primary_repository: string;
14
+ github_branch: string | null;
15
+ github_pr_url: string | null;
16
+ created_at: string;
17
+ updated_at: string;
18
+ }
19
+
20
+ export interface SupportingFile {
21
+ name: string;
22
+ content: string;
23
+ type: 'plan' | 'context' | 'reference' | 'output';
24
+ created_at: string;
25
+ }
26
+
27
+ // Removed legacy ExecutionMode in favor of configurable workflows
28
+
29
+ export enum PermissionMode {
30
+ PLAN = "plan",
31
+ DEFAULT = "default",
32
+ ACCEPT_EDITS = "acceptEdits",
33
+ BYPASS = "bypassPermissions"
34
+ }
35
+
36
+ export interface ExecutionOptions {
37
+ repositoryPath?: string;
38
+ permissionMode?: PermissionMode;
39
+ }
40
+
41
+ // Base event with timestamp
42
+ interface BaseEvent {
43
+ ts: number;
44
+ }
45
+
46
+ // Streaming content events
47
+ export interface TokenEvent extends BaseEvent {
48
+ type: 'token';
49
+ content: string;
50
+ contentType?: 'text' | 'thinking' | 'tool_input';
51
+ }
52
+
53
+ export interface ContentBlockStartEvent extends BaseEvent {
54
+ type: 'content_block_start';
55
+ index: number;
56
+ contentType: 'text' | 'tool_use' | 'thinking';
57
+ toolName?: string;
58
+ toolId?: string;
59
+ }
60
+
61
+ export interface ContentBlockStopEvent extends BaseEvent {
62
+ type: 'content_block_stop';
63
+ index: number;
64
+ }
65
+
66
+ // Tool events
67
+ export interface ToolCallEvent extends BaseEvent {
68
+ type: 'tool_call';
69
+ toolName: string;
70
+ callId: string;
71
+ args: Record<string, any>;
72
+ }
73
+
74
+ export interface ToolResultEvent extends BaseEvent {
75
+ type: 'tool_result';
76
+ toolName: string;
77
+ callId: string;
78
+ result: any;
79
+ }
80
+
81
+ // Message lifecycle events
82
+ export interface MessageStartEvent extends BaseEvent {
83
+ type: 'message_start';
84
+ messageId?: string;
85
+ model?: string;
86
+ }
87
+
88
+ export interface MessageDeltaEvent extends BaseEvent {
89
+ type: 'message_delta';
90
+ stopReason?: string;
91
+ stopSequence?: string;
92
+ usage?: {
93
+ outputTokens: number;
94
+ };
95
+ }
96
+
97
+ export interface MessageStopEvent extends BaseEvent {
98
+ type: 'message_stop';
99
+ }
100
+
101
+ // User message events
102
+ export interface UserMessageEvent extends BaseEvent {
103
+ type: 'user_message';
104
+ content: string;
105
+ isSynthetic?: boolean;
106
+ }
107
+
108
+ // System events
109
+ export interface StatusEvent extends BaseEvent {
110
+ type: 'status';
111
+ phase: string;
112
+ [key: string]: any;
113
+ }
114
+
115
+ export interface InitEvent extends BaseEvent {
116
+ type: 'init';
117
+ model: string;
118
+ tools: string[];
119
+ permissionMode: string;
120
+ cwd: string;
121
+ apiKeySource: string;
122
+ }
123
+
124
+ export interface CompactBoundaryEvent extends BaseEvent {
125
+ type: 'compact_boundary';
126
+ trigger: 'manual' | 'auto';
127
+ preTokens: number;
128
+ }
129
+
130
+ // Result events
131
+ export interface DoneEvent extends BaseEvent {
132
+ type: 'done';
133
+ durationMs?: number;
134
+ numTurns?: number;
135
+ totalCostUsd?: number;
136
+ usage?: any;
137
+ }
138
+
139
+ export interface ErrorEvent extends BaseEvent {
140
+ type: 'error';
141
+ message: string;
142
+ error?: any;
143
+ errorType?: string;
144
+ }
145
+
146
+ // Legacy events (keeping for backwards compatibility)
147
+ export interface DiffEvent extends BaseEvent {
148
+ type: 'diff';
149
+ file: string;
150
+ patch: string;
151
+ summary?: string;
152
+ }
153
+
154
+ export interface FileWriteEvent extends BaseEvent {
155
+ type: 'file_write';
156
+ path: string;
157
+ bytes: number;
158
+ }
159
+
160
+ export interface MetricEvent extends BaseEvent {
161
+ type: 'metric';
162
+ key: string;
163
+ value: number;
164
+ unit?: string;
165
+ }
166
+
167
+ export interface ArtifactEvent extends BaseEvent {
168
+ type: 'artifact';
169
+ kind: string;
170
+ content: any;
171
+ }
172
+
173
+ export type AgentEvent =
174
+ | TokenEvent
175
+ | ContentBlockStartEvent
176
+ | ContentBlockStopEvent
177
+ | ToolCallEvent
178
+ | ToolResultEvent
179
+ | MessageStartEvent
180
+ | MessageDeltaEvent
181
+ | MessageStopEvent
182
+ | UserMessageEvent
183
+ | StatusEvent
184
+ | InitEvent
185
+ | CompactBoundaryEvent
186
+ | DoneEvent
187
+ | ErrorEvent
188
+ | DiffEvent
189
+ | FileWriteEvent
190
+ | MetricEvent
191
+ | ArtifactEvent;
192
+
193
+ export interface ExecutionResult {
194
+ results: any[];
195
+ }
196
+
197
+ export interface PlanResult {
198
+ plan: string;
199
+ }
200
+
201
+ export interface TaskExecutionResult {
202
+ task: Task;
203
+ plan?: string;
204
+ executionResult?: ExecutionResult;
205
+ // Deprecated: mode removed in workflow-based execution
206
+ }
207
+
208
+ export interface AgentConfig {
209
+ workingDirectory?: string;
210
+ onEvent?: (event: AgentEvent) => void;
211
+
212
+ // PostHog API configuration
213
+ posthogApiUrl?: string;
214
+ posthogApiKey?: string;
215
+
216
+ // Logging configuration
217
+ debug?: boolean;
218
+ }
219
+
220
+ export interface PostHogAPIConfig {
221
+ apiUrl: string;
222
+ apiKey: string;
223
+ }