@posthog/agent 2.1.120 → 2.1.125

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@posthog/agent",
3
- "version": "2.1.120",
3
+ "version": "2.1.125",
4
4
  "repository": "https://github.com/PostHog/twig",
5
5
  "description": "TypeScript agent framework wrapping Claude Agent SDK with Git-based task execution for PostHog",
6
6
  "exports": {
@@ -76,8 +76,8 @@
76
76
  },
77
77
  "dependencies": {
78
78
  "@agentclientprotocol/sdk": "^0.14.0",
79
- "@anthropic-ai/claude-agent-sdk": "0.2.59",
80
- "@anthropic-ai/sdk": "^0.71.0",
79
+ "@anthropic-ai/claude-agent-sdk": "0.2.63",
80
+ "@anthropic-ai/sdk": "^0.78.0",
81
81
  "@hono/node-server": "^1.19.9",
82
82
  "@opentelemetry/api-logs": "^0.208.0",
83
83
  "@opentelemetry/exporter-logs-otlp-http": "^0.208.0",
@@ -257,6 +257,8 @@ function processContentChunk(
257
257
  case "citations_delta":
258
258
  case "signature_delta":
259
259
  case "container_upload":
260
+ case "compaction":
261
+ case "compaction_delta":
260
262
  return null;
261
263
 
262
264
  default:
@@ -1,5 +1,6 @@
1
1
  import { type ChildProcess, spawn } from "node:child_process";
2
2
  import { existsSync } from "node:fs";
3
+ import { delimiter, dirname } from "node:path";
3
4
  import type { Readable, Writable } from "node:stream";
4
5
  import type { ProcessSpawnedCallback } from "../../types.js";
5
6
  import { Logger } from "../../utils/logger.js";
@@ -79,8 +80,8 @@ export function spawnCodexProcess(options: CodexProcessOptions): CodexProcess {
79
80
  const { command, args } = findCodexBinary(options);
80
81
 
81
82
  if (options.binaryPath && existsSync(options.binaryPath)) {
82
- const binDir = options.binaryPath.replace(/\/[^/]+$/, "");
83
- env.PATH = `${binDir}:${env.PATH ?? ""}`;
83
+ const binDir = dirname(options.binaryPath);
84
+ env.PATH = `${binDir}${delimiter}${env.PATH ?? ""}`;
84
85
  }
85
86
 
86
87
  logger.info("Spawning codex-acp process", {
@@ -100,7 +101,7 @@ export function spawnCodexProcess(options: CodexProcessOptions): CodexProcess {
100
101
  });
101
102
 
102
103
  child.stderr?.on("data", (data: Buffer) => {
103
- logger.debug("codex-acp stderr:", data.toString());
104
+ logger.error("codex-acp stderr:", data.toString());
104
105
  });
105
106
 
106
107
  child.on("error", (err) => {
@@ -7,6 +7,13 @@ import type { TaskRun } from "../types.js";
7
7
  import { AgentServer } from "./agent-server.js";
8
8
  import { type JwtPayload, SANDBOX_CONNECTION_AUDIENCE } from "./jwt.js";
9
9
 
10
+ interface TestableServer {
11
+ getInitialPromptOverride(run: TaskRun): string | null;
12
+ detectAndAttachPrUrl(payload: unknown, update: unknown): void;
13
+ detectedPrUrl: string | null;
14
+ buildCloudSystemPrompt(prUrl?: string | null): string;
15
+ }
16
+
10
17
  function createTestJwt(
11
18
  payload: JwtPayload,
12
19
  privateKey: string,
@@ -225,14 +232,18 @@ describe("AgentServer HTTP Mode", () => {
225
232
  const run = {
226
233
  state: { initial_prompt_override: "do something else" },
227
234
  } as unknown as TaskRun;
228
- const result = (s as any).getInitialPromptOverride(run);
235
+ const result = (s as unknown as TestableServer).getInitialPromptOverride(
236
+ run,
237
+ );
229
238
  expect(result).toBe("do something else");
230
239
  });
231
240
 
232
241
  it("returns null when override is absent", () => {
233
242
  const s = createServer();
234
243
  const run = { state: {} } as unknown as TaskRun;
235
- const result = (s as any).getInitialPromptOverride(run);
244
+ const result = (s as unknown as TestableServer).getInitialPromptOverride(
245
+ run,
246
+ );
236
247
  expect(result).toBeNull();
237
248
  });
238
249
 
@@ -241,7 +252,9 @@ describe("AgentServer HTTP Mode", () => {
241
252
  const run = {
242
253
  state: { initial_prompt_override: " " },
243
254
  } as unknown as TaskRun;
244
- const result = (s as any).getInitialPromptOverride(run);
255
+ const result = (s as unknown as TestableServer).getInitialPromptOverride(
256
+ run,
257
+ );
245
258
  expect(result).toBeNull();
246
259
  });
247
260
 
@@ -250,7 +263,9 @@ describe("AgentServer HTTP Mode", () => {
250
263
  const run = {
251
264
  state: { initial_prompt_override: 42 },
252
265
  } as unknown as TaskRun;
253
- const result = (s as any).getInitialPromptOverride(run);
266
+ const result = (s as unknown as TestableServer).getInitialPromptOverride(
267
+ run,
268
+ );
254
269
  expect(result).toBeNull();
255
270
  });
256
271
  });
@@ -274,8 +289,8 @@ describe("AgentServer HTTP Mode", () => {
274
289
  },
275
290
  };
276
291
 
277
- (s as any).detectAndAttachPrUrl(payload, update);
278
- expect((s as any).detectedPrUrl).toBe(
292
+ (s as unknown as TestableServer).detectAndAttachPrUrl(payload, update);
293
+ expect((s as unknown as TestableServer).detectedPrUrl).toBe(
279
294
  "https://github.com/PostHog/posthog/pull/42",
280
295
  );
281
296
  });
@@ -295,15 +310,15 @@ describe("AgentServer HTTP Mode", () => {
295
310
  },
296
311
  };
297
312
 
298
- (s as any).detectAndAttachPrUrl(payload, update);
299
- expect((s as any).detectedPrUrl).toBeNull();
313
+ (s as unknown as TestableServer).detectAndAttachPrUrl(payload, update);
314
+ expect((s as unknown as TestableServer).detectedPrUrl).toBeNull();
300
315
  });
301
316
  });
