@posthog/agent 2.3.259 → 2.3.263
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/dist/agent.js +9 -2
- package/dist/agent.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/posthog-api.js +1 -1
- package/dist/posthog-api.js.map +1 -1
- package/dist/server/agent-server.d.ts +23 -0
- package/dist/server/agent-server.js +223 -20
- package/dist/server/agent-server.js.map +1 -1
- package/dist/server/bin.cjs +232 -21
- package/dist/server/bin.cjs.map +1 -1
- package/package.json +1 -1
- package/src/acp-extensions.ts +3 -0
- package/src/adapters/claude/permissions/permission-handlers.ts +11 -5
- package/src/server/agent-server.test.ts +140 -7
- package/src/server/agent-server.ts +317 -29
- package/src/server/bin.ts +13 -0
- package/src/server/question-relay.test.ts +34 -5
- package/src/server/schemas.test.ts +52 -0
- package/src/server/schemas.ts +16 -0
- package/src/server/types.ts +1 -0
package/package.json
CHANGED
package/src/acp-extensions.ts
CHANGED
|
@@ -63,6 +63,9 @@ export const POSTHOG_NOTIFICATIONS = {
|
|
|
63
63
|
|
|
64
64
|
/** Token usage update for a session turn */
|
|
65
65
|
USAGE_UPDATE: "_posthog/usage_update",
|
|
66
|
+
|
|
67
|
+
/** Response to a relayed permission request (plan approval, question) */
|
|
68
|
+
PERMISSION_RESPONSE: "_posthog/permission_response",
|
|
66
69
|
} as const;
|
|
67
70
|
|
|
68
71
|
type NotificationMethod =
|
|
@@ -490,11 +490,17 @@ export async function canUseTool(
|
|
|
490
490
|
return planFileResult;
|
|
491
491
|
}
|
|
492
492
|
|
|
493
|
-
//
|
|
494
|
-
//
|
|
495
|
-
//
|
|
496
|
-
//
|
|
497
|
-
|
|
493
|
+
// In plan mode, deny tools that aren't in the allowed set. The agent must
|
|
494
|
+
// write its plan to ~/.claude/plans/ and call ExitPlanMode before it can
|
|
495
|
+
// use write or bash tools. Without this guard, cloud runs auto-approve
|
|
496
|
+
// restricted tools and the agent skips planning entirely.
|
|
497
|
+
if (session.permissionMode === "plan") {
|
|
498
|
+
const message =
|
|
499
|
+
"This tool is not available in plan mode. Write your plan " +
|
|
500
|
+
`to a file in ${getClaudePlansDir()} and call ExitPlanMode when ready.`;
|
|
501
|
+
await emitToolDenial(context, message);
|
|
502
|
+
return { behavior: "deny", message, interrupt: false };
|
|
503
|
+
}
|
|
498
504
|
|
|
499
505
|
return handleDefaultPermissionFlow(context);
|
|
500
506
|
}
|
|
@@ -20,6 +20,7 @@ interface TestableServer {
|
|
|
20
20
|
detectAndAttachPrUrl(payload: unknown, update: unknown): void;
|
|
21
21
|
detectedPrUrl: string | null;
|
|
22
22
|
buildCloudSystemPrompt(prUrl?: string | null): string;
|
|
23
|
+
buildDetectedPrContext(prUrl: string): string;
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
// The Claude Agent SDK has an internal readMessages() loop that rejects with
|
|
@@ -380,14 +381,17 @@ describe("AgentServer HTTP Mode", () => {
|
|
|
380
381
|
});
|
|
381
382
|
|
|
382
383
|
describe("buildCloudSystemPrompt", () => {
|
|
383
|
-
it("returns
|
|
384
|
+
it("returns review-first prompt for existing PRs on non-Slack runs", () => {
|
|
384
385
|
const s = createServer();
|
|
385
386
|
const prompt = (s as unknown as TestableServer).buildCloudSystemPrompt(
|
|
386
387
|
"https://github.com/org/repo/pull/1",
|
|
387
388
|
);
|
|
388
|
-
expect(prompt).toContain("
|
|
389
|
+
expect(prompt).toContain("stop with local changes ready for review");
|
|
389
390
|
expect(prompt).toContain("https://github.com/org/repo/pull/1");
|
|
390
|
-
expect(prompt).toContain(
|
|
391
|
+
expect(prompt).toContain(
|
|
392
|
+
"Do NOT create new commits, push to the branch, or update the pull request unless the user explicitly asks.",
|
|
393
|
+
);
|
|
394
|
+
expect(prompt).not.toContain("gh pr checkout");
|
|
391
395
|
expect(prompt).not.toContain("Create a draft pull request");
|
|
392
396
|
expect(prompt).toContain("Generated-By: PostHog Code");
|
|
393
397
|
expect(prompt).toContain("Task-Id: test-task-id");
|
|
@@ -396,12 +400,13 @@ describe("AgentServer HTTP Mode", () => {
|
|
|
396
400
|
it("returns default prompt when no prUrl", () => {
|
|
397
401
|
const s = createServer();
|
|
398
402
|
const prompt = (s as unknown as TestableServer).buildCloudSystemPrompt();
|
|
399
|
-
expect(prompt).toContain("
|
|
400
|
-
expect(prompt).toContain(
|
|
401
|
-
|
|
403
|
+
expect(prompt).toContain("stop with local changes ready for review");
|
|
404
|
+
expect(prompt).toContain(
|
|
405
|
+
"Do NOT create a branch, commit, push, or open a pull request unless the user explicitly asks.",
|
|
406
|
+
);
|
|
402
407
|
expect(prompt).toContain("Generated-By: PostHog Code");
|
|
403
408
|
expect(prompt).toContain("Task-Id: test-task-id");
|
|
404
|
-
expect(prompt).toContain("
|
|
409
|
+
expect(prompt).not.toContain("gh pr create --draft");
|
|
405
410
|
});
|
|
406
411
|
|
|
407
412
|
it("returns default prompt when prUrl is null", () => {
|
|
@@ -409,12 +414,41 @@ describe("AgentServer HTTP Mode", () => {
|
|
|
409
414
|
const prompt = (s as unknown as TestableServer).buildCloudSystemPrompt(
|
|
410
415
|
null,
|
|
411
416
|
);
|
|
417
|
+
expect(prompt).toContain("stop with local changes ready for review");
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
it("returns auto-PR prompt for Slack-origin runs", () => {
|
|
421
|
+
process.env.POSTHOG_CODE_INTERACTION_ORIGIN = "slack";
|
|
422
|
+
const s = createServer();
|
|
423
|
+
const prompt = (s as unknown as TestableServer).buildCloudSystemPrompt();
|
|
412
424
|
expect(prompt).toContain("posthog-code/");
|
|
413
425
|
expect(prompt).toContain("Create a draft pull request");
|
|
414
426
|
expect(prompt).toContain("gh pr create --draft");
|
|
427
|
+
expect(prompt).toContain("Generated-By: PostHog Code");
|
|
428
|
+
expect(prompt).toContain("Task-Id: test-task-id");
|
|
429
|
+
expect(prompt).toContain("Created with [PostHog Code]");
|
|
430
|
+
delete process.env.POSTHOG_CODE_INTERACTION_ORIGIN;
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
it("returns PR-update prompt for existing PRs on Slack-origin runs", () => {
|
|
434
|
+
process.env.POSTHOG_CODE_INTERACTION_ORIGIN = "slack";
|
|
435
|
+
const s = createServer();
|
|
436
|
+
const prompt = (s as unknown as TestableServer).buildCloudSystemPrompt(
|
|
437
|
+
"https://github.com/org/repo/pull/1",
|
|
438
|
+
);
|
|
439
|
+
expect(prompt).toContain(
|
|
440
|
+
"gh pr checkout https://github.com/org/repo/pull/1",
|
|
441
|
+
);
|
|
442
|
+
expect(prompt).toContain(
|
|
443
|
+
"Stage and commit all changes with a clear commit message",
|
|
444
|
+
);
|
|
445
|
+
expect(prompt).toContain("Push to the existing PR branch");
|
|
446
|
+
expect(prompt).not.toContain("Create a draft pull request");
|
|
447
|
+
delete process.env.POSTHOG_CODE_INTERACTION_ORIGIN;
|
|
415
448
|
});
|
|
416
449
|
|
|
417
450
|
it("includes --base flag when baseBranch is configured", () => {
|
|
451
|
+
process.env.POSTHOG_CODE_INTERACTION_ORIGIN = "slack";
|
|
418
452
|
server = new AgentServer({
|
|
419
453
|
port,
|
|
420
454
|
jwtPublicKey: TEST_PUBLIC_KEY,
|
|
@@ -433,13 +467,112 @@ describe("AgentServer HTTP Mode", () => {
|
|
|
433
467
|
expect(prompt).toContain(
|
|
434
468
|
"gh pr create --draft --base add-yolo-to-readme",
|
|
435
469
|
);
|
|
470
|
+
delete process.env.POSTHOG_CODE_INTERACTION_ORIGIN;
|
|
436
471
|
});
|
|
437
472
|
|
|
438
473
|
it("omits --base flag when baseBranch is not configured", () => {
|
|
474
|
+
process.env.POSTHOG_CODE_INTERACTION_ORIGIN = "slack";
|
|
439
475
|
const s = createServer();
|
|
440
476
|
const prompt = (s as unknown as TestableServer).buildCloudSystemPrompt();
|
|
441
477
|
expect(prompt).toContain("gh pr create --draft`");
|
|
442
478
|
expect(prompt).not.toContain("--base");
|
|
479
|
+
delete process.env.POSTHOG_CODE_INTERACTION_ORIGIN;
|
|
480
|
+
});
|
|
481
|
+
|
|
482
|
+
it("disables auto-publish for Slack-origin runs when createPr is false", () => {
|
|
483
|
+
process.env.POSTHOG_CODE_INTERACTION_ORIGIN = "slack";
|
|
484
|
+
server = new AgentServer({
|
|
485
|
+
port,
|
|
486
|
+
jwtPublicKey: TEST_PUBLIC_KEY,
|
|
487
|
+
repositoryPath: repo.path,
|
|
488
|
+
apiUrl: "http://localhost:8000",
|
|
489
|
+
apiKey: "test-api-key",
|
|
490
|
+
projectId: 1,
|
|
491
|
+
mode: "interactive",
|
|
492
|
+
taskId: "test-task-id",
|
|
493
|
+
runId: "test-run-id",
|
|
494
|
+
createPr: false,
|
|
495
|
+
});
|
|
496
|
+
const prompt = (
|
|
497
|
+
server as unknown as TestableServer
|
|
498
|
+
).buildCloudSystemPrompt();
|
|
499
|
+
expect(prompt).toContain("stop with local changes ready for review");
|
|
500
|
+
expect(prompt).not.toContain("gh pr create --draft");
|
|
501
|
+
delete process.env.POSTHOG_CODE_INTERACTION_ORIGIN;
|
|
502
|
+
});
|
|
503
|
+
|
|
504
|
+
it("disables auto-publish for existing PRs when createPr is false", () => {
|
|
505
|
+
process.env.POSTHOG_CODE_INTERACTION_ORIGIN = "slack";
|
|
506
|
+
server = new AgentServer({
|
|
507
|
+
port,
|
|
508
|
+
jwtPublicKey: TEST_PUBLIC_KEY,
|
|
509
|
+
repositoryPath: repo.path,
|
|
510
|
+
apiUrl: "http://localhost:8000",
|
|
511
|
+
apiKey: "test-api-key",
|
|
512
|
+
projectId: 1,
|
|
513
|
+
mode: "interactive",
|
|
514
|
+
taskId: "test-task-id",
|
|
515
|
+
runId: "test-run-id",
|
|
516
|
+
createPr: false,
|
|
517
|
+
});
|
|
518
|
+
const prompt = (
|
|
519
|
+
server as unknown as TestableServer
|
|
520
|
+
).buildCloudSystemPrompt("https://github.com/org/repo/pull/1");
|
|
521
|
+
expect(prompt).toContain("stop with local changes ready for review");
|
|
522
|
+
expect(prompt).not.toContain("gh pr checkout");
|
|
523
|
+
expect(prompt).not.toContain("Push to the existing PR branch");
|
|
524
|
+
delete process.env.POSTHOG_CODE_INTERACTION_ORIGIN;
|
|
525
|
+
});
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
describe("buildDetectedPrContext", () => {
|
|
529
|
+
const prUrl = "https://github.com/org/repo/pull/1";
|
|
530
|
+
|
|
531
|
+
it("returns review-first PR context for non-Slack runs", () => {
|
|
532
|
+
const s = createServer();
|
|
533
|
+
const context = (s as unknown as TestableServer).buildDetectedPrContext(
|
|
534
|
+
prUrl,
|
|
535
|
+
);
|
|
536
|
+
expect(context).toContain("stop with local changes ready for review");
|
|
537
|
+
expect(context).toContain(
|
|
538
|
+
"Do NOT create commits, push to the PR branch, update the pull request",
|
|
539
|
+
);
|
|
540
|
+
expect(context).not.toContain("gh pr checkout");
|
|
541
|
+
});
|
|
542
|
+
|
|
543
|
+
it("returns auto-update PR context for Slack-origin runs", () => {
|
|
544
|
+
process.env.POSTHOG_CODE_INTERACTION_ORIGIN = "slack";
|
|
545
|
+
const s = createServer();
|
|
546
|
+
const context = (s as unknown as TestableServer).buildDetectedPrContext(
|
|
547
|
+
prUrl,
|
|
548
|
+
);
|
|
549
|
+
expect(context).toContain(`gh pr checkout ${prUrl}`);
|
|
550
|
+
expect(context).toContain(
|
|
551
|
+
"Make changes, commit, and push to that branch",
|
|
552
|
+
);
|
|
553
|
+
delete process.env.POSTHOG_CODE_INTERACTION_ORIGIN;
|
|
554
|
+
});
|
|
555
|
+
|
|
556
|
+
it("returns review-first PR context when createPr is false", () => {
|
|
557
|
+
process.env.POSTHOG_CODE_INTERACTION_ORIGIN = "slack";
|
|
558
|
+
server = new AgentServer({
|
|
559
|
+
port,
|
|
560
|
+
jwtPublicKey: TEST_PUBLIC_KEY,
|
|
561
|
+
repositoryPath: repo.path,
|
|
562
|
+
apiUrl: "http://localhost:8000",
|
|
563
|
+
apiKey: "test-api-key",
|
|
564
|
+
projectId: 1,
|
|
565
|
+
mode: "interactive",
|
|
566
|
+
taskId: "test-task-id",
|
|
567
|
+
runId: "test-run-id",
|
|
568
|
+
createPr: false,
|
|
569
|
+
});
|
|
570
|
+
const context = (
|
|
571
|
+
server as unknown as TestableServer
|
|
572
|
+
).buildDetectedPrContext(prUrl);
|
|
573
|
+
expect(context).toContain("stop with local changes ready for review");
|
|
574
|
+
expect(context).not.toContain("gh pr checkout");
|
|
575
|
+
delete process.env.POSTHOG_CODE_INTERACTION_ORIGIN;
|
|
443
576
|
});
|
|
444
577
|
});
|
|
445
578
|
});
|