@posthog/agent 1.30.0 → 2.0.1

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 (144) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +221 -219
  3. package/dist/adapters/claude/conversion/tool-use-to-acp.d.ts +21 -0
  4. package/dist/adapters/claude/conversion/tool-use-to-acp.js +547 -0
  5. package/dist/adapters/claude/conversion/tool-use-to-acp.js.map +1 -0
  6. package/dist/adapters/claude/permissions/permission-options.d.ts +13 -0
  7. package/dist/adapters/claude/permissions/permission-options.js +117 -0
  8. package/dist/adapters/claude/permissions/permission-options.js.map +1 -0
  9. package/dist/adapters/claude/questions/utils.d.ts +132 -0
  10. package/dist/adapters/claude/questions/utils.js +63 -0
  11. package/dist/adapters/claude/questions/utils.js.map +1 -0
  12. package/dist/adapters/claude/tools.d.ts +18 -0
  13. package/dist/adapters/claude/tools.js +95 -0
  14. package/dist/adapters/claude/tools.js.map +1 -0
  15. package/dist/agent-DBQY1BfC.d.ts +123 -0
  16. package/dist/agent.d.ts +5 -0
  17. package/dist/agent.js +3656 -0
  18. package/dist/agent.js.map +1 -0
  19. package/dist/claude-cli/cli.js +3695 -2746
  20. package/dist/claude-cli/vendor/ripgrep/COPYING +3 -0
  21. package/dist/claude-cli/vendor/ripgrep/arm64-darwin/rg +0 -0
  22. package/dist/claude-cli/vendor/ripgrep/arm64-darwin/ripgrep.node +0 -0
  23. package/dist/claude-cli/vendor/ripgrep/arm64-linux/rg +0 -0
  24. package/dist/claude-cli/vendor/ripgrep/arm64-linux/ripgrep.node +0 -0
  25. package/dist/claude-cli/vendor/ripgrep/x64-darwin/rg +0 -0
  26. package/dist/claude-cli/vendor/ripgrep/x64-darwin/ripgrep.node +0 -0
  27. package/dist/claude-cli/vendor/ripgrep/x64-linux/rg +0 -0
  28. package/dist/claude-cli/vendor/ripgrep/x64-linux/ripgrep.node +0 -0
  29. package/dist/claude-cli/vendor/ripgrep/x64-win32/rg.exe +0 -0
  30. package/dist/claude-cli/vendor/ripgrep/x64-win32/ripgrep.node +0 -0
  31. package/dist/gateway-models.d.ts +24 -0
  32. package/dist/gateway-models.js +93 -0
  33. package/dist/gateway-models.js.map +1 -0
  34. package/dist/index.d.ts +172 -1203
  35. package/dist/index.js +3704 -6826
  36. package/dist/index.js.map +1 -1
  37. package/dist/logger-DDBiMOOD.d.ts +24 -0
  38. package/dist/posthog-api.d.ts +40 -0
  39. package/dist/posthog-api.js +175 -0
  40. package/dist/posthog-api.js.map +1 -0
  41. package/dist/server/agent-server.d.ts +41 -0
  42. package/dist/server/agent-server.js +4451 -0
  43. package/dist/server/agent-server.js.map +1 -0
  44. package/dist/server/bin.d.ts +1 -0
  45. package/dist/server/bin.js +4507 -0
  46. package/dist/server/bin.js.map +1 -0
  47. package/dist/types.d.ts +129 -0
  48. package/dist/types.js +1 -0
  49. package/dist/types.js.map +1 -0
  50. package/package.json +66 -14
  51. package/src/acp-extensions.ts +93 -61
  52. package/src/adapters/acp-connection.ts +494 -0
  53. package/src/adapters/base-acp-agent.ts +150 -0
  54. package/src/adapters/claude/claude-agent.ts +596 -0
  55. package/src/adapters/claude/conversion/acp-to-sdk.ts +102 -0
  56. package/src/adapters/claude/conversion/sdk-to-acp.ts +571 -0
  57. package/src/adapters/claude/conversion/tool-use-to-acp.ts +618 -0
  58. package/src/adapters/claude/hooks.ts +64 -0
  59. package/src/adapters/claude/mcp/tool-metadata.ts +102 -0
  60. package/src/adapters/claude/permissions/permission-handlers.ts +433 -0
  61. package/src/adapters/claude/permissions/permission-options.ts +103 -0
  62. package/src/adapters/claude/plan/utils.ts +56 -0
  63. package/src/adapters/claude/questions/utils.ts +92 -0
  64. package/src/adapters/claude/session/commands.ts +38 -0
  65. package/src/adapters/claude/session/mcp-config.ts +37 -0
  66. package/src/adapters/claude/session/models.ts +12 -0
  67. package/src/adapters/claude/session/options.ts +236 -0
  68. package/src/adapters/claude/tool-meta.ts +143 -0
  69. package/src/adapters/claude/tools.ts +53 -611
  70. package/src/adapters/claude/types.ts +61 -0
  71. package/src/adapters/codex/spawn.ts +130 -0
  72. package/src/agent.ts +97 -734
  73. package/src/execution-mode.ts +43 -0
  74. package/src/gateway-models.ts +135 -0
  75. package/src/index.ts +79 -0
  76. package/src/otel-log-writer.test.ts +105 -0
  77. package/src/otel-log-writer.ts +94 -0
  78. package/src/posthog-api.ts +75 -235
  79. package/src/resume.ts +115 -0
  80. package/src/sagas/apply-snapshot-saga.test.ts +690 -0
  81. package/src/sagas/apply-snapshot-saga.ts +88 -0
  82. package/src/sagas/capture-tree-saga.test.ts +892 -0
  83. package/src/sagas/capture-tree-saga.ts +141 -0
  84. package/src/sagas/resume-saga.test.ts +558 -0
  85. package/src/sagas/resume-saga.ts +332 -0
  86. package/src/sagas/test-fixtures.ts +250 -0
  87. package/src/server/agent-server.test.ts +220 -0
  88. package/src/server/agent-server.ts +748 -0
  89. package/src/server/bin.ts +88 -0
  90. package/src/server/jwt.ts +65 -0
  91. package/src/server/schemas.ts +47 -0
  92. package/src/server/types.ts +13 -0
  93. package/src/server/utils/retry.test.ts +122 -0
  94. package/src/server/utils/retry.ts +61 -0
  95. package/src/server/utils/sse-parser.test.ts +93 -0
  96. package/src/server/utils/sse-parser.ts +46 -0
  97. package/src/session-log-writer.test.ts +140 -0
  98. package/src/session-log-writer.ts +137 -0
  99. package/src/test/assertions.ts +114 -0
  100. package/src/test/controllers/sse-controller.ts +107 -0
  101. package/src/test/fixtures/api.ts +111 -0
  102. package/src/test/fixtures/config.ts +33 -0
  103. package/src/test/fixtures/notifications.ts +92 -0
  104. package/src/test/mocks/claude-sdk.ts +251 -0
  105. package/src/test/mocks/msw-handlers.ts +48 -0
  106. package/src/test/setup.ts +114 -0
  107. package/src/test/wait.ts +41 -0
  108. package/src/tree-tracker.ts +173 -0
  109. package/src/types.ts +51 -154
  110. package/src/utils/acp-content.ts +58 -0
  111. package/src/utils/async-mutex.test.ts +104 -0
  112. package/src/utils/async-mutex.ts +31 -0
  113. package/src/utils/common.ts +15 -0
  114. package/src/utils/gateway.ts +9 -6
  115. package/src/utils/logger.ts +0 -30
  116. package/src/utils/streams.ts +220 -0
  117. package/CLAUDE.md +0 -331
  118. package/dist/templates/plan-template.md +0 -41
  119. package/src/adapters/claude/claude.ts +0 -1543
  120. package/src/adapters/claude/mcp-server.ts +0 -810
  121. package/src/adapters/claude/utils.ts +0 -267
  122. package/src/agents/execution.ts +0 -37
  123. package/src/agents/planning.ts +0 -60
  124. package/src/agents/research.ts +0 -160
  125. package/src/file-manager.ts +0 -306
  126. package/src/git-manager.ts +0 -577
  127. package/src/prompt-builder.ts +0 -499
  128. package/src/schemas.ts +0 -241
  129. package/src/session-store.ts +0 -259
  130. package/src/task-manager.ts +0 -163
  131. package/src/template-manager.ts +0 -236
  132. package/src/templates/plan-template.md +0 -41
  133. package/src/todo-manager.ts +0 -180
  134. package/src/tools/registry.ts +0 -129
  135. package/src/tools/types.ts +0 -127
  136. package/src/utils/tapped-stream.ts +0 -60
  137. package/src/workflow/config.ts +0 -53
  138. package/src/workflow/steps/build.ts +0 -135
  139. package/src/workflow/steps/finalize.ts +0 -241
  140. package/src/workflow/steps/plan.ts +0 -167
  141. package/src/workflow/steps/research.ts +0 -223
  142. package/src/workflow/types.ts +0 -62
  143. package/src/workflow/utils.ts +0 -53
  144. package/src/worktree-manager.ts +0 -928
