@posthog/agent 2.3.256 → 2.3.261
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 +24 -2
- package/dist/agent.js.map +1 -1
- package/dist/posthog-api.d.ts +1 -0
- package/dist/posthog-api.js +11 -1
- package/dist/posthog-api.js.map +1 -1
- package/dist/server/agent-server.d.ts +11 -0
- package/dist/server/agent-server.js +139 -30
- package/dist/server/agent-server.js.map +1 -1
- package/dist/server/bin.cjs +148 -31
- package/dist/server/bin.cjs.map +1 -1
- package/dist/types.d.ts +2 -0
- package/package.json +4 -3
- package/src/adapters/acp-connection.ts +6 -1
- package/src/adapters/claude/claude-agent.ts +19 -0
- package/src/adapters/claude/session/options.ts +3 -0
- package/src/adapters/claude/types.ts +1 -0
- package/src/agent.ts +1 -0
- package/src/posthog-api.ts +14 -0
- package/src/server/agent-server.test.ts +140 -7
- package/src/server/agent-server.ts +170 -37
- package/src/server/bin.ts +13 -0
- package/src/server/question-relay.test.ts +34 -5
- package/src/server/types.ts +1 -0
- package/src/types.ts +2 -0
package/dist/server/bin.cjs
CHANGED
|
@@ -5683,7 +5683,7 @@ var import_hono = require("hono");
|
|
|
5683
5683
|
// package.json
|
|
5684
5684
|
var package_default = {
|
|
5685
5685
|
name: "@posthog/agent",
|
|
5686
|
-
version: "2.3.
|
|
5686
|
+
version: "2.3.261",
|
|
5687
5687
|
repository: "https://github.com/PostHog/code",
|
|
5688
5688
|
description: "TypeScript agent framework wrapping Claude Agent SDK with Git-based task execution for PostHog",
|
|
5689
5689
|
exports: {
|
|
@@ -5779,6 +5779,7 @@ var package_default = {
|
|
|
5779
5779
|
},
|
|
5780
5780
|
dependencies: {
|
|
5781
5781
|
"@agentclientprotocol/sdk": "0.16.1",
|
|
5782
|
+
ajv: "^8.17.1",
|
|
5782
5783
|
"@anthropic-ai/claude-agent-sdk": "0.2.76",
|
|
5783
5784
|
"@anthropic-ai/sdk": "^0.78.0",
|
|
5784
5785
|
"@hono/node-server": "^1.19.9",
|
|
@@ -8630,6 +8631,7 @@ function buildSessionOptions(params) {
|
|
|
8630
8631
|
params.settingsManager,
|
|
8631
8632
|
params.logger
|
|
8632
8633
|
),
|
|
8634
|
+
outputFormat: params.outputFormat,
|
|
8633
8635
|
abortController: getAbortController(
|
|
8634
8636
|
params.userProvidedOptions?.abortController
|
|
8635
8637
|
),
|
|
@@ -9217,6 +9219,11 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
9217
9219
|
};
|
|
9218
9220
|
const result = handleResultMessage(message);
|
|
9219
9221
|
if (result.error) throw result.error;
|
|
9222
|
+
if (message.subtype === "success" && message.structured_output != null && this.options?.onStructuredOutput) {
|
|
9223
|
+
await this.options.onStructuredOutput(
|
|
9224
|
+
message.structured_output
|
|
9225
|
+
);
|
|
9226
|
+
}
|
|
9220
9227
|
if (isLocalOnlyCommand && message.subtype === "success" && message.result) {
|
|
9221
9228
|
await this.client.sessionUpdate({
|
|
9222
9229
|
sessionId: params.sessionId,
|
|
@@ -9442,6 +9449,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
9442
9449
|
const earlyModelId = settingsManager.getSettings().model || meta?.model || "";
|
|
9443
9450
|
const mcpServers = supportsMcpInjection(earlyModelId) ? parseMcpServers(params) : {};
|
|
9444
9451
|
const systemPrompt = buildSystemPrompt(meta?.systemPrompt);
|
|
9452
|
+
const outputFormat = meta?.jsonSchema && this.options?.onStructuredOutput ? { type: "json_schema", schema: meta.jsonSchema } : void 0;
|
|
9445
9453
|
this.logger.info(isResume ? "Resuming session" : "Creating new session", {
|
|
9446
9454
|
sessionId,
|
|
9447
9455
|
taskId,
|
|
@@ -9465,6 +9473,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
9465
9473
|
...meta?.additionalRoots ?? []
|
|
9466
9474
|
],
|
|
9467
9475
|
disableBuiltInTools: meta?.disableBuiltInTools,
|
|
9476
|
+
outputFormat,
|
|
9468
9477
|
settingsManager,
|
|
9469
9478
|
onModeChange: this.createOnModeChange(),
|
|
9470
9479
|
onProcessSpawned: this.options?.onProcessSpawned,
|
|
@@ -10424,7 +10433,10 @@ function createClaudeConnection(config) {
|
|
|
10424
10433
|
const agentStream = (0, import_sdk4.ndJsonStream)(agentWritable, streams.agent.readable);
|
|
10425
10434
|
let agent = null;
|
|
10426
10435
|
const agentConnection = new import_sdk4.AgentSideConnection((client) => {
|
|
10427
|
-
agent = new ClaudeAcpAgent(client,
|
|
10436
|
+
agent = new ClaudeAcpAgent(client, {
|
|
10437
|
+
...config.processCallbacks,
|
|
10438
|
+
onStructuredOutput: config.onStructuredOutput
|
|
10439
|
+
});
|
|
10428
10440
|
logger.info(`Created ${agent.adapterName} agent`);
|
|
10429
10441
|
return agent;
|
|
10430
10442
|
}, agentStream);
|
|
@@ -10656,6 +10668,15 @@ var PostHogAPIClient = class {
|
|
|
10656
10668
|
}
|
|
10657
10669
|
);
|
|
10658
10670
|
}
|
|
10671
|
+
async setTaskRunOutput(taskId, runId, output) {
|
|
10672
|
+
return this.apiRequest(
|
|
10673
|
+
`/api/projects/${this.getTeamId()}/tasks/${taskId}/runs/${runId}/set_output/`,
|
|
10674
|
+
{
|
|
10675
|
+
method: "PATCH",
|
|
10676
|
+
body: JSON.stringify(output)
|
|
10677
|
+
}
|
|
10678
|
+
);
|
|
10679
|
+
}
|
|
10659
10680
|
async appendTaskRunLog(taskId, runId, entries) {
|
|
10660
10681
|
const teamId = this.getTeamId();
|
|
10661
10682
|
return this.apiRequest(
|
|
@@ -12591,12 +12612,9 @@ var AgentServer = class _AgentServer {
|
|
|
12591
12612
|
prompt,
|
|
12592
12613
|
...this.detectedPrUrl && {
|
|
12593
12614
|
_meta: {
|
|
12594
|
-
|
|
12595
|
-
|
|
12596
|
-
|
|
12597
|
-
1. Check out the existing PR branch with \`gh pr checkout ${this.detectedPrUrl}\`
|
|
12598
|
-
2. Make changes, commit, and push to that branch
|
|
12599
|
-
You MUST NOT create a new branch, close the existing PR, or create a new PR.`
|
|
12615
|
+
// Keep the live-session PR override aligned with the startup
|
|
12616
|
+
// prompt policy so non-Slack runs remain review-first.
|
|
12617
|
+
prContext: this.buildDetectedPrContext(this.detectedPrUrl)
|
|
12600
12618
|
}
|
|
12601
12619
|
}
|
|
12602
12620
|
});
|
|
@@ -12704,7 +12722,16 @@ You MUST NOT create a new branch, close the existing PR, or create a new PR.`
|
|
|
12704
12722
|
taskRunId: payload.run_id,
|
|
12705
12723
|
taskId: payload.task_id,
|
|
12706
12724
|
deviceType: deviceInfo.type,
|
|
12707
|
-
logWriter
|
|
12725
|
+
logWriter,
|
|
12726
|
+
onStructuredOutput: async (output) => {
|
|
12727
|
+
await this.posthogAPI.setTaskRunOutput(
|
|
12728
|
+
payload.task_id,
|
|
12729
|
+
payload.run_id,
|
|
12730
|
+
{
|
|
12731
|
+
output
|
|
12732
|
+
}
|
|
12733
|
+
);
|
|
12734
|
+
}
|
|
12708
12735
|
});
|
|
12709
12736
|
const onAcpMessage = (message) => {
|
|
12710
12737
|
this.broadcastEvent({
|
|
@@ -12732,18 +12759,23 @@ You MUST NOT create a new branch, close the existing PR, or create a new PR.`
|
|
|
12732
12759
|
protocolVersion: import_sdk5.PROTOCOL_VERSION,
|
|
12733
12760
|
clientCapabilities: {}
|
|
12734
12761
|
});
|
|
12735
|
-
|
|
12736
|
-
|
|
12737
|
-
|
|
12738
|
-
|
|
12739
|
-
|
|
12740
|
-
|
|
12741
|
-
|
|
12742
|
-
|
|
12743
|
-
|
|
12744
|
-
|
|
12745
|
-
|
|
12746
|
-
|
|
12762
|
+
const [preTaskRun, preTask] = await Promise.all([
|
|
12763
|
+
this.posthogAPI.getTaskRun(payload.task_id, payload.run_id).catch((err) => {
|
|
12764
|
+
this.logger.warn("Failed to fetch task run for session context", {
|
|
12765
|
+
taskId: payload.task_id,
|
|
12766
|
+
runId: payload.run_id,
|
|
12767
|
+
error: err
|
|
12768
|
+
});
|
|
12769
|
+
return null;
|
|
12770
|
+
}),
|
|
12771
|
+
this.posthogAPI.getTask(payload.task_id).catch((err) => {
|
|
12772
|
+
this.logger.warn("Failed to fetch task for session context", {
|
|
12773
|
+
taskId: payload.task_id,
|
|
12774
|
+
error: err
|
|
12775
|
+
});
|
|
12776
|
+
return null;
|
|
12777
|
+
})
|
|
12778
|
+
]);
|
|
12747
12779
|
const prUrl = typeof preTaskRun?.state?.slack_notified_pr_url === "string" ? (preTaskRun?.state).slack_notified_pr_url : null;
|
|
12748
12780
|
if (prUrl) {
|
|
12749
12781
|
this.detectedPrUrl = prUrl;
|
|
@@ -12756,6 +12788,7 @@ You MUST NOT create a new branch, close the existing PR, or create a new PR.`
|
|
|
12756
12788
|
taskRunId: payload.run_id,
|
|
12757
12789
|
systemPrompt: this.buildSessionSystemPrompt(prUrl),
|
|
12758
12790
|
allowedDomains: this.config.allowedDomains,
|
|
12791
|
+
jsonSchema: preTask?.json_schema ?? null,
|
|
12759
12792
|
...this.config.claudeCode?.plugins?.length && {
|
|
12760
12793
|
claudeCode: {
|
|
12761
12794
|
options: {
|
|
@@ -13041,13 +13074,38 @@ ${toolSummary}`);
|
|
|
13041
13074
|
}
|
|
13042
13075
|
return { append: cloudAppend };
|
|
13043
13076
|
}
|
|
13077
|
+
getCloudInteractionOrigin() {
|
|
13078
|
+
return process.env.POSTHOG_CODE_INTERACTION_ORIGIN ?? process.env.CODE_INTERACTION_ORIGIN ?? process.env.TWIG_INTERACTION_ORIGIN;
|
|
13079
|
+
}
|
|
13080
|
+
/**
|
|
13081
|
+
* Slack-origin cloud runs auto-publish by default. Every other origin is
|
|
13082
|
+
* review-first unless the user explicitly asks, and createPr=false always
|
|
13083
|
+
* disables publishing.
|
|
13084
|
+
*/
|
|
13085
|
+
shouldAutoPublishCloudChanges() {
|
|
13086
|
+
return this.getCloudInteractionOrigin() === "slack" && this.config.createPr !== false;
|
|
13087
|
+
}
|
|
13088
|
+
buildDetectedPrContext(prUrl) {
|
|
13089
|
+
if (!this.shouldAutoPublishCloudChanges()) {
|
|
13090
|
+
return `An open pull request already exists: ${prUrl}
|
|
13091
|
+
Use that PR as context if it is helpful, but stop with local changes ready for review.
|
|
13092
|
+
Do NOT create commits, push to the PR branch, update the pull request, create a new branch, or create a new pull request unless the user explicitly asks.`;
|
|
13093
|
+
}
|
|
13094
|
+
return `IMPORTANT \u2014 OVERRIDE PREVIOUS INSTRUCTIONS ABOUT CREATING BRANCHES/PRs.
|
|
13095
|
+
You already have an open pull request: ${prUrl}
|
|
13096
|
+
You MUST:
|
|
13097
|
+
1. Check out the existing PR branch with \`gh pr checkout ${prUrl}\`
|
|
13098
|
+
2. Make changes, commit, and push to that branch
|
|
13099
|
+
You MUST NOT create a new branch, close the existing PR, or create a new PR.`;
|
|
13100
|
+
}
|
|
13044
13101
|
buildCloudSystemPrompt(prUrl) {
|
|
13045
13102
|
const taskId = this.config.taskId;
|
|
13103
|
+
const shouldAutoCreatePr = this.shouldAutoPublishCloudChanges();
|
|
13046
13104
|
const attributionInstructions = `
|
|
13047
13105
|
## Attribution
|
|
13048
13106
|
Do NOT use Claude Code's default attribution (no "Co-Authored-By" trailers, no "Generated with [Claude Code]" lines).
|
|
13049
13107
|
|
|
13050
|
-
|
|
13108
|
+
If you create a commit, add the following trailers to the commit message (after a blank line at the end):
|
|
13051
13109
|
Generated-By: PostHog Code
|
|
13052
13110
|
Task-Id: ${taskId}
|
|
13053
13111
|
|
|
@@ -13062,6 +13120,20 @@ EOF
|
|
|
13062
13120
|
)"
|
|
13063
13121
|
\`\`\``;
|
|
13064
13122
|
if (prUrl) {
|
|
13123
|
+
if (!shouldAutoCreatePr) {
|
|
13124
|
+
return `
|
|
13125
|
+
# Cloud Task Execution
|
|
13126
|
+
|
|
13127
|
+
This task already has an open pull request: ${prUrl}
|
|
13128
|
+
|
|
13129
|
+
Do the requested work, but stop with local changes ready for review.
|
|
13130
|
+
|
|
13131
|
+
Important:
|
|
13132
|
+
- Do NOT create new commits, push to the branch, or update the pull request unless the user explicitly asks.
|
|
13133
|
+
- Do NOT create a new branch or a new pull request.
|
|
13134
|
+
${attributionInstructions}
|
|
13135
|
+
`;
|
|
13136
|
+
}
|
|
13065
13137
|
return `
|
|
13066
13138
|
# Cloud Task Execution
|
|
13067
13139
|
|
|
@@ -13095,6 +13167,17 @@ When the user asks for code changes or software engineering tasks:
|
|
|
13095
13167
|
Important:
|
|
13096
13168
|
- Do NOT create branches, commits, or pull requests in this mode.
|
|
13097
13169
|
- Prefer using MCP tools to answer questions with real data over giving generic advice.
|
|
13170
|
+
`;
|
|
13171
|
+
}
|
|
13172
|
+
if (!shouldAutoCreatePr) {
|
|
13173
|
+
return `
|
|
13174
|
+
# Cloud Task Execution
|
|
13175
|
+
|
|
13176
|
+
Do the requested work, but stop with local changes ready for review.
|
|
13177
|
+
|
|
13178
|
+
Important:
|
|
13179
|
+
- Do NOT create a branch, commit, push, or open a pull request unless the user explicitly asks.
|
|
13180
|
+
${attributionInstructions}
|
|
13098
13181
|
`;
|
|
13099
13182
|
}
|
|
13100
13183
|
return `
|
|
@@ -13203,9 +13286,30 @@ ${attributionInstructions}
|
|
|
13203
13286
|
LLM_GATEWAY_URL: gatewayUrl
|
|
13204
13287
|
});
|
|
13205
13288
|
}
|
|
13289
|
+
buildSlackQuestionRelayResponse(payload, toolMeta2) {
|
|
13290
|
+
this.relaySlackQuestion(payload, toolMeta2);
|
|
13291
|
+
return {
|
|
13292
|
+
outcome: { outcome: "cancelled" },
|
|
13293
|
+
_meta: {
|
|
13294
|
+
message: "This question has been relayed to the Slack thread where this task originated. The user will reply there. Do NOT re-ask the question or pick an answer yourself. Simply let the user know you are waiting for their reply."
|
|
13295
|
+
}
|
|
13296
|
+
};
|
|
13297
|
+
}
|
|
13298
|
+
shouldBlockPublishPermission(params) {
|
|
13299
|
+
if (this.config.createPr !== false) {
|
|
13300
|
+
return false;
|
|
13301
|
+
}
|
|
13302
|
+
const meta = params.toolCall?._meta && typeof params.toolCall._meta === "object" && !Array.isArray(params.toolCall._meta) ? params.toolCall._meta : null;
|
|
13303
|
+
const rawInput = params.toolCall?.rawInput && typeof params.toolCall.rawInput === "object" && !Array.isArray(params.toolCall.rawInput) ? params.toolCall.rawInput : null;
|
|
13304
|
+
const toolName = typeof meta?.toolName === "string" ? meta.toolName : null;
|
|
13305
|
+
const command = typeof rawInput?.command === "string" ? rawInput.command : null;
|
|
13306
|
+
return Boolean(
|
|
13307
|
+
toolName && (toolName === "Bash" || toolName.includes("bash")) && command && /\bgit\s+push\b|\bgh\s+pr\s+(create|edit|ready|merge)\b/.test(command)
|
|
13308
|
+
);
|
|
13309
|
+
}
|
|
13206
13310
|
createCloudClient(payload) {
|
|
13207
13311
|
const mode = this.getEffectiveMode(payload);
|
|
13208
|
-
const interactionOrigin = process.env.CODE_INTERACTION_ORIGIN ?? process.env.TWIG_INTERACTION_ORIGIN;
|
|
13312
|
+
const interactionOrigin = process.env.POSTHOG_CODE_INTERACTION_ORIGIN ?? process.env.CODE_INTERACTION_ORIGIN ?? process.env.TWIG_INTERACTION_ORIGIN;
|
|
13209
13313
|
return {
|
|
13210
13314
|
requestPermission: async (params) => {
|
|
13211
13315
|
this.logger.debug("Permission request", {
|
|
@@ -13220,15 +13324,20 @@ ${attributionInstructions}
|
|
|
13220
13324
|
if (interactionOrigin === "slack") {
|
|
13221
13325
|
const codeToolKind = params.toolCall?._meta?.codeToolKind;
|
|
13222
13326
|
if (codeToolKind === "question") {
|
|
13223
|
-
this.
|
|
13224
|
-
|
|
13225
|
-
|
|
13226
|
-
|
|
13227
|
-
message: "This question has been relayed to the Slack thread where this task originated. The user will reply there. Do NOT re-ask the question or pick an answer yourself. Simply let the user know you are waiting for their reply."
|
|
13228
|
-
}
|
|
13229
|
-
};
|
|
13327
|
+
return this.buildSlackQuestionRelayResponse(
|
|
13328
|
+
payload,
|
|
13329
|
+
params.toolCall?._meta
|
|
13330
|
+
);
|
|
13230
13331
|
}
|
|
13231
13332
|
}
|
|
13333
|
+
if (this.shouldBlockPublishPermission(params)) {
|
|
13334
|
+
return {
|
|
13335
|
+
outcome: { outcome: "cancelled" },
|
|
13336
|
+
_meta: {
|
|
13337
|
+
message: "This run is configured to stop before publishing. Do not push commits or create/update pull requests unless the user explicitly asks."
|
|
13338
|
+
}
|
|
13339
|
+
};
|
|
13340
|
+
}
|
|
13232
13341
|
return {
|
|
13233
13342
|
outcome: {
|
|
13234
13343
|
outcome: "selected",
|
|
@@ -13513,6 +13622,12 @@ var envSchema = import_v42.z.object({
|
|
|
13513
13622
|
}).regex(/^\d+$/, "POSTHOG_PROJECT_ID must be a numeric string").transform((val) => parseInt(val, 10))
|
|
13514
13623
|
});
|
|
13515
13624
|
var program = new import_commander.Command();
|
|
13625
|
+
function parseBooleanOption(raw, flag) {
|
|
13626
|
+
if (raw === void 0) return void 0;
|
|
13627
|
+
if (raw === "true") return true;
|
|
13628
|
+
if (raw === "false") return false;
|
|
13629
|
+
program.error(`${flag} must be either "true" or "false"`);
|
|
13630
|
+
}
|
|
13516
13631
|
function parseJsonOption(raw, schema, flag) {
|
|
13517
13632
|
if (!raw) return void 0;
|
|
13518
13633
|
let parsed;
|
|
@@ -13536,7 +13651,7 @@ program.name("agent-server").description("PostHog cloud agent server - runs in s
|
|
|
13536
13651
|
).option("--repositoryPath <path>", "Path to the repository").requiredOption("--taskId <id>", "Task ID").requiredOption("--runId <id>", "Task run ID").option(
|
|
13537
13652
|
"--mcpServers <json>",
|
|
13538
13653
|
"MCP servers config as JSON array (ACP McpServer[] format)"
|
|
13539
|
-
).option("--baseBranch <branch>", "Base branch for PR creation").option(
|
|
13654
|
+
).option("--createPr <boolean>", "Whether this run may publish changes").option("--baseBranch <branch>", "Base branch for PR creation").option(
|
|
13540
13655
|
"--claudeCodeConfig <json>",
|
|
13541
13656
|
"Claude Code config as JSON (systemPrompt, systemPromptAppend, plugins)"
|
|
13542
13657
|
).option(
|
|
@@ -13552,6 +13667,7 @@ ${errors}`);
|
|
|
13552
13667
|
}
|
|
13553
13668
|
const env = envResult.data;
|
|
13554
13669
|
const mode = options.mode === "background" ? "background" : "interactive";
|
|
13670
|
+
const createPr = parseBooleanOption(options.createPr, "--createPr");
|
|
13555
13671
|
const mcpServers = parseJsonOption(
|
|
13556
13672
|
options.mcpServers,
|
|
13557
13673
|
mcpServersSchema,
|
|
@@ -13573,6 +13689,7 @@ ${errors}`);
|
|
|
13573
13689
|
mode,
|
|
13574
13690
|
taskId: options.taskId,
|
|
13575
13691
|
runId: options.runId,
|
|
13692
|
+
createPr,
|
|
13576
13693
|
mcpServers,
|
|
13577
13694
|
baseBranch: options.baseBranch,
|
|
13578
13695
|
claudeCode,
|