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