@@ -1,223 +0,0 @@
1
- import { query } from "@anthropic-ai/claude-agent-sdk";
2
- import { POSTHOG_NOTIFICATIONS } from "../../acp-extensions.js";
3
- import { RESEARCH_SYSTEM_PROMPT } from "../../agents/research.js";
4
- import type { ResearchEvaluation } from "../../types.js";
5
- import type { WorkflowStepRunner } from "../types.js";
6
- import { finalizeStepGitActions } from "../utils.js";
7
-
8
- export const researchStep: WorkflowStepRunner = async ({ step, context }) => {
9
- const {
10
- task,
11
- cwd,
12
- isCloudMode,
13
- options,
14
- logger,
15
- fileManager,
16
- gitManager,
17
- promptBuilder,
18
- sessionId,
19
- mcpServers,
20
- sendNotification,
21
- } = context;
22
-
23
- const stepLogger = logger.child("ResearchStep");
24
-
25
- const existingResearch = await fileManager.readResearch(task.id);
26
- if (existingResearch) {
27
- stepLogger.info("Research already exists", {
28
- taskId: task.id,
29
- hasQuestions: !!existingResearch.questions,
30
- answered: existingResearch.answered,
31
- });
32
-
33
- // If there are unanswered questions, re-emit them so UI can prompt user
34
- if (existingResearch.questions && !existingResearch.answered) {
35
- stepLogger.info("Re-emitting unanswered research questions", {
36
- taskId: task.id,
37
- questionCount: existingResearch.questions.length,
38
- });
39
-
40
- await sendNotification(POSTHOG_NOTIFICATIONS.ARTIFACT, {
41
- sessionId,
42
- kind: "research_questions",
43
- content: existingResearch.questions,
44
- });
45
-
46
- // In local mode, halt to allow user to answer
47
- if (!isCloudMode) {
48
- await sendNotification(POSTHOG_NOTIFICATIONS.PHASE_COMPLETE, {
49
- sessionId,
50
- phase: "research",
51
- });
52
- return { status: "skipped", halt: true };
53
- }
54
- }
55
-
56
- return { status: "skipped" };
57
- }
58
-
59
- stepLogger.info("Starting research phase", { taskId: task.id });
60
- await sendNotification(POSTHOG_NOTIFICATIONS.PHASE_START, {
61
- sessionId,
62
- phase: "research",
63
- });
64
-
65
- const researchPrompt = await promptBuilder.buildResearchPrompt(task, cwd);
66
- const fullPrompt = `${RESEARCH_SYSTEM_PROMPT}\n\n${researchPrompt}`;
67
-
68
- const baseOptions: Record<string, unknown> = {
69
- model: step.model,
70
- cwd,
71
- permissionMode: "plan",
72
- settingSources: ["local"],
73
- mcpServers,
74
- // Allow research tools: read-only operations, web search, and MCP resources
75
- allowedTools: [
76
- "Read",
77
- "Glob",
78
- "Grep",
79
- "WebFetch",
80
- "WebSearch",
81
- "ListMcpResources",
82
- "ReadMcpResource",
83
- "TodoWrite",
84
- "BashOutput",
85
- ],
86
- };
87
-
88
- const response = query({
89
- prompt: fullPrompt,
90
- options: { ...baseOptions, ...(options.queryOverrides || {}) },
91
- });
92
-
93
- let jsonContent = "";
94
- try {
95
- for await (const message of response) {
96
- // Extract text content from assistant messages
97
- if (message.type === "assistant" && message.message?.content) {
98
- for (const c of message.message.content) {
99
- if (c.type === "text" && c.text) {
100
- jsonContent += c.text;
101
- }
102
- }
103
- }
104
- }
105
- } catch (error) {
106
- stepLogger.error("Error during research step query", error);
107
- throw error;
108
- }
109
-
110
- if (!jsonContent.trim()) {
111
- stepLogger.error("No JSON output from research agent", { taskId: task.id });
112
- await sendNotification(POSTHOG_NOTIFICATIONS.ERROR, {
113
- sessionId,
114
- message: "Research agent returned no output",
115
- });
116
- return { status: "completed", halt: true };
117
- }
118
-
119
- // Parse JSON response
120
- let evaluation: ResearchEvaluation;
121
- try {
122
- // Extract JSON from potential markdown code blocks or other wrapping
123
- const jsonMatch = jsonContent.match(/\{[\s\S]*\}/);
124
- if (!jsonMatch) {
125
- throw new Error("No JSON object found in response");
126
- }
127
- evaluation = JSON.parse(jsonMatch[0]);
128
- stepLogger.info("Parsed research evaluation", {
129
- taskId: task.id,
130
- score: evaluation.actionabilityScore,
131
- hasQuestions: !!evaluation.questions,
132
- });
133
- } catch (error) {
134
- stepLogger.error("Failed to parse research JSON", {
135
- taskId: task.id,
136
- error: error instanceof Error ? error.message : String(error),
137
- content: jsonContent.substring(0, 500),
138
- });
139
- await sendNotification(POSTHOG_NOTIFICATIONS.ERROR, {
140
- sessionId,
141
- message: `Failed to parse research JSON: ${
142
- error instanceof Error ? error.message : String(error)
143
- }`,
144
- });
145
- return { status: "completed", halt: true };
146
- }
147
-
148
- // Add answered/answers fields to evaluation
149
- if (evaluation.questions && evaluation.questions.length > 0) {
150
- evaluation.answered = false;
151
- evaluation.answers = undefined;
152
- }
153
-
154
- // Always write research.json
155
- await fileManager.writeResearch(task.id, evaluation);
156
- stepLogger.info("Research evaluation written", {
157
- taskId: task.id,
158
- score: evaluation.actionabilityScore,
159
- hasQuestions: !!evaluation.questions,
160
- });
161
-
162
- await sendNotification(POSTHOG_NOTIFICATIONS.ARTIFACT, {
163
- sessionId,
164
- kind: "research_evaluation",
165
- content: evaluation,
166
- });
167
-
168
- await gitManager.addAllPostHogFiles();
169
- await finalizeStepGitActions(context, step, {
170
- commitMessage: `Research phase for ${task.title}`,
171
- });
172
-
173
- // Log whether questions need answering
174
- if (
175
- evaluation.actionabilityScore < 0.7 &&
176
- evaluation.questions &&
177
- evaluation.questions.length > 0
178
- ) {
179
- stepLogger.info("Actionability score below threshold, questions needed", {
180
- taskId: task.id,
181
- score: evaluation.actionabilityScore,
182
- questionCount: evaluation.questions.length,
183
- });
184
-
185
- await sendNotification(POSTHOG_NOTIFICATIONS.ARTIFACT, {
186
- sessionId,
187
- kind: "research_questions",
188
- content: evaluation.questions,
189
- });
190
- } else {
191
- stepLogger.info("Actionability score acceptable, proceeding to planning", {
192
- taskId: task.id,
193
- score: evaluation.actionabilityScore,
194
- });
195
- }
196
-
197
- // In local mode, always halt after research for user review
198
- if (!isCloudMode) {
199
- await sendNotification(POSTHOG_NOTIFICATIONS.PHASE_COMPLETE, {
200
- sessionId,
201
- phase: "research",
202
- });
203
- return { status: "completed", halt: true };
204
- }
205
-
206
- // In cloud mode, check if questions need answering
207
- const researchData = await fileManager.readResearch(task.id);
208
- if (researchData?.questions && !researchData.answered) {
209
- // Questions need answering - halt for user input in cloud mode too
210
- await sendNotification(POSTHOG_NOTIFICATIONS.PHASE_COMPLETE, {
211
- sessionId,
212
- phase: "research",
213
- });
214
- return { status: "completed", halt: true };
215
- }
216
-
217
- // No questions or questions already answered - proceed to planning
218
- await sendNotification(POSTHOG_NOTIFICATIONS.PHASE_COMPLETE, {
219
- sessionId,
220
- phase: "research",
221
- });
222
- return { status: "completed" };
223
- };
@@ -1,62 +0,0 @@
1
- import type { AgentSideConnection } from "@agentclientprotocol/sdk";
2
- import type { PostHogFileManager } from "../file-manager.js";
3
- import type { GitManager } from "../git-manager.js";
4
- import type { PostHogAPIClient } from "../posthog-api.js";
5
- import type { PromptBuilder } from "../prompt-builder.js";
6
- import type { PermissionMode, Task, TaskExecutionOptions } from "../types.js";
7
- import type { Logger } from "../utils/logger.js";
8
-
9
- /**
10
- * Function type for sending custom PostHog notifications via ACP extNotification.
11
- * Used by workflow steps to emit artifacts, phase updates, etc.
12
- */
13
- export type SendNotification = (
14
- method: string,
15
- params: Record<string, unknown>,
16
- ) => Promise<void>;
17
-
18
- export interface WorkflowRuntime {
19
- task: Task;
20
- taskSlug: string;
21
- runId: string;
22
- cwd: string;
23
- isCloudMode: boolean;
24
- options: TaskExecutionOptions;
25
- logger: Logger;
26
- fileManager: PostHogFileManager;
27
- gitManager: GitManager;
28
- promptBuilder: PromptBuilder;
29
- connection: AgentSideConnection;
30
- sessionId: string;
31
- mcpServers?: Record<string, unknown>;
32
- posthogAPI?: PostHogAPIClient;
33
- sendNotification: SendNotification;
34
- stepResults: Record<string, unknown>;
35
- }
36
-
37
- export interface WorkflowStepDefinition {
38
- id: string;
39
- name: string;
40
- agent: string;
41
- model: string;
42
- permissionMode?: PermissionMode | string;
43
- commit?: boolean;
44
- push?: boolean;
45
- run: WorkflowStepRunner;
46
- }
47
-
48
- export interface WorkflowStepRuntime {
49
- step: WorkflowStepDefinition;
50
- context: WorkflowRuntime;
51
- }
52
-
53
- export interface WorkflowStepResult {
54
- status: "completed" | "skipped";
55
- halt?: boolean;
56
- }
57
-
58
- export type WorkflowStepRunner = (
59
- runtime: WorkflowStepRuntime,
60
- ) => Promise<WorkflowStepResult>;
61
-
62
- export type WorkflowDefinition = WorkflowStepDefinition[];
@@ -1,53 +0,0 @@
1
- import type { WorkflowRuntime, WorkflowStepDefinition } from "./types.js";
2
-
3
- interface FinalizeGitOptions {
4
- commitMessage: string;
5
- allowEmptyCommit?: boolean;
6
- }
7
-
8
- /**
9
- * Commits (and optionally pushes) any staged changes according to the step configuration.
10
- * Returns true if a commit was created.
11
- */
12
- export async function finalizeStepGitActions(
13
- context: WorkflowRuntime,
14
- step: WorkflowStepDefinition,
15
- options: FinalizeGitOptions,
16
- ): Promise<boolean> {
17
- if (!step.commit) {
18
- return false;
19
- }
20
-
21
- const { gitManager, logger } = context;
22
- const hasStagedChanges = await gitManager.hasStagedChanges();
23
-
24
- if (!hasStagedChanges && !options.allowEmptyCommit) {
25
- logger.debug("No staged changes to commit for step", { stepId: step.id });
26
- return false;
27
- }
28
-
29
- try {
30
- await gitManager.commitChanges(options.commitMessage);
31
- logger.info("Committed changes for step", {
32
- stepId: step.id,
33
- message: options.commitMessage,
34
- });
35
- } catch (error) {
36
- logger.error("Failed to commit changes for step", {
37
- stepId: step.id,
38
- error: error instanceof Error ? error.message : String(error),
39
- });
40
- throw error;
41
- }
42
-
43
- if (step.push) {
44
- const branchName = await gitManager.getCurrentBranch();
45
- await gitManager.pushBranch(branchName);
46
- logger.info("Pushed branch after step", {
47
- stepId: step.id,
48
- branch: branchName,
49
- });
50
- }
51
-
52
- return true;
53
- }