@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.
- package/CLAUDE.md +3 -3
- package/README.md +3 -3
- package/dist/index.d.ts +11 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/src/adapters/claude/claude-adapter.d.ts +3 -3
- package/dist/src/adapters/claude/claude-adapter.d.ts.map +1 -1
- package/dist/src/adapters/claude/claude-adapter.js +156 -111
- package/dist/src/adapters/claude/claude-adapter.js.map +1 -1
- package/dist/src/adapters/claude/tool-mapper.d.ts +1 -1
- package/dist/src/adapters/claude/tool-mapper.d.ts.map +1 -1
- package/dist/src/adapters/claude/tool-mapper.js.map +1 -1
- package/dist/src/adapters/types.d.ts +1 -1
- package/dist/src/adapters/types.d.ts.map +1 -1
- package/dist/src/agent.d.ts +7 -7
- package/dist/src/agent.d.ts.map +1 -1
- package/dist/src/agent.js +143 -85
- package/dist/src/agent.js.map +1 -1
- package/dist/src/agents/execution.js.map +1 -1
- package/dist/src/agents/planning.js.map +1 -1
- package/dist/src/agents/research.js.map +1 -1
- package/dist/src/file-manager.d.ts +4 -4
- package/dist/src/file-manager.d.ts.map +1 -1
- package/dist/src/file-manager.js +59 -58
- package/dist/src/file-manager.js.map +1 -1
- package/dist/src/git-manager.d.ts +1 -1
- package/dist/src/git-manager.d.ts.map +1 -1
- package/dist/src/git-manager.js +93 -69
- package/dist/src/git-manager.js.map +1 -1
- package/dist/src/posthog-api.d.ts +2 -3
- package/dist/src/posthog-api.d.ts.map +1 -1
- package/dist/src/posthog-api.js +22 -22
- package/dist/src/posthog-api.js.map +1 -1
- package/dist/src/prompt-builder.d.ts +3 -3
- package/dist/src/prompt-builder.d.ts.map +1 -1
- package/dist/src/prompt-builder.js +123 -93
- package/dist/src/prompt-builder.js.map +1 -1
- package/dist/src/task-manager.d.ts +4 -4
- package/dist/src/task-manager.d.ts.map +1 -1
- package/dist/src/task-manager.js +19 -18
- package/dist/src/task-manager.js.map +1 -1
- package/dist/src/task-progress-reporter.d.ts +3 -4
- package/dist/src/task-progress-reporter.d.ts.map +1 -1
- package/dist/src/task-progress-reporter.js +59 -54
- package/dist/src/task-progress-reporter.js.map +1 -1
- package/dist/src/template-manager.d.ts +1 -1
- package/dist/src/template-manager.d.ts.map +1 -1
- package/dist/src/template-manager.js +30 -28
- package/dist/src/template-manager.js.map +1 -1
- package/dist/src/todo-manager.d.ts +3 -3
- package/dist/src/todo-manager.d.ts.map +1 -1
- package/dist/src/todo-manager.js +29 -24
- package/dist/src/todo-manager.js.map +1 -1
- package/dist/src/tools/registry.d.ts +1 -1
- package/dist/src/tools/registry.js +60 -60
- package/dist/src/tools/registry.js.map +1 -1
- package/dist/src/tools/types.d.ts +31 -31
- package/dist/src/types.d.ts +33 -33
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js.map +1 -1
- package/dist/src/utils/logger.d.ts +4 -4
- package/dist/src/utils/logger.d.ts.map +1 -1
- package/dist/src/utils/logger.js +8 -8
- package/dist/src/utils/logger.js.map +1 -1
- package/dist/src/workflow/config.d.ts +1 -1
- package/dist/src/workflow/config.d.ts.map +1 -1
- package/dist/src/workflow/config.js +18 -18
- package/dist/src/workflow/config.js.map +1 -1
- package/dist/src/workflow/steps/build.d.ts +1 -1
- package/dist/src/workflow/steps/build.d.ts.map +1 -1
- package/dist/src/workflow/steps/build.js +46 -38
- package/dist/src/workflow/steps/build.js.map +1 -1
- package/dist/src/workflow/steps/finalize.d.ts +1 -1
- package/dist/src/workflow/steps/finalize.d.ts.map +1 -1
- package/dist/src/workflow/steps/finalize.js +54 -48
- package/dist/src/workflow/steps/finalize.js.map +1 -1
- package/dist/src/workflow/steps/plan.d.ts +1 -1
- package/dist/src/workflow/steps/plan.d.ts.map +1 -1
- package/dist/src/workflow/steps/plan.js +58 -46
- package/dist/src/workflow/steps/plan.js.map +1 -1
- package/dist/src/workflow/steps/research.d.ts +1 -1
- package/dist/src/workflow/steps/research.d.ts.map +1 -1
- package/dist/src/workflow/steps/research.js +68 -56
- package/dist/src/workflow/steps/research.js.map +1 -1
- package/dist/src/workflow/types.d.ts +12 -12
- package/dist/src/workflow/types.d.ts.map +1 -1
- package/dist/src/workflow/utils.d.ts +1 -1
- package/dist/src/workflow/utils.d.ts.map +1 -1
- package/dist/src/workflow/utils.js +7 -4
- package/dist/src/workflow/utils.js.map +1 -1
- package/package.json +8 -8
- package/src/adapters/claude/claude-adapter.ts +220 -168
- package/src/adapters/claude/tool-mapper.ts +2 -2
- package/src/adapters/types.ts +1 -1
- package/src/agent.ts +579 -444
- package/src/agents/execution.ts +1 -1
- package/src/agents/planning.ts +1 -1
- package/src/agents/research.ts +0 -1
- package/src/file-manager.ts +64 -63
- package/src/git-manager.ts +152 -87
- package/src/posthog-api.ts +122 -82
- package/src/prompt-builder.ts +180 -135
- package/src/task-manager.ts +38 -30
- package/src/task-progress-reporter.ts +70 -59
- package/src/template-manager.ts +98 -45
- package/src/todo-manager.ts +35 -30
- package/src/tools/registry.ts +62 -62
- package/src/tools/types.ts +36 -36
- package/src/types.ts +93 -71
- package/src/utils/logger.ts +62 -56
- package/src/workflow/config.ts +48 -48
- package/src/workflow/steps/build.ts +122 -113
- package/src/workflow/steps/finalize.ts +214 -182
- package/src/workflow/steps/plan.ts +151 -131
- package/src/workflow/steps/research.ts +205 -186
- package/src/workflow/types.ts +38 -36
- package/src/workflow/utils.ts +37 -34
- package/LICENSE +0 -33
|
@@ -1,216 +1,248 @@
|
|
|
1
|
-
import type { LocalArtifact } from
|
|
2
|
-
import type { Task, TaskRunArtifact } from
|
|
3
|
-
import type { WorkflowStepRunner } from
|
|
4
|
-
import { finalizeStepGitActions } from
|
|
1
|
+
import type { LocalArtifact } from "../../file-manager.js";
|
|
2
|
+
import type { Task, TaskRunArtifact } from "../../types.js";
|
|
3
|
+
import type { WorkflowStepRunner } from "../types.js";
|
|
4
|
+
import { finalizeStepGitActions } from "../utils.js";
|
|
5
5
|
|
|
6
6
|
const MAX_SNIPPET_LENGTH = 1200;
|
|
7
7
|
|
|
8
8
|
export const finalizeStep: WorkflowStepRunner = async ({ step, context }) => {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
hasPostHogApi: Boolean(posthogAPI),
|
|
45
|
-
runId: progressReporter.runId,
|
|
46
|
-
});
|
|
9
|
+
const {
|
|
10
|
+
task,
|
|
11
|
+
logger,
|
|
12
|
+
fileManager,
|
|
13
|
+
gitManager,
|
|
14
|
+
posthogAPI,
|
|
15
|
+
progressReporter,
|
|
16
|
+
} = context;
|
|
17
|
+
|
|
18
|
+
const stepLogger = logger.child("FinalizeStep");
|
|
19
|
+
const artifacts = await fileManager.collectTaskArtifacts(task.id);
|
|
20
|
+
let uploadedArtifacts: TaskRunArtifact[] | undefined;
|
|
21
|
+
|
|
22
|
+
if (artifacts.length && posthogAPI && progressReporter.runId) {
|
|
23
|
+
try {
|
|
24
|
+
const payload = artifacts.map((artifact) => ({
|
|
25
|
+
name: artifact.name,
|
|
26
|
+
type: artifact.type,
|
|
27
|
+
content: artifact.content,
|
|
28
|
+
content_type: artifact.contentType,
|
|
29
|
+
}));
|
|
30
|
+
uploadedArtifacts = await posthogAPI.uploadTaskArtifacts(
|
|
31
|
+
task.id,
|
|
32
|
+
progressReporter.runId,
|
|
33
|
+
payload,
|
|
34
|
+
);
|
|
35
|
+
stepLogger.info("Uploaded task artifacts to PostHog", {
|
|
36
|
+
taskId: task.id,
|
|
37
|
+
uploadedCount: uploadedArtifacts.length,
|
|
38
|
+
});
|
|
39
|
+
} catch (error) {
|
|
40
|
+
stepLogger.warn("Failed to upload task artifacts", {
|
|
41
|
+
taskId: task.id,
|
|
42
|
+
error: error instanceof Error ? error.message : String(error),
|
|
43
|
+
});
|
|
47
44
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
// Commit the deletion of artifacts
|
|
54
|
-
await finalizeStepGitActions(context, step, {
|
|
55
|
-
commitMessage: `Cleanup task artifacts for ${task.title}`,
|
|
56
|
-
allowEmptyCommit: true
|
|
45
|
+
} else {
|
|
46
|
+
stepLogger.debug("Skipping artifact upload", {
|
|
47
|
+
hasArtifacts: artifacts.length > 0,
|
|
48
|
+
hasPostHogApi: Boolean(posthogAPI),
|
|
49
|
+
runId: progressReporter.runId,
|
|
57
50
|
});
|
|
51
|
+
}
|
|
58
52
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
artifactCount: artifacts.length,
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
return { status: 'completed' };
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
function buildPullRequestBody(task: Task, artifacts: LocalArtifact[], uploaded?: TaskRunArtifact[]): string {
|
|
69
|
-
const lines: string[] = [];
|
|
70
|
-
const taskSlug = (task as any).slug || task.id;
|
|
53
|
+
const prBody = buildPullRequestBody(task, artifacts, uploadedArtifacts);
|
|
54
|
+
await fileManager.cleanupTaskDirectory(task.id);
|
|
55
|
+
await gitManager.addAllPostHogFiles();
|
|
71
56
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
57
|
+
// Commit the deletion of artifacts
|
|
58
|
+
await finalizeStepGitActions(context, step, {
|
|
59
|
+
commitMessage: `Cleanup task artifacts for ${task.title}`,
|
|
60
|
+
allowEmptyCommit: true,
|
|
61
|
+
});
|
|
76
62
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
const usedFiles = new Set<string>();
|
|
83
|
-
|
|
84
|
-
const contextArtifact = artifacts.find((artifact) => artifact.name === 'context.md');
|
|
85
|
-
if (contextArtifact) {
|
|
86
|
-
lines.push('');
|
|
87
|
-
lines.push('### Task prompt');
|
|
88
|
-
lines.push(contextArtifact.content);
|
|
89
|
-
usedFiles.add(contextArtifact.name);
|
|
90
|
-
}
|
|
63
|
+
context.stepResults[step.id] = {
|
|
64
|
+
prBody,
|
|
65
|
+
uploadedArtifacts,
|
|
66
|
+
artifactCount: artifacts.length,
|
|
67
|
+
};
|
|
91
68
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
usedFiles.add(researchArtifact.name);
|
|
95
|
-
const researchSection = formatResearchSection(researchArtifact.content);
|
|
96
|
-
if (researchSection) {
|
|
97
|
-
lines.push('');
|
|
98
|
-
lines.push(researchSection);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
69
|
+
return { status: "completed" };
|
|
70
|
+
};
|
|
101
71
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
72
|
+
function buildPullRequestBody(
|
|
73
|
+
task: Task,
|
|
74
|
+
artifacts: LocalArtifact[],
|
|
75
|
+
uploaded?: TaskRunArtifact[],
|
|
76
|
+
): string {
|
|
77
|
+
const lines: string[] = [];
|
|
78
|
+
const taskSlug = (task as unknown as Record<string, unknown>).slug || task.id;
|
|
79
|
+
|
|
80
|
+
lines.push("## Task context");
|
|
81
|
+
lines.push(`- **Task**: ${taskSlug}`);
|
|
82
|
+
lines.push(`- **Title**: ${task.title}`);
|
|
83
|
+
lines.push(`- **Origin**: ${task.origin_product}`);
|
|
84
|
+
|
|
85
|
+
if (task.description) {
|
|
86
|
+
lines.push("");
|
|
87
|
+
lines.push(`> ${task.description.trim().split("\n").join("\n> ")}`);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const usedFiles = new Set<string>();
|
|
91
|
+
|
|
92
|
+
const contextArtifact = artifacts.find(
|
|
93
|
+
(artifact) => artifact.name === "context.md",
|
|
94
|
+
);
|
|
95
|
+
if (contextArtifact) {
|
|
96
|
+
lines.push("");
|
|
97
|
+
lines.push("### Task prompt");
|
|
98
|
+
lines.push(contextArtifact.content);
|
|
99
|
+
usedFiles.add(contextArtifact.name);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const researchArtifact = artifacts.find(
|
|
103
|
+
(artifact) => artifact.name === "research.json",
|
|
104
|
+
);
|
|
105
|
+
if (researchArtifact) {
|
|
106
|
+
usedFiles.add(researchArtifact.name);
|
|
107
|
+
const researchSection = formatResearchSection(researchArtifact.content);
|
|
108
|
+
if (researchSection) {
|
|
109
|
+
lines.push("");
|
|
110
|
+
lines.push(researchSection);
|
|
108
111
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const planArtifact = artifacts.find(
|
|
115
|
+
(artifact) => artifact.name === "plan.md",
|
|
116
|
+
);
|
|
117
|
+
if (planArtifact) {
|
|
118
|
+
lines.push("");
|
|
119
|
+
lines.push("### Implementation plan");
|
|
120
|
+
lines.push(planArtifact.content);
|
|
121
|
+
usedFiles.add(planArtifact.name);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const todoArtifact = artifacts.find(
|
|
125
|
+
(artifact) => artifact.name === "todos.json",
|
|
126
|
+
);
|
|
127
|
+
if (todoArtifact) {
|
|
128
|
+
const summary = summarizeTodos(todoArtifact.content);
|
|
129
|
+
if (summary) {
|
|
130
|
+
lines.push("");
|
|
131
|
+
lines.push("### Todo list");
|
|
132
|
+
lines.push(summary);
|
|
119
133
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
134
|
+
usedFiles.add(todoArtifact.name);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const remainingArtifacts = artifacts.filter(
|
|
138
|
+
(artifact) => !usedFiles.has(artifact.name),
|
|
139
|
+
);
|
|
140
|
+
if (remainingArtifacts.length) {
|
|
141
|
+
lines.push("");
|
|
142
|
+
lines.push("### Additional artifacts");
|
|
143
|
+
for (const artifact of remainingArtifacts) {
|
|
144
|
+
lines.push(`#### ${artifact.name}`);
|
|
145
|
+
lines.push(renderCodeFence(artifact.content));
|
|
129
146
|
}
|
|
147
|
+
}
|
|
130
148
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
149
|
+
const artifactList =
|
|
150
|
+
uploaded ??
|
|
151
|
+
artifacts.map((artifact) => ({
|
|
152
|
+
name: artifact.name,
|
|
153
|
+
type: artifact.type,
|
|
134
154
|
}));
|
|
135
155
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
156
|
+
if (artifactList.length) {
|
|
157
|
+
lines.push("");
|
|
158
|
+
lines.push("### Uploaded artifacts");
|
|
159
|
+
for (const artifact of artifactList) {
|
|
160
|
+
const rawStoragePath =
|
|
161
|
+
"storage_path" in artifact
|
|
162
|
+
? (artifact as Record<string, unknown>).storage_path
|
|
163
|
+
: undefined;
|
|
164
|
+
const storagePath =
|
|
165
|
+
typeof rawStoragePath === "string" ? rawStoragePath : undefined;
|
|
166
|
+
const storage =
|
|
167
|
+
storagePath && storagePath.trim().length > 0
|
|
168
|
+
? ` – \`${storagePath.trim()}\``
|
|
169
|
+
: "";
|
|
170
|
+
lines.push(`- ${artifact.name} (${artifact.type})${storage}`);
|
|
145
171
|
}
|
|
172
|
+
}
|
|
146
173
|
|
|
147
|
-
|
|
174
|
+
return lines.join("\n\n");
|
|
148
175
|
}
|
|
149
176
|
|
|
150
177
|
function renderCodeFence(content: string): string {
|
|
151
|
-
|
|
152
|
-
|
|
178
|
+
const snippet = truncate(content, MAX_SNIPPET_LENGTH);
|
|
179
|
+
return ["```", snippet, "```"].join("\n");
|
|
153
180
|
}
|
|
154
181
|
|
|
155
182
|
function truncate(value: string, maxLength: number): string {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
183
|
+
if (value.length <= maxLength) {
|
|
184
|
+
return value;
|
|
185
|
+
}
|
|
186
|
+
return `${value.slice(0, maxLength)}\n…`;
|
|
160
187
|
}
|
|
161
188
|
|
|
162
189
|
function formatResearchSection(content: string): string | null {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
return null;
|
|
190
|
+
try {
|
|
191
|
+
const parsed = JSON.parse(content);
|
|
192
|
+
const sections: string[] = [];
|
|
193
|
+
|
|
194
|
+
if (parsed.context) {
|
|
195
|
+
sections.push("### Research summary");
|
|
196
|
+
sections.push(parsed.context);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (parsed.questions?.length) {
|
|
200
|
+
sections.push("");
|
|
201
|
+
sections.push("### Questions needing answers");
|
|
202
|
+
for (const question of parsed.questions) {
|
|
203
|
+
sections.push(`- ${question.question ?? question}`);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if (parsed.answers?.length) {
|
|
208
|
+
sections.push("");
|
|
209
|
+
sections.push("### Answers provided");
|
|
210
|
+
for (const answer of parsed.answers) {
|
|
211
|
+
const questionId = answer.questionId
|
|
212
|
+
? ` (Q: ${answer.questionId})`
|
|
213
|
+
: "";
|
|
214
|
+
sections.push(
|
|
215
|
+
`- ${answer.selectedOption || answer.customInput || "answer"}${questionId}`,
|
|
216
|
+
);
|
|
217
|
+
}
|
|
192
218
|
}
|
|
219
|
+
|
|
220
|
+
return sections.length ? sections.join("\n") : null;
|
|
221
|
+
} catch {
|
|
222
|
+
return null;
|
|
223
|
+
}
|
|
193
224
|
}
|
|
194
225
|
|
|
195
226
|
function summarizeTodos(content: string): string | null {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
return lines.join('\n');
|
|
212
|
-
} catch {
|
|
213
|
-
return null;
|
|
227
|
+
try {
|
|
228
|
+
const data = JSON.parse(content);
|
|
229
|
+
const total = data?.metadata?.total ?? data?.items?.length;
|
|
230
|
+
const completed =
|
|
231
|
+
data?.metadata?.completed ??
|
|
232
|
+
data?.items?.filter(
|
|
233
|
+
(item: { status?: string }) => item.status === "completed",
|
|
234
|
+
).length;
|
|
235
|
+
|
|
236
|
+
const lines = [`Progress: ${completed}/${total} completed`];
|
|
237
|
+
|
|
238
|
+
if (data?.items?.length) {
|
|
239
|
+
for (const item of data.items) {
|
|
240
|
+
lines.push(`- [${item.status}] ${item.content}`);
|
|
241
|
+
}
|
|
214
242
|
}
|
|
215
|
-
}
|
|
216
243
|
|
|
244
|
+
return lines.join("\n");
|
|
245
|
+
} catch {
|
|
246
|
+
return null;
|
|
247
|
+
}
|
|
248
|
+
}
|