@posthog/agent 1.7.1 → 1.10.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 (54) hide show
  1. package/README.md +8 -5
  2. package/dist/index.d.ts +5 -1
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +2 -0
  5. package/dist/index.js.map +1 -1
  6. package/dist/src/adapters/claude/claude-adapter.d.ts +17 -0
  7. package/dist/src/adapters/claude/claude-adapter.d.ts.map +1 -0
  8. package/dist/src/{event-transformer.js → adapters/claude/claude-adapter.js} +34 -10
  9. package/dist/src/adapters/claude/claude-adapter.js.map +1 -0
  10. package/dist/src/adapters/claude/tool-mapper.d.ts +19 -0
  11. package/dist/src/adapters/claude/tool-mapper.d.ts.map +1 -0
  12. package/dist/src/adapters/claude/tool-mapper.js +44 -0
  13. package/dist/src/adapters/claude/tool-mapper.js.map +1 -0
  14. package/dist/src/adapters/types.d.ts +28 -0
  15. package/dist/src/adapters/types.d.ts.map +1 -0
  16. package/dist/src/agent.d.ts +1 -1
  17. package/dist/src/agent.d.ts.map +1 -1
  18. package/dist/src/agent.js +61 -44
  19. package/dist/src/agent.js.map +1 -1
  20. package/dist/src/posthog-api.d.ts +16 -57
  21. package/dist/src/posthog-api.d.ts.map +1 -1
  22. package/dist/src/posthog-api.js +38 -38
  23. package/dist/src/posthog-api.js.map +1 -1
  24. package/dist/src/stage-executor.d.ts +1 -1
  25. package/dist/src/stage-executor.d.ts.map +1 -1
  26. package/dist/src/stage-executor.js +7 -7
  27. package/dist/src/stage-executor.js.map +1 -1
  28. package/dist/src/task-progress-reporter.d.ts +2 -7
  29. package/dist/src/task-progress-reporter.d.ts.map +1 -1
  30. package/dist/src/task-progress-reporter.js +37 -55
  31. package/dist/src/task-progress-reporter.js.map +1 -1
  32. package/dist/src/tools/registry.d.ts +25 -0
  33. package/dist/src/tools/registry.d.ts.map +1 -0
  34. package/dist/src/tools/registry.js +120 -0
  35. package/dist/src/tools/registry.js.map +1 -0
  36. package/dist/src/tools/types.d.ts +80 -0
  37. package/dist/src/tools/types.d.ts.map +1 -0
  38. package/dist/src/types.d.ts +65 -15
  39. package/dist/src/types.d.ts.map +1 -1
  40. package/dist/src/types.js.map +1 -1
  41. package/package.json +1 -1
  42. package/src/{event-transformer.ts → adapters/claude/claude-adapter.ts} +40 -16
  43. package/src/adapters/claude/tool-mapper.ts +46 -0
  44. package/src/adapters/types.ts +31 -0
  45. package/src/agent.ts +64 -41
  46. package/src/posthog-api.ts +57 -92
  47. package/src/stage-executor.ts +11 -11
  48. package/src/task-progress-reporter.ts +38 -63
  49. package/src/tools/registry.ts +129 -0
  50. package/src/tools/types.ts +127 -0
  51. package/src/types.ts +73 -20
  52. package/dist/src/event-transformer.d.ts +0 -10
  53. package/dist/src/event-transformer.d.ts.map +0 -1
  54. package/dist/src/event-transformer.js.map +0 -1
package/src/agent.ts CHANGED
@@ -6,7 +6,8 @@ import { PostHogAPIClient } from './posthog-api.js';
6
6
  import { PostHogFileManager } from './file-manager.js';
7
7
  import { GitManager } from './git-manager.js';
8
8
  import { TemplateManager } from './template-manager.js';
