Skip to content

Commit d8b0d76

Browse files
skoob13claude
andauthored
feat(phai): add refresh_session ACP method for sandboxes (#1717)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent aa30b91 commit d8b0d76

4 files changed

Lines changed: 522 additions & 7 deletions

File tree

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { describe, expect, it } from "vitest";
2+
import {
3+
isMethod,
4+
isNotification,
5+
POSTHOG_METHODS,
6+
POSTHOG_NOTIFICATIONS,
7+
} from "./acp-extensions";
8+
9+
describe("isNotification", () => {
10+
it("matches the exact notification name", () => {
11+
expect(
12+
isNotification(
13+
POSTHOG_NOTIFICATIONS.TURN_COMPLETE,
14+
POSTHOG_NOTIFICATIONS.TURN_COMPLETE,
15+
),
16+
).toBe(true);
17+
});
18+
19+
it("matches the double-underscore prefix variant", () => {
20+
expect(
21+
isNotification(
22+
`_${POSTHOG_NOTIFICATIONS.TURN_COMPLETE}`,
23+
POSTHOG_NOTIFICATIONS.TURN_COMPLETE,
24+
),
25+
).toBe(true);
26+
});
27+
28+
it("returns false for a different notification", () => {
29+
expect(
30+
isNotification(
31+
POSTHOG_NOTIFICATIONS.USAGE_UPDATE,
32+
POSTHOG_NOTIFICATIONS.TURN_COMPLETE,
33+
),
34+
).toBe(false);
35+
});
36+
37+
it("returns false for undefined", () => {
38+
expect(isNotification(undefined, POSTHOG_NOTIFICATIONS.TURN_COMPLETE)).toBe(
39+
false,
40+
);
41+
});
42+
});
43+
44+
describe("isMethod", () => {
45+
it("matches the exact method name", () => {
46+
expect(
47+
isMethod(
48+
POSTHOG_METHODS.REFRESH_SESSION,
49+
POSTHOG_METHODS.REFRESH_SESSION,
50+
),
51+
).toBe(true);
52+
});
53+
54+
it("matches the double-underscore prefix variant", () => {
55+
expect(
56+
isMethod(
57+
`_${POSTHOG_METHODS.REFRESH_SESSION}`,
58+
POSTHOG_METHODS.REFRESH_SESSION,
59+
),
60+
).toBe(true);
61+
});
62+
63+
it("returns false for unrelated method strings", () => {
64+
expect(isMethod("session/prompt", POSTHOG_METHODS.REFRESH_SESSION)).toBe(
65+
false,
66+
);
67+
});
68+
69+
it("returns false for undefined", () => {
70+
expect(isMethod(undefined, POSTHOG_METHODS.REFRESH_SESSION)).toBe(false);
71+
});
72+
});

packages/agent/src/acp-extensions.ts

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,17 +68,48 @@ export const POSTHOG_NOTIFICATIONS = {
6868
PERMISSION_RESPONSE: "_posthog/permission_response",
6969
} as const;
7070

71-
type NotificationMethod =
71+
/**
72+
* Custom request methods for PostHog-specific operations that need a response
73+
* (request/response, not fire-and-forget). Used with
74+
* ClientSideConnection.extMethod() on the sender and Agent.extMethod() on the
75+
* receiver.
76+
*/
77+
export const POSTHOG_METHODS = {
78+
/**
79+
* Client requests a session refresh between turns. Payload may include
80+
* `mcpServers` to trigger a resume-with-new-options reinit; future fields
81+
* can extend this without adding new methods. Returns once the refresh has
82+
* completed so the caller can safely send the next prompt.
83+
*/
84+
REFRESH_SESSION: "_posthog/refresh_session",
85+
} as const;
86+
87+
type PosthogNotification =
7288
(typeof POSTHOG_NOTIFICATIONS)[keyof typeof POSTHOG_NOTIFICATIONS];
7389

90+
type PosthogMethod = (typeof POSTHOG_METHODS)[keyof typeof POSTHOG_METHODS];
91+
7492
/**
75-
* Check if an ACP method matches a PostHog notification, handling the
76-
* possible `__posthog/` double-prefix from extNotification().
93+
* Does `method` match `expected`? Shared by notification and method matchers.
94+
* Handles the `__posthog/` double-prefix that extNotification() can produce.
7795
*/
96+
function matchesExt(method: string | undefined, expected: string): boolean {
97+
if (!method) return false;
98+
return method === expected || method === `_${expected}`;
99+
}
100+
101+
/** Dispatcher check for incoming `extNotification` calls on the agent side. */
78102
export function isNotification(
79103
method: string | undefined,
80-
notification: NotificationMethod,
104+
expected: PosthogNotification,
81105
): boolean {
82-
if (!method) return false;
83-
return method === notification || method === `_${notification}`;
106+
return matchesExt(method, expected);
107+
}
108+
109+
/** Dispatcher check for incoming `extMethod` calls on the agent side. */
110+
export function isMethod(
111+
method: string | undefined,
112+
expected: PosthogMethod,
113+
): boolean {
114+
return matchesExt(method, expected);
84115
}

0 commit comments

Comments
 (0)