@posthog/agent 2.1.16 → 2.1.22
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 +57 -47
- package/dist/agent.js.map +1 -1
- package/dist/claude-cli/cli.js +5349 -3347
- package/dist/claude-cli/vendor/ripgrep/arm64-win32/rg.exe +0 -0
- package/dist/claude-cli/vendor/ripgrep/arm64-win32/ripgrep.node +0 -0
- package/dist/index.js +57 -47
- package/dist/index.js.map +1 -1
- package/dist/server/agent-server.js +57 -47
- package/dist/server/agent-server.js.map +1 -1
- package/dist/server/bin.cjs +57 -47
- package/dist/server/bin.cjs.map +1 -1
- package/package.json +6 -6
- package/src/adapters/claude/claude-agent.ts +35 -28
- package/src/adapters/claude/conversion/sdk-to-acp.ts +1 -11
- package/src/adapters/claude/session/options.ts +22 -3
- package/src/adapters/claude/types.ts +0 -1
- package/src/test/mocks/claude-sdk.ts +7 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@posthog/agent",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.22",
|
|
4
4
|
"repository": "https://github.com/PostHog/twig",
|
|
5
5
|
"description": "TypeScript agent framework wrapping Claude Agent SDK with Git-based task execution for PostHog",
|
|
6
6
|
"exports": {
|
|
@@ -76,16 +76,16 @@
|
|
|
76
76
|
"@twig/git": "1.0.0"
|
|
77
77
|
},
|
|
78
78
|
"dependencies": {
|
|
79
|
+
"@agentclientprotocol/sdk": "^0.14.0",
|
|
80
|
+
"@anthropic-ai/claude-agent-sdk": "0.2.42",
|
|
81
|
+
"@anthropic-ai/sdk": "^0.71.0",
|
|
82
|
+
"@hono/node-server": "^1.19.9",
|
|
83
|
+
"@modelcontextprotocol/sdk": "^1.25.3",
|
|
79
84
|
"@opentelemetry/api-logs": "^0.208.0",
|
|
80
85
|
"@opentelemetry/exporter-logs-otlp-http": "^0.208.0",
|
|
81
86
|
"@opentelemetry/resources": "^2.0.0",
|
|
82
87
|
"@opentelemetry/sdk-logs": "^0.208.0",
|
|
83
88
|
"@opentelemetry/semantic-conventions": "^1.28.0",
|
|
84
|
-
"@agentclientprotocol/sdk": "^0.14.0",
|
|
85
|
-
"@anthropic-ai/claude-agent-sdk": "0.2.12",
|
|
86
|
-
"@anthropic-ai/sdk": "^0.71.0",
|
|
87
|
-
"@hono/node-server": "^1.19.9",
|
|
88
|
-
"@modelcontextprotocol/sdk": "^1.25.3",
|
|
89
89
|
"@types/jsonwebtoken": "^9.0.10",
|
|
90
90
|
"commander": "^14.0.2",
|
|
91
91
|
"diff": "^8.0.2",
|
|
@@ -137,7 +137,7 @@ export class ClaudeAcpAgent extends BaseAcpAgent {
|
|
|
137
137
|
this.checkAuthStatus();
|
|
138
138
|
|
|
139
139
|
const meta = params._meta as NewSessionMeta | undefined;
|
|
140
|
-
const
|
|
140
|
+
const sessionId = uuidv7();
|
|
141
141
|
const permissionMode: TwigExecutionMode =
|
|
142
142
|
meta?.permissionMode &&
|
|
143
143
|
TWIG_EXECUTION_MODES.includes(meta.permissionMode as TwigExecutionMode)
|
|
@@ -151,11 +151,13 @@ export class ClaudeAcpAgent extends BaseAcpAgent {
|
|
|
151
151
|
cwd: params.cwd,
|
|
152
152
|
mcpServers,
|
|
153
153
|
permissionMode,
|
|
154
|
-
canUseTool: this.createCanUseTool(
|
|
154
|
+
canUseTool: this.createCanUseTool(sessionId),
|
|
155
155
|
logger: this.logger,
|
|
156
156
|
systemPrompt: buildSystemPrompt(meta?.systemPrompt),
|
|
157
157
|
userProvidedOptions: meta?.claudeCode?.options,
|
|
158
|
-
|
|
158
|
+
sessionId,
|
|
159
|
+
isResume: false,
|
|
160
|
+
onModeChange: this.createOnModeChange(sessionId),
|
|
159
161
|
onProcessSpawned: this.processCallbacks?.onProcessSpawned,
|
|
160
162
|
onProcessExited: this.processCallbacks?.onProcessExited,
|
|
161
163
|
});
|
|
@@ -164,7 +166,7 @@ export class ClaudeAcpAgent extends BaseAcpAgent {
|
|
|
164
166
|
const q = query({ prompt: input, options });
|
|
165
167
|
|
|
166
168
|
const session = this.createSession(
|
|
167
|
-
|
|
169
|
+
sessionId,
|
|
168
170
|
q,
|
|
169
171
|
input,
|
|
170
172
|
permissionMode,
|
|
@@ -172,21 +174,27 @@ export class ClaudeAcpAgent extends BaseAcpAgent {
|
|
|
172
174
|
options.abortController as AbortController,
|
|
173
175
|
);
|
|
174
176
|
session.taskRunId = meta?.taskRunId;
|
|
175
|
-
this.registerPersistence(
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
177
|
+
this.registerPersistence(sessionId, meta as Record<string, unknown>);
|
|
178
|
+
|
|
179
|
+
if (meta?.taskRunId) {
|
|
180
|
+
await this.client.extNotification("_posthog/sdk_session", {
|
|
181
|
+
taskRunId: meta.taskRunId,
|
|
182
|
+
sessionId,
|
|
183
|
+
adapter: "claude",
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
|
|
179
187
|
const modelOptions = await this.getModelConfigOptions();
|
|
180
188
|
session.modelId = modelOptions.currentModelId;
|
|
181
189
|
await this.trySetModel(q, modelOptions.currentModelId);
|
|
182
190
|
|
|
183
191
|
this.sendAvailableCommandsUpdate(
|
|
184
|
-
|
|
192
|
+
sessionId,
|
|
185
193
|
await getAvailableSlashCommands(q),
|
|
186
194
|
);
|
|
187
195
|
|
|
188
196
|
return {
|
|
189
|
-
sessionId
|
|
197
|
+
sessionId,
|
|
190
198
|
configOptions: await this.buildConfigOptions(modelOptions),
|
|
191
199
|
};
|
|
192
200
|
}
|
|
@@ -198,12 +206,15 @@ export class ClaudeAcpAgent extends BaseAcpAgent {
|
|
|
198
206
|
async resumeSession(
|
|
199
207
|
params: LoadSessionRequest,
|
|
200
208
|
): Promise<LoadSessionResponse> {
|
|
201
|
-
const
|
|
202
|
-
|
|
209
|
+
const meta = params._meta as NewSessionMeta | undefined;
|
|
210
|
+
const sessionId = meta?.sessionId;
|
|
211
|
+
if (!sessionId) {
|
|
212
|
+
throw new Error("Cannot resume session without sessionId");
|
|
213
|
+
}
|
|
214
|
+
if (this.sessionId === sessionId) {
|
|
203
215
|
return {};
|
|
204
216
|
}
|
|
205
217
|
|
|
206
|
-
const meta = params._meta as NewSessionMeta | undefined;
|
|
207
218
|
const mcpServers = parseMcpServers(params);
|
|
208
219
|
await fetchMcpToolMetadata(mcpServers, this.logger);
|
|
209
220
|
|
|
@@ -214,27 +225,21 @@ export class ClaudeAcpAgent extends BaseAcpAgent {
|
|
|
214
225
|
: "default";
|
|
215
226
|
|
|
216
227
|
const { query: q, session } = await this.initializeQuery({
|
|
217
|
-
internalSessionId,
|
|
218
228
|
cwd: params.cwd,
|
|
219
229
|
permissionMode,
|
|
220
230
|
mcpServers,
|
|
221
231
|
systemPrompt: buildSystemPrompt(meta?.systemPrompt),
|
|
222
232
|
userProvidedOptions: meta?.claudeCode?.options,
|
|
223
|
-
sessionId
|
|
233
|
+
sessionId,
|
|
234
|
+
isResume: true,
|
|
224
235
|
additionalDirectories: meta?.claudeCode?.options?.additionalDirectories,
|
|
225
236
|
});
|
|
226
237
|
|
|
227
238
|
session.taskRunId = meta?.taskRunId;
|
|
228
|
-
if (meta?.sessionId) {
|
|
229
|
-
session.sessionId = meta.sessionId;
|
|
230
|
-
}
|
|
231
239
|
|
|
232
|
-
this.registerPersistence(
|
|
233
|
-
internalSessionId,
|
|
234
|
-
meta as Record<string, unknown>,
|
|
235
|
-
);
|
|
240
|
+
this.registerPersistence(sessionId, meta as Record<string, unknown>);
|
|
236
241
|
this.sendAvailableCommandsUpdate(
|
|
237
|
-
|
|
242
|
+
sessionId,
|
|
238
243
|
await getAvailableSlashCommands(q),
|
|
239
244
|
);
|
|
240
245
|
|
|
@@ -322,13 +327,13 @@ export class ClaudeAcpAgent extends BaseAcpAgent {
|
|
|
322
327
|
}
|
|
323
328
|
|
|
324
329
|
private async initializeQuery(config: {
|
|
325
|
-
internalSessionId: string;
|
|
326
330
|
cwd: string;
|
|
327
331
|
permissionMode: TwigExecutionMode;
|
|
328
332
|
mcpServers: ReturnType<typeof parseMcpServers>;
|
|
329
333
|
userProvidedOptions?: Options;
|
|
330
334
|
systemPrompt?: Options["systemPrompt"];
|
|
331
|
-
sessionId
|
|
335
|
+
sessionId: string;
|
|
336
|
+
isResume: boolean;
|
|
332
337
|
additionalDirectories?: string[];
|
|
333
338
|
}): Promise<{
|
|
334
339
|
query: Query;
|
|
@@ -341,13 +346,14 @@ export class ClaudeAcpAgent extends BaseAcpAgent {
|
|
|
341
346
|
cwd: config.cwd,
|
|
342
347
|
mcpServers: config.mcpServers,
|
|
343
348
|
permissionMode: config.permissionMode,
|
|
344
|
-
canUseTool: this.createCanUseTool(config.
|
|
349
|
+
canUseTool: this.createCanUseTool(config.sessionId),
|
|
345
350
|
logger: this.logger,
|
|
346
351
|
systemPrompt: config.systemPrompt,
|
|
347
352
|
userProvidedOptions: config.userProvidedOptions,
|
|
348
353
|
sessionId: config.sessionId,
|
|
354
|
+
isResume: config.isResume,
|
|
349
355
|
additionalDirectories: config.additionalDirectories,
|
|
350
|
-
onModeChange: this.createOnModeChange(config.
|
|
356
|
+
onModeChange: this.createOnModeChange(config.sessionId),
|
|
351
357
|
onProcessSpawned: this.processCallbacks?.onProcessSpawned,
|
|
352
358
|
onProcessExited: this.processCallbacks?.onProcessExited,
|
|
353
359
|
});
|
|
@@ -356,7 +362,7 @@ export class ClaudeAcpAgent extends BaseAcpAgent {
|
|
|
356
362
|
const abortController = options.abortController as AbortController;
|
|
357
363
|
|
|
358
364
|
const session = this.createSession(
|
|
359
|
-
config.
|
|
365
|
+
config.sessionId,
|
|
360
366
|
q,
|
|
361
367
|
input,
|
|
362
368
|
config.permissionMode,
|
|
@@ -596,6 +602,7 @@ export class ClaudeAcpAgent extends BaseAcpAgent {
|
|
|
596
602
|
|
|
597
603
|
case "tool_progress":
|
|
598
604
|
case "auth_status":
|
|
605
|
+
case "tool_use_summary":
|
|
599
606
|
return null;
|
|
600
607
|
|
|
601
608
|
default:
|
|
@@ -328,20 +328,10 @@ export async function handleSystemMessage(
|
|
|
328
328
|
message: any,
|
|
329
329
|
context: MessageHandlerContext,
|
|
330
330
|
): Promise<void> {
|
|
331
|
-
const {
|
|
331
|
+
const { sessionId, client, logger } = context;
|
|
332
332
|
|
|
333
333
|
switch (message.subtype) {
|
|
334
334
|
case "init":
|
|
335
|
-
if (message.session_id && session && !session.sessionId) {
|
|
336
|
-
session.sessionId = message.session_id;
|
|
337
|
-
if (session.taskRunId) {
|
|
338
|
-
await client.extNotification("_posthog/sdk_session", {
|
|
339
|
-
taskRunId: session.taskRunId,
|
|
340
|
-
sessionId: message.session_id,
|
|
341
|
-
adapter: "claude",
|
|
342
|
-
});
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
335
|
break;
|
|
346
336
|
case "compact_boundary":
|
|
347
337
|
await client.extNotification("_posthog/compact_boundary", {
|
|
@@ -27,7 +27,8 @@ export interface BuildOptionsParams {
|
|
|
27
27
|
logger: Logger;
|
|
28
28
|
systemPrompt?: Options["systemPrompt"];
|
|
29
29
|
userProvidedOptions?: Options;
|
|
30
|
-
sessionId
|
|
30
|
+
sessionId: string;
|
|
31
|
+
isResume: boolean;
|
|
31
32
|
additionalDirectories?: string[];
|
|
32
33
|
onModeChange?: OnModeChange;
|
|
33
34
|
onProcessSpawned?: (info: ProcessSpawnedInfo) => void;
|
|
@@ -175,7 +176,22 @@ function buildSpawnWrapper(
|
|
|
175
176
|
};
|
|
176
177
|
}
|
|
177
178
|
|
|
179
|
+
function ensureLocalSettings(cwd: string): void {
|
|
180
|
+
const claudeDir = path.join(cwd, ".claude");
|
|
181
|
+
const localSettingsPath = path.join(claudeDir, "settings.local.json");
|
|
182
|
+
try {
|
|
183
|
+
if (!fs.existsSync(localSettingsPath)) {
|
|
184
|
+
fs.mkdirSync(claudeDir, { recursive: true });
|
|
185
|
+
fs.writeFileSync(localSettingsPath, "{}\n", { flag: "wx" });
|
|
186
|
+
}
|
|
187
|
+
} catch {
|
|
188
|
+
// Best-effort — don't fail session creation if we can't write
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
178
192
|
export function buildSessionOptions(params: BuildOptionsParams): Options {
|
|
193
|
+
ensureLocalSettings(params.cwd);
|
|
194
|
+
|
|
179
195
|
const options: Options = {
|
|
180
196
|
...params.userProvidedOptions,
|
|
181
197
|
systemPrompt: params.systemPrompt ?? buildSystemPrompt(),
|
|
@@ -198,7 +214,7 @@ export function buildSessionOptions(params: BuildOptionsParams): Options {
|
|
|
198
214
|
),
|
|
199
215
|
...(params.onProcessSpawned && {
|
|
200
216
|
spawnClaudeCodeProcess: buildSpawnWrapper(
|
|
201
|
-
params.sessionId
|
|
217
|
+
params.sessionId,
|
|
202
218
|
params.onProcessSpawned,
|
|
203
219
|
params.onProcessExited,
|
|
204
220
|
),
|
|
@@ -209,8 +225,11 @@ export function buildSessionOptions(params: BuildOptionsParams): Options {
|
|
|
209
225
|
options.pathToClaudeCodeExecutable = process.env.CLAUDE_CODE_EXECUTABLE;
|
|
210
226
|
}
|
|
211
227
|
|
|
212
|
-
if (params.
|
|
228
|
+
if (params.isResume) {
|
|
213
229
|
options.resume = params.sessionId;
|
|
230
|
+
options.forkSession = false;
|
|
231
|
+
} else {
|
|
232
|
+
options.sessionId = params.sessionId;
|
|
214
233
|
}
|
|
215
234
|
|
|
216
235
|
if (params.additionalDirectories) {
|
|
@@ -95,6 +95,11 @@ export function createMockQuery(
|
|
|
95
95
|
.fn()
|
|
96
96
|
.mockResolvedValue({ added: [], removed: [], errors: {} }),
|
|
97
97
|
streamInput: vi.fn().mockResolvedValue(undefined),
|
|
98
|
+
close: vi.fn(),
|
|
99
|
+
initializationResult: vi.fn().mockResolvedValue({}),
|
|
100
|
+
reconnectMcpServer: vi.fn().mockResolvedValue(undefined),
|
|
101
|
+
toggleMcpServer: vi.fn().mockResolvedValue(undefined),
|
|
102
|
+
stopTask: vi.fn().mockResolvedValue(undefined),
|
|
98
103
|
[Symbol.asyncDispose]: vi.fn().mockResolvedValue(undefined),
|
|
99
104
|
_abortController: abortController,
|
|
100
105
|
_mockHelpers: {
|
|
@@ -158,6 +163,7 @@ export function createSuccessResult(
|
|
|
158
163
|
is_error: false,
|
|
159
164
|
num_turns: 1,
|
|
160
165
|
result: "Done",
|
|
166
|
+
stop_reason: null,
|
|
161
167
|
total_cost_usd: 0.01,
|
|
162
168
|
usage: {
|
|
163
169
|
input_tokens: 100,
|
|
@@ -190,6 +196,7 @@ export function createErrorResult(
|
|
|
190
196
|
duration_ms: 100,
|
|
191
197
|
duration_api_ms: 50,
|
|
192
198
|
num_turns: 1,
|
|
199
|
+
stop_reason: null,
|
|
193
200
|
total_cost_usd: 0.01,
|
|
194
201
|
usage: {
|
|
195
202
|
input_tokens: 100,
|