@posthog/agent 1.22.0 → 1.24.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 (118) hide show
  1. package/CLAUDE.md +3 -3
  2. package/README.md +3 -3
  3. package/dist/index.d.ts +11 -11
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +3 -3
  6. package/dist/src/adapters/claude/claude-adapter.d.ts +3 -3
  7. package/dist/src/adapters/claude/claude-adapter.d.ts.map +1 -1
  8. package/dist/src/adapters/claude/claude-adapter.js +156 -111
  9. package/dist/src/adapters/claude/claude-adapter.js.map +1 -1
  10. package/dist/src/adapters/claude/tool-mapper.d.ts +1 -1
  11. package/dist/src/adapters/claude/tool-mapper.d.ts.map +1 -1
  12. package/dist/src/adapters/claude/tool-mapper.js.map +1 -1
  13. package/dist/src/adapters/types.d.ts +1 -1
  14. package/dist/src/adapters/types.d.ts.map +1 -1
  15. package/dist/src/agent.d.ts +7 -7
  16. package/dist/src/agent.d.ts.map +1 -1
  17. package/dist/src/agent.js +143 -85
  18. package/dist/src/agent.js.map +1 -1
  19. package/dist/src/agents/execution.js.map +1 -1
  20. package/dist/src/agents/planning.js.map +1 -1
  21. package/dist/src/agents/research.js.map +1 -1
  22. package/dist/src/file-manager.d.ts +4 -4
  23. package/dist/src/file-manager.d.ts.map +1 -1
  24. package/dist/src/file-manager.js +59 -58
  25. package/dist/src/file-manager.js.map +1 -1
  26. package/dist/src/git-manager.d.ts +1 -1
  27. package/dist/src/git-manager.d.ts.map +1 -1
  28. package/dist/src/git-manager.js +93 -69
  29. package/dist/src/git-manager.js.map +1 -1
  30. package/dist/src/posthog-api.d.ts +2 -3
  31. package/dist/src/posthog-api.d.ts.map +1 -1
  32. package/dist/src/posthog-api.js +22 -22
  33. package/dist/src/posthog-api.js.map +1 -1
  34. package/dist/src/prompt-builder.d.ts +3 -3
  35. package/dist/src/prompt-builder.d.ts.map +1 -1
  36. package/dist/src/prompt-builder.js +123 -93
  37. package/dist/src/prompt-builder.js.map +1 -1
  38. package/dist/src/task-manager.d.ts +4 -4
  39. package/dist/src/task-manager.d.ts.map +1 -1
  40. package/dist/src/task-manager.js +19 -18
  41. package/dist/src/task-manager.js.map +1 -1
  42. package/dist/src/task-progress-reporter.d.ts +3 -4
  43. package/dist/src/task-progress-reporter.d.ts.map +1 -1
  44. package/dist/src/task-progress-reporter.js +59 -54
  45. package/dist/src/task-progress-reporter.js.map +1 -1
  46. package/dist/src/template-manager.d.ts +1 -1
  47. package/dist/src/template-manager.d.ts.map +1 -1
  48. package/dist/src/template-manager.js +30 -28
  49. package/dist/src/template-manager.js.map +1 -1
  50. package/dist/src/todo-manager.d.ts +3 -3
  51. package/dist/src/todo-manager.d.ts.map +1 -1
  52. package/dist/src/todo-manager.js +29 -24
  53. package/dist/src/todo-manager.js.map +1 -1
  54. package/dist/src/tools/registry.d.ts +1 -1
  55. package/dist/src/tools/registry.js +60 -60
  56. package/dist/src/tools/registry.js.map +1 -1
  57. package/dist/src/tools/types.d.ts +31 -31
  58. package/dist/src/types.d.ts +33 -33
  59. package/dist/src/types.d.ts.map +1 -1
  60. package/dist/src/types.js.map +1 -1
  61. package/dist/src/utils/logger.d.ts +4 -4
  62. package/dist/src/utils/logger.d.ts.map +1 -1
  63. package/dist/src/utils/logger.js +8 -8
  64. package/dist/src/utils/logger.js.map +1 -1
  65. package/dist/src/workflow/config.d.ts +1 -1
  66. package/dist/src/workflow/config.d.ts.map +1 -1
  67. package/dist/src/workflow/config.js +18 -18
  68. package/dist/src/workflow/config.js.map +1 -1
  69. package/dist/src/workflow/steps/build.d.ts +1 -1
  70. package/dist/src/workflow/steps/build.d.ts.map +1 -1
  71. package/dist/src/workflow/steps/build.js +46 -38
  72. package/dist/src/workflow/steps/build.js.map +1 -1
  73. package/dist/src/workflow/steps/finalize.d.ts +1 -1
  74. package/dist/src/workflow/steps/finalize.d.ts.map +1 -1
  75. package/dist/src/workflow/steps/finalize.js +54 -48
  76. package/dist/src/workflow/steps/finalize.js.map +1 -1
  77. package/dist/src/workflow/steps/plan.d.ts +1 -1
  78. package/dist/src/workflow/steps/plan.d.ts.map +1 -1
  79. package/dist/src/workflow/steps/plan.js +58 -46
  80. package/dist/src/workflow/steps/plan.js.map +1 -1
  81. package/dist/src/workflow/steps/research.d.ts +1 -1
  82. package/dist/src/workflow/steps/research.d.ts.map +1 -1
  83. package/dist/src/workflow/steps/research.js +68 -56
  84. package/dist/src/workflow/steps/research.js.map +1 -1
  85. package/dist/src/workflow/types.d.ts +12 -12
  86. package/dist/src/workflow/types.d.ts.map +1 -1
  87. package/dist/src/workflow/utils.d.ts +1 -1
  88. package/dist/src/workflow/utils.d.ts.map +1 -1
  89. package/dist/src/workflow/utils.js +7 -4
  90. package/dist/src/workflow/utils.js.map +1 -1
  91. package/package.json +8 -8
  92. package/src/adapters/claude/claude-adapter.ts +220 -168
  93. package/src/adapters/claude/tool-mapper.ts +2 -2
  94. package/src/adapters/types.ts +1 -1
  95. package/src/agent.ts +579 -444
  96. package/src/agents/execution.ts +1 -1
  97. package/src/agents/planning.ts +1 -1
  98. package/src/agents/research.ts +0 -1
  99. package/src/file-manager.ts +64 -63
  100. package/src/git-manager.ts +152 -87
  101. package/src/posthog-api.ts +122 -82
  102. package/src/prompt-builder.ts +180 -135
  103. package/src/task-manager.ts +38 -30
  104. package/src/task-progress-reporter.ts +70 -59
  105. package/src/template-manager.ts +98 -45
  106. package/src/todo-manager.ts +35 -30
  107. package/src/tools/registry.ts +62 -62
  108. package/src/tools/types.ts +36 -36
  109. package/src/types.ts +93 -71
  110. package/src/utils/logger.ts +62 -56
  111. package/src/workflow/config.ts +48 -48
  112. package/src/workflow/steps/build.ts +122 -113
  113. package/src/workflow/steps/finalize.ts +214 -182
  114. package/src/workflow/steps/plan.ts +151 -131
  115. package/src/workflow/steps/research.ts +205 -186
  116. package/src/workflow/types.ts +38 -36
  117. package/src/workflow/utils.ts +37 -34
  118. package/LICENSE +0 -33