302
317
 
303
318
  describe("buildCloudSystemPrompt", () => {
304
319
  it("returns PR-aware prompt when prUrl is provided", () => {
305
320
  const s = createServer();
306
- const prompt = (s as any).buildCloudSystemPrompt(
321
+ const prompt = (s as unknown as TestableServer).buildCloudSystemPrompt(
307
322
  "https://github.com/org/repo/pull/1",
308
323
  );
309
324
  expect(prompt).toContain("Do NOT create a new branch");
@@ -314,14 +329,16 @@ describe("AgentServer HTTP Mode", () => {
314
329
 
315
330
  it("returns default prompt when no prUrl", () => {
316
331
  const s = createServer();
317
- const prompt = (s as any).buildCloudSystemPrompt();
332
+ const prompt = (s as unknown as TestableServer).buildCloudSystemPrompt();
318
333
  expect(prompt).toContain("Create a new branch");
319
334
  expect(prompt).toContain("Create a pull request");
320
335
  });
321
336
 
322
337
  it("returns default prompt when prUrl is null", () => {
323
338
  const s = createServer();
324
- const prompt = (s as any).buildCloudSystemPrompt(null);
339
+ const prompt = (s as unknown as TestableServer).buildCloudSystemPrompt(
340
+ null,
341
+ );
325
342
  expect(prompt).toContain("Create a new branch");
326
343
  expect(prompt).toContain("Create a pull request");
327
344
  });
@@ -1,10 +1,30 @@
1
1
  import { type SetupServerApi, setupServer } from "msw/node";
2
2
  import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
3
+ import type { PostHogAPIClient } from "../posthog-api.js";
3
4
  import { createTestRepo, type TestRepo } from "../test/fixtures/api.js";
4
5
  import { createPostHogHandlers } from "../test/mocks/msw-handlers.js";
6
+ import type { Task, TaskRun } from "../types.js";
5
7
  import { AgentServer } from "./agent-server.js";
6
8
 
7
- /* eslint-disable @typescript-eslint/no-explicit-any */
9
+ interface TestableAgentServer {
10
+ posthogAPI: PostHogAPIClient;
11
+ isQuestionMeta: (value: unknown) => boolean;
12
+ getFirstQuestionMeta: (meta: unknown) => unknown;
13
+ relaySlackQuestion: (payload: Record<string, unknown>, meta: unknown) => void;
14
+ createCloudClient: (payload: Record<string, unknown>) => {
15
+ requestPermission: (opts: {
16
+ options: unknown[];
17
+ toolCall: unknown;
18
+ }) => Promise<{
19
+ outcome: { outcome: string };
20
+ _meta?: { message?: string };
21
+ }>;
22
+ };
23
+ questionRelayedToSlack: boolean;
24
+ session: unknown;
25
+ relayAgentResponse: (payload: Record<string, unknown>) => Promise<void>;
26
+ sendInitialTaskMessage: (payload: Record<string, unknown>) => Promise<void>;
27
+ }
8
28
 
9
29
  const TEST_PAYLOAD = {
10
30
  run_id: "test-run-id",
@@ -31,7 +51,7 @@ const QUESTION_META = {
31
51
 
32
52
  describe("Question relay", () => {
33
53
  let repo: TestRepo;
34
- let server: any;
54
+ let server: TestableAgentServer;
35
55
  let mswServer: SetupServerApi;
36
56
  const port = 3098;
37
57
 
@@ -52,7 +72,7 @@ describe("Question relay", () => {
52
72
  mode: "interactive",
53
73
  taskId: "test-task-id",
54
74
  runId: "test-run-id",
55
- });
75
+ }) as unknown as TestableAgentServer;
56
76
  });
57
77
 
58
78
  afterEach(async () => {
@@ -291,12 +311,12 @@ describe("Question relay", () => {
291
311
  id: "test-task-id",
292
312
  title: "t",
293
313
  description: "original task description",
294
- } as any);
314
+ } as unknown as Task);
295
315
  vi.spyOn(server.posthogAPI, "getTaskRun").mockResolvedValue({
296
316
  id: "test-run-id",
297
317
  task: "test-task-id",
298
318
  state: { initial_prompt_override: "override instruction" },
299
- } as any);
319
+ } as unknown as TaskRun);
300
320
 
301
321
  const promptSpy = vi.fn().mockResolvedValue({ stopReason: "max_tokens" });
302
322
  server.session = {
@@ -318,12 +338,12 @@ describe("Question relay", () => {
318
338
  id: "test-task-id",
319
339
  title: "t",
320
340
  description: "original task description",
321
- } as any);
341
+ } as unknown as Task);
322
342
  vi.spyOn(server.posthogAPI, "getTaskRun").mockResolvedValue({
323
343
  id: "test-run-id",
324
344
  task: "test-task-id",
325
345
  state: {},
326
- } as any);
346
+ } as unknown as TaskRun);
327
347
 
328
348
  const promptSpy = vi.fn().mockResolvedValue({ stopReason: "max_tokens" });
329
349
  server.session = {
@@ -99,6 +99,7 @@ export function createMockQuery(
99
99
  initializationResult: vi.fn().mockResolvedValue({}),
100
100
  reconnectMcpServer: vi.fn().mockResolvedValue(undefined),
101
101
  toggleMcpServer: vi.fn().mockResolvedValue(undefined),
102
+ supportedAgents: vi.fn().mockResolvedValue([]),
102
103
  stopTask: vi.fn().mockResolvedValue(undefined),
103
104
  [Symbol.asyncDispose]: vi.fn().mockResolvedValue(undefined),
104
105
  _abortController: abortController,
@@ -176,6 +177,9 @@ export function createSuccessResult(
176
177
  },
177
178
  server_tool_use: { web_search_requests: 0, web_fetch_requests: 0 },
178
179
  service_tier: "standard",
180
+ inference_geo: "us",
181
+ iterations: [],
182
+ speed: "standard",
179
183
  },
180
184
  modelUsage: {},
181
185
  permission_denials: [],
@@ -209,6 +213,9 @@ export function createErrorResult(
209
213
  },
210
214
  server_tool_use: { web_search_requests: 0, web_fetch_requests: 0 },
211
215
  service_tier: "standard",
216
+ inference_geo: "us",
217
+ iterations: [],
218
+ speed: "standard",
212
219
  },
213
220
  modelUsage: {},
214
221
  permission_denials: [],