9
- import { EventTransformer } from './event-transformer.js';
9
+ import { ClaudeAdapter } from './adapters/claude/claude-adapter.js';
10
+ import type { ProviderAdapter } from './adapters/types.js';
10
11
  import { PLANNING_SYSTEM_PROMPT } from './agents/planning.js';
11
12
  import { EXECUTION_SYSTEM_PROMPT } from './agents/execution.js';
12
13
  import { Logger } from './utils/logger.js';
@@ -24,7 +25,7 @@ export class Agent {
24
25
  private fileManager: PostHogFileManager;
25
26
  private gitManager: GitManager;
26
27
  private templateManager: TemplateManager;
27
- private eventTransformer: EventTransformer;
28
+ private adapter: ProviderAdapter;
28
29
  private logger: Logger;
29
30
  private agentRegistry: AgentRegistry;
30
31
  private workflowRegistry: WorkflowRegistry;
@@ -64,7 +65,8 @@ export class Agent {
64
65
  };
65
66
  this.logger = new Logger({ debug: this.debug, prefix: '[PostHog Agent]' });
66
67
  this.taskManager = new TaskManager();
67
- this.eventTransformer = new EventTransformer();
68
+ // Hardcode Claude adapter for now - extensible for other providers later
69
+ this.adapter = new ClaudeAdapter();
68
70
 
69
71
  this.fileManager = new PostHogFileManager(
70
72
  this.workingDirectory,
@@ -156,13 +158,8 @@ export class Agent {
156
158
  await this.posthogAPI.updateTask(task.id, { workflow: workflowId } as any);
157
159
  (task as any).workflow = workflowId;
158
160
  }
159
- if (!(task as any).current_stage && workflow.stages.length > 0) {
160
- const firstStage = [...workflow.stages].sort((a, b) => a.position - b.position)[0];
161
- await this.posthogAPI.updateTaskStage(task.id, firstStage.id);
162
- (task as any).current_stage = firstStage.id;
163
- }
164
161
  } catch (e) {
165
- this.logger.warn('Failed to sync task workflow/stage before execution', { error: (e as Error).message });
162
+ this.logger.warn('Failed to sync task workflow before execution', { error: (e as Error).message });
166
163
  }
167
164
  }
168
165
 
