@posthog/agent 2.3.172 → 2.3.173
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 +101 -116
- 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 +66 -81
- package/dist/server/agent-server.js.map +1 -1
- package/dist/server/bin.cjs +66 -81
- package/dist/server/bin.cjs.map +1 -1
- package/package.json +1 -1
- package/src/acp-extensions.ts +3 -0
- package/src/adapters/claude/claude-agent.ts +13 -9
- package/src/adapters/codex/codex-agent.ts +51 -74
- package/src/adapters/codex/codex-client.ts +8 -7
- package/src/adapters/codex/session-state.ts +5 -8
- package/src/adapters/codex/spawn.ts +2 -0
package/package.json
CHANGED
package/src/acp-extensions.ts
CHANGED
|
@@ -44,6 +44,7 @@ import {
|
|
|
44
44
|
} from "@anthropic-ai/claude-agent-sdk";
|
|
45
45
|
import { v7 as uuidv7 } from "uuid";
|
|
46
46
|
import packageJson from "../../../package.json" with { type: "json" };
|
|
47
|
+
import { POSTHOG_NOTIFICATIONS } from "../../acp-extensions";
|
|
47
48
|
import { unreachable, withTimeout } from "../../utils/common";
|
|
48
49
|
import { Logger } from "../../utils/logger";
|
|
49
50
|
import { Pushable } from "../../utils/streams";
|
|
@@ -442,16 +443,19 @@ export class ClaudeAcpAgent extends BaseAcpAgent {
|
|
|
442
443
|
});
|
|
443
444
|
}
|
|
444
445
|
|
|
445
|
-
await this.client.extNotification(
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
446
|
+
await this.client.extNotification(
|
|
447
|
+
POSTHOG_NOTIFICATIONS.USAGE_UPDATE,
|
|
448
|
+
{
|
|
449
|
+
sessionId: params.sessionId,
|
|
450
|
+
used: {
|
|
451
|
+
inputTokens: message.usage.input_tokens,
|
|
452
|
+
outputTokens: message.usage.output_tokens,
|
|
453
|
+
cachedReadTokens: message.usage.cache_read_input_tokens,
|
|
454
|
+
cachedWriteTokens: message.usage.cache_creation_input_tokens,
|
|
455
|
+
},
|
|
456
|
+
cost: message.total_cost_usd,
|
|
452
457
|
},
|
|
453
|
-
|
|
454
|
-
});
|
|
458
|
+
);
|
|
455
459
|
|
|
456
460
|
const usage: Usage = {
|
|
457
461
|
inputTokens: this.session.accumulatedUsage.inputTokens,
|
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
import {
|
|
13
13
|
type AgentSideConnection,
|
|
14
14
|
type AuthenticateRequest,
|
|
15
|
-
type CancelNotification,
|
|
16
15
|
ClientSideConnection,
|
|
17
16
|
type ForkSessionRequest,
|
|
18
17
|
type ForkSessionResponse,
|
|
@@ -37,9 +36,8 @@ import {
|
|
|
37
36
|
import packageJson from "../../../package.json" with { type: "json" };
|
|
38
37
|
import { POSTHOG_NOTIFICATIONS } from "../../acp-extensions";
|
|
39
38
|
import {
|
|
40
|
-
|
|
41
|
-
type
|
|
42
|
-
type PermissionMode,
|
|
39
|
+
CODE_EXECUTION_MODES,
|
|
40
|
+
type CodeExecutionMode,
|
|
43
41
|
} from "../../execution-mode";
|
|
44
42
|
import type { ProcessSpawnedCallback } from "../../types";
|
|
45
43
|
import { Logger } from "../../utils/logger";
|
|
@@ -85,19 +83,26 @@ type CodexSession = BaseSession & {
|
|
|
85
83
|
settingsManager: CodexSettingsManager;
|
|
86
84
|
};
|
|
87
85
|
|
|
88
|
-
function
|
|
89
|
-
if (mode && (
|
|
90
|
-
return mode as
|
|
86
|
+
function toCodeExecutionMode(mode?: string): CodeExecutionMode {
|
|
87
|
+
if (mode && (CODE_EXECUTION_MODES as readonly string[]).includes(mode)) {
|
|
88
|
+
return mode as CodeExecutionMode;
|
|
91
89
|
}
|
|
92
|
-
return "
|
|
90
|
+
return "default";
|
|
93
91
|
}
|
|
94
92
|
|
|
93
|
+
const CODEX_NATIVE_MODE: Record<CodeExecutionMode, string> = {
|
|
94
|
+
default: "default",
|
|
95
|
+
acceptEdits: "default",
|
|
96
|
+
plan: "plan",
|
|
97
|
+
bypassPermissions: "default",
|
|
98
|
+
};
|
|
99
|
+
|
|
95
100
|
export class CodexAcpAgent extends BaseAcpAgent {
|
|
96
101
|
readonly adapterName = "codex";
|
|
97
102
|
declare session: CodexSession;
|
|
98
103
|
private codexProcess: CodexProcess;
|
|
99
|
-
private codexConnection
|
|
100
|
-
private sessionState
|
|
104
|
+
private codexConnection: ClientSideConnection;
|
|
105
|
+
private sessionState: CodexSessionState;
|
|
101
106
|
|
|
102
107
|
constructor(client: AgentSideConnection, options: CodexAcpAgentOptions) {
|
|
103
108
|
super(client);
|
|
@@ -126,29 +131,14 @@ export class CodexAcpAgent extends BaseAcpAgent {
|
|
|
126
131
|
cancelled: false,
|
|
127
132
|
};
|
|
128
133
|
|
|
134
|
+
this.sessionState = createSessionState("", cwd);
|
|
135
|
+
|
|
129
136
|
// Create the ClientSideConnection to codex-acp.
|
|
130
137
|
// The Client handler delegates all requests from codex-acp to the upstream
|
|
131
138
|
// PostHog Code client via our AgentSideConnection.
|
|
132
139
|
this.codexConnection = new ClientSideConnection(
|
|
133
140
|
(_agent) =>
|
|
134
|
-
createCodexClient(
|
|
135
|
-
this.client,
|
|
136
|
-
this.logger,
|
|
137
|
-
this.sessionState ?? {
|
|
138
|
-
sessionId: "",
|
|
139
|
-
cwd: "",
|
|
140
|
-
modeId: "auto",
|
|
141
|
-
configOptions: [],
|
|
142
|
-
accumulatedUsage: {
|
|
143
|
-
inputTokens: 0,
|
|
144
|
-
outputTokens: 0,
|
|
145
|
-
cachedReadTokens: 0,
|
|
146
|
-
cachedWriteTokens: 0,
|
|
147
|
-
},
|
|
148
|
-
permissionMode: "auto",
|
|
149
|
-
cancelled: false,
|
|
150
|
-
},
|
|
151
|
-
),
|
|
141
|
+
createCodexClient(this.client, this.logger, this.sessionState),
|
|
152
142
|
codexStream,
|
|
153
143
|
);
|
|
154
144
|
}
|
|
@@ -195,7 +185,7 @@ export class CodexAcpAgent extends BaseAcpAgent {
|
|
|
195
185
|
taskId: meta?.taskId ?? meta?.persistence?.taskId,
|
|
196
186
|
modeId: response.modes?.currentModeId ?? "default",
|
|
197
187
|
modelId: response.models?.currentModelId,
|
|
198
|
-
permissionMode:
|
|
188
|
+
permissionMode: toCodeExecutionMode(meta?.permissionMode),
|
|
199
189
|
});
|
|
200
190
|
this.sessionId = response.sessionId;
|
|
201
191
|
this.sessionState.configOptions = response.configOptions ?? [];
|
|
@@ -219,9 +209,11 @@ export class CodexAcpAgent extends BaseAcpAgent {
|
|
|
219
209
|
|
|
220
210
|
async loadSession(params: LoadSessionRequest): Promise<LoadSessionResponse> {
|
|
221
211
|
const response = await this.codexConnection.loadSession(params);
|
|
212
|
+
const meta = params._meta as NewSessionMeta | undefined;
|
|
222
213
|
|
|
223
|
-
|
|
224
|
-
|
|
214
|
+
this.sessionState = createSessionState(params.sessionId, params.cwd, {
|
|
215
|
+
permissionMode: toCodeExecutionMode(meta?.permissionMode),
|
|
216
|
+
});
|
|
225
217
|
this.sessionId = params.sessionId;
|
|
226
218
|
this.sessionState.configOptions = response.configOptions ?? [];
|
|
227
219
|
|
|
@@ -238,11 +230,15 @@ export class CodexAcpAgent extends BaseAcpAgent {
|
|
|
238
230
|
mcpServers: params.mcpServers ?? [],
|
|
239
231
|
});
|
|
240
232
|
|
|
241
|
-
|
|
233
|
+
const meta = params._meta as NewSessionMeta | undefined;
|
|
234
|
+
this.sessionState = createSessionState(params.sessionId, params.cwd, {
|
|
235
|
+
taskRunId: meta?.taskRunId,
|
|
236
|
+
taskId: meta?.taskId ?? meta?.persistence?.taskId,
|
|
237
|
+
permissionMode: toCodeExecutionMode(meta?.permissionMode),
|
|
238
|
+
});
|
|
242
239
|
this.sessionId = params.sessionId;
|
|
243
240
|
this.sessionState.configOptions = loadResponse.configOptions ?? [];
|
|
244
241
|
|
|
245
|
-
const meta = params._meta as NewSessionMeta | undefined;
|
|
246
242
|
if (meta?.taskRunId) {
|
|
247
243
|
await this.client.extNotification(POSTHOG_NOTIFICATIONS.SDK_SESSION, {
|
|
248
244
|
taskRunId: meta.taskRunId,
|
|
@@ -268,7 +264,12 @@ export class CodexAcpAgent extends BaseAcpAgent {
|
|
|
268
264
|
_meta: params._meta,
|
|
269
265
|
});
|
|
270
266
|
|
|
271
|
-
|
|
267
|
+
const meta = params._meta as NewSessionMeta | undefined;
|
|
268
|
+
this.sessionState = createSessionState(newResponse.sessionId, params.cwd, {
|
|
269
|
+
taskRunId: meta?.taskRunId,
|
|
270
|
+
taskId: meta?.taskId ?? meta?.persistence?.taskId,
|
|
271
|
+
permissionMode: toCodeExecutionMode(meta?.permissionMode),
|
|
272
|
+
});
|
|
272
273
|
this.sessionId = newResponse.sessionId;
|
|
273
274
|
this.sessionState.configOptions = newResponse.configOptions ?? [];
|
|
274
275
|
|
|
@@ -284,31 +285,21 @@ export class CodexAcpAgent extends BaseAcpAgent {
|
|
|
284
285
|
async unstable_listSessions(
|
|
285
286
|
params: ListSessionsRequest,
|
|
286
287
|
): Promise<ListSessionsResponse> {
|
|
287
|
-
return this.
|
|
288
|
+
return this.listSessions(params);
|
|
288
289
|
}
|
|
289
290
|
|
|
290
291
|
async prompt(params: PromptRequest): Promise<PromptResponse> {
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
resetUsage(this.sessionState);
|
|
295
|
-
}
|
|
292
|
+
this.session.cancelled = false;
|
|
293
|
+
this.session.interruptReason = undefined;
|
|
294
|
+
resetUsage(this.sessionState);
|
|
296
295
|
|
|
297
296
|
const response = await this.codexConnection.prompt(params);
|
|
298
297
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
response.usage.inputTokens ?? 0;
|
|
303
|
-
this.sessionState.accumulatedUsage.outputTokens +=
|
|
304
|
-
response.usage.outputTokens ?? 0;
|
|
305
|
-
this.sessionState.accumulatedUsage.cachedReadTokens +=
|
|
306
|
-
response.usage.cachedReadTokens ?? 0;
|
|
307
|
-
this.sessionState.accumulatedUsage.cachedWriteTokens +=
|
|
308
|
-
response.usage.cachedWriteTokens ?? 0;
|
|
309
|
-
}
|
|
298
|
+
// Usage is already accumulated via sessionUpdate notifications in
|
|
299
|
+
// codex-client.ts. Do NOT also add response.usage here or tokens
|
|
300
|
+
// get double-counted.
|
|
310
301
|
|
|
311
|
-
if (this.sessionState
|
|
302
|
+
if (this.sessionState.taskRunId) {
|
|
312
303
|
const { accumulatedUsage } = this.sessionState;
|
|
313
304
|
|
|
314
305
|
await this.client.extNotification(POSTHOG_NOTIFICATIONS.TURN_COMPLETE, {
|
|
@@ -328,7 +319,7 @@ export class CodexAcpAgent extends BaseAcpAgent {
|
|
|
328
319
|
});
|
|
329
320
|
|
|
330
321
|
if (response.usage) {
|
|
331
|
-
await this.client.extNotification(
|
|
322
|
+
await this.client.extNotification(POSTHOG_NOTIFICATIONS.USAGE_UPDATE, {
|
|
332
323
|
sessionId: params.sessionId,
|
|
333
324
|
used: {
|
|
334
325
|
inputTokens: response.usage.inputTokens ?? 0,
|
|
@@ -345,39 +336,24 @@ export class CodexAcpAgent extends BaseAcpAgent {
|
|
|
345
336
|
}
|
|
346
337
|
|
|
347
338
|
protected async interrupt(): Promise<void> {
|
|
348
|
-
if (this.sessionState) {
|
|
349
|
-
this.sessionState.cancelled = true;
|
|
350
|
-
}
|
|
351
339
|
await this.codexConnection.cancel({
|
|
352
340
|
sessionId: this.sessionId,
|
|
353
341
|
});
|
|
354
342
|
}
|
|
355
343
|
|
|
356
|
-
async cancel(params: CancelNotification): Promise<void> {
|
|
357
|
-
if (this.sessionState) {
|
|
358
|
-
this.sessionState.cancelled = true;
|
|
359
|
-
const meta = params._meta as { interruptReason?: string } | undefined;
|
|
360
|
-
if (meta?.interruptReason) {
|
|
361
|
-
this.sessionState.interruptReason = meta.interruptReason;
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
await this.codexConnection.cancel(params);
|
|
365
|
-
}
|
|
366
|
-
|
|
367
344
|
async setSessionMode(
|
|
368
345
|
params: SetSessionModeRequest,
|
|
369
346
|
): Promise<SetSessionModeResponse> {
|
|
370
|
-
const
|
|
347
|
+
const requestedMode = toCodeExecutionMode(params.modeId);
|
|
348
|
+
const nativeMode = CODEX_NATIVE_MODE[requestedMode];
|
|
371
349
|
|
|
372
350
|
const response = await this.codexConnection.setSessionMode({
|
|
373
351
|
...params,
|
|
374
|
-
modeId:
|
|
352
|
+
modeId: nativeMode,
|
|
375
353
|
});
|
|
376
354
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
this.sessionState.permissionMode = permissionMode;
|
|
380
|
-
}
|
|
355
|
+
this.sessionState.modeId = nativeMode;
|
|
356
|
+
this.sessionState.permissionMode = requestedMode;
|
|
381
357
|
return response ?? {};
|
|
382
358
|
}
|
|
383
359
|
|
|
@@ -385,7 +361,7 @@ export class CodexAcpAgent extends BaseAcpAgent {
|
|
|
385
361
|
params: SetSessionConfigOptionRequest,
|
|
386
362
|
): Promise<SetSessionConfigOptionResponse> {
|
|
387
363
|
const response = await this.codexConnection.setSessionConfigOption(params);
|
|
388
|
-
if (
|
|
364
|
+
if (response.configOptions) {
|
|
389
365
|
this.sessionState.configOptions = response.configOptions;
|
|
390
366
|
}
|
|
391
367
|
return response;
|
|
@@ -397,6 +373,7 @@ export class CodexAcpAgent extends BaseAcpAgent {
|
|
|
397
373
|
|
|
398
374
|
async closeSession(): Promise<void> {
|
|
399
375
|
this.logger.info("Closing Codex session", { sessionId: this.sessionId });
|
|
376
|
+
this.session.abortController.abort();
|
|
400
377
|
this.session.settingsManager.dispose();
|
|
401
378
|
try {
|
|
402
379
|
this.codexProcess.kill();
|
|
@@ -29,7 +29,7 @@ import type {
|
|
|
29
29
|
WriteTextFileRequest,
|
|
30
30
|
WriteTextFileResponse,
|
|
31
31
|
} from "@agentclientprotocol/sdk";
|
|
32
|
-
import type {
|
|
32
|
+
import type { CodeExecutionMode } from "../../execution-mode";
|
|
33
33
|
import type { Logger } from "../../utils/logger";
|
|
34
34
|
import type { CodexSessionState } from "./session-state";
|
|
35
35
|
|
|
@@ -38,10 +38,11 @@ export interface CodexClientCallbacks {
|
|
|
38
38
|
onUsageUpdate?: (update: Record<string, unknown>) => void;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
const AUTO_APPROVED_KINDS:
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
const AUTO_APPROVED_KINDS: Record<CodeExecutionMode, Set<ToolKind>> = {
|
|
42
|
+
default: new Set(["read", "search", "fetch", "think"]),
|
|
43
|
+
acceptEdits: new Set(["read", "edit", "search", "fetch", "think"]),
|
|
44
|
+
plan: new Set(["read", "search", "fetch", "think"]),
|
|
45
|
+
bypassPermissions: new Set([
|
|
45
46
|
"read",
|
|
46
47
|
"edit",
|
|
47
48
|
"delete",
|
|
@@ -56,10 +57,10 @@ const AUTO_APPROVED_KINDS: Partial<Record<PermissionMode, Set<ToolKind>>> = {
|
|
|
56
57
|
};
|
|
57
58
|
|
|
58
59
|
function shouldAutoApprove(
|
|
59
|
-
mode:
|
|
60
|
+
mode: CodeExecutionMode,
|
|
60
61
|
kind: ToolKind | null | undefined,
|
|
61
62
|
): boolean {
|
|
62
|
-
if (mode === "
|
|
63
|
+
if (mode === "bypassPermissions") return true;
|
|
63
64
|
if (!kind) return false;
|
|
64
65
|
return AUTO_APPROVED_KINDS[mode]?.has(kind) ?? false;
|
|
65
66
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import type { SessionConfigOption } from "@agentclientprotocol/sdk";
|
|
7
|
-
import type {
|
|
7
|
+
import type { CodeExecutionMode } from "../../execution-mode";
|
|
8
8
|
|
|
9
9
|
export interface CodexUsage {
|
|
10
10
|
inputTokens: number;
|
|
@@ -22,9 +22,7 @@ export interface CodexSessionState {
|
|
|
22
22
|
accumulatedUsage: CodexUsage;
|
|
23
23
|
contextSize?: number;
|
|
24
24
|
contextUsed?: number;
|
|
25
|
-
permissionMode:
|
|
26
|
-
cancelled: boolean;
|
|
27
|
-
interruptReason?: string;
|
|
25
|
+
permissionMode: CodeExecutionMode;
|
|
28
26
|
taskRunId?: string;
|
|
29
27
|
taskId?: string;
|
|
30
28
|
}
|
|
@@ -37,13 +35,13 @@ export function createSessionState(
|
|
|
37
35
|
taskId?: string;
|
|
38
36
|
modeId?: string;
|
|
39
37
|
modelId?: string;
|
|
40
|
-
permissionMode?:
|
|
38
|
+
permissionMode?: CodeExecutionMode;
|
|
41
39
|
},
|
|
42
40
|
): CodexSessionState {
|
|
43
41
|
return {
|
|
44
42
|
sessionId,
|
|
45
43
|
cwd,
|
|
46
|
-
modeId: opts?.modeId ?? "
|
|
44
|
+
modeId: opts?.modeId ?? "default",
|
|
47
45
|
modelId: opts?.modelId,
|
|
48
46
|
configOptions: [],
|
|
49
47
|
accumulatedUsage: {
|
|
@@ -52,8 +50,7 @@ export function createSessionState(
|
|
|
52
50
|
cachedReadTokens: 0,
|
|
53
51
|
cachedWriteTokens: 0,
|
|
54
52
|
},
|
|
55
|
-
permissionMode: opts?.permissionMode ?? "
|
|
56
|
-
cancelled: false,
|
|
53
|
+
permissionMode: opts?.permissionMode ?? "default",
|
|
57
54
|
taskRunId: opts?.taskRunId,
|
|
58
55
|
taskId: opts?.taskId,
|
|
59
56
|
};
|
|
@@ -46,6 +46,8 @@ function buildConfigArgs(options: CodexProcessOptions): string[] {
|
|
|
46
46
|
if (options.instructions) {
|
|
47
47
|
const escaped = options.instructions
|
|
48
48
|
.replace(/\\/g, "\\\\")
|
|
49
|
+
.replace(/\n/g, "\\n")
|
|
50
|
+
.replace(/\r/g, "\\r")
|
|
49
51
|
.replace(/"/g, '\\"');
|
|
50
52
|
args.push("-c", `instructions="${escaped}"`);
|
|
51
53
|
}
|