@posthog/agent 1.0.2 → 1.2.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.
- package/CLAUDE.md +68 -35
- package/README.md +46 -14
- package/dist/index.js +4 -5
- package/dist/index.js.map +1 -1
- package/dist/src/agent-registry.js +4 -2
- package/dist/src/agent-registry.js.map +1 -1
- package/dist/src/agent.d.ts +4 -1
- package/dist/src/agent.d.ts.map +1 -1
- package/dist/src/agent.js +45 -14
- package/dist/src/agent.js.map +1 -1
- package/dist/src/agents/execution.js +4 -2
- package/dist/src/agents/execution.js.map +1 -1
- package/dist/src/agents/planning.js +4 -2
- package/dist/src/agents/planning.js.map +1 -1
- package/dist/src/event-transformer.d.ts +2 -0
- package/dist/src/event-transformer.d.ts.map +1 -1
- package/dist/src/event-transformer.js +57 -7
- package/dist/src/event-transformer.js.map +1 -1
- package/dist/src/file-manager.js +17 -14
- package/dist/src/file-manager.js.map +1 -1
- package/dist/src/git-manager.js +5 -2
- package/dist/src/git-manager.js.map +1 -1
- package/dist/src/posthog-api.d.ts +34 -0
- package/dist/src/posthog-api.d.ts.map +1 -1
- package/dist/src/posthog-api.js +42 -2
- package/dist/src/posthog-api.js.map +1 -1
- package/dist/src/prompt-builder.js +5 -2
- package/dist/src/prompt-builder.js.map +1 -1
- package/dist/src/stage-executor.d.ts +4 -2
- package/dist/src/stage-executor.d.ts.map +1 -1
- package/dist/src/stage-executor.js +22 -9
- package/dist/src/stage-executor.js.map +1 -1
- package/dist/src/task-manager.js +5 -2
- package/dist/src/task-manager.js.map +1 -1
- package/dist/src/task-progress-reporter.d.ts +44 -0
- package/dist/src/task-progress-reporter.d.ts.map +1 -0
- package/dist/src/task-progress-reporter.js +234 -0
- package/dist/src/task-progress-reporter.js.map +1 -0
- package/dist/src/template-manager.d.ts.map +1 -1
- package/dist/src/template-manager.js +16 -6
- package/dist/src/template-manager.js.map +1 -1
- package/dist/src/types.js +4 -2
- package/dist/src/types.js.map +1 -1
- package/dist/src/utils/logger.js +5 -3
- package/dist/src/utils/logger.js.map +1 -1
- package/dist/src/utils/mcp.js +4 -2
- package/dist/src/utils/mcp.js.map +1 -1
- package/dist/src/workflow-registry.js +4 -3
- package/dist/src/workflow-registry.js.map +1 -1
- package/dist/templates/plan-template.md +45 -0
- package/package.json +8 -2
- package/src/agent.ts +41 -8
- package/src/event-transformer.ts +61 -7
- package/src/posthog-api.ts +79 -0
- package/src/stage-executor.ts +24 -8
- package/src/task-progress-reporter.ts +287 -0
- package/src/template-manager.ts +11 -3
- package/dist/example.js +0 -49
- package/dist/example.js.map +0 -1
- package/dist/src/workflow-types.js +0 -2
- package/dist/src/workflow-types.js.map +0 -1
package/CLAUDE.md
CHANGED
|
@@ -114,16 +114,43 @@ const task = await agent.fetchTask("task_abc123");
|
|
|
114
114
|
const result = await agent.runTask(task, ExecutionMode.PLAN_AND_BUILD);
|
|
115
115
|
```
|
|
116
116
|
|
|
117
|
-
###
|
|
117
|
+
### Progress Updates
|
|
118
118
|
```typescript
|
|
119
|
-
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
}
|
|
119
|
+
const posthogClient = agent.getPostHogClient();
|
|
120
|
+
const poller = setInterval(async () => {
|
|
121
|
+
const progress = await posthogClient?.getTaskProgress(taskId);
|
|
122
|
+
if (progress?.has_progress) {
|
|
123
|
+
updateUI(progress.status, progress.current_step, progress.completed_steps, progress.total_steps);
|
|
124
|
+
}
|
|
125
|
+
}, 3000);
|
|
126
|
+
|
|
127
|
+
try {
|
|
128
|
+
await agent.runWorkflow(taskId, workflowId, {
|
|
129
|
+
repositoryPath: selectedRepoPath,
|
|
130
|
+
permissionMode: PermissionMode.DEFAULT,
|
|
131
|
+
autoProgress: true,
|
|
132
|
+
});
|
|
133
|
+
} finally {
|
|
134
|
+
clearInterval(poller);
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
> The agent still emits transformed events via the `onEvent` callback, so UI layers can combine streaming updates with periodic polling if desired.
|
|
125
139
|
|
|
126
|
-
|
|
140
|
+
```typescript
|
|
141
|
+
// Handle the hook provided when constructing the Agent
|
|
142
|
+
import type { AgentEvent } from '@posthog/agent';
|
|
143
|
+
|
|
144
|
+
private handleLiveEvent(event: AgentEvent) {
|
|
145
|
+
switch (event.type) {
|
|
146
|
+
case 'status':
|
|
147
|
+
this.updateUI(event.phase, event.stage);
|
|
148
|
+
break;
|
|
149
|
+
case 'error':
|
|
150
|
+
this.showError(event.message);
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
127
154
|
```
|
|
128
155
|
|
|
129
156
|
### Working with Task Files
|
|
@@ -212,10 +239,11 @@ await agent.writeTaskFile(task.id, "requirements.md",
|
|
|
212
239
|
"context"
|
|
213
240
|
);
|
|
214
241
|
|
|
215
|
-
// 4. Execute with PLAN_AND_BUILD mode
|
|
216
|
-
const result = await agent.
|
|
242
|
+
// 4. Execute with PLAN_AND_BUILD mode and rely on PostHog polling for progress
|
|
243
|
+
const result = await agent.runWorkflow(task.id, workflowId, {
|
|
244
|
+
repositoryPath: "/path/to/repo",
|
|
217
245
|
permissionMode: PermissionMode.DEFAULT,
|
|
218
|
-
|
|
246
|
+
autoProgress: true,
|
|
219
247
|
});
|
|
220
248
|
|
|
221
249
|
// 5. Review results
|
|
@@ -227,31 +255,36 @@ console.log("Plan location:", `.posthog/${task.id}/plan.md`);
|
|
|
227
255
|
### Array App Integration Pattern
|
|
228
256
|
|
|
229
257
|
```typescript
|
|
230
|
-
// How Array app uses the SDK
|
|
231
258
|
class ArrayTaskExecution {
|
|
232
|
-
async executeTask(taskId: string,
|
|
233
|
-
const
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
259
|
+
async executeTask(taskId: string, workflowId: string, repoPath: string) {
|
|
260
|
+
const poller = setInterval(() => this.pollProgress(taskId), 3000);
|
|
261
|
+
try {
|
|
262
|
+
await this.agent.runWorkflow(taskId, workflowId, {
|
|
263
|
+
repositoryPath: repoPath,
|
|
264
|
+
permissionMode: PermissionMode.DEFAULT,
|
|
265
|
+
autoProgress: true,
|
|
266
|
+
});
|
|
267
|
+
} finally {
|
|
268
|
+
clearInterval(poller);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
this.showBranchesForReview(taskId);
|
|
242
272
|
}
|
|
243
|
-
|
|
244
|
-
private
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
273
|
+
|
|
274
|
+
private async pollProgress(taskId: string) {
|
|
275
|
+
const client = this.agent.getPostHogClient();
|
|
276
|
+
if (!client) {
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
const progress = await client.getTaskProgress(taskId);
|
|
281
|
+
if (progress.has_progress) {
|
|
282
|
+
this.updateProgressBar({
|
|
283
|
+
status: progress.status,
|
|
284
|
+
currentStep: progress.current_step,
|
|
285
|
+
completed: progress.completed_steps,
|
|
286
|
+
total: progress.total_steps,
|
|
287
|
+
});
|
|
255
288
|
}
|
|
256
289
|
}
|
|
257
290
|
}
|
|
@@ -293,4 +326,4 @@ try {
|
|
|
293
326
|
- **File I/O**: Efficient `.posthog/` folder management with minimal disk usage
|
|
294
327
|
- **API Calls**: Cached PostHog task data to minimize network requests
|
|
295
328
|
- **Event Streaming**: Real-time updates without blocking execution
|
|
296
|
-
- **Template Processing**: Lazy-loaded templates with variable substitution
|
|
329
|
+
- **Template Processing**: Lazy-loaded templates with variable substitution
|
package/README.md
CHANGED
|
@@ -15,17 +15,24 @@ bun run example
|
|
|
15
15
|
- **PostHog Integration**: Fetches existing tasks from PostHog API
|
|
16
16
|
- **Configurable Workflows**: Execute tasks via PostHog-defined or local workflows
|
|
17
17
|
- **Branch Management**: Automatic branch creation for planning and implementation
|
|
18
|
-
- **
|
|
18
|
+
- **Progress Tracking**: Execution status stored in PostHog `TaskProgress` records for easy polling
|
|
19
19
|
|
|
20
20
|
## Usage
|
|
21
21
|
|
|
22
22
|
```typescript
|
|
23
23
|
import { Agent, PermissionMode } from '@posthog/agent';
|
|
24
|
+
import type { AgentEvent } from '@posthog/agent';
|
|
24
25
|
|
|
25
26
|
const agent = new Agent({
|
|
26
27
|
workingDirectory: "/path/to/repo",
|
|
27
28
|
posthogApiUrl: "https://app.posthog.com",
|
|
28
|
-
posthogApiKey: process.env.POSTHOG_API_KEY
|
|
29
|
+
posthogApiKey: process.env.POSTHOG_API_KEY,
|
|
30
|
+
onEvent: (event) => {
|
|
31
|
+
// Streamed updates for responsive UIs
|
|
32
|
+
if (event.type !== 'token') {
|
|
33
|
+
handleLiveEvent(event);
|
|
34
|
+
}
|
|
35
|
+
},
|
|
29
36
|
});
|
|
30
37
|
|
|
31
38
|
// Run by workflow
|
|
@@ -78,22 +85,47 @@ your-repo/
|
|
|
78
85
|
└── (your code)
|
|
79
86
|
```
|
|
80
87
|
|
|
81
|
-
##
|
|
88
|
+
## Progress Updates
|
|
89
|
+
|
|
90
|
+
Progress for each task execution is persisted to PostHog's `TaskProgress` model, so UIs can poll for updates without relying on streaming hooks:
|
|
82
91
|
|
|
83
92
|
```typescript
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
switch (event.type) {
|
|
89
|
-
case 'status': updateProgress(event.data); break;
|
|
90
|
-
case 'file_write': showFileChange(event.data); break;
|
|
91
|
-
case 'done': showCompletion(); break;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
93
|
+
const agent = new Agent({
|
|
94
|
+
workingDirectory: repoPath,
|
|
95
|
+
posthogApiUrl: "https://app.posthog.com",
|
|
96
|
+
posthogApiKey: process.env.POSTHOG_KEY,
|
|
94
97
|
});
|
|
98
|
+
|
|
99
|
+
const poller = setInterval(async () => {
|
|
100
|
+
const progress = await agent.getPostHogClient()?.getTaskProgress(taskId);
|
|
101
|
+
if (progress?.has_progress) {
|
|
102
|
+
renderProgress(progress.status, progress.current_step, progress.completed_steps, progress.total_steps);
|
|
103
|
+
}
|
|
104
|
+
}, 3000);
|
|
105
|
+
|
|
106
|
+
try {
|
|
107
|
+
await agent.runWorkflow(taskId, workflowId, { repositoryPath: repoPath });
|
|
108
|
+
} finally {
|
|
109
|
+
clearInterval(poller);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Live stream still available through the onEvent hook
|
|
113
|
+
function handleLiveEvent(event: AgentEvent) {
|
|
114
|
+
switch (event.type) {
|
|
115
|
+
case 'status':
|
|
116
|
+
// optimistic UI update
|
|
117
|
+
break;
|
|
118
|
+
case 'error':
|
|
119
|
+
notifyError(event.message);
|
|
120
|
+
break;
|
|
121
|
+
default:
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
95
125
|
```
|
|
96
126
|
|
|
127
|
+
> Prefer streaming updates? Pass an `onEvent` handler when constructing the agent to keep receiving real-time events while progress is also written to PostHog.
|
|
128
|
+
|
|
97
129
|
## Requirements
|
|
98
130
|
|
|
99
131
|
- Bun runtime
|
|
@@ -139,4 +171,4 @@ await agent.runWorkflow(taskId, workflowId, {
|
|
|
139
171
|
});
|
|
140
172
|
```
|
|
141
173
|
|
|
142
|
-
Precedence for query options: base defaults in the SDK < global `queryOverrides` < per-stage `stageOverrides[stageKey].queryOverrides`.
|
|
174
|
+
Precedence for query options: base defaults in the SDK < global `queryOverrides` < per-stage `stageOverrides[stageKey].queryOverrides`.
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
export {
|
|
3
|
-
export {
|
|
4
|
-
|
|
5
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
export { Agent } from './src/agent.js';
|
|
2
|
+
export { PermissionMode } from './src/types.js';
|
|
3
|
+
export { LogLevel, Logger } from './src/utils/logger.js';
|
|
4
|
+
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
class AgentRegistry {
|
|
2
2
|
agentsByName = new Map();
|
|
3
3
|
constructor(definitions) {
|
|
4
4
|
if (definitions) {
|
|
@@ -51,4 +51,6 @@ export class AgentRegistry {
|
|
|
51
51
|
return this.listAgents().map(({ id, name, agent_type, description }) => ({ id, name, agent_type, description }));
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
|
-
|
|
54
|
+
|
|
55
|
+
export { AgentRegistry };
|
|
56
|
+
//# sourceMappingURL=agent-registry.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-registry.js","
|
|
1
|
+
{"version":3,"file":"agent-registry.js","sources":["../../src/agent-registry.ts"],"sourcesContent":["import type { AgentDefinition, AgentType } from './workflow-types.js';\n\nexport class AgentRegistry {\n private agentsByName: Map<string, AgentDefinition> = new Map();\n\n constructor(definitions?: AgentDefinition[]) {\n if (definitions) {\n for (const def of definitions) this.register(def);\n } else {\n for (const def of AgentRegistry.getDefaultAgents()) this.register(def);\n }\n }\n\n static getDefaultAgents(): AgentDefinition[] {\n return [\n {\n id: 'planning_basic',\n name: 'planning_basic',\n agent_type: 'planning',\n description: 'Analyze repo and produce implementation plan',\n },\n {\n id: 'code_generation',\n name: 'code_generation',\n agent_type: 'execution',\n description: 'Implements code changes using Claude SDK',\n },\n {\n id: 'review_basic',\n name: 'review_basic',\n agent_type: 'review',\n description: 'Reviews changes and suggests fixes',\n },\n {\n id: 'testing_basic',\n name: 'testing_basic',\n agent_type: 'testing',\n description: 'Runs tests and reports results',\n },\n ];\n }\n\n register(def: AgentDefinition): void {\n this.agentsByName.set(def.name, def);\n }\n\n getAgent(name: string): AgentDefinition | undefined {\n return this.agentsByName.get(name);\n }\n\n listAgents(): AgentDefinition[] {\n return Array.from(this.agentsByName.values());\n }\n\n exportForPostHog(): { id: string; name: string; agent_type: AgentType; description?: string }[] {\n return this.listAgents().map(({ id, name, agent_type, description }) => ({ id, name, agent_type, description }));\n }\n}\n\n"],"names":[],"mappings":"MAEa,aAAa,CAAA;AAChB,IAAA,YAAY,GAAiC,IAAI,GAAG,EAAE;AAE9D,IAAA,WAAA,CAAY,WAA+B,EAAA;QACzC,IAAI,WAAW,EAAE;YACf,KAAK,MAAM,GAAG,IAAI,WAAW;AAAE,gBAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QACnD;aAAO;AACL,YAAA,KAAK,MAAM,GAAG,IAAI,aAAa,CAAC,gBAAgB,EAAE;AAAE,gBAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QACxE;IACF;AAEA,IAAA,OAAO,gBAAgB,GAAA;QACrB,OAAO;AACL,YAAA;AACE,gBAAA,EAAE,EAAE,gBAAgB;AACpB,gBAAA,IAAI,EAAE,gBAAgB;AACtB,gBAAA,UAAU,EAAE,UAAU;AACtB,gBAAA,WAAW,EAAE,8CAA8C;AAC5D,aAAA;AACD,YAAA;AACE,gBAAA,EAAE,EAAE,iBAAiB;AACrB,gBAAA,IAAI,EAAE,iBAAiB;AACvB,gBAAA,UAAU,EAAE,WAAW;AACvB,gBAAA,WAAW,EAAE,0CAA0C;AACxD,aAAA;AACD,YAAA;AACE,gBAAA,EAAE,EAAE,cAAc;AAClB,gBAAA,IAAI,EAAE,cAAc;AACpB,gBAAA,UAAU,EAAE,QAAQ;AACpB,gBAAA,WAAW,EAAE,oCAAoC;AAClD,aAAA;AACD,YAAA;AACE,gBAAA,EAAE,EAAE,eAAe;AACnB,gBAAA,IAAI,EAAE,eAAe;AACrB,gBAAA,UAAU,EAAE,SAAS;AACrB,gBAAA,WAAW,EAAE,gCAAgC;AAC9C,aAAA;SACF;IACH;AAEA,IAAA,QAAQ,CAAC,GAAoB,EAAA;QAC3B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC;IACtC;AAEA,IAAA,QAAQ,CAAC,IAAY,EAAA;QACnB,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC;IACpC;IAEA,UAAU,GAAA;QACR,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC;IAC/C;IAEA,gBAAgB,GAAA;AACd,QAAA,OAAO,IAAI,CAAC,UAAU,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC,CAAC;IAClH;AACD;;;;"}
|
package/dist/src/agent.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Task, ExecutionResult, AgentConfig } from './types.js';
|
|
2
2
|
import type { WorkflowDefinition, WorkflowStage, WorkflowExecutionOptions } from './workflow-types.js';
|
|
3
|
+
import { PostHogAPIClient } from './posthog-api.js';
|
|
3
4
|
export declare class Agent {
|
|
4
5
|
private workingDirectory;
|
|
5
6
|
private onEvent?;
|
|
@@ -13,6 +14,7 @@ export declare class Agent {
|
|
|
13
14
|
private agentRegistry;
|
|
14
15
|
private workflowRegistry;
|
|
15
16
|
private stageExecutor;
|
|
17
|
+
private progressReporter;
|
|
16
18
|
debug: boolean;
|
|
17
19
|
constructor(config?: AgentConfig);
|
|
18
20
|
/**
|
|
@@ -31,6 +33,7 @@ export declare class Agent {
|
|
|
31
33
|
queryOverrides?: Record<string, any>;
|
|
32
34
|
}): Promise<ExecutionResult>;
|
|
33
35
|
fetchTask(taskId: string): Promise<Task>;
|
|
36
|
+
getPostHogClient(): PostHogAPIClient | undefined;
|
|
34
37
|
listTasks(filters?: {
|
|
35
38
|
repository?: string;
|
|
36
39
|
organization?: string;
|
|
@@ -48,7 +51,7 @@ export declare class Agent {
|
|
|
48
51
|
createImplementationBranch(taskId: string, planningBranchName?: string): Promise<string>;
|
|
49
52
|
commitImplementation(taskId: string, taskTitle: string, planSummary?: string): Promise<string>;
|
|
50
53
|
createPullRequest(taskId: string, branchName: string, taskTitle: string, taskDescription: string): Promise<string>;
|
|
51
|
-
attachPullRequestToTask(taskId: string, prUrl: string): Promise<void>;
|
|
54
|
+
attachPullRequestToTask(taskId: string, prUrl: string, branchName?: string): Promise<void>;
|
|
52
55
|
updateTaskBranch(taskId: string, branchName: string): Promise<void>;
|
|
53
56
|
cancelTask(taskId: string): void;
|
|
54
57
|
getTaskExecutionStatus(taskId: string): string | null;
|
package/dist/src/agent.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/agent.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,eAAe,EAAc,WAAW,EAAE,MAAM,YAAY,CAAC;AACjF,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/agent.ts"],"names":[],"mappings":"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"}
|
package/dist/src/agent.js
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
|
-
import { query } from
|
|
1
|
+
import { query } from '@anthropic-ai/claude-agent-sdk';
|
|
2
2
|
import { TaskManager } from './task-manager.js';
|
|
3
3
|
import { PostHogAPIClient } from './posthog-api.js';
|
|
4
4
|
import { PostHogFileManager } from './file-manager.js';
|
|
5
5
|
import { GitManager } from './git-manager.js';
|
|
6
6
|
import { TemplateManager } from './template-manager.js';
|
|
7
7
|
import { EventTransformer } from './event-transformer.js';
|
|
8
|
-
import { PLANNING_SYSTEM_PROMPT } from './agents/planning.js';
|
|
9
|
-
import { EXECUTION_SYSTEM_PROMPT } from './agents/execution.js';
|
|
10
8
|
import { Logger } from './utils/logger.js';
|
|
11
9
|
import { AgentRegistry } from './agent-registry.js';
|
|
12
10
|
import { WorkflowRegistry } from './workflow-registry.js';
|
|
13
11
|
import { StageExecutor } from './stage-executor.js';
|
|
14
12
|
import { PromptBuilder } from './prompt-builder.js';
|
|
15
|
-
|
|
13
|
+
import { TaskProgressReporter } from './task-progress-reporter.js';
|
|
14
|
+
export { PermissionMode } from './types.js';
|
|
15
|
+
|
|
16
|
+
class Agent {
|
|
16
17
|
workingDirectory;
|
|
17
18
|
onEvent;
|
|
18
19
|
taskManager;
|
|
@@ -25,6 +26,7 @@ export class Agent {
|
|
|
25
26
|
agentRegistry;
|
|
26
27
|
workflowRegistry;
|
|
27
28
|
stageExecutor;
|
|
29
|
+
progressReporter;
|
|
28
30
|
debug;
|
|
29
31
|
constructor(config = {}) {
|
|
30
32
|
this.workingDirectory = config.workingDirectory || process.cwd();
|
|
@@ -54,6 +56,8 @@ export class Agent {
|
|
|
54
56
|
logger: this.logger.child('PromptBuilder')
|
|
55
57
|
});
|
|
56
58
|
this.stageExecutor = new StageExecutor(this.agentRegistry, this.logger, promptBuilder);
|
|
59
|
+
this.stageExecutor.setEventHandler((event) => this.emitEvent(event));
|
|
60
|
+
this.progressReporter = new TaskProgressReporter(this.posthogAPI, this.logger);
|
|
57
61
|
}
|
|
58
62
|
/**
|
|
59
63
|
* Enable or disable debug logging
|
|
@@ -70,6 +74,7 @@ export class Agent {
|
|
|
70
74
|
if (!workflow) {
|
|
71
75
|
throw new Error(`Workflow ${workflowId} not found`);
|
|
72
76
|
}
|
|
77
|
+
const orderedStages = [...workflow.stages].sort((a, b) => a.position - b.position);
|
|
73
78
|
// Ensure task is assigned to workflow and positioned at first stage
|
|
74
79
|
if (this.posthogAPI) {
|
|
75
80
|
try {
|
|
@@ -90,8 +95,12 @@ export class Agent {
|
|
|
90
95
|
const executionId = this.taskManager.generateExecutionId();
|
|
91
96
|
this.logger.info('Starting workflow execution', { taskId: task.id, workflowId, executionId });
|
|
92
97
|
this.taskManager.startExecution(task.id, 'plan_and_build', executionId);
|
|
98
|
+
await this.progressReporter.start(task.id, {
|
|
99
|
+
workflowId,
|
|
100
|
+
workflowRunId: executionId,
|
|
101
|
+
totalSteps: orderedStages.length,
|
|
102
|
+
});
|
|
93
103
|
try {
|
|
94
|
-
const orderedStages = [...workflow.stages].sort((a, b) => a.position - b.position);
|
|
95
104
|
let startIndex = 0;
|
|
96
105
|
const currentStageId = task.current_stage;
|
|
97
106
|
// If task is already at the last stage, fail gracefully without progressing
|
|
@@ -99,7 +108,10 @@ export class Agent {
|
|
|
99
108
|
const currIdx = orderedStages.findIndex(s => s.id === currentStageId);
|
|
100
109
|
const atLastStage = currIdx >= 0 && currIdx === orderedStages.length - 1;
|
|
101
110
|
if (atLastStage) {
|
|
102
|
-
|
|
111
|
+
const finalStageKey = orderedStages[currIdx]?.key;
|
|
112
|
+
this.emitEvent(this.eventTransformer.createStatusEvent('no_next_stage', { stage: finalStageKey }));
|
|
113
|
+
await this.progressReporter.noNextStage(finalStageKey);
|
|
114
|
+
await this.progressReporter.complete();
|
|
103
115
|
this.taskManager.completeExecution(executionId, { task, workflow });
|
|
104
116
|
return { task, workflow };
|
|
105
117
|
}
|
|
@@ -122,7 +134,9 @@ export class Agent {
|
|
|
122
134
|
}
|
|
123
135
|
for (let i = startIndex; i < orderedStages.length; i++) {
|
|
124
136
|
const stage = orderedStages[i];
|
|
137
|
+
await this.progressReporter.stageStarted(stage.key, i);
|
|
125
138
|
await this.executeStage(task, stage, options);
|
|
139
|
+
await this.progressReporter.stageCompleted(stage.key, i + 1);
|
|
126
140
|
if (options.autoProgress) {
|
|
127
141
|
const hasNext = i < orderedStages.length - 1;
|
|
128
142
|
if (hasNext) {
|
|
@@ -130,10 +144,12 @@ export class Agent {
|
|
|
130
144
|
}
|
|
131
145
|
}
|
|
132
146
|
}
|
|
147
|
+
await this.progressReporter.complete();
|
|
133
148
|
this.taskManager.completeExecution(executionId, { task, workflow });
|
|
134
149
|
return { task, workflow };
|
|
135
150
|
}
|
|
136
151
|
catch (error) {
|
|
152
|
+
await this.progressReporter.fail(error);
|
|
137
153
|
this.taskManager.failExecution(executionId, error);
|
|
138
154
|
throw error;
|
|
139
155
|
}
|
|
@@ -153,17 +169,20 @@ export class Agent {
|
|
|
153
169
|
const planningBranch = await this.createPlanningBranch(task.id);
|
|
154
170
|
await this.updateTaskBranch(task.id, planningBranch);
|
|
155
171
|
this.emitEvent(this.eventTransformer.createStatusEvent('branch_created', { stage: stage.key, branch: planningBranch }));
|
|
172
|
+
await this.progressReporter.branchCreated(stage.key, planningBranch);
|
|
156
173
|
}
|
|
157
174
|
else if (!isPlanning && !isManual && shouldCreateImplBranch) {
|
|
158
175
|
const implBranch = await this.createImplementationBranch(task.id);
|
|
159
176
|
await this.updateTaskBranch(task.id, implBranch);
|
|
160
177
|
this.emitEvent(this.eventTransformer.createStatusEvent('branch_created', { stage: stage.key, branch: implBranch }));
|
|
178
|
+
await this.progressReporter.branchCreated(stage.key, implBranch);
|
|
161
179
|
}
|
|
162
180
|
const result = await this.stageExecutor.execute(task, stage, options);
|
|
163
181
|
if (result.plan) {
|
|
164
182
|
await this.writePlan(task.id, result.plan);
|
|
165
183
|
await this.commitPlan(task.id, task.title);
|
|
166
184
|
this.emitEvent(this.eventTransformer.createStatusEvent('commit_made', { stage: stage.key, kind: 'plan' }));
|
|
185
|
+
await this.progressReporter.commitMade(stage.key, 'plan');
|
|
167
186
|
}
|
|
168
187
|
if (isManual) {
|
|
169
188
|
const defaultOpenPR = true; // manual stages default to PR for review
|
|
@@ -177,12 +196,14 @@ export class Agent {
|
|
|
177
196
|
await this.updateTaskBranch(task.id, implBranch);
|
|
178
197
|
branchName = implBranch;
|
|
179
198
|
this.emitEvent(this.eventTransformer.createStatusEvent('branch_created', { stage: stage.key, branch: implBranch }));
|
|
199
|
+
await this.progressReporter.branchCreated(stage.key, implBranch);
|
|
180
200
|
}
|
|
181
201
|
try {
|
|
182
202
|
const prUrl = await this.createPullRequest(task.id, branchName, task.title, task.description);
|
|
183
203
|
await this.updateTaskBranch(task.id, branchName);
|
|
184
|
-
await this.attachPullRequestToTask(task.id, prUrl);
|
|
204
|
+
await this.attachPullRequestToTask(task.id, prUrl, branchName);
|
|
185
205
|
this.emitEvent(this.eventTransformer.createStatusEvent('pr_created', { stage: stage.key, prUrl }));
|
|
206
|
+
await this.progressReporter.pullRequestCreated(stage.key, prUrl);
|
|
186
207
|
}
|
|
187
208
|
catch { }
|
|
188
209
|
}
|
|
@@ -195,6 +216,7 @@ export class Agent {
|
|
|
195
216
|
const planSummary = existingPlan ? existingPlan.split('\n')[0] : undefined;
|
|
196
217
|
await this.commitImplementation(task.id, task.title, planSummary);
|
|
197
218
|
this.emitEvent(this.eventTransformer.createStatusEvent('commit_made', { stage: stage.key, kind: 'implementation' }));
|
|
219
|
+
await this.progressReporter.commitMade(stage.key, 'implementation');
|
|
198
220
|
}
|
|
199
221
|
// PR creation on complete stage (or if explicitly requested), regardless of whether edits occurred
|
|
200
222
|
{
|
|
@@ -205,8 +227,9 @@ export class Agent {
|
|
|
205
227
|
try {
|
|
206
228
|
const prUrl = await this.createPullRequest(task.id, branchName, task.title, task.description);
|
|
207
229
|
await this.updateTaskBranch(task.id, branchName);
|
|
208
|
-
await this.attachPullRequestToTask(task.id, prUrl);
|
|
230
|
+
await this.attachPullRequestToTask(task.id, prUrl, branchName);
|
|
209
231
|
this.emitEvent(this.eventTransformer.createStatusEvent('pr_created', { stage: stage.key, prUrl }));
|
|
232
|
+
await this.progressReporter.pullRequestCreated(stage.key, prUrl);
|
|
210
233
|
}
|
|
211
234
|
catch { }
|
|
212
235
|
}
|
|
@@ -249,6 +272,9 @@ export class Agent {
|
|
|
249
272
|
}
|
|
250
273
|
return this.posthogAPI.fetchTask(taskId);
|
|
251
274
|
}
|
|
275
|
+
getPostHogClient() {
|
|
276
|
+
return this.posthogAPI;
|
|
277
|
+
}
|
|
252
278
|
async listTasks(filters) {
|
|
253
279
|
if (!this.posthogAPI) {
|
|
254
280
|
throw new Error('PostHog API not configured. Provide posthogApiUrl and posthogApiKey in constructor.');
|
|
@@ -320,14 +346,14 @@ Generated by PostHog Agent`;
|
|
|
320
346
|
this.logger.info('Pull request created', { taskId, prUrl });
|
|
321
347
|
return prUrl;
|
|
322
348
|
}
|
|
323
|
-
async attachPullRequestToTask(taskId, prUrl) {
|
|
324
|
-
this.logger.info('Attaching PR to task', { taskId, prUrl });
|
|
349
|
+
async attachPullRequestToTask(taskId, prUrl, branchName) {
|
|
350
|
+
this.logger.info('Attaching PR to task', { taskId, prUrl, branchName });
|
|
325
351
|
if (!this.posthogAPI) {
|
|
326
352
|
const error = new Error('PostHog API not configured. Cannot attach PR to task.');
|
|
327
353
|
this.logger.error('PostHog API not configured', error);
|
|
328
354
|
throw error;
|
|
329
355
|
}
|
|
330
|
-
await this.posthogAPI.
|
|
356
|
+
await this.posthogAPI.attachTaskPullRequest(taskId, prUrl, branchName);
|
|
331
357
|
this.logger.debug('PR attached to task', { taskId, prUrl });
|
|
332
358
|
}
|
|
333
359
|
async updateTaskBranch(taskId, branchName) {
|
|
@@ -337,7 +363,7 @@ Generated by PostHog Agent`;
|
|
|
337
363
|
this.logger.error('PostHog API not configured', error);
|
|
338
364
|
throw error;
|
|
339
365
|
}
|
|
340
|
-
await this.posthogAPI.
|
|
366
|
+
await this.posthogAPI.setTaskBranch(taskId, branchName);
|
|
341
367
|
this.logger.debug('Task branch updated', { taskId, branchName });
|
|
342
368
|
}
|
|
343
369
|
// Execution management
|
|
@@ -364,8 +390,13 @@ Generated by PostHog Agent`;
|
|
|
364
390
|
// Log all events except tokens (too verbose)
|
|
365
391
|
this.logger.debug('Emitting event', { type: event.type, ts: event.ts });
|
|
366
392
|
}
|
|
393
|
+
const persistPromise = this.progressReporter.recordEvent(event);
|
|
394
|
+
if (persistPromise && typeof persistPromise.then === 'function') {
|
|
395
|
+
persistPromise.catch((error) => this.logger.debug('Failed to persist agent event', { message: error.message }));
|
|
396
|
+
}
|
|
367
397
|
this.onEvent?.(event);
|
|
368
398
|
}
|
|
369
399
|
}
|
|
370
|
-
|
|
371
|
-
|
|
400
|
+
|
|
401
|
+
export { Agent };
|
|
402
|
+
//# sourceMappingURL=agent.js.map
|