@posthog/agent 2.3.504 → 2.3.508
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 +154 -10
- package/dist/agent.js.map +1 -1
- package/dist/posthog-api.js +1 -1
- package/dist/posthog-api.js.map +1 -1
- package/dist/server/agent-server.js +166 -12
- package/dist/server/agent-server.js.map +1 -1
- package/dist/server/bin.cjs +166 -12
- package/dist/server/bin.cjs.map +1 -1
- package/package.json +3 -3
- package/src/adapters/claude/hooks.test.ts +125 -1
- package/src/adapters/claude/hooks.ts +24 -0
- package/src/adapters/claude/permissions/permission-handlers.test.ts +152 -0
- package/src/adapters/claude/permissions/permission-handlers.ts +109 -15
- package/src/adapters/claude/permissions/posthog-exec-gate.test.ts +84 -0
- package/src/adapters/claude/permissions/posthog-exec-gate.ts +30 -0
- package/src/adapters/claude/session/settings.test.ts +50 -0
- package/src/adapters/claude/session/settings.ts +48 -0
- package/src/server/agent-server.test.ts +43 -0
- package/src/server/agent-server.ts +16 -2
|
@@ -196,6 +196,7 @@ export interface ClaudeCodeSettings {
|
|
|
196
196
|
permissions?: PermissionSettings;
|
|
197
197
|
env?: Record<string, string>;
|
|
198
198
|
model?: string;
|
|
199
|
+
posthogApprovedExecTools?: string[];
|
|
199
200
|
}
|
|
200
201
|
|
|
201
202
|
export type PermissionDecision = "allow" | "deny" | "ask";
|
|
@@ -295,6 +296,7 @@ export class SettingsManager {
|
|
|
295
296
|
ask: [],
|
|
296
297
|
};
|
|
297
298
|
const merged: ClaudeCodeSettings = { permissions };
|
|
299
|
+
const posthogApprovedExecTools = new Set<string>();
|
|
298
300
|
|
|
299
301
|
for (const settings of allSettings) {
|
|
300
302
|
if (settings.permissions) {
|
|
@@ -323,6 +325,15 @@ export class SettingsManager {
|
|
|
323
325
|
if (settings.model) {
|
|
324
326
|
merged.model = settings.model;
|
|
325
327
|
}
|
|
328
|
+
if (settings.posthogApprovedExecTools) {
|
|
329
|
+
for (const tool of settings.posthogApprovedExecTools) {
|
|
330
|
+
posthogApprovedExecTools.add(tool);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
if (posthogApprovedExecTools.size > 0) {
|
|
336
|
+
merged.posthogApprovedExecTools = Array.from(posthogApprovedExecTools);
|
|
326
337
|
}
|
|
327
338
|
|
|
328
339
|
this.mergedSettings = merged;
|
|
@@ -405,6 +416,43 @@ export class SettingsManager {
|
|
|
405
416
|
}
|
|
406
417
|
}
|
|
407
418
|
|
|
419
|
+
hasPostHogExecApproval(subTool: string): boolean {
|
|
420
|
+
return (
|
|
421
|
+
this.mergedSettings.posthogApprovedExecTools?.includes(subTool) ?? false
|
|
422
|
+
);
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Persists an approved PostHog MCP `exec` sub-tool (e.g. `experiment-update`)
|
|
427
|
+
* to the local settings file so future calls skip the prompt. Mirrors
|
|
428
|
+
* `addAllowRules` — serialised via `writeMutex`, atomic temp-file + rename.
|
|
429
|
+
*/
|
|
430
|
+
async addPostHogExecApproval(subTool: string): Promise<void> {
|
|
431
|
+
if (!subTool) return;
|
|
432
|
+
if (!this.initialized) await this.initialize();
|
|
433
|
+
await this.writeMutex.acquire();
|
|
434
|
+
try {
|
|
435
|
+
const filePath = this.getLocalSettingsPath();
|
|
436
|
+
const existing = await readSettingsFileForUpdate(filePath);
|
|
437
|
+
const current = new Set(existing.posthogApprovedExecTools ?? []);
|
|
438
|
+
if (current.has(subTool)) {
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
441
|
+
current.add(subTool);
|
|
442
|
+
const next: ClaudeCodeSettings = {
|
|
443
|
+
...existing,
|
|
444
|
+
posthogApprovedExecTools: Array.from(current),
|
|
445
|
+
};
|
|
446
|
+
await fs.promises.mkdir(path.dirname(filePath), { recursive: true });
|
|
447
|
+
await writeFileAtomic(filePath, `${JSON.stringify(next, null, 2)}\n`);
|
|
448
|
+
|
|
449
|
+
this.localSettings = next;
|
|
450
|
+
this.mergeAllSettings();
|
|
451
|
+
} finally {
|
|
452
|
+
this.writeMutex.release();
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
408
456
|
async setCwd(cwd: string): Promise<void> {
|
|
409
457
|
if (this.cwd === cwd) return;
|
|
410
458
|
if (this.initPromise) await this.initPromise;
|
|
@@ -639,6 +639,49 @@ describe("AgentServer HTTP Mode", () => {
|
|
|
639
639
|
expect(prompt).toContain("stop with local changes ready for review");
|
|
640
640
|
});
|
|
641
641
|
|
|
642
|
+
it.each([
|
|
643
|
+
{
|
|
644
|
+
label: "createPr unset",
|
|
645
|
+
config: { repositoryPath: undefined },
|
|
646
|
+
shouldContain: [
|
|
647
|
+
"Cloud Task Execution — No Repository Mode",
|
|
648
|
+
"Clone the repository into /tmp/workspace/repos/<owner>/<repo>",
|
|
649
|
+
"gh repo clone <owner>/<repo> /tmp/workspace/repos/<owner>/<repo>",
|
|
650
|
+
"If the user explicitly asks you to open or update a pull request",
|
|
651
|
+
"open a draft pull request",
|
|
652
|
+
"unless the user explicitly asks",
|
|
653
|
+
"Generated-By: PostHog Code",
|
|
654
|
+
"Task-Id: test-task-id",
|
|
655
|
+
],
|
|
656
|
+
shouldNotContain: [],
|
|
657
|
+
},
|
|
658
|
+
{
|
|
659
|
+
label: "createPr false",
|
|
660
|
+
config: { repositoryPath: undefined, createPr: false },
|
|
661
|
+
shouldContain: [
|
|
662
|
+
"Cloud Task Execution — No Repository Mode",
|
|
663
|
+
"You may clone a repository and make local edits in that clone",
|
|
664
|
+
"Do NOT create branches, commits, push changes, or open pull requests in this run",
|
|
665
|
+
],
|
|
666
|
+
shouldNotContain: ["open a draft pull request", "gh pr create --draft"],
|
|
667
|
+
},
|
|
668
|
+
])(
|
|
669
|
+
"returns no-repository prompt for $label",
|
|
670
|
+
({ config, shouldContain, shouldNotContain }) => {
|
|
671
|
+
const s = createServer(config);
|
|
672
|
+
const prompt = (
|
|
673
|
+
s as unknown as TestableServer
|
|
674
|
+
).buildCloudSystemPrompt();
|
|
675
|
+
|
|
676
|
+
for (const text of shouldContain) {
|
|
677
|
+
expect(prompt).toContain(text);
|
|
678
|
+
}
|
|
679
|
+
for (const text of shouldNotContain) {
|
|
680
|
+
expect(prompt).not.toContain(text);
|
|
681
|
+
}
|
|
682
|
+
},
|
|
683
|
+
);
|
|
684
|
+
|
|
642
685
|
it("returns auto-PR prompt for Slack-origin runs", () => {
|
|
643
686
|
process.env.POSTHOG_CODE_INTERACTION_ORIGIN = "slack";
|
|
644
687
|
const s = createServer();
|
|
@@ -1605,6 +1605,19 @@ ${attributionInstructions}
|
|
|
1605
1605
|
}
|
|
1606
1606
|
|
|
1607
1607
|
if (!this.config.repositoryPath) {
|
|
1608
|
+
const publishInstructions =
|
|
1609
|
+
this.config.createPr === false
|
|
1610
|
+
? `
|
|
1611
|
+
When the user asks for code changes:
|
|
1612
|
+
- You may clone a repository and make local edits in that clone
|
|
1613
|
+
- Do NOT create branches, commits, push changes, or open pull requests in this run`
|
|
1614
|
+
: `
|
|
1615
|
+
When the user explicitly asks to clone or work in a GitHub repository:
|
|
1616
|
+
- Clone the repository into /tmp/workspace/repos/<owner>/<repo> using \`gh repo clone <owner>/<repo> /tmp/workspace/repos/<owner>/<repo>\`
|
|
1617
|
+
- Work from inside that cloned repository for follow-up code changes
|
|
1618
|
+
- If the user explicitly asks you to open or update a pull request, create a branch, commit the requested changes, push it, and open a draft pull request from inside the clone
|
|
1619
|
+
- Do NOT create branches, commits, push changes, or open pull requests unless the user explicitly asks for that`;
|
|
1620
|
+
|
|
1608
1621
|
return `
|
|
1609
1622
|
# Cloud Task Execution — No Repository Mode
|
|
1610
1623
|
|
|
@@ -1617,11 +1630,12 @@ When the user asks about analytics, data, metrics, events, funnels, dashboards,
|
|
|
1617
1630
|
|
|
1618
1631
|
When the user asks for code changes or software engineering tasks:
|
|
1619
1632
|
- Let them know you can help but don't have a repository connected for this session
|
|
1620
|
-
-
|
|
1633
|
+
- If they have not specified a repository to clone, offer to write code snippets, scripts, or provide guidance
|
|
1634
|
+
${publishInstructions}
|
|
1621
1635
|
|
|
1622
1636
|
Important:
|
|
1623
|
-
- Do NOT create branches, commits, or pull requests in this mode.
|
|
1624
1637
|
- Prefer using MCP tools to answer questions with real data over giving generic advice.
|
|
1638
|
+
${attributionInstructions}
|
|
1625
1639
|
`;
|
|
1626
1640
|
}
|
|
1627
1641
|
|