@posthog/agent 1.21.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/claude-cli/cli.js +1396 -1347
- 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 +2 -1
- package/dist/src/git-manager.d.ts.map +1 -1
- package/dist/src/git-manager.js +99 -68
- 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 +69 -53
- 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 +62 -47
- 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 +9 -9
- 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 +159 -86
- 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 +80 -58
- 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 +218 -177
- 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,207 +1,248 @@
|
|
|
1
|
-
import type { LocalArtifact } from
|
|
2
|
-
import type { Task, TaskRunArtifact } from
|
|
3
|
-
import type { WorkflowStepRunner } 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";
|
|
4
5
|
|
|
5
6
|
const MAX_SNIPPET_LENGTH = 1200;
|
|
6
7
|
|
|
7
8
|
export const finalizeStep: WorkflowStepRunner = async ({ step, context }) => {
|
|
8
|
-
|
|
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
|
-
hasPostHogApi: Boolean(posthogAPI),
|
|
44
|
-
runId: progressReporter.runId,
|
|
45
|
-
});
|
|
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
|
+
});
|
|
46
44
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
45
|
+
} else {
|
|
46
|
+
stepLogger.debug("Skipping artifact upload", {
|
|
47
|
+
hasArtifacts: artifacts.length > 0,
|
|
48
|
+
hasPostHogApi: Boolean(posthogAPI),
|
|
49
|
+
runId: progressReporter.runId,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const prBody = buildPullRequestBody(task, artifacts, uploadedArtifacts);
|
|
54
|
+
await fileManager.cleanupTaskDirectory(task.id);
|
|
55
|
+
await gitManager.addAllPostHogFiles();
|
|
56
|
+
|
|
57
|
+
// Commit the deletion of artifacts
|
|
58
|
+
await finalizeStepGitActions(context, step, {
|
|
59
|
+
commitMessage: `Cleanup task artifacts for ${task.title}`,
|
|
60
|
+
allowEmptyCommit: true,
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
context.stepResults[step.id] = {
|
|
64
|
+
prBody,
|
|
65
|
+
uploadedArtifacts,
|
|
66
|
+
artifactCount: artifacts.length,
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
return { status: "completed" };
|
|
59
70
|
};
|
|
60
71
|
|
|
61
|
-
function buildPullRequestBody(
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
usedFiles.add(planArtifact.name);
|
|
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);
|
|
101
111
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
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);
|
|
112
133
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
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));
|
|
122
146
|
}
|
|
147
|
+
}
|
|
123
148
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
149
|
+
const artifactList =
|
|
150
|
+
uploaded ??
|
|
151
|
+
artifacts.map((artifact) => ({
|
|
152
|
+
name: artifact.name,
|
|
153
|
+
type: artifact.type,
|
|
127
154
|
}));
|
|
128
155
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
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}`);
|
|
136
171
|
}
|
|
172
|
+
}
|
|
137
173
|
|
|
138
|
-
|
|
174
|
+
return lines.join("\n\n");
|
|
139
175
|
}
|
|
140
176
|
|
|
141
177
|
function renderCodeFence(content: string): string {
|
|
142
|
-
|
|
143
|
-
|
|
178
|
+
const snippet = truncate(content, MAX_SNIPPET_LENGTH);
|
|
179
|
+
return ["```", snippet, "```"].join("\n");
|
|
144
180
|
}
|
|
145
181
|
|
|
146
182
|
function truncate(value: string, maxLength: number): string {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
183
|
+
if (value.length <= maxLength) {
|
|
184
|
+
return value;
|
|
185
|
+
}
|
|
186
|
+
return `${value.slice(0, maxLength)}\n…`;
|
|
151
187
|
}
|
|
152
188
|
|
|
153
189
|
function formatResearchSection(content: string): string | null {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
if (parsed.questions && parsed.questions.length) {
|
|
164
|
-
sections.push('');
|
|
165
|
-
sections.push('### Questions needing answers');
|
|
166
|
-
for (const question of parsed.questions) {
|
|
167
|
-
sections.push(`- ${question.question ?? question}`);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
if (parsed.answers && parsed.answers.length) {
|
|
172
|
-
sections.push('');
|
|
173
|
-
sections.push('### Answers provided');
|
|
174
|
-
for (const answer of parsed.answers) {
|
|
175
|
-
const questionId = answer.questionId ? ` (Q: ${answer.questionId})` : '';
|
|
176
|
-
sections.push(`- ${answer.selectedOption || answer.customInput || 'answer'}${questionId}`);
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
return sections.length ? sections.join('\n') : null;
|
|
181
|
-
} catch {
|
|
182
|
-
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);
|
|
183
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
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return sections.length ? sections.join("\n") : null;
|
|
221
|
+
} catch {
|
|
222
|
+
return null;
|
|
223
|
+
}
|
|
184
224
|
}
|
|
185
225
|
|
|
186
226
|
function summarizeTodos(content: string): string | null {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
return lines.join('\n');
|
|
203
|
-
} catch {
|
|
204
|
-
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
|
+
}
|
|
205
242
|
}
|
|
206
|
-
}
|
|
207
243
|
|
|
244
|
+
return lines.join("\n");
|
|
245
|
+
} catch {
|
|
246
|
+
return null;
|
|
247
|
+
}
|
|
248
|
+
}
|