@posthog/agent 2.3.443 → 2.3.449
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/adapters/claude/permissions/permission-options.d.ts +1 -1
- package/dist/adapters/claude/permissions/permission-options.js +26 -7
- package/dist/adapters/claude/permissions/permission-options.js.map +1 -1
- package/dist/agent.js +36 -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 +36 -10
- package/dist/server/agent-server.js.map +1 -1
- package/dist/server/bin.cjs +36 -10
- package/dist/server/bin.cjs.map +1 -1
- package/package.json +3 -3
- package/src/adapters/claude/claude-agent.ts +7 -0
- package/src/adapters/claude/permissions/permission-handlers.ts +2 -2
- package/src/adapters/claude/permissions/permission-options.test.ts +51 -0
- package/src/adapters/claude/permissions/permission-options.ts +33 -7
- package/src/adapters/claude/types.ts +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@posthog/agent",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.449",
|
|
4
4
|
"repository": "https://github.com/PostHog/code",
|
|
5
5
|
"description": "TypeScript agent framework wrapping Claude Agent SDK with Git-based task execution for PostHog",
|
|
6
6
|
"exports": {
|
|
@@ -103,8 +103,8 @@
|
|
|
103
103
|
"typescript": "^5.5.0",
|
|
104
104
|
"vitest": "^2.1.8",
|
|
105
105
|
"@posthog/shared": "1.0.0",
|
|
106
|
-
"@posthog/
|
|
107
|
-
"@posthog/
|
|
106
|
+
"@posthog/enricher": "1.0.0",
|
|
107
|
+
"@posthog/git": "1.0.0"
|
|
108
108
|
},
|
|
109
109
|
"dependencies": {
|
|
110
110
|
"@agentclientprotocol/sdk": "0.19.0",
|
|
@@ -1047,6 +1047,9 @@ export class ClaudeAcpAgent extends BaseAcpAgent {
|
|
|
1047
1047
|
}
|
|
1048
1048
|
const previousMode = this.session.permissionMode;
|
|
1049
1049
|
this.session.permissionMode = modeId as CodeExecutionMode;
|
|
1050
|
+
if (modeId === "plan" && previousMode !== "plan") {
|
|
1051
|
+
this.session.modeBeforePlan = previousMode;
|
|
1052
|
+
}
|
|
1050
1053
|
try {
|
|
1051
1054
|
await this.session.query.setPermissionMode(modeId as CodeExecutionMode);
|
|
1052
1055
|
} catch (error) {
|
|
@@ -1343,7 +1346,11 @@ export class ClaudeAcpAgent extends BaseAcpAgent {
|
|
|
1343
1346
|
private createOnModeChange() {
|
|
1344
1347
|
return async (newMode: CodeExecutionMode) => {
|
|
1345
1348
|
if (this.session) {
|
|
1349
|
+
const previousMode = this.session.permissionMode;
|
|
1346
1350
|
this.session.permissionMode = newMode;
|
|
1351
|
+
if (newMode === "plan" && previousMode !== "plan") {
|
|
1352
|
+
this.session.modeBeforePlan = previousMode;
|
|
1353
|
+
}
|
|
1347
1354
|
}
|
|
1348
1355
|
await this.updateConfigOption("mode", newMode);
|
|
1349
1356
|
};
|
|
@@ -142,7 +142,7 @@ async function requestPlanApproval(
|
|
|
142
142
|
context: ToolHandlerContext,
|
|
143
143
|
updatedInput: Record<string, unknown>,
|
|
144
144
|
): Promise<RequestPermissionResponse> {
|
|
145
|
-
const { client, sessionId, toolUseID } = context;
|
|
145
|
+
const { client, sessionId, toolUseID, session } = context;
|
|
146
146
|
|
|
147
147
|
const toolInfo = toolInfoFromToolUse({
|
|
148
148
|
name: context.toolName,
|
|
@@ -150,7 +150,7 @@ async function requestPlanApproval(
|
|
|
150
150
|
});
|
|
151
151
|
|
|
152
152
|
return await client.requestPermission({
|
|
153
|
-
options: buildExitPlanModePermissionOptions(),
|
|
153
|
+
options: buildExitPlanModePermissionOptions(session.modeBeforePlan),
|
|
154
154
|
sessionId,
|
|
155
155
|
toolCall: {
|
|
156
156
|
toolCallId: toolUseID,
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { buildExitPlanModePermissionOptions } from "./permission-options";
|
|
3
|
+
|
|
4
|
+
describe("buildExitPlanModePermissionOptions", () => {
|
|
5
|
+
it("does not relabel any option when no previous mode is provided", () => {
|
|
6
|
+
const options = buildExitPlanModePermissionOptions();
|
|
7
|
+
for (const opt of options) {
|
|
8
|
+
expect(opt.name).not.toMatch(/^Yes, continue/);
|
|
9
|
+
}
|
|
10
|
+
expect(options[options.length - 1].optionId).toBe("reject_with_feedback");
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it("promotes the previous mode to the first position with a continue label", () => {
|
|
14
|
+
const options = buildExitPlanModePermissionOptions("default");
|
|
15
|
+
expect(options[0]).toMatchObject({
|
|
16
|
+
optionId: "default",
|
|
17
|
+
name: "Yes, continue manually approving edits",
|
|
18
|
+
});
|
|
19
|
+
expect(options[options.length - 1].optionId).toBe("reject_with_feedback");
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("relabels the auto option when it is the previous mode", () => {
|
|
23
|
+
const options = buildExitPlanModePermissionOptions("auto");
|
|
24
|
+
expect(options[0]).toMatchObject({
|
|
25
|
+
optionId: "auto",
|
|
26
|
+
name: 'Yes, continue in "auto" mode',
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("relabels the acceptEdits option when it is the previous mode", () => {
|
|
31
|
+
const options = buildExitPlanModePermissionOptions("acceptEdits");
|
|
32
|
+
expect(options[0]).toMatchObject({
|
|
33
|
+
optionId: "acceptEdits",
|
|
34
|
+
name: "Yes, continue auto-accepting edits",
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("ignores an unknown previous mode", () => {
|
|
39
|
+
const options = buildExitPlanModePermissionOptions("plan");
|
|
40
|
+
expect(options[0].name).toMatch(/^Yes, /);
|
|
41
|
+
expect(options[0].name).not.toMatch(/^Yes, continue/);
|
|
42
|
+
expect(options[options.length - 1].optionId).toBe("reject_with_feedback");
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it("always keeps the reject option last", () => {
|
|
46
|
+
for (const previousMode of ["auto", "acceptEdits", "default", undefined]) {
|
|
47
|
+
const options = buildExitPlanModePermissionOptions(previousMode);
|
|
48
|
+
expect(options[options.length - 1].optionId).toBe("reject_with_feedback");
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
});
|
|
@@ -92,7 +92,16 @@ export function buildPermissionOptions(
|
|
|
92
92
|
return permissionOptions("Yes, always allow");
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
-
|
|
95
|
+
const CONTINUE_LABELS: Record<string, string> = {
|
|
96
|
+
auto: 'Yes, continue in "auto" mode',
|
|
97
|
+
acceptEdits: "Yes, continue auto-accepting edits",
|
|
98
|
+
default: "Yes, continue manually approving edits",
|
|
99
|
+
bypassPermissions: "Yes, continue bypassing all permissions",
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
export function buildExitPlanModePermissionOptions(
|
|
103
|
+
previousMode?: string,
|
|
104
|
+
): PermissionOption[] {
|
|
96
105
|
const options: PermissionOption[] = [];
|
|
97
106
|
|
|
98
107
|
if (ALLOW_BYPASS) {
|
|
@@ -119,13 +128,30 @@ export function buildExitPlanModePermissionOptions(): PermissionOption[] {
|
|
|
119
128
|
name: "Yes, and manually approve edits",
|
|
120
129
|
optionId: "default",
|
|
121
130
|
},
|
|
122
|
-
{
|
|
123
|
-
kind: "reject_once",
|
|
124
|
-
name: "No, and tell the agent what to do differently",
|
|
125
|
-
optionId: "reject_with_feedback",
|
|
126
|
-
_meta: { customInput: true },
|
|
127
|
-
},
|
|
128
131
|
);
|
|
129
132
|
|
|
133
|
+
const previousIndex = previousMode
|
|
134
|
+
? options.findIndex((opt) => opt.optionId === previousMode)
|
|
135
|
+
: -1;
|
|
136
|
+
if (previousIndex > 0) {
|
|
137
|
+
const [previous] = options.splice(previousIndex, 1);
|
|
138
|
+
const continueLabel = CONTINUE_LABELS[previous.optionId];
|
|
139
|
+
options.unshift(
|
|
140
|
+
continueLabel ? { ...previous, name: continueLabel } : previous,
|
|
141
|
+
);
|
|
142
|
+
} else if (previousIndex === 0) {
|
|
143
|
+
const continueLabel = CONTINUE_LABELS[options[0].optionId];
|
|
144
|
+
if (continueLabel) {
|
|
145
|
+
options[0] = { ...options[0], name: continueLabel };
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
options.push({
|
|
150
|
+
kind: "reject_once",
|
|
151
|
+
name: "No, and tell the agent what to do differently",
|
|
152
|
+
optionId: "reject_with_feedback",
|
|
153
|
+
_meta: { customInput: true },
|
|
154
|
+
});
|
|
155
|
+
|
|
130
156
|
return options;
|
|
131
157
|
}
|