@@ -170,11 +167,21 @@ export class Agent {
170
167
  this.logger.info('Starting workflow execution', { taskId: task.id, workflowId, executionId });
171
168
  this.taskManager.startExecution(task.id, 'plan_and_build', executionId);
172
169
  await this.progressReporter.start(task.id, {
173
- workflowId,
174
- workflowRunId: executionId,
175
170
  totalSteps: orderedStages.length,
176
171
  });
177
172
 
173
+ // Set initial stage on the newly created run
174
+ const firstStage = orderedStages[0];
175
+ if (this.posthogAPI && this.progressReporter.runId && firstStage) {
176
+ try {
177
+ await this.posthogAPI.updateTaskRun(task.id, this.progressReporter.runId, {
178
+ current_stage: firstStage.id
179
+ });
180
+ } catch (e) {
181
+ this.logger.warn('Failed to set initial stage on run', { error: (e as Error).message });
182
+ }
183
+ }
184
+
178
185
  try {
179
186
  let startIndex = 0;
180
187
  const currentStageId = (task as any).current_stage as string | undefined;
@@ -185,7 +192,7 @@ export class Agent {
185
192
  const atLastStage = currIdx >= 0 && currIdx === orderedStages.length - 1;
186
193
  if (atLastStage) {
187
194
  const finalStageKey = orderedStages[currIdx]?.key;
188
- this.emitEvent(this.eventTransformer.createStatusEvent('no_next_stage', { stage: finalStageKey }));
195
+ this.emitEvent(this.adapter.createStatusEvent('no_next_stage', { stage: finalStageKey }));
189
196
  await this.progressReporter.noNextStage(finalStageKey);
190
197
  await this.progressReporter.complete();
191
198
  this.taskManager.completeExecution(executionId, { task, workflow });
@@ -198,11 +205,17 @@ export class Agent {
198
205
  if (idx >= 0) startIndex = idx;
199
206
  }
200
207
 
201
- // Align server-side stage when restarting from the beginning
202
- if (this.posthogAPI) {
208
+ // Align server-side stage when restarting from a different stage
209
+ if (this.posthogAPI && this.progressReporter.runId) {
203
210
  const targetStage = orderedStages[startIndex];
204
211
  if (targetStage && targetStage.id !== currentStageId) {
205
- try { await this.posthogAPI.updateTaskStage(task.id, targetStage.id); (task as any).current_stage = targetStage.id; } catch {}
212
+ try {
213
+ await this.posthogAPI.updateTaskRun(task.id, this.progressReporter.runId, {
214
+ current_stage: targetStage.id
215
+ });
216
+ } catch (e) {
217
+ this.logger.warn('Failed to update run stage', { error: (e as Error).message });
218
+ }
206
219
  }
207
220
  }
208
221
 
@@ -229,7 +242,7 @@ export class Agent {
229
242
  }
230
243
 
231
244
  async executeStage(task: Task, stage: WorkflowStage, options: WorkflowExecutionOptions = {}): Promise<void> {
232
- this.emitEvent(this.eventTransformer.createStatusEvent('stage_start', { stage: stage.key }));
245
+ this.emitEvent(this.adapter.createStatusEvent('stage_start', { stage: stage.key }));
233
246
  const overrides = options.stageOverrides?.[stage.key];
234
247
  const agentName = stage.agent_name || 'code_generation';
235
248
  const agentDef = this.agentRegistry.getAgent(agentName);
@@ -243,12 +256,12 @@ export class Agent {
243
256
  if (isPlanning && shouldCreatePlanningBranch) {
244
257
  const planningBranch = await this.createPlanningBranch(task.id);
245
258
  await this.updateTaskBranch(task.id, planningBranch);
246
- this.emitEvent(this.eventTransformer.createStatusEvent('branch_created', { stage: stage.key, branch: planningBranch }));
259
+ this.emitEvent(this.adapter.createStatusEvent('branch_created', { stage: stage.key, branch: planningBranch }));
247
260
  await this.progressReporter.branchCreated(stage.key, planningBranch);
248
261
  } else if (!isPlanning && !isManual && shouldCreateImplBranch) {
249
262
  const implBranch = await this.createImplementationBranch(task.id);
250
263
  await this.updateTaskBranch(task.id, implBranch);
251
- this.emitEvent(this.eventTransformer.createStatusEvent('branch_created', { stage: stage.key, branch: implBranch }));
264
+ this.emitEvent(this.adapter.createStatusEvent('branch_created', { stage: stage.key, branch: implBranch }));
252
265
  await this.progressReporter.branchCreated(stage.key, implBranch);
253
266
  }
254
267
 
@@ -257,7 +270,7 @@ export class Agent {
257
270
  if (result.plan) {
258
271
  await this.writePlan(task.id, result.plan);
259
272
  await this.commitPlan(task.id, task.title);
260
- this.emitEvent(this.eventTransformer.createStatusEvent('commit_made', { stage: stage.key, kind: 'plan' }));
273
+ this.emitEvent(this.adapter.createStatusEvent('commit_made', { stage: stage.key, kind: 'plan' }));
261
274
  await this.progressReporter.commitMade(stage.key, 'plan');
262
275
  }
263
276
 
@@ -272,19 +285,19 @@ export class Agent {
272
285
  const implBranch = await this.createImplementationBranch(task.id);
273
286
  await this.updateTaskBranch(task.id, implBranch);
274
287
  branchName = implBranch;
275
- this.emitEvent(this.eventTransformer.createStatusEvent('branch_created', { stage: stage.key, branch: implBranch }));
288
+ this.emitEvent(this.adapter.createStatusEvent('branch_created', { stage: stage.key, branch: implBranch }));
276
289
  await this.progressReporter.branchCreated(stage.key, implBranch);
277
290
  }
278
291
  try {
279
292
  const prUrl = await this.createPullRequest(task.id, branchName, task.title, task.description);
280
293
  await this.updateTaskBranch(task.id, branchName);
281
294
  await this.attachPullRequestToTask(task.id, prUrl, branchName);
282
- this.emitEvent(this.eventTransformer.createStatusEvent('pr_created', { stage: stage.key, prUrl }));
295
+ this.emitEvent(this.adapter.createStatusEvent('pr_created', { stage: stage.key, prUrl }));
283
296
  await this.progressReporter.pullRequestCreated(stage.key, prUrl);
284
297
  } catch {}
285
298
  }
286
299
  // Do not auto-progress on manual stages
287
- this.emitEvent(this.eventTransformer.createStatusEvent('stage_complete', { stage: stage.key }));
300
+ this.emitEvent(this.adapter.createStatusEvent('stage_complete', { stage: stage.key }));
288
301
  return;
289
302
  }
290
303
 
@@ -292,7 +305,7 @@ export class Agent {
292
305
  const existingPlan = await this.readPlan(task.id);
293
306
  const planSummary = existingPlan ? existingPlan.split('\n')[0] : undefined;
294
307
  await this.commitImplementation(task.id, task.title, planSummary);
295
- this.emitEvent(this.eventTransformer.createStatusEvent('commit_made', { stage: stage.key, kind: 'implementation' }));
308
+ this.emitEvent(this.adapter.createStatusEvent('commit_made', { stage: stage.key, kind: 'implementation' }));
296
309
  await this.progressReporter.commitMade(stage.key, 'implementation');
297
310
  }
298
311
 
@@ -306,27 +319,30 @@ export class Agent {
306
319
  const prUrl = await this.createPullRequest(task.id, branchName, task.title, task.description);
307
320
  await this.updateTaskBranch(task.id, branchName);
308
321
  await this.attachPullRequestToTask(task.id, prUrl, branchName);
309
- this.emitEvent(this.eventTransformer.createStatusEvent('pr_created', { stage: stage.key, prUrl }));
322
+ this.emitEvent(this.adapter.createStatusEvent('pr_created', { stage: stage.key, prUrl }));
310
323
  await this.progressReporter.pullRequestCreated(stage.key, prUrl);
311
324
  } catch {}
312
325
  }
313
326
  }
314
327
 
315
- this.emitEvent(this.eventTransformer.createStatusEvent('stage_complete', { stage: stage.key }));
328
+ this.emitEvent(this.adapter.createStatusEvent('stage_complete', { stage: stage.key }));
316
329
  }
317
330
 
318
331
  async progressToNextStage(taskId: string, currentStageKey?: string): Promise<void> {
319
- if (!this.posthogAPI) throw new Error('PostHog API not configured. Cannot progress stage.');
332
+ if (!this.posthogAPI || !this.progressReporter.runId) {
333
+ throw new Error('PostHog API not configured or no active run. Cannot progress stage.');
334
+ }
320
335
  try {
321
- await this.posthogAPI.progressTask(taskId, { auto: true });
336
+ await this.posthogAPI.progressTaskRun(taskId, this.progressReporter.runId);
322
337
  } catch (error) {
323
338
  if (error instanceof Error && error.message.includes('No next stage available')) {
324
- this.logger.warn('No next stage available when attempting to progress task', {
339
+ this.logger.warn('No next stage available when attempting to progress run', {
325
340
  taskId,
341
+ runId: this.progressReporter.runId,
326
342
  stage: currentStageKey,
327
343
  error: error.message,
328
344
  });
329
- this.emitEvent(this.eventTransformer.createStatusEvent('no_next_stage', { stage: currentStageKey }));
345
+ this.emitEvent(this.adapter.createStatusEvent('no_next_stage', { stage: currentStageKey }));
330
346
  await this.progressReporter.noNextStage(currentStageKey);
331
347
  return;
332
348
  }
@@ -354,9 +370,9 @@ export class Agent {
354
370
  for await (const message of response) {
355
371
  this.logger.debug('Received message in direct run', message);
356
372
  // Emit raw SDK event
357
- this.emitEvent(this.eventTransformer.createRawSDKEvent(message));
373
+ this.emitEvent(this.adapter.createRawSDKEvent(message));
358
374
  // Emit transformed event
359
- const transformedEvent = this.eventTransformer.transform(message);
375
+ const transformedEvent = this.adapter.transform(message);
360
376
  if (transformedEvent) {
361
377
  this.emitEvent(transformedEvent);
362
378
  }
@@ -477,29 +493,36 @@ Generated by PostHog Agent`;
477
493
  }
478
494
 
479
495
  async attachPullRequestToTask(taskId: string, prUrl: string, branchName?: string): Promise<void> {
480
- this.logger.info('Attaching PR to task', { taskId, prUrl, branchName });
496
+ this.logger.info('Attaching PR to task run', { taskId, prUrl, branchName });
481
497
 
482
- if (!this.posthogAPI) {
483
- const error = new Error('PostHog API not configured. Cannot attach PR to task.');
498
+ if (!this.posthogAPI || !this.progressReporter.runId) {
499
+ const error = new Error('PostHog API not configured or no active run. Cannot attach PR to task.');
484
500
  this.logger.error('PostHog API not configured', error);
485
501
  throw error;
486
502
  }
487
503
 
488
- await this.posthogAPI.attachTaskPullRequest(taskId, prUrl, branchName);
489
- this.logger.debug('PR attached to task', { taskId, prUrl });
504
+ const updates: any = {
505
+ output: { pr_url: prUrl }
506
+ };
507
+ if (branchName) {
508
+ updates.branch = branchName;
509
+ }
510
+
511
+ await this.posthogAPI.updateTaskRun(taskId, this.progressReporter.runId, updates);
512
+ this.logger.debug('PR attached to task run', { taskId, runId: this.progressReporter.runId, prUrl });
490
513
  }
491
514
 
492
515
  async updateTaskBranch(taskId: string, branchName: string): Promise<void> {
493
- this.logger.info('Updating task branch', { taskId, branchName });
516
+ this.logger.info('Updating task run branch', { taskId, branchName });
494
517
 
495
- if (!this.posthogAPI) {
496
- const error = new Error('PostHog API not configured. Cannot update task branch.');
518
+ if (!this.posthogAPI || !this.progressReporter.runId) {
519
+ const error = new Error('PostHog API not configured or no active run. Cannot update branch.');
497
520
  this.logger.error('PostHog API not configured', error);
498
521
  throw error;
499
522
  }
500
523
 
501
- await this.posthogAPI.setTaskBranch(taskId, branchName);
502
- this.logger.debug('Task branch updated', { taskId, branchName });
524
+ await this.posthogAPI.updateTaskRun(taskId, this.progressReporter.runId, { branch: branchName });
525
+ this.logger.debug('Task run branch updated', { taskId, runId: this.progressReporter.runId, branchName });
503
526
  }
504
527
 
505
528
  // Execution management
@@ -1,4 +1,4 @@
1
- import type { Task, SupportingFile, PostHogAPIConfig, PostHogResource, ResourceType, UrlMention } from './types.js';
1
+ import type { Task, TaskRun, LogEntry, SupportingFile, PostHogAPIConfig, PostHogResource, ResourceType, UrlMention } from './types.js';
2
2
  import type { WorkflowDefinition, AgentDefinition } from './workflow-types.js';
3
3
 
4
4
  interface PostHogApiResponse<T> {
@@ -8,52 +8,14 @@ interface PostHogApiResponse<T> {
8
8
  previous?: string | null;
9
9
  }
10
10
 
11
- interface TaskProgressResponse {
12
- has_progress: boolean;
13
- id?: string;
14
- status?: "started" | "in_progress" | "completed" | "failed";
15
- current_step?: string;
16
- completed_steps?: number;
17
- total_steps?: number;
18
- progress_percentage?: number;
19
- output_log?: string;
20
- error_message?: string;
21
- created_at?: string;
22
- updated_at?: string;
23
- completed_at?: string;
24
- workflow_id?: string;
25
- workflow_run_id?: string;
26
- message?: string;
27
- }
28
-
29
- export interface TaskProgressRecord {
30
- id: string;
31
- task: string;
32
- status: "started" | "in_progress" | "completed" | "failed";
33
- current_step?: string | null;
34
- completed_steps?: number | null;
35
- total_steps?: number | null;
36
- progress_percentage?: number | null;
37
- output_log?: string | null;
38
- error_message?: string | null;
39
- workflow_id?: string | null;
40
- workflow_run_id?: string | null;
41
- activity_id?: string | null;
42
- created_at: string;
43
- updated_at: string;
44
- completed_at?: string | null;
45
- }
46
-
47
- export interface TaskProgressUpdate {
48
- status?: TaskProgressRecord["status"];
49
- current_step?: string | null;
50
- completed_steps?: number | null;
51
- total_steps?: number | null;
52
- output_log?: string | null;
11
+ export interface TaskRunUpdate {
12
+ status?: TaskRun["status"];
13
+ branch?: string | null;
14
+ current_stage?: string | null;
15
+ log?: LogEntry[];
53
16
  error_message?: string | null;
54
- workflow_id?: string | null;
55
- workflow_run_id?: string | null;
56
- activity_id?: string | null;
17
+ output?: Record<string, unknown> | null;
18
+ state?: Record<string, unknown>;
57
19
  }
58
20
 
59
21
  export class PostHogAPIClient {
@@ -172,65 +134,76 @@ export class PostHogAPIClient {
172
134
  });
173
135
  }
174
136
 
175
- async updateTaskStage(taskId: string, stageId: string): Promise<Task> {
137
+ // TaskRun methods
138
+ async listTaskRuns(taskId: string): Promise<TaskRun[]> {
176
139
  const teamId = await this.getTeamId();
177
- return this.apiRequest<Task>(`/api/projects/${teamId}/tasks/${taskId}/update_stage/`, {
178
- method: 'PATCH',
179
- body: JSON.stringify({ current_stage: stageId }),
180
- });
140
+ const response = await this.apiRequest<PostHogApiResponse<TaskRun>>(
141
+ `/api/projects/${teamId}/tasks/${taskId}/runs/`
142
+ );
143
+ return response.results || [];
181
144
  }
182
145
 
183
- async setTaskBranch(taskId: string, branch: string): Promise<Task> {
146
+ async getTaskRun(taskId: string, runId: string): Promise<TaskRun> {
184
147
  const teamId = await this.getTeamId();
185
- return this.apiRequest<Task>(`/api/projects/${teamId}/tasks/${taskId}/set_branch/`, {
148
+ return this.apiRequest<TaskRun>(`/api/projects/${teamId}/tasks/${taskId}/runs/${runId}/`);
149
+ }
150
+
151
+ async createTaskRun(
152
+ taskId: string,
153
+ payload?: Partial<Omit<TaskRun, 'id' | 'task' | 'team' | 'created_at' | 'updated_at' | 'completed_at'>>
154
+ ): Promise<TaskRun> {
155
+ const teamId = await this.getTeamId();
156
+ return this.apiRequest<TaskRun>(`/api/projects/${teamId}/tasks/${taskId}/runs/`, {
186
157
  method: "POST",
187
- body: JSON.stringify({ branch }),
158
+ body: JSON.stringify(payload || {}),
188
159
  });
189
160
  }
190
161
 
191
- async attachTaskPullRequest(taskId: string, prUrl: string, branch?: string): Promise<Task> {
162
+ async updateTaskRun(
163
+ taskId: string,
164
+ runId: string,
165
+ payload: TaskRunUpdate
166
+ ): Promise<TaskRun> {
192
167
  const teamId = await this.getTeamId();
193
- const payload: Record<string, string> = { pr_url: prUrl };
194
- if (branch) {
195
- payload.branch = branch;
196
- }
197
- return this.apiRequest<Task>(`/api/projects/${teamId}/tasks/${taskId}/attach_pr/`, {
198
- method: "POST",
168
+ return this.apiRequest<TaskRun>(`/api/projects/${teamId}/tasks/${taskId}/runs/${runId}/`, {
169
+ method: "PATCH",
199
170
  body: JSON.stringify(payload),
200
171
  });
201
172
  }
202
173
 
203
- async getTaskProgress(taskId: string): Promise<TaskProgressResponse> {
174
+ async updateTaskRunStage(taskId: string, runId: string, stageId: string): Promise<TaskRun> {
204
175
  const teamId = await this.getTeamId();
205
- return this.apiRequest<TaskProgressResponse>(`/api/projects/${teamId}/tasks/${taskId}/progress/`);
176
+ return this.apiRequest<TaskRun>(`/api/projects/${teamId}/tasks/${taskId}/runs/${runId}/update_stage/`, {
177
+ method: 'PATCH',
178
+ body: JSON.stringify({ current_stage: stageId }),
179
+ });
206
180
  }
207
181
 
208
- async createTaskProgress(
209
- taskId: string,
210
- payload: TaskProgressUpdate & { status: TaskProgressRecord["status"] }
211
- ): Promise<TaskProgressRecord> {
182
+ async progressTaskRun(taskId: string, runId: string, nextStageId?: string): Promise<TaskRun> {
212
183
  const teamId = await this.getTeamId();
213
- return this.apiRequest<TaskProgressRecord>(`/api/projects/${teamId}/task_progress/`, {
214
- method: "POST",
215
- body: JSON.stringify({
216
- ...payload,
217
- task: taskId,
218
- }),
184
+ const payload: Record<string, string> = {};
185
+ if (nextStageId) {
186
+ payload.next_stage_id = nextStageId;
187
+ }
188
+ return this.apiRequest<TaskRun>(`/api/projects/${teamId}/tasks/${taskId}/runs/${runId}/progress_run/`, {
189
+ method: 'POST',
190
+ body: JSON.stringify(payload),
219
191
  });
220
192
  }
221
193
 
222
- async updateTaskProgress(
223
- taskId: string,
224
- progressId: string,
225
- payload: TaskProgressUpdate
226
- ): Promise<TaskProgressRecord> {
194
+ async setTaskRunOutput(taskId: string, runId: string, output: Record<string, unknown>): Promise<TaskRun> {
227
195
  const teamId = await this.getTeamId();
228
- return this.apiRequest<TaskProgressRecord>(`/api/projects/${teamId}/task_progress/${progressId}/`, {
229
- method: "PATCH",
230
- body: JSON.stringify({
231
- ...payload,
232
- task: taskId,
233
- }),
196
+ return this.apiRequest<TaskRun>(`/api/projects/${teamId}/tasks/${taskId}/runs/${runId}/set_output/`, {
197
+ method: 'PATCH',
198
+ body: JSON.stringify({ output }),
199
+ });
200
+ }
201
+
202
+ async appendTaskRunLog(taskId: string, runId: string, entries: LogEntry[]): Promise<TaskRun> {
203
+ const teamId = await this.getTeamId();
204
+ return this.apiRequest<TaskRun>(`/api/projects/${teamId}/tasks/${taskId}/runs/${runId}/append_log/`, {
205
+ method: 'POST',
206
+ body: JSON.stringify({ entries }),
234
207
  });
235
208
  }
236
209
 
@@ -251,14 +224,6 @@ export class PostHogAPIClient {
251
224
  return this.apiRequest<AgentDefinition[]>(`/api/agents/`);
252
225
  }
253
226
 
254
- async progressTask(taskId: string, options?: { next_stage_id?: string; auto?: boolean }): Promise<Task> {
255
- const teamId = await this.getTeamId();
256
- return this.apiRequest<Task>(`/api/projects/${teamId}/tasks/${taskId}/progress_task/`, {
257
- method: 'POST',
258
- body: JSON.stringify(options || {}),
259
- });
260
- }
261
-
262
227
  /**
263
228
  * Fetch error details from PostHog error tracking
264
229
  */
@@ -1,6 +1,6 @@
1
1
  import { query } from '@anthropic-ai/claude-agent-sdk';
2
2
  import { Logger } from './utils/logger.js';
3
- import { EventTransformer } from './event-transformer.js';
3
+ import { ClaudeAdapter } from './adapters/claude/claude-adapter.js';
4
4
  import { AgentRegistry } from './agent-registry.js';
5
5
  import type { AgentEvent, Task, McpServerConfig } from './types.js';
6
6
  import type { WorkflowStage, WorkflowStageExecutionResult, WorkflowExecutionOptions } from './workflow-types.js';
@@ -11,7 +11,7 @@ import { PromptBuilder } from './prompt-builder.js';
11
11
  export class StageExecutor {
12
12
  private registry: AgentRegistry;
13
13
  private logger: Logger;
14
- private eventTransformer: EventTransformer;
14
+ private adapter: ClaudeAdapter;
15
15
  private promptBuilder: PromptBuilder;
16
16
  private eventHandler?: (event: AgentEvent) => void;
17
17
  private mcpServers?: Record<string, McpServerConfig>;
@@ -25,7 +25,7 @@ export class StageExecutor {
25
25
  ) {
26
26
  this.registry = registry;
27
27
  this.logger = logger.child('StageExecutor');
28
- this.eventTransformer = new EventTransformer();
28
+ this.adapter = new ClaudeAdapter();
29
29
  this.promptBuilder = promptBuilder || new PromptBuilder({
30
30
  getTaskFiles: async () => [],
31
31
  generatePlanTemplate: async () => '',
@@ -96,17 +96,17 @@ export class StageExecutor {
96
96
  let plan = '';
97
97
  for await (const message of response) {
98
98
  // Emit raw SDK event first
99
- this.eventHandler?.(this.eventTransformer.createRawSDKEvent(message));
100
-
99
+ this.eventHandler?.(this.adapter.createRawSDKEvent(message));
100
+
101
101
  // Then emit transformed event
102
- const transformed = this.eventTransformer.transform(message);
102
+ const transformed = this.adapter.transform(message);
103
103
  if (transformed) {
104
104
  if (transformed.type !== 'token') {
105
105
  this.logger.debug('Planning event', { type: transformed.type });
106
106
  }
107
107
  this.eventHandler?.(transformed);
108
108
  }
109
-
109
+
110
110
  if (message.type === 'assistant' && message.message?.content) {
111
111
  for (const c of message.message.content) {
112
112
  if (c.type === 'text' && c.text) plan += c.text + '\n';
@@ -142,17 +142,17 @@ export class StageExecutor {
142
142
  const results: any[] = [];
143
143
  for await (const message of response) {
144
144
  // Emit raw SDK event first
145
- this.eventHandler?.(this.eventTransformer.createRawSDKEvent(message));
146
-
145
+ this.eventHandler?.(this.adapter.createRawSDKEvent(message));
146
+
147
147
  // Then emit transformed event
148
- const transformed = this.eventTransformer.transform(message);
148
+ const transformed = this.adapter.transform(message);
149
149
  if (transformed) {
150
150
  if (transformed.type !== 'token') {
151
151
  this.logger.debug('Execution event', { type: transformed.type });
152
152
  }
153
153
  this.eventHandler?.(transformed);
154
154
  }
155
-
155
+
156
156
  results.push(message);
157
157
  }
158
158
  return { results };