@posthog/agent 2.3.46 → 2.3.53
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 +15 -2
- 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.d.ts +4 -0
- package/dist/server/agent-server.js +104 -5
- package/dist/server/agent-server.js.map +1 -1
- package/dist/server/bin.cjs +104 -5
- package/dist/server/bin.cjs.map +1 -1
- package/package.json +1 -1
- package/src/server/agent-server.ts +119 -4
- package/src/server/question-relay.test.ts +17 -3
- package/src/session-log-writer.ts +17 -1
package/dist/server/bin.cjs
CHANGED
|
@@ -904,7 +904,7 @@ var import_hono = require("hono");
|
|
|
904
904
|
// package.json
|
|
905
905
|
var package_default = {
|
|
906
906
|
name: "@posthog/agent",
|
|
907
|
-
version: "2.3.
|
|
907
|
+
version: "2.3.53",
|
|
908
908
|
repository: "https://github.com/PostHog/code",
|
|
909
909
|
description: "TypeScript agent framework wrapping Claude Agent SDK with Git-based task execution for PostHog",
|
|
910
910
|
exports: {
|
|
@@ -11108,7 +11108,7 @@ var SessionLogWriter = class _SessionLogWriter {
|
|
|
11108
11108
|
taskId: context.taskId,
|
|
11109
11109
|
runId: context.runId
|
|
11110
11110
|
});
|
|
11111
|
-
this.sessions.set(sessionId, { context });
|
|
11111
|
+
this.sessions.set(sessionId, { context, currentTurnMessages: [] });
|
|
11112
11112
|
this.lastFlushAttemptTime.set(sessionId, Date.now());
|
|
11113
11113
|
if (this.localCachePath) {
|
|
11114
11114
|
const sessionDir = import_node_path7.default.join(
|
|
@@ -11155,6 +11155,7 @@ var SessionLogWriter = class _SessionLogWriter {
|
|
|
11155
11155
|
const nonChunkAgentText = this.extractAgentMessageText(message);
|
|
11156
11156
|
if (nonChunkAgentText) {
|
|
11157
11157
|
session.lastAgentMessage = nonChunkAgentText;
|
|
11158
|
+
session.currentTurnMessages.push(nonChunkAgentText);
|
|
11158
11159
|
}
|
|
11159
11160
|
const entry = {
|
|
11160
11161
|
type: "notification",
|
|
@@ -11251,6 +11252,7 @@ var SessionLogWriter = class _SessionLogWriter {
|
|
|
11251
11252
|
const { text: text2, firstTimestamp } = session.chunkBuffer;
|
|
11252
11253
|
session.chunkBuffer = void 0;
|
|
11253
11254
|
session.lastAgentMessage = text2;
|
|
11255
|
+
session.currentTurnMessages.push(text2);
|
|
11254
11256
|
const entry = {
|
|
11255
11257
|
type: "notification",
|
|
11256
11258
|
timestamp: firstTimestamp,
|
|
@@ -11276,6 +11278,17 @@ var SessionLogWriter = class _SessionLogWriter {
|
|
|
11276
11278
|
getLastAgentMessage(sessionId) {
|
|
11277
11279
|
return this.sessions.get(sessionId)?.lastAgentMessage;
|
|
11278
11280
|
}
|
|
11281
|
+
getFullAgentResponse(sessionId) {
|
|
11282
|
+
const session = this.sessions.get(sessionId);
|
|
11283
|
+
if (!session || session.currentTurnMessages.length === 0) return void 0;
|
|
11284
|
+
return session.currentTurnMessages.join("\n\n");
|
|
11285
|
+
}
|
|
11286
|
+
resetTurnMessages(sessionId) {
|
|
11287
|
+
const session = this.sessions.get(sessionId);
|
|
11288
|
+
if (session) {
|
|
11289
|
+
session.currentTurnMessages = [];
|
|
11290
|
+
}
|
|
11291
|
+
}
|
|
11279
11292
|
extractAgentMessageText(message) {
|
|
11280
11293
|
if (message.method !== "session/update") {
|
|
11281
11294
|
return null;
|
|
@@ -11591,6 +11604,12 @@ var AgentServer = class _AgentServer {
|
|
|
11591
11604
|
questionRelayedToSlack = false;
|
|
11592
11605
|
detectedPrUrl = null;
|
|
11593
11606
|
resumeState = null;
|
|
11607
|
+
// Guards against concurrent session initialization. autoInitializeSession() and
|
|
11608
|
+
// the GET /events SSE handler can both call initializeSession() — the SSE connection
|
|
11609
|
+
// often arrives while newSession() is still awaited (this.session is still null),
|
|
11610
|
+
// causing a second session to be created and duplicate Slack messages to be sent.
|
|
11611
|
+
initializationPromise = null;
|
|
11612
|
+
pendingEvents = [];
|
|
11594
11613
|
emitConsoleLog = (level, _scope, message, data) => {
|
|
11595
11614
|
if (!this.session) return;
|
|
11596
11615
|
const formatted = data !== void 0 ? `${message} ${JSON.stringify(data)}` : message;
|
|
@@ -11670,6 +11689,7 @@ var AgentServer = class _AgentServer {
|
|
|
11670
11689
|
await this.initializeSession(payload, sseController);
|
|
11671
11690
|
} else {
|
|
11672
11691
|
this.session.sseController = sseController;
|
|
11692
|
+
this.replayPendingEvents();
|
|
11673
11693
|
}
|
|
11674
11694
|
this.sendSseEvent(sseController, {
|
|
11675
11695
|
type: "connected",
|
|
@@ -11849,6 +11869,7 @@ var AgentServer = class _AgentServer {
|
|
|
11849
11869
|
this.logger.info(
|
|
11850
11870
|
`Processing user message (detectedPrUrl=${this.detectedPrUrl ?? "none"}): ${content.substring(0, 100)}...`
|
|
11851
11871
|
);
|
|
11872
|
+
this.session.logWriter.resetTurnMessages(this.session.payload.run_id);
|
|
11852
11873
|
const result = await this.session.clientConnection.prompt({
|
|
11853
11874
|
sessionId: this.session.acpSessionId,
|
|
11854
11875
|
prompt: [{ type: "text", text: content }],
|
|
@@ -11864,7 +11885,24 @@ You MUST NOT create a new branch, close the existing PR, or create a new PR.`
|
|
|
11864
11885
|
}
|
|
11865
11886
|
});
|
|
11866
11887
|
this.broadcastTurnComplete(result.stopReason);
|
|
11867
|
-
|
|
11888
|
+
if (result.stopReason === "end_turn") {
|
|
11889
|
+
this.relayAgentResponse(this.session.payload).catch(
|
|
11890
|
+
(err) => this.logger.warn("Failed to relay follow-up response", err)
|
|
11891
|
+
);
|
|
11892
|
+
}
|
|
11893
|
+
let assistantMessage;
|
|
11894
|
+
try {
|
|
11895
|
+
await this.session.logWriter.flush(this.session.payload.run_id);
|
|
11896
|
+
assistantMessage = this.session.logWriter.getFullAgentResponse(
|
|
11897
|
+
this.session.payload.run_id
|
|
11898
|
+
);
|
|
11899
|
+
} catch {
|
|
11900
|
+
this.logger.warn("Failed to extract assistant message from logs");
|
|
11901
|
+
}
|
|
11902
|
+
return {
|
|
11903
|
+
stopReason: result.stopReason,
|
|
11904
|
+
...assistantMessage && { assistant_message: assistantMessage }
|
|
11905
|
+
};
|
|
11868
11906
|
}
|
|
11869
11907
|
case POSTHOG_NOTIFICATIONS.CANCEL:
|
|
11870
11908
|
case "cancel": {
|
|
@@ -11887,6 +11925,28 @@ You MUST NOT create a new branch, close the existing PR, or create a new PR.`
|
|
|
11887
11925
|
}
|
|
11888
11926
|
}
|
|
11889
11927
|
async initializeSession(payload, sseController) {
|
|
11928
|
+
if (this.initializationPromise) {
|
|
11929
|
+
this.logger.info("Waiting for in-progress initialization", {
|
|
11930
|
+
runId: payload.run_id
|
|
11931
|
+
});
|
|
11932
|
+
await this.initializationPromise;
|
|
11933
|
+
if (this.session && sseController) {
|
|
11934
|
+
this.session.sseController = sseController;
|
|
11935
|
+
this.replayPendingEvents();
|
|
11936
|
+
}
|
|
11937
|
+
return;
|
|
11938
|
+
}
|
|
11939
|
+
this.initializationPromise = this._doInitializeSession(
|
|
11940
|
+
payload,
|
|
11941
|
+
sseController
|
|
11942
|
+
);
|
|
11943
|
+
try {
|
|
11944
|
+
await this.initializationPromise;
|
|
11945
|
+
} finally {
|
|
11946
|
+
this.initializationPromise = null;
|
|
11947
|
+
}
|
|
11948
|
+
}
|
|
11949
|
+
async _doInitializeSession(payload, sseController) {
|
|
11890
11950
|
if (this.session) {
|
|
11891
11951
|
await this.cleanupSession();
|
|
11892
11952
|
}
|
|
@@ -12073,6 +12133,7 @@ You MUST NOT create a new branch, close the existing PR, or create a new PR.`
|
|
|
12073
12133
|
descriptionLength: initialPrompt.length,
|
|
12074
12134
|
usedInitialPromptOverride: !!initialPromptOverride
|
|
12075
12135
|
});
|
|
12136
|
+
this.session.logWriter.resetTurnMessages(payload.run_id);
|
|
12076
12137
|
const result = await this.session.clientConnection.prompt({
|
|
12077
12138
|
sessionId: this.session.acpSessionId,
|
|
12078
12139
|
prompt: [{ type: "text", text: initialPrompt }]
|
|
@@ -12099,7 +12160,7 @@ You MUST NOT create a new branch, close the existing PR, or create a new PR.`
|
|
|
12099
12160
|
this.resumeState.conversation
|
|
12100
12161
|
);
|
|
12101
12162
|
const pendingUserMessage = this.getPendingUserMessage(taskRun);
|
|
12102
|
-
const sandboxContext = this.resumeState.snapshotApplied ? `The
|
|
12163
|
+
const sandboxContext = this.resumeState.snapshotApplied ? `The workspace environment (all files, packages, and code changes) has been fully restored from where you left off.` : `The workspace files from the previous session were not restored (the file snapshot may have expired), so you are starting with a fresh environment. Your conversation history is fully preserved below.`;
|
|
12103
12164
|
let resumePrompt;
|
|
12104
12165
|
if (pendingUserMessage) {
|
|
12105
12166
|
resumePrompt = `You are resuming a previous conversation. ${sandboxContext}
|
|
@@ -12130,6 +12191,7 @@ Continue from where you left off. The user is waiting for your response.`;
|
|
|
12130
12191
|
snapshotApplied: this.resumeState.snapshotApplied
|
|
12131
12192
|
});
|
|
12132
12193
|
this.resumeState = null;
|
|
12194
|
+
this.session.logWriter.resetTurnMessages(payload.run_id);
|
|
12133
12195
|
const result = await this.session.clientConnection.prompt({
|
|
12134
12196
|
sessionId: this.session.acpSessionId,
|
|
12135
12197
|
prompt: [{ type: "text", text: resumePrompt }]
|
|
@@ -12138,6 +12200,9 @@ Continue from where you left off. The user is waiting for your response.`;
|
|
|
12138
12200
|
stopReason: result.stopReason
|
|
12139
12201
|
});
|
|
12140
12202
|
this.broadcastTurnComplete(result.stopReason);
|
|
12203
|
+
if (result.stopReason === "end_turn") {
|
|
12204
|
+
await this.relayAgentResponse(payload);
|
|
12205
|
+
}
|
|
12141
12206
|
} catch (error) {
|
|
12142
12207
|
this.logger.error("Failed to send resume message", error);
|
|
12143
12208
|
if (this.session) {
|
|
@@ -12236,6 +12301,26 @@ Important:
|
|
|
12236
12301
|
- Do NOT create a new branch or a new pull request.
|
|
12237
12302
|
- Do NOT add "Co-Authored-By" trailers to commit messages.
|
|
12238
12303
|
- Do NOT add "Generated with [Claude Code]" or similar attribution lines to PR descriptions.
|
|
12304
|
+
`;
|
|
12305
|
+
}
|
|
12306
|
+
if (!this.config.repositoryPath) {
|
|
12307
|
+
return `
|
|
12308
|
+
# Cloud Task Execution \u2014 No Repository Mode
|
|
12309
|
+
|
|
12310
|
+
You are a helpful assistant with access to PostHog via MCP tools. You can help with both code tasks and data/analytics questions.
|
|
12311
|
+
|
|
12312
|
+
When the user asks about analytics, data, metrics, events, funnels, dashboards, feature flags, experiments, or anything PostHog-related:
|
|
12313
|
+
- Use your PostHog MCP tools to query data, search insights, and provide real answers
|
|
12314
|
+
- Do NOT tell the user to check an external analytics platform \u2014 you ARE the analytics platform
|
|
12315
|
+
- Use tools like insight-query, query-run, event-definitions-list, and others to answer questions directly
|
|
12316
|
+
|
|
12317
|
+
When the user asks for code changes or software engineering tasks:
|
|
12318
|
+
- Let them know you can help but don't have a repository connected for this session
|
|
12319
|
+
- Offer to write code snippets, scripts, or provide guidance
|
|
12320
|
+
|
|
12321
|
+
Important:
|
|
12322
|
+
- Do NOT create branches, commits, or pull requests in this mode.
|
|
12323
|
+
- Prefer using MCP tools to answer questions with real data over giving generic advice.
|
|
12239
12324
|
`;
|
|
12240
12325
|
}
|
|
12241
12326
|
return `
|
|
@@ -12338,6 +12423,9 @@ Important:
|
|
|
12338
12423
|
}
|
|
12339
12424
|
};
|
|
12340
12425
|
},
|
|
12426
|
+
extNotification: async (method, params) => {
|
|
12427
|
+
this.logger.debug("Extension notification", { method, params });
|
|
12428
|
+
},
|
|
12341
12429
|
sessionUpdate: async (params) => {
|
|
12342
12430
|
if (params.update?.sessionUpdate === "tool_call_update") {
|
|
12343
12431
|
const meta = params.update?._meta?.claudeCode;
|
|
@@ -12370,7 +12458,7 @@ Important:
|
|
|
12370
12458
|
error
|
|
12371
12459
|
});
|
|
12372
12460
|
}
|
|
12373
|
-
const message = this.session.logWriter.
|
|
12461
|
+
const message = this.session.logWriter.getFullAgentResponse(payload.run_id);
|
|
12374
12462
|
if (!message) {
|
|
12375
12463
|
this.logger.warn("No agent message found for Slack relay", {
|
|
12376
12464
|
taskId: payload.task_id,
|
|
@@ -12523,6 +12611,7 @@ Important:
|
|
|
12523
12611
|
if (this.session.sseController) {
|
|
12524
12612
|
this.session.sseController.close();
|
|
12525
12613
|
}
|
|
12614
|
+
this.pendingEvents = [];
|
|
12526
12615
|
this.session = null;
|
|
12527
12616
|
}
|
|
12528
12617
|
async captureTreeState() {
|
|
@@ -12571,6 +12660,16 @@ Important:
|
|
|
12571
12660
|
broadcastEvent(event) {
|
|
12572
12661
|
if (this.session?.sseController) {
|
|
12573
12662
|
this.sendSseEvent(this.session.sseController, event);
|
|
12663
|
+
} else if (this.session) {
|
|
12664
|
+
this.pendingEvents.push(event);
|
|
12665
|
+
}
|
|
12666
|
+
}
|
|
12667
|
+
replayPendingEvents() {
|
|
12668
|
+
if (!this.session?.sseController || this.pendingEvents.length === 0) return;
|
|
12669
|
+
const events = this.pendingEvents;
|
|
12670
|
+
this.pendingEvents = [];
|
|
12671
|
+
for (const event of events) {
|
|
12672
|
+
this.sendSseEvent(this.session.sseController, event);
|
|
12574
12673
|
}
|
|
12575
12674
|
}
|
|
12576
12675
|
sendSseEvent(controller, data) {
|