@rallycry/conveyor-agent 7.3.2 → 7.3.4
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/{chunk-WDGSLU5S.js → chunk-TP5WEBQE.js} +1107 -296
- package/dist/chunk-TP5WEBQE.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/index.d.ts +28 -4
- package/dist/index.js +1 -1
- package/dist/{task-audit-handler-TJOM5OJS.js → task-audit-handler-4675WBIX.js} +3 -3
- package/dist/{task-audit-handler-TJOM5OJS.js.map → task-audit-handler-4675WBIX.js.map} +1 -1
- package/package.json +1 -1
- package/dist/chunk-WDGSLU5S.js.map +0 -1
|
@@ -28,6 +28,7 @@ var AgentConnection = class _AgentConnection {
|
|
|
28
28
|
recentMessages = [];
|
|
29
29
|
static DEDUP_WINDOW_MS = 3e4;
|
|
30
30
|
static DEDUP_SIMILARITY_THRESHOLD = 0.7;
|
|
31
|
+
static DEDUP_PREVIEW_LIMIT = 120;
|
|
31
32
|
// Early-buffering: events that arrive before callbacks are registered
|
|
32
33
|
earlyMessages = [];
|
|
33
34
|
earlyStop = false;
|
|
@@ -276,18 +277,43 @@ var AgentConnection = class _AgentConnection {
|
|
|
276
277
|
}
|
|
277
278
|
postChatMessage(content) {
|
|
278
279
|
if (!this.socket) return;
|
|
279
|
-
if (this.
|
|
280
|
-
process.stderr.write(`[dedup] Suppressed near-duplicate message
|
|
281
|
-
`);
|
|
282
|
-
return;
|
|
283
|
-
}
|
|
280
|
+
if (this.suppressIfDuplicate(content)) return;
|
|
284
281
|
void this.call("postAgentMessage", {
|
|
285
282
|
sessionId: this.config.sessionId,
|
|
286
283
|
content
|
|
287
284
|
}).catch(() => {
|
|
288
285
|
});
|
|
289
286
|
}
|
|
290
|
-
|
|
287
|
+
// Awaitable variant of postChatMessage for callers that need to guarantee
|
|
288
|
+
// the message is acknowledged by the server before proceeding (e.g. before
|
|
289
|
+
// aborting the session). Dedup still applies; a suppressed message resolves
|
|
290
|
+
// immediately without hitting the wire.
|
|
291
|
+
async postChatMessageAwait(content) {
|
|
292
|
+
if (!this.socket) return;
|
|
293
|
+
if (this.suppressIfDuplicate(content)) return;
|
|
294
|
+
try {
|
|
295
|
+
await this.call("postAgentMessage", {
|
|
296
|
+
sessionId: this.config.sessionId,
|
|
297
|
+
content
|
|
298
|
+
});
|
|
299
|
+
} catch (err) {
|
|
300
|
+
process.stderr.write(
|
|
301
|
+
`[conveyor-agent] postChatMessageAwait failed: ${err instanceof Error ? err.message : String(err)}
|
|
302
|
+
`
|
|
303
|
+
);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
suppressIfDuplicate(content) {
|
|
307
|
+
const d = this.checkAndTrackDuplicate(content);
|
|
308
|
+
if (!d.duplicate) return false;
|
|
309
|
+
process.stderr.write(
|
|
310
|
+
`[dedup] Suppressed near-duplicate (matched: "${d.matchedMessagePreview}")
|
|
311
|
+
`
|
|
312
|
+
);
|
|
313
|
+
return true;
|
|
314
|
+
}
|
|
315
|
+
// Exposed so `post_to_chat` can surface suppression back to the agent.
|
|
316
|
+
checkAndTrackDuplicate(content) {
|
|
291
317
|
const now = Date.now();
|
|
292
318
|
this.recentMessages = this.recentMessages.filter(
|
|
293
319
|
(m) => now - m.timestamp < _AgentConnection.DEDUP_WINDOW_MS
|
|
@@ -295,22 +321,20 @@ var AgentConnection = class _AgentConnection {
|
|
|
295
321
|
const words = new Set(
|
|
296
322
|
content.toLowerCase().replace(/[^\w\s]/g, "").split(/\s+/).filter((w) => w.length >= 3)
|
|
297
323
|
);
|
|
298
|
-
if (words.size === 0) return false;
|
|
324
|
+
if (words.size === 0) return { duplicate: false };
|
|
299
325
|
for (const recent of this.recentMessages) {
|
|
300
326
|
let intersection = 0;
|
|
301
|
-
for (const w of words)
|
|
302
|
-
if (recent.words.has(w)) intersection++;
|
|
303
|
-
}
|
|
327
|
+
for (const w of words) if (recent.words.has(w)) intersection++;
|
|
304
328
|
const union = (/* @__PURE__ */ new Set([...words, ...recent.words])).size;
|
|
305
329
|
if (union > 0 && intersection / union > _AgentConnection.DEDUP_SIMILARITY_THRESHOLD) {
|
|
306
|
-
return true;
|
|
330
|
+
return { duplicate: true, matchedMessagePreview: recent.preview };
|
|
307
331
|
}
|
|
308
332
|
}
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
return false;
|
|
333
|
+
const max = _AgentConnection.DEDUP_PREVIEW_LIMIT;
|
|
334
|
+
const preview = content.length > max ? content.slice(0, max) + "\u2026" : content;
|
|
335
|
+
this.recentMessages.push({ words, timestamp: now, preview });
|
|
336
|
+
if (this.recentMessages.length > 3) this.recentMessages.shift();
|
|
337
|
+
return { duplicate: false };
|
|
314
338
|
}
|
|
315
339
|
sendHeartbeat() {
|
|
316
340
|
if (!this.socket) return;
|
|
@@ -332,21 +356,20 @@ var AgentConnection = class _AgentConnection {
|
|
|
332
356
|
emitModeChanged(agentMode) {
|
|
333
357
|
this.sendEvent({ type: "mode_changed", agentMode });
|
|
334
358
|
}
|
|
335
|
-
updateTaskFields(fields) {
|
|
336
|
-
if (!this.socket) return;
|
|
337
|
-
|
|
338
|
-
sessionId: this.config.sessionId,
|
|
339
|
-
|
|
340
|
-
}
|
|
341
|
-
|
|
359
|
+
async updateTaskFields(fields) {
|
|
360
|
+
if (!this.socket) return { ok: false, error: "socket not connected" };
|
|
361
|
+
try {
|
|
362
|
+
await this.call("updateTaskFields", { sessionId: this.config.sessionId, ...fields });
|
|
363
|
+
return { ok: true };
|
|
364
|
+
} catch (err) {
|
|
365
|
+
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
366
|
+
}
|
|
342
367
|
}
|
|
343
368
|
storeSessionId(sdkSessionId) {
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
}).catch(() => {
|
|
349
|
-
});
|
|
369
|
+
void this.call("storeSessionId", { sessionId: this.config.sessionId, sdkSessionId }).catch(
|
|
370
|
+
() => {
|
|
371
|
+
}
|
|
372
|
+
);
|
|
350
373
|
}
|
|
351
374
|
// ── Typing indicators ───────────────────────────────────────────────
|
|
352
375
|
sendTypingStart() {
|
|
@@ -411,6 +434,9 @@ ${q.question}${q.options.length ? "\n" + q.options.map((o) => `- ${o.label}: ${o
|
|
|
411
434
|
triggerIdentification() {
|
|
412
435
|
return this.call("triggerIdentification", { sessionId: this.config.sessionId });
|
|
413
436
|
}
|
|
437
|
+
getCumulativeSpending() {
|
|
438
|
+
return this.call("getCumulativeSpending", { sessionId: this.config.sessionId });
|
|
439
|
+
}
|
|
414
440
|
async refreshAuthToken() {
|
|
415
441
|
const codespaceName = process.env.CODESPACE_NAME || process.env.CLAUDESPACE_NAME;
|
|
416
442
|
const apiUrl = this.config.apiUrl;
|
|
@@ -924,8 +950,8 @@ var PlanSync = class {
|
|
|
924
950
|
for (const file of readdirSync(plansDir).filter((f) => f.endsWith(".md"))) {
|
|
925
951
|
try {
|
|
926
952
|
const fullPath = join(plansDir, file);
|
|
927
|
-
const
|
|
928
|
-
this.planFileSnapshot.set(fullPath,
|
|
953
|
+
const stat2 = statSync(fullPath);
|
|
954
|
+
this.planFileSnapshot.set(fullPath, stat2.mtimeMs);
|
|
929
955
|
} catch {
|
|
930
956
|
continue;
|
|
931
957
|
}
|
|
@@ -946,11 +972,11 @@ var PlanSync = class {
|
|
|
946
972
|
for (const file of files) {
|
|
947
973
|
const fullPath = join(plansDir, file);
|
|
948
974
|
try {
|
|
949
|
-
const
|
|
975
|
+
const stat2 = statSync(fullPath);
|
|
950
976
|
const prevMtime = this.planFileSnapshot.get(fullPath);
|
|
951
|
-
const isNew = prevMtime === void 0 ||
|
|
952
|
-
if (isNew && (!newest ||
|
|
953
|
-
newest = { path: fullPath, mtime:
|
|
977
|
+
const isNew = prevMtime === void 0 || stat2.mtimeMs > prevMtime;
|
|
978
|
+
if (isNew && (!newest || stat2.mtimeMs > newest.mtime)) {
|
|
979
|
+
newest = { path: fullPath, mtime: stat2.mtimeMs };
|
|
954
980
|
}
|
|
955
981
|
} catch {
|
|
956
982
|
continue;
|
|
@@ -959,31 +985,35 @@ var PlanSync = class {
|
|
|
959
985
|
}
|
|
960
986
|
return newest;
|
|
961
987
|
}
|
|
962
|
-
syncPlanFile() {
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
988
|
+
async syncPlanFile() {
|
|
989
|
+
const isInitialDetection = this.lockedPlanFile === null;
|
|
990
|
+
const target = this.lockedPlanFile ?? this.findNewestPlanFile()?.path ?? null;
|
|
991
|
+
if (!target) return;
|
|
992
|
+
if (isInitialDetection) {
|
|
993
|
+
this.lockedPlanFile = target;
|
|
994
|
+
}
|
|
995
|
+
const fileName = target.split("/").pop() ?? "plan";
|
|
996
|
+
let content;
|
|
997
|
+
try {
|
|
998
|
+
content = readFileSync(target, "utf-8").trim();
|
|
999
|
+
} catch (err) {
|
|
1000
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
1001
|
+
this.connection.postChatMessage(
|
|
1002
|
+
`Plan sync warning: could not read local plan file (${fileName}): ${reason}. The task plan was not updated.`
|
|
1003
|
+
);
|
|
973
1004
|
return;
|
|
974
1005
|
}
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
this.connection.postChatMessage(
|
|
983
|
-
`Detected local plan file (${fileName}) and synced it to the task plan.`
|
|
984
|
-
);
|
|
985
|
-
}
|
|
1006
|
+
if (!content) return;
|
|
1007
|
+
const result = await this.connection.updateTaskFields({ plan: content });
|
|
1008
|
+
if (!result.ok) {
|
|
1009
|
+
this.connection.postChatMessage(
|
|
1010
|
+
`Plan sync failed: the local plan file (${fileName}) was not persisted to the task (${result.error ?? "unknown error"}). Retry update_task_plan or re-run ExitPlanMode.`
|
|
1011
|
+
);
|
|
1012
|
+
return;
|
|
986
1013
|
}
|
|
1014
|
+
const verb = isInitialDetection ? "Detected local plan file" : "Synced local plan file";
|
|
1015
|
+
const suffix = isInitialDetection ? " and synced it to the task plan." : " to the task plan.";
|
|
1016
|
+
this.connection.postChatMessage(`${verb} (${fileName})${suffix}`);
|
|
987
1017
|
}
|
|
988
1018
|
};
|
|
989
1019
|
|
|
@@ -993,6 +1023,558 @@ import { existsSync } from "fs";
|
|
|
993
1023
|
import { homedir } from "os";
|
|
994
1024
|
import { join as join2 } from "path";
|
|
995
1025
|
|
|
1026
|
+
// ../shared/dist/index.js
|
|
1027
|
+
import { z } from "zod";
|
|
1028
|
+
import { z as z2 } from "zod";
|
|
1029
|
+
import { z as z3 } from "zod";
|
|
1030
|
+
var MAX_FILE_SIZE_BYTES = 25 * 1024 * 1024;
|
|
1031
|
+
var EMBED_THRESHOLD_IMAGES = 5 * 1024 * 1024;
|
|
1032
|
+
var EMBED_THRESHOLD_TEXT = 2 * 1024 * 1024;
|
|
1033
|
+
var AgentHeartbeatSchema = z.object({
|
|
1034
|
+
sessionId: z.string().optional(),
|
|
1035
|
+
timestamp: z.string(),
|
|
1036
|
+
status: z.enum(["active", "idle", "building"]),
|
|
1037
|
+
currentAction: z.string().optional()
|
|
1038
|
+
});
|
|
1039
|
+
var CreatePRInputSchema = z.object({
|
|
1040
|
+
title: z.string().min(1),
|
|
1041
|
+
body: z.string(),
|
|
1042
|
+
head: z.string().optional(),
|
|
1043
|
+
base: z.string().optional()
|
|
1044
|
+
});
|
|
1045
|
+
var PostToChatInputSchema = z.object({
|
|
1046
|
+
message: z.string().min(1),
|
|
1047
|
+
type: z.enum(["message", "question", "update"]).optional().default("message")
|
|
1048
|
+
});
|
|
1049
|
+
var GetTaskContextRequestSchema = z.object({
|
|
1050
|
+
sessionId: z.string(),
|
|
1051
|
+
includeHistory: z.boolean().optional().default(false)
|
|
1052
|
+
});
|
|
1053
|
+
var GetChatMessagesRequestSchema = z.object({
|
|
1054
|
+
sessionId: z.string(),
|
|
1055
|
+
limit: z.number().int().positive().optional().default(50),
|
|
1056
|
+
offset: z.number().int().nonnegative().optional().default(0)
|
|
1057
|
+
});
|
|
1058
|
+
var GetTaskFilesRequestSchema = z.object({
|
|
1059
|
+
sessionId: z.string()
|
|
1060
|
+
});
|
|
1061
|
+
var GetTaskFileRequestSchema = z.object({
|
|
1062
|
+
sessionId: z.string(),
|
|
1063
|
+
fileId: z.string()
|
|
1064
|
+
});
|
|
1065
|
+
var GetTaskRequestSchema = z.object({
|
|
1066
|
+
sessionId: z.string(),
|
|
1067
|
+
taskSlugOrId: z.string()
|
|
1068
|
+
});
|
|
1069
|
+
var GetCliHistoryRequestSchema = z.object({
|
|
1070
|
+
sessionId: z.string(),
|
|
1071
|
+
limit: z.number().int().positive().optional().default(100),
|
|
1072
|
+
source: z.enum(["agent", "application"]).optional()
|
|
1073
|
+
});
|
|
1074
|
+
var ListSubtasksRequestSchema = z.object({
|
|
1075
|
+
sessionId: z.string()
|
|
1076
|
+
});
|
|
1077
|
+
var GetDependenciesRequestSchema = z.object({
|
|
1078
|
+
sessionId: z.string()
|
|
1079
|
+
});
|
|
1080
|
+
var GetSuggestionsRequestSchema = z.object({
|
|
1081
|
+
sessionId: z.string(),
|
|
1082
|
+
status: z.string().optional(),
|
|
1083
|
+
limit: z.number().int().min(1).max(100).optional()
|
|
1084
|
+
});
|
|
1085
|
+
var CreatePullRequestRequestSchema = CreatePRInputSchema.extend({ sessionId: z.string() });
|
|
1086
|
+
var UpdateTaskStatusRequestSchema = z.object({
|
|
1087
|
+
sessionId: z.string(),
|
|
1088
|
+
status: z.string(),
|
|
1089
|
+
force: z.boolean().optional().default(false)
|
|
1090
|
+
});
|
|
1091
|
+
var StoreSessionIdRequestSchema = z.object({
|
|
1092
|
+
sessionId: z.string(),
|
|
1093
|
+
sdkSessionId: z.string()
|
|
1094
|
+
});
|
|
1095
|
+
var TrackSpendingRequestSchema = z.object({
|
|
1096
|
+
sessionId: z.string(),
|
|
1097
|
+
inputTokens: z.number().int().nonnegative(),
|
|
1098
|
+
outputTokens: z.number().int().nonnegative(),
|
|
1099
|
+
costUsd: z.number().nonnegative(),
|
|
1100
|
+
model: z.string()
|
|
1101
|
+
});
|
|
1102
|
+
var SessionStartRequestSchema = z.object({
|
|
1103
|
+
sessionId: z.string(),
|
|
1104
|
+
agentVersion: z.string(),
|
|
1105
|
+
capabilities: z.array(z.string())
|
|
1106
|
+
});
|
|
1107
|
+
var SessionStopRequestSchema = z.object({
|
|
1108
|
+
sessionId: z.string(),
|
|
1109
|
+
reason: z.string().optional()
|
|
1110
|
+
});
|
|
1111
|
+
var ConnectAgentRequestSchema = z.object({
|
|
1112
|
+
sessionId: z.string()
|
|
1113
|
+
});
|
|
1114
|
+
var ReportAgentStatusRequestSchema = z.object({
|
|
1115
|
+
sessionId: z.string(),
|
|
1116
|
+
status: z.string()
|
|
1117
|
+
});
|
|
1118
|
+
var NotifyAgentVersionRequestSchema = z.object({
|
|
1119
|
+
sessionId: z.string(),
|
|
1120
|
+
agentVersion: z.string()
|
|
1121
|
+
});
|
|
1122
|
+
var CreateSubtaskRequestSchema = z.object({
|
|
1123
|
+
sessionId: z.string(),
|
|
1124
|
+
title: z.string().min(1),
|
|
1125
|
+
description: z.string().optional(),
|
|
1126
|
+
plan: z.string().optional(),
|
|
1127
|
+
storyPointValue: z.number().int().positive().optional(),
|
|
1128
|
+
ordinal: z.number().int().nonnegative().optional()
|
|
1129
|
+
});
|
|
1130
|
+
var UpdateSubtaskRequestSchema = z.object({
|
|
1131
|
+
sessionId: z.string(),
|
|
1132
|
+
subtaskId: z.string(),
|
|
1133
|
+
title: z.string().min(1).optional(),
|
|
1134
|
+
description: z.string().optional(),
|
|
1135
|
+
plan: z.string().optional(),
|
|
1136
|
+
status: z.string().optional(),
|
|
1137
|
+
storyPointValue: z.number().int().positive().optional()
|
|
1138
|
+
});
|
|
1139
|
+
var DeleteSubtaskRequestSchema = z.object({
|
|
1140
|
+
sessionId: z.string(),
|
|
1141
|
+
subtaskId: z.string()
|
|
1142
|
+
});
|
|
1143
|
+
var GetTaskPropertiesRequestSchema = z.object({
|
|
1144
|
+
sessionId: z.string()
|
|
1145
|
+
});
|
|
1146
|
+
var GetCumulativeSpendingRequestSchema = z.object({
|
|
1147
|
+
sessionId: z.string()
|
|
1148
|
+
});
|
|
1149
|
+
var ModelUsageEntrySchema = z.object({
|
|
1150
|
+
model: z.string(),
|
|
1151
|
+
inputTokens: z.number().nonnegative(),
|
|
1152
|
+
outputTokens: z.number().nonnegative(),
|
|
1153
|
+
cacheReadInputTokens: z.number().nonnegative(),
|
|
1154
|
+
cacheCreationInputTokens: z.number().nonnegative(),
|
|
1155
|
+
costUSD: z.number().nonnegative()
|
|
1156
|
+
});
|
|
1157
|
+
var GetCumulativeSpendingResponseSchema = z.object({
|
|
1158
|
+
totalCostUsd: z.number().nonnegative(),
|
|
1159
|
+
modelUsage: z.array(ModelUsageEntrySchema)
|
|
1160
|
+
});
|
|
1161
|
+
var UpdateTaskFieldsRequestSchema = z.object({
|
|
1162
|
+
sessionId: z.string(),
|
|
1163
|
+
plan: z.string().optional(),
|
|
1164
|
+
description: z.string().optional()
|
|
1165
|
+
});
|
|
1166
|
+
var UpdateTaskPropertiesRequestSchema = z.object({
|
|
1167
|
+
sessionId: z.string(),
|
|
1168
|
+
title: z.string().optional(),
|
|
1169
|
+
storyPointValue: z.number().int().positive().optional(),
|
|
1170
|
+
tagIds: z.array(z.string()).optional(),
|
|
1171
|
+
tagNames: z.array(z.string()).optional(),
|
|
1172
|
+
githubPRUrl: z.string().url().optional(),
|
|
1173
|
+
githubBranch: z.string().optional()
|
|
1174
|
+
});
|
|
1175
|
+
var ListIconsRequestSchema = z.object({
|
|
1176
|
+
sessionId: z.string()
|
|
1177
|
+
});
|
|
1178
|
+
var GenerateTaskIconRequestSchema = z.object({
|
|
1179
|
+
sessionId: z.string(),
|
|
1180
|
+
prompt: z.string().min(1),
|
|
1181
|
+
aspectRatio: z.string().optional()
|
|
1182
|
+
});
|
|
1183
|
+
var SearchFaIconsRequestSchema = z.object({
|
|
1184
|
+
sessionId: z.string(),
|
|
1185
|
+
query: z.string().min(1),
|
|
1186
|
+
first: z.number().int().positive().optional()
|
|
1187
|
+
});
|
|
1188
|
+
var PickFaIconRequestSchema = z.object({
|
|
1189
|
+
sessionId: z.string(),
|
|
1190
|
+
fontAwesomeId: z.string().min(1),
|
|
1191
|
+
fontAwesomeStyle: z.string().optional()
|
|
1192
|
+
});
|
|
1193
|
+
var CreateFollowUpTaskRequestSchema = z.object({
|
|
1194
|
+
sessionId: z.string(),
|
|
1195
|
+
title: z.string().min(1),
|
|
1196
|
+
description: z.string().optional(),
|
|
1197
|
+
plan: z.string().optional(),
|
|
1198
|
+
storyPointValue: z.number().int().positive().optional()
|
|
1199
|
+
});
|
|
1200
|
+
var AddDependencyRequestSchema = z.object({
|
|
1201
|
+
sessionId: z.string(),
|
|
1202
|
+
dependsOnSlugOrId: z.string()
|
|
1203
|
+
});
|
|
1204
|
+
var RemoveDependencyRequestSchema = z.object({
|
|
1205
|
+
sessionId: z.string(),
|
|
1206
|
+
dependsOnSlugOrId: z.string()
|
|
1207
|
+
});
|
|
1208
|
+
var CreateSuggestionRequestSchema = z.object({
|
|
1209
|
+
sessionId: z.string(),
|
|
1210
|
+
title: z.string().min(1),
|
|
1211
|
+
description: z.string().optional(),
|
|
1212
|
+
tagNames: z.array(z.string()).optional()
|
|
1213
|
+
});
|
|
1214
|
+
var VoteSuggestionRequestSchema = z.object({
|
|
1215
|
+
sessionId: z.string(),
|
|
1216
|
+
suggestionId: z.string(),
|
|
1217
|
+
value: z.union([z.literal(1), z.literal(-1)])
|
|
1218
|
+
});
|
|
1219
|
+
var TriggerIdentificationRequestSchema = z.object({
|
|
1220
|
+
sessionId: z.string()
|
|
1221
|
+
});
|
|
1222
|
+
var SubmitCodeReviewResultRequestSchema = z.object({
|
|
1223
|
+
sessionId: z.string(),
|
|
1224
|
+
approved: z.boolean(),
|
|
1225
|
+
content: z.string()
|
|
1226
|
+
});
|
|
1227
|
+
var StartChildCloudBuildRequestSchema = z.object({
|
|
1228
|
+
sessionId: z.string(),
|
|
1229
|
+
childTaskId: z.string()
|
|
1230
|
+
});
|
|
1231
|
+
var StopChildBuildRequestSchema = z.object({
|
|
1232
|
+
sessionId: z.string(),
|
|
1233
|
+
childTaskId: z.string()
|
|
1234
|
+
});
|
|
1235
|
+
var ApproveAndMergePRRequestSchema = z.object({
|
|
1236
|
+
sessionId: z.string(),
|
|
1237
|
+
childTaskId: z.string()
|
|
1238
|
+
});
|
|
1239
|
+
var PostChildChatMessageRequestSchema = z.object({
|
|
1240
|
+
sessionId: z.string(),
|
|
1241
|
+
childTaskId: z.string(),
|
|
1242
|
+
message: z.string().min(1)
|
|
1243
|
+
});
|
|
1244
|
+
var UpdateChildStatusRequestSchema = z.object({
|
|
1245
|
+
sessionId: z.string(),
|
|
1246
|
+
childTaskId: z.string(),
|
|
1247
|
+
status: z.string()
|
|
1248
|
+
});
|
|
1249
|
+
var GetAgentStatusRequestSchema = z.object({
|
|
1250
|
+
taskId: z.string()
|
|
1251
|
+
});
|
|
1252
|
+
var GetUiCliHistoryRequestSchema = z.object({
|
|
1253
|
+
taskId: z.string()
|
|
1254
|
+
});
|
|
1255
|
+
var SendSoftStopRequestSchema = z.object({
|
|
1256
|
+
taskId: z.string().optional(),
|
|
1257
|
+
projectId: z.string().optional()
|
|
1258
|
+
});
|
|
1259
|
+
var FlushTaskQueueRequestSchema = z.object({
|
|
1260
|
+
taskId: z.string(),
|
|
1261
|
+
softStop: z.boolean().optional()
|
|
1262
|
+
});
|
|
1263
|
+
var FlushProjectQueueRequestSchema = z.object({
|
|
1264
|
+
projectId: z.string()
|
|
1265
|
+
});
|
|
1266
|
+
var CancelTaskQueuedMessageRequestSchema = z.object({
|
|
1267
|
+
taskId: z.string(),
|
|
1268
|
+
messageId: z.string()
|
|
1269
|
+
});
|
|
1270
|
+
var FlushSingleQueuedMessageRequestSchema = z.object({
|
|
1271
|
+
taskId: z.string(),
|
|
1272
|
+
messageId: z.string(),
|
|
1273
|
+
softStop: z.boolean().optional()
|
|
1274
|
+
});
|
|
1275
|
+
var FlushSingleProjectQueuedMessageRequestSchema = z.object({
|
|
1276
|
+
projectId: z.string(),
|
|
1277
|
+
index: z.number().int().nonnegative()
|
|
1278
|
+
});
|
|
1279
|
+
var AnswerAgentQuestionRequestSchema = z.object({
|
|
1280
|
+
taskId: z.string(),
|
|
1281
|
+
requestId: z.string(),
|
|
1282
|
+
answers: z.record(z.string(), z.string())
|
|
1283
|
+
});
|
|
1284
|
+
var ClearAgentTodosRequestSchema = z.object({
|
|
1285
|
+
taskId: z.string()
|
|
1286
|
+
});
|
|
1287
|
+
var AgentQuestionOptionSchema = z.object({
|
|
1288
|
+
label: z.string(),
|
|
1289
|
+
description: z.string(),
|
|
1290
|
+
preview: z.string().optional()
|
|
1291
|
+
});
|
|
1292
|
+
var AgentQuestionSchema = z.object({
|
|
1293
|
+
question: z.string(),
|
|
1294
|
+
header: z.string(),
|
|
1295
|
+
options: z.array(AgentQuestionOptionSchema),
|
|
1296
|
+
multiSelect: z.boolean().optional()
|
|
1297
|
+
});
|
|
1298
|
+
var AskUserQuestionRequestSchema = z.object({
|
|
1299
|
+
sessionId: z.string(),
|
|
1300
|
+
question: z.string().min(1),
|
|
1301
|
+
requestId: z.string().min(1),
|
|
1302
|
+
questions: z.array(AgentQuestionSchema).min(1)
|
|
1303
|
+
});
|
|
1304
|
+
var AgentEventSchema = z.object({
|
|
1305
|
+
type: z.string().min(1)
|
|
1306
|
+
}).catchall(z.unknown());
|
|
1307
|
+
var EmitAgentEventRequestSchema = z.object({
|
|
1308
|
+
sessionId: z.string(),
|
|
1309
|
+
events: z.array(AgentEventSchema).max(500)
|
|
1310
|
+
});
|
|
1311
|
+
var RefreshGithubTokenRequestSchema = z.object({
|
|
1312
|
+
sessionId: z.string()
|
|
1313
|
+
});
|
|
1314
|
+
var RefreshGithubTokenResponseSchema = z.object({
|
|
1315
|
+
token: z.string()
|
|
1316
|
+
});
|
|
1317
|
+
var CreatePRResponseSchema = z.object({
|
|
1318
|
+
prNumber: z.number().int().positive(),
|
|
1319
|
+
prUrl: z.string().url()
|
|
1320
|
+
});
|
|
1321
|
+
var PostToChatResponseSchema = z.object({
|
|
1322
|
+
messageId: z.string()
|
|
1323
|
+
});
|
|
1324
|
+
var UpdateTaskStatusResponseSchema = z.object({
|
|
1325
|
+
taskId: z.string(),
|
|
1326
|
+
status: z.string()
|
|
1327
|
+
});
|
|
1328
|
+
var StoreSessionIdResponseSchema = z.object({
|
|
1329
|
+
success: z.boolean()
|
|
1330
|
+
});
|
|
1331
|
+
var HeartbeatResponseSchema = z.object({
|
|
1332
|
+
acknowledged: z.boolean()
|
|
1333
|
+
});
|
|
1334
|
+
var SessionStartResponseSchema = z.object({
|
|
1335
|
+
sessionId: z.string(),
|
|
1336
|
+
startedAt: z.string()
|
|
1337
|
+
});
|
|
1338
|
+
var SessionStopResponseSchema = z.object({
|
|
1339
|
+
sessionId: z.string(),
|
|
1340
|
+
stoppedAt: z.string()
|
|
1341
|
+
});
|
|
1342
|
+
var DeleteSubtaskResponseSchema = z.object({
|
|
1343
|
+
deleted: z.boolean()
|
|
1344
|
+
});
|
|
1345
|
+
var RegisterProjectAgentResponseSchema = z.object({
|
|
1346
|
+
registered: z.boolean(),
|
|
1347
|
+
agentName: z.string(),
|
|
1348
|
+
agentInstructions: z.string(),
|
|
1349
|
+
model: z.string(),
|
|
1350
|
+
agentSettings: z.record(z.string(), z.unknown()).nullable(),
|
|
1351
|
+
branchSwitchCommand: z.string().nullable()
|
|
1352
|
+
});
|
|
1353
|
+
var RegisterProjectAgentRequestSchema = z2.object({
|
|
1354
|
+
projectId: z2.string(),
|
|
1355
|
+
capabilities: z2.array(z2.string())
|
|
1356
|
+
});
|
|
1357
|
+
var ProjectRunnerHeartbeatRequestSchema = z2.object({
|
|
1358
|
+
projectId: z2.string()
|
|
1359
|
+
});
|
|
1360
|
+
var ReportProjectAgentStatusRequestSchema = z2.object({
|
|
1361
|
+
projectId: z2.string(),
|
|
1362
|
+
status: z2.enum(["busy", "idle"]),
|
|
1363
|
+
activeChatId: z2.string().nullish(),
|
|
1364
|
+
activeTaskId: z2.string().nullish(),
|
|
1365
|
+
activeBranch: z2.string().nullish()
|
|
1366
|
+
});
|
|
1367
|
+
var DisconnectProjectRunnerRequestSchema = z2.object({
|
|
1368
|
+
projectId: z2.string()
|
|
1369
|
+
});
|
|
1370
|
+
var GetProjectAgentContextRequestSchema = z2.object({
|
|
1371
|
+
projectId: z2.string()
|
|
1372
|
+
});
|
|
1373
|
+
var GetProjectAgentContextByRoleRequestSchema = z2.object({
|
|
1374
|
+
projectId: z2.string(),
|
|
1375
|
+
role: z2.string()
|
|
1376
|
+
});
|
|
1377
|
+
var GetProjectFunctionConfigRequestSchema = z2.object({
|
|
1378
|
+
projectId: z2.string(),
|
|
1379
|
+
functionId: z2.string()
|
|
1380
|
+
});
|
|
1381
|
+
var GetProjectChatHistoryRequestSchema = z2.object({
|
|
1382
|
+
projectId: z2.string(),
|
|
1383
|
+
limit: z2.number().int().positive().optional().default(50),
|
|
1384
|
+
chatId: z2.string().optional()
|
|
1385
|
+
});
|
|
1386
|
+
var PostProjectAgentMessageRequestSchema = z2.object({
|
|
1387
|
+
projectId: z2.string(),
|
|
1388
|
+
content: z2.string().min(1),
|
|
1389
|
+
chatId: z2.string().optional()
|
|
1390
|
+
});
|
|
1391
|
+
var ListProjectTasksRequestSchema = z2.object({
|
|
1392
|
+
projectId: z2.string(),
|
|
1393
|
+
status: z2.string().optional(),
|
|
1394
|
+
assigneeId: z2.string().optional(),
|
|
1395
|
+
limit: z2.number().int().positive().optional().default(50)
|
|
1396
|
+
});
|
|
1397
|
+
var GetProjectTaskRequestSchema = z2.object({
|
|
1398
|
+
projectId: z2.string(),
|
|
1399
|
+
taskId: z2.string()
|
|
1400
|
+
});
|
|
1401
|
+
var SearchProjectTasksRequestSchema = z2.object({
|
|
1402
|
+
projectId: z2.string(),
|
|
1403
|
+
tagNames: z2.array(z2.string()).optional(),
|
|
1404
|
+
searchQuery: z2.string().optional(),
|
|
1405
|
+
statusFilters: z2.array(z2.string()).optional(),
|
|
1406
|
+
limit: z2.number().int().positive().optional().default(20)
|
|
1407
|
+
});
|
|
1408
|
+
var ListProjectTagsRequestSchema = z2.object({
|
|
1409
|
+
projectId: z2.string()
|
|
1410
|
+
});
|
|
1411
|
+
var GetProjectSummaryRequestSchema = z2.object({
|
|
1412
|
+
projectId: z2.string()
|
|
1413
|
+
});
|
|
1414
|
+
var CreateProjectTaskRequestSchema = z2.object({
|
|
1415
|
+
projectId: z2.string(),
|
|
1416
|
+
title: z2.string().min(1),
|
|
1417
|
+
description: z2.string().optional(),
|
|
1418
|
+
plan: z2.string().optional(),
|
|
1419
|
+
status: z2.string().optional()
|
|
1420
|
+
});
|
|
1421
|
+
var UpdateProjectTaskRequestSchema = z2.object({
|
|
1422
|
+
projectId: z2.string(),
|
|
1423
|
+
taskId: z2.string(),
|
|
1424
|
+
title: z2.string().optional(),
|
|
1425
|
+
description: z2.string().optional(),
|
|
1426
|
+
plan: z2.string().optional(),
|
|
1427
|
+
status: z2.string().optional(),
|
|
1428
|
+
assignedUserId: z2.string().nullish()
|
|
1429
|
+
});
|
|
1430
|
+
var ReportProjectAgentEventRequestSchema = z2.object({
|
|
1431
|
+
projectId: z2.string(),
|
|
1432
|
+
event: z2.record(z2.string(), z2.unknown())
|
|
1433
|
+
});
|
|
1434
|
+
var ReportTagAuditProgressRequestSchema = z2.object({
|
|
1435
|
+
projectId: z2.string(),
|
|
1436
|
+
requestId: z2.string(),
|
|
1437
|
+
activity: z2.object({
|
|
1438
|
+
tool: z2.string(),
|
|
1439
|
+
input: z2.string().optional(),
|
|
1440
|
+
timestamp: z2.string()
|
|
1441
|
+
})
|
|
1442
|
+
});
|
|
1443
|
+
var ReportTagAuditResultRequestSchema = z2.object({
|
|
1444
|
+
projectId: z2.string(),
|
|
1445
|
+
requestId: z2.string(),
|
|
1446
|
+
recommendations: z2.array(z2.record(z2.string(), z2.unknown())),
|
|
1447
|
+
summary: z2.string(),
|
|
1448
|
+
complete: z2.boolean()
|
|
1449
|
+
});
|
|
1450
|
+
var ReportNewCommitsDetectedRequestSchema = z2.object({
|
|
1451
|
+
projectId: z2.string(),
|
|
1452
|
+
commits: z2.array(
|
|
1453
|
+
z2.object({
|
|
1454
|
+
sha: z2.string(),
|
|
1455
|
+
message: z2.string(),
|
|
1456
|
+
author: z2.string()
|
|
1457
|
+
})
|
|
1458
|
+
),
|
|
1459
|
+
branch: z2.string()
|
|
1460
|
+
});
|
|
1461
|
+
var ReportEnvironmentReadyRequestSchema = z2.object({
|
|
1462
|
+
projectId: z2.string(),
|
|
1463
|
+
branch: z2.string(),
|
|
1464
|
+
setupComplete: z2.boolean(),
|
|
1465
|
+
startCommandRunning: z2.boolean()
|
|
1466
|
+
});
|
|
1467
|
+
var ReportEnvSwitchProgressRequestSchema = z2.object({
|
|
1468
|
+
projectId: z2.string(),
|
|
1469
|
+
step: z2.string(),
|
|
1470
|
+
progress: z2.number(),
|
|
1471
|
+
message: z2.string().optional()
|
|
1472
|
+
});
|
|
1473
|
+
var ForwardProjectChatMessageRequestSchema = z2.object({
|
|
1474
|
+
projectId: z2.string(),
|
|
1475
|
+
chatId: z2.string(),
|
|
1476
|
+
content: z2.string().min(1),
|
|
1477
|
+
targetUserId: z2.string().optional()
|
|
1478
|
+
});
|
|
1479
|
+
var CancelQueuedProjectMessageRequestSchema = z2.object({
|
|
1480
|
+
projectId: z2.string(),
|
|
1481
|
+
index: z2.number().int().nonnegative()
|
|
1482
|
+
});
|
|
1483
|
+
var GetProjectCliHistoryRequestSchema = z2.object({
|
|
1484
|
+
projectId: z2.string(),
|
|
1485
|
+
limit: z2.number().int().positive().optional().default(50),
|
|
1486
|
+
source: z2.string().optional()
|
|
1487
|
+
});
|
|
1488
|
+
var PostToProjectTaskChatRequestSchema = z2.object({
|
|
1489
|
+
projectId: z2.string(),
|
|
1490
|
+
taskId: z2.string(),
|
|
1491
|
+
content: z2.string()
|
|
1492
|
+
});
|
|
1493
|
+
var GetProjectTaskCliRequestSchema = z2.object({
|
|
1494
|
+
projectId: z2.string(),
|
|
1495
|
+
taskId: z2.string(),
|
|
1496
|
+
limit: z2.number().int().positive().optional().default(50),
|
|
1497
|
+
source: z2.string().optional()
|
|
1498
|
+
});
|
|
1499
|
+
var StartProjectBuildRequestSchema = z2.object({
|
|
1500
|
+
projectId: z2.string(),
|
|
1501
|
+
taskId: z2.string()
|
|
1502
|
+
});
|
|
1503
|
+
var StopProjectBuildRequestSchema = z2.object({
|
|
1504
|
+
projectId: z2.string(),
|
|
1505
|
+
taskId: z2.string()
|
|
1506
|
+
});
|
|
1507
|
+
var ApproveProjectMergePRRequestSchema = z2.object({
|
|
1508
|
+
projectId: z2.string(),
|
|
1509
|
+
childTaskId: z2.string()
|
|
1510
|
+
});
|
|
1511
|
+
var StartTaskAuditRequestSchema = z3.object({
|
|
1512
|
+
projectId: z3.string(),
|
|
1513
|
+
taskIds: z3.array(z3.string()).min(1)
|
|
1514
|
+
});
|
|
1515
|
+
var ReportTaskAuditProgressRequestSchema = z3.object({
|
|
1516
|
+
projectId: z3.string(),
|
|
1517
|
+
requestId: z3.string(),
|
|
1518
|
+
taskId: z3.string(),
|
|
1519
|
+
activity: z3.object({
|
|
1520
|
+
tool: z3.string(),
|
|
1521
|
+
input: z3.string().optional(),
|
|
1522
|
+
timestamp: z3.string()
|
|
1523
|
+
})
|
|
1524
|
+
});
|
|
1525
|
+
var CreateProjectSuggestionRequestSchema = z3.object({
|
|
1526
|
+
projectId: z3.string(),
|
|
1527
|
+
title: z3.string().min(1),
|
|
1528
|
+
description: z3.string().optional(),
|
|
1529
|
+
tagNames: z3.array(z3.string()).optional()
|
|
1530
|
+
});
|
|
1531
|
+
var ReportTaskAuditBatchCompleteRequestSchema = z3.object({
|
|
1532
|
+
projectId: z3.string(),
|
|
1533
|
+
requestId: z3.string()
|
|
1534
|
+
});
|
|
1535
|
+
var ReportTaskAuditResultRequestSchema = z3.object({
|
|
1536
|
+
projectId: z3.string(),
|
|
1537
|
+
requestId: z3.string(),
|
|
1538
|
+
taskId: z3.string(),
|
|
1539
|
+
summary: z3.string(),
|
|
1540
|
+
turnGrades: z3.array(
|
|
1541
|
+
z3.object({
|
|
1542
|
+
turnIndex: z3.number(),
|
|
1543
|
+
phase: z3.enum(["planning", "building", "human"]),
|
|
1544
|
+
grade: z3.enum(["correct", "neutral", "blunder"]),
|
|
1545
|
+
reasoning: z3.string(),
|
|
1546
|
+
eventType: z3.string(),
|
|
1547
|
+
eventSummary: z3.string()
|
|
1548
|
+
})
|
|
1549
|
+
),
|
|
1550
|
+
planningAccuracy: z3.number().nullable(),
|
|
1551
|
+
buildingAccuracy: z3.number().nullable(),
|
|
1552
|
+
humanAccuracy: z3.number().nullable(),
|
|
1553
|
+
planningCorrect: z3.number(),
|
|
1554
|
+
planningNeutral: z3.number(),
|
|
1555
|
+
planningBlunder: z3.number(),
|
|
1556
|
+
buildingCorrect: z3.number(),
|
|
1557
|
+
buildingNeutral: z3.number(),
|
|
1558
|
+
buildingBlunder: z3.number(),
|
|
1559
|
+
humanCorrect: z3.number(),
|
|
1560
|
+
humanNeutral: z3.number(),
|
|
1561
|
+
humanBlunder: z3.number(),
|
|
1562
|
+
humanEvaluations: z3.array(
|
|
1563
|
+
z3.object({
|
|
1564
|
+
messageIndex: z3.number(),
|
|
1565
|
+
rating: z3.number().int().min(-1).max(1),
|
|
1566
|
+
reasoning: z3.string()
|
|
1567
|
+
})
|
|
1568
|
+
).optional().default([]),
|
|
1569
|
+
suggestionIds: z3.array(z3.string()),
|
|
1570
|
+
auditCostUsd: z3.number().nullable(),
|
|
1571
|
+
model: z3.string().nullable(),
|
|
1572
|
+
error: z3.string().optional()
|
|
1573
|
+
});
|
|
1574
|
+
var TASK_CHAT_HISTORY_LIMIT = 20;
|
|
1575
|
+
var PM_CHAT_HISTORY_LIMIT = 40;
|
|
1576
|
+
var AGENT_CHAT_HISTORY_FETCH_LIMIT = Math.max(TASK_CHAT_HISTORY_LIMIT, PM_CHAT_HISTORY_LIMIT) + 10;
|
|
1577
|
+
|
|
996
1578
|
// src/execution/pack-runner-prompt.ts
|
|
997
1579
|
function findLastAgentMessageIndex(history) {
|
|
998
1580
|
for (let i = history.length - 1; i >= 0; i--) {
|
|
@@ -1040,7 +1622,7 @@ function buildPackRunnerSystemPrompt(context, config, setupLog) {
|
|
|
1040
1622
|
`2. Evaluate children by status and dependency readiness:`,
|
|
1041
1623
|
` - "ReviewPR": Review and merge its PR with approve_and_merge_pr. (Highest priority)`,
|
|
1042
1624
|
` - If merge fails due to pending CI: post a status update to chat, state you are going idle.`,
|
|
1043
|
-
` - If merge fails due to failed CI: use
|
|
1625
|
+
` - If merge fails due to failed CI: use get_execution_logs(childTaskId) to check. Escalate to team.`,
|
|
1044
1626
|
` - "InProgress": A Task Runner is actively working. Do nothing \u2014 wait.`,
|
|
1045
1627
|
` - "Open" + allDependenciesMet=true: Ready to fire. Use start_child_cloud_build.`,
|
|
1046
1628
|
` - "Open" + allDependenciesMet=false: Blocked \u2014 skip for now. Will be unblocked when deps complete.`,
|
|
@@ -1060,7 +1642,7 @@ function buildPackRunnerSystemPrompt(context, config, setupLog) {
|
|
|
1060
1642
|
`- When NO dependencies are set on any children, fall back to ordinal order (one at a time). This preserves backward compatibility.`,
|
|
1061
1643
|
`- After firing builds OR when waiting on CI, explicitly state you are going idle. The system will disconnect you and relaunch when there's a status change.`,
|
|
1062
1644
|
`- Do NOT attempt to write code yourself. Your role is coordination only.`,
|
|
1063
|
-
`- If a child is stuck in "InProgress" for an unusually long time, use
|
|
1645
|
+
`- If a child is stuck in "InProgress" for an unusually long time, use get_execution_logs(childTaskId) to check its logs and escalate to the team if it appears stuck.`,
|
|
1064
1646
|
`- You can use get_task(childTaskId) to get a child's full details including PR URL and branch.`,
|
|
1065
1647
|
`- list_subtasks returns PR info (githubPRNumber, githubPRUrl), agent assignment (agentId), and dependency info for each child \u2014 use this to verify readiness before firing builds.`,
|
|
1066
1648
|
`- You can use read_task_chat to check for team messages.`
|
|
@@ -1124,7 +1706,6 @@ After addressing the feedback, resume your autonomous loop: call list_subtasks a
|
|
|
1124
1706
|
}
|
|
1125
1707
|
|
|
1126
1708
|
// src/execution/prompt-formatters.ts
|
|
1127
|
-
var PM_CHAT_HISTORY_LIMIT = 40;
|
|
1128
1709
|
function formatFileSize(bytes) {
|
|
1129
1710
|
if (bytes === void 0) return "";
|
|
1130
1711
|
if (bytes < 1024) return `${bytes}B`;
|
|
@@ -1146,7 +1727,7 @@ function formatChatFile(file) {
|
|
|
1146
1727
|
}
|
|
1147
1728
|
if (file.content && file.contentEncoding === "base64") {
|
|
1148
1729
|
return [
|
|
1149
|
-
`[Attached image: ${file.fileName} (${file.mimeType}${sizeStr}) \u2014 use
|
|
1730
|
+
`[Attached image: ${file.fileName} (${file.mimeType}${sizeStr}) \u2014 use get_attachment("${file.fileId}") to view]`
|
|
1150
1731
|
];
|
|
1151
1732
|
}
|
|
1152
1733
|
return [`[Attached: ${file.fileName} (${file.mimeType}${sizeStr})]`];
|
|
@@ -1159,7 +1740,7 @@ function formatTaskFile(file) {
|
|
|
1159
1740
|
if (file.content && file.contentEncoding === "base64") {
|
|
1160
1741
|
const size = formatFileSize(file.fileSize);
|
|
1161
1742
|
return [
|
|
1162
|
-
`- [Attached image: ${file.fileName} (${file.mimeType}${size ? `, ${size}` : ""}) \u2014 use
|
|
1743
|
+
`- [Attached image: ${file.fileName} (${file.mimeType}${size ? `, ${size}` : ""}) \u2014 use get_attachment("${file.fileId}") to view]`
|
|
1163
1744
|
];
|
|
1164
1745
|
}
|
|
1165
1746
|
if (!file.content) {
|
|
@@ -1236,7 +1817,7 @@ function formatIncidents(incidents) {
|
|
|
1236
1817
|
}
|
|
1237
1818
|
|
|
1238
1819
|
// src/execution/tag-context-resolver.ts
|
|
1239
|
-
import { readFile, readdir } from "fs/promises";
|
|
1820
|
+
import { readFile, readdir, stat } from "fs/promises";
|
|
1240
1821
|
var TYPE_PRIORITY = { rule: 0, file: 1, folder: 2, doc: 3 };
|
|
1241
1822
|
var BINARY_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
1242
1823
|
".png",
|
|
@@ -1271,6 +1852,10 @@ function isBinaryPath(filePath) {
|
|
|
1271
1852
|
const ext = filePath.slice(filePath.lastIndexOf(".")).toLowerCase();
|
|
1272
1853
|
return BINARY_EXTENSIONS.has(ext);
|
|
1273
1854
|
}
|
|
1855
|
+
var fileContentCache = /* @__PURE__ */ new Map();
|
|
1856
|
+
var folderListingCache = /* @__PURE__ */ new Map();
|
|
1857
|
+
var fileReadCount = 0;
|
|
1858
|
+
var folderReadCount = 0;
|
|
1274
1859
|
function getContextBudgetChars(_model, betas, runnerMode) {
|
|
1275
1860
|
const contextWindow = betas?.some((b) => b.includes("context-1m")) ? 1e6 : 2e5;
|
|
1276
1861
|
const budgetPct = runnerMode === "task" ? 0.15 : 0.25;
|
|
@@ -1279,21 +1864,50 @@ function getContextBudgetChars(_model, betas, runnerMode) {
|
|
|
1279
1864
|
async function readFileContent(filePath, maxChars) {
|
|
1280
1865
|
try {
|
|
1281
1866
|
if (isBinaryPath(filePath)) return null;
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1867
|
+
let rawContent;
|
|
1868
|
+
let mtimeMs;
|
|
1869
|
+
try {
|
|
1870
|
+
const st = await stat(filePath);
|
|
1871
|
+
mtimeMs = st.mtimeMs;
|
|
1872
|
+
} catch {
|
|
1873
|
+
return null;
|
|
1874
|
+
}
|
|
1875
|
+
const cached = fileContentCache.get(filePath);
|
|
1876
|
+
if (cached && cached.mtimeMs === mtimeMs) {
|
|
1877
|
+
rawContent = cached.content;
|
|
1878
|
+
} else {
|
|
1879
|
+
rawContent = await readFile(filePath, "utf-8");
|
|
1880
|
+
fileReadCount++;
|
|
1881
|
+
fileContentCache.set(filePath, { mtimeMs, content: rawContent });
|
|
1882
|
+
}
|
|
1883
|
+
if (rawContent.length > maxChars) {
|
|
1884
|
+
const omitted = rawContent.length - maxChars;
|
|
1885
|
+
return rawContent.slice(0, maxChars) + `
|
|
1286
1886
|
[... truncated, ${omitted} chars omitted]`;
|
|
1287
1887
|
}
|
|
1288
|
-
return
|
|
1888
|
+
return rawContent;
|
|
1289
1889
|
} catch {
|
|
1290
1890
|
return null;
|
|
1291
1891
|
}
|
|
1292
1892
|
}
|
|
1293
1893
|
async function readFolderListing(folderPath) {
|
|
1294
1894
|
try {
|
|
1895
|
+
let mtimeMs;
|
|
1896
|
+
try {
|
|
1897
|
+
const st = await stat(folderPath);
|
|
1898
|
+
mtimeMs = st.mtimeMs;
|
|
1899
|
+
} catch {
|
|
1900
|
+
return null;
|
|
1901
|
+
}
|
|
1902
|
+
const cached = folderListingCache.get(folderPath);
|
|
1903
|
+
if (cached && cached.mtimeMs === mtimeMs) {
|
|
1904
|
+
return cached.listing;
|
|
1905
|
+
}
|
|
1295
1906
|
const entries = await readdir(folderPath);
|
|
1296
|
-
|
|
1907
|
+
folderReadCount++;
|
|
1908
|
+
const listing = `Files: ${entries.join(", ")}`;
|
|
1909
|
+
folderListingCache.set(folderPath, { mtimeMs, listing });
|
|
1910
|
+
return listing;
|
|
1297
1911
|
} catch {
|
|
1298
1912
|
return null;
|
|
1299
1913
|
}
|
|
@@ -1414,6 +2028,18 @@ async function resolveTagContext(projectTags, taskTagIds, model, betas, runnerMo
|
|
|
1414
2028
|
};
|
|
1415
2029
|
}
|
|
1416
2030
|
|
|
2031
|
+
// src/execution/prompt-truncation.ts
|
|
2032
|
+
var PLAN_SOFT_CAP = 4e3;
|
|
2033
|
+
var PLAN_HEAD_CHARS = 3e3;
|
|
2034
|
+
var PLAN_TAIL_CHARS = 500;
|
|
2035
|
+
var PLAN_TRUNCATION_MARKER = "\n\n... plan truncated \u2014 call get_current_plan for full text ...\n\n";
|
|
2036
|
+
function truncatePlanForPrompt(plan) {
|
|
2037
|
+
if (plan.length <= PLAN_SOFT_CAP) return plan;
|
|
2038
|
+
const head = plan.slice(0, PLAN_HEAD_CHARS);
|
|
2039
|
+
const tail = plan.slice(plan.length - PLAN_TAIL_CHARS);
|
|
2040
|
+
return `${head}${PLAN_TRUNCATION_MARKER}${tail}`;
|
|
2041
|
+
}
|
|
2042
|
+
|
|
1417
2043
|
// src/execution/mode-prompt.ts
|
|
1418
2044
|
var SP_DESC_MAX_CHARS = 80;
|
|
1419
2045
|
function truncateDescription(desc, maxChars) {
|
|
@@ -1473,7 +2099,19 @@ function buildExplorationMethodology() {
|
|
|
1473
2099
|
`- Search first, read second: use grep/glob to locate relevant code, then read only the files that matter`,
|
|
1474
2100
|
`- Never re-read a file already in your context \u2014 you have a large context window, scroll up instead`,
|
|
1475
2101
|
`- Start with 3-5 critical files, form a hypothesis about the approach, then validate with targeted reads`,
|
|
1476
|
-
`- Stop exploring when you can
|
|
2102
|
+
`- Stop exploring when you can cite specific \`file.ts:line\` locations and function names for every step in your plan \u2014 that's enough`
|
|
2103
|
+
];
|
|
2104
|
+
}
|
|
2105
|
+
function buildPlanCitationFormat() {
|
|
2106
|
+
return [
|
|
2107
|
+
``,
|
|
2108
|
+
`### Plan Citation Format`,
|
|
2109
|
+
`Plans must ground each change in the code. For every step that touches code:`,
|
|
2110
|
+
`- Cite the exact location as \`path/from/repo/root.ts:lineNumber\` (e.g. \`packages/conveyor-agent/src/execution/mode-prompt.ts:129\`).`,
|
|
2111
|
+
`- Name the specific function, class, constant, or JSX element being touched.`,
|
|
2112
|
+
`- When behavior hinges on a short piece of code, quote 1\u20133 lines inline instead of paraphrasing.`,
|
|
2113
|
+
`- Ranges are fine for larger edits (\`foo.ts:120-145\`). Do not cite whole files without a line.`,
|
|
2114
|
+
`- If a file doesn't exist yet, write \`NEW: path/to/new-file.ts\` and describe the surrounding module it fits into.`
|
|
1477
2115
|
];
|
|
1478
2116
|
}
|
|
1479
2117
|
function buildDiscoveryPrompt(context, runnerMode) {
|
|
@@ -1493,15 +2131,16 @@ function buildDiscoveryPrompt(context, runnerMode) {
|
|
|
1493
2131
|
`Your PRIMARY goal is to create a thorough plan. Complete these steps in order:`,
|
|
1494
2132
|
`1. Read the task description and chat history \u2014 respond to what's been discussed`,
|
|
1495
2133
|
`2. Investigate the codebase using the methodology below \u2014 search first, read targeted files`,
|
|
1496
|
-
`3. Save a detailed plan via \`
|
|
2134
|
+
`3. Save a detailed plan via \`update_task_plan\``,
|
|
1497
2135
|
`4. Set story points, tags, and title via \`update_task_properties\` (icon is set automatically)`,
|
|
1498
2136
|
`5. Discuss the plan with the team if they're engaged, incorporate feedback`,
|
|
1499
2137
|
`6. THEN call ExitPlanMode \u2014 it is the LAST step, not the first`,
|
|
1500
2138
|
...buildExplorationMethodology(),
|
|
2139
|
+
...buildPlanCitationFormat(),
|
|
1501
2140
|
``,
|
|
1502
2141
|
`### Self-Identification Tools`,
|
|
1503
2142
|
`Use these MCP tools to set your own task properties:`,
|
|
1504
|
-
`- \`
|
|
2143
|
+
`- \`update_task_plan\` \u2014 save your plan and description`,
|
|
1505
2144
|
`- \`update_task_properties\` \u2014 set title, story points, and tags (any combination)`,
|
|
1506
2145
|
`Note: Icons are assigned automatically during identification after planning is complete.`,
|
|
1507
2146
|
``,
|
|
@@ -1524,21 +2163,20 @@ function buildDiscoveryPrompt(context, runnerMode) {
|
|
|
1524
2163
|
`### Subtask Plan Requirements`,
|
|
1525
2164
|
`When creating subtasks, each MUST include a detailed \`plan\` field:`,
|
|
1526
2165
|
`- Plans should be multi-step implementation guides, not vague descriptions`,
|
|
1527
|
-
`- Include
|
|
2166
|
+
`- Include concrete \`file.ts:line\` citations, function/symbol names, and short code snippets where relevant`,
|
|
1528
2167
|
`- Reference existing implementations when relevant (e.g., "follow the pattern in src/services/foo.ts")`,
|
|
1529
2168
|
`- Include testing requirements and acceptance criteria`,
|
|
1530
2169
|
`- Set \`storyPointValue\` based on estimated complexity`,
|
|
1531
2170
|
``,
|
|
1532
2171
|
`### Plan Verification Requirements`,
|
|
1533
|
-
`Every plan MUST include a **Testing / Verification** section
|
|
1534
|
-
`- The quality gates: \`bun run lint\`, \`bun run typecheck\`, \`bun run test\` (or scoped equivalents)`,
|
|
2172
|
+
`Every plan MUST include a **Testing / Verification** section so the build agent has a clear definition of "done". Enumerate:`,
|
|
2173
|
+
`- The quality gates the build agent should run: \`bun run lint\`, \`bun run typecheck\`, \`bun run test\` (or scoped equivalents)`,
|
|
1535
2174
|
`- Any task-specific end-to-end checks (manual UI walk-through, API smoke test, migration dry-run, etc.)`,
|
|
1536
|
-
|
|
1537
|
-
`This ensures executing agents and reviewers have a clear definition of "done" and prevents silent regressions.`,
|
|
2175
|
+
`You are NOT expected to run these gates yourself \u2014 discovery is read-only. Just describe them in the plan.`,
|
|
1538
2176
|
``,
|
|
1539
2177
|
`### Completing Planning`,
|
|
1540
2178
|
`Once ALL checklist items above are done, call the **ExitPlanMode** tool.`,
|
|
1541
|
-
`- Required before ExitPlanMode will succeed: **plan** (via
|
|
2179
|
+
`- Required before ExitPlanMode will succeed: **plan** (via update_task_plan), **story points** (via update_task_properties), **title** (via update_task_properties)`,
|
|
1542
2180
|
`- ExitPlanMode validates these properties and marks planning as complete`,
|
|
1543
2181
|
`- It does NOT start building \u2014 the team controls when to switch to Build mode`,
|
|
1544
2182
|
`- Do NOT call ExitPlanMode until you have thoroughly explored the codebase and saved a detailed plan`
|
|
@@ -1554,11 +2192,11 @@ function buildAutoPrompt(context, runnerMode) {
|
|
|
1554
2192
|
``,
|
|
1555
2193
|
`### Phase 1: Discovery & Planning (current)`,
|
|
1556
2194
|
`- You are in the SDK's plan mode \u2014 read-only access is enforced automatically`,
|
|
1557
|
-
`- You have MCP tools for task properties:
|
|
2195
|
+
`- You have MCP tools for task properties: update_task_plan, update_task_properties`,
|
|
1558
2196
|
``,
|
|
1559
2197
|
`### Required before transitioning:`,
|
|
1560
2198
|
`Before calling ExitPlanMode, you MUST fill in ALL of these:`,
|
|
1561
|
-
`1. **Plan** \u2014 Save a clear implementation plan using
|
|
2199
|
+
`1. **Plan** \u2014 Save a clear implementation plan using update_task_plan`,
|
|
1562
2200
|
`2. **Story Points** \u2014 Assign via update_task_properties`,
|
|
1563
2201
|
`3. **Title** \u2014 Set an accurate title via update_task_properties (if the current one is vague or "Untitled")`,
|
|
1564
2202
|
``,
|
|
@@ -1571,11 +2209,13 @@ function buildAutoPrompt(context, runnerMode) {
|
|
|
1571
2209
|
`### Subtask Plan Requirements`,
|
|
1572
2210
|
`When creating subtasks, each MUST include a detailed \`plan\` field:`,
|
|
1573
2211
|
`- Plans should be multi-step implementation guides, not vague descriptions`,
|
|
1574
|
-
`- Include
|
|
2212
|
+
`- Include concrete \`file.ts:line\` citations, function/symbol names, and short code snippets where relevant`,
|
|
1575
2213
|
`- Reference existing implementations when relevant`,
|
|
1576
2214
|
`- Include testing requirements and acceptance criteria`,
|
|
1577
2215
|
`- Set \`storyPointValue\` based on estimated complexity`,
|
|
1578
2216
|
``,
|
|
2217
|
+
...buildPlanCitationFormat(),
|
|
2218
|
+
``,
|
|
1579
2219
|
...context?.isParentTask ? [
|
|
1580
2220
|
``,
|
|
1581
2221
|
`### Parent Task Guidance`,
|
|
@@ -1645,7 +2285,7 @@ function buildReviewPrompt(context) {
|
|
|
1645
2285
|
`You are reviewing and coordinating child tasks.`,
|
|
1646
2286
|
`- Use \`list_subtasks\` to see current child task state and progress.`,
|
|
1647
2287
|
`- For children in ReviewPR status: review their code quality and merge with \`approve_and_merge_pr\`.`,
|
|
1648
|
-
`- For children with failing CI: check with \`
|
|
2288
|
+
`- For children with failing CI: check with \`get_execution_logs(childTaskId)\` and escalate if stuck.`,
|
|
1649
2289
|
`- Fire next child builds with \`start_child_cloud_build\` when ready.`,
|
|
1650
2290
|
`- Create follow-up tasks for issues discovered during review.`,
|
|
1651
2291
|
``,
|
|
@@ -1722,7 +2362,7 @@ Environment (ready, no setup required):`,
|
|
|
1722
2362
|
`
|
|
1723
2363
|
Workflow:`,
|
|
1724
2364
|
`- You can draft and iterate on plans in .claude/plans/*.md \u2014 these files are automatically synced to the task.`,
|
|
1725
|
-
`- You can also use
|
|
2365
|
+
`- You can also use update_task_plan directly to save the plan to the task.`,
|
|
1726
2366
|
`- After saving the plan, end your turn with a summary reply (the team sees your responses in chat automatically). Do NOT attempt to execute the plan yourself.`,
|
|
1727
2367
|
`- A separate task agent will handle execution after the team reviews and approves your plan.`
|
|
1728
2368
|
];
|
|
@@ -1749,7 +2389,7 @@ function buildActivePreamble(context, workspaceDir) {
|
|
|
1749
2389
|
`You are an AI project manager in ACTIVE mode for the "${context.title}" project.`,
|
|
1750
2390
|
`You have direct coding access to the repository at ${workspaceDir}.`,
|
|
1751
2391
|
`You can edit files, run tests, and make commits.`,
|
|
1752
|
-
`You still have access to all PM tools (subtasks,
|
|
2392
|
+
`You still have access to all PM tools (subtasks, update_task_plan, chat).`,
|
|
1753
2393
|
`
|
|
1754
2394
|
Environment (ready, no setup required):`,
|
|
1755
2395
|
`- Repository is cloned at your current working directory.`,
|
|
@@ -1876,17 +2516,26 @@ Your responses are sent directly to the task chat \u2014 the team sees everythin
|
|
|
1876
2516
|
}
|
|
1877
2517
|
|
|
1878
2518
|
// src/execution/prompt-builder.ts
|
|
1879
|
-
var TASK_CHAT_HISTORY_LIMIT = 20;
|
|
1880
2519
|
function findLastAgentMessageIndex2(history) {
|
|
1881
2520
|
for (let i = history.length - 1; i >= 0; i--) {
|
|
1882
2521
|
if (history[i].role === "assistant") return i;
|
|
1883
2522
|
}
|
|
1884
2523
|
return -1;
|
|
1885
2524
|
}
|
|
2525
|
+
function messagesAfterCursor(history, lastSeenMessageId) {
|
|
2526
|
+
if (!lastSeenMessageId) return history;
|
|
2527
|
+
const idx = history.findIndex((m) => m.id === lastSeenMessageId);
|
|
2528
|
+
return idx === -1 ? history : history.slice(idx + 1);
|
|
2529
|
+
}
|
|
1886
2530
|
function detectRelaunchScenario(context, trustChatHistory = false) {
|
|
2531
|
+
if (context.lastSeenMessageId) {
|
|
2532
|
+
const newMessages = messagesAfterCursor(context.chatHistory, context.lastSeenMessageId);
|
|
2533
|
+
const hasNewUserMessages2 = newMessages.some((m) => m.role === "user");
|
|
2534
|
+
return hasNewUserMessages2 ? "feedback_relaunch" : "idle_relaunch";
|
|
2535
|
+
}
|
|
1887
2536
|
const lastAgentIdx = findLastAgentMessageIndex2(context.chatHistory);
|
|
1888
2537
|
if (lastAgentIdx === -1) return "fresh";
|
|
1889
|
-
const hasPriorWork = !!context.githubPRUrl ||
|
|
2538
|
+
const hasPriorWork = !!context.githubPRUrl || trustChatHistory;
|
|
1890
2539
|
if (!hasPriorWork) return "fresh";
|
|
1891
2540
|
const messagesAfterAgent = context.chatHistory.slice(lastAgentIdx + 1);
|
|
1892
2541
|
const hasNewUserMessages = messagesAfterAgent.some((m) => m.role === "user");
|
|
@@ -1925,7 +2574,7 @@ CRITICAL: You are in Auto mode. Do NOT report status, ask for confirmation, or g
|
|
|
1925
2574
|
parts.push(
|
|
1926
2575
|
`
|
|
1927
2576
|
You are in auto mode. A plan already exists for this task.`,
|
|
1928
|
-
`Verify that story points, title, and tags are set via
|
|
2577
|
+
`Verify that story points, title, and tags are set via get_current_plan, then call ExitPlanMode immediately to transition to building.`,
|
|
1929
2578
|
`Do NOT wait for team input \u2014 proceed autonomously.`
|
|
1930
2579
|
);
|
|
1931
2580
|
} else {
|
|
@@ -1947,13 +2596,14 @@ You are the project manager for this task.`,
|
|
|
1947
2596
|
}
|
|
1948
2597
|
function buildRelaunchWithSession(mode, context, agentMode, isAuto) {
|
|
1949
2598
|
const scenario = detectRelaunchScenario(context);
|
|
1950
|
-
|
|
2599
|
+
const hasPriorTurn = !!context.lastSeenMessageId || !!context.claudeSessionId;
|
|
2600
|
+
if (!hasPriorTurn || scenario === "fresh") return null;
|
|
1951
2601
|
const parts = [];
|
|
1952
2602
|
const lastAgentIdx = findLastAgentMessageIndex2(context.chatHistory);
|
|
1953
2603
|
if (mode === "pm") {
|
|
1954
2604
|
parts.push(...buildPmRelaunchParts(context, lastAgentIdx, isAuto, agentMode));
|
|
1955
2605
|
} else if (scenario === "feedback_relaunch") {
|
|
1956
|
-
const newMessages = context.chatHistory.slice(lastAgentIdx + 1).filter((m) => m.role === "user");
|
|
2606
|
+
const newMessages = (context.lastSeenMessageId ? messagesAfterCursor(context.chatHistory, context.lastSeenMessageId) : context.chatHistory.slice(lastAgentIdx + 1)).filter((m) => m.role === "user");
|
|
1957
2607
|
parts.push(
|
|
1958
2608
|
`You have been relaunched with new feedback.`,
|
|
1959
2609
|
`Work on the git branch "${context.githubBranch}". Stay on this branch \u2014 do not checkout or create other branches.`,
|
|
@@ -2024,7 +2674,7 @@ ${context.description}`);
|
|
|
2024
2674
|
if (context.plan) {
|
|
2025
2675
|
parts.push(`
|
|
2026
2676
|
## Plan
|
|
2027
|
-
${context.plan}`);
|
|
2677
|
+
${truncatePlanForPrompt(context.plan)}`);
|
|
2028
2678
|
}
|
|
2029
2679
|
if (context.files && context.files.length > 0) {
|
|
2030
2680
|
parts.push(`
|
|
@@ -2081,7 +2731,7 @@ CRITICAL: You are in Auto mode. Do NOT report status, ask for confirmation, or g
|
|
|
2081
2731
|
return [
|
|
2082
2732
|
`You are operating autonomously. Begin planning immediately.`,
|
|
2083
2733
|
`1. Search the codebase (grep/glob) to locate relevant files, then read the critical ones`,
|
|
2084
|
-
`2. Draft a clear implementation plan and save it with
|
|
2734
|
+
`2. Draft a clear implementation plan and save it with update_task_plan`,
|
|
2085
2735
|
`3. Set story points, tags, and title (update_task_properties)`,
|
|
2086
2736
|
`4. When the plan and all required properties are set, call ExitPlanMode to transition to building`,
|
|
2087
2737
|
`Do NOT wait for team input \u2014 proceed autonomously.`
|
|
@@ -2093,7 +2743,7 @@ CRITICAL: You are in Auto mode. Do NOT report status, ask for confirmation, or g
|
|
|
2093
2743
|
`Review existing subtasks via \`list_subtasks\` and the chat history before taking action.`,
|
|
2094
2744
|
`Read the task description and chat history carefully \u2014 the team has provided the initial context below. Acknowledge what they've asked for and respond in chat before taking silent tool actions.`,
|
|
2095
2745
|
`Start planning now \u2014 explore the codebase, ask clarifying questions if needed, and propose a subtask breakdown. Do not wait for additional team input before engaging.`,
|
|
2096
|
-
`When you finish planning, save the plan with
|
|
2746
|
+
`When you finish planning, save the plan with update_task_plan and end your turn. Your reply will be visible to the team in chat.`
|
|
2097
2747
|
];
|
|
2098
2748
|
}
|
|
2099
2749
|
if (isPm) {
|
|
@@ -2101,7 +2751,7 @@ CRITICAL: You are in Auto mode. Do NOT report status, ask for confirmation, or g
|
|
|
2101
2751
|
`You are the project manager for this task.`,
|
|
2102
2752
|
`Read the task description and chat history carefully \u2014 the team has provided the initial context below. Acknowledge what they've asked for and respond in chat before taking silent tool actions.`,
|
|
2103
2753
|
`Start planning now \u2014 explore the codebase, ask clarifying questions if needed, and draft a plan. Do not wait for additional team input before engaging; the initial message IS the team engaging.`,
|
|
2104
|
-
`When you finish planning, save the plan with
|
|
2754
|
+
`When you finish planning, save the plan with update_task_plan and end your turn. Your reply summarizing the plan will be visible in chat. A separate task agent will execute the plan after review.`
|
|
2105
2755
|
];
|
|
2106
2756
|
}
|
|
2107
2757
|
const parts = [
|
|
@@ -2145,7 +2795,7 @@ Your plan has been approved. Address the feedback above, then begin implementing
|
|
|
2145
2795
|
} else if (isAuto) {
|
|
2146
2796
|
parts2.push(
|
|
2147
2797
|
`
|
|
2148
|
-
You are in auto mode. Address the feedback above \u2014 update the plan accordingly using
|
|
2798
|
+
You are in auto mode. Address the feedback above \u2014 update the plan accordingly using update_task_plan.`,
|
|
2149
2799
|
`When the plan and all required properties are set, call ExitPlanMode to transition to building.`,
|
|
2150
2800
|
`Do NOT wait for additional team input \u2014 the messages above ARE the team's input. Proceed autonomously.`
|
|
2151
2801
|
);
|
|
@@ -2256,14 +2906,14 @@ async function buildInitialPrompt(mode, context, isAuto, agentMode) {
|
|
|
2256
2906
|
}
|
|
2257
2907
|
|
|
2258
2908
|
// src/tools/task-context-tools.ts
|
|
2259
|
-
import { z } from "zod";
|
|
2909
|
+
import { z as z4 } from "zod";
|
|
2260
2910
|
function buildReadTaskChatTool(connection) {
|
|
2261
2911
|
return defineTool(
|
|
2262
2912
|
"read_task_chat",
|
|
2263
|
-
"Read recent human/user chat messages for a task.
|
|
2913
|
+
"Read recent human/user chat messages for a task. Omit task_id for the current task; pass a child ID for a child's chat. For agent logs use get_execution_logs.",
|
|
2264
2914
|
{
|
|
2265
|
-
limit:
|
|
2266
|
-
task_id:
|
|
2915
|
+
limit: z4.number().optional().describe("Number of recent messages to fetch (default 20)"),
|
|
2916
|
+
task_id: z4.string().optional().describe("Child task ID to read chat from. Omit to read the current task's chat.")
|
|
2267
2917
|
},
|
|
2268
2918
|
async ({ limit, task_id }) => {
|
|
2269
2919
|
try {
|
|
@@ -2284,10 +2934,10 @@ function buildReadTaskChatTool(connection) {
|
|
|
2284
2934
|
{ annotations: { readOnlyHint: true } }
|
|
2285
2935
|
);
|
|
2286
2936
|
}
|
|
2287
|
-
function
|
|
2937
|
+
function buildGetCurrentPlanTool(connection) {
|
|
2288
2938
|
return defineTool(
|
|
2289
|
-
"
|
|
2290
|
-
"Re-read the current task's plan.
|
|
2939
|
+
"get_current_plan",
|
|
2940
|
+
"Re-read the current task's plan. Use when the user updated the plan or asked you to re-read it \u2014 otherwise the plan is already in initial context. For task metadata use get_task.",
|
|
2291
2941
|
{},
|
|
2292
2942
|
async () => {
|
|
2293
2943
|
try {
|
|
@@ -2305,9 +2955,9 @@ function buildGetTaskPlanTool(connection) {
|
|
|
2305
2955
|
function buildGetTaskTool(connection) {
|
|
2306
2956
|
return defineTool(
|
|
2307
2957
|
"get_task",
|
|
2308
|
-
"Look up any task by slug or ID.
|
|
2958
|
+
"Look up any task by slug or ID. Returns JSON with id, slug, title, description, plan, status, branch, githubPRNumber, githubPRUrl, storyPoints. For children use list_subtasks.",
|
|
2309
2959
|
{
|
|
2310
|
-
slug_or_id:
|
|
2960
|
+
slug_or_id: z4.string().describe("The task slug (e.g. 'my-task') or CUID")
|
|
2311
2961
|
},
|
|
2312
2962
|
async ({ slug_or_id }) => {
|
|
2313
2963
|
try {
|
|
@@ -2325,14 +2975,14 @@ function buildGetTaskTool(connection) {
|
|
|
2325
2975
|
{ annotations: { readOnlyHint: true } }
|
|
2326
2976
|
);
|
|
2327
2977
|
}
|
|
2328
|
-
function
|
|
2978
|
+
function buildGetExecutionLogsTool(connection) {
|
|
2329
2979
|
return defineTool(
|
|
2330
|
-
"
|
|
2331
|
-
"Read CLI execution logs
|
|
2980
|
+
"get_execution_logs",
|
|
2981
|
+
"Read CLI execution logs \u2014 agent reasoning, tool calls, and setup/dev-server output. Filter via source='agent' or 'application'. For human chat use read_task_chat.",
|
|
2332
2982
|
{
|
|
2333
|
-
task_id:
|
|
2334
|
-
source:
|
|
2335
|
-
limit:
|
|
2983
|
+
task_id: z4.string().optional().describe("Task ID or slug. Omit to read logs from the current task."),
|
|
2984
|
+
source: z4.enum(["agent", "application"]).optional().describe("Filter by log source. Omit for all logs."),
|
|
2985
|
+
limit: z4.number().optional().describe("Max number of log entries to return (default 50, max 500).")
|
|
2336
2986
|
},
|
|
2337
2987
|
async ({ task_id, source, limit }) => {
|
|
2338
2988
|
try {
|
|
@@ -2361,7 +3011,7 @@ function buildGetTaskCliTool(connection) {
|
|
|
2361
3011
|
function buildListTaskFilesTool(connection) {
|
|
2362
3012
|
return defineTool(
|
|
2363
3013
|
"list_task_files",
|
|
2364
|
-
"List all files attached to this task with metadata.
|
|
3014
|
+
"List all files attached to this task with metadata. Use before fetching a specific file to see what is available and how large each is. For file contents use get_attachment.",
|
|
2365
3015
|
{},
|
|
2366
3016
|
async () => {
|
|
2367
3017
|
try {
|
|
@@ -2388,11 +3038,11 @@ function buildListTaskFilesTool(connection) {
|
|
|
2388
3038
|
{ annotations: { readOnlyHint: true } }
|
|
2389
3039
|
);
|
|
2390
3040
|
}
|
|
2391
|
-
function
|
|
3041
|
+
function buildGetAttachmentTool(connection) {
|
|
2392
3042
|
return defineTool(
|
|
2393
|
-
"
|
|
2394
|
-
"Fetch one task file's content plus metadata by file ID.
|
|
2395
|
-
{ fileId:
|
|
3043
|
+
"get_attachment",
|
|
3044
|
+
"Fetch one task file's content plus metadata by file ID. Call list_task_files first to discover IDs and check sizes \u2014 large binaries may be truncated by the service's size limit.",
|
|
3045
|
+
{ fileId: z4.string().describe("The file ID to retrieve") },
|
|
2396
3046
|
async ({ fileId }) => {
|
|
2397
3047
|
try {
|
|
2398
3048
|
const file = await connection.call("getTaskFile", {
|
|
@@ -2421,20 +3071,20 @@ function buildGetTaskFileTool(connection) {
|
|
|
2421
3071
|
function buildTaskContextTools(connection) {
|
|
2422
3072
|
return [
|
|
2423
3073
|
buildReadTaskChatTool(connection),
|
|
2424
|
-
|
|
3074
|
+
buildGetCurrentPlanTool(connection),
|
|
2425
3075
|
buildGetTaskTool(connection),
|
|
2426
|
-
|
|
3076
|
+
buildGetExecutionLogsTool(connection),
|
|
2427
3077
|
buildListTaskFilesTool(connection),
|
|
2428
|
-
|
|
3078
|
+
buildGetAttachmentTool(connection)
|
|
2429
3079
|
];
|
|
2430
3080
|
}
|
|
2431
3081
|
|
|
2432
3082
|
// src/tools/dependency-suggestion-tools.ts
|
|
2433
|
-
import { z as
|
|
3083
|
+
import { z as z5 } from "zod";
|
|
2434
3084
|
function buildGetDependenciesTool(connection) {
|
|
2435
3085
|
return defineTool(
|
|
2436
3086
|
"get_dependencies",
|
|
2437
|
-
"Get this task's dependencies and their
|
|
3087
|
+
"Get this task's dependencies and their met/unmet status (met = merged to dev). Use to confirm blockers merged, or see why a task cannot start. For task state use get_task.",
|
|
2438
3088
|
{},
|
|
2439
3089
|
async () => {
|
|
2440
3090
|
try {
|
|
@@ -2454,12 +3104,12 @@ function buildGetDependenciesTool(connection) {
|
|
|
2454
3104
|
function buildGetSuggestionsTool(connection) {
|
|
2455
3105
|
return defineTool(
|
|
2456
3106
|
"get_suggestions",
|
|
2457
|
-
"List project suggestions sorted by vote score.
|
|
3107
|
+
"List project suggestions sorted by vote score. Filter by status or cap with limit (default 20). Suggestions are project-level ideas, not tasks \u2014 use get_task for tasks.",
|
|
2458
3108
|
{
|
|
2459
|
-
status:
|
|
3109
|
+
status: z5.string().optional().describe(
|
|
2460
3110
|
"Filter by status: Planning, Open, InProgress, ReviewPR, ReviewDev, ReviewLive, Complete, Cancelled"
|
|
2461
3111
|
),
|
|
2462
|
-
limit:
|
|
3112
|
+
limit: z5.number().int().min(1).max(100).optional().describe("Max results (default 20)")
|
|
2463
3113
|
},
|
|
2464
3114
|
async ({ status, limit }) => {
|
|
2465
3115
|
try {
|
|
@@ -2483,14 +3133,14 @@ function buildGetSuggestionsTool(connection) {
|
|
|
2483
3133
|
}
|
|
2484
3134
|
|
|
2485
3135
|
// src/tools/mutation-tools.ts
|
|
2486
|
-
import { z as
|
|
3136
|
+
import { z as z6 } from "zod";
|
|
2487
3137
|
function buildPostToChatTool(connection) {
|
|
2488
3138
|
return defineTool(
|
|
2489
3139
|
"post_to_chat",
|
|
2490
|
-
"Post an out-of-band message to a task
|
|
3140
|
+
"Post an out-of-band chat message to a task. Use only when explicitly asked, or to message a child's chat (pass its ID). Normal replies already appear in chat automatically.",
|
|
2491
3141
|
{
|
|
2492
|
-
message:
|
|
2493
|
-
task_id:
|
|
3142
|
+
message: z6.string().describe("The message to post to the team"),
|
|
3143
|
+
task_id: z6.string().optional().describe("Child task ID to post to. Omit to post to the current task's chat.")
|
|
2494
3144
|
},
|
|
2495
3145
|
async ({ message, task_id }) => {
|
|
2496
3146
|
try {
|
|
@@ -2500,10 +3150,21 @@ function buildPostToChatTool(connection) {
|
|
|
2500
3150
|
childTaskId: task_id,
|
|
2501
3151
|
message
|
|
2502
3152
|
});
|
|
2503
|
-
return textResult(
|
|
3153
|
+
return textResult(JSON.stringify({ posted: true, target: `child:${task_id}` }));
|
|
3154
|
+
}
|
|
3155
|
+
const dedup = connection.checkAndTrackDuplicate(message);
|
|
3156
|
+
if (dedup.duplicate) {
|
|
3157
|
+
return textResult(
|
|
3158
|
+
JSON.stringify({
|
|
3159
|
+
posted: false,
|
|
3160
|
+
reason: "duplicate",
|
|
3161
|
+
matchedMessagePreview: dedup.matchedMessagePreview,
|
|
3162
|
+
hint: "A near-identical message (>70% word overlap) was posted within the last 30s. Rephrase with new information or skip this post."
|
|
3163
|
+
})
|
|
3164
|
+
);
|
|
2504
3165
|
}
|
|
2505
3166
|
await connection.call("postToChat", { message });
|
|
2506
|
-
return textResult(
|
|
3167
|
+
return textResult(JSON.stringify({ posted: true }));
|
|
2507
3168
|
} catch (error) {
|
|
2508
3169
|
return textResult(
|
|
2509
3170
|
`Failed to post message: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
@@ -2515,10 +3176,10 @@ function buildPostToChatTool(connection) {
|
|
|
2515
3176
|
function buildForceUpdateTaskStatusTool(connection) {
|
|
2516
3177
|
return defineTool(
|
|
2517
3178
|
"force_update_task_status",
|
|
2518
|
-
"EMERGENCY ONLY: force-override a task's Kanban status.
|
|
3179
|
+
"EMERGENCY ONLY: force-override a task's Kanban status. Use when an automatic transition failed and the task is wedged. Normal flow transitions status automatically.",
|
|
2519
3180
|
{
|
|
2520
|
-
status:
|
|
2521
|
-
task_id:
|
|
3181
|
+
status: z6.enum(["InProgress", "ReviewPR", "ReviewDev", "Complete"]).describe("The new status for the task"),
|
|
3182
|
+
task_id: z6.string().optional().describe("Child task ID to update. Omit to update the current task.")
|
|
2522
3183
|
},
|
|
2523
3184
|
async ({ status, task_id }) => {
|
|
2524
3185
|
try {
|
|
@@ -2547,17 +3208,17 @@ function buildForceUpdateTaskStatusTool(connection) {
|
|
|
2547
3208
|
function buildCreatePullRequestTool(connection, config) {
|
|
2548
3209
|
return defineTool(
|
|
2549
3210
|
"create_pull_request",
|
|
2550
|
-
"Create a GitHub
|
|
3211
|
+
"Create a GitHub PR for this task. Auto-stages, commits (commitMessage or title default), pushes to origin, then opens the PR. Always use this instead of gh CLI or raw git.",
|
|
2551
3212
|
{
|
|
2552
|
-
title:
|
|
2553
|
-
body:
|
|
2554
|
-
branch:
|
|
3213
|
+
title: z6.string().describe("The PR title"),
|
|
3214
|
+
body: z6.string().describe("The PR description/body in markdown"),
|
|
3215
|
+
branch: z6.string().optional().describe(
|
|
2555
3216
|
"The head branch name for the PR. If the task doesn't have a branch set, this will be used. Defaults to the task's existing branch."
|
|
2556
3217
|
),
|
|
2557
|
-
baseBranch:
|
|
3218
|
+
baseBranch: z6.string().optional().describe(
|
|
2558
3219
|
"The base branch to target for the PR (e.g. 'main', 'develop'). Defaults to the project's configured dev branch."
|
|
2559
3220
|
),
|
|
2560
|
-
commitMessage:
|
|
3221
|
+
commitMessage: z6.string().optional().describe(
|
|
2561
3222
|
"Commit message for staging uncommitted changes. If not provided, a default message based on the PR title will be used."
|
|
2562
3223
|
)
|
|
2563
3224
|
},
|
|
@@ -2633,9 +3294,9 @@ Troubleshooting:
|
|
|
2633
3294
|
function buildAddDependencyTool(connection) {
|
|
2634
3295
|
return defineTool(
|
|
2635
3296
|
"add_dependency",
|
|
2636
|
-
"Add a blocking dependency \u2014 this task cannot start until the named task is merged to dev.
|
|
3297
|
+
"Add a blocking dependency \u2014 this task cannot start until the named task is merged to dev. For post-task follow-ups use create_follow_up_task instead.",
|
|
2637
3298
|
{
|
|
2638
|
-
depends_on_slug_or_id:
|
|
3299
|
+
depends_on_slug_or_id: z6.string().describe("Slug or ID of the task this task depends on")
|
|
2639
3300
|
},
|
|
2640
3301
|
async ({ depends_on_slug_or_id }) => {
|
|
2641
3302
|
try {
|
|
@@ -2657,7 +3318,7 @@ function buildRemoveDependencyTool(connection) {
|
|
|
2657
3318
|
"remove_dependency",
|
|
2658
3319
|
"Remove a previously added dependency from this task. When to use: the dependency was added in error or is no longer relevant. Returns: confirmation string.",
|
|
2659
3320
|
{
|
|
2660
|
-
depends_on_slug_or_id:
|
|
3321
|
+
depends_on_slug_or_id: z6.string().describe("Slug or ID of the task to remove as dependency")
|
|
2661
3322
|
},
|
|
2662
3323
|
async ({ depends_on_slug_or_id }) => {
|
|
2663
3324
|
try {
|
|
@@ -2677,12 +3338,12 @@ function buildRemoveDependencyTool(connection) {
|
|
|
2677
3338
|
function buildCreateFollowUpTaskTool(connection) {
|
|
2678
3339
|
return defineTool(
|
|
2679
3340
|
"create_follow_up_task",
|
|
2680
|
-
"Create a follow-up task that depends on the current task.
|
|
3341
|
+
"Create a follow-up task that depends on the current task. Use for out-of-scope work or cleanup that should land after this task merges. For blockers use add_dependency.",
|
|
2681
3342
|
{
|
|
2682
|
-
title:
|
|
2683
|
-
description:
|
|
2684
|
-
plan:
|
|
2685
|
-
story_point_value:
|
|
3343
|
+
title: z6.string().describe("Follow-up task title"),
|
|
3344
|
+
description: z6.string().optional().describe("Brief description of the follow-up work"),
|
|
3345
|
+
plan: z6.string().optional().describe("Implementation plan if known"),
|
|
3346
|
+
story_point_value: z6.number().optional().describe("Story point estimate (1=Common, 2=Magic, 3=Rare, 5=Unique)")
|
|
2686
3347
|
},
|
|
2687
3348
|
async ({ title, description, plan, story_point_value }) => {
|
|
2688
3349
|
try {
|
|
@@ -2707,13 +3368,13 @@ function buildCreateFollowUpTaskTool(connection) {
|
|
|
2707
3368
|
function buildCreateSuggestionTool(connection) {
|
|
2708
3369
|
return defineTool(
|
|
2709
3370
|
"create_suggestion",
|
|
2710
|
-
"Suggest a feature, improvement, rule, or idea for the project.
|
|
3371
|
+
"Suggest a feature, improvement, rule, or idea for the project. Duplicates are deduped and your upvote is recorded. For actionable work on this task open a follow-up task.",
|
|
2711
3372
|
{
|
|
2712
|
-
title:
|
|
2713
|
-
description:
|
|
3373
|
+
title: z6.string().describe("Short title for the suggestion"),
|
|
3374
|
+
description: z6.string().optional().describe(
|
|
2714
3375
|
"1-2 sentence description of what should change and why. Keep concise and project-focused."
|
|
2715
3376
|
),
|
|
2716
|
-
tag_names:
|
|
3377
|
+
tag_names: z6.array(z6.string()).optional().describe("Tag names to categorize the suggestion")
|
|
2717
3378
|
},
|
|
2718
3379
|
async ({ title, description, tag_names }) => {
|
|
2719
3380
|
try {
|
|
@@ -2740,10 +3401,10 @@ function buildCreateSuggestionTool(connection) {
|
|
|
2740
3401
|
function buildVoteSuggestionTool(connection) {
|
|
2741
3402
|
return defineTool(
|
|
2742
3403
|
"vote_suggestion",
|
|
2743
|
-
"Vote +1 or -1 on a project suggestion.
|
|
3404
|
+
"Vote +1 or -1 on a project suggestion. Use to express support or disagreement with a specific suggestion returned by get_suggestions.",
|
|
2744
3405
|
{
|
|
2745
|
-
suggestion_id:
|
|
2746
|
-
value:
|
|
3406
|
+
suggestion_id: z6.string().describe("The suggestion ID to vote on"),
|
|
3407
|
+
value: z6.number().refine((v) => v === 1 || v === -1, { message: "Value must be 1 or -1" }).describe("+1 to upvote, -1 to downvote")
|
|
2747
3408
|
},
|
|
2748
3409
|
async ({ suggestion_id, value }) => {
|
|
2749
3410
|
try {
|
|
@@ -2784,15 +3445,15 @@ function buildCommonTools(connection, config) {
|
|
|
2784
3445
|
}
|
|
2785
3446
|
|
|
2786
3447
|
// src/tools/pm-tools.ts
|
|
2787
|
-
import { z as
|
|
3448
|
+
import { z as z7 } from "zod";
|
|
2788
3449
|
var SP_DESCRIPTION = "Story point value (1=Common, 2=Magic, 3=Rare, 5=Unique)";
|
|
2789
3450
|
function buildUpdateTaskTool(connection) {
|
|
2790
3451
|
return defineTool(
|
|
2791
|
-
"
|
|
2792
|
-
"Save the finalized plan and/or description to the current task.
|
|
3452
|
+
"update_task_plan",
|
|
3453
|
+
"Save the finalized plan and/or description to the current task. Use in Plan mode after alignment. For children use update_subtask; for title/tags/PR use update_task_properties.",
|
|
2793
3454
|
{
|
|
2794
|
-
plan:
|
|
2795
|
-
description:
|
|
3455
|
+
plan: z7.string().optional().describe("The task plan in markdown"),
|
|
3456
|
+
description: z7.string().optional().describe("Updated task description")
|
|
2796
3457
|
},
|
|
2797
3458
|
async ({ plan, description }) => {
|
|
2798
3459
|
try {
|
|
@@ -2811,13 +3472,13 @@ function buildUpdateTaskTool(connection) {
|
|
|
2811
3472
|
function buildCreateSubtaskTool(connection) {
|
|
2812
3473
|
return defineTool(
|
|
2813
3474
|
"create_subtask",
|
|
2814
|
-
"Create a subtask under the current parent task.
|
|
3475
|
+
"Create a subtask under the current parent task. Use when breaking a complex parent into smaller pieces during planning. For post-task follow-ups use create_follow_up_task.",
|
|
2815
3476
|
{
|
|
2816
|
-
title:
|
|
2817
|
-
description:
|
|
2818
|
-
plan:
|
|
2819
|
-
ordinal:
|
|
2820
|
-
storyPointValue:
|
|
3477
|
+
title: z7.string().describe("Subtask title"),
|
|
3478
|
+
description: z7.string().optional().describe("Brief description"),
|
|
3479
|
+
plan: z7.string().optional().describe("Implementation plan in markdown"),
|
|
3480
|
+
ordinal: z7.number().optional().describe("Step/order number (0-based)"),
|
|
3481
|
+
storyPointValue: z7.number().optional().describe(SP_DESCRIPTION)
|
|
2821
3482
|
},
|
|
2822
3483
|
async ({ title, description, plan, ordinal, storyPointValue }) => {
|
|
2823
3484
|
try {
|
|
@@ -2841,14 +3502,14 @@ function buildCreateSubtaskTool(connection) {
|
|
|
2841
3502
|
function buildUpdateSubtaskTool(connection) {
|
|
2842
3503
|
return defineTool(
|
|
2843
3504
|
"update_subtask",
|
|
2844
|
-
"Update an existing subtask's fields (title, description, plan, ordinal, storyPointValue).
|
|
3505
|
+
"Update an existing subtask's fields (title, description, plan, ordinal, storyPointValue). Use when refining a child's plan or reordering. For the current task use update_task_plan.",
|
|
2845
3506
|
{
|
|
2846
|
-
subtaskId:
|
|
2847
|
-
title:
|
|
2848
|
-
description:
|
|
2849
|
-
plan:
|
|
2850
|
-
ordinal:
|
|
2851
|
-
storyPointValue:
|
|
3507
|
+
subtaskId: z7.string().describe("The subtask ID to update"),
|
|
3508
|
+
title: z7.string().optional(),
|
|
3509
|
+
description: z7.string().optional(),
|
|
3510
|
+
plan: z7.string().optional(),
|
|
3511
|
+
ordinal: z7.number().optional(),
|
|
3512
|
+
storyPointValue: z7.number().optional().describe(SP_DESCRIPTION)
|
|
2852
3513
|
},
|
|
2853
3514
|
async ({ subtaskId, title, description, plan, storyPointValue }) => {
|
|
2854
3515
|
try {
|
|
@@ -2871,7 +3532,7 @@ function buildDeleteSubtaskTool(connection) {
|
|
|
2871
3532
|
return defineTool(
|
|
2872
3533
|
"delete_subtask",
|
|
2873
3534
|
"Delete a subtask by id. When to use: a subtask was created in error or is no longer needed. Returns: confirmation string.",
|
|
2874
|
-
{ subtaskId:
|
|
3535
|
+
{ subtaskId: z7.string().describe("The subtask ID to delete") },
|
|
2875
3536
|
async ({ subtaskId }) => {
|
|
2876
3537
|
try {
|
|
2877
3538
|
await connection.call("deleteSubtask", {
|
|
@@ -2888,7 +3549,7 @@ function buildDeleteSubtaskTool(connection) {
|
|
|
2888
3549
|
function buildListSubtasksTool(connection) {
|
|
2889
3550
|
return defineTool(
|
|
2890
3551
|
"list_subtasks",
|
|
2891
|
-
"List all subtasks under the current parent task.
|
|
3552
|
+
"List all subtasks under the current parent task. Use to coordinate child work \u2014 check who is running, ready for review, or blocked. For non-child tasks use get_task.",
|
|
2892
3553
|
{},
|
|
2893
3554
|
async () => {
|
|
2894
3555
|
try {
|
|
@@ -2907,9 +3568,9 @@ function buildPackTools(connection) {
|
|
|
2907
3568
|
return [
|
|
2908
3569
|
defineTool(
|
|
2909
3570
|
"start_child_cloud_build",
|
|
2910
|
-
"Start a cloud build (codespace) for a child task. Preconditions:
|
|
3571
|
+
"Start a cloud build (codespace) for a child task. Preconditions: child is in Open status, has a story point value, and has an agent assigned.",
|
|
2911
3572
|
{
|
|
2912
|
-
childTaskId:
|
|
3573
|
+
childTaskId: z7.string().describe("The child task ID to start a cloud build for")
|
|
2913
3574
|
},
|
|
2914
3575
|
async ({ childTaskId }) => {
|
|
2915
3576
|
try {
|
|
@@ -2927,9 +3588,9 @@ function buildPackTools(connection) {
|
|
|
2927
3588
|
),
|
|
2928
3589
|
defineTool(
|
|
2929
3590
|
"stop_child_build",
|
|
2930
|
-
"Send a graceful stop signal to a running child build's agent.
|
|
3591
|
+
"Send a graceful stop signal to a running child build's agent. Not a force-kill \u2014 the agent may take a moment to wind down.",
|
|
2931
3592
|
{
|
|
2932
|
-
childTaskId:
|
|
3593
|
+
childTaskId: z7.string().describe("The child task ID whose build should be stopped")
|
|
2933
3594
|
},
|
|
2934
3595
|
async ({ childTaskId }) => {
|
|
2935
3596
|
try {
|
|
@@ -2947,9 +3608,9 @@ function buildPackTools(connection) {
|
|
|
2947
3608
|
),
|
|
2948
3609
|
defineTool(
|
|
2949
3610
|
"approve_and_merge_pr",
|
|
2950
|
-
"Approve and merge a child task's PR. Preconditions: child
|
|
3611
|
+
"Approve and merge a child task's PR. Preconditions: child in ReviewPR. Returns { merged }: true = merged (status\u2192ReviewDev); false = automerge queued, wait for ReviewDev.",
|
|
2951
3612
|
{
|
|
2952
|
-
childTaskId:
|
|
3613
|
+
childTaskId: z7.string().describe("The child task ID whose PR should be approved and merged")
|
|
2953
3614
|
},
|
|
2954
3615
|
async ({ childTaskId }) => {
|
|
2955
3616
|
try {
|
|
@@ -2987,7 +3648,7 @@ function buildPmTools(connection, options) {
|
|
|
2987
3648
|
}
|
|
2988
3649
|
|
|
2989
3650
|
// src/tools/discovery-tools.ts
|
|
2990
|
-
import { z as
|
|
3651
|
+
import { z as z8 } from "zod";
|
|
2991
3652
|
var SP_DESCRIPTION2 = "Story point value (1=Common, 2=Magic, 3=Rare, 5=Unique)";
|
|
2992
3653
|
function buildDiscoveryTools(connection) {
|
|
2993
3654
|
return [
|
|
@@ -2995,11 +3656,11 @@ function buildDiscoveryTools(connection) {
|
|
|
2995
3656
|
"update_task_properties",
|
|
2996
3657
|
"Set one or more task properties in a single call. All fields are optional \u2014 only include the fields you want to update.",
|
|
2997
3658
|
{
|
|
2998
|
-
title:
|
|
2999
|
-
storyPointValue:
|
|
3000
|
-
tagNames:
|
|
3001
|
-
githubPRUrl:
|
|
3002
|
-
githubBranch:
|
|
3659
|
+
title: z8.string().optional().describe("The new task title"),
|
|
3660
|
+
storyPointValue: z8.number().optional().describe(SP_DESCRIPTION2),
|
|
3661
|
+
tagNames: z8.array(z8.string()).optional().describe("Array of tag names to assign"),
|
|
3662
|
+
githubPRUrl: z8.string().url().optional().describe("GitHub pull request URL to link to this task"),
|
|
3663
|
+
githubBranch: z8.string().optional().describe("Set the GitHub branch name for this task (e.g. 'conveyor/my-feature-abc123')")
|
|
3003
3664
|
},
|
|
3004
3665
|
async ({ title, storyPointValue, tagNames, githubPRUrl, githubBranch }) => {
|
|
3005
3666
|
try {
|
|
@@ -3030,14 +3691,14 @@ function buildDiscoveryTools(connection) {
|
|
|
3030
3691
|
}
|
|
3031
3692
|
|
|
3032
3693
|
// src/tools/code-review-tools.ts
|
|
3033
|
-
import { z as
|
|
3694
|
+
import { z as z9 } from "zod";
|
|
3034
3695
|
function buildCodeReviewTools(connection) {
|
|
3035
3696
|
return [
|
|
3036
3697
|
defineTool(
|
|
3037
3698
|
"approve_code_review",
|
|
3038
|
-
"Approve the code review and exit.
|
|
3699
|
+
"Approve the code review and exit. Use when the diff passes all review criteria. Takes only a summary \u2014 for changes, use request_code_changes with a structured issues[] list.",
|
|
3039
3700
|
{
|
|
3040
|
-
summary:
|
|
3701
|
+
summary: z9.string().describe("Brief summary of what was reviewed and why it looks good")
|
|
3041
3702
|
},
|
|
3042
3703
|
async ({ summary }) => {
|
|
3043
3704
|
const content = `**Code Review: Approved** :white_check_mark:
|
|
@@ -3058,17 +3719,17 @@ ${summary}`;
|
|
|
3058
3719
|
),
|
|
3059
3720
|
defineTool(
|
|
3060
3721
|
"request_code_changes",
|
|
3061
|
-
"Request changes during code review and exit.
|
|
3722
|
+
"Request changes during code review and exit. Use when substantive issues must be fixed before merge. Each issue: { file, line?, severity: critical|major|minor, description }.",
|
|
3062
3723
|
{
|
|
3063
|
-
issues:
|
|
3064
|
-
|
|
3065
|
-
file:
|
|
3066
|
-
line:
|
|
3067
|
-
severity:
|
|
3068
|
-
description:
|
|
3724
|
+
issues: z9.array(
|
|
3725
|
+
z9.object({
|
|
3726
|
+
file: z9.string().describe("File path where the issue was found"),
|
|
3727
|
+
line: z9.number().optional().describe("Line number (if applicable)"),
|
|
3728
|
+
severity: z9.enum(["critical", "major", "minor"]).describe("Issue severity"),
|
|
3729
|
+
description: z9.string().describe("What is wrong and how to fix it")
|
|
3069
3730
|
})
|
|
3070
3731
|
).describe("List of issues found during review"),
|
|
3071
|
-
summary:
|
|
3732
|
+
summary: z9.string().describe("Brief overall summary of the review findings")
|
|
3072
3733
|
},
|
|
3073
3734
|
async ({ issues, summary }) => {
|
|
3074
3735
|
const issueLines = issues.map((issue) => {
|
|
@@ -3098,10 +3759,10 @@ ${issueLines}`;
|
|
|
3098
3759
|
}
|
|
3099
3760
|
|
|
3100
3761
|
// src/tools/debug-tools.ts
|
|
3101
|
-
import { z as
|
|
3762
|
+
import { z as z12 } from "zod";
|
|
3102
3763
|
|
|
3103
3764
|
// src/tools/telemetry-tools.ts
|
|
3104
|
-
import { z as
|
|
3765
|
+
import { z as z10 } from "zod";
|
|
3105
3766
|
|
|
3106
3767
|
// src/debug/telemetry-injector.ts
|
|
3107
3768
|
var BUFFER_SIZE = 200;
|
|
@@ -3494,14 +4155,14 @@ function formatError(error) {
|
|
|
3494
4155
|
function buildGetTelemetryTool(manager) {
|
|
3495
4156
|
return defineTool(
|
|
3496
4157
|
"debug_get_telemetry",
|
|
3497
|
-
"Query structured telemetry events (HTTP
|
|
4158
|
+
"Query structured telemetry events (HTTP, DB, Socket.IO, errors) captured from the dev server. Returns filtered structured data instead of raw logs.",
|
|
3498
4159
|
{
|
|
3499
|
-
type:
|
|
3500
|
-
urlPattern:
|
|
3501
|
-
minDuration:
|
|
3502
|
-
errorOnly:
|
|
3503
|
-
since:
|
|
3504
|
-
limit:
|
|
4160
|
+
type: z10.enum(["http", "db", "socket", "error"]).optional().describe("Filter by event type"),
|
|
4161
|
+
urlPattern: z10.string().optional().describe("Regex pattern to filter HTTP events by URL"),
|
|
4162
|
+
minDuration: z10.number().optional().describe("Minimum duration in ms \u2014 only return events slower than this"),
|
|
4163
|
+
errorOnly: z10.boolean().optional().describe("Only return error events and HTTP 4xx/5xx responses"),
|
|
4164
|
+
since: z10.number().optional().describe("Only return events after this timestamp (ms since epoch)"),
|
|
4165
|
+
limit: z10.number().optional().describe("Max events to return (default: 20, from most recent)")
|
|
3505
4166
|
},
|
|
3506
4167
|
async ({ type, urlPattern, minDuration, errorOnly, since, limit }) => {
|
|
3507
4168
|
const clientOrErr = requireDebugClient(manager);
|
|
@@ -3571,7 +4232,7 @@ function buildTelemetryTools(manager) {
|
|
|
3571
4232
|
}
|
|
3572
4233
|
|
|
3573
4234
|
// src/tools/client-debug-tools.ts
|
|
3574
|
-
import { z as
|
|
4235
|
+
import { z as z11 } from "zod";
|
|
3575
4236
|
function requirePlaywrightClient(manager) {
|
|
3576
4237
|
if (!manager.isClientDebugMode()) {
|
|
3577
4238
|
return "Client debug mode is not active. Use debug_enter_mode with clientSide: true first.";
|
|
@@ -3589,13 +4250,13 @@ function buildClientBreakpointTools(manager) {
|
|
|
3589
4250
|
return [
|
|
3590
4251
|
defineTool(
|
|
3591
4252
|
"debug_set_client_breakpoint",
|
|
3592
|
-
"Set a breakpoint in client-side code running in
|
|
4253
|
+
"Set a breakpoint in client-side code running in headless Chromium. V8 resolves source maps automatically \u2014 use original .tsx/.ts file paths.",
|
|
3593
4254
|
{
|
|
3594
|
-
file:
|
|
4255
|
+
file: z11.string().describe(
|
|
3595
4256
|
"Original source file path (e.g., src/components/App.tsx) \u2014 source maps resolve automatically"
|
|
3596
4257
|
),
|
|
3597
|
-
line:
|
|
3598
|
-
condition:
|
|
4258
|
+
line: z11.number().describe("Line number (1-based) in the original source file"),
|
|
4259
|
+
condition: z11.string().optional().describe("JavaScript condition expression \u2014 breakpoint only triggers when truthy")
|
|
3599
4260
|
},
|
|
3600
4261
|
async ({ file, line, condition }) => {
|
|
3601
4262
|
const clientOrErr = requirePlaywrightClient(manager);
|
|
@@ -3617,7 +4278,7 @@ Breakpoint ID: ${breakpointId}${sourceMapNote}`
|
|
|
3617
4278
|
"debug_remove_client_breakpoint",
|
|
3618
4279
|
"Remove a previously set client-side breakpoint by its ID.",
|
|
3619
4280
|
{
|
|
3620
|
-
breakpointId:
|
|
4281
|
+
breakpointId: z11.string().describe("The breakpoint ID returned by debug_set_client_breakpoint")
|
|
3621
4282
|
},
|
|
3622
4283
|
async ({ breakpointId }) => {
|
|
3623
4284
|
const clientOrErr = requirePlaywrightClient(manager);
|
|
@@ -3652,7 +4313,7 @@ function buildClientInspectionTools(manager) {
|
|
|
3652
4313
|
return [
|
|
3653
4314
|
defineTool(
|
|
3654
4315
|
"debug_inspect_client_paused",
|
|
3655
|
-
"When the client
|
|
4316
|
+
"When the client (browser) debugger is paused, returns call stack and local variables. For server pauses use debug_inspect_paused. Queued hits returned if already resumed.",
|
|
3656
4317
|
{},
|
|
3657
4318
|
async () => {
|
|
3658
4319
|
const clientOrErr = requirePlaywrightClient(manager);
|
|
@@ -3695,10 +4356,10 @@ ${JSON.stringify(queuedHits, null, 2)}`
|
|
|
3695
4356
|
),
|
|
3696
4357
|
defineTool(
|
|
3697
4358
|
"debug_evaluate_client",
|
|
3698
|
-
"Evaluate a JavaScript expression in the browser context. When paused
|
|
4359
|
+
"Evaluate a JavaScript expression in the browser context. When paused, runs in the paused frame's scope; otherwise the page's global scope. Side effects execute \u2014 prefer read-only.",
|
|
3699
4360
|
{
|
|
3700
|
-
expression:
|
|
3701
|
-
frameIndex:
|
|
4361
|
+
expression: z11.string().describe("JavaScript expression to evaluate in the browser context"),
|
|
4362
|
+
frameIndex: z11.number().optional().describe("Call stack frame index (0 = top frame). Defaults to the top frame.")
|
|
3702
4363
|
},
|
|
3703
4364
|
async ({ expression, frameIndex }) => {
|
|
3704
4365
|
const clientOrErr = requirePlaywrightClient(manager);
|
|
@@ -3769,9 +4430,9 @@ function buildClientInteractionTools(manager) {
|
|
|
3769
4430
|
),
|
|
3770
4431
|
defineTool(
|
|
3771
4432
|
"debug_navigate_client",
|
|
3772
|
-
"Navigate the headless browser to a URL.
|
|
4433
|
+
"Navigate the headless browser to a URL. Waits for domcontentloaded (Playwright's default ~30s timeout applies).",
|
|
3773
4434
|
{
|
|
3774
|
-
url:
|
|
4435
|
+
url: z11.string().describe("URL to navigate to (e.g., http://localhost:3000/dashboard)")
|
|
3775
4436
|
},
|
|
3776
4437
|
async ({ url }) => {
|
|
3777
4438
|
const clientOrErr = requirePlaywrightClient(manager);
|
|
@@ -3786,9 +4447,9 @@ function buildClientInteractionTools(manager) {
|
|
|
3786
4447
|
),
|
|
3787
4448
|
defineTool(
|
|
3788
4449
|
"debug_click_client",
|
|
3789
|
-
"Click an element in the headless browser by CSS selector.
|
|
4450
|
+
"Click an element in the headless browser by CSS selector. Playwright auto-waits for visibility/stability/enabled up to 10s \u2014 a miss throws with a failure message.",
|
|
3790
4451
|
{
|
|
3791
|
-
selector:
|
|
4452
|
+
selector: z11.string().describe(
|
|
3792
4453
|
"CSS selector of the element to click (e.g., 'button.submit', '#login-form input[type=submit]')"
|
|
3793
4454
|
)
|
|
3794
4455
|
},
|
|
@@ -3810,8 +4471,8 @@ function buildClientConsoleTool(manager) {
|
|
|
3810
4471
|
"debug_get_client_console",
|
|
3811
4472
|
"Get console messages captured from the headless browser. Includes console.log, warn, error, etc.",
|
|
3812
4473
|
{
|
|
3813
|
-
level:
|
|
3814
|
-
limit:
|
|
4474
|
+
level: z11.string().optional().describe("Filter by console level: log, warn, error, info, debug"),
|
|
4475
|
+
limit: z11.number().optional().describe("Maximum number of recent messages to return (default: all)")
|
|
3815
4476
|
},
|
|
3816
4477
|
// oxlint-disable-next-line require-await
|
|
3817
4478
|
async ({ level, limit }) => {
|
|
@@ -3838,8 +4499,8 @@ function buildClientNetworkTool(manager) {
|
|
|
3838
4499
|
"debug_get_client_network",
|
|
3839
4500
|
"Get network requests captured from the headless browser. Shows URLs, methods, status codes, and timing.",
|
|
3840
4501
|
{
|
|
3841
|
-
filter:
|
|
3842
|
-
limit:
|
|
4502
|
+
filter: z11.string().optional().describe("Regex pattern to filter requests by URL"),
|
|
4503
|
+
limit: z11.number().optional().describe("Maximum number of recent requests to return (default: all)")
|
|
3843
4504
|
},
|
|
3844
4505
|
// oxlint-disable-next-line require-await
|
|
3845
4506
|
async ({ filter, limit }) => {
|
|
@@ -3867,7 +4528,7 @@ function buildClientErrorsTool(manager) {
|
|
|
3867
4528
|
"debug_get_client_errors",
|
|
3868
4529
|
"Get uncaught errors captured from the headless browser. Includes error messages and source-mapped stack traces.",
|
|
3869
4530
|
{
|
|
3870
|
-
limit:
|
|
4531
|
+
limit: z11.number().optional().describe("Maximum number of recent errors to return (default: all)")
|
|
3871
4532
|
},
|
|
3872
4533
|
// oxlint-disable-next-line require-await
|
|
3873
4534
|
async ({ limit }) => {
|
|
@@ -3959,14 +4620,14 @@ function buildDebugLifecycleTools(manager) {
|
|
|
3959
4620
|
return [
|
|
3960
4621
|
defineTool(
|
|
3961
4622
|
"debug_enter_mode",
|
|
3962
|
-
"Activate debug mode.
|
|
4623
|
+
"Activate debug mode. Default: server-only (Node --inspect via CDP). Set clientSide=true (previewUrl required) or both flags for full-stack (adds headless Chromium via Playwright).",
|
|
3963
4624
|
{
|
|
3964
|
-
hypothesis:
|
|
3965
|
-
serverSide:
|
|
4625
|
+
hypothesis: z12.string().optional().describe("Your hypothesis about the bug \u2014 helps track debugging intent"),
|
|
4626
|
+
serverSide: z12.boolean().optional().describe(
|
|
3966
4627
|
"Enable server-side Node.js debugging (default: true if clientSide is not set)"
|
|
3967
4628
|
),
|
|
3968
|
-
clientSide:
|
|
3969
|
-
previewUrl:
|
|
4629
|
+
clientSide: z12.boolean().optional().describe("Enable client-side browser debugging via headless Chromium + Playwright"),
|
|
4630
|
+
previewUrl: z12.string().optional().describe(
|
|
3970
4631
|
"Preview URL for client-side debugging (e.g., http://localhost:3000). Required when clientSide is true."
|
|
3971
4632
|
)
|
|
3972
4633
|
},
|
|
@@ -4002,9 +4663,9 @@ function buildBreakpointTools(manager) {
|
|
|
4002
4663
|
"debug_set_breakpoint",
|
|
4003
4664
|
"Set a breakpoint at the specified file and line number. Optionally provide a condition expression that must evaluate to true for the breakpoint to pause execution.",
|
|
4004
4665
|
{
|
|
4005
|
-
file:
|
|
4006
|
-
line:
|
|
4007
|
-
condition:
|
|
4666
|
+
file: z12.string().describe("Absolute or relative file path to set the breakpoint in"),
|
|
4667
|
+
line: z12.number().describe("Line number (1-based) to set the breakpoint on"),
|
|
4668
|
+
condition: z12.string().optional().describe("JavaScript condition expression \u2014 breakpoint only triggers when truthy")
|
|
4008
4669
|
},
|
|
4009
4670
|
async ({ file, line, condition }) => {
|
|
4010
4671
|
const clientOrErr = requireDebugClient2(manager);
|
|
@@ -4026,7 +4687,7 @@ Breakpoint ID: ${breakpointId}`
|
|
|
4026
4687
|
"debug_remove_breakpoint",
|
|
4027
4688
|
"Remove a previously set breakpoint by its ID.",
|
|
4028
4689
|
{
|
|
4029
|
-
breakpointId:
|
|
4690
|
+
breakpointId: z12.string().describe("The breakpoint ID returned by debug_set_breakpoint")
|
|
4030
4691
|
},
|
|
4031
4692
|
async ({ breakpointId }) => {
|
|
4032
4693
|
const clientOrErr = requireDebugClient2(manager);
|
|
@@ -4105,10 +4766,10 @@ ${JSON.stringify(queuedHits, null, 2)}`
|
|
|
4105
4766
|
),
|
|
4106
4767
|
defineTool(
|
|
4107
4768
|
"debug_evaluate",
|
|
4108
|
-
"Evaluate a JavaScript expression server-side in the Node process. When paused
|
|
4769
|
+
"Evaluate a JavaScript expression server-side in the Node process. When paused, runs in the frame's scope (frameIndex selects frame). Side effects execute \u2014 prefer read-only.",
|
|
4109
4770
|
{
|
|
4110
|
-
expression:
|
|
4111
|
-
frameIndex:
|
|
4771
|
+
expression: z12.string().describe("The JavaScript expression to evaluate"),
|
|
4772
|
+
frameIndex: z12.number().optional().describe("Call stack frame index (0 = top frame). Defaults to the top frame.")
|
|
4112
4773
|
},
|
|
4113
4774
|
async ({ expression, frameIndex }) => {
|
|
4114
4775
|
const clientOrErr = requireDebugClient2(manager);
|
|
@@ -4134,14 +4795,14 @@ function buildProbeManagementTools(manager) {
|
|
|
4134
4795
|
return [
|
|
4135
4796
|
defineTool(
|
|
4136
4797
|
"debug_add_probe",
|
|
4137
|
-
"Add a debug probe at a
|
|
4798
|
+
"Add a debug probe at a code location. Captures expression values each time the line executes, without pausing or modifying source. Auto-cleaned on debug exit.",
|
|
4138
4799
|
{
|
|
4139
|
-
file:
|
|
4140
|
-
line:
|
|
4141
|
-
expressions:
|
|
4800
|
+
file: z12.string().describe("File path to probe"),
|
|
4801
|
+
line: z12.number().describe("Line number (1-based) to probe"),
|
|
4802
|
+
expressions: z12.array(z12.string()).describe(
|
|
4142
4803
|
'JavaScript expressions to capture when the line executes (e.g., ["req.params.id", "user.role"])'
|
|
4143
4804
|
),
|
|
4144
|
-
label:
|
|
4805
|
+
label: z12.string().optional().describe("Optional label for this probe (defaults to file:line)")
|
|
4145
4806
|
},
|
|
4146
4807
|
async ({ file, line, expressions, label }) => {
|
|
4147
4808
|
const clientOrErr = requireDebugClient2(manager);
|
|
@@ -4166,7 +4827,7 @@ Trigger the code path, then use debug_get_probe_results to see captured values.`
|
|
|
4166
4827
|
"debug_remove_probe",
|
|
4167
4828
|
"Remove a previously set debug probe by its ID.",
|
|
4168
4829
|
{
|
|
4169
|
-
probeId:
|
|
4830
|
+
probeId: z12.string().describe("The probe ID returned by debug_add_probe")
|
|
4170
4831
|
},
|
|
4171
4832
|
async ({ probeId }) => {
|
|
4172
4833
|
const clientOrErr = requireDebugClient2(manager);
|
|
@@ -4204,11 +4865,11 @@ function buildProbeResultTools(manager) {
|
|
|
4204
4865
|
return [
|
|
4205
4866
|
defineTool(
|
|
4206
4867
|
"debug_get_probe_results",
|
|
4207
|
-
"Fetch captured probe hit data.
|
|
4868
|
+
"Fetch captured probe hit data. Filter by label (wins) or probeId. Returns grouped text with per-probe hit count, timestamps, and captured expression values.",
|
|
4208
4869
|
{
|
|
4209
|
-
probeId:
|
|
4210
|
-
label:
|
|
4211
|
-
limit:
|
|
4870
|
+
probeId: z12.string().optional().describe("Filter results by probe ID (resolves to its label)"),
|
|
4871
|
+
label: z12.string().optional().describe("Filter results by probe label"),
|
|
4872
|
+
limit: z12.number().optional().describe("Maximum number of recent hits to return (default: all)")
|
|
4212
4873
|
},
|
|
4213
4874
|
async ({ probeId, label, limit }) => {
|
|
4214
4875
|
const clientOrErr = requireDebugClient2(manager);
|
|
@@ -4802,7 +5463,7 @@ async function processEvents(events, context, host) {
|
|
|
4802
5463
|
// src/execution/task-property-utils.ts
|
|
4803
5464
|
function collectMissingProps(taskProps) {
|
|
4804
5465
|
const missing = [];
|
|
4805
|
-
if (!taskProps.plan?.trim()) missing.push("plan (save via
|
|
5466
|
+
if (!taskProps.plan?.trim()) missing.push("plan (save via update_task_plan)");
|
|
4806
5467
|
if (!taskProps.storyPointId) missing.push("story points (use update_task_properties)");
|
|
4807
5468
|
if (!taskProps.title || taskProps.title === "Untitled")
|
|
4808
5469
|
missing.push("title (use update_task_properties)");
|
|
@@ -4811,7 +5472,31 @@ function collectMissingProps(taskProps) {
|
|
|
4811
5472
|
|
|
4812
5473
|
// src/execution/tool-access.ts
|
|
4813
5474
|
var PM_PLAN_FILE_TOOLS = /* @__PURE__ */ new Set(["Write", "Edit", "MultiEdit"]);
|
|
4814
|
-
var
|
|
5475
|
+
var DESTRUCTIVE_PATTERNS = [
|
|
5476
|
+
{
|
|
5477
|
+
name: "git push --force (without --force-with-lease)",
|
|
5478
|
+
re: /git\s+push\s+(?:-f\b|--force(?!-with-lease))/
|
|
5479
|
+
},
|
|
5480
|
+
{ name: "git push --delete", re: /git\s+push\s+(?:-d\b|--delete\b)/ },
|
|
5481
|
+
{ name: "git reset --hard", re: /git\s+reset\s+--hard\b/ },
|
|
5482
|
+
{
|
|
5483
|
+
name: "rm -rf /",
|
|
5484
|
+
re: /rm\s+(?:-[a-zA-Z]*r[a-zA-Z]*f|-[a-zA-Z]*f[a-zA-Z]*r|--recursive\s+--force)\s+\/(?!\S)/
|
|
5485
|
+
},
|
|
5486
|
+
{ name: "sudo rm", re: /\bsudo\s+rm\b/ },
|
|
5487
|
+
{ name: "chmod world-writable", re: /\bchmod\s+(?:-R\s+)?[0-7]*7{2,3}\b/ },
|
|
5488
|
+
{ name: "dd to device", re: /\bdd\s+.*\bof=\/dev\// },
|
|
5489
|
+
{ name: "redirect to block device", re: />\s*\/dev\/(?:sd[a-z]|nvme\d|xvd[a-z])/ },
|
|
5490
|
+
{ name: "mkfs filesystem creation", re: /\bmkfs(?:\.|\s)/ },
|
|
5491
|
+
{ name: "shutdown/poweroff/halt/reboot", re: /\b(?:shutdown|poweroff|halt|reboot)\b/ },
|
|
5492
|
+
{ name: "fork bomb", re: /:\(\)\s*\{\s*:\|\s*:&\s*\}\s*;\s*:/ }
|
|
5493
|
+
];
|
|
5494
|
+
function matchesDestructive(cmd) {
|
|
5495
|
+
for (const { name, re } of DESTRUCTIVE_PATTERNS) {
|
|
5496
|
+
if (re.test(cmd)) return name;
|
|
5497
|
+
}
|
|
5498
|
+
return null;
|
|
5499
|
+
}
|
|
4815
5500
|
function isPlanFile(input) {
|
|
4816
5501
|
const filePath = String(input.file_path ?? input.path ?? "");
|
|
4817
5502
|
return filePath.includes(".claude/plans/");
|
|
@@ -4831,10 +5516,11 @@ function handleDiscoveryToolAccess(toolName, input) {
|
|
|
4831
5516
|
function handleBuildingToolAccess(toolName, input) {
|
|
4832
5517
|
if (toolName === "Bash") {
|
|
4833
5518
|
const cmd = String(input.command ?? "");
|
|
4834
|
-
|
|
5519
|
+
const matched = matchesDestructive(cmd);
|
|
5520
|
+
if (matched) {
|
|
4835
5521
|
return {
|
|
4836
5522
|
behavior: "deny",
|
|
4837
|
-
message:
|
|
5523
|
+
message: `Destructive operation blocked (${matched}). Use safer alternatives.`
|
|
4838
5524
|
};
|
|
4839
5525
|
}
|
|
4840
5526
|
}
|
|
@@ -4849,13 +5535,32 @@ function handleAutoToolAccess(toolName, input, hasExitedPlanMode, isParentTask)
|
|
|
4849
5535
|
}
|
|
4850
5536
|
return { behavior: "allow", updatedInput: input };
|
|
4851
5537
|
}
|
|
5538
|
+
function enforceMissingProps(host, input, missingProps) {
|
|
5539
|
+
if (missingProps.length === 0) return null;
|
|
5540
|
+
if (input.bypassValidation !== true) {
|
|
5541
|
+
return {
|
|
5542
|
+
behavior: "deny",
|
|
5543
|
+
message: [
|
|
5544
|
+
"Cannot exit plan mode. Required task properties are missing:",
|
|
5545
|
+
...missingProps.map((p) => `- ${p}`),
|
|
5546
|
+
"",
|
|
5547
|
+
"Fill these in using MCP tools (e.g. update_task_plan, update_task_properties), then call ExitPlanMode again.",
|
|
5548
|
+
"",
|
|
5549
|
+
"If you have a deliberate reason to proceed without them, you must explicitly bypass validation by calling ExitPlanMode with `bypassValidation: true` as a tool argument. Do not bypass unless the team has asked you to \u2014 it will be surfaced in chat."
|
|
5550
|
+
].join("\n")
|
|
5551
|
+
};
|
|
5552
|
+
}
|
|
5553
|
+
host.connection.postChatMessage(
|
|
5554
|
+
`\u26A0\uFE0F [BYPASS] ExitPlanMode forced through with \`bypassValidation: true\` despite missing required properties: ${missingProps.join(", ")}. Please backfill these.`
|
|
5555
|
+
);
|
|
5556
|
+
return null;
|
|
5557
|
+
}
|
|
4852
5558
|
async function handleExitPlanMode(host, input) {
|
|
4853
5559
|
if (host.hasExitedPlanMode) {
|
|
4854
5560
|
return { behavior: "allow", updatedInput: input };
|
|
4855
5561
|
}
|
|
4856
|
-
host.exitPlanAttempts++;
|
|
4857
5562
|
try {
|
|
4858
|
-
host.syncPlanFile();
|
|
5563
|
+
await host.syncPlanFile();
|
|
4859
5564
|
const taskProps = await host.connection.getTaskProperties();
|
|
4860
5565
|
const missingProps = collectMissingProps(taskProps);
|
|
4861
5566
|
if (host.isParentTask) {
|
|
@@ -4875,30 +5580,22 @@ async function handleExitPlanMode(host, input) {
|
|
|
4875
5580
|
} catch {
|
|
4876
5581
|
}
|
|
4877
5582
|
}
|
|
4878
|
-
|
|
4879
|
-
|
|
4880
|
-
return {
|
|
4881
|
-
behavior: "deny",
|
|
4882
|
-
message: [
|
|
4883
|
-
"Cannot exit plan mode yet. Required task properties are missing:",
|
|
4884
|
-
...missingProps.map((p) => `- ${p}`),
|
|
4885
|
-
"",
|
|
4886
|
-
"Fill these in using MCP tools, then try ExitPlanMode again."
|
|
4887
|
-
].join("\n")
|
|
4888
|
-
};
|
|
4889
|
-
}
|
|
4890
|
-
host.connection.postChatMessage(
|
|
4891
|
-
`\u26A0\uFE0F ExitPlanMode allowed with missing properties: ${missingProps.join(", ")}. Consider backfilling these later.`
|
|
4892
|
-
);
|
|
4893
|
-
}
|
|
5583
|
+
const gate = enforceMissingProps(host, input, missingProps);
|
|
5584
|
+
if (gate) return gate;
|
|
4894
5585
|
if (host.agentMode === "discovery") {
|
|
4895
5586
|
host.hasExitedPlanMode = true;
|
|
4896
5587
|
host.discoveryCompleted = true;
|
|
4897
|
-
|
|
4898
|
-
|
|
4899
|
-
|
|
4900
|
-
|
|
5588
|
+
try {
|
|
5589
|
+
await host.connection.triggerIdentification();
|
|
5590
|
+
} catch (triggerErr) {
|
|
5591
|
+
host.connection.postChatMessage(
|
|
5592
|
+
`Identification trigger encountered an issue (${triggerErr instanceof Error ? triggerErr.message : "unknown error"}). Icon and agent assignment may use fallbacks.`
|
|
5593
|
+
);
|
|
5594
|
+
}
|
|
5595
|
+
await host.connection.postChatMessageAwait(
|
|
5596
|
+
"Planning complete \u2014 awaiting team approval. Icon and agent assignment will be set automatically."
|
|
4901
5597
|
);
|
|
5598
|
+
host.requestStop();
|
|
4902
5599
|
return { behavior: "allow", updatedInput: input };
|
|
4903
5600
|
}
|
|
4904
5601
|
try {
|
|
@@ -5017,6 +5714,65 @@ function buildCanUseTool(host) {
|
|
|
5017
5714
|
};
|
|
5018
5715
|
}
|
|
5019
5716
|
|
|
5717
|
+
// src/execution/redactor.ts
|
|
5718
|
+
var REDACTED = "<redacted>";
|
|
5719
|
+
var BEARER_RE = /\b(Bearer\s+)[A-Za-z0-9_\-.]{20,}/g;
|
|
5720
|
+
var VENDOR_KEY_RE = /\b(?:sk-[a-zA-Z0-9_-]{20,}|ghp_[A-Za-z0-9]{36}|github_pat_[A-Za-z0-9_]{22,}|xoxb-[A-Za-z0-9-]+|xai-[A-Za-z0-9-]{20,})\b/g;
|
|
5721
|
+
var AWS_ACCESS_KEY_RE = /\bAKIA[0-9A-Z]{16}\b/g;
|
|
5722
|
+
var JWT_RE = /\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\b/g;
|
|
5723
|
+
var ENV_SECRET_RE = /^(\s*(?:export\s+)?([A-Z][A-Z0-9_]*(?:TOKEN|SECRET|KEY|PASSWORD|PASS|CREDENTIAL|CREDENTIALS)[A-Z0-9_]*)\s*=\s*)['"]?([^\s'"]+)['"]?/gm;
|
|
5724
|
+
var COOKIE_HEADER_RE = /(Cookie:\s*)[^\r\n]+/gi;
|
|
5725
|
+
var BASIC_AUTH_URL_RE = /(https?:\/\/)([^:@\s/]+):([^@\s]+)@/g;
|
|
5726
|
+
var AWS_SECRET_LINE_RE = /^.*(?:secret|aws_secret).*$/gim;
|
|
5727
|
+
var AWS_SECRET_VALUE_RE = /\b([A-Za-z0-9/+=]{40})\b/g;
|
|
5728
|
+
var SYSTEM_REMINDER_RE = /<system-reminder>[\s\S]*?<\/system-reminder>/gi;
|
|
5729
|
+
function redact(input) {
|
|
5730
|
+
if (!input) return { output: input, redacted: 0 };
|
|
5731
|
+
let count = 0;
|
|
5732
|
+
let output = input;
|
|
5733
|
+
output = output.replace(SYSTEM_REMINDER_RE, () => {
|
|
5734
|
+
count++;
|
|
5735
|
+
return "<!-- stripped injection -->";
|
|
5736
|
+
});
|
|
5737
|
+
output = output.replace(BEARER_RE, (_match, prefix) => {
|
|
5738
|
+
count++;
|
|
5739
|
+
return `${prefix}${REDACTED}`;
|
|
5740
|
+
});
|
|
5741
|
+
output = output.replace(VENDOR_KEY_RE, () => {
|
|
5742
|
+
count++;
|
|
5743
|
+
return REDACTED;
|
|
5744
|
+
});
|
|
5745
|
+
output = output.replace(AWS_ACCESS_KEY_RE, () => {
|
|
5746
|
+
count++;
|
|
5747
|
+
return REDACTED;
|
|
5748
|
+
});
|
|
5749
|
+
output = output.replace(JWT_RE, () => {
|
|
5750
|
+
count++;
|
|
5751
|
+
return REDACTED;
|
|
5752
|
+
});
|
|
5753
|
+
output = output.replace(
|
|
5754
|
+
AWS_SECRET_LINE_RE,
|
|
5755
|
+
(line) => line.replace(AWS_SECRET_VALUE_RE, (match) => {
|
|
5756
|
+
if (/^[a-f0-9]+$/i.test(match)) return match;
|
|
5757
|
+
count++;
|
|
5758
|
+
return REDACTED;
|
|
5759
|
+
})
|
|
5760
|
+
);
|
|
5761
|
+
output = output.replace(ENV_SECRET_RE, (_match, prefix, _key, _value) => {
|
|
5762
|
+
count++;
|
|
5763
|
+
return `${prefix}${REDACTED}`;
|
|
5764
|
+
});
|
|
5765
|
+
output = output.replace(COOKIE_HEADER_RE, (_match, prefix) => {
|
|
5766
|
+
count++;
|
|
5767
|
+
return `${prefix}${REDACTED}`;
|
|
5768
|
+
});
|
|
5769
|
+
output = output.replace(BASIC_AUTH_URL_RE, (_match, scheme, user) => {
|
|
5770
|
+
count++;
|
|
5771
|
+
return `${scheme}${user}:${REDACTED}@`;
|
|
5772
|
+
});
|
|
5773
|
+
return { output, redacted: count };
|
|
5774
|
+
}
|
|
5775
|
+
|
|
5020
5776
|
// src/execution/query-executor.ts
|
|
5021
5777
|
var logger2 = createServiceLogger("QueryExecutor");
|
|
5022
5778
|
var IMAGE_ERROR_PATTERN2 = /Could not process image/i;
|
|
@@ -5029,12 +5785,15 @@ function buildHooks(host) {
|
|
|
5029
5785
|
async (input) => {
|
|
5030
5786
|
if (host.isStopped()) return await Promise.resolve({ continue: false });
|
|
5031
5787
|
if (input.hook_event_name === "PostToolUse") {
|
|
5032
|
-
const
|
|
5788
|
+
const raw = typeof input.tool_response === "string" ? input.tool_response : JSON.stringify(input.tool_response);
|
|
5789
|
+
const { output: redacted, redacted: redactedCount } = redact(raw);
|
|
5790
|
+
const output = redacted.slice(0, 500);
|
|
5033
5791
|
host.connection.sendEvent({
|
|
5034
5792
|
type: "tool_result",
|
|
5035
5793
|
tool: input.tool_name,
|
|
5036
5794
|
output,
|
|
5037
|
-
isError: false
|
|
5795
|
+
isError: false,
|
|
5796
|
+
...redactedCount > 0 ? { redactedCount } : {}
|
|
5038
5797
|
});
|
|
5039
5798
|
host.pendingToolOutputs.push({ tool: input.tool_name, output });
|
|
5040
5799
|
if (input.tool_name === "mcp__conveyor__create_pull_request") {
|
|
@@ -5229,7 +5988,7 @@ async function runSdkQuery(host, context, followUpContent) {
|
|
|
5229
5988
|
}
|
|
5230
5989
|
}
|
|
5231
5990
|
if (needsPlanSync) {
|
|
5232
|
-
host.syncPlanFile();
|
|
5991
|
+
await host.syncPlanFile();
|
|
5233
5992
|
}
|
|
5234
5993
|
}
|
|
5235
5994
|
async function buildRetryQuery(host, context, options, lastErrorWasImage) {
|
|
@@ -5401,6 +6160,22 @@ async function runWithRetry(initialQuery, context, host, options) {
|
|
|
5401
6160
|
var CostTracker = class {
|
|
5402
6161
|
cumulativeCostUsd = 0;
|
|
5403
6162
|
modelUsage = /* @__PURE__ */ new Map();
|
|
6163
|
+
seeded = false;
|
|
6164
|
+
/**
|
|
6165
|
+
* Rehydrate cumulative spend from the server so `maxBudgetUsd` enforcement
|
|
6166
|
+
* accounts for costs incurred by prior agent runs on the same task. Must be
|
|
6167
|
+
* called before any `addQueryCost` / `addModelUsage` — re-seeding after
|
|
6168
|
+
* costs have accumulated would clobber in-process totals.
|
|
6169
|
+
*/
|
|
6170
|
+
seed(totalCostUsd, modelUsage) {
|
|
6171
|
+
if (this.seeded) return;
|
|
6172
|
+
if (this.cumulativeCostUsd > 0 || this.modelUsage.size > 0) return;
|
|
6173
|
+
this.cumulativeCostUsd = totalCostUsd;
|
|
6174
|
+
for (const entry of modelUsage) {
|
|
6175
|
+
this.modelUsage.set(entry.model, { ...entry });
|
|
6176
|
+
}
|
|
6177
|
+
this.seeded = true;
|
|
6178
|
+
}
|
|
5404
6179
|
/** Add cost from a completed query and return the running total */
|
|
5405
6180
|
addQueryCost(queryCostUsd) {
|
|
5406
6181
|
this.cumulativeCostUsd += queryCostUsd;
|
|
@@ -5591,6 +6366,10 @@ var QueryBridge = class {
|
|
|
5591
6366
|
resume() {
|
|
5592
6367
|
this._stopped = false;
|
|
5593
6368
|
}
|
|
6369
|
+
/** Rehydrate CostTracker from server-side cumulative spend on agent boot. */
|
|
6370
|
+
seedCostTracker(totalCostUsd, modelUsage) {
|
|
6371
|
+
this.costTracker.seed(totalCostUsd, modelUsage);
|
|
6372
|
+
}
|
|
5594
6373
|
/**
|
|
5595
6374
|
* Execute a Claude SDK query.
|
|
5596
6375
|
* Without followUpContent: runs initial mode execution (build/plan).
|
|
@@ -5646,7 +6425,6 @@ var QueryBridge = class {
|
|
|
5646
6425
|
set hasExitedPlanMode(val) {
|
|
5647
6426
|
bridge.mode.hasExitedPlanMode = val;
|
|
5648
6427
|
},
|
|
5649
|
-
exitPlanAttempts: 0,
|
|
5650
6428
|
get pendingModeRestart() {
|
|
5651
6429
|
return bridge.mode.pendingModeRestart;
|
|
5652
6430
|
},
|
|
@@ -5703,6 +6481,7 @@ import { fileURLToPath } from "url";
|
|
|
5703
6481
|
function mapChatHistory(messages) {
|
|
5704
6482
|
if (!messages) return [];
|
|
5705
6483
|
return messages.map((m) => ({
|
|
6484
|
+
id: m.id,
|
|
5706
6485
|
role: m.role ?? "user",
|
|
5707
6486
|
content: m.content ?? "",
|
|
5708
6487
|
userId: m.userId,
|
|
@@ -5856,6 +6635,7 @@ var SessionRunner = class _SessionRunner {
|
|
|
5856
6635
|
});
|
|
5857
6636
|
}
|
|
5858
6637
|
this.queryBridge = this.createQueryBridge();
|
|
6638
|
+
await this.seedCostTrackerFromServer();
|
|
5859
6639
|
this.logInitialization();
|
|
5860
6640
|
const staleMessageCount = this.pendingMessages.length;
|
|
5861
6641
|
const didExecuteInitialQuery = await this.executeInitialMode();
|
|
@@ -6130,6 +6910,7 @@ var SessionRunner = class _SessionRunner {
|
|
|
6130
6910
|
projectDescription: ctx.projectDescription ?? null,
|
|
6131
6911
|
githubPRUrl: ctx.githubPRUrl,
|
|
6132
6912
|
claudeSessionId: ctx.claudeSessionId ?? null,
|
|
6913
|
+
lastSeenMessageId: ctx.lastSeenMessageId ?? null,
|
|
6133
6914
|
isParentTask: !!ctx.parentTaskId,
|
|
6134
6915
|
storyPoints: ctx.storyPoints ?? void 0,
|
|
6135
6916
|
projectAgents: ctx.projectAgents ?? void 0,
|
|
@@ -6217,6 +6998,36 @@ var SessionRunner = class _SessionRunner {
|
|
|
6217
6998
|
}
|
|
6218
6999
|
});
|
|
6219
7000
|
}
|
|
7001
|
+
/**
|
|
7002
|
+
* Rehydrate CostTracker from server. Caps at 3s so a slow API call never
|
|
7003
|
+
* blocks agent startup — on timeout/error we fall through with a $0 tracker
|
|
7004
|
+
* (the existing behavior before this rehydration path was added).
|
|
7005
|
+
*/
|
|
7006
|
+
async seedCostTrackerFromServer() {
|
|
7007
|
+
if (!this.queryBridge) return;
|
|
7008
|
+
const TIMEOUT_MS = 3e3;
|
|
7009
|
+
try {
|
|
7010
|
+
const timeout = new Promise((resolve2) => {
|
|
7011
|
+
setTimeout(() => resolve2(null), TIMEOUT_MS);
|
|
7012
|
+
});
|
|
7013
|
+
const fetched = await Promise.race([this.connection.getCumulativeSpending(), timeout]);
|
|
7014
|
+
if (fetched) {
|
|
7015
|
+
this.queryBridge.seedCostTracker(fetched.totalCostUsd, fetched.modelUsage);
|
|
7016
|
+
process.stderr.write(
|
|
7017
|
+
`[conveyor-agent] CostTracker seeded: $${fetched.totalCostUsd.toFixed(4)} across ${fetched.modelUsage.length} model(s)
|
|
7018
|
+
`
|
|
7019
|
+
);
|
|
7020
|
+
} else {
|
|
7021
|
+
process.stderr.write(
|
|
7022
|
+
"[conveyor-agent] CostTracker seed timed out after 3s \u2014 starting at $0\n"
|
|
7023
|
+
);
|
|
7024
|
+
}
|
|
7025
|
+
} catch (err) {
|
|
7026
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
7027
|
+
process.stderr.write(`[conveyor-agent] CostTracker seed failed: ${msg} \u2014 starting at $0
|
|
7028
|
+
`);
|
|
7029
|
+
}
|
|
7030
|
+
}
|
|
6220
7031
|
/** Proactively refresh the GitHub token before the 1-hour expiry. */
|
|
6221
7032
|
async refreshGithubToken() {
|
|
6222
7033
|
try {
|
|
@@ -6695,7 +7506,7 @@ function runStartCommand(cmd, cwd, onOutput) {
|
|
|
6695
7506
|
}
|
|
6696
7507
|
|
|
6697
7508
|
// src/tools/project-tools.ts
|
|
6698
|
-
import { z as
|
|
7509
|
+
import { z as z13 } from "zod";
|
|
6699
7510
|
function buildTaskListTools(connection) {
|
|
6700
7511
|
const projectId = connection.projectId;
|
|
6701
7512
|
return [
|
|
@@ -6703,9 +7514,9 @@ function buildTaskListTools(connection) {
|
|
|
6703
7514
|
"list_tasks",
|
|
6704
7515
|
"List tasks in the project. Optionally filter by status or assignee.",
|
|
6705
7516
|
{
|
|
6706
|
-
status:
|
|
6707
|
-
assigneeId:
|
|
6708
|
-
limit:
|
|
7517
|
+
status: z13.string().optional().describe("Filter by task status"),
|
|
7518
|
+
assigneeId: z13.string().optional().describe("Filter by assigned user ID"),
|
|
7519
|
+
limit: z13.number().optional().describe("Max number of tasks to return (default 50)")
|
|
6709
7520
|
},
|
|
6710
7521
|
async (params) => {
|
|
6711
7522
|
try {
|
|
@@ -6722,7 +7533,7 @@ function buildTaskListTools(connection) {
|
|
|
6722
7533
|
defineTool(
|
|
6723
7534
|
"get_project_task",
|
|
6724
7535
|
"Get detailed information about a task in this project (chat messages, child tasks, session). Project-runner scope.",
|
|
6725
|
-
{ task_id:
|
|
7536
|
+
{ task_id: z13.string().describe("The task ID to look up") },
|
|
6726
7537
|
async ({ task_id }) => {
|
|
6727
7538
|
try {
|
|
6728
7539
|
const task = await connection.call("getProjectTask", { projectId, taskId: task_id });
|
|
@@ -6739,10 +7550,10 @@ function buildTaskListTools(connection) {
|
|
|
6739
7550
|
"search_tasks",
|
|
6740
7551
|
"Search tasks by tags, text query, or status filters.",
|
|
6741
7552
|
{
|
|
6742
|
-
tagNames:
|
|
6743
|
-
searchQuery:
|
|
6744
|
-
statusFilters:
|
|
6745
|
-
limit:
|
|
7553
|
+
tagNames: z13.array(z13.string()).optional().describe("Filter by tag names"),
|
|
7554
|
+
searchQuery: z13.string().optional().describe("Text search in title/description"),
|
|
7555
|
+
statusFilters: z13.array(z13.string()).optional().describe("Filter by statuses"),
|
|
7556
|
+
limit: z13.number().optional().describe("Max results (default 20)")
|
|
6746
7557
|
},
|
|
6747
7558
|
async (params) => {
|
|
6748
7559
|
try {
|
|
@@ -6802,10 +7613,10 @@ function buildMutationTools2(connection) {
|
|
|
6802
7613
|
"create_task",
|
|
6803
7614
|
"Create a new task in the project.",
|
|
6804
7615
|
{
|
|
6805
|
-
title:
|
|
6806
|
-
description:
|
|
6807
|
-
plan:
|
|
6808
|
-
status:
|
|
7616
|
+
title: z13.string().describe("Task title"),
|
|
7617
|
+
description: z13.string().optional().describe("Task description"),
|
|
7618
|
+
plan: z13.string().optional().describe("Implementation plan in markdown"),
|
|
7619
|
+
status: z13.string().optional().describe("Initial status (default: Planning)")
|
|
6809
7620
|
},
|
|
6810
7621
|
async (params) => {
|
|
6811
7622
|
try {
|
|
@@ -6822,12 +7633,12 @@ function buildMutationTools2(connection) {
|
|
|
6822
7633
|
"update_project_task",
|
|
6823
7634
|
"Update an existing task's title, description, plan, status, or assignee. Project-runner scope.",
|
|
6824
7635
|
{
|
|
6825
|
-
task_id:
|
|
6826
|
-
title:
|
|
6827
|
-
description:
|
|
6828
|
-
plan:
|
|
6829
|
-
status:
|
|
6830
|
-
assignedUserId:
|
|
7636
|
+
task_id: z13.string().describe("The task ID to update"),
|
|
7637
|
+
title: z13.string().optional().describe("New title"),
|
|
7638
|
+
description: z13.string().optional().describe("New description"),
|
|
7639
|
+
plan: z13.string().optional().describe("New plan in markdown"),
|
|
7640
|
+
status: z13.string().optional().describe("New status"),
|
|
7641
|
+
assignedUserId: z13.string().nullable().optional().describe("Assign to user ID, or null to unassign")
|
|
6831
7642
|
},
|
|
6832
7643
|
async ({ task_id, ...fields }) => {
|
|
6833
7644
|
try {
|
|
@@ -7724,7 +8535,7 @@ var ProjectRunner = class {
|
|
|
7724
8535
|
async handleAuditTasks(request) {
|
|
7725
8536
|
this.connection.emitStatus("busy");
|
|
7726
8537
|
try {
|
|
7727
|
-
const { handleTaskAudit } = await import("./task-audit-handler-
|
|
8538
|
+
const { handleTaskAudit } = await import("./task-audit-handler-4675WBIX.js");
|
|
7728
8539
|
await handleTaskAudit(request, this.connection, this.projectDir);
|
|
7729
8540
|
} catch (error) {
|
|
7730
8541
|
const msg = parseErrorMessage(error);
|
|
@@ -7825,4 +8636,4 @@ export {
|
|
|
7825
8636
|
loadForwardPorts,
|
|
7826
8637
|
loadConveyorConfig
|
|
7827
8638
|
};
|
|
7828
|
-
//# sourceMappingURL=chunk-
|
|
8639
|
+
//# sourceMappingURL=chunk-TP5WEBQE.js.map
|