@groupchatai/claude-runner 0.4.9 → 0.4.11
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/index.js +100 -7
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -79,6 +79,39 @@ var GroupChatAgentClient = class {
|
|
|
79
79
|
return this.request("POST", `/runs/${runId}/comment`, { body });
|
|
80
80
|
}
|
|
81
81
|
};
|
|
82
|
+
function buildResumedPrompt(detail, agentUserId) {
|
|
83
|
+
const comments = detail.activity.filter(
|
|
84
|
+
(a) => a.type === "comment" && a.body && a.body.trim().length > 0
|
|
85
|
+
);
|
|
86
|
+
let lastAgentCommentIdx = -1;
|
|
87
|
+
for (let i = comments.length - 1; i >= 0; i--) {
|
|
88
|
+
if (comments[i].userId === agentUserId) {
|
|
89
|
+
lastAgentCommentIdx = i;
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
const newComments = comments.slice(lastAgentCommentIdx + 1).filter((c) => c.userId !== agentUserId);
|
|
94
|
+
const parts = [];
|
|
95
|
+
if (newComments.length > 0) {
|
|
96
|
+
parts.push("New comments since your last response:");
|
|
97
|
+
for (const c of newComments) {
|
|
98
|
+
const author = c.userName ?? "Someone";
|
|
99
|
+
parts.push(`
|
|
100
|
+
**${author}**:
|
|
101
|
+
${c.body}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
if (detail.lastFollowUpMessage && detail.lastFollowUpMessage !== "Continue working on this task.") {
|
|
105
|
+
parts.push(`
|
|
106
|
+
Follow-up request: ${detail.lastFollowUpMessage}`);
|
|
107
|
+
}
|
|
108
|
+
if (parts.length === 0) {
|
|
109
|
+
parts.push(
|
|
110
|
+
"The user has asked you to continue working on this task. Check the conversation history and address any outstanding requests."
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
return parts.join("\n");
|
|
114
|
+
}
|
|
82
115
|
function buildClaudePrompt(detail, repoResolved) {
|
|
83
116
|
const parts = [];
|
|
84
117
|
parts.push(`# Task: ${detail.task.title}`);
|
|
@@ -127,6 +160,14 @@ ${comment.body}`
|
|
|
127
160
|
);
|
|
128
161
|
}
|
|
129
162
|
}
|
|
163
|
+
if (detail.lastFollowUpMessage) {
|
|
164
|
+
parts.push(
|
|
165
|
+
`
|
|
166
|
+
## Latest Follow-up Request
|
|
167
|
+
The user has sent a follow-up message. Address this:
|
|
168
|
+
${detail.lastFollowUpMessage}`
|
|
169
|
+
);
|
|
170
|
+
}
|
|
130
171
|
const existingPrUrl = detail.pullRequestUrl ?? detail.task.pullRequestUrl;
|
|
131
172
|
if (existingPrUrl) {
|
|
132
173
|
parts.push(`
|
|
@@ -613,6 +654,7 @@ function runShellCommand(cmd, args, cwd) {
|
|
|
613
654
|
});
|
|
614
655
|
}
|
|
615
656
|
var sessionCache = /* @__PURE__ */ new Map();
|
|
657
|
+
var currentAgentUserId = "";
|
|
616
658
|
var activeProcesses = /* @__PURE__ */ new Map();
|
|
617
659
|
var stoppedRunIds = /* @__PURE__ */ new Set();
|
|
618
660
|
function stopActiveProcess(runId) {
|
|
@@ -932,6 +974,23 @@ async function processRun(client, run, config, worktreeDir, detail, runBaseDir,
|
|
|
932
974
|
const logGreen = (msg) => console.log(`${runTag} ${C.green}${msg}${C.reset}`);
|
|
933
975
|
const ownerName = run.owner?.name ?? detail.owner?.name ?? "unknown";
|
|
934
976
|
log(`\u{1F4CB} "${run.taskTitle}" \u2014 delegated by ${ownerName}`);
|
|
977
|
+
if (config.verbose) {
|
|
978
|
+
log(`\u{1F4CE} Run ID: ${run.id} | Task ID: ${run.taskId}`);
|
|
979
|
+
log(
|
|
980
|
+
`\u{1F4CE} Detail status: ${detail.status} | Has lastFollowUpMessage: ${!!detail.lastFollowUpMessage} | Has lastSessionId: ${!!detail.lastSessionId}`
|
|
981
|
+
);
|
|
982
|
+
log(
|
|
983
|
+
`\u{1F4CE} In-memory session cache hit: ${sessionCache.has(run.taskId)} | Activity items: ${detail.activity.length}`
|
|
984
|
+
);
|
|
985
|
+
if (detail.lastFollowUpMessage) {
|
|
986
|
+
log(
|
|
987
|
+
`\u{1F4CE} lastFollowUpMessage: "${detail.lastFollowUpMessage.slice(0, 150)}${detail.lastFollowUpMessage.length > 150 ? "\u2026" : ""}"`
|
|
988
|
+
);
|
|
989
|
+
}
|
|
990
|
+
if (detail.lastSessionId) {
|
|
991
|
+
log(`\u{1F4CE} Server lastSessionId: ${detail.lastSessionId.slice(0, 12)}\u2026`);
|
|
992
|
+
}
|
|
993
|
+
}
|
|
935
994
|
if (detail.status !== "PENDING") {
|
|
936
995
|
log(`\u23ED Run is no longer PENDING (now ${detail.status}), skipping.`);
|
|
937
996
|
return;
|
|
@@ -975,16 +1034,41 @@ async function processRun(client, run, config, worktreeDir, detail, runBaseDir,
|
|
|
975
1034
|
});
|
|
976
1035
|
await new Promise((resolve) => git.on("close", () => resolve()));
|
|
977
1036
|
}
|
|
978
|
-
const cachedSessionId = sessionCache.get(run.taskId);
|
|
1037
|
+
const cachedSessionId = sessionCache.get(run.taskId) ?? detail.lastSessionId;
|
|
979
1038
|
const isFollowUp = cachedSessionId !== void 0;
|
|
980
|
-
|
|
1039
|
+
let effectivePrompt;
|
|
1040
|
+
if (isFollowUp && cachedSessionId) {
|
|
1041
|
+
effectivePrompt = buildResumedPrompt(detail, currentAgentUserId);
|
|
1042
|
+
} else {
|
|
1043
|
+
effectivePrompt = prompt;
|
|
1044
|
+
}
|
|
981
1045
|
const resumeSession = isFollowUp ? cachedSessionId : void 0;
|
|
982
1046
|
if (config.verbose) {
|
|
983
1047
|
if (isFollowUp) {
|
|
984
|
-
|
|
1048
|
+
const sessionSource = sessionCache.has(run.taskId) ? "in-memory cache" : "server (lastSessionId)";
|
|
1049
|
+
log(`\u{1F504} Resuming session ${cachedSessionId.slice(0, 12)}\u2026 (source: ${sessionSource})`);
|
|
1050
|
+
if (detail.lastFollowUpMessage) {
|
|
1051
|
+
log(
|
|
1052
|
+
`\u{1F4AC} Follow-up message: "${detail.lastFollowUpMessage.slice(0, 200)}${detail.lastFollowUpMessage.length > 200 ? "\u2026" : ""}"`
|
|
1053
|
+
);
|
|
1054
|
+
} else {
|
|
1055
|
+
log(`\u26A0 No lastFollowUpMessage found \u2014 using full prompt for resumed session`);
|
|
1056
|
+
}
|
|
1057
|
+
} else {
|
|
1058
|
+
log(`\u{1F195} Initial run (no session to resume)`);
|
|
985
1059
|
}
|
|
986
|
-
log(
|
|
1060
|
+
log(
|
|
1061
|
+
`\u{1F4DD} Prompt (${effectivePrompt.length} chars)${isFollowUp ? " [follow-up]" : " [initial]"}`
|
|
1062
|
+
);
|
|
1063
|
+
const previewLen = 500;
|
|
1064
|
+
log(
|
|
1065
|
+
`\u{1F4DD} Prompt preview:
|
|
1066
|
+
${effectivePrompt.slice(0, previewLen)}${effectivePrompt.length > previewLen ? "\n... (truncated)" : ""}`
|
|
1067
|
+
);
|
|
987
1068
|
if (effectiveModel) log(`\u{1F9E0} Model: ${effectiveModel}`);
|
|
1069
|
+
log(
|
|
1070
|
+
`\u{1F4CA} Activity items: ${detail.activity.length}, Comments: ${detail.activity.filter((a) => a.type === "comment").length}`
|
|
1071
|
+
);
|
|
988
1072
|
}
|
|
989
1073
|
const { process: child, output } = spawnClaudeCode(
|
|
990
1074
|
effectivePrompt,
|
|
@@ -1017,6 +1101,9 @@ async function processRun(client, run, config, worktreeDir, detail, runBaseDir,
|
|
|
1017
1101
|
}
|
|
1018
1102
|
if (sessionId) {
|
|
1019
1103
|
sessionCache.set(run.taskId, sessionId);
|
|
1104
|
+
if (config.verbose) {
|
|
1105
|
+
log(`\u{1F4BE} Session ${sessionId.slice(0, 12)}\u2026 cached for task ${run.taskId}`);
|
|
1106
|
+
}
|
|
1020
1107
|
}
|
|
1021
1108
|
const pullRequestUrl = streamPrUrl ?? await detectPullRequestUrl(effectiveCwd) ?? extractPullRequestUrlFromOutput(stdout) ?? extractPullRequestUrlFromOutput(rawOutput);
|
|
1022
1109
|
const streamEvents = parseClaudeNdjsonEvents(rawOutput);
|
|
@@ -1051,7 +1138,8 @@ async function processRun(client, run, config, worktreeDir, detail, runBaseDir,
|
|
|
1051
1138
|
await client.errorRun(run.id, errorMsg, {
|
|
1052
1139
|
pullRequestUrl,
|
|
1053
1140
|
errorType: retryInfo?.errorType,
|
|
1054
|
-
retryAfter: retryInfo?.retryAfterMs
|
|
1141
|
+
retryAfter: retryInfo?.retryAfterMs,
|
|
1142
|
+
sessionId: lastClaude.sessionId
|
|
1055
1143
|
});
|
|
1056
1144
|
if (retryInfo) {
|
|
1057
1145
|
const retryAt = new Date(retryInfo.retryAfterMs).toLocaleString(void 0, {
|
|
@@ -1082,7 +1170,11 @@ async function processRun(client, run, config, worktreeDir, detail, runBaseDir,
|
|
|
1082
1170
|
}
|
|
1083
1171
|
const resultText = extractResultText(stdout);
|
|
1084
1172
|
const cost = extractCost(stdout);
|
|
1085
|
-
await client.completeRun(run.id, resultText, {
|
|
1173
|
+
await client.completeRun(run.id, resultText, {
|
|
1174
|
+
...cost,
|
|
1175
|
+
pullRequestUrl,
|
|
1176
|
+
sessionId: lastClaude.sessionId
|
|
1177
|
+
});
|
|
1086
1178
|
if (pullRequestUrl) logGreen(`\u{1F517} PR: ${pullRequestUrl}`);
|
|
1087
1179
|
logGreen(`\u2705 Run completed`);
|
|
1088
1180
|
} catch (err) {
|
|
@@ -1114,7 +1206,7 @@ async function processRun(client, run, config, worktreeDir, detail, runBaseDir,
|
|
|
1114
1206
|
${message.slice(0, 2e3)}
|
|
1115
1207
|
\`\`\``;
|
|
1116
1208
|
try {
|
|
1117
|
-
await client.errorRun(run.id, errorBody);
|
|
1209
|
+
await client.errorRun(run.id, errorBody, { sessionId: lastClaude.sessionId });
|
|
1118
1210
|
} catch {
|
|
1119
1211
|
log(`${C.dim}\u26A0 Failed to report error to API${C.reset}`);
|
|
1120
1212
|
}
|
|
@@ -1610,6 +1702,7 @@ async function main() {
|
|
|
1610
1702
|
console.error("Failed to authenticate:", errMsg(err));
|
|
1611
1703
|
process.exit(1);
|
|
1612
1704
|
}
|
|
1705
|
+
currentAgentUserId = me.agentUserId;
|
|
1613
1706
|
console.log(`
|
|
1614
1707
|
\u{1F916} Agent Runner \u2014 ${me.name}`);
|
|
1615
1708
|
console.log(` Owner: ${me.ownerName}`);
|