@posthog/agent 1.11.0 → 1.12.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/README.md +26 -65
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/src/adapters/types.d.ts +1 -1
- package/dist/src/agent.d.ts +0 -13
- package/dist/src/agent.d.ts.map +1 -1
- package/dist/src/agent.js +2 -214
- package/dist/src/agent.js.map +1 -1
- package/dist/src/agents/execution.d.ts +1 -1
- package/dist/src/agents/execution.js +2 -2
- package/dist/src/agents/execution.js.map +1 -1
- package/dist/src/git-manager.js +1 -1
- package/dist/src/git-manager.js.map +1 -1
- package/dist/src/posthog-api.d.ts +0 -8
- package/dist/src/posthog-api.d.ts.map +1 -1
- package/dist/src/posthog-api.js +0 -32
- package/dist/src/posthog-api.js.map +1 -1
- package/dist/src/task-progress-reporter.d.ts +0 -6
- package/dist/src/task-progress-reporter.d.ts.map +1 -1
- package/dist/src/task-progress-reporter.js +2 -26
- package/dist/src/task-progress-reporter.js.map +1 -1
- package/dist/src/template-manager.d.ts.map +1 -1
- package/dist/src/template-manager.js +26 -4
- package/dist/src/template-manager.js.map +1 -1
- package/dist/src/types.d.ts +0 -4
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js +0 -1
- package/dist/src/types.js.map +1 -1
- package/package.json +2 -3
- package/src/adapters/types.ts +1 -1
- package/src/agent.ts +3 -234
- package/src/agents/execution.ts +2 -2
- package/src/git-manager.ts +1 -1
- package/src/posthog-api.ts +0 -40
- package/src/task-progress-reporter.ts +2 -34
- package/src/template-manager.ts +35 -5
- package/src/types.ts +0 -7
- package/dist/src/agent-registry.d.ts +0 -16
- package/dist/src/agent-registry.d.ts.map +0 -1
- package/dist/src/agent-registry.js +0 -62
- package/dist/src/agent-registry.js.map +0 -1
- package/dist/src/stage-executor.d.ts +0 -20
- package/dist/src/stage-executor.d.ts.map +0 -1
- package/dist/src/stage-executor.js +0 -178
- package/dist/src/stage-executor.js.map +0 -1
- package/dist/src/workflow-registry.d.ts +0 -11
- package/dist/src/workflow-registry.d.ts.map +0 -1
- package/dist/src/workflow-registry.js +0 -27
- package/dist/src/workflow-registry.js.map +0 -1
- package/dist/src/workflow-types.d.ts +0 -45
- package/dist/src/workflow-types.d.ts.map +0 -1
- package/src/agent-registry.ts +0 -65
- package/src/stage-executor.ts +0 -210
- package/src/workflow-registry.ts +0 -30
- package/src/workflow-types.ts +0 -52
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# PostHog Agent SDK
|
|
2
2
|
|
|
3
|
-
TypeScript agent framework that wraps the Claude Agent SDK for PostHog's Array desktop app. Features a Git-based
|
|
3
|
+
TypeScript agent framework that wraps the Claude Agent SDK for PostHog's Array desktop app. Features a Git-based task execution system that stores task artifacts alongside your code.
|
|
4
4
|
|
|
5
5
|
## Quick Start
|
|
6
6
|
|
|
@@ -11,9 +11,9 @@ bun run example
|
|
|
11
11
|
|
|
12
12
|
## Key Features
|
|
13
13
|
|
|
14
|
-
- **Git-Based
|
|
14
|
+
- **Git-Based Task Execution**: Plans and artifacts stored in `.posthog/` folders and committed to Git
|
|
15
15
|
- **PostHog Integration**: Fetches existing tasks from PostHog API
|
|
16
|
-
- **
|
|
16
|
+
- **3-Phase Execution**: Research → Plan → Build with automatic progression
|
|
17
17
|
- **Branch Management**: Automatic branch creation for planning and implementation
|
|
18
18
|
- **Progress Tracking**: Execution status stored in PostHog `TaskRun` records for easy polling
|
|
19
19
|
|
|
@@ -35,12 +35,14 @@ const agent = new Agent({
|
|
|
35
35
|
},
|
|
36
36
|
});
|
|
37
37
|
|
|
38
|
-
// Run
|
|
38
|
+
// Run a task
|
|
39
39
|
const taskId = "task_abc123";
|
|
40
|
-
const
|
|
41
|
-
|
|
40
|
+
const task = await agent.getPostHogClient()?.fetchTask(taskId);
|
|
41
|
+
|
|
42
|
+
await agent.runTask(task, {
|
|
42
43
|
repositoryPath: "/path/to/repo",
|
|
43
44
|
permissionMode: PermissionMode.ACCEPT_EDITS,
|
|
45
|
+
isCloudMode: false,
|
|
44
46
|
autoProgress: true,
|
|
45
47
|
});
|
|
46
48
|
```
|
|
@@ -54,32 +56,13 @@ const agent = new Agent({
|
|
|
54
56
|
});
|
|
55
57
|
```
|
|
56
58
|
|
|
57
|
-
##
|
|
58
|
-
|
|
59
|
-
Each task execution creates Git branches:
|
|
60
|
-
|
|
61
|
-
1. **Planning**: `posthog/task-{id}-planning` - Contains plan in `.posthog/{id}/plan.md`
|
|
62
|
-
2. **Implementation**: `posthog/task-{id}-implementation` - Contains code changes
|
|
63
|
-
|
|
64
|
-
## Manual Stages and Resume
|
|
65
|
-
|
|
66
|
-
- Manual stages (no agent, or `is_manual_only`) are stop-points: the SDK will not auto-advance.
|
|
67
|
-
- On manual stages, a PR is opened by default for human review (configurable per stage with `openPullRequest`).
|
|
59
|
+
## Task Execution
|
|
68
60
|
|
|
69
|
-
|
|
61
|
+
Each task execution creates Git branches and follows a 3-phase approach:
|
|
70
62
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
permissionMode: PermissionMode.ACCEPT_EDITS,
|
|
75
|
-
resumeFromCurrentStage: true,
|
|
76
|
-
autoProgress: true, // ignored on manual stages
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
// Or explicitly progress via API then resume
|
|
80
|
-
await agent.progressToNextStage(taskId);
|
|
81
|
-
await agent.runWorkflow(taskId, workflowId, { resumeFromCurrentStage: true });
|
|
82
|
-
```
|
|
63
|
+
1. **Research Phase**: Analyzes the codebase and may generate clarifying questions
|
|
64
|
+
2. **Planning Phase**: Creates an implementation plan in `.posthog/{id}/plan.md` on branch `posthog/task-{id}-planning`
|
|
65
|
+
3. **Build Phase**: Implements code changes on branch `posthog/task-{id}-implementation`
|
|
83
66
|
|
|
84
67
|
## File System
|
|
85
68
|
|
|
@@ -90,6 +73,7 @@ your-repo/
|
|
|
90
73
|
│ ├── .gitignore
|
|
91
74
|
│ └── {task-id}/
|
|
92
75
|
│ ├── plan.md
|
|
76
|
+
│ ├── questions.json (if research phase generated questions)
|
|
93
77
|
│ └── context.md (optional)
|
|
94
78
|
└── (your code)
|
|
95
79
|
```
|
|
@@ -111,12 +95,12 @@ const poller = setInterval(async () => {
|
|
|
111
95
|
new Date(b.created_at).getTime() - new Date(a.created_at).getTime()
|
|
112
96
|
)[0];
|
|
113
97
|
if (latestRun) {
|
|
114
|
-
renderProgress(latestRun.status, latestRun.log
|
|
98
|
+
renderProgress(latestRun.status, latestRun.log);
|
|
115
99
|
}
|
|
116
100
|
}, 3000);
|
|
117
101
|
|
|
118
102
|
try {
|
|
119
|
-
await agent.
|
|
103
|
+
await agent.runTask(task, { repositoryPath: repoPath });
|
|
120
104
|
} finally {
|
|
121
105
|
clearInterval(poller);
|
|
122
106
|
}
|
|
@@ -141,46 +125,23 @@ function handleLiveEvent(event: AgentEvent) {
|
|
|
141
125
|
## Requirements
|
|
142
126
|
|
|
143
127
|
- Bun runtime
|
|
144
|
-
- Git repository
|
|
128
|
+
- Git repository
|
|
145
129
|
- PostHog API access
|
|
146
130
|
- Claude API access via `@anthropic-ai/claude-agent-sdk`
|
|
147
131
|
|
|
132
|
+
## Configuration Options
|
|
148
133
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
You can customize behavior per workflow stage using `stageOverrides`, and pass low-level model options using `queryOverrides`.
|
|
134
|
+
You can customize behavior using `TaskExecutionOptions`:
|
|
152
135
|
|
|
153
136
|
```ts
|
|
154
|
-
await agent.
|
|
137
|
+
await agent.runTask(task, {
|
|
155
138
|
repositoryPath: "/path/to/repo",
|
|
156
|
-
//
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
plan: {
|
|
163
|
-
permissionMode: PermissionMode.PLAN,
|
|
164
|
-
createPlanningBranch: true,
|
|
165
|
-
// Only applied during the planning stage
|
|
166
|
-
queryOverrides: { temperature: 0.2 }
|
|
167
|
-
},
|
|
168
|
-
build: {
|
|
169
|
-
createImplementationBranch: true,
|
|
170
|
-
openPullRequest: false,
|
|
171
|
-
// Inject custom MCP servers or any other query option
|
|
172
|
-
queryOverrides: {
|
|
173
|
-
mcpServers: {
|
|
174
|
-
// example: override or add servers
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
},
|
|
178
|
-
complete: {
|
|
179
|
-
// ensure a PR is opened at the end regardless of edits
|
|
180
|
-
openPullRequest: true
|
|
181
|
-
}
|
|
139
|
+
permissionMode: PermissionMode.ACCEPT_EDITS, // or PLAN, DEFAULT, BYPASS
|
|
140
|
+
isCloudMode: false, // local execution with pauses between phases
|
|
141
|
+
autoProgress: true, // automatically progress through phases
|
|
142
|
+
queryOverrides: {
|
|
143
|
+
model: 'claude-sonnet-4-5-20250929',
|
|
144
|
+
temperature: 0.7
|
|
182
145
|
}
|
|
183
146
|
});
|
|
184
147
|
```
|
|
185
|
-
|
|
186
|
-
Precedence for query options: base defaults in the SDK < global `queryOverrides` < per-stage `stageOverrides[stageKey].queryOverrides`.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export { Agent, } from './src/agent.js';
|
|
2
2
|
export { PermissionMode, } from './src/types.js';
|
|
3
3
|
export type { Task, TaskRun, SupportingFile, ExecutionResult, AgentConfig, McpServerConfig, AgentEvent } from './src/types.js';
|
|
4
|
-
export type { WorkflowDefinition, WorkflowStage, WorkflowExecutionOptions, AgentDefinition } from './src/workflow-types.js';
|
|
5
4
|
export { Logger, LogLevel, } from './src/utils/logger.js';
|
|
6
5
|
export type { LoggerConfig } from './src/utils/logger.js';
|
|
7
6
|
export type { ExtractedQuestion, ExtractedQuestionWithAnswer, StructuredExtractor } from './src/structured-extraction.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AACA,OAAO,EACH,KAAK,GACR,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACH,cAAc,GACjB,MAAM,gBAAgB,CAAC;AAExB,YAAY,EACR,IAAI,EACJ,OAAO,EACP,cAAc,EACd,eAAe,EACf,WAAW,EACX,eAAe,EACf,UAAU,EACb,MAAM,gBAAgB,CAAC;AAExB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AACA,OAAO,EACH,KAAK,GACR,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACH,cAAc,GACjB,MAAM,gBAAgB,CAAC;AAExB,YAAY,EACR,IAAI,EACJ,OAAO,EACP,cAAc,EACd,eAAe,EACf,WAAW,EACX,eAAe,EACf,UAAU,EACb,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACH,MAAM,EACN,QAAQ,GACX,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EACR,YAAY,EACf,MAAM,uBAAuB,CAAC;AAG/B,YAAY,EACR,iBAAiB,EACjB,2BAA2B,EAC3B,mBAAmB,EACtB,MAAM,gCAAgC,CAAC;AAGxC,YAAY,EACR,YAAY,EACZ,UAAU,EACV,aAAa,EAChB,MAAM,uBAAuB,CAAC;AAG/B,YAAY,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC;AAGxE,YAAY,EACR,IAAI,EACJ,YAAY,EACZ,SAAS,EACT,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,gBAAgB,EAChB,QAAQ,EACR,cAAc,EACd,aAAa,EACb,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,QAAQ,EACR,aAAa,EACb,gBAAgB,EAChB,gBAAgB,GACnB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC"}
|
|
@@ -16,7 +16,7 @@ export interface ProviderAdapter {
|
|
|
16
16
|
transform(sdkMessage: unknown): AgentEvent | null;
|
|
17
17
|
/**
|
|
18
18
|
* Create a standardized status event.
|
|
19
|
-
* Used for
|
|
19
|
+
* Used for task phase transitions and other status updates.
|
|
20
20
|
*/
|
|
21
21
|
createStatusEvent(phase: string, additionalData?: any): StatusEvent;
|
|
22
22
|
/**
|
package/dist/src/agent.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { Task, ExecutionResult, AgentConfig } from './types.js';
|
|
2
|
-
import type { WorkflowDefinition, WorkflowStage, WorkflowExecutionOptions } from './workflow-types.js';
|
|
3
2
|
import { PostHogAPIClient } from './posthog-api.js';
|
|
4
3
|
import { type ExtractedQuestion, type ExtractedQuestionWithAnswer } from './structured-extraction.js';
|
|
5
4
|
export declare class Agent {
|
|
@@ -12,9 +11,6 @@ export declare class Agent {
|
|
|
12
11
|
private templateManager;
|
|
13
12
|
private adapter;
|
|
14
13
|
private logger;
|
|
15
|
-
private agentRegistry;
|
|
16
|
-
private workflowRegistry;
|
|
17
|
-
private stageExecutor;
|
|
18
14
|
private progressReporter;
|
|
19
15
|
private promptBuilder;
|
|
20
16
|
private extractor?;
|
|
@@ -29,13 +25,7 @@ export declare class Agent {
|
|
|
29
25
|
* Configure LLM gateway environment variables for Claude Code CLI
|
|
30
26
|
*/
|
|
31
27
|
private _configureLlmGateway;
|
|
32
|
-
runWorkflow(taskOrId: Task | string, workflowId: string, options?: WorkflowExecutionOptions): Promise<{
|
|
33
|
-
task: Task;
|
|
34
|
-
workflow: WorkflowDefinition;
|
|
35
|
-
}>;
|
|
36
|
-
executeStage(task: Task, stage: WorkflowStage, options?: WorkflowExecutionOptions): Promise<void>;
|
|
37
28
|
runTask(taskOrId: Task | string, options?: import('./types.js').TaskExecutionOptions): Promise<void>;
|
|
38
|
-
progressToNextStage(taskId: string, currentStageKey?: string): Promise<void>;
|
|
39
29
|
run(prompt: string, options?: {
|
|
40
30
|
repositoryPath?: string;
|
|
41
31
|
permissionMode?: import('./types.js').PermissionMode;
|
|
@@ -47,8 +37,6 @@ export declare class Agent {
|
|
|
47
37
|
repository?: string;
|
|
48
38
|
organization?: string;
|
|
49
39
|
origin_product?: string;
|
|
50
|
-
workflow?: string;
|
|
51
|
-
current_stage?: string;
|
|
52
40
|
}): Promise<Task[]>;
|
|
53
41
|
writeTaskFile(taskId: string, fileName: string, content: string, type?: 'plan' | 'context' | 'reference' | 'output'): Promise<void>;
|
|
54
42
|
readTaskFile(taskId: string, fileName: string): Promise<string | null>;
|
|
@@ -69,5 +57,4 @@ export declare class Agent {
|
|
|
69
57
|
}
|
|
70
58
|
export { PermissionMode } from './types.js';
|
|
71
59
|
export type { Task, SupportingFile, ExecutionResult, AgentConfig } from './types.js';
|
|
72
|
-
export type { WorkflowDefinition, WorkflowStage, WorkflowExecutionOptions } from './workflow-types.js';
|
|
73
60
|
//# sourceMappingURL=agent.d.ts.map
|
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;
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/agent.ts"],"names":[],"mappings":"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"}
|
package/dist/src/agent.js
CHANGED
|
@@ -6,9 +6,6 @@ import { GitManager } from './git-manager.js';
|
|
|
6
6
|
import { TemplateManager } from './template-manager.js';
|
|
7
7
|
import { ClaudeAdapter } from './adapters/claude/claude-adapter.js';
|
|
8
8
|
import { Logger } from './utils/logger.js';
|
|
9
|
-
import { AgentRegistry } from './agent-registry.js';
|
|
10
|
-
import { WorkflowRegistry } from './workflow-registry.js';
|
|
11
|
-
import { StageExecutor } from './stage-executor.js';
|
|
12
9
|
import { PromptBuilder } from './prompt-builder.js';
|
|
13
10
|
import { TaskProgressReporter } from './task-progress-reporter.js';
|
|
14
11
|
import { OpenAIExtractor } from './structured-extraction.js';
|
|
@@ -24,9 +21,6 @@ class Agent {
|
|
|
24
21
|
templateManager;
|
|
25
22
|
adapter;
|
|
26
23
|
logger;
|
|
27
|
-
agentRegistry;
|
|
28
|
-
workflowRegistry;
|
|
29
|
-
stageExecutor;
|
|
30
24
|
progressReporter;
|
|
31
25
|
promptBuilder;
|
|
32
26
|
extractor;
|
|
@@ -68,23 +62,18 @@ class Agent {
|
|
|
68
62
|
// TODO: Add author config from environment or config
|
|
69
63
|
});
|
|
70
64
|
this.templateManager = new TemplateManager();
|
|
71
|
-
this.agentRegistry = new AgentRegistry();
|
|
72
65
|
if (config.posthogApiUrl && config.posthogApiKey) {
|
|
73
66
|
this.posthogAPI = new PostHogAPIClient({
|
|
74
67
|
apiUrl: config.posthogApiUrl,
|
|
75
68
|
apiKey: config.posthogApiKey,
|
|
76
69
|
});
|
|
77
70
|
}
|
|
78
|
-
this.workflowRegistry = new WorkflowRegistry(this.posthogAPI);
|
|
79
71
|
this.promptBuilder = new PromptBuilder({
|
|
80
72
|
getTaskFiles: (taskId) => this.getTaskFiles(taskId),
|
|
81
73
|
generatePlanTemplate: (vars) => this.templateManager.generatePlan(vars),
|
|
82
74
|
posthogClient: this.posthogAPI,
|
|
83
75
|
logger: this.logger.child('PromptBuilder')
|
|
84
76
|
});
|
|
85
|
-
this.stageExecutor = new StageExecutor(this.agentRegistry, this.logger, this.promptBuilder, undefined, // eventHandler set via setEventHandler below
|
|
86
|
-
this.mcpServers);
|
|
87
|
-
this.stageExecutor.setEventHandler((event) => this.emitEvent(event));
|
|
88
77
|
this.progressReporter = new TaskProgressReporter(this.posthogAPI, this.logger);
|
|
89
78
|
// Initialize OpenAI extractor if API key is available
|
|
90
79
|
if (process.env.OPENAI_API_KEY) {
|
|
@@ -120,186 +109,7 @@ class Agent {
|
|
|
120
109
|
throw error;
|
|
121
110
|
}
|
|
122
111
|
}
|
|
123
|
-
//
|
|
124
|
-
async runWorkflow(taskOrId, workflowId, options = {}) {
|
|
125
|
-
await this._configureLlmGateway();
|
|
126
|
-
const task = typeof taskOrId === 'string' ? await this.fetchTask(taskOrId) : taskOrId;
|
|
127
|
-
await this.workflowRegistry.loadWorkflows();
|
|
128
|
-
const workflow = this.workflowRegistry.getWorkflow(workflowId);
|
|
129
|
-
if (!workflow) {
|
|
130
|
-
throw new Error(`Workflow ${workflowId} not found`);
|
|
131
|
-
}
|
|
132
|
-
const orderedStages = [...workflow.stages].sort((a, b) => a.position - b.position);
|
|
133
|
-
// Ensure task is assigned to workflow and positioned at first stage
|
|
134
|
-
if (this.posthogAPI) {
|
|
135
|
-
try {
|
|
136
|
-
if (task.workflow !== workflowId) {
|
|
137
|
-
await this.posthogAPI.updateTask(task.id, { workflow: workflowId });
|
|
138
|
-
task.workflow = workflowId;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
catch (e) {
|
|
142
|
-
this.logger.warn('Failed to sync task workflow before execution', { error: e.message });
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
const executionId = this.taskManager.generateExecutionId();
|
|
146
|
-
this.logger.info('Starting workflow execution', { taskId: task.id, workflowId, executionId });
|
|
147
|
-
this.taskManager.startExecution(task.id, 'plan_and_build', executionId);
|
|
148
|
-
await this.progressReporter.start(task.id, {
|
|
149
|
-
totalSteps: orderedStages.length,
|
|
150
|
-
});
|
|
151
|
-
// Set initial stage on the newly created run
|
|
152
|
-
const firstStage = orderedStages[0];
|
|
153
|
-
if (this.posthogAPI && this.progressReporter.runId && firstStage) {
|
|
154
|
-
try {
|
|
155
|
-
await this.posthogAPI.updateTaskRun(task.id, this.progressReporter.runId, {
|
|
156
|
-
current_stage: firstStage.id
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
catch (e) {
|
|
160
|
-
this.logger.warn('Failed to set initial stage on run', { error: e.message });
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
try {
|
|
164
|
-
let startIndex = 0;
|
|
165
|
-
const currentStageId = task.current_stage;
|
|
166
|
-
// If task is already at the last stage, fail gracefully without progressing
|
|
167
|
-
if (currentStageId) {
|
|
168
|
-
const currIdx = orderedStages.findIndex(s => s.id === currentStageId);
|
|
169
|
-
const atLastStage = currIdx >= 0 && currIdx === orderedStages.length - 1;
|
|
170
|
-
if (atLastStage) {
|
|
171
|
-
const finalStageKey = orderedStages[currIdx]?.key;
|
|
172
|
-
this.emitEvent(this.adapter.createStatusEvent('no_next_stage', { stage: finalStageKey }));
|
|
173
|
-
await this.progressReporter.noNextStage(finalStageKey);
|
|
174
|
-
await this.progressReporter.complete();
|
|
175
|
-
this.taskManager.completeExecution(executionId, { task, workflow });
|
|
176
|
-
return { task, workflow };
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
if (options.resumeFromCurrentStage && currentStageId) {
|
|
180
|
-
const idx = orderedStages.findIndex(s => s.id === currentStageId);
|
|
181
|
-
if (idx >= 0)
|
|
182
|
-
startIndex = idx;
|
|
183
|
-
}
|
|
184
|
-
// Align server-side stage when restarting from a different stage
|
|
185
|
-
if (this.posthogAPI && this.progressReporter.runId) {
|
|
186
|
-
const targetStage = orderedStages[startIndex];
|
|
187
|
-
if (targetStage && targetStage.id !== currentStageId) {
|
|
188
|
-
try {
|
|
189
|
-
await this.posthogAPI.updateTaskRun(task.id, this.progressReporter.runId, {
|
|
190
|
-
current_stage: targetStage.id
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
catch (e) {
|
|
194
|
-
this.logger.warn('Failed to update run stage', { error: e.message });
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
for (let i = startIndex; i < orderedStages.length; i++) {
|
|
199
|
-
const stage = orderedStages[i];
|
|
200
|
-
await this.progressReporter.stageStarted(stage.key, i);
|
|
201
|
-
await this.executeStage(task, stage, options);
|
|
202
|
-
await this.progressReporter.stageCompleted(stage.key, i + 1);
|
|
203
|
-
if (options.autoProgress) {
|
|
204
|
-
const hasNext = i < orderedStages.length - 1;
|
|
205
|
-
if (hasNext) {
|
|
206
|
-
await this.progressToNextStage(task.id, stage.key);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
await this.progressReporter.complete();
|
|
211
|
-
this.taskManager.completeExecution(executionId, { task, workflow });
|
|
212
|
-
return { task, workflow };
|
|
213
|
-
}
|
|
214
|
-
catch (error) {
|
|
215
|
-
await this.progressReporter.fail(error);
|
|
216
|
-
this.taskManager.failExecution(executionId, error);
|
|
217
|
-
throw error;
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
async executeStage(task, stage, options = {}) {
|
|
221
|
-
this.emitEvent(this.adapter.createStatusEvent('stage_start', { stage: stage.key }));
|
|
222
|
-
const overrides = options.stageOverrides?.[stage.key];
|
|
223
|
-
const agentName = stage.agent_name || 'code_generation';
|
|
224
|
-
const agentDef = this.agentRegistry.getAgent(agentName);
|
|
225
|
-
const isManual = stage.is_manual_only === true;
|
|
226
|
-
const stageKeyLower = (stage.key || '').toLowerCase().trim();
|
|
227
|
-
const isPlanningByKey = stageKeyLower === 'plan' || stageKeyLower.includes('plan');
|
|
228
|
-
const isPlanning = !isManual && ((agentDef?.agent_type === 'planning') || isPlanningByKey);
|
|
229
|
-
const shouldCreatePlanningBranch = overrides?.createPlanningBranch !== false; // default true
|
|
230
|
-
const shouldCreateImplBranch = overrides?.createImplementationBranch !== false; // default true
|
|
231
|
-
if (isPlanning && shouldCreatePlanningBranch) {
|
|
232
|
-
const planningBranch = await this.createPlanningBranch(task.id);
|
|
233
|
-
await this.updateTaskBranch(task.id, planningBranch);
|
|
234
|
-
this.emitEvent(this.adapter.createStatusEvent('branch_created', { stage: stage.key, branch: planningBranch }));
|
|
235
|
-
await this.progressReporter.branchCreated(stage.key, planningBranch);
|
|
236
|
-
}
|
|
237
|
-
else if (!isPlanning && !isManual && shouldCreateImplBranch) {
|
|
238
|
-
const implBranch = await this.createImplementationBranch(task.id);
|
|
239
|
-
await this.updateTaskBranch(task.id, implBranch);
|
|
240
|
-
this.emitEvent(this.adapter.createStatusEvent('branch_created', { stage: stage.key, branch: implBranch }));
|
|
241
|
-
await this.progressReporter.branchCreated(stage.key, implBranch);
|
|
242
|
-
}
|
|
243
|
-
const result = await this.stageExecutor.execute(task, stage, options);
|
|
244
|
-
if (result.plan) {
|
|
245
|
-
await this.writePlan(task.id, result.plan);
|
|
246
|
-
await this.commitPlan(task.id, task.title);
|
|
247
|
-
this.emitEvent(this.adapter.createStatusEvent('commit_made', { stage: stage.key, kind: 'plan' }));
|
|
248
|
-
await this.progressReporter.commitMade(stage.key, 'plan');
|
|
249
|
-
}
|
|
250
|
-
if (isManual) {
|
|
251
|
-
const defaultOpenPR = true; // manual stages default to PR for review
|
|
252
|
-
const openPR = overrides?.openPullRequest ?? defaultOpenPR;
|
|
253
|
-
if (openPR) {
|
|
254
|
-
// Ensure we're on an implementation branch for PRs
|
|
255
|
-
let branchName = await this.gitManager.getCurrentBranch();
|
|
256
|
-
const onTaskBranch = branchName.includes(`posthog/task-${task.id}`);
|
|
257
|
-
if (!onTaskBranch && (overrides?.createImplementationBranch !== false)) {
|
|
258
|
-
const implBranch = await this.createImplementationBranch(task.id);
|
|
259
|
-
await this.updateTaskBranch(task.id, implBranch);
|
|
260
|
-
branchName = implBranch;
|
|
261
|
-
this.emitEvent(this.adapter.createStatusEvent('branch_created', { stage: stage.key, branch: implBranch }));
|
|
262
|
-
await this.progressReporter.branchCreated(stage.key, implBranch);
|
|
263
|
-
}
|
|
264
|
-
try {
|
|
265
|
-
const prUrl = await this.createPullRequest(task.id, branchName, task.title, task.description);
|
|
266
|
-
await this.updateTaskBranch(task.id, branchName);
|
|
267
|
-
await this.attachPullRequestToTask(task.id, prUrl, branchName);
|
|
268
|
-
this.emitEvent(this.adapter.createStatusEvent('pr_created', { stage: stage.key, prUrl }));
|
|
269
|
-
await this.progressReporter.pullRequestCreated(stage.key, prUrl);
|
|
270
|
-
}
|
|
271
|
-
catch { }
|
|
272
|
-
}
|
|
273
|
-
// Do not auto-progress on manual stages
|
|
274
|
-
this.emitEvent(this.adapter.createStatusEvent('stage_complete', { stage: stage.key }));
|
|
275
|
-
return;
|
|
276
|
-
}
|
|
277
|
-
if (result.results) {
|
|
278
|
-
const existingPlan = await this.readPlan(task.id);
|
|
279
|
-
const planSummary = existingPlan ? existingPlan.split('\n')[0] : undefined;
|
|
280
|
-
await this.commitImplementation(task.id, task.title, planSummary);
|
|
281
|
-
this.emitEvent(this.adapter.createStatusEvent('commit_made', { stage: stage.key, kind: 'implementation' }));
|
|
282
|
-
await this.progressReporter.commitMade(stage.key, 'implementation');
|
|
283
|
-
}
|
|
284
|
-
// PR creation on complete stage (or if explicitly requested), regardless of whether edits occurred
|
|
285
|
-
{
|
|
286
|
-
const defaultOpenPR = stage.key.toLowerCase().includes('complete');
|
|
287
|
-
const openPR = overrides?.openPullRequest ?? defaultOpenPR;
|
|
288
|
-
if (openPR) {
|
|
289
|
-
const branchName = await this.gitManager.getCurrentBranch();
|
|
290
|
-
try {
|
|
291
|
-
const prUrl = await this.createPullRequest(task.id, branchName, task.title, task.description);
|
|
292
|
-
await this.updateTaskBranch(task.id, branchName);
|
|
293
|
-
await this.attachPullRequestToTask(task.id, prUrl, branchName);
|
|
294
|
-
this.emitEvent(this.adapter.createStatusEvent('pr_created', { stage: stage.key, prUrl }));
|
|
295
|
-
await this.progressReporter.pullRequestCreated(stage.key, prUrl);
|
|
296
|
-
}
|
|
297
|
-
catch { }
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
this.emitEvent(this.adapter.createStatusEvent('stage_complete', { stage: stage.key }));
|
|
301
|
-
}
|
|
302
|
-
// Adaptive task execution - 3-phase workflow (research → plan → build)
|
|
112
|
+
// Adaptive task execution - 3 phases (research → plan → build)
|
|
303
113
|
async runTask(taskOrId, options = {}) {
|
|
304
114
|
await this._configureLlmGateway();
|
|
305
115
|
const task = typeof taskOrId === 'string' ? await this.fetchTask(taskOrId) : taskOrId;
|
|
@@ -601,28 +411,6 @@ class Agent {
|
|
|
601
411
|
this.logger.info('Task execution complete', { taskId: task.id });
|
|
602
412
|
this.emitEvent(this.adapter.createStatusEvent('task_complete', { taskId: task.id }));
|
|
603
413
|
}
|
|
604
|
-
async progressToNextStage(taskId, currentStageKey) {
|
|
605
|
-
if (!this.posthogAPI || !this.progressReporter.runId) {
|
|
606
|
-
throw new Error('PostHog API not configured or no active run. Cannot progress stage.');
|
|
607
|
-
}
|
|
608
|
-
try {
|
|
609
|
-
await this.posthogAPI.progressTaskRun(taskId, this.progressReporter.runId);
|
|
610
|
-
}
|
|
611
|
-
catch (error) {
|
|
612
|
-
if (error instanceof Error && error.message.includes('No next stage available')) {
|
|
613
|
-
this.logger.warn('No next stage available when attempting to progress run', {
|
|
614
|
-
taskId,
|
|
615
|
-
runId: this.progressReporter.runId,
|
|
616
|
-
stage: currentStageKey,
|
|
617
|
-
error: error.message,
|
|
618
|
-
});
|
|
619
|
-
this.emitEvent(this.adapter.createStatusEvent('no_next_stage', { stage: currentStageKey }));
|
|
620
|
-
await this.progressReporter.noNextStage(currentStageKey);
|
|
621
|
-
return;
|
|
622
|
-
}
|
|
623
|
-
throw error;
|
|
624
|
-
}
|
|
625
|
-
}
|
|
626
414
|
// Direct prompt execution - still supported for low-level usage
|
|
627
415
|
async run(prompt, options = {}) {
|
|
628
416
|
await this._configureLlmGateway();
|
|
@@ -709,7 +497,7 @@ class Agent {
|
|
|
709
497
|
return await this.extractor.extractQuestions(researchContent);
|
|
710
498
|
}
|
|
711
499
|
}
|
|
712
|
-
// Git operations for task
|
|
500
|
+
// Git operations for task execution
|
|
713
501
|
async createPlanningBranch(taskId) {
|
|
714
502
|
this.logger.info('Creating planning branch', { taskId });
|
|
715
503
|
const branchName = await this.gitManager.createTaskPlanningBranch(taskId);
|