@posthog/agent 2.3.524 → 2.3.527
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 +30 -5
- package/dist/agent.js.map +1 -1
- package/dist/handoff-checkpoint.js +2 -2
- package/dist/handoff-checkpoint.js.map +1 -1
- package/dist/posthog-api.js +5 -1
- package/dist/posthog-api.js.map +1 -1
- package/dist/pr-url-detector.d.ts +12 -0
- package/dist/pr-url-detector.js +34 -0
- package/dist/pr-url-detector.js.map +1 -0
- package/dist/server/agent-server.js +76 -39
- package/dist/server/agent-server.js.map +1 -1
- package/dist/server/bin.cjs +76 -39
- package/dist/server/bin.cjs.map +1 -1
- package/package.json +7 -3
- package/src/adapters/claude/conversion/sdk-to-acp.ts +28 -3
- package/src/adapters/claude/types.ts +1 -0
- package/src/handoff-checkpoint.ts +2 -2
- package/src/pr-url-detector.test.ts +140 -0
- package/src/pr-url-detector.ts +46 -0
- package/src/server/agent-server.test.ts +68 -1
- package/src/server/agent-server.ts +17 -40
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@posthog/agent",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.527",
|
|
4
4
|
"repository": "https://github.com/PostHog/code",
|
|
5
5
|
"description": "TypeScript agent framework wrapping Claude Agent SDK with Git-based task execution for PostHog",
|
|
6
6
|
"exports": {
|
|
@@ -20,6 +20,10 @@
|
|
|
20
20
|
"types": "./dist/posthog-api.d.ts",
|
|
21
21
|
"import": "./dist/posthog-api.js"
|
|
22
22
|
},
|
|
23
|
+
"./pr-url-detector": {
|
|
24
|
+
"types": "./dist/pr-url-detector.d.ts",
|
|
25
|
+
"import": "./dist/pr-url-detector.js"
|
|
26
|
+
},
|
|
23
27
|
"./types": {
|
|
24
28
|
"types": "./dist/types.d.ts",
|
|
25
29
|
"import": "./dist/types.js"
|
|
@@ -102,9 +106,9 @@
|
|
|
102
106
|
"tsx": "^4.20.6",
|
|
103
107
|
"typescript": "^5.5.0",
|
|
104
108
|
"vitest": "^2.1.8",
|
|
105
|
-
"@posthog/git": "1.0.0",
|
|
106
109
|
"@posthog/shared": "1.0.0",
|
|
107
|
-
"@posthog/enricher": "1.0.0"
|
|
110
|
+
"@posthog/enricher": "1.0.0",
|
|
111
|
+
"@posthog/git": "1.0.0"
|
|
108
112
|
},
|
|
109
113
|
"dependencies": {
|
|
110
114
|
"@agentclientprotocol/sdk": "0.19.0",
|
|
@@ -90,13 +90,23 @@ function toolMeta(
|
|
|
90
90
|
toolName: string,
|
|
91
91
|
toolResponse?: unknown,
|
|
92
92
|
parentToolCallId?: string,
|
|
93
|
+
bashCommand?: string,
|
|
93
94
|
): ToolUpdateMeta {
|
|
94
95
|
const meta: ToolUpdateMeta["claudeCode"] = { toolName };
|
|
95
96
|
if (toolResponse !== undefined) meta.toolResponse = toolResponse;
|
|
96
97
|
if (parentToolCallId) meta.parentToolCallId = parentToolCallId;
|
|
98
|
+
if (bashCommand) meta.bashCommand = bashCommand;
|
|
97
99
|
return { claudeCode: meta };
|
|
98
100
|
}
|
|
99
101
|
|
|
102
|
+
function bashCommandFromToolUse(
|
|
103
|
+
toolUse: ToolUseCache[string] | undefined,
|
|
104
|
+
): string | undefined {
|
|
105
|
+
if (!toolUse || toolUse.name !== "Bash") return undefined;
|
|
106
|
+
const command = (toolUse.input as { command?: unknown } | undefined)?.command;
|
|
107
|
+
return typeof command === "string" ? command : undefined;
|
|
108
|
+
}
|
|
109
|
+
|
|
100
110
|
function handleTextChunk(
|
|
101
111
|
chunk: { text: string },
|
|
102
112
|
role: Role,
|
|
@@ -181,7 +191,12 @@ function handleToolUseChunk(
|
|
|
181
191
|
await ctx.client.sessionUpdate({
|
|
182
192
|
sessionId: ctx.sessionId,
|
|
183
193
|
update: {
|
|
184
|
-
_meta: toolMeta(
|
|
194
|
+
_meta: toolMeta(
|
|
195
|
+
toolUse.name,
|
|
196
|
+
toolResponse,
|
|
197
|
+
ctx.parentToolCallId,
|
|
198
|
+
bashCommandFromToolUse(toolUse),
|
|
199
|
+
),
|
|
185
200
|
toolCallId: toolUseId,
|
|
186
201
|
sessionUpdate: "tool_call_update",
|
|
187
202
|
...(editUpdate ? editUpdate : {}),
|
|
@@ -211,7 +226,12 @@ function handleToolUseChunk(
|
|
|
211
226
|
});
|
|
212
227
|
|
|
213
228
|
const meta: Record<string, unknown> = {
|
|
214
|
-
...toolMeta(
|
|
229
|
+
...toolMeta(
|
|
230
|
+
chunk.name,
|
|
231
|
+
undefined,
|
|
232
|
+
ctx.parentToolCallId,
|
|
233
|
+
bashCommandFromToolUse(chunk),
|
|
234
|
+
),
|
|
215
235
|
};
|
|
216
236
|
if (chunk.name === "Bash" && ctx.supportsTerminalOutput && !alreadyCached) {
|
|
217
237
|
meta.terminal_info = { terminal_id: chunk.id };
|
|
@@ -351,7 +371,12 @@ function handleToolResultChunk(
|
|
|
351
371
|
}
|
|
352
372
|
|
|
353
373
|
const meta: Record<string, unknown> = {
|
|
354
|
-
...toolMeta(
|
|
374
|
+
...toolMeta(
|
|
375
|
+
toolUse.name,
|
|
376
|
+
undefined,
|
|
377
|
+
ctx.parentToolCallId,
|
|
378
|
+
bashCommandFromToolUse(toolUse),
|
|
379
|
+
),
|
|
355
380
|
...(resultMeta?.terminal_exit
|
|
356
381
|
? { terminal_exit: resultMeta.terminal_exit }
|
|
357
382
|
: {}),
|
|
@@ -300,7 +300,7 @@ export class HandoffCheckpointTracker {
|
|
|
300
300
|
checkpoint: GitHandoffCheckpoint,
|
|
301
301
|
uploads: Uploads,
|
|
302
302
|
): void {
|
|
303
|
-
this.logger.
|
|
303
|
+
this.logger.debug("Captured handoff checkpoint", {
|
|
304
304
|
branch: checkpoint.branch,
|
|
305
305
|
head: checkpoint.head?.slice(0, 7),
|
|
306
306
|
totalBytes: this.sumRawBytes(uploads.pack, uploads.index),
|
|
@@ -312,7 +312,7 @@ export class HandoffCheckpointTracker {
|
|
|
312
312
|
_downloads: Downloads,
|
|
313
313
|
totalBytes: number,
|
|
314
314
|
): void {
|
|
315
|
-
this.logger.
|
|
315
|
+
this.logger.debug("Applied handoff checkpoint", {
|
|
316
316
|
branch: checkpoint.branch,
|
|
317
317
|
head: checkpoint.head?.slice(0, 7),
|
|
318
318
|
totalBytes,
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import {
|
|
3
|
+
type ExtractCreatedPrUrlInput,
|
|
4
|
+
extractCreatedPrUrl,
|
|
5
|
+
} from "./pr-url-detector";
|
|
6
|
+
|
|
7
|
+
const PR_URL = "https://github.com/PostHog/posthog/pull/12345";
|
|
8
|
+
|
|
9
|
+
interface Case {
|
|
10
|
+
name: string;
|
|
11
|
+
input: ExtractCreatedPrUrlInput;
|
|
12
|
+
expected: string | null;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const cases: Case[] = [
|
|
16
|
+
{
|
|
17
|
+
name: "returns the URL when gh pr create produced it (string toolResponse)",
|
|
18
|
+
input: {
|
|
19
|
+
toolName: "Bash",
|
|
20
|
+
bashCommand: 'gh pr create --title "x" --body "y"',
|
|
21
|
+
toolResponse: `${PR_URL}\n`,
|
|
22
|
+
},
|
|
23
|
+
expected: PR_URL,
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: "returns the URL when gh pr create produced it (object toolResponse)",
|
|
27
|
+
input: {
|
|
28
|
+
toolName: "Bash",
|
|
29
|
+
bashCommand: "gh pr create --fill",
|
|
30
|
+
toolResponse: { stdout: `${PR_URL}\n`, stderr: "" },
|
|
31
|
+
},
|
|
32
|
+
expected: PR_URL,
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
name: "ignores PR URLs from gh pr view",
|
|
36
|
+
input: {
|
|
37
|
+
toolName: "Bash",
|
|
38
|
+
bashCommand: `gh pr view ${PR_URL}`,
|
|
39
|
+
toolResponse: { stdout: PR_URL },
|
|
40
|
+
},
|
|
41
|
+
expected: null,
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: "ignores PR URLs from gh search prs",
|
|
45
|
+
input: {
|
|
46
|
+
toolName: "Bash",
|
|
47
|
+
bashCommand: 'gh search prs "fix login"',
|
|
48
|
+
toolResponse: PR_URL,
|
|
49
|
+
},
|
|
50
|
+
expected: null,
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: "ignores PR URLs from gh pr list",
|
|
54
|
+
input: {
|
|
55
|
+
toolName: "Bash",
|
|
56
|
+
bashCommand: "gh pr list --json url",
|
|
57
|
+
toolResponse: PR_URL,
|
|
58
|
+
},
|
|
59
|
+
expected: null,
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
name: "returns null when bashCommand is missing",
|
|
63
|
+
input: {
|
|
64
|
+
toolName: "Bash",
|
|
65
|
+
bashCommand: undefined,
|
|
66
|
+
toolResponse: PR_URL,
|
|
67
|
+
},
|
|
68
|
+
expected: null,
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
name: "returns null for non-Bash tools",
|
|
72
|
+
input: {
|
|
73
|
+
toolName: "Edit",
|
|
74
|
+
bashCommand: "gh pr create",
|
|
75
|
+
toolResponse: PR_URL,
|
|
76
|
+
},
|
|
77
|
+
expected: null,
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
name: "accepts the lowercase 'bash' tool variant",
|
|
81
|
+
input: {
|
|
82
|
+
toolName: "bash",
|
|
83
|
+
bashCommand: "gh pr create",
|
|
84
|
+
toolResponse: PR_URL,
|
|
85
|
+
},
|
|
86
|
+
expected: PR_URL,
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
name: "returns null when output has no PR URL",
|
|
90
|
+
input: {
|
|
91
|
+
toolName: "Bash",
|
|
92
|
+
bashCommand: "gh pr create",
|
|
93
|
+
toolResponse: "no pr was created",
|
|
94
|
+
},
|
|
95
|
+
expected: null,
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
name: "finds the URL in the content array when toolResponse is empty",
|
|
99
|
+
input: {
|
|
100
|
+
toolName: "Bash",
|
|
101
|
+
bashCommand: "gh pr create --fill",
|
|
102
|
+
toolResponse: undefined,
|
|
103
|
+
content: [{ type: "text", text: `Created: ${PR_URL}` }],
|
|
104
|
+
},
|
|
105
|
+
expected: PR_URL,
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
name: "handles output field on object toolResponse",
|
|
109
|
+
input: {
|
|
110
|
+
toolName: "Bash",
|
|
111
|
+
bashCommand: "gh pr create",
|
|
112
|
+
toolResponse: { output: PR_URL },
|
|
113
|
+
},
|
|
114
|
+
expected: PR_URL,
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
name: "matches gh pr create even with a chained command",
|
|
118
|
+
input: {
|
|
119
|
+
toolName: "Bash",
|
|
120
|
+
bashCommand: "git push -u origin feat/x && gh pr create --fill",
|
|
121
|
+
toolResponse: { stdout: PR_URL },
|
|
122
|
+
},
|
|
123
|
+
expected: PR_URL,
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
name: "does not match a fake command containing 'pr create' as text",
|
|
127
|
+
input: {
|
|
128
|
+
toolName: "Bash",
|
|
129
|
+
bashCommand: "echo 'i should pr create later'",
|
|
130
|
+
toolResponse: PR_URL,
|
|
131
|
+
},
|
|
132
|
+
expected: null,
|
|
133
|
+
},
|
|
134
|
+
];
|
|
135
|
+
|
|
136
|
+
describe("extractCreatedPrUrl", () => {
|
|
137
|
+
it.each(cases)("$name", ({ input, expected }) => {
|
|
138
|
+
expect(extractCreatedPrUrl(input)).toBe(expected);
|
|
139
|
+
});
|
|
140
|
+
});
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const PR_URL_REGEX = /https:\/\/github\.com\/[^/]+\/[^/]+\/pull\/\d+/;
|
|
2
|
+
const GH_PR_CREATE_REGEX = /\bgh\s+pr\s+create\b/;
|
|
3
|
+
|
|
4
|
+
export interface ExtractCreatedPrUrlInput {
|
|
5
|
+
toolName: string | undefined;
|
|
6
|
+
bashCommand: string | undefined;
|
|
7
|
+
toolResponse: unknown;
|
|
8
|
+
content?: Array<{ type?: string; text?: string }>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function extractCreatedPrUrl(
|
|
12
|
+
input: ExtractCreatedPrUrlInput,
|
|
13
|
+
): string | null {
|
|
14
|
+
const { toolName, bashCommand, toolResponse, content } = input;
|
|
15
|
+
|
|
16
|
+
if (!toolName || !/bash/i.test(toolName)) return null;
|
|
17
|
+
if (!bashCommand || !GH_PR_CREATE_REGEX.test(bashCommand)) return null;
|
|
18
|
+
|
|
19
|
+
let textToSearch = "";
|
|
20
|
+
|
|
21
|
+
if (toolResponse) {
|
|
22
|
+
if (typeof toolResponse === "string") {
|
|
23
|
+
textToSearch = toolResponse;
|
|
24
|
+
} else if (typeof toolResponse === "object" && toolResponse !== null) {
|
|
25
|
+
const respObj = toolResponse as Record<string, unknown>;
|
|
26
|
+
textToSearch =
|
|
27
|
+
String(respObj.stdout || "") + String(respObj.stderr || "");
|
|
28
|
+
if (!textToSearch && respObj.output) {
|
|
29
|
+
textToSearch = String(respObj.output);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (Array.isArray(content)) {
|
|
35
|
+
for (const item of content) {
|
|
36
|
+
if (item.type === "text" && item.text) {
|
|
37
|
+
textToSearch += ` ${item.text}`;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (!textToSearch) return null;
|
|
43
|
+
|
|
44
|
+
const match = textToSearch.match(PR_URL_REGEX);
|
|
45
|
+
return match ? match[0] : null;
|
|
46
|
+
}
|
|
@@ -625,7 +625,7 @@ describe("AgentServer HTTP Mode", () => {
|
|
|
625
625
|
});
|
|
626
626
|
|
|
627
627
|
describe("detectedPrUrl tracking", () => {
|
|
628
|
-
it("stores PR URL when
|
|
628
|
+
it("stores PR URL when gh pr create produces it", () => {
|
|
629
629
|
const s = createServer();
|
|
630
630
|
const payload = {
|
|
631
631
|
task_id: "test-task-id",
|
|
@@ -635,6 +635,7 @@ describe("AgentServer HTTP Mode", () => {
|
|
|
635
635
|
_meta: {
|
|
636
636
|
claudeCode: {
|
|
637
637
|
toolName: "Bash",
|
|
638
|
+
bashCommand: 'gh pr create --title "x" --body "y"',
|
|
638
639
|
toolResponse: {
|
|
639
640
|
stdout:
|
|
640
641
|
"https://github.com/PostHog/posthog/pull/42\nCreating pull request...",
|
|
@@ -659,6 +660,7 @@ describe("AgentServer HTTP Mode", () => {
|
|
|
659
660
|
_meta: {
|
|
660
661
|
claudeCode: {
|
|
661
662
|
toolName: "Bash",
|
|
663
|
+
bashCommand: "gh pr create",
|
|
662
664
|
toolResponse: { stdout: "just some output" },
|
|
663
665
|
},
|
|
664
666
|
},
|
|
@@ -667,6 +669,71 @@ describe("AgentServer HTTP Mode", () => {
|
|
|
667
669
|
(s as unknown as TestableServer).detectAndAttachPrUrl(payload, update);
|
|
668
670
|
expect((s as unknown as TestableServer).detectedPrUrl).toBeNull();
|
|
669
671
|
});
|
|
672
|
+
|
|
673
|
+
it("does not attach PR URL when the bash command is gh pr view", () => {
|
|
674
|
+
const s = createServer();
|
|
675
|
+
const payload = {
|
|
676
|
+
task_id: "test-task-id",
|
|
677
|
+
run_id: "test-run-id",
|
|
678
|
+
};
|
|
679
|
+
const update = {
|
|
680
|
+
_meta: {
|
|
681
|
+
claudeCode: {
|
|
682
|
+
toolName: "Bash",
|
|
683
|
+
bashCommand: "gh pr view 42 --json url",
|
|
684
|
+
toolResponse: {
|
|
685
|
+
stdout: "https://github.com/PostHog/posthog/pull/42",
|
|
686
|
+
},
|
|
687
|
+
},
|
|
688
|
+
},
|
|
689
|
+
};
|
|
690
|
+
|
|
691
|
+
(s as unknown as TestableServer).detectAndAttachPrUrl(payload, update);
|
|
692
|
+
expect((s as unknown as TestableServer).detectedPrUrl).toBeNull();
|
|
693
|
+
});
|
|
694
|
+
|
|
695
|
+
it("does not attach PR URL when the bash command is gh search prs", () => {
|
|
696
|
+
const s = createServer();
|
|
697
|
+
const payload = {
|
|
698
|
+
task_id: "test-task-id",
|
|
699
|
+
run_id: "test-run-id",
|
|
700
|
+
};
|
|
701
|
+
const update = {
|
|
702
|
+
_meta: {
|
|
703
|
+
claudeCode: {
|
|
704
|
+
toolName: "Bash",
|
|
705
|
+
bashCommand: 'gh search prs "fix login"',
|
|
706
|
+
toolResponse: {
|
|
707
|
+
stdout: "https://github.com/PostHog/posthog/pull/42",
|
|
708
|
+
},
|
|
709
|
+
},
|
|
710
|
+
},
|
|
711
|
+
};
|
|
712
|
+
|
|
713
|
+
(s as unknown as TestableServer).detectAndAttachPrUrl(payload, update);
|
|
714
|
+
expect((s as unknown as TestableServer).detectedPrUrl).toBeNull();
|
|
715
|
+
});
|
|
716
|
+
|
|
717
|
+
it("does not attach PR URL when bashCommand is missing", () => {
|
|
718
|
+
const s = createServer();
|
|
719
|
+
const payload = {
|
|
720
|
+
task_id: "test-task-id",
|
|
721
|
+
run_id: "test-run-id",
|
|
722
|
+
};
|
|
723
|
+
const update = {
|
|
724
|
+
_meta: {
|
|
725
|
+
claudeCode: {
|
|
726
|
+
toolName: "Bash",
|
|
727
|
+
toolResponse: {
|
|
728
|
+
stdout: "https://github.com/PostHog/posthog/pull/42",
|
|
729
|
+
},
|
|
730
|
+
},
|
|
731
|
+
},
|
|
732
|
+
};
|
|
733
|
+
|
|
734
|
+
(s as unknown as TestableServer).detectAndAttachPrUrl(payload, update);
|
|
735
|
+
expect((s as unknown as TestableServer).detectedPrUrl).toBeNull();
|
|
736
|
+
});
|
|
670
737
|
});
|
|
671
738
|
|
|
672
739
|
describe("buildCloudSystemPrompt", () => {
|
|
@@ -29,6 +29,7 @@ import type { PermissionMode } from "../execution-mode";
|
|
|
29
29
|
import { DEFAULT_CODEX_MODEL } from "../gateway-models";
|
|
30
30
|
import { HandoffCheckpointTracker } from "../handoff-checkpoint";
|
|
31
31
|
import { PostHogAPIClient } from "../posthog-api";
|
|
32
|
+
import { extractCreatedPrUrl } from "../pr-url-detector";
|
|
32
33
|
import {
|
|
33
34
|
formatConversationForResume,
|
|
34
35
|
type ResumeState,
|
|
@@ -588,7 +589,7 @@ export class AgentServer {
|
|
|
588
589
|
switch (method) {
|
|
589
590
|
case POSTHOG_NOTIFICATIONS.USER_MESSAGE:
|
|
590
591
|
case "user_message": {
|
|
591
|
-
this.logger.
|
|
592
|
+
this.logger.debug("Received user_message command", {
|
|
592
593
|
hasContent:
|
|
593
594
|
typeof params.content === "string"
|
|
594
595
|
? params.content.trim().length > 0
|
|
@@ -608,7 +609,7 @@ export class AgentServer {
|
|
|
608
609
|
if (prompt.length === 0) {
|
|
609
610
|
throw new Error("User message cannot be empty");
|
|
610
611
|
}
|
|
611
|
-
this.logger.
|
|
612
|
+
this.logger.debug("Built user_message prompt", {
|
|
612
613
|
blockTypes: prompt.map((block) => block.type),
|
|
613
614
|
});
|
|
614
615
|
const promptPreview = promptBlocksToText(prompt);
|
|
@@ -718,7 +719,7 @@ export class AgentServer {
|
|
|
718
719
|
? params.mcpServers
|
|
719
720
|
: [];
|
|
720
721
|
|
|
721
|
-
this.logger.
|
|
722
|
+
this.logger.debug("Refresh session requested", {
|
|
722
723
|
serverCount: mcpServers.length,
|
|
723
724
|
});
|
|
724
725
|
|
|
@@ -1191,7 +1192,7 @@ export class AgentServer {
|
|
|
1191
1192
|
this.resumeState.latestGitCheckpoint,
|
|
1192
1193
|
);
|
|
1193
1194
|
checkpointApplied = true;
|
|
1194
|
-
this.logger.
|
|
1195
|
+
this.logger.debug("Git checkpoint applied", {
|
|
1195
1196
|
branch: this.resumeState.latestGitCheckpoint.branch,
|
|
1196
1197
|
head: this.resumeState.latestGitCheckpoint.head,
|
|
1197
1198
|
packBytes: metrics.packBytes,
|
|
@@ -1314,7 +1315,7 @@ export class AgentServer {
|
|
|
1314
1315
|
taskId: taskRun.task,
|
|
1315
1316
|
runId: taskRun.id,
|
|
1316
1317
|
});
|
|
1317
|
-
this.logger.
|
|
1318
|
+
this.logger.debug("Built pending user prompt", {
|
|
1318
1319
|
hasMessage: typeof message === "string" && message.trim().length > 0,
|
|
1319
1320
|
requestedArtifactCount: artifactIds.length,
|
|
1320
1321
|
blockTypes: prompt.map((block) => block.type),
|
|
@@ -2131,45 +2132,21 @@ ${attributionInstructions}
|
|
|
2131
2132
|
const meta = (update?._meta as Record<string, unknown>)?.claudeCode as
|
|
2132
2133
|
| Record<string, unknown>
|
|
2133
2134
|
| undefined;
|
|
2134
|
-
const toolResponse = meta?.toolResponse;
|
|
2135
|
-
|
|
2136
|
-
// Extract text content from tool response
|
|
2137
|
-
let textToSearch = "";
|
|
2138
|
-
|
|
2139
|
-
if (toolResponse) {
|
|
2140
|
-
if (typeof toolResponse === "string") {
|
|
2141
|
-
textToSearch = toolResponse;
|
|
2142
|
-
} else if (typeof toolResponse === "object" && toolResponse !== null) {
|
|
2143
|
-
const respObj = toolResponse as Record<string, unknown>;
|
|
2144
|
-
textToSearch =
|
|
2145
|
-
String(respObj.stdout || "") + String(respObj.stderr || "");
|
|
2146
|
-
if (!textToSearch && respObj.output) {
|
|
2147
|
-
textToSearch = String(respObj.output);
|
|
2148
|
-
}
|
|
2149
|
-
}
|
|
2150
|
-
}
|
|
2151
|
-
|
|
2152
|
-
// Also check content array
|
|
2153
|
-
const content = update?.content;
|
|
2154
|
-
if (Array.isArray(content)) {
|
|
2155
|
-
for (const item of content) {
|
|
2156
|
-
if (item.type === "text" && item.text) {
|
|
2157
|
-
textToSearch += ` ${item.text}`;
|
|
2158
|
-
}
|
|
2159
|
-
}
|
|
2160
|
-
}
|
|
2161
2135
|
|
|
2162
|
-
|
|
2136
|
+
const content = update?.content as
|
|
2137
|
+
| Array<{ type?: string; text?: string }>
|
|
2138
|
+
| undefined;
|
|
2163
2139
|
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2140
|
+
const prUrl = extractCreatedPrUrl({
|
|
2141
|
+
toolName: meta?.toolName as string | undefined,
|
|
2142
|
+
bashCommand: meta?.bashCommand as string | undefined,
|
|
2143
|
+
toolResponse: meta?.toolResponse,
|
|
2144
|
+
content,
|
|
2145
|
+
});
|
|
2146
|
+
if (!prUrl) return;
|
|
2169
2147
|
|
|
2170
|
-
const prUrl = prUrlMatch[0];
|
|
2171
2148
|
this.detectedPrUrl = prUrl;
|
|
2172
|
-
this.logger.debug("Detected PR URL
|
|
2149
|
+
this.logger.debug("Detected PR URL from gh pr create", {
|
|
2173
2150
|
runId: payload.run_id,
|
|
2174
2151
|
prUrl,
|
|
2175
2152
|
});
|