package/src/agent.ts CHANGED
@@ -1,322 +1,403 @@
1
1
  import { query } from "@anthropic-ai/claude-agent-sdk";
2
- import type { Task, ExecutionResult, AgentConfig, CanUseTool } from './types.js';
3
- import { TaskManager } from './task-manager.js';
4
- import { PostHogAPIClient } from './posthog-api.js';
5
- import { PostHogFileManager } from './file-manager.js';
6
- import { GitManager } from './git-manager.js';
7
- import { TemplateManager } from './template-manager.js';
8
- import { ClaudeAdapter } from './adapters/claude/claude-adapter.js';
9
- import type { ProviderAdapter } from './adapters/types.js';
10
- import { Logger } from './utils/logger.js';
11
- import { PromptBuilder } from './prompt-builder.js';
12
- import { TaskProgressReporter } from './task-progress-reporter.js';
13
- import { TASK_WORKFLOW } from './workflow/config.js';
14
- import type { WorkflowRuntime } from './workflow/types.js';
2
+ import { ClaudeAdapter } from "./adapters/claude/claude-adapter.js";
3
+ import type { ProviderAdapter } from "./adapters/types.js";
4
+ import { PostHogFileManager } from "./file-manager.js";
5
+ import { GitManager } from "./git-manager.js";
6
+ import { PostHogAPIClient } from "./posthog-api.js";
7
+ import { PromptBuilder } from "./prompt-builder.js";
8
+ import { TaskManager } from "./task-manager.js";
9
+ import { TaskProgressReporter } from "./task-progress-reporter.js";
10
+ import { TemplateManager } from "./template-manager.js";
11
+ import type {
12
+ AgentConfig,
13
+ CanUseTool,
14
+ ExecutionResult,
15
+ Task,
16
+ } from "./types.js";
17
+ import { Logger } from "./utils/logger.js";
18
+ import { TASK_WORKFLOW } from "./workflow/config.js";
19
+ import type { WorkflowRuntime } from "./workflow/types.js";
15
20
 
16
21
  export class Agent {
17
- private workingDirectory: string;
18
- private onEvent?: (event: any) => void;
19
- private taskManager: TaskManager;
20
- private posthogAPI?: PostHogAPIClient;
21
- private fileManager: PostHogFileManager;
22
- private gitManager: GitManager;
23
- private templateManager: TemplateManager;
24
- private adapter: ProviderAdapter;
25
- private logger: Logger;
26
- private progressReporter: TaskProgressReporter;
27
- private promptBuilder: PromptBuilder;
28
- private mcpServers?: Record<string, any>;
29
- private canUseTool?: CanUseTool;
30
- public debug: boolean;
31
-
32
- constructor(config: AgentConfig) {
33
- this.workingDirectory = config.workingDirectory || process.cwd();
34
- this.onEvent = config.onEvent;
35
- this.canUseTool = config.canUseTool;
36
- this.debug = config.debug || false;
37
-
38
- // Build default PostHog MCP server configuration
39
- const posthogMcpUrl = config.posthogMcpUrl
40
- || process.env.POSTHOG_MCP_URL
41
- || 'https://mcp.posthog.com/mcp';
42
-
43
- // Add auth if API key provided
44
- const headers: Record<string, string> = {};
45
- if (config.posthogApiKey) {
46
- headers['Authorization'] = `Bearer ${config.posthogApiKey}`;
47
- }
48
-
49
- const defaultMcpServers = {
50
- posthog: {
51
- type: 'http' as const,
52
- url: posthogMcpUrl,
53
- ...(Object.keys(headers).length > 0 ? { headers } : {}),
54
- }
55
- };
56
-
57
- // Merge default PostHog MCP with user-provided servers (user config takes precedence)
58
- this.mcpServers = {
59
- ...defaultMcpServers,
60
- ...config.mcpServers
61
- };
62
- this.logger = new Logger({ debug: this.debug, prefix: '[PostHog Agent]' });
63
- this.taskManager = new TaskManager();
64
- // Hardcode Claude adapter for now - extensible for other providers later
65
- this.adapter = new ClaudeAdapter();
66
-
67
- this.fileManager = new PostHogFileManager(
68
- this.workingDirectory,
69
- this.logger.child('FileManager')
70
- );
71
- this.gitManager = new GitManager({
72
- repositoryPath: this.workingDirectory,
73
- logger: this.logger.child('GitManager')
74
- // TODO: Add author config from environment or config
75
- });
76
- this.templateManager = new TemplateManager();
77
-
78
- if (config.posthogApiUrl && config.posthogApiKey) {
79
- this.posthogAPI = new PostHogAPIClient({
80
- apiUrl: config.posthogApiUrl,
81
- apiKey: config.posthogApiKey,
82
- projectId: config.posthogProjectId,
83
- });
84
- }
85
-
86
- this.promptBuilder = new PromptBuilder({
87
- getTaskFiles: (taskId: string) => this.getTaskFiles(taskId),
88
- generatePlanTemplate: (vars) => this.templateManager.generatePlan(vars),
89
- posthogClient: this.posthogAPI,
90
- logger: this.logger.child('PromptBuilder')
91
- });
92
- this.progressReporter = new TaskProgressReporter(this.posthogAPI, this.logger);
22
+ private workingDirectory: string;
23
+ private onEvent?: (event: any) => void;
24
+ private taskManager: TaskManager;
25
+ private posthogAPI?: PostHogAPIClient;
26
+ private fileManager: PostHogFileManager;
27
+ private gitManager: GitManager;
28
+ private templateManager: TemplateManager;
29
+ private adapter: ProviderAdapter;
30
+ private logger: Logger;
31
+ private progressReporter: TaskProgressReporter;
32
+ private promptBuilder: PromptBuilder;
33
+ private mcpServers?: Record<string, any>;
34
+ private canUseTool?: CanUseTool;
35
+ public debug: boolean;
36
+
37
+ constructor(config: AgentConfig) {
38
+ this.workingDirectory = config.workingDirectory || process.cwd();
39
+ this.onEvent = config.onEvent;
40
+ this.canUseTool = config.canUseTool;
41
+ this.debug = config.debug || false;
42
+
43
+ // Build default PostHog MCP server configuration
44
+ const posthogMcpUrl =
45
+ config.posthogMcpUrl ||
46
+ process.env.POSTHOG_MCP_URL ||
47
+ "https://mcp.posthog.com/mcp";
48
+
49
+ // Add auth if API key provided
50
+ const headers: Record<string, string> = {};
51
+ if (config.posthogApiKey) {
52
+ headers.Authorization = `Bearer ${config.posthogApiKey}`;
93
53
  }
94
54
 
95
- /**
96
- * Enable or disable debug logging
97
- */
98
- setDebug(enabled: boolean) {
99
- this.debug = enabled;
100
- this.logger.setDebug(enabled);
55
+ const defaultMcpServers = {
56
+ posthog: {
57
+ type: "http" as const,
58
+ url: posthogMcpUrl,
59
+ ...(Object.keys(headers).length > 0 ? { headers } : {}),
60
+ },
61
+ };
62
+
63
+ // Merge default PostHog MCP with user-provided servers (user config takes precedence)
64
+ this.mcpServers = {
65
+ ...defaultMcpServers,
66
+ ...config.mcpServers,
67
+ };
68
+ this.logger = new Logger({ debug: this.debug, prefix: "[PostHog Agent]" });
69
+ this.taskManager = new TaskManager();
70
+ // Hardcode Claude adapter for now - extensible for other providers later
71
+ this.adapter = new ClaudeAdapter();
72
+
73
+ this.fileManager = new PostHogFileManager(
74
+ this.workingDirectory,
75
+ this.logger.child("FileManager"),
76
+ );
77
+ this.gitManager = new GitManager({
78
+ repositoryPath: this.workingDirectory,
79
+ logger: this.logger.child("GitManager"),
80
+ // TODO: Add author config from environment or config
81
+ });
82
+ this.templateManager = new TemplateManager();
83
+
84
+ if (config.posthogApiUrl && config.posthogApiKey) {
85
+ this.posthogAPI = new PostHogAPIClient({
86
+ apiUrl: config.posthogApiUrl,
87
+ apiKey: config.posthogApiKey,
88
+ projectId: config.posthogProjectId,
89
+ });
101
90
  }
102
91
 
103
- /**
104
- * Configure LLM gateway environment variables for Claude Code CLI
105
- */
106
- private async _configureLlmGateway(): Promise<void> {
107
- if (!this.posthogAPI) {
108
- return;
109
- }
110
-
111
- try {
112
- const gatewayUrl = this.posthogAPI.getLlmGatewayUrl();
113
- const apiKey = this.posthogAPI.getApiKey();
114
-
115
- process.env.ANTHROPIC_BASE_URL = gatewayUrl;
116
- process.env.ANTHROPIC_AUTH_TOKEN = apiKey;
117
- this.ensureOpenAIGatewayEnv(gatewayUrl, apiKey);
118
-
119
- this.logger.debug('Configured LLM gateway', { gatewayUrl });
120
- } catch (error) {
121
- this.logger.error('Failed to configure LLM gateway', error);
122
- throw error;
123
- }
92
+ this.promptBuilder = new PromptBuilder({
93
+ getTaskFiles: (taskId: string) => this.getTaskFiles(taskId),
94
+ generatePlanTemplate: (vars) => this.templateManager.generatePlan(vars),
95
+ posthogClient: this.posthogAPI,
96
+ logger: this.logger.child("PromptBuilder"),
97
+ });
98
+ this.progressReporter = new TaskProgressReporter(
99
+ this.posthogAPI,
100
+ this.logger,
101
+ );
102
+ }
103
+
104
+ /**
105
+ * Enable or disable debug logging
106
+ */
107
+ setDebug(enabled: boolean) {
108
+ this.debug = enabled;
109
+ this.logger.setDebug(enabled);
110
+ }
111
+
112
+ /**
113
+ * Configure LLM gateway environment variables for Claude Code CLI
114
+ */
115
+ private async _configureLlmGateway(): Promise<void> {
116
+ if (!this.posthogAPI) {
117
+ return;
124
118
  }
125
119
 
126
- // Adaptive task execution orchestrated via workflow steps
127
- async runTask(taskOrId: Task | string, options: import('./types.js').TaskExecutionOptions = {}): Promise<void> {
128
- await this._configureLlmGateway();
129
-
130
- const task = typeof taskOrId === 'string' ? await this.fetchTask(taskOrId) : taskOrId;
131
- const cwd = options.repositoryPath || this.workingDirectory;
132
- const isCloudMode = options.isCloudMode ?? false;
133
- const taskSlug = (task as any).slug || task.id;
134
-
135
- this.logger.info('Starting adaptive task execution', { taskId: task.id, taskSlug, isCloudMode });
136
-
137
- // Initialize progress reporter for task run tracking (needed for PR attachment)
138
- await this.progressReporter.start(task.id, { totalSteps: TASK_WORKFLOW.length });
139
- this.emitEvent(this.adapter.createStatusEvent('run_started', { runId: this.progressReporter.runId }));
140
-
141
- await this.prepareTaskBranch(taskSlug, isCloudMode);
142
-
143
- let taskError: Error | undefined;
144
- try {
145
- const workflowContext: WorkflowRuntime = {
146
- task,
147
- taskSlug,
148
- cwd,
149
- isCloudMode,
150
- options,
151
- logger: this.logger,
152
- fileManager: this.fileManager,
153
- gitManager: this.gitManager,
154
- promptBuilder: this.promptBuilder,
155
- progressReporter: this.progressReporter,
156
- adapter: this.adapter,
157
- mcpServers: this.mcpServers,
158
- posthogAPI: this.posthogAPI,
159
- emitEvent: (event: any) => this.emitEvent(event),
160
- stepResults: {},
161
- };
162
-
163
- for (const step of TASK_WORKFLOW) {
164
- const result = await step.run({ step, context: workflowContext });
165
- if (result.halt) {
166
- return;
167
- }
168
- }
169
-
170
- const shouldCreatePR = options.createPR ?? isCloudMode;
171
- if (shouldCreatePR) {
172
- await this.ensurePullRequest(task, workflowContext.stepResults);
173
- }
174
-
175
- this.logger.info('Task execution complete', { taskId: task.id });
176
- this.emitEvent(this.adapter.createStatusEvent('task_complete', { taskId: task.id }));
177
- } catch (error) {
178
- taskError = error instanceof Error ? error : new Error(String(error));
179
- this.logger.error('Task execution failed', { taskId: task.id, error: taskError.message });
180
- } finally {
181
- if (taskError) {
182
- await this.progressReporter.fail(taskError);
183
- throw taskError;
184
- } else {
185
- await this.progressReporter.complete();
186
- }
187
- }
188
- }
189
-
190
- // Direct prompt execution - still supported for low-level usage
191
- async run(prompt: string, options: { repositoryPath?: string; permissionMode?: import('./types.js').PermissionMode; queryOverrides?: Record<string, any>; canUseTool?: CanUseTool } = {}): Promise<ExecutionResult> {
192
- await this._configureLlmGateway();
193
- const baseOptions: Record<string, any> = {
194
- model: "claude-sonnet-4-5-20250929",
195
- cwd: options.repositoryPath || this.workingDirectory,
196
- permissionMode: (options.permissionMode as any) || "default",
197
- settingSources: ["local"],
198
- mcpServers: this.mcpServers,
199
- };
200
-
201
- // Add canUseTool hook if provided (options take precedence over instance config)
202
- const canUseTool = options.canUseTool || this.canUseTool;
203
- if (canUseTool) {
204
- baseOptions.canUseTool = canUseTool;
205
- }
120
+ try {
121
+ const gatewayUrl = this.posthogAPI.getLlmGatewayUrl();
122
+ const apiKey = this.posthogAPI.getApiKey();
206
123
 
207
- const response = query({
208
- prompt,
209
- options: { ...baseOptions, ...(options.queryOverrides || {}) },
210
- });
124
+ process.env.ANTHROPIC_BASE_URL = gatewayUrl;
125
+ process.env.ANTHROPIC_AUTH_TOKEN = apiKey;
126
+ this.ensureOpenAIGatewayEnv(gatewayUrl, apiKey);
211
127
 
212
- const results = [];
213
- for await (const message of response) {
214
- this.logger.debug('Received message in direct run', message);
215
- // Emit raw SDK event
216
- this.emitEvent(this.adapter.createRawSDKEvent(message));
217
- const transformedEvents = this.adapter.transform(message);
218
- for (const event of transformedEvents) {
219
- this.emitEvent(event);
220
- }
221
- results.push(message);
222
- }
223
-
224
- return { results };
128
+ this.logger.debug("Configured LLM gateway", { gatewayUrl });
129
+ } catch (error) {
130
+ this.logger.error("Failed to configure LLM gateway", error);
131
+ throw error;
225
132
  }
226
-
227
- // PostHog task operations
228
- async fetchTask(taskId: string): Promise<Task> {
229
- this.logger.debug('Fetching task from PostHog', { taskId });
230
- if (!this.posthogAPI) {
231
- const error = new Error('PostHog API not configured. Provide posthogApiUrl and posthogApiKey in constructor.');
232
- this.logger.error('PostHog API not configured', error);
233
- throw error;
133
+ }
134
+
135
+ // Adaptive task execution orchestrated via workflow steps
136
+ async runTask(
137
+ taskOrId: Task | string,
138
+ options: import("./types.js").TaskExecutionOptions = {},
139
+ ): Promise<void> {
140
+ await this._configureLlmGateway();
141
+
142
+ const task =
143
+ typeof taskOrId === "string" ? await this.fetchTask(taskOrId) : taskOrId;
144
+ const cwd = options.repositoryPath || this.workingDirectory;
145
+ const isCloudMode = options.isCloudMode ?? false;
146
+ const taskSlug = (task as any).slug || task.id;
147
+
148
+ this.logger.info("Starting adaptive task execution", {
149
+ taskId: task.id,
150
+ taskSlug,
151
+ isCloudMode,
152
+ });
153
+
154
+ // Initialize progress reporter for task run tracking (needed for PR attachment)
155
+ await this.progressReporter.start(task.id, {
156
+ totalSteps: TASK_WORKFLOW.length,
157
+ });
158
+ this.emitEvent(
159
+ this.adapter.createStatusEvent("run_started", {
160
+ runId: this.progressReporter.runId,
161
+ }),
162
+ );
163
+
164
+ await this.prepareTaskBranch(taskSlug, isCloudMode);
165
+
166
+ let taskError: Error | undefined;
167
+ try {
168
+ const workflowContext: WorkflowRuntime = {
169
+ task,
170
+ taskSlug,
171
+ cwd,
172
+ isCloudMode,
173
+ options,
174
+ logger: this.logger,
175
+ fileManager: this.fileManager,
176
+ gitManager: this.gitManager,
177
+ promptBuilder: this.promptBuilder,
178
+ progressReporter: this.progressReporter,
179
+ adapter: this.adapter,
180
+ mcpServers: this.mcpServers,
181
+ posthogAPI: this.posthogAPI,
182
+ emitEvent: (event: any) => this.emitEvent(event),
183
+ stepResults: {},
184
+ };
185
+
186
+ for (const step of TASK_WORKFLOW) {
187
+ const result = await step.run({ step, context: workflowContext });
188
+ if (result.halt) {
189
+ return;
234
190
  }
235
- return this.posthogAPI.fetchTask(taskId);
191
+ }
192
+
193
+ const shouldCreatePR = options.createPR ?? isCloudMode;
194
+ if (shouldCreatePR) {
195
+ await this.ensurePullRequest(task, workflowContext.stepResults);
196
+ }
197
+
198
+ this.logger.info("Task execution complete", { taskId: task.id });
199
+ this.emitEvent(
200
+ this.adapter.createStatusEvent("task_complete", { taskId: task.id }),
201
+ );
202
+ } catch (error) {
203
+ taskError = error instanceof Error ? error : new Error(String(error));
204
+ this.logger.error("Task execution failed", {
205
+ taskId: task.id,
206
+ error: taskError.message,
207
+ });
208
+ } finally {
209
+ if (taskError) {
210
+ await this.progressReporter.fail(taskError);
211
+ // biome-ignore lint/correctness/noUnsafeFinally: we actually want to throw the error
212
+ throw taskError;
213
+ } else {
214
+ await this.progressReporter.complete();
215
+ }
236
216
  }
237
-
238
- getPostHogClient(): PostHogAPIClient | undefined {
239
- return this.posthogAPI;
217
+ }
218
+
219
+ // Direct prompt execution - still supported for low-level usage
220
+ async run(
221
+ prompt: string,
222
+ options: {
223
+ repositoryPath?: string;
224
+ permissionMode?: import("./types.js").PermissionMode;
225
+ queryOverrides?: Record<string, any>;
226
+ canUseTool?: CanUseTool;
227
+ } = {},
228
+ ): Promise<ExecutionResult> {
229
+ await this._configureLlmGateway();
230
+ const baseOptions: Record<string, any> = {
231
+ model: "claude-sonnet-4-5-20250929",
232
+ cwd: options.repositoryPath || this.workingDirectory,
233
+ permissionMode: (options.permissionMode as any) || "default",
234
+ settingSources: ["local"],
235
+ mcpServers: this.mcpServers,
236
+ };
237
+
238
+ // Add canUseTool hook if provided (options take precedence over instance config)
239
+ const canUseTool = options.canUseTool || this.canUseTool;
240
+ if (canUseTool) {
241
+ baseOptions.canUseTool = canUseTool;
240
242
  }
241
-
242
- async listTasks(filters?: {
243
- repository?: string;
244
- organization?: string;
245
- origin_product?: string;
246
- }): Promise<Task[]> {
247
- if (!this.posthogAPI) {
248
- throw new Error('PostHog API not configured. Provide posthogApiUrl and posthogApiKey in constructor.');
243
+
244
+ const response = query({
245
+ prompt,
246
+ options: { ...baseOptions, ...(options.queryOverrides || {}) },
247
+ });
248
+
249
+ const results = [];
250
+ try {
251
+ for await (const message of response) {
252
+ this.logger.debug("Received message in direct run", message);
253
+ // Emit raw SDK event
254
+ this.emitEvent(this.adapter.createRawSDKEvent(message));
255
+ const transformedEvents = this.adapter.transform(message);
256
+ for (const event of transformedEvents) {
257
+ this.emitEvent(event);
249
258
  }
250
- return this.posthogAPI.listTasks(filters);
251
- }
252
-
253
- // File system operations for task artifacts
254
- async writeTaskFile(taskId: string, fileName: string, content: string, type: 'plan' | 'context' | 'reference' | 'output' = 'reference'): Promise<void> {
255
- this.logger.debug('Writing task file', { taskId, fileName, type, contentLength: content.length });
256
- await this.fileManager.writeTaskFile(taskId, { name: fileName, content, type });
257
- }
258
-
259
- async readTaskFile(taskId: string, fileName: string): Promise<string | null> {
260
- this.logger.debug('Reading task file', { taskId, fileName });
261
- return await this.fileManager.readTaskFile(taskId, fileName);
262
- }
263
-
264
- async getTaskFiles(taskId: string): Promise<any[]> {
265
- this.logger.debug('Getting task files', { taskId });
266
- const files = await this.fileManager.getTaskFiles(taskId);
267
- this.logger.debug('Found task files', { taskId, fileCount: files.length });
268
- return files;
269
- }
270
-
271
- async writePlan(taskId: string, plan: string): Promise<void> {
272
- this.logger.info('Writing plan', { taskId, planLength: plan.length });
273
- await this.fileManager.writePlan(taskId, plan);
274
- }
275
-
276
- async readPlan(taskId: string): Promise<string | null> {
277
- this.logger.debug('Reading plan', { taskId });
278
- return await this.fileManager.readPlan(taskId);
259
+ results.push(message);
260
+ }
261
+ } catch (error) {
262
+ this.logger.error("Error during direct run", error);
263
+ throw error;
279
264
  }
280
265
 
281
- // Git operations for task execution
282
- async createPlanningBranch(taskId: string): Promise<string> {
283
- this.logger.info('Creating planning branch', { taskId });
284
- const branchName = await this.gitManager.createTaskPlanningBranch(taskId);
285
- this.logger.debug('Planning branch created', { taskId, branchName });
286
- return branchName;
287
- }
288
-
289
- async commitPlan(taskId: string, taskTitle: string): Promise<string> {
290
- this.logger.info('Committing plan', { taskId, taskTitle });
291
- const commitHash = await this.gitManager.commitPlan(taskId, taskTitle);
292
- this.logger.debug('Plan committed', { taskId, commitHash });
293
- return commitHash;
266
+ return { results };
267
+ }
268
+
269
+ // PostHog task operations
270
+ async fetchTask(taskId: string): Promise<Task> {
271
+ this.logger.debug("Fetching task from PostHog", { taskId });
272
+ if (!this.posthogAPI) {
273
+ const error = new Error(
274
+ "PostHog API not configured. Provide posthogApiUrl and posthogApiKey in constructor.",
275
+ );
276
+ this.logger.error("PostHog API not configured", error);
277
+ throw error;
294
278
  }
295
-
296
- async createImplementationBranch(taskId: string, planningBranchName?: string): Promise<string> {
297
- this.logger.info('Creating implementation branch', { taskId, fromBranch: planningBranchName });
298
- const branchName = await this.gitManager.createTaskImplementationBranch(taskId, planningBranchName);
299
- this.logger.debug('Implementation branch created', { taskId, branchName });
300
- return branchName;
279
+ return this.posthogAPI.fetchTask(taskId);
280
+ }
281
+
282
+ getPostHogClient(): PostHogAPIClient | undefined {
283
+ return this.posthogAPI;
284
+ }
285
+
286
+ async listTasks(filters?: {
287
+ repository?: string;
288
+ organization?: string;
289
+ origin_product?: string;
290
+ }): Promise<Task[]> {
291
+ if (!this.posthogAPI) {
292
+ throw new Error(
293
+ "PostHog API not configured. Provide posthogApiUrl and posthogApiKey in constructor.",
294
+ );
301
295
  }
302
-
303
- async commitImplementation(taskId: string, taskTitle: string, planSummary?: string): Promise<string> {
304
- this.logger.info('Committing implementation', { taskId, taskTitle });
305
- const commitHash = await this.gitManager.commitImplementation(taskId, taskTitle, planSummary);
306
- this.logger.debug('Implementation committed', { taskId, commitHash });
307
- return commitHash;
308
- }
309
-
310
- async createPullRequest(
311
- taskId: string,
312
- branchName: string,
313
- taskTitle: string,
314
- taskDescription: string,
315
- customBody?: string
316
- ): Promise<string> {
317
- this.logger.info('Creating pull request', { taskId, branchName, taskTitle });
318
-
319
- const defaultBody = `## Task Details
296
+ return this.posthogAPI.listTasks(filters);
297
+ }
298
+
299
+ // File system operations for task artifacts
300
+ async writeTaskFile(
301
+ taskId: string,
302
+ fileName: string,
303
+ content: string,
304
+ type: "plan" | "context" | "reference" | "output" = "reference",
305
+ ): Promise<void> {
306
+ this.logger.debug("Writing task file", {
307
+ taskId,
308
+ fileName,
309
+ type,
310
+ contentLength: content.length,
311
+ });
312
+ await this.fileManager.writeTaskFile(taskId, {
313
+ name: fileName,
314
+ content,
315
+ type,
316
+ });
317
+ }
318
+
319
+ async readTaskFile(taskId: string, fileName: string): Promise<string | null> {
320
+ this.logger.debug("Reading task file", { taskId, fileName });
321
+ return await this.fileManager.readTaskFile(taskId, fileName);
322
+ }
323
+
324
+ async getTaskFiles(taskId: string): Promise<any[]> {
325
+ this.logger.debug("Getting task files", { taskId });
326
+ const files = await this.fileManager.getTaskFiles(taskId);
327
+ this.logger.debug("Found task files", { taskId, fileCount: files.length });
328
+ return files;
329
+ }
330
+
331
+ async writePlan(taskId: string, plan: string): Promise<void> {
332
+ this.logger.info("Writing plan", { taskId, planLength: plan.length });
333
+ await this.fileManager.writePlan(taskId, plan);
334
+ }
335
+
336
+ async readPlan(taskId: string): Promise<string | null> {
337
+ this.logger.debug("Reading plan", { taskId });
338
+ return await this.fileManager.readPlan(taskId);
339
+ }
340
+
341
+ // Git operations for task execution
342
+ async createPlanningBranch(taskId: string): Promise<string> {
343
+ this.logger.info("Creating planning branch", { taskId });
344
+ const branchName = await this.gitManager.createTaskPlanningBranch(taskId);
345
+ this.logger.debug("Planning branch created", { taskId, branchName });
346
+ return branchName;
347
+ }
348
+
349
+ async commitPlan(taskId: string, taskTitle: string): Promise<string> {
350
+ this.logger.info("Committing plan", { taskId, taskTitle });
351
+ const commitHash = await this.gitManager.commitPlan(taskId, taskTitle);
352
+ this.logger.debug("Plan committed", { taskId, commitHash });
353
+ return commitHash;
354
+ }
355
+
356
+ async createImplementationBranch(
357
+ taskId: string,
358
+ planningBranchName?: string,
359
+ ): Promise<string> {
360
+ this.logger.info("Creating implementation branch", {
361
+ taskId,
362
+ fromBranch: planningBranchName,
363
+ });
364
+ const branchName = await this.gitManager.createTaskImplementationBranch(
365
+ taskId,
366
+ planningBranchName,
367
+ );
368
+ this.logger.debug("Implementation branch created", { taskId, branchName });
369
+ return branchName;
370
+ }
371
+
372
+ async commitImplementation(
373
+ taskId: string,
374
+ taskTitle: string,
375
+ planSummary?: string,
376
+ ): Promise<string> {
377
+ this.logger.info("Committing implementation", { taskId, taskTitle });
378
+ const commitHash = await this.gitManager.commitImplementation(
379
+ taskId,
380
+ taskTitle,
381
+ planSummary,
382
+ );
383
+ this.logger.debug("Implementation committed", { taskId, commitHash });
384
+ return commitHash;
385
+ }
386
+
387
+ async createPullRequest(
388
+ taskId: string,
389
+ branchName: string,
390
+ taskTitle: string,
391
+ taskDescription: string,
392
+ customBody?: string,
393
+ ): Promise<string> {
394
+ this.logger.info("Creating pull request", {
395
+ taskId,
396
+ branchName,
397
+ taskTitle,
398
+ });
399
+
400
+ const defaultBody = `## Task Details
320
401
  **Task ID**: ${taskId}
321
402
  **Description**: ${taskDescription}
322
403
 
@@ -324,171 +405,225 @@ export class Agent {
324
405
  This PR implements the changes described in the task.
325
406
 
326
407
  Generated by PostHog Agent`;
327
- const prBody = customBody || defaultBody;
328
-
329
- const prUrl = await this.gitManager.createPullRequest(
330
- branchName,
331
- taskTitle,
332
- prBody
333
- );
334
-
335
- this.logger.info('Pull request created', { taskId, prUrl });
336
- return prUrl;
408
+ const prBody = customBody || defaultBody;
409
+
410
+ const prUrl = await this.gitManager.createPullRequest(
411
+ branchName,
412
+ taskTitle,
413
+ prBody,
414
+ );
415
+
416
+ this.logger.info("Pull request created", { taskId, prUrl });
417
+ return prUrl;
418
+ }
419
+
420
+ async attachPullRequestToTask(
421
+ taskId: string,
422
+ prUrl: string,
423
+ branchName?: string,
424
+ ): Promise<void> {
425
+ this.logger.info("Attaching PR to task run", { taskId, prUrl, branchName });
426
+
427
+ if (!this.posthogAPI || !this.progressReporter.runId) {
428
+ const error = new Error(
429
+ "PostHog API not configured or no active run. Cannot attach PR to task.",
430
+ );
431
+ this.logger.error("PostHog API not configured", error);
432
+ throw error;
337
433
  }
338
434
 
339
- async attachPullRequestToTask(taskId: string, prUrl: string, branchName?: string): Promise<void> {
340
- this.logger.info('Attaching PR to task run', { taskId, prUrl, branchName });
341
-
342
- if (!this.posthogAPI || !this.progressReporter.runId) {
343
- const error = new Error('PostHog API not configured or no active run. Cannot attach PR to task.');
344
- this.logger.error('PostHog API not configured', error);
345
- throw error;
346
- }
347
-
348
- const updates: any = {
349
- output: { pr_url: prUrl }
350
- };
351
- if (branchName) {
352
- updates.branch = branchName;
353
- }
354
-
355
- await this.posthogAPI.updateTaskRun(taskId, this.progressReporter.runId, updates);
356
- this.logger.debug('PR attached to task run', { taskId, runId: this.progressReporter.runId, prUrl });
435
+ const updates: any = {
436
+ output: { pr_url: prUrl },
437
+ };
438
+ if (branchName) {
439
+ updates.branch = branchName;
357
440
  }
358
441
 
359
- async updateTaskBranch(taskId: string, branchName: string): Promise<void> {
360
- this.logger.info('Updating task run branch', { taskId, branchName });
361
-
362
- if (!this.posthogAPI || !this.progressReporter.runId) {
363
- const error = new Error('PostHog API not configured or no active run. Cannot update branch.');
364
- this.logger.error('PostHog API not configured', error);
365
- throw error;
366
- }
367
-
368
- await this.posthogAPI.updateTaskRun(taskId, this.progressReporter.runId, { branch: branchName });
369
- this.logger.debug('Task run branch updated', { taskId, runId: this.progressReporter.runId, branchName });
442
+ await this.posthogAPI.updateTaskRun(
443
+ taskId,
444
+ this.progressReporter.runId,
445
+ updates,
446
+ );
447
+ this.logger.debug("PR attached to task run", {
448
+ taskId,
449
+ runId: this.progressReporter.runId,
450
+ prUrl,
451
+ });
452
+ }
453
+
454
+ async updateTaskBranch(taskId: string, branchName: string): Promise<void> {
455
+ this.logger.info("Updating task run branch", { taskId, branchName });
456
+
457
+ if (!this.posthogAPI || !this.progressReporter.runId) {
458
+ const error = new Error(
459
+ "PostHog API not configured or no active run. Cannot update branch.",
460
+ );
461
+ this.logger.error("PostHog API not configured", error);
462
+ throw error;
370
463
  }
371
464
 
372
- // Execution management
373
- cancelTask(taskId: string): void {
374
- // Find the execution for this task and cancel it
375
- for (const [executionId, execution] of this.taskManager['executionStates']) {
376
- if (execution.taskId === taskId && execution.status === 'running') {
377
- this.taskManager.cancelExecution(executionId);
378
- break;
379
- }
380
- }
465
+ await this.posthogAPI.updateTaskRun(taskId, this.progressReporter.runId, {
466
+ branch: branchName,
467
+ });
468
+ this.logger.debug("Task run branch updated", {
469
+ taskId,
470
+ runId: this.progressReporter.runId,
471
+ branchName,
472
+ });
473
+ }
474
+
475
+ // Execution management
476
+ cancelTask(taskId: string): void {
477
+ // Find the execution for this task and cancel it
478
+ for (const [executionId, execution] of this.taskManager.executionStates) {
479
+ if (execution.taskId === taskId && execution.status === "running") {
480
+ this.taskManager.cancelExecution(executionId);
481
+ break;
482
+ }
381
483
  }
382
-
383
- getTaskExecutionStatus(taskId: string): string | null {
384
- // Find the execution for this task
385
- for (const execution of this.taskManager['executionStates'].values()) {
386
- if (execution.taskId === taskId) {
387
- return execution.status;
388
- }
389
- }
390
- return null;
484
+ }
485
+
486
+ getTaskExecutionStatus(taskId: string): string | null {
487
+ // Find the execution for this task
488
+ for (const execution of this.taskManager.executionStates.values()) {
489
+ if (execution.taskId === taskId) {
490
+ return execution.status;
491
+ }
391
492
  }
392
-
393
- private async prepareTaskBranch(taskSlug: string, isCloudMode: boolean): Promise<void> {
394
- if (await this.gitManager.hasChanges()) {
395
- throw new Error('Cannot start task with uncommitted changes. Please commit or stash your changes first.');
396
- }
397
-
398
- await this.gitManager.resetToDefaultBranchIfNeeded();
399
-
400
- const existingBranch = await this.gitManager.getTaskBranch(taskSlug);
401
- if (!existingBranch) {
402
- const branchName = await this.gitManager.createTaskBranch(taskSlug);
403
- this.emitEvent(this.adapter.createStatusEvent('branch_created', { branch: branchName }));
404
-
405
- await this.gitManager.addAllPostHogFiles();
406
-
407
- // Only commit if there are changes or we're in cloud mode
408
- if (isCloudMode) {
409
- await this.gitManager.commitAndPush(`Initialize task ${taskSlug}`, { allowEmpty: true });
410
- } else {
411
- // Check if there are any changes before committing
412
- const hasChanges = await this.gitManager.hasStagedChanges();
413
- if (hasChanges) {
414
- await this.gitManager.commitChanges(`Initialize task ${taskSlug}`);
415
- }
416
- }
417
- } else {
418
- this.logger.info('Switching to existing task branch', { branch: existingBranch });
419
- await this.gitManager.switchToBranch(existingBranch);
420
- }
493
+ return null;
494
+ }
495
+
496
+ private async prepareTaskBranch(
497
+ taskSlug: string,
498
+ isCloudMode: boolean,
499
+ ): Promise<void> {
500
+ if (await this.gitManager.hasChanges()) {
501
+ throw new Error(
502
+ "Cannot start task with uncommitted changes. Please commit or stash your changes first.",
503
+ );
421
504
  }
422
505
 
423
- private ensureOpenAIGatewayEnv(gatewayUrl?: string, token?: string): void {
424
- const resolvedGatewayUrl = gatewayUrl || process.env.ANTHROPIC_BASE_URL;
425
- const resolvedToken = token || process.env.ANTHROPIC_AUTH_TOKEN;
506
+ await this.gitManager.resetToDefaultBranchIfNeeded();
426
507
 
427
- if (resolvedGatewayUrl) {
428
- process.env.OPENAI_BASE_URL = resolvedGatewayUrl;
429
- }
508
+ const existingBranch = await this.gitManager.getTaskBranch(taskSlug);
509
+ if (!existingBranch) {
510
+ const branchName = await this.gitManager.createTaskBranch(taskSlug);
511
+ this.emitEvent(
512
+ this.adapter.createStatusEvent("branch_created", {
513
+ branch: branchName,
514
+ }),
515
+ );
516
+
517
+ await this.gitManager.addAllPostHogFiles();
430
518
 
431
- if (resolvedToken) {
432
- process.env.OPENAI_API_KEY = resolvedToken;
519
+ // Only commit if there are changes or we're in cloud mode
520
+ if (isCloudMode) {
521
+ await this.gitManager.commitAndPush(`Initialize task ${taskSlug}`, {
522
+ allowEmpty: true,
523
+ });
524
+ } else {
525
+ // Check if there are any changes before committing
526
+ const hasChanges = await this.gitManager.hasStagedChanges();
527
+ if (hasChanges) {
528
+ await this.gitManager.commitChanges(`Initialize task ${taskSlug}`);
433
529
  }
530
+ }
531
+ } else {
532
+ this.logger.info("Switching to existing task branch", {
533
+ branch: existingBranch,
534
+ });
535
+ await this.gitManager.switchToBranch(existingBranch);
434
536
  }
537
+ }
435
538
 
436
- private async ensurePullRequest(task: Task, stepResults: Record<string, any>): Promise<void> {
437
- const latestRun = task.latest_run;
438
- const existingPr =
439
- latestRun?.output && typeof latestRun.output === 'object'
440
- ? (latestRun.output as any).pr_url
441
- : null;
539
+ private ensureOpenAIGatewayEnv(gatewayUrl?: string, token?: string): void {
540
+ const resolvedGatewayUrl = gatewayUrl || process.env.ANTHROPIC_BASE_URL;
541
+ const resolvedToken = token || process.env.ANTHROPIC_AUTH_TOKEN;
442
542
 
443
- if (existingPr) {
444
- this.logger.info('PR already exists, skipping creation', { taskId: task.id, prUrl: existingPr });
445
- return;
446
- }
543
+ if (resolvedGatewayUrl) {
544
+ process.env.OPENAI_BASE_URL = resolvedGatewayUrl;
545
+ }
447
546
 
448
- const buildResult = stepResults['build'];
449
- if (!buildResult?.commitCreated) {
450
- this.logger.warn('Build step did not produce a commit; skipping PR creation', { taskId: task.id });
451
- return;
452
- }
547
+ if (resolvedToken) {
548
+ process.env.OPENAI_API_KEY = resolvedToken;
549
+ }
550
+ }
551
+
552
+ private async ensurePullRequest(
553
+ task: Task,
554
+ stepResults: Record<string, any>,
555
+ ): Promise<void> {
556
+ const latestRun = task.latest_run;
557
+ const existingPr =
558
+ latestRun?.output && typeof latestRun.output === "object"
559
+ ? (latestRun.output as any).pr_url
560
+ : null;
561
+
562
+ if (existingPr) {
563
+ this.logger.info("PR already exists, skipping creation", {
564
+ taskId: task.id,
565
+ prUrl: existingPr,
566
+ });
567
+ return;
568
+ }
453
569
 
454
- const branchName = await this.gitManager.getCurrentBranch();
455
- const finalizeResult = stepResults['finalize'];
456
- const prBody = finalizeResult?.prBody;
457
-
458
- const prUrl = await this.createPullRequest(
459
- task.id,
460
- branchName,
461
- task.title,
462
- task.description ?? '',
463
- prBody
464
- );
465
-
466
- this.emitEvent(this.adapter.createStatusEvent('pr_created', { prUrl }));
467
-
468
- try {
469
- await this.attachPullRequestToTask(task.id, prUrl, branchName);
470
- this.logger.info('PR attached to task successfully', { taskId: task.id, prUrl });
471
- } catch (error) {
472
- this.logger.warn('Could not attach PR to task', {
473
- error: error instanceof Error ? error.message : String(error),
474
- });
475
- }
570
+ const buildResult = stepResults.build;
571
+ if (!buildResult?.commitCreated) {
572
+ this.logger.warn(
573
+ "Build step did not produce a commit; skipping PR creation",
574
+ { taskId: task.id },
575
+ );
576
+ return;
476
577
  }
477
578
 
478
- private emitEvent(event: any): void {
479
- if (this.debug && event.type !== 'token') {
480
- // Log all events except tokens (too verbose)
481
- this.logger.debug('Emitting event', { type: event.type, ts: event.ts });
482
- }
483
- const persistPromise = this.progressReporter.recordEvent(event);
484
- if (persistPromise && typeof persistPromise.then === 'function') {
485
- persistPromise.catch((error: Error) =>
486
- this.logger.debug('Failed to persist agent event', { message: error.message })
487
- );
488
- }
489
- this.onEvent?.(event);
579
+ const branchName = await this.gitManager.getCurrentBranch();
580
+ const finalizeResult = stepResults.finalize;
581
+ const prBody = finalizeResult?.prBody;
582
+
583
+ const prUrl = await this.createPullRequest(
584
+ task.id,
585
+ branchName,
586
+ task.title,
587
+ task.description ?? "",
588
+ prBody,
589
+ );
590
+
591
+ this.emitEvent(this.adapter.createStatusEvent("pr_created", { prUrl }));
592
+
593
+ try {
594
+ await this.attachPullRequestToTask(task.id, prUrl, branchName);
595
+ this.logger.info("PR attached to task successfully", {
596
+ taskId: task.id,
597
+ prUrl,
598
+ });
599
+ } catch (error) {
600
+ this.logger.warn("Could not attach PR to task", {
601
+ error: error instanceof Error ? error.message : String(error),
602
+ });
603
+ }
604
+ }
605
+
606
+ private emitEvent(event: any): void {
607
+ if (this.debug && event.type !== "token") {
608
+ // Log all events except tokens (too verbose)
609
+ this.logger.debug("Emitting event", { type: event.type, ts: event.ts });
610
+ }
611
+ const persistPromise = this.progressReporter.recordEvent(event);
612
+ if (persistPromise && typeof persistPromise.then === "function") {
613
+ persistPromise.catch((error: Error) =>
614
+ this.logger.debug("Failed to persist agent event", {
615
+ message: error.message,
616
+ }),
617
+ );
490
618
  }
619
+ this.onEvent?.(event);
620
+ }
491
621
  }
492
622
 
493
- export { PermissionMode } from './types.js';
494
- export type { Task, SupportingFile, ExecutionResult, AgentConfig } from './types.js';
623
+ export type {
624
+ AgentConfig,
625
+ ExecutionResult,
626
+ SupportingFile,
627
+ Task,
628
+ } from "./types.js";
629
+ export { PermissionMode } from "./types.js";