@rallycry/conveyor-agent 7.3.3 → 7.3.5
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-COJPX2QI.js → chunk-KO2YQJEV.js} +1107 -305
- package/dist/chunk-KO2YQJEV.js.map +1 -0
- package/dist/cli.js +20 -4
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +51 -6
- 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 +2 -2
- package/dist/chunk-COJPX2QI.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() {
|
|
@@ -618,8 +641,10 @@ var ModeController = class {
|
|
|
618
641
|
// src/runner/lifecycle.ts
|
|
619
642
|
var DEFAULT_LIFECYCLE_CONFIG = {
|
|
620
643
|
idleTimeoutMs: 30 * 60 * 1e3,
|
|
644
|
+
dormantTimeoutMs: 60 * 60 * 1e3,
|
|
621
645
|
heartbeatIntervalMs: 3e4,
|
|
622
|
-
tokenRefreshIntervalMs: 45 * 60 * 1e3
|
|
646
|
+
tokenRefreshIntervalMs: 45 * 60 * 1e3,
|
|
647
|
+
gitFlushIntervalMs: 2 * 60 * 1e3
|
|
623
648
|
};
|
|
624
649
|
var Lifecycle = class {
|
|
625
650
|
config;
|
|
@@ -628,6 +653,8 @@ var Lifecycle = class {
|
|
|
628
653
|
tokenRefreshTimer = null;
|
|
629
654
|
idleTimer = null;
|
|
630
655
|
idleCheckInterval = null;
|
|
656
|
+
dormantTimer = null;
|
|
657
|
+
gitFlushTimer = null;
|
|
631
658
|
constructor(config, callbacks) {
|
|
632
659
|
this.config = config;
|
|
633
660
|
this.callbacks = callbacks;
|
|
@@ -659,6 +686,19 @@ var Lifecycle = class {
|
|
|
659
686
|
this.tokenRefreshTimer = null;
|
|
660
687
|
}
|
|
661
688
|
}
|
|
689
|
+
// ── Periodic git flush ────────────────────────────────────────────
|
|
690
|
+
startGitFlush() {
|
|
691
|
+
this.stopGitFlush();
|
|
692
|
+
this.gitFlushTimer = setInterval(() => {
|
|
693
|
+
this.callbacks.onGitFlush();
|
|
694
|
+
}, this.config.gitFlushIntervalMs);
|
|
695
|
+
}
|
|
696
|
+
stopGitFlush() {
|
|
697
|
+
if (this.gitFlushTimer) {
|
|
698
|
+
clearInterval(this.gitFlushTimer);
|
|
699
|
+
this.gitFlushTimer = null;
|
|
700
|
+
}
|
|
701
|
+
}
|
|
662
702
|
// ── Idle timer ─────────────────────────────────────────────────────
|
|
663
703
|
startIdleTimer() {
|
|
664
704
|
this.clearIdleTimers();
|
|
@@ -669,11 +709,26 @@ var Lifecycle = class {
|
|
|
669
709
|
cancelIdleTimer() {
|
|
670
710
|
this.clearIdleTimers();
|
|
671
711
|
}
|
|
712
|
+
// ── Dormant timer ──────────────────────────────────────────────────
|
|
713
|
+
startDormantTimer() {
|
|
714
|
+
this.cancelDormantTimer();
|
|
715
|
+
this.dormantTimer = setTimeout(() => {
|
|
716
|
+
this.callbacks.onDormantTimeout();
|
|
717
|
+
}, this.config.dormantTimeoutMs);
|
|
718
|
+
}
|
|
719
|
+
cancelDormantTimer() {
|
|
720
|
+
if (this.dormantTimer) {
|
|
721
|
+
clearTimeout(this.dormantTimer);
|
|
722
|
+
this.dormantTimer = null;
|
|
723
|
+
}
|
|
724
|
+
}
|
|
672
725
|
// ── Cleanup ────────────────────────────────────────────────────────
|
|
673
726
|
destroy() {
|
|
674
727
|
this.stopHeartbeat();
|
|
675
728
|
this.stopTokenRefresh();
|
|
729
|
+
this.stopGitFlush();
|
|
676
730
|
this.clearIdleTimers();
|
|
731
|
+
this.cancelDormantTimer();
|
|
677
732
|
}
|
|
678
733
|
// ── Private ────────────────────────────────────────────────────────
|
|
679
734
|
clearIdleTimers() {
|
|
@@ -927,8 +982,8 @@ var PlanSync = class {
|
|
|
927
982
|
for (const file of readdirSync(plansDir).filter((f) => f.endsWith(".md"))) {
|
|
928
983
|
try {
|
|
929
984
|
const fullPath = join(plansDir, file);
|
|
930
|
-
const
|
|
931
|
-
this.planFileSnapshot.set(fullPath,
|
|
985
|
+
const stat2 = statSync(fullPath);
|
|
986
|
+
this.planFileSnapshot.set(fullPath, stat2.mtimeMs);
|
|
932
987
|
} catch {
|
|
933
988
|
continue;
|
|
934
989
|
}
|
|
@@ -949,11 +1004,11 @@ var PlanSync = class {
|
|
|
949
1004
|
for (const file of files) {
|
|
950
1005
|
const fullPath = join(plansDir, file);
|
|
951
1006
|
try {
|
|
952
|
-
const
|
|
1007
|
+
const stat2 = statSync(fullPath);
|
|
953
1008
|
const prevMtime = this.planFileSnapshot.get(fullPath);
|
|
954
|
-
const isNew = prevMtime === void 0 ||
|
|
955
|
-
if (isNew && (!newest ||
|
|
956
|
-
newest = { path: fullPath, mtime:
|
|
1009
|
+
const isNew = prevMtime === void 0 || stat2.mtimeMs > prevMtime;
|
|
1010
|
+
if (isNew && (!newest || stat2.mtimeMs > newest.mtime)) {
|
|
1011
|
+
newest = { path: fullPath, mtime: stat2.mtimeMs };
|
|
957
1012
|
}
|
|
958
1013
|
} catch {
|
|
959
1014
|
continue;
|
|
@@ -962,31 +1017,35 @@ var PlanSync = class {
|
|
|
962
1017
|
}
|
|
963
1018
|
return newest;
|
|
964
1019
|
}
|
|
965
|
-
syncPlanFile() {
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
1020
|
+
async syncPlanFile() {
|
|
1021
|
+
const isInitialDetection = this.lockedPlanFile === null;
|
|
1022
|
+
const target = this.lockedPlanFile ?? this.findNewestPlanFile()?.path ?? null;
|
|
1023
|
+
if (!target) return;
|
|
1024
|
+
if (isInitialDetection) {
|
|
1025
|
+
this.lockedPlanFile = target;
|
|
1026
|
+
}
|
|
1027
|
+
const fileName = target.split("/").pop() ?? "plan";
|
|
1028
|
+
let content;
|
|
1029
|
+
try {
|
|
1030
|
+
content = readFileSync(target, "utf-8").trim();
|
|
1031
|
+
} catch (err) {
|
|
1032
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
1033
|
+
this.connection.postChatMessage(
|
|
1034
|
+
`Plan sync warning: could not read local plan file (${fileName}): ${reason}. The task plan was not updated.`
|
|
1035
|
+
);
|
|
976
1036
|
return;
|
|
977
1037
|
}
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
this.connection.postChatMessage(
|
|
986
|
-
`Detected local plan file (${fileName}) and synced it to the task plan.`
|
|
987
|
-
);
|
|
988
|
-
}
|
|
1038
|
+
if (!content) return;
|
|
1039
|
+
const result = await this.connection.updateTaskFields({ plan: content });
|
|
1040
|
+
if (!result.ok) {
|
|
1041
|
+
this.connection.postChatMessage(
|
|
1042
|
+
`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.`
|
|
1043
|
+
);
|
|
1044
|
+
return;
|
|
989
1045
|
}
|
|
1046
|
+
const verb = isInitialDetection ? "Detected local plan file" : "Synced local plan file";
|
|
1047
|
+
const suffix = isInitialDetection ? " and synced it to the task plan." : " to the task plan.";
|
|
1048
|
+
this.connection.postChatMessage(`${verb} (${fileName})${suffix}`);
|
|
990
1049
|
}
|
|
991
1050
|
};
|
|
992
1051
|
|
|
@@ -996,6 +1055,558 @@ import { existsSync } from "fs";
|
|
|
996
1055
|
import { homedir } from "os";
|
|
997
1056
|
import { join as join2 } from "path";
|
|
998
1057
|
|
|
1058
|
+
// ../shared/dist/index.js
|
|
1059
|
+
import { z } from "zod";
|
|
1060
|
+
import { z as z2 } from "zod";
|
|
1061
|
+
import { z as z3 } from "zod";
|
|
1062
|
+
var MAX_FILE_SIZE_BYTES = 25 * 1024 * 1024;
|
|
1063
|
+
var EMBED_THRESHOLD_IMAGES = 5 * 1024 * 1024;
|
|
1064
|
+
var EMBED_THRESHOLD_TEXT = 2 * 1024 * 1024;
|
|
1065
|
+
var AgentHeartbeatSchema = z.object({
|
|
1066
|
+
sessionId: z.string().optional(),
|
|
1067
|
+
timestamp: z.string(),
|
|
1068
|
+
status: z.enum(["active", "idle", "building"]),
|
|
1069
|
+
currentAction: z.string().optional()
|
|
1070
|
+
});
|
|
1071
|
+
var CreatePRInputSchema = z.object({
|
|
1072
|
+
title: z.string().min(1),
|
|
1073
|
+
body: z.string(),
|
|
1074
|
+
head: z.string().optional(),
|
|
1075
|
+
base: z.string().optional()
|
|
1076
|
+
});
|
|
1077
|
+
var PostToChatInputSchema = z.object({
|
|
1078
|
+
message: z.string().min(1),
|
|
1079
|
+
type: z.enum(["message", "question", "update"]).optional().default("message")
|
|
1080
|
+
});
|
|
1081
|
+
var GetTaskContextRequestSchema = z.object({
|
|
1082
|
+
sessionId: z.string(),
|
|
1083
|
+
includeHistory: z.boolean().optional().default(false)
|
|
1084
|
+
});
|
|
1085
|
+
var GetChatMessagesRequestSchema = z.object({
|
|
1086
|
+
sessionId: z.string(),
|
|
1087
|
+
limit: z.number().int().positive().optional().default(50),
|
|
1088
|
+
offset: z.number().int().nonnegative().optional().default(0)
|
|
1089
|
+
});
|
|
1090
|
+
var GetTaskFilesRequestSchema = z.object({
|
|
1091
|
+
sessionId: z.string()
|
|
1092
|
+
});
|
|
1093
|
+
var GetTaskFileRequestSchema = z.object({
|
|
1094
|
+
sessionId: z.string(),
|
|
1095
|
+
fileId: z.string()
|
|
1096
|
+
});
|
|
1097
|
+
var GetTaskRequestSchema = z.object({
|
|
1098
|
+
sessionId: z.string(),
|
|
1099
|
+
taskSlugOrId: z.string()
|
|
1100
|
+
});
|
|
1101
|
+
var GetCliHistoryRequestSchema = z.object({
|
|
1102
|
+
sessionId: z.string(),
|
|
1103
|
+
limit: z.number().int().positive().optional().default(100),
|
|
1104
|
+
source: z.enum(["agent", "application"]).optional()
|
|
1105
|
+
});
|
|
1106
|
+
var ListSubtasksRequestSchema = z.object({
|
|
1107
|
+
sessionId: z.string()
|
|
1108
|
+
});
|
|
1109
|
+
var GetDependenciesRequestSchema = z.object({
|
|
1110
|
+
sessionId: z.string()
|
|
1111
|
+
});
|
|
1112
|
+
var GetSuggestionsRequestSchema = z.object({
|
|
1113
|
+
sessionId: z.string(),
|
|
1114
|
+
status: z.string().optional(),
|
|
1115
|
+
limit: z.number().int().min(1).max(100).optional()
|
|
1116
|
+
});
|
|
1117
|
+
var CreatePullRequestRequestSchema = CreatePRInputSchema.extend({ sessionId: z.string() });
|
|
1118
|
+
var UpdateTaskStatusRequestSchema = z.object({
|
|
1119
|
+
sessionId: z.string(),
|
|
1120
|
+
status: z.string(),
|
|
1121
|
+
force: z.boolean().optional().default(false)
|
|
1122
|
+
});
|
|
1123
|
+
var StoreSessionIdRequestSchema = z.object({
|
|
1124
|
+
sessionId: z.string(),
|
|
1125
|
+
sdkSessionId: z.string()
|
|
1126
|
+
});
|
|
1127
|
+
var TrackSpendingRequestSchema = z.object({
|
|
1128
|
+
sessionId: z.string(),
|
|
1129
|
+
inputTokens: z.number().int().nonnegative(),
|
|
1130
|
+
outputTokens: z.number().int().nonnegative(),
|
|
1131
|
+
costUsd: z.number().nonnegative(),
|
|
1132
|
+
model: z.string()
|
|
1133
|
+
});
|
|
1134
|
+
var SessionStartRequestSchema = z.object({
|
|
1135
|
+
sessionId: z.string(),
|
|
1136
|
+
agentVersion: z.string(),
|
|
1137
|
+
capabilities: z.array(z.string())
|
|
1138
|
+
});
|
|
1139
|
+
var SessionStopRequestSchema = z.object({
|
|
1140
|
+
sessionId: z.string(),
|
|
1141
|
+
reason: z.string().optional()
|
|
1142
|
+
});
|
|
1143
|
+
var ConnectAgentRequestSchema = z.object({
|
|
1144
|
+
sessionId: z.string()
|
|
1145
|
+
});
|
|
1146
|
+
var ReportAgentStatusRequestSchema = z.object({
|
|
1147
|
+
sessionId: z.string(),
|
|
1148
|
+
status: z.string()
|
|
1149
|
+
});
|
|
1150
|
+
var NotifyAgentVersionRequestSchema = z.object({
|
|
1151
|
+
sessionId: z.string(),
|
|
1152
|
+
agentVersion: z.string()
|
|
1153
|
+
});
|
|
1154
|
+
var CreateSubtaskRequestSchema = z.object({
|
|
1155
|
+
sessionId: z.string(),
|
|
1156
|
+
title: z.string().min(1),
|
|
1157
|
+
description: z.string().optional(),
|
|
1158
|
+
plan: z.string().optional(),
|
|
1159
|
+
storyPointValue: z.number().int().positive().optional(),
|
|
1160
|
+
ordinal: z.number().int().nonnegative().optional()
|
|
1161
|
+
});
|
|
1162
|
+
var UpdateSubtaskRequestSchema = z.object({
|
|
1163
|
+
sessionId: z.string(),
|
|
1164
|
+
subtaskId: z.string(),
|
|
1165
|
+
title: z.string().min(1).optional(),
|
|
1166
|
+
description: z.string().optional(),
|
|
1167
|
+
plan: z.string().optional(),
|
|
1168
|
+
status: z.string().optional(),
|
|
1169
|
+
storyPointValue: z.number().int().positive().optional()
|
|
1170
|
+
});
|
|
1171
|
+
var DeleteSubtaskRequestSchema = z.object({
|
|
1172
|
+
sessionId: z.string(),
|
|
1173
|
+
subtaskId: z.string()
|
|
1174
|
+
});
|
|
1175
|
+
var GetTaskPropertiesRequestSchema = z.object({
|
|
1176
|
+
sessionId: z.string()
|
|
1177
|
+
});
|
|
1178
|
+
var GetCumulativeSpendingRequestSchema = z.object({
|
|
1179
|
+
sessionId: z.string()
|
|
1180
|
+
});
|
|
1181
|
+
var ModelUsageEntrySchema = z.object({
|
|
1182
|
+
model: z.string(),
|
|
1183
|
+
inputTokens: z.number().nonnegative(),
|
|
1184
|
+
outputTokens: z.number().nonnegative(),
|
|
1185
|
+
cacheReadInputTokens: z.number().nonnegative(),
|
|
1186
|
+
cacheCreationInputTokens: z.number().nonnegative(),
|
|
1187
|
+
costUSD: z.number().nonnegative()
|
|
1188
|
+
});
|
|
1189
|
+
var GetCumulativeSpendingResponseSchema = z.object({
|
|
1190
|
+
totalCostUsd: z.number().nonnegative(),
|
|
1191
|
+
modelUsage: z.array(ModelUsageEntrySchema)
|
|
1192
|
+
});
|
|
1193
|
+
var UpdateTaskFieldsRequestSchema = z.object({
|
|
1194
|
+
sessionId: z.string(),
|
|
1195
|
+
plan: z.string().optional(),
|
|
1196
|
+
description: z.string().optional()
|
|
1197
|
+
});
|
|
1198
|
+
var UpdateTaskPropertiesRequestSchema = z.object({
|
|
1199
|
+
sessionId: z.string(),
|
|
1200
|
+
title: z.string().optional(),
|
|
1201
|
+
storyPointValue: z.number().int().positive().optional(),
|
|
1202
|
+
tagIds: z.array(z.string()).optional(),
|
|
1203
|
+
tagNames: z.array(z.string()).optional(),
|
|
1204
|
+
githubPRUrl: z.string().url().optional(),
|
|
1205
|
+
githubBranch: z.string().optional()
|
|
1206
|
+
});
|
|
1207
|
+
var ListIconsRequestSchema = z.object({
|
|
1208
|
+
sessionId: z.string()
|
|
1209
|
+
});
|
|
1210
|
+
var GenerateTaskIconRequestSchema = z.object({
|
|
1211
|
+
sessionId: z.string(),
|
|
1212
|
+
prompt: z.string().min(1),
|
|
1213
|
+
aspectRatio: z.string().optional()
|
|
1214
|
+
});
|
|
1215
|
+
var SearchFaIconsRequestSchema = z.object({
|
|
1216
|
+
sessionId: z.string(),
|
|
1217
|
+
query: z.string().min(1),
|
|
1218
|
+
first: z.number().int().positive().optional()
|
|
1219
|
+
});
|
|
1220
|
+
var PickFaIconRequestSchema = z.object({
|
|
1221
|
+
sessionId: z.string(),
|
|
1222
|
+
fontAwesomeId: z.string().min(1),
|
|
1223
|
+
fontAwesomeStyle: z.string().optional()
|
|
1224
|
+
});
|
|
1225
|
+
var CreateFollowUpTaskRequestSchema = z.object({
|
|
1226
|
+
sessionId: z.string(),
|
|
1227
|
+
title: z.string().min(1),
|
|
1228
|
+
description: z.string().optional(),
|
|
1229
|
+
plan: z.string().optional(),
|
|
1230
|
+
storyPointValue: z.number().int().positive().optional()
|
|
1231
|
+
});
|
|
1232
|
+
var AddDependencyRequestSchema = z.object({
|
|
1233
|
+
sessionId: z.string(),
|
|
1234
|
+
dependsOnSlugOrId: z.string()
|
|
1235
|
+
});
|
|
1236
|
+
var RemoveDependencyRequestSchema = z.object({
|
|
1237
|
+
sessionId: z.string(),
|
|
1238
|
+
dependsOnSlugOrId: z.string()
|
|
1239
|
+
});
|
|
1240
|
+
var CreateSuggestionRequestSchema = z.object({
|
|
1241
|
+
sessionId: z.string(),
|
|
1242
|
+
title: z.string().min(1),
|
|
1243
|
+
description: z.string().optional(),
|
|
1244
|
+
tagNames: z.array(z.string()).optional()
|
|
1245
|
+
});
|
|
1246
|
+
var VoteSuggestionRequestSchema = z.object({
|
|
1247
|
+
sessionId: z.string(),
|
|
1248
|
+
suggestionId: z.string(),
|
|
1249
|
+
value: z.union([z.literal(1), z.literal(-1)])
|
|
1250
|
+
});
|
|
1251
|
+
var TriggerIdentificationRequestSchema = z.object({
|
|
1252
|
+
sessionId: z.string()
|
|
1253
|
+
});
|
|
1254
|
+
var SubmitCodeReviewResultRequestSchema = z.object({
|
|
1255
|
+
sessionId: z.string(),
|
|
1256
|
+
approved: z.boolean(),
|
|
1257
|
+
content: z.string()
|
|
1258
|
+
});
|
|
1259
|
+
var StartChildCloudBuildRequestSchema = z.object({
|
|
1260
|
+
sessionId: z.string(),
|
|
1261
|
+
childTaskId: z.string()
|
|
1262
|
+
});
|
|
1263
|
+
var StopChildBuildRequestSchema = z.object({
|
|
1264
|
+
sessionId: z.string(),
|
|
1265
|
+
childTaskId: z.string()
|
|
1266
|
+
});
|
|
1267
|
+
var ApproveAndMergePRRequestSchema = z.object({
|
|
1268
|
+
sessionId: z.string(),
|
|
1269
|
+
childTaskId: z.string()
|
|
1270
|
+
});
|
|
1271
|
+
var PostChildChatMessageRequestSchema = z.object({
|
|
1272
|
+
sessionId: z.string(),
|
|
1273
|
+
childTaskId: z.string(),
|
|
1274
|
+
message: z.string().min(1)
|
|
1275
|
+
});
|
|
1276
|
+
var UpdateChildStatusRequestSchema = z.object({
|
|
1277
|
+
sessionId: z.string(),
|
|
1278
|
+
childTaskId: z.string(),
|
|
1279
|
+
status: z.string()
|
|
1280
|
+
});
|
|
1281
|
+
var GetAgentStatusRequestSchema = z.object({
|
|
1282
|
+
taskId: z.string()
|
|
1283
|
+
});
|
|
1284
|
+
var GetUiCliHistoryRequestSchema = z.object({
|
|
1285
|
+
taskId: z.string()
|
|
1286
|
+
});
|
|
1287
|
+
var SendSoftStopRequestSchema = z.object({
|
|
1288
|
+
taskId: z.string().optional(),
|
|
1289
|
+
projectId: z.string().optional()
|
|
1290
|
+
});
|
|
1291
|
+
var FlushTaskQueueRequestSchema = z.object({
|
|
1292
|
+
taskId: z.string(),
|
|
1293
|
+
softStop: z.boolean().optional()
|
|
1294
|
+
});
|
|
1295
|
+
var FlushProjectQueueRequestSchema = z.object({
|
|
1296
|
+
projectId: z.string()
|
|
1297
|
+
});
|
|
1298
|
+
var CancelTaskQueuedMessageRequestSchema = z.object({
|
|
1299
|
+
taskId: z.string(),
|
|
1300
|
+
messageId: z.string()
|
|
1301
|
+
});
|
|
1302
|
+
var FlushSingleQueuedMessageRequestSchema = z.object({
|
|
1303
|
+
taskId: z.string(),
|
|
1304
|
+
messageId: z.string(),
|
|
1305
|
+
softStop: z.boolean().optional()
|
|
1306
|
+
});
|
|
1307
|
+
var FlushSingleProjectQueuedMessageRequestSchema = z.object({
|
|
1308
|
+
projectId: z.string(),
|
|
1309
|
+
index: z.number().int().nonnegative()
|
|
1310
|
+
});
|
|
1311
|
+
var AnswerAgentQuestionRequestSchema = z.object({
|
|
1312
|
+
taskId: z.string(),
|
|
1313
|
+
requestId: z.string(),
|
|
1314
|
+
answers: z.record(z.string(), z.string())
|
|
1315
|
+
});
|
|
1316
|
+
var ClearAgentTodosRequestSchema = z.object({
|
|
1317
|
+
taskId: z.string()
|
|
1318
|
+
});
|
|
1319
|
+
var AgentQuestionOptionSchema = z.object({
|
|
1320
|
+
label: z.string(),
|
|
1321
|
+
description: z.string(),
|
|
1322
|
+
preview: z.string().optional()
|
|
1323
|
+
});
|
|
1324
|
+
var AgentQuestionSchema = z.object({
|
|
1325
|
+
question: z.string(),
|
|
1326
|
+
header: z.string(),
|
|
1327
|
+
options: z.array(AgentQuestionOptionSchema),
|
|
1328
|
+
multiSelect: z.boolean().optional()
|
|
1329
|
+
});
|
|
1330
|
+
var AskUserQuestionRequestSchema = z.object({
|
|
1331
|
+
sessionId: z.string(),
|
|
1332
|
+
question: z.string().min(1),
|
|
1333
|
+
requestId: z.string().min(1),
|
|
1334
|
+
questions: z.array(AgentQuestionSchema).min(1)
|
|
1335
|
+
});
|
|
1336
|
+
var AgentEventSchema = z.object({
|
|
1337
|
+
type: z.string().min(1)
|
|
1338
|
+
}).catchall(z.unknown());
|
|
1339
|
+
var EmitAgentEventRequestSchema = z.object({
|
|
1340
|
+
sessionId: z.string(),
|
|
1341
|
+
events: z.array(AgentEventSchema).max(500)
|
|
1342
|
+
});
|
|
1343
|
+
var RefreshGithubTokenRequestSchema = z.object({
|
|
1344
|
+
sessionId: z.string()
|
|
1345
|
+
});
|
|
1346
|
+
var RefreshGithubTokenResponseSchema = z.object({
|
|
1347
|
+
token: z.string()
|
|
1348
|
+
});
|
|
1349
|
+
var CreatePRResponseSchema = z.object({
|
|
1350
|
+
prNumber: z.number().int().positive(),
|
|
1351
|
+
prUrl: z.string().url()
|
|
1352
|
+
});
|
|
1353
|
+
var PostToChatResponseSchema = z.object({
|
|
1354
|
+
messageId: z.string()
|
|
1355
|
+
});
|
|
1356
|
+
var UpdateTaskStatusResponseSchema = z.object({
|
|
1357
|
+
taskId: z.string(),
|
|
1358
|
+
status: z.string()
|
|
1359
|
+
});
|
|
1360
|
+
var StoreSessionIdResponseSchema = z.object({
|
|
1361
|
+
success: z.boolean()
|
|
1362
|
+
});
|
|
1363
|
+
var HeartbeatResponseSchema = z.object({
|
|
1364
|
+
acknowledged: z.boolean()
|
|
1365
|
+
});
|
|
1366
|
+
var SessionStartResponseSchema = z.object({
|
|
1367
|
+
sessionId: z.string(),
|
|
1368
|
+
startedAt: z.string()
|
|
1369
|
+
});
|
|
1370
|
+
var SessionStopResponseSchema = z.object({
|
|
1371
|
+
sessionId: z.string(),
|
|
1372
|
+
stoppedAt: z.string()
|
|
1373
|
+
});
|
|
1374
|
+
var DeleteSubtaskResponseSchema = z.object({
|
|
1375
|
+
deleted: z.boolean()
|
|
1376
|
+
});
|
|
1377
|
+
var RegisterProjectAgentResponseSchema = z.object({
|
|
1378
|
+
registered: z.boolean(),
|
|
1379
|
+
agentName: z.string(),
|
|
1380
|
+
agentInstructions: z.string(),
|
|
1381
|
+
model: z.string(),
|
|
1382
|
+
agentSettings: z.record(z.string(), z.unknown()).nullable(),
|
|
1383
|
+
branchSwitchCommand: z.string().nullable()
|
|
1384
|
+
});
|
|
1385
|
+
var RegisterProjectAgentRequestSchema = z2.object({
|
|
1386
|
+
projectId: z2.string(),
|
|
1387
|
+
capabilities: z2.array(z2.string())
|
|
1388
|
+
});
|
|
1389
|
+
var ProjectRunnerHeartbeatRequestSchema = z2.object({
|
|
1390
|
+
projectId: z2.string()
|
|
1391
|
+
});
|
|
1392
|
+
var ReportProjectAgentStatusRequestSchema = z2.object({
|
|
1393
|
+
projectId: z2.string(),
|
|
1394
|
+
status: z2.enum(["busy", "idle"]),
|
|
1395
|
+
activeChatId: z2.string().nullish(),
|
|
1396
|
+
activeTaskId: z2.string().nullish(),
|
|
1397
|
+
activeBranch: z2.string().nullish()
|
|
1398
|
+
});
|
|
1399
|
+
var DisconnectProjectRunnerRequestSchema = z2.object({
|
|
1400
|
+
projectId: z2.string()
|
|
1401
|
+
});
|
|
1402
|
+
var GetProjectAgentContextRequestSchema = z2.object({
|
|
1403
|
+
projectId: z2.string()
|
|
1404
|
+
});
|
|
1405
|
+
var GetProjectAgentContextByRoleRequestSchema = z2.object({
|
|
1406
|
+
projectId: z2.string(),
|
|
1407
|
+
role: z2.string()
|
|
1408
|
+
});
|
|
1409
|
+
var GetProjectFunctionConfigRequestSchema = z2.object({
|
|
1410
|
+
projectId: z2.string(),
|
|
1411
|
+
functionId: z2.string()
|
|
1412
|
+
});
|
|
1413
|
+
var GetProjectChatHistoryRequestSchema = z2.object({
|
|
1414
|
+
projectId: z2.string(),
|
|
1415
|
+
limit: z2.number().int().positive().optional().default(50),
|
|
1416
|
+
chatId: z2.string().optional()
|
|
1417
|
+
});
|
|
1418
|
+
var PostProjectAgentMessageRequestSchema = z2.object({
|
|
1419
|
+
projectId: z2.string(),
|
|
1420
|
+
content: z2.string().min(1),
|
|
1421
|
+
chatId: z2.string().optional()
|
|
1422
|
+
});
|
|
1423
|
+
var ListProjectTasksRequestSchema = z2.object({
|
|
1424
|
+
projectId: z2.string(),
|
|
1425
|
+
status: z2.string().optional(),
|
|
1426
|
+
assigneeId: z2.string().optional(),
|
|
1427
|
+
limit: z2.number().int().positive().optional().default(50)
|
|
1428
|
+
});
|
|
1429
|
+
var GetProjectTaskRequestSchema = z2.object({
|
|
1430
|
+
projectId: z2.string(),
|
|
1431
|
+
taskId: z2.string()
|
|
1432
|
+
});
|
|
1433
|
+
var SearchProjectTasksRequestSchema = z2.object({
|
|
1434
|
+
projectId: z2.string(),
|
|
1435
|
+
tagNames: z2.array(z2.string()).optional(),
|
|
1436
|
+
searchQuery: z2.string().optional(),
|
|
1437
|
+
statusFilters: z2.array(z2.string()).optional(),
|
|
1438
|
+
limit: z2.number().int().positive().optional().default(20)
|
|
1439
|
+
});
|
|
1440
|
+
var ListProjectTagsRequestSchema = z2.object({
|
|
1441
|
+
projectId: z2.string()
|
|
1442
|
+
});
|
|
1443
|
+
var GetProjectSummaryRequestSchema = z2.object({
|
|
1444
|
+
projectId: z2.string()
|
|
1445
|
+
});
|
|
1446
|
+
var CreateProjectTaskRequestSchema = z2.object({
|
|
1447
|
+
projectId: z2.string(),
|
|
1448
|
+
title: z2.string().min(1),
|
|
1449
|
+
description: z2.string().optional(),
|
|
1450
|
+
plan: z2.string().optional(),
|
|
1451
|
+
status: z2.string().optional()
|
|
1452
|
+
});
|
|
1453
|
+
var UpdateProjectTaskRequestSchema = z2.object({
|
|
1454
|
+
projectId: z2.string(),
|
|
1455
|
+
taskId: z2.string(),
|
|
1456
|
+
title: z2.string().optional(),
|
|
1457
|
+
description: z2.string().optional(),
|
|
1458
|
+
plan: z2.string().optional(),
|
|
1459
|
+
status: z2.string().optional(),
|
|
1460
|
+
assignedUserId: z2.string().nullish()
|
|
1461
|
+
});
|
|
1462
|
+
var ReportProjectAgentEventRequestSchema = z2.object({
|
|
1463
|
+
projectId: z2.string(),
|
|
1464
|
+
event: z2.record(z2.string(), z2.unknown())
|
|
1465
|
+
});
|
|
1466
|
+
var ReportTagAuditProgressRequestSchema = z2.object({
|
|
1467
|
+
projectId: z2.string(),
|
|
1468
|
+
requestId: z2.string(),
|
|
1469
|
+
activity: z2.object({
|
|
1470
|
+
tool: z2.string(),
|
|
1471
|
+
input: z2.string().optional(),
|
|
1472
|
+
timestamp: z2.string()
|
|
1473
|
+
})
|
|
1474
|
+
});
|
|
1475
|
+
var ReportTagAuditResultRequestSchema = z2.object({
|
|
1476
|
+
projectId: z2.string(),
|
|
1477
|
+
requestId: z2.string(),
|
|
1478
|
+
recommendations: z2.array(z2.record(z2.string(), z2.unknown())),
|
|
1479
|
+
summary: z2.string(),
|
|
1480
|
+
complete: z2.boolean()
|
|
1481
|
+
});
|
|
1482
|
+
var ReportNewCommitsDetectedRequestSchema = z2.object({
|
|
1483
|
+
projectId: z2.string(),
|
|
1484
|
+
commits: z2.array(
|
|
1485
|
+
z2.object({
|
|
1486
|
+
sha: z2.string(),
|
|
1487
|
+
message: z2.string(),
|
|
1488
|
+
author: z2.string()
|
|
1489
|
+
})
|
|
1490
|
+
),
|
|
1491
|
+
branch: z2.string()
|
|
1492
|
+
});
|
|
1493
|
+
var ReportEnvironmentReadyRequestSchema = z2.object({
|
|
1494
|
+
projectId: z2.string(),
|
|
1495
|
+
branch: z2.string(),
|
|
1496
|
+
setupComplete: z2.boolean(),
|
|
1497
|
+
startCommandRunning: z2.boolean()
|
|
1498
|
+
});
|
|
1499
|
+
var ReportEnvSwitchProgressRequestSchema = z2.object({
|
|
1500
|
+
projectId: z2.string(),
|
|
1501
|
+
step: z2.string(),
|
|
1502
|
+
progress: z2.number(),
|
|
1503
|
+
message: z2.string().optional()
|
|
1504
|
+
});
|
|
1505
|
+
var ForwardProjectChatMessageRequestSchema = z2.object({
|
|
1506
|
+
projectId: z2.string(),
|
|
1507
|
+
chatId: z2.string(),
|
|
1508
|
+
content: z2.string().min(1),
|
|
1509
|
+
targetUserId: z2.string().optional()
|
|
1510
|
+
});
|
|
1511
|
+
var CancelQueuedProjectMessageRequestSchema = z2.object({
|
|
1512
|
+
projectId: z2.string(),
|
|
1513
|
+
index: z2.number().int().nonnegative()
|
|
1514
|
+
});
|
|
1515
|
+
var GetProjectCliHistoryRequestSchema = z2.object({
|
|
1516
|
+
projectId: z2.string(),
|
|
1517
|
+
limit: z2.number().int().positive().optional().default(50),
|
|
1518
|
+
source: z2.string().optional()
|
|
1519
|
+
});
|
|
1520
|
+
var PostToProjectTaskChatRequestSchema = z2.object({
|
|
1521
|
+
projectId: z2.string(),
|
|
1522
|
+
taskId: z2.string(),
|
|
1523
|
+
content: z2.string()
|
|
1524
|
+
});
|
|
1525
|
+
var GetProjectTaskCliRequestSchema = z2.object({
|
|
1526
|
+
projectId: z2.string(),
|
|
1527
|
+
taskId: z2.string(),
|
|
1528
|
+
limit: z2.number().int().positive().optional().default(50),
|
|
1529
|
+
source: z2.string().optional()
|
|
1530
|
+
});
|
|
1531
|
+
var StartProjectBuildRequestSchema = z2.object({
|
|
1532
|
+
projectId: z2.string(),
|
|
1533
|
+
taskId: z2.string()
|
|
1534
|
+
});
|
|
1535
|
+
var StopProjectBuildRequestSchema = z2.object({
|
|
1536
|
+
projectId: z2.string(),
|
|
1537
|
+
taskId: z2.string()
|
|
1538
|
+
});
|
|
1539
|
+
var ApproveProjectMergePRRequestSchema = z2.object({
|
|
1540
|
+
projectId: z2.string(),
|
|
1541
|
+
childTaskId: z2.string()
|
|
1542
|
+
});
|
|
1543
|
+
var StartTaskAuditRequestSchema = z3.object({
|
|
1544
|
+
projectId: z3.string(),
|
|
1545
|
+
taskIds: z3.array(z3.string()).min(1)
|
|
1546
|
+
});
|
|
1547
|
+
var ReportTaskAuditProgressRequestSchema = z3.object({
|
|
1548
|
+
projectId: z3.string(),
|
|
1549
|
+
requestId: z3.string(),
|
|
1550
|
+
taskId: z3.string(),
|
|
1551
|
+
activity: z3.object({
|
|
1552
|
+
tool: z3.string(),
|
|
1553
|
+
input: z3.string().optional(),
|
|
1554
|
+
timestamp: z3.string()
|
|
1555
|
+
})
|
|
1556
|
+
});
|
|
1557
|
+
var CreateProjectSuggestionRequestSchema = z3.object({
|
|
1558
|
+
projectId: z3.string(),
|
|
1559
|
+
title: z3.string().min(1),
|
|
1560
|
+
description: z3.string().optional(),
|
|
1561
|
+
tagNames: z3.array(z3.string()).optional()
|
|
1562
|
+
});
|
|
1563
|
+
var ReportTaskAuditBatchCompleteRequestSchema = z3.object({
|
|
1564
|
+
projectId: z3.string(),
|
|
1565
|
+
requestId: z3.string()
|
|
1566
|
+
});
|
|
1567
|
+
var ReportTaskAuditResultRequestSchema = z3.object({
|
|
1568
|
+
projectId: z3.string(),
|
|
1569
|
+
requestId: z3.string(),
|
|
1570
|
+
taskId: z3.string(),
|
|
1571
|
+
summary: z3.string(),
|
|
1572
|
+
turnGrades: z3.array(
|
|
1573
|
+
z3.object({
|
|
1574
|
+
turnIndex: z3.number(),
|
|
1575
|
+
phase: z3.enum(["planning", "building", "human"]),
|
|
1576
|
+
grade: z3.enum(["correct", "neutral", "blunder"]),
|
|
1577
|
+
reasoning: z3.string(),
|
|
1578
|
+
eventType: z3.string(),
|
|
1579
|
+
eventSummary: z3.string()
|
|
1580
|
+
})
|
|
1581
|
+
),
|
|
1582
|
+
planningAccuracy: z3.number().nullable(),
|
|
1583
|
+
buildingAccuracy: z3.number().nullable(),
|
|
1584
|
+
humanAccuracy: z3.number().nullable(),
|
|
1585
|
+
planningCorrect: z3.number(),
|
|
1586
|
+
planningNeutral: z3.number(),
|
|
1587
|
+
planningBlunder: z3.number(),
|
|
1588
|
+
buildingCorrect: z3.number(),
|
|
1589
|
+
buildingNeutral: z3.number(),
|
|
1590
|
+
buildingBlunder: z3.number(),
|
|
1591
|
+
humanCorrect: z3.number(),
|
|
1592
|
+
humanNeutral: z3.number(),
|
|
1593
|
+
humanBlunder: z3.number(),
|
|
1594
|
+
humanEvaluations: z3.array(
|
|
1595
|
+
z3.object({
|
|
1596
|
+
messageIndex: z3.number(),
|
|
1597
|
+
rating: z3.number().int().min(-1).max(1),
|
|
1598
|
+
reasoning: z3.string()
|
|
1599
|
+
})
|
|
1600
|
+
).optional().default([]),
|
|
1601
|
+
suggestionIds: z3.array(z3.string()),
|
|
1602
|
+
auditCostUsd: z3.number().nullable(),
|
|
1603
|
+
model: z3.string().nullable(),
|
|
1604
|
+
error: z3.string().optional()
|
|
1605
|
+
});
|
|
1606
|
+
var TASK_CHAT_HISTORY_LIMIT = 20;
|
|
1607
|
+
var PM_CHAT_HISTORY_LIMIT = 40;
|
|
1608
|
+
var AGENT_CHAT_HISTORY_FETCH_LIMIT = Math.max(TASK_CHAT_HISTORY_LIMIT, PM_CHAT_HISTORY_LIMIT) + 10;
|
|
1609
|
+
|
|
999
1610
|
// src/execution/pack-runner-prompt.ts
|
|
1000
1611
|
function findLastAgentMessageIndex(history) {
|
|
1001
1612
|
for (let i = history.length - 1; i >= 0; i--) {
|
|
@@ -1043,7 +1654,7 @@ function buildPackRunnerSystemPrompt(context, config, setupLog) {
|
|
|
1043
1654
|
`2. Evaluate children by status and dependency readiness:`,
|
|
1044
1655
|
` - "ReviewPR": Review and merge its PR with approve_and_merge_pr. (Highest priority)`,
|
|
1045
1656
|
` - If merge fails due to pending CI: post a status update to chat, state you are going idle.`,
|
|
1046
|
-
` - If merge fails due to failed CI: use
|
|
1657
|
+
` - If merge fails due to failed CI: use get_execution_logs(childTaskId) to check. Escalate to team.`,
|
|
1047
1658
|
` - "InProgress": A Task Runner is actively working. Do nothing \u2014 wait.`,
|
|
1048
1659
|
` - "Open" + allDependenciesMet=true: Ready to fire. Use start_child_cloud_build.`,
|
|
1049
1660
|
` - "Open" + allDependenciesMet=false: Blocked \u2014 skip for now. Will be unblocked when deps complete.`,
|
|
@@ -1063,7 +1674,7 @@ function buildPackRunnerSystemPrompt(context, config, setupLog) {
|
|
|
1063
1674
|
`- When NO dependencies are set on any children, fall back to ordinal order (one at a time). This preserves backward compatibility.`,
|
|
1064
1675
|
`- 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.`,
|
|
1065
1676
|
`- Do NOT attempt to write code yourself. Your role is coordination only.`,
|
|
1066
|
-
`- If a child is stuck in "InProgress" for an unusually long time, use
|
|
1677
|
+
`- 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.`,
|
|
1067
1678
|
`- You can use get_task(childTaskId) to get a child's full details including PR URL and branch.`,
|
|
1068
1679
|
`- 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.`,
|
|
1069
1680
|
`- You can use read_task_chat to check for team messages.`
|
|
@@ -1127,7 +1738,6 @@ After addressing the feedback, resume your autonomous loop: call list_subtasks a
|
|
|
1127
1738
|
}
|
|
1128
1739
|
|
|
1129
1740
|
// src/execution/prompt-formatters.ts
|
|
1130
|
-
var PM_CHAT_HISTORY_LIMIT = 40;
|
|
1131
1741
|
function formatFileSize(bytes) {
|
|
1132
1742
|
if (bytes === void 0) return "";
|
|
1133
1743
|
if (bytes < 1024) return `${bytes}B`;
|
|
@@ -1149,7 +1759,7 @@ function formatChatFile(file) {
|
|
|
1149
1759
|
}
|
|
1150
1760
|
if (file.content && file.contentEncoding === "base64") {
|
|
1151
1761
|
return [
|
|
1152
|
-
`[Attached image: ${file.fileName} (${file.mimeType}${sizeStr}) \u2014 use
|
|
1762
|
+
`[Attached image: ${file.fileName} (${file.mimeType}${sizeStr}) \u2014 use get_attachment("${file.fileId}") to view]`
|
|
1153
1763
|
];
|
|
1154
1764
|
}
|
|
1155
1765
|
return [`[Attached: ${file.fileName} (${file.mimeType}${sizeStr})]`];
|
|
@@ -1162,7 +1772,7 @@ function formatTaskFile(file) {
|
|
|
1162
1772
|
if (file.content && file.contentEncoding === "base64") {
|
|
1163
1773
|
const size = formatFileSize(file.fileSize);
|
|
1164
1774
|
return [
|
|
1165
|
-
`- [Attached image: ${file.fileName} (${file.mimeType}${size ? `, ${size}` : ""}) \u2014 use
|
|
1775
|
+
`- [Attached image: ${file.fileName} (${file.mimeType}${size ? `, ${size}` : ""}) \u2014 use get_attachment("${file.fileId}") to view]`
|
|
1166
1776
|
];
|
|
1167
1777
|
}
|
|
1168
1778
|
if (!file.content) {
|
|
@@ -1195,6 +1805,20 @@ function formatRepoRefs(repoRefs) {
|
|
|
1195
1805
|
}
|
|
1196
1806
|
return parts;
|
|
1197
1807
|
}
|
|
1808
|
+
function formatReferenceProjects(referenceProjects) {
|
|
1809
|
+
const parts = [];
|
|
1810
|
+
parts.push(`
|
|
1811
|
+
## Reference Projects`);
|
|
1812
|
+
parts.push(
|
|
1813
|
+
`These sibling Conveyor projects have been shallow-cloned read-only into \`/workspaces/references/<slug>/\` for inspiration. You MAY grep/read them to compare approaches, but you MUST NOT modify them or commit anything from them into this task's repo.
|
|
1814
|
+
`
|
|
1815
|
+
);
|
|
1816
|
+
for (const ref of referenceProjects) {
|
|
1817
|
+
const repo = ref.githubRepoOwner && ref.githubRepoName ? ` (${ref.githubRepoOwner}/${ref.githubRepoName})` : "";
|
|
1818
|
+
parts.push(`- **${ref.name}**${repo} \u2014 \`/workspaces/references/${ref.slug}/\``);
|
|
1819
|
+
}
|
|
1820
|
+
return parts;
|
|
1821
|
+
}
|
|
1198
1822
|
function formatProjectObjectives(objectives) {
|
|
1199
1823
|
const parts = [];
|
|
1200
1824
|
parts.push(`
|
|
@@ -1239,7 +1863,7 @@ function formatIncidents(incidents) {
|
|
|
1239
1863
|
}
|
|
1240
1864
|
|
|
1241
1865
|
// src/execution/tag-context-resolver.ts
|
|
1242
|
-
import { readFile, readdir } from "fs/promises";
|
|
1866
|
+
import { readFile, readdir, stat } from "fs/promises";
|
|
1243
1867
|
var TYPE_PRIORITY = { rule: 0, file: 1, folder: 2, doc: 3 };
|
|
1244
1868
|
var BINARY_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
1245
1869
|
".png",
|
|
@@ -1274,6 +1898,10 @@ function isBinaryPath(filePath) {
|
|
|
1274
1898
|
const ext = filePath.slice(filePath.lastIndexOf(".")).toLowerCase();
|
|
1275
1899
|
return BINARY_EXTENSIONS.has(ext);
|
|
1276
1900
|
}
|
|
1901
|
+
var fileContentCache = /* @__PURE__ */ new Map();
|
|
1902
|
+
var folderListingCache = /* @__PURE__ */ new Map();
|
|
1903
|
+
var fileReadCount = 0;
|
|
1904
|
+
var folderReadCount = 0;
|
|
1277
1905
|
function getContextBudgetChars(_model, betas, runnerMode) {
|
|
1278
1906
|
const contextWindow = betas?.some((b) => b.includes("context-1m")) ? 1e6 : 2e5;
|
|
1279
1907
|
const budgetPct = runnerMode === "task" ? 0.15 : 0.25;
|
|
@@ -1282,21 +1910,50 @@ function getContextBudgetChars(_model, betas, runnerMode) {
|
|
|
1282
1910
|
async function readFileContent(filePath, maxChars) {
|
|
1283
1911
|
try {
|
|
1284
1912
|
if (isBinaryPath(filePath)) return null;
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1913
|
+
let rawContent;
|
|
1914
|
+
let mtimeMs;
|
|
1915
|
+
try {
|
|
1916
|
+
const st = await stat(filePath);
|
|
1917
|
+
mtimeMs = st.mtimeMs;
|
|
1918
|
+
} catch {
|
|
1919
|
+
return null;
|
|
1920
|
+
}
|
|
1921
|
+
const cached = fileContentCache.get(filePath);
|
|
1922
|
+
if (cached && cached.mtimeMs === mtimeMs) {
|
|
1923
|
+
rawContent = cached.content;
|
|
1924
|
+
} else {
|
|
1925
|
+
rawContent = await readFile(filePath, "utf-8");
|
|
1926
|
+
fileReadCount++;
|
|
1927
|
+
fileContentCache.set(filePath, { mtimeMs, content: rawContent });
|
|
1928
|
+
}
|
|
1929
|
+
if (rawContent.length > maxChars) {
|
|
1930
|
+
const omitted = rawContent.length - maxChars;
|
|
1931
|
+
return rawContent.slice(0, maxChars) + `
|
|
1289
1932
|
[... truncated, ${omitted} chars omitted]`;
|
|
1290
1933
|
}
|
|
1291
|
-
return
|
|
1934
|
+
return rawContent;
|
|
1292
1935
|
} catch {
|
|
1293
1936
|
return null;
|
|
1294
1937
|
}
|
|
1295
1938
|
}
|
|
1296
1939
|
async function readFolderListing(folderPath) {
|
|
1297
1940
|
try {
|
|
1941
|
+
let mtimeMs;
|
|
1942
|
+
try {
|
|
1943
|
+
const st = await stat(folderPath);
|
|
1944
|
+
mtimeMs = st.mtimeMs;
|
|
1945
|
+
} catch {
|
|
1946
|
+
return null;
|
|
1947
|
+
}
|
|
1948
|
+
const cached = folderListingCache.get(folderPath);
|
|
1949
|
+
if (cached && cached.mtimeMs === mtimeMs) {
|
|
1950
|
+
return cached.listing;
|
|
1951
|
+
}
|
|
1298
1952
|
const entries = await readdir(folderPath);
|
|
1299
|
-
|
|
1953
|
+
folderReadCount++;
|
|
1954
|
+
const listing = `Files: ${entries.join(", ")}`;
|
|
1955
|
+
folderListingCache.set(folderPath, { mtimeMs, listing });
|
|
1956
|
+
return listing;
|
|
1300
1957
|
} catch {
|
|
1301
1958
|
return null;
|
|
1302
1959
|
}
|
|
@@ -1417,6 +2074,18 @@ async function resolveTagContext(projectTags, taskTagIds, model, betas, runnerMo
|
|
|
1417
2074
|
};
|
|
1418
2075
|
}
|
|
1419
2076
|
|
|
2077
|
+
// src/execution/prompt-truncation.ts
|
|
2078
|
+
var PLAN_SOFT_CAP = 4e3;
|
|
2079
|
+
var PLAN_HEAD_CHARS = 3e3;
|
|
2080
|
+
var PLAN_TAIL_CHARS = 500;
|
|
2081
|
+
var PLAN_TRUNCATION_MARKER = "\n\n... plan truncated \u2014 call get_current_plan for full text ...\n\n";
|
|
2082
|
+
function truncatePlanForPrompt(plan) {
|
|
2083
|
+
if (plan.length <= PLAN_SOFT_CAP) return plan;
|
|
2084
|
+
const head = plan.slice(0, PLAN_HEAD_CHARS);
|
|
2085
|
+
const tail = plan.slice(plan.length - PLAN_TAIL_CHARS);
|
|
2086
|
+
return `${head}${PLAN_TRUNCATION_MARKER}${tail}`;
|
|
2087
|
+
}
|
|
2088
|
+
|
|
1420
2089
|
// src/execution/mode-prompt.ts
|
|
1421
2090
|
var SP_DESC_MAX_CHARS = 80;
|
|
1422
2091
|
function truncateDescription(desc, maxChars) {
|
|
@@ -1476,7 +2145,19 @@ function buildExplorationMethodology() {
|
|
|
1476
2145
|
`- Search first, read second: use grep/glob to locate relevant code, then read only the files that matter`,
|
|
1477
2146
|
`- Never re-read a file already in your context \u2014 you have a large context window, scroll up instead`,
|
|
1478
2147
|
`- Start with 3-5 critical files, form a hypothesis about the approach, then validate with targeted reads`,
|
|
1479
|
-
`- Stop exploring when you can
|
|
2148
|
+
`- Stop exploring when you can cite specific \`file.ts:line\` locations and function names for every step in your plan \u2014 that's enough`
|
|
2149
|
+
];
|
|
2150
|
+
}
|
|
2151
|
+
function buildPlanCitationFormat() {
|
|
2152
|
+
return [
|
|
2153
|
+
``,
|
|
2154
|
+
`### Plan Citation Format`,
|
|
2155
|
+
`Plans must ground each change in the code. For every step that touches code:`,
|
|
2156
|
+
`- Cite the exact location as \`path/from/repo/root.ts:lineNumber\` (e.g. \`packages/conveyor-agent/src/execution/mode-prompt.ts:129\`).`,
|
|
2157
|
+
`- Name the specific function, class, constant, or JSX element being touched.`,
|
|
2158
|
+
`- When behavior hinges on a short piece of code, quote 1\u20133 lines inline instead of paraphrasing.`,
|
|
2159
|
+
`- Ranges are fine for larger edits (\`foo.ts:120-145\`). Do not cite whole files without a line.`,
|
|
2160
|
+
`- If a file doesn't exist yet, write \`NEW: path/to/new-file.ts\` and describe the surrounding module it fits into.`
|
|
1480
2161
|
];
|
|
1481
2162
|
}
|
|
1482
2163
|
function buildDiscoveryPrompt(context, runnerMode) {
|
|
@@ -1496,15 +2177,16 @@ function buildDiscoveryPrompt(context, runnerMode) {
|
|
|
1496
2177
|
`Your PRIMARY goal is to create a thorough plan. Complete these steps in order:`,
|
|
1497
2178
|
`1. Read the task description and chat history \u2014 respond to what's been discussed`,
|
|
1498
2179
|
`2. Investigate the codebase using the methodology below \u2014 search first, read targeted files`,
|
|
1499
|
-
`3. Save a detailed plan via \`
|
|
2180
|
+
`3. Save a detailed plan via \`update_task_plan\``,
|
|
1500
2181
|
`4. Set story points, tags, and title via \`update_task_properties\` (icon is set automatically)`,
|
|
1501
2182
|
`5. Discuss the plan with the team if they're engaged, incorporate feedback`,
|
|
1502
2183
|
`6. THEN call ExitPlanMode \u2014 it is the LAST step, not the first`,
|
|
1503
2184
|
...buildExplorationMethodology(),
|
|
2185
|
+
...buildPlanCitationFormat(),
|
|
1504
2186
|
``,
|
|
1505
2187
|
`### Self-Identification Tools`,
|
|
1506
2188
|
`Use these MCP tools to set your own task properties:`,
|
|
1507
|
-
`- \`
|
|
2189
|
+
`- \`update_task_plan\` \u2014 save your plan and description`,
|
|
1508
2190
|
`- \`update_task_properties\` \u2014 set title, story points, and tags (any combination)`,
|
|
1509
2191
|
`Note: Icons are assigned automatically during identification after planning is complete.`,
|
|
1510
2192
|
``,
|
|
@@ -1527,21 +2209,20 @@ function buildDiscoveryPrompt(context, runnerMode) {
|
|
|
1527
2209
|
`### Subtask Plan Requirements`,
|
|
1528
2210
|
`When creating subtasks, each MUST include a detailed \`plan\` field:`,
|
|
1529
2211
|
`- Plans should be multi-step implementation guides, not vague descriptions`,
|
|
1530
|
-
`- Include
|
|
2212
|
+
`- Include concrete \`file.ts:line\` citations, function/symbol names, and short code snippets where relevant`,
|
|
1531
2213
|
`- Reference existing implementations when relevant (e.g., "follow the pattern in src/services/foo.ts")`,
|
|
1532
2214
|
`- Include testing requirements and acceptance criteria`,
|
|
1533
2215
|
`- Set \`storyPointValue\` based on estimated complexity`,
|
|
1534
2216
|
``,
|
|
1535
2217
|
`### Plan Verification Requirements`,
|
|
1536
|
-
`Every plan MUST include a **Testing / Verification** section
|
|
1537
|
-
`- The quality gates: \`bun run lint\`, \`bun run typecheck\`, \`bun run test\` (or scoped equivalents)`,
|
|
2218
|
+
`Every plan MUST include a **Testing / Verification** section so the build agent has a clear definition of "done". Enumerate:`,
|
|
2219
|
+
`- The quality gates the build agent should run: \`bun run lint\`, \`bun run typecheck\`, \`bun run test\` (or scoped equivalents)`,
|
|
1538
2220
|
`- Any task-specific end-to-end checks (manual UI walk-through, API smoke test, migration dry-run, etc.)`,
|
|
1539
|
-
|
|
1540
|
-
`This ensures executing agents and reviewers have a clear definition of "done" and prevents silent regressions.`,
|
|
2221
|
+
`You are NOT expected to run these gates yourself \u2014 discovery is read-only. Just describe them in the plan.`,
|
|
1541
2222
|
``,
|
|
1542
2223
|
`### Completing Planning`,
|
|
1543
2224
|
`Once ALL checklist items above are done, call the **ExitPlanMode** tool.`,
|
|
1544
|
-
`- Required before ExitPlanMode will succeed: **plan** (via
|
|
2225
|
+
`- Required before ExitPlanMode will succeed: **plan** (via update_task_plan), **story points** (via update_task_properties), **title** (via update_task_properties)`,
|
|
1545
2226
|
`- ExitPlanMode validates these properties and marks planning as complete`,
|
|
1546
2227
|
`- It does NOT start building \u2014 the team controls when to switch to Build mode`,
|
|
1547
2228
|
`- Do NOT call ExitPlanMode until you have thoroughly explored the codebase and saved a detailed plan`
|
|
@@ -1557,11 +2238,11 @@ function buildAutoPrompt(context, runnerMode) {
|
|
|
1557
2238
|
``,
|
|
1558
2239
|
`### Phase 1: Discovery & Planning (current)`,
|
|
1559
2240
|
`- You are in the SDK's plan mode \u2014 read-only access is enforced automatically`,
|
|
1560
|
-
`- You have MCP tools for task properties:
|
|
2241
|
+
`- You have MCP tools for task properties: update_task_plan, update_task_properties`,
|
|
1561
2242
|
``,
|
|
1562
2243
|
`### Required before transitioning:`,
|
|
1563
2244
|
`Before calling ExitPlanMode, you MUST fill in ALL of these:`,
|
|
1564
|
-
`1. **Plan** \u2014 Save a clear implementation plan using
|
|
2245
|
+
`1. **Plan** \u2014 Save a clear implementation plan using update_task_plan`,
|
|
1565
2246
|
`2. **Story Points** \u2014 Assign via update_task_properties`,
|
|
1566
2247
|
`3. **Title** \u2014 Set an accurate title via update_task_properties (if the current one is vague or "Untitled")`,
|
|
1567
2248
|
``,
|
|
@@ -1574,11 +2255,13 @@ function buildAutoPrompt(context, runnerMode) {
|
|
|
1574
2255
|
`### Subtask Plan Requirements`,
|
|
1575
2256
|
`When creating subtasks, each MUST include a detailed \`plan\` field:`,
|
|
1576
2257
|
`- Plans should be multi-step implementation guides, not vague descriptions`,
|
|
1577
|
-
`- Include
|
|
2258
|
+
`- Include concrete \`file.ts:line\` citations, function/symbol names, and short code snippets where relevant`,
|
|
1578
2259
|
`- Reference existing implementations when relevant`,
|
|
1579
2260
|
`- Include testing requirements and acceptance criteria`,
|
|
1580
2261
|
`- Set \`storyPointValue\` based on estimated complexity`,
|
|
1581
2262
|
``,
|
|
2263
|
+
...buildPlanCitationFormat(),
|
|
2264
|
+
``,
|
|
1582
2265
|
...context?.isParentTask ? [
|
|
1583
2266
|
``,
|
|
1584
2267
|
`### Parent Task Guidance`,
|
|
@@ -1648,7 +2331,7 @@ function buildReviewPrompt(context) {
|
|
|
1648
2331
|
`You are reviewing and coordinating child tasks.`,
|
|
1649
2332
|
`- Use \`list_subtasks\` to see current child task state and progress.`,
|
|
1650
2333
|
`- For children in ReviewPR status: review their code quality and merge with \`approve_and_merge_pr\`.`,
|
|
1651
|
-
`- For children with failing CI: check with \`
|
|
2334
|
+
`- For children with failing CI: check with \`get_execution_logs(childTaskId)\` and escalate if stuck.`,
|
|
1652
2335
|
`- Fire next child builds with \`start_child_cloud_build\` when ready.`,
|
|
1653
2336
|
`- Create follow-up tasks for issues discovered during review.`,
|
|
1654
2337
|
``,
|
|
@@ -1725,7 +2408,7 @@ Environment (ready, no setup required):`,
|
|
|
1725
2408
|
`
|
|
1726
2409
|
Workflow:`,
|
|
1727
2410
|
`- You can draft and iterate on plans in .claude/plans/*.md \u2014 these files are automatically synced to the task.`,
|
|
1728
|
-
`- You can also use
|
|
2411
|
+
`- You can also use update_task_plan directly to save the plan to the task.`,
|
|
1729
2412
|
`- 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.`,
|
|
1730
2413
|
`- A separate task agent will handle execution after the team reviews and approves your plan.`
|
|
1731
2414
|
];
|
|
@@ -1752,7 +2435,7 @@ function buildActivePreamble(context, workspaceDir) {
|
|
|
1752
2435
|
`You are an AI project manager in ACTIVE mode for the "${context.title}" project.`,
|
|
1753
2436
|
`You have direct coding access to the repository at ${workspaceDir}.`,
|
|
1754
2437
|
`You can edit files, run tests, and make commits.`,
|
|
1755
|
-
`You still have access to all PM tools (subtasks,
|
|
2438
|
+
`You still have access to all PM tools (subtasks, update_task_plan, chat).`,
|
|
1756
2439
|
`
|
|
1757
2440
|
Environment (ready, no setup required):`,
|
|
1758
2441
|
`- Repository is cloned at your current working directory.`,
|
|
@@ -1879,17 +2562,26 @@ Your responses are sent directly to the task chat \u2014 the team sees everythin
|
|
|
1879
2562
|
}
|
|
1880
2563
|
|
|
1881
2564
|
// src/execution/prompt-builder.ts
|
|
1882
|
-
var TASK_CHAT_HISTORY_LIMIT = 20;
|
|
1883
2565
|
function findLastAgentMessageIndex2(history) {
|
|
1884
2566
|
for (let i = history.length - 1; i >= 0; i--) {
|
|
1885
2567
|
if (history[i].role === "assistant") return i;
|
|
1886
2568
|
}
|
|
1887
2569
|
return -1;
|
|
1888
2570
|
}
|
|
2571
|
+
function messagesAfterCursor(history, lastSeenMessageId) {
|
|
2572
|
+
if (!lastSeenMessageId) return history;
|
|
2573
|
+
const idx = history.findIndex((m) => m.id === lastSeenMessageId);
|
|
2574
|
+
return idx === -1 ? history : history.slice(idx + 1);
|
|
2575
|
+
}
|
|
1889
2576
|
function detectRelaunchScenario(context, trustChatHistory = false) {
|
|
2577
|
+
if (context.lastSeenMessageId) {
|
|
2578
|
+
const newMessages = messagesAfterCursor(context.chatHistory, context.lastSeenMessageId);
|
|
2579
|
+
const hasNewUserMessages2 = newMessages.some((m) => m.role === "user");
|
|
2580
|
+
return hasNewUserMessages2 ? "feedback_relaunch" : "idle_relaunch";
|
|
2581
|
+
}
|
|
1890
2582
|
const lastAgentIdx = findLastAgentMessageIndex2(context.chatHistory);
|
|
1891
2583
|
if (lastAgentIdx === -1) return "fresh";
|
|
1892
|
-
const hasPriorWork = !!context.githubPRUrl ||
|
|
2584
|
+
const hasPriorWork = !!context.githubPRUrl || trustChatHistory;
|
|
1893
2585
|
if (!hasPriorWork) return "fresh";
|
|
1894
2586
|
const messagesAfterAgent = context.chatHistory.slice(lastAgentIdx + 1);
|
|
1895
2587
|
const hasNewUserMessages = messagesAfterAgent.some((m) => m.role === "user");
|
|
@@ -1928,7 +2620,7 @@ CRITICAL: You are in Auto mode. Do NOT report status, ask for confirmation, or g
|
|
|
1928
2620
|
parts.push(
|
|
1929
2621
|
`
|
|
1930
2622
|
You are in auto mode. A plan already exists for this task.`,
|
|
1931
|
-
`Verify that story points, title, and tags are set via
|
|
2623
|
+
`Verify that story points, title, and tags are set via get_current_plan, then call ExitPlanMode immediately to transition to building.`,
|
|
1932
2624
|
`Do NOT wait for team input \u2014 proceed autonomously.`
|
|
1933
2625
|
);
|
|
1934
2626
|
} else {
|
|
@@ -1950,13 +2642,14 @@ You are the project manager for this task.`,
|
|
|
1950
2642
|
}
|
|
1951
2643
|
function buildRelaunchWithSession(mode, context, agentMode, isAuto) {
|
|
1952
2644
|
const scenario = detectRelaunchScenario(context);
|
|
1953
|
-
|
|
2645
|
+
const hasPriorTurn = !!context.lastSeenMessageId || !!context.claudeSessionId;
|
|
2646
|
+
if (!hasPriorTurn || scenario === "fresh") return null;
|
|
1954
2647
|
const parts = [];
|
|
1955
2648
|
const lastAgentIdx = findLastAgentMessageIndex2(context.chatHistory);
|
|
1956
2649
|
if (mode === "pm") {
|
|
1957
2650
|
parts.push(...buildPmRelaunchParts(context, lastAgentIdx, isAuto, agentMode));
|
|
1958
2651
|
} else if (scenario === "feedback_relaunch") {
|
|
1959
|
-
const newMessages = context.chatHistory.slice(lastAgentIdx + 1).filter((m) => m.role === "user");
|
|
2652
|
+
const newMessages = (context.lastSeenMessageId ? messagesAfterCursor(context.chatHistory, context.lastSeenMessageId) : context.chatHistory.slice(lastAgentIdx + 1)).filter((m) => m.role === "user");
|
|
1960
2653
|
parts.push(
|
|
1961
2654
|
`You have been relaunched with new feedback.`,
|
|
1962
2655
|
`Work on the git branch "${context.githubBranch}". Stay on this branch \u2014 do not checkout or create other branches.`,
|
|
@@ -2027,7 +2720,7 @@ ${context.description}`);
|
|
|
2027
2720
|
if (context.plan) {
|
|
2028
2721
|
parts.push(`
|
|
2029
2722
|
## Plan
|
|
2030
|
-
${context.plan}`);
|
|
2723
|
+
${truncatePlanForPrompt(context.plan)}`);
|
|
2031
2724
|
}
|
|
2032
2725
|
if (context.files && context.files.length > 0) {
|
|
2033
2726
|
parts.push(`
|
|
@@ -2039,6 +2732,9 @@ ${context.plan}`);
|
|
|
2039
2732
|
if (context.repoRefs && context.repoRefs.length > 0) {
|
|
2040
2733
|
parts.push(...formatRepoRefs(context.repoRefs));
|
|
2041
2734
|
}
|
|
2735
|
+
if (context.referenceProjects && context.referenceProjects.length > 0) {
|
|
2736
|
+
parts.push(...formatReferenceProjects(context.referenceProjects));
|
|
2737
|
+
}
|
|
2042
2738
|
const tagSection = await resolveTaskTagContext(context, runnerMode);
|
|
2043
2739
|
if (tagSection) parts.push(tagSection);
|
|
2044
2740
|
if (runnerMode !== "task") {
|
|
@@ -2084,7 +2780,7 @@ CRITICAL: You are in Auto mode. Do NOT report status, ask for confirmation, or g
|
|
|
2084
2780
|
return [
|
|
2085
2781
|
`You are operating autonomously. Begin planning immediately.`,
|
|
2086
2782
|
`1. Search the codebase (grep/glob) to locate relevant files, then read the critical ones`,
|
|
2087
|
-
`2. Draft a clear implementation plan and save it with
|
|
2783
|
+
`2. Draft a clear implementation plan and save it with update_task_plan`,
|
|
2088
2784
|
`3. Set story points, tags, and title (update_task_properties)`,
|
|
2089
2785
|
`4. When the plan and all required properties are set, call ExitPlanMode to transition to building`,
|
|
2090
2786
|
`Do NOT wait for team input \u2014 proceed autonomously.`
|
|
@@ -2096,7 +2792,7 @@ CRITICAL: You are in Auto mode. Do NOT report status, ask for confirmation, or g
|
|
|
2096
2792
|
`Review existing subtasks via \`list_subtasks\` and the chat history before taking action.`,
|
|
2097
2793
|
`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.`,
|
|
2098
2794
|
`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.`,
|
|
2099
|
-
`When you finish planning, save the plan with
|
|
2795
|
+
`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.`
|
|
2100
2796
|
];
|
|
2101
2797
|
}
|
|
2102
2798
|
if (isPm) {
|
|
@@ -2104,7 +2800,7 @@ CRITICAL: You are in Auto mode. Do NOT report status, ask for confirmation, or g
|
|
|
2104
2800
|
`You are the project manager for this task.`,
|
|
2105
2801
|
`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.`,
|
|
2106
2802
|
`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.`,
|
|
2107
|
-
`When you finish planning, save the plan with
|
|
2803
|
+
`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.`
|
|
2108
2804
|
];
|
|
2109
2805
|
}
|
|
2110
2806
|
const parts = [
|
|
@@ -2148,7 +2844,7 @@ Your plan has been approved. Address the feedback above, then begin implementing
|
|
|
2148
2844
|
} else if (isAuto) {
|
|
2149
2845
|
parts2.push(
|
|
2150
2846
|
`
|
|
2151
|
-
You are in auto mode. Address the feedback above \u2014 update the plan accordingly using
|
|
2847
|
+
You are in auto mode. Address the feedback above \u2014 update the plan accordingly using update_task_plan.`,
|
|
2152
2848
|
`When the plan and all required properties are set, call ExitPlanMode to transition to building.`,
|
|
2153
2849
|
`Do NOT wait for additional team input \u2014 the messages above ARE the team's input. Proceed autonomously.`
|
|
2154
2850
|
);
|
|
@@ -2259,14 +2955,14 @@ async function buildInitialPrompt(mode, context, isAuto, agentMode) {
|
|
|
2259
2955
|
}
|
|
2260
2956
|
|
|
2261
2957
|
// src/tools/task-context-tools.ts
|
|
2262
|
-
import { z } from "zod";
|
|
2958
|
+
import { z as z4 } from "zod";
|
|
2263
2959
|
function buildReadTaskChatTool(connection) {
|
|
2264
2960
|
return defineTool(
|
|
2265
2961
|
"read_task_chat",
|
|
2266
|
-
"Read recent human/user chat messages for a task.
|
|
2962
|
+
"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.",
|
|
2267
2963
|
{
|
|
2268
|
-
limit:
|
|
2269
|
-
task_id:
|
|
2964
|
+
limit: z4.number().optional().describe("Number of recent messages to fetch (default 20)"),
|
|
2965
|
+
task_id: z4.string().optional().describe("Child task ID to read chat from. Omit to read the current task's chat.")
|
|
2270
2966
|
},
|
|
2271
2967
|
async ({ limit, task_id }) => {
|
|
2272
2968
|
try {
|
|
@@ -2287,10 +2983,10 @@ function buildReadTaskChatTool(connection) {
|
|
|
2287
2983
|
{ annotations: { readOnlyHint: true } }
|
|
2288
2984
|
);
|
|
2289
2985
|
}
|
|
2290
|
-
function
|
|
2986
|
+
function buildGetCurrentPlanTool(connection) {
|
|
2291
2987
|
return defineTool(
|
|
2292
|
-
"
|
|
2293
|
-
"Re-read the current task's plan.
|
|
2988
|
+
"get_current_plan",
|
|
2989
|
+
"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.",
|
|
2294
2990
|
{},
|
|
2295
2991
|
async () => {
|
|
2296
2992
|
try {
|
|
@@ -2308,9 +3004,9 @@ function buildGetTaskPlanTool(connection) {
|
|
|
2308
3004
|
function buildGetTaskTool(connection) {
|
|
2309
3005
|
return defineTool(
|
|
2310
3006
|
"get_task",
|
|
2311
|
-
"Look up any task by slug or ID.
|
|
3007
|
+
"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.",
|
|
2312
3008
|
{
|
|
2313
|
-
slug_or_id:
|
|
3009
|
+
slug_or_id: z4.string().describe("The task slug (e.g. 'my-task') or CUID")
|
|
2314
3010
|
},
|
|
2315
3011
|
async ({ slug_or_id }) => {
|
|
2316
3012
|
try {
|
|
@@ -2328,14 +3024,14 @@ function buildGetTaskTool(connection) {
|
|
|
2328
3024
|
{ annotations: { readOnlyHint: true } }
|
|
2329
3025
|
);
|
|
2330
3026
|
}
|
|
2331
|
-
function
|
|
3027
|
+
function buildGetExecutionLogsTool(connection) {
|
|
2332
3028
|
return defineTool(
|
|
2333
|
-
"
|
|
2334
|
-
"Read CLI execution logs
|
|
3029
|
+
"get_execution_logs",
|
|
3030
|
+
"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.",
|
|
2335
3031
|
{
|
|
2336
|
-
task_id:
|
|
2337
|
-
source:
|
|
2338
|
-
limit:
|
|
3032
|
+
task_id: z4.string().optional().describe("Task ID or slug. Omit to read logs from the current task."),
|
|
3033
|
+
source: z4.enum(["agent", "application"]).optional().describe("Filter by log source. Omit for all logs."),
|
|
3034
|
+
limit: z4.number().optional().describe("Max number of log entries to return (default 50, max 500).")
|
|
2339
3035
|
},
|
|
2340
3036
|
async ({ task_id, source, limit }) => {
|
|
2341
3037
|
try {
|
|
@@ -2364,7 +3060,7 @@ function buildGetTaskCliTool(connection) {
|
|
|
2364
3060
|
function buildListTaskFilesTool(connection) {
|
|
2365
3061
|
return defineTool(
|
|
2366
3062
|
"list_task_files",
|
|
2367
|
-
"List all files attached to this task with metadata.
|
|
3063
|
+
"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.",
|
|
2368
3064
|
{},
|
|
2369
3065
|
async () => {
|
|
2370
3066
|
try {
|
|
@@ -2391,11 +3087,11 @@ function buildListTaskFilesTool(connection) {
|
|
|
2391
3087
|
{ annotations: { readOnlyHint: true } }
|
|
2392
3088
|
);
|
|
2393
3089
|
}
|
|
2394
|
-
function
|
|
3090
|
+
function buildGetAttachmentTool(connection) {
|
|
2395
3091
|
return defineTool(
|
|
2396
|
-
"
|
|
2397
|
-
"Fetch one task file's content plus metadata by file ID.
|
|
2398
|
-
{ fileId:
|
|
3092
|
+
"get_attachment",
|
|
3093
|
+
"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.",
|
|
3094
|
+
{ fileId: z4.string().describe("The file ID to retrieve") },
|
|
2399
3095
|
async ({ fileId }) => {
|
|
2400
3096
|
try {
|
|
2401
3097
|
const file = await connection.call("getTaskFile", {
|
|
@@ -2424,20 +3120,20 @@ function buildGetTaskFileTool(connection) {
|
|
|
2424
3120
|
function buildTaskContextTools(connection) {
|
|
2425
3121
|
return [
|
|
2426
3122
|
buildReadTaskChatTool(connection),
|
|
2427
|
-
|
|
3123
|
+
buildGetCurrentPlanTool(connection),
|
|
2428
3124
|
buildGetTaskTool(connection),
|
|
2429
|
-
|
|
3125
|
+
buildGetExecutionLogsTool(connection),
|
|
2430
3126
|
buildListTaskFilesTool(connection),
|
|
2431
|
-
|
|
3127
|
+
buildGetAttachmentTool(connection)
|
|
2432
3128
|
];
|
|
2433
3129
|
}
|
|
2434
3130
|
|
|
2435
3131
|
// src/tools/dependency-suggestion-tools.ts
|
|
2436
|
-
import { z as
|
|
3132
|
+
import { z as z5 } from "zod";
|
|
2437
3133
|
function buildGetDependenciesTool(connection) {
|
|
2438
3134
|
return defineTool(
|
|
2439
3135
|
"get_dependencies",
|
|
2440
|
-
"Get this task's dependencies and their
|
|
3136
|
+
"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.",
|
|
2441
3137
|
{},
|
|
2442
3138
|
async () => {
|
|
2443
3139
|
try {
|
|
@@ -2457,12 +3153,12 @@ function buildGetDependenciesTool(connection) {
|
|
|
2457
3153
|
function buildGetSuggestionsTool(connection) {
|
|
2458
3154
|
return defineTool(
|
|
2459
3155
|
"get_suggestions",
|
|
2460
|
-
"List project suggestions sorted by vote score.
|
|
3156
|
+
"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.",
|
|
2461
3157
|
{
|
|
2462
|
-
status:
|
|
3158
|
+
status: z5.string().optional().describe(
|
|
2463
3159
|
"Filter by status: Planning, Open, InProgress, ReviewPR, ReviewDev, ReviewLive, Complete, Cancelled"
|
|
2464
3160
|
),
|
|
2465
|
-
limit:
|
|
3161
|
+
limit: z5.number().int().min(1).max(100).optional().describe("Max results (default 20)")
|
|
2466
3162
|
},
|
|
2467
3163
|
async ({ status, limit }) => {
|
|
2468
3164
|
try {
|
|
@@ -2486,14 +3182,14 @@ function buildGetSuggestionsTool(connection) {
|
|
|
2486
3182
|
}
|
|
2487
3183
|
|
|
2488
3184
|
// src/tools/mutation-tools.ts
|
|
2489
|
-
import { z as
|
|
3185
|
+
import { z as z6 } from "zod";
|
|
2490
3186
|
function buildPostToChatTool(connection) {
|
|
2491
3187
|
return defineTool(
|
|
2492
3188
|
"post_to_chat",
|
|
2493
|
-
"Post an out-of-band message to a task
|
|
3189
|
+
"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.",
|
|
2494
3190
|
{
|
|
2495
|
-
message:
|
|
2496
|
-
task_id:
|
|
3191
|
+
message: z6.string().describe("The message to post to the team"),
|
|
3192
|
+
task_id: z6.string().optional().describe("Child task ID to post to. Omit to post to the current task's chat.")
|
|
2497
3193
|
},
|
|
2498
3194
|
async ({ message, task_id }) => {
|
|
2499
3195
|
try {
|
|
@@ -2503,10 +3199,21 @@ function buildPostToChatTool(connection) {
|
|
|
2503
3199
|
childTaskId: task_id,
|
|
2504
3200
|
message
|
|
2505
3201
|
});
|
|
2506
|
-
return textResult(
|
|
3202
|
+
return textResult(JSON.stringify({ posted: true, target: `child:${task_id}` }));
|
|
3203
|
+
}
|
|
3204
|
+
const dedup = connection.checkAndTrackDuplicate(message);
|
|
3205
|
+
if (dedup.duplicate) {
|
|
3206
|
+
return textResult(
|
|
3207
|
+
JSON.stringify({
|
|
3208
|
+
posted: false,
|
|
3209
|
+
reason: "duplicate",
|
|
3210
|
+
matchedMessagePreview: dedup.matchedMessagePreview,
|
|
3211
|
+
hint: "A near-identical message (>70% word overlap) was posted within the last 30s. Rephrase with new information or skip this post."
|
|
3212
|
+
})
|
|
3213
|
+
);
|
|
2507
3214
|
}
|
|
2508
3215
|
await connection.call("postToChat", { message });
|
|
2509
|
-
return textResult(
|
|
3216
|
+
return textResult(JSON.stringify({ posted: true }));
|
|
2510
3217
|
} catch (error) {
|
|
2511
3218
|
return textResult(
|
|
2512
3219
|
`Failed to post message: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
@@ -2518,10 +3225,10 @@ function buildPostToChatTool(connection) {
|
|
|
2518
3225
|
function buildForceUpdateTaskStatusTool(connection) {
|
|
2519
3226
|
return defineTool(
|
|
2520
3227
|
"force_update_task_status",
|
|
2521
|
-
"EMERGENCY ONLY: force-override a task's Kanban status.
|
|
3228
|
+
"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.",
|
|
2522
3229
|
{
|
|
2523
|
-
status:
|
|
2524
|
-
task_id:
|
|
3230
|
+
status: z6.enum(["InProgress", "ReviewPR", "ReviewDev", "Complete"]).describe("The new status for the task"),
|
|
3231
|
+
task_id: z6.string().optional().describe("Child task ID to update. Omit to update the current task.")
|
|
2525
3232
|
},
|
|
2526
3233
|
async ({ status, task_id }) => {
|
|
2527
3234
|
try {
|
|
@@ -2550,17 +3257,17 @@ function buildForceUpdateTaskStatusTool(connection) {
|
|
|
2550
3257
|
function buildCreatePullRequestTool(connection, config) {
|
|
2551
3258
|
return defineTool(
|
|
2552
3259
|
"create_pull_request",
|
|
2553
|
-
"Create a GitHub
|
|
3260
|
+
"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.",
|
|
2554
3261
|
{
|
|
2555
|
-
title:
|
|
2556
|
-
body:
|
|
2557
|
-
branch:
|
|
3262
|
+
title: z6.string().describe("The PR title"),
|
|
3263
|
+
body: z6.string().describe("The PR description/body in markdown"),
|
|
3264
|
+
branch: z6.string().optional().describe(
|
|
2558
3265
|
"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."
|
|
2559
3266
|
),
|
|
2560
|
-
baseBranch:
|
|
3267
|
+
baseBranch: z6.string().optional().describe(
|
|
2561
3268
|
"The base branch to target for the PR (e.g. 'main', 'develop'). Defaults to the project's configured dev branch."
|
|
2562
3269
|
),
|
|
2563
|
-
commitMessage:
|
|
3270
|
+
commitMessage: z6.string().optional().describe(
|
|
2564
3271
|
"Commit message for staging uncommitted changes. If not provided, a default message based on the PR title will be used."
|
|
2565
3272
|
)
|
|
2566
3273
|
},
|
|
@@ -2636,9 +3343,9 @@ Troubleshooting:
|
|
|
2636
3343
|
function buildAddDependencyTool(connection) {
|
|
2637
3344
|
return defineTool(
|
|
2638
3345
|
"add_dependency",
|
|
2639
|
-
"Add a blocking dependency \u2014 this task cannot start until the named task is merged to dev.
|
|
3346
|
+
"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.",
|
|
2640
3347
|
{
|
|
2641
|
-
depends_on_slug_or_id:
|
|
3348
|
+
depends_on_slug_or_id: z6.string().describe("Slug or ID of the task this task depends on")
|
|
2642
3349
|
},
|
|
2643
3350
|
async ({ depends_on_slug_or_id }) => {
|
|
2644
3351
|
try {
|
|
@@ -2660,7 +3367,7 @@ function buildRemoveDependencyTool(connection) {
|
|
|
2660
3367
|
"remove_dependency",
|
|
2661
3368
|
"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.",
|
|
2662
3369
|
{
|
|
2663
|
-
depends_on_slug_or_id:
|
|
3370
|
+
depends_on_slug_or_id: z6.string().describe("Slug or ID of the task to remove as dependency")
|
|
2664
3371
|
},
|
|
2665
3372
|
async ({ depends_on_slug_or_id }) => {
|
|
2666
3373
|
try {
|
|
@@ -2680,12 +3387,12 @@ function buildRemoveDependencyTool(connection) {
|
|
|
2680
3387
|
function buildCreateFollowUpTaskTool(connection) {
|
|
2681
3388
|
return defineTool(
|
|
2682
3389
|
"create_follow_up_task",
|
|
2683
|
-
"Create a follow-up task that depends on the current task.
|
|
3390
|
+
"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.",
|
|
2684
3391
|
{
|
|
2685
|
-
title:
|
|
2686
|
-
description:
|
|
2687
|
-
plan:
|
|
2688
|
-
story_point_value:
|
|
3392
|
+
title: z6.string().describe("Follow-up task title"),
|
|
3393
|
+
description: z6.string().optional().describe("Brief description of the follow-up work"),
|
|
3394
|
+
plan: z6.string().optional().describe("Implementation plan if known"),
|
|
3395
|
+
story_point_value: z6.number().optional().describe("Story point estimate (1=Common, 2=Magic, 3=Rare, 5=Unique)")
|
|
2689
3396
|
},
|
|
2690
3397
|
async ({ title, description, plan, story_point_value }) => {
|
|
2691
3398
|
try {
|
|
@@ -2710,13 +3417,13 @@ function buildCreateFollowUpTaskTool(connection) {
|
|
|
2710
3417
|
function buildCreateSuggestionTool(connection) {
|
|
2711
3418
|
return defineTool(
|
|
2712
3419
|
"create_suggestion",
|
|
2713
|
-
"Suggest a feature, improvement, rule, or idea for the project.
|
|
3420
|
+
"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.",
|
|
2714
3421
|
{
|
|
2715
|
-
title:
|
|
2716
|
-
description:
|
|
3422
|
+
title: z6.string().describe("Short title for the suggestion"),
|
|
3423
|
+
description: z6.string().optional().describe(
|
|
2717
3424
|
"1-2 sentence description of what should change and why. Keep concise and project-focused."
|
|
2718
3425
|
),
|
|
2719
|
-
tag_names:
|
|
3426
|
+
tag_names: z6.array(z6.string()).optional().describe("Tag names to categorize the suggestion")
|
|
2720
3427
|
},
|
|
2721
3428
|
async ({ title, description, tag_names }) => {
|
|
2722
3429
|
try {
|
|
@@ -2743,10 +3450,10 @@ function buildCreateSuggestionTool(connection) {
|
|
|
2743
3450
|
function buildVoteSuggestionTool(connection) {
|
|
2744
3451
|
return defineTool(
|
|
2745
3452
|
"vote_suggestion",
|
|
2746
|
-
"Vote +1 or -1 on a project suggestion.
|
|
3453
|
+
"Vote +1 or -1 on a project suggestion. Use to express support or disagreement with a specific suggestion returned by get_suggestions.",
|
|
2747
3454
|
{
|
|
2748
|
-
suggestion_id:
|
|
2749
|
-
value:
|
|
3455
|
+
suggestion_id: z6.string().describe("The suggestion ID to vote on"),
|
|
3456
|
+
value: z6.number().refine((v) => v === 1 || v === -1, { message: "Value must be 1 or -1" }).describe("+1 to upvote, -1 to downvote")
|
|
2750
3457
|
},
|
|
2751
3458
|
async ({ suggestion_id, value }) => {
|
|
2752
3459
|
try {
|
|
@@ -2787,15 +3494,15 @@ function buildCommonTools(connection, config) {
|
|
|
2787
3494
|
}
|
|
2788
3495
|
|
|
2789
3496
|
// src/tools/pm-tools.ts
|
|
2790
|
-
import { z as
|
|
3497
|
+
import { z as z7 } from "zod";
|
|
2791
3498
|
var SP_DESCRIPTION = "Story point value (1=Common, 2=Magic, 3=Rare, 5=Unique)";
|
|
2792
3499
|
function buildUpdateTaskTool(connection) {
|
|
2793
3500
|
return defineTool(
|
|
2794
|
-
"
|
|
2795
|
-
"Save the finalized plan and/or description to the current task.
|
|
3501
|
+
"update_task_plan",
|
|
3502
|
+
"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.",
|
|
2796
3503
|
{
|
|
2797
|
-
plan:
|
|
2798
|
-
description:
|
|
3504
|
+
plan: z7.string().optional().describe("The task plan in markdown"),
|
|
3505
|
+
description: z7.string().optional().describe("Updated task description")
|
|
2799
3506
|
},
|
|
2800
3507
|
async ({ plan, description }) => {
|
|
2801
3508
|
try {
|
|
@@ -2814,13 +3521,13 @@ function buildUpdateTaskTool(connection) {
|
|
|
2814
3521
|
function buildCreateSubtaskTool(connection) {
|
|
2815
3522
|
return defineTool(
|
|
2816
3523
|
"create_subtask",
|
|
2817
|
-
"Create a subtask under the current parent task.
|
|
3524
|
+
"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.",
|
|
2818
3525
|
{
|
|
2819
|
-
title:
|
|
2820
|
-
description:
|
|
2821
|
-
plan:
|
|
2822
|
-
ordinal:
|
|
2823
|
-
storyPointValue:
|
|
3526
|
+
title: z7.string().describe("Subtask title"),
|
|
3527
|
+
description: z7.string().optional().describe("Brief description"),
|
|
3528
|
+
plan: z7.string().optional().describe("Implementation plan in markdown"),
|
|
3529
|
+
ordinal: z7.number().optional().describe("Step/order number (0-based)"),
|
|
3530
|
+
storyPointValue: z7.number().optional().describe(SP_DESCRIPTION)
|
|
2824
3531
|
},
|
|
2825
3532
|
async ({ title, description, plan, ordinal, storyPointValue }) => {
|
|
2826
3533
|
try {
|
|
@@ -2844,14 +3551,14 @@ function buildCreateSubtaskTool(connection) {
|
|
|
2844
3551
|
function buildUpdateSubtaskTool(connection) {
|
|
2845
3552
|
return defineTool(
|
|
2846
3553
|
"update_subtask",
|
|
2847
|
-
"Update an existing subtask's fields (title, description, plan, ordinal, storyPointValue).
|
|
3554
|
+
"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.",
|
|
2848
3555
|
{
|
|
2849
|
-
subtaskId:
|
|
2850
|
-
title:
|
|
2851
|
-
description:
|
|
2852
|
-
plan:
|
|
2853
|
-
ordinal:
|
|
2854
|
-
storyPointValue:
|
|
3556
|
+
subtaskId: z7.string().describe("The subtask ID to update"),
|
|
3557
|
+
title: z7.string().optional(),
|
|
3558
|
+
description: z7.string().optional(),
|
|
3559
|
+
plan: z7.string().optional(),
|
|
3560
|
+
ordinal: z7.number().optional(),
|
|
3561
|
+
storyPointValue: z7.number().optional().describe(SP_DESCRIPTION)
|
|
2855
3562
|
},
|
|
2856
3563
|
async ({ subtaskId, title, description, plan, storyPointValue }) => {
|
|
2857
3564
|
try {
|
|
@@ -2874,7 +3581,7 @@ function buildDeleteSubtaskTool(connection) {
|
|
|
2874
3581
|
return defineTool(
|
|
2875
3582
|
"delete_subtask",
|
|
2876
3583
|
"Delete a subtask by id. When to use: a subtask was created in error or is no longer needed. Returns: confirmation string.",
|
|
2877
|
-
{ subtaskId:
|
|
3584
|
+
{ subtaskId: z7.string().describe("The subtask ID to delete") },
|
|
2878
3585
|
async ({ subtaskId }) => {
|
|
2879
3586
|
try {
|
|
2880
3587
|
await connection.call("deleteSubtask", {
|
|
@@ -2891,7 +3598,7 @@ function buildDeleteSubtaskTool(connection) {
|
|
|
2891
3598
|
function buildListSubtasksTool(connection) {
|
|
2892
3599
|
return defineTool(
|
|
2893
3600
|
"list_subtasks",
|
|
2894
|
-
"List all subtasks under the current parent task.
|
|
3601
|
+
"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.",
|
|
2895
3602
|
{},
|
|
2896
3603
|
async () => {
|
|
2897
3604
|
try {
|
|
@@ -2910,9 +3617,9 @@ function buildPackTools(connection) {
|
|
|
2910
3617
|
return [
|
|
2911
3618
|
defineTool(
|
|
2912
3619
|
"start_child_cloud_build",
|
|
2913
|
-
"Start a cloud build (codespace) for a child task. Preconditions:
|
|
3620
|
+
"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.",
|
|
2914
3621
|
{
|
|
2915
|
-
childTaskId:
|
|
3622
|
+
childTaskId: z7.string().describe("The child task ID to start a cloud build for")
|
|
2916
3623
|
},
|
|
2917
3624
|
async ({ childTaskId }) => {
|
|
2918
3625
|
try {
|
|
@@ -2930,9 +3637,9 @@ function buildPackTools(connection) {
|
|
|
2930
3637
|
),
|
|
2931
3638
|
defineTool(
|
|
2932
3639
|
"stop_child_build",
|
|
2933
|
-
"Send a graceful stop signal to a running child build's agent.
|
|
3640
|
+
"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.",
|
|
2934
3641
|
{
|
|
2935
|
-
childTaskId:
|
|
3642
|
+
childTaskId: z7.string().describe("The child task ID whose build should be stopped")
|
|
2936
3643
|
},
|
|
2937
3644
|
async ({ childTaskId }) => {
|
|
2938
3645
|
try {
|
|
@@ -2950,9 +3657,9 @@ function buildPackTools(connection) {
|
|
|
2950
3657
|
),
|
|
2951
3658
|
defineTool(
|
|
2952
3659
|
"approve_and_merge_pr",
|
|
2953
|
-
"Approve and merge a child task's PR. Preconditions: child
|
|
3660
|
+
"Approve and merge a child task's PR. Preconditions: child in ReviewPR. Returns { merged }: true = merged (status\u2192ReviewDev); false = automerge queued, wait for ReviewDev.",
|
|
2954
3661
|
{
|
|
2955
|
-
childTaskId:
|
|
3662
|
+
childTaskId: z7.string().describe("The child task ID whose PR should be approved and merged")
|
|
2956
3663
|
},
|
|
2957
3664
|
async ({ childTaskId }) => {
|
|
2958
3665
|
try {
|
|
@@ -2990,7 +3697,7 @@ function buildPmTools(connection, options) {
|
|
|
2990
3697
|
}
|
|
2991
3698
|
|
|
2992
3699
|
// src/tools/discovery-tools.ts
|
|
2993
|
-
import { z as
|
|
3700
|
+
import { z as z8 } from "zod";
|
|
2994
3701
|
var SP_DESCRIPTION2 = "Story point value (1=Common, 2=Magic, 3=Rare, 5=Unique)";
|
|
2995
3702
|
function buildDiscoveryTools(connection) {
|
|
2996
3703
|
return [
|
|
@@ -2998,11 +3705,11 @@ function buildDiscoveryTools(connection) {
|
|
|
2998
3705
|
"update_task_properties",
|
|
2999
3706
|
"Set one or more task properties in a single call. All fields are optional \u2014 only include the fields you want to update.",
|
|
3000
3707
|
{
|
|
3001
|
-
title:
|
|
3002
|
-
storyPointValue:
|
|
3003
|
-
tagNames:
|
|
3004
|
-
githubPRUrl:
|
|
3005
|
-
githubBranch:
|
|
3708
|
+
title: z8.string().optional().describe("The new task title"),
|
|
3709
|
+
storyPointValue: z8.number().optional().describe(SP_DESCRIPTION2),
|
|
3710
|
+
tagNames: z8.array(z8.string()).optional().describe("Array of tag names to assign"),
|
|
3711
|
+
githubPRUrl: z8.string().url().optional().describe("GitHub pull request URL to link to this task"),
|
|
3712
|
+
githubBranch: z8.string().optional().describe("Set the GitHub branch name for this task (e.g. 'conveyor/my-feature-abc123')")
|
|
3006
3713
|
},
|
|
3007
3714
|
async ({ title, storyPointValue, tagNames, githubPRUrl, githubBranch }) => {
|
|
3008
3715
|
try {
|
|
@@ -3033,14 +3740,14 @@ function buildDiscoveryTools(connection) {
|
|
|
3033
3740
|
}
|
|
3034
3741
|
|
|
3035
3742
|
// src/tools/code-review-tools.ts
|
|
3036
|
-
import { z as
|
|
3743
|
+
import { z as z9 } from "zod";
|
|
3037
3744
|
function buildCodeReviewTools(connection) {
|
|
3038
3745
|
return [
|
|
3039
3746
|
defineTool(
|
|
3040
3747
|
"approve_code_review",
|
|
3041
|
-
"Approve the code review and exit.
|
|
3748
|
+
"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.",
|
|
3042
3749
|
{
|
|
3043
|
-
summary:
|
|
3750
|
+
summary: z9.string().describe("Brief summary of what was reviewed and why it looks good")
|
|
3044
3751
|
},
|
|
3045
3752
|
async ({ summary }) => {
|
|
3046
3753
|
const content = `**Code Review: Approved** :white_check_mark:
|
|
@@ -3061,17 +3768,17 @@ ${summary}`;
|
|
|
3061
3768
|
),
|
|
3062
3769
|
defineTool(
|
|
3063
3770
|
"request_code_changes",
|
|
3064
|
-
"Request changes during code review and exit.
|
|
3771
|
+
"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 }.",
|
|
3065
3772
|
{
|
|
3066
|
-
issues:
|
|
3067
|
-
|
|
3068
|
-
file:
|
|
3069
|
-
line:
|
|
3070
|
-
severity:
|
|
3071
|
-
description:
|
|
3773
|
+
issues: z9.array(
|
|
3774
|
+
z9.object({
|
|
3775
|
+
file: z9.string().describe("File path where the issue was found"),
|
|
3776
|
+
line: z9.number().optional().describe("Line number (if applicable)"),
|
|
3777
|
+
severity: z9.enum(["critical", "major", "minor"]).describe("Issue severity"),
|
|
3778
|
+
description: z9.string().describe("What is wrong and how to fix it")
|
|
3072
3779
|
})
|
|
3073
3780
|
).describe("List of issues found during review"),
|
|
3074
|
-
summary:
|
|
3781
|
+
summary: z9.string().describe("Brief overall summary of the review findings")
|
|
3075
3782
|
},
|
|
3076
3783
|
async ({ issues, summary }) => {
|
|
3077
3784
|
const issueLines = issues.map((issue) => {
|
|
@@ -3101,10 +3808,10 @@ ${issueLines}`;
|
|
|
3101
3808
|
}
|
|
3102
3809
|
|
|
3103
3810
|
// src/tools/debug-tools.ts
|
|
3104
|
-
import { z as
|
|
3811
|
+
import { z as z12 } from "zod";
|
|
3105
3812
|
|
|
3106
3813
|
// src/tools/telemetry-tools.ts
|
|
3107
|
-
import { z as
|
|
3814
|
+
import { z as z10 } from "zod";
|
|
3108
3815
|
|
|
3109
3816
|
// src/debug/telemetry-injector.ts
|
|
3110
3817
|
var BUFFER_SIZE = 200;
|
|
@@ -3497,14 +4204,14 @@ function formatError(error) {
|
|
|
3497
4204
|
function buildGetTelemetryTool(manager) {
|
|
3498
4205
|
return defineTool(
|
|
3499
4206
|
"debug_get_telemetry",
|
|
3500
|
-
"Query structured telemetry events (HTTP
|
|
4207
|
+
"Query structured telemetry events (HTTP, DB, Socket.IO, errors) captured from the dev server. Returns filtered structured data instead of raw logs.",
|
|
3501
4208
|
{
|
|
3502
|
-
type:
|
|
3503
|
-
urlPattern:
|
|
3504
|
-
minDuration:
|
|
3505
|
-
errorOnly:
|
|
3506
|
-
since:
|
|
3507
|
-
limit:
|
|
4209
|
+
type: z10.enum(["http", "db", "socket", "error"]).optional().describe("Filter by event type"),
|
|
4210
|
+
urlPattern: z10.string().optional().describe("Regex pattern to filter HTTP events by URL"),
|
|
4211
|
+
minDuration: z10.number().optional().describe("Minimum duration in ms \u2014 only return events slower than this"),
|
|
4212
|
+
errorOnly: z10.boolean().optional().describe("Only return error events and HTTP 4xx/5xx responses"),
|
|
4213
|
+
since: z10.number().optional().describe("Only return events after this timestamp (ms since epoch)"),
|
|
4214
|
+
limit: z10.number().optional().describe("Max events to return (default: 20, from most recent)")
|
|
3508
4215
|
},
|
|
3509
4216
|
async ({ type, urlPattern, minDuration, errorOnly, since, limit }) => {
|
|
3510
4217
|
const clientOrErr = requireDebugClient(manager);
|
|
@@ -3574,7 +4281,7 @@ function buildTelemetryTools(manager) {
|
|
|
3574
4281
|
}
|
|
3575
4282
|
|
|
3576
4283
|
// src/tools/client-debug-tools.ts
|
|
3577
|
-
import { z as
|
|
4284
|
+
import { z as z11 } from "zod";
|
|
3578
4285
|
function requirePlaywrightClient(manager) {
|
|
3579
4286
|
if (!manager.isClientDebugMode()) {
|
|
3580
4287
|
return "Client debug mode is not active. Use debug_enter_mode with clientSide: true first.";
|
|
@@ -3592,13 +4299,13 @@ function buildClientBreakpointTools(manager) {
|
|
|
3592
4299
|
return [
|
|
3593
4300
|
defineTool(
|
|
3594
4301
|
"debug_set_client_breakpoint",
|
|
3595
|
-
"Set a breakpoint in client-side code running in
|
|
4302
|
+
"Set a breakpoint in client-side code running in headless Chromium. V8 resolves source maps automatically \u2014 use original .tsx/.ts file paths.",
|
|
3596
4303
|
{
|
|
3597
|
-
file:
|
|
4304
|
+
file: z11.string().describe(
|
|
3598
4305
|
"Original source file path (e.g., src/components/App.tsx) \u2014 source maps resolve automatically"
|
|
3599
4306
|
),
|
|
3600
|
-
line:
|
|
3601
|
-
condition:
|
|
4307
|
+
line: z11.number().describe("Line number (1-based) in the original source file"),
|
|
4308
|
+
condition: z11.string().optional().describe("JavaScript condition expression \u2014 breakpoint only triggers when truthy")
|
|
3602
4309
|
},
|
|
3603
4310
|
async ({ file, line, condition }) => {
|
|
3604
4311
|
const clientOrErr = requirePlaywrightClient(manager);
|
|
@@ -3620,7 +4327,7 @@ Breakpoint ID: ${breakpointId}${sourceMapNote}`
|
|
|
3620
4327
|
"debug_remove_client_breakpoint",
|
|
3621
4328
|
"Remove a previously set client-side breakpoint by its ID.",
|
|
3622
4329
|
{
|
|
3623
|
-
breakpointId:
|
|
4330
|
+
breakpointId: z11.string().describe("The breakpoint ID returned by debug_set_client_breakpoint")
|
|
3624
4331
|
},
|
|
3625
4332
|
async ({ breakpointId }) => {
|
|
3626
4333
|
const clientOrErr = requirePlaywrightClient(manager);
|
|
@@ -3655,7 +4362,7 @@ function buildClientInspectionTools(manager) {
|
|
|
3655
4362
|
return [
|
|
3656
4363
|
defineTool(
|
|
3657
4364
|
"debug_inspect_client_paused",
|
|
3658
|
-
"When the client
|
|
4365
|
+
"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.",
|
|
3659
4366
|
{},
|
|
3660
4367
|
async () => {
|
|
3661
4368
|
const clientOrErr = requirePlaywrightClient(manager);
|
|
@@ -3698,10 +4405,10 @@ ${JSON.stringify(queuedHits, null, 2)}`
|
|
|
3698
4405
|
),
|
|
3699
4406
|
defineTool(
|
|
3700
4407
|
"debug_evaluate_client",
|
|
3701
|
-
"Evaluate a JavaScript expression in the browser context. When paused
|
|
4408
|
+
"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.",
|
|
3702
4409
|
{
|
|
3703
|
-
expression:
|
|
3704
|
-
frameIndex:
|
|
4410
|
+
expression: z11.string().describe("JavaScript expression to evaluate in the browser context"),
|
|
4411
|
+
frameIndex: z11.number().optional().describe("Call stack frame index (0 = top frame). Defaults to the top frame.")
|
|
3705
4412
|
},
|
|
3706
4413
|
async ({ expression, frameIndex }) => {
|
|
3707
4414
|
const clientOrErr = requirePlaywrightClient(manager);
|
|
@@ -3772,9 +4479,9 @@ function buildClientInteractionTools(manager) {
|
|
|
3772
4479
|
),
|
|
3773
4480
|
defineTool(
|
|
3774
4481
|
"debug_navigate_client",
|
|
3775
|
-
"Navigate the headless browser to a URL.
|
|
4482
|
+
"Navigate the headless browser to a URL. Waits for domcontentloaded (Playwright's default ~30s timeout applies).",
|
|
3776
4483
|
{
|
|
3777
|
-
url:
|
|
4484
|
+
url: z11.string().describe("URL to navigate to (e.g., http://localhost:3000/dashboard)")
|
|
3778
4485
|
},
|
|
3779
4486
|
async ({ url }) => {
|
|
3780
4487
|
const clientOrErr = requirePlaywrightClient(manager);
|
|
@@ -3789,9 +4496,9 @@ function buildClientInteractionTools(manager) {
|
|
|
3789
4496
|
),
|
|
3790
4497
|
defineTool(
|
|
3791
4498
|
"debug_click_client",
|
|
3792
|
-
"Click an element in the headless browser by CSS selector.
|
|
4499
|
+
"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.",
|
|
3793
4500
|
{
|
|
3794
|
-
selector:
|
|
4501
|
+
selector: z11.string().describe(
|
|
3795
4502
|
"CSS selector of the element to click (e.g., 'button.submit', '#login-form input[type=submit]')"
|
|
3796
4503
|
)
|
|
3797
4504
|
},
|
|
@@ -3813,8 +4520,8 @@ function buildClientConsoleTool(manager) {
|
|
|
3813
4520
|
"debug_get_client_console",
|
|
3814
4521
|
"Get console messages captured from the headless browser. Includes console.log, warn, error, etc.",
|
|
3815
4522
|
{
|
|
3816
|
-
level:
|
|
3817
|
-
limit:
|
|
4523
|
+
level: z11.string().optional().describe("Filter by console level: log, warn, error, info, debug"),
|
|
4524
|
+
limit: z11.number().optional().describe("Maximum number of recent messages to return (default: all)")
|
|
3818
4525
|
},
|
|
3819
4526
|
// oxlint-disable-next-line require-await
|
|
3820
4527
|
async ({ level, limit }) => {
|
|
@@ -3841,8 +4548,8 @@ function buildClientNetworkTool(manager) {
|
|
|
3841
4548
|
"debug_get_client_network",
|
|
3842
4549
|
"Get network requests captured from the headless browser. Shows URLs, methods, status codes, and timing.",
|
|
3843
4550
|
{
|
|
3844
|
-
filter:
|
|
3845
|
-
limit:
|
|
4551
|
+
filter: z11.string().optional().describe("Regex pattern to filter requests by URL"),
|
|
4552
|
+
limit: z11.number().optional().describe("Maximum number of recent requests to return (default: all)")
|
|
3846
4553
|
},
|
|
3847
4554
|
// oxlint-disable-next-line require-await
|
|
3848
4555
|
async ({ filter, limit }) => {
|
|
@@ -3870,7 +4577,7 @@ function buildClientErrorsTool(manager) {
|
|
|
3870
4577
|
"debug_get_client_errors",
|
|
3871
4578
|
"Get uncaught errors captured from the headless browser. Includes error messages and source-mapped stack traces.",
|
|
3872
4579
|
{
|
|
3873
|
-
limit:
|
|
4580
|
+
limit: z11.number().optional().describe("Maximum number of recent errors to return (default: all)")
|
|
3874
4581
|
},
|
|
3875
4582
|
// oxlint-disable-next-line require-await
|
|
3876
4583
|
async ({ limit }) => {
|
|
@@ -3962,14 +4669,14 @@ function buildDebugLifecycleTools(manager) {
|
|
|
3962
4669
|
return [
|
|
3963
4670
|
defineTool(
|
|
3964
4671
|
"debug_enter_mode",
|
|
3965
|
-
"Activate debug mode.
|
|
4672
|
+
"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).",
|
|
3966
4673
|
{
|
|
3967
|
-
hypothesis:
|
|
3968
|
-
serverSide:
|
|
4674
|
+
hypothesis: z12.string().optional().describe("Your hypothesis about the bug \u2014 helps track debugging intent"),
|
|
4675
|
+
serverSide: z12.boolean().optional().describe(
|
|
3969
4676
|
"Enable server-side Node.js debugging (default: true if clientSide is not set)"
|
|
3970
4677
|
),
|
|
3971
|
-
clientSide:
|
|
3972
|
-
previewUrl:
|
|
4678
|
+
clientSide: z12.boolean().optional().describe("Enable client-side browser debugging via headless Chromium + Playwright"),
|
|
4679
|
+
previewUrl: z12.string().optional().describe(
|
|
3973
4680
|
"Preview URL for client-side debugging (e.g., http://localhost:3000). Required when clientSide is true."
|
|
3974
4681
|
)
|
|
3975
4682
|
},
|
|
@@ -4005,9 +4712,9 @@ function buildBreakpointTools(manager) {
|
|
|
4005
4712
|
"debug_set_breakpoint",
|
|
4006
4713
|
"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.",
|
|
4007
4714
|
{
|
|
4008
|
-
file:
|
|
4009
|
-
line:
|
|
4010
|
-
condition:
|
|
4715
|
+
file: z12.string().describe("Absolute or relative file path to set the breakpoint in"),
|
|
4716
|
+
line: z12.number().describe("Line number (1-based) to set the breakpoint on"),
|
|
4717
|
+
condition: z12.string().optional().describe("JavaScript condition expression \u2014 breakpoint only triggers when truthy")
|
|
4011
4718
|
},
|
|
4012
4719
|
async ({ file, line, condition }) => {
|
|
4013
4720
|
const clientOrErr = requireDebugClient2(manager);
|
|
@@ -4029,7 +4736,7 @@ Breakpoint ID: ${breakpointId}`
|
|
|
4029
4736
|
"debug_remove_breakpoint",
|
|
4030
4737
|
"Remove a previously set breakpoint by its ID.",
|
|
4031
4738
|
{
|
|
4032
|
-
breakpointId:
|
|
4739
|
+
breakpointId: z12.string().describe("The breakpoint ID returned by debug_set_breakpoint")
|
|
4033
4740
|
},
|
|
4034
4741
|
async ({ breakpointId }) => {
|
|
4035
4742
|
const clientOrErr = requireDebugClient2(manager);
|
|
@@ -4108,10 +4815,10 @@ ${JSON.stringify(queuedHits, null, 2)}`
|
|
|
4108
4815
|
),
|
|
4109
4816
|
defineTool(
|
|
4110
4817
|
"debug_evaluate",
|
|
4111
|
-
"Evaluate a JavaScript expression server-side in the Node process. When paused
|
|
4818
|
+
"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.",
|
|
4112
4819
|
{
|
|
4113
|
-
expression:
|
|
4114
|
-
frameIndex:
|
|
4820
|
+
expression: z12.string().describe("The JavaScript expression to evaluate"),
|
|
4821
|
+
frameIndex: z12.number().optional().describe("Call stack frame index (0 = top frame). Defaults to the top frame.")
|
|
4115
4822
|
},
|
|
4116
4823
|
async ({ expression, frameIndex }) => {
|
|
4117
4824
|
const clientOrErr = requireDebugClient2(manager);
|
|
@@ -4137,14 +4844,14 @@ function buildProbeManagementTools(manager) {
|
|
|
4137
4844
|
return [
|
|
4138
4845
|
defineTool(
|
|
4139
4846
|
"debug_add_probe",
|
|
4140
|
-
"Add a debug probe at a
|
|
4847
|
+
"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.",
|
|
4141
4848
|
{
|
|
4142
|
-
file:
|
|
4143
|
-
line:
|
|
4144
|
-
expressions:
|
|
4849
|
+
file: z12.string().describe("File path to probe"),
|
|
4850
|
+
line: z12.number().describe("Line number (1-based) to probe"),
|
|
4851
|
+
expressions: z12.array(z12.string()).describe(
|
|
4145
4852
|
'JavaScript expressions to capture when the line executes (e.g., ["req.params.id", "user.role"])'
|
|
4146
4853
|
),
|
|
4147
|
-
label:
|
|
4854
|
+
label: z12.string().optional().describe("Optional label for this probe (defaults to file:line)")
|
|
4148
4855
|
},
|
|
4149
4856
|
async ({ file, line, expressions, label }) => {
|
|
4150
4857
|
const clientOrErr = requireDebugClient2(manager);
|
|
@@ -4169,7 +4876,7 @@ Trigger the code path, then use debug_get_probe_results to see captured values.`
|
|
|
4169
4876
|
"debug_remove_probe",
|
|
4170
4877
|
"Remove a previously set debug probe by its ID.",
|
|
4171
4878
|
{
|
|
4172
|
-
probeId:
|
|
4879
|
+
probeId: z12.string().describe("The probe ID returned by debug_add_probe")
|
|
4173
4880
|
},
|
|
4174
4881
|
async ({ probeId }) => {
|
|
4175
4882
|
const clientOrErr = requireDebugClient2(manager);
|
|
@@ -4207,11 +4914,11 @@ function buildProbeResultTools(manager) {
|
|
|
4207
4914
|
return [
|
|
4208
4915
|
defineTool(
|
|
4209
4916
|
"debug_get_probe_results",
|
|
4210
|
-
"Fetch captured probe hit data.
|
|
4917
|
+
"Fetch captured probe hit data. Filter by label (wins) or probeId. Returns grouped text with per-probe hit count, timestamps, and captured expression values.",
|
|
4211
4918
|
{
|
|
4212
|
-
probeId:
|
|
4213
|
-
label:
|
|
4214
|
-
limit:
|
|
4919
|
+
probeId: z12.string().optional().describe("Filter results by probe ID (resolves to its label)"),
|
|
4920
|
+
label: z12.string().optional().describe("Filter results by probe label"),
|
|
4921
|
+
limit: z12.number().optional().describe("Maximum number of recent hits to return (default: all)")
|
|
4215
4922
|
},
|
|
4216
4923
|
async ({ probeId, label, limit }) => {
|
|
4217
4924
|
const clientOrErr = requireDebugClient2(manager);
|
|
@@ -4805,7 +5512,7 @@ async function processEvents(events, context, host) {
|
|
|
4805
5512
|
// src/execution/task-property-utils.ts
|
|
4806
5513
|
function collectMissingProps(taskProps) {
|
|
4807
5514
|
const missing = [];
|
|
4808
|
-
if (!taskProps.plan?.trim()) missing.push("plan (save via
|
|
5515
|
+
if (!taskProps.plan?.trim()) missing.push("plan (save via update_task_plan)");
|
|
4809
5516
|
if (!taskProps.storyPointId) missing.push("story points (use update_task_properties)");
|
|
4810
5517
|
if (!taskProps.title || taskProps.title === "Untitled")
|
|
4811
5518
|
missing.push("title (use update_task_properties)");
|
|
@@ -4877,13 +5584,32 @@ function handleAutoToolAccess(toolName, input, hasExitedPlanMode, isParentTask)
|
|
|
4877
5584
|
}
|
|
4878
5585
|
return { behavior: "allow", updatedInput: input };
|
|
4879
5586
|
}
|
|
5587
|
+
function enforceMissingProps(host, input, missingProps) {
|
|
5588
|
+
if (missingProps.length === 0) return null;
|
|
5589
|
+
if (input.bypassValidation !== true) {
|
|
5590
|
+
return {
|
|
5591
|
+
behavior: "deny",
|
|
5592
|
+
message: [
|
|
5593
|
+
"Cannot exit plan mode. Required task properties are missing:",
|
|
5594
|
+
...missingProps.map((p) => `- ${p}`),
|
|
5595
|
+
"",
|
|
5596
|
+
"Fill these in using MCP tools (e.g. update_task_plan, update_task_properties), then call ExitPlanMode again.",
|
|
5597
|
+
"",
|
|
5598
|
+
"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."
|
|
5599
|
+
].join("\n")
|
|
5600
|
+
};
|
|
5601
|
+
}
|
|
5602
|
+
host.connection.postChatMessage(
|
|
5603
|
+
`\u26A0\uFE0F [BYPASS] ExitPlanMode forced through with \`bypassValidation: true\` despite missing required properties: ${missingProps.join(", ")}. Please backfill these.`
|
|
5604
|
+
);
|
|
5605
|
+
return null;
|
|
5606
|
+
}
|
|
4880
5607
|
async function handleExitPlanMode(host, input) {
|
|
4881
5608
|
if (host.hasExitedPlanMode) {
|
|
4882
5609
|
return { behavior: "allow", updatedInput: input };
|
|
4883
5610
|
}
|
|
4884
|
-
host.exitPlanAttempts++;
|
|
4885
5611
|
try {
|
|
4886
|
-
host.syncPlanFile();
|
|
5612
|
+
await host.syncPlanFile();
|
|
4887
5613
|
const taskProps = await host.connection.getTaskProperties();
|
|
4888
5614
|
const missingProps = collectMissingProps(taskProps);
|
|
4889
5615
|
if (host.isParentTask) {
|
|
@@ -4903,30 +5629,22 @@ async function handleExitPlanMode(host, input) {
|
|
|
4903
5629
|
} catch {
|
|
4904
5630
|
}
|
|
4905
5631
|
}
|
|
4906
|
-
|
|
4907
|
-
|
|
4908
|
-
return {
|
|
4909
|
-
behavior: "deny",
|
|
4910
|
-
message: [
|
|
4911
|
-
"Cannot exit plan mode yet. Required task properties are missing:",
|
|
4912
|
-
...missingProps.map((p) => `- ${p}`),
|
|
4913
|
-
"",
|
|
4914
|
-
"Fill these in using MCP tools, then try ExitPlanMode again."
|
|
4915
|
-
].join("\n")
|
|
4916
|
-
};
|
|
4917
|
-
}
|
|
4918
|
-
host.connection.postChatMessage(
|
|
4919
|
-
`\u26A0\uFE0F ExitPlanMode allowed with missing properties: ${missingProps.join(", ")}. Consider backfilling these later.`
|
|
4920
|
-
);
|
|
4921
|
-
}
|
|
5632
|
+
const gate = enforceMissingProps(host, input, missingProps);
|
|
5633
|
+
if (gate) return gate;
|
|
4922
5634
|
if (host.agentMode === "discovery") {
|
|
4923
5635
|
host.hasExitedPlanMode = true;
|
|
4924
5636
|
host.discoveryCompleted = true;
|
|
4925
|
-
|
|
4926
|
-
|
|
4927
|
-
|
|
4928
|
-
|
|
5637
|
+
try {
|
|
5638
|
+
await host.connection.triggerIdentification();
|
|
5639
|
+
} catch (triggerErr) {
|
|
5640
|
+
host.connection.postChatMessage(
|
|
5641
|
+
`Identification trigger encountered an issue (${triggerErr instanceof Error ? triggerErr.message : "unknown error"}). Icon and agent assignment may use fallbacks.`
|
|
5642
|
+
);
|
|
5643
|
+
}
|
|
5644
|
+
await host.connection.postChatMessageAwait(
|
|
5645
|
+
"Planning complete \u2014 awaiting team approval. Icon and agent assignment will be set automatically."
|
|
4929
5646
|
);
|
|
5647
|
+
host.requestStop();
|
|
4930
5648
|
return { behavior: "allow", updatedInput: input };
|
|
4931
5649
|
}
|
|
4932
5650
|
try {
|
|
@@ -5319,7 +6037,7 @@ async function runSdkQuery(host, context, followUpContent) {
|
|
|
5319
6037
|
}
|
|
5320
6038
|
}
|
|
5321
6039
|
if (needsPlanSync) {
|
|
5322
|
-
host.syncPlanFile();
|
|
6040
|
+
await host.syncPlanFile();
|
|
5323
6041
|
}
|
|
5324
6042
|
}
|
|
5325
6043
|
async function buildRetryQuery(host, context, options, lastErrorWasImage) {
|
|
@@ -5756,7 +6474,6 @@ var QueryBridge = class {
|
|
|
5756
6474
|
set hasExitedPlanMode(val) {
|
|
5757
6475
|
bridge.mode.hasExitedPlanMode = val;
|
|
5758
6476
|
},
|
|
5759
|
-
exitPlanAttempts: 0,
|
|
5760
6477
|
get pendingModeRestart() {
|
|
5761
6478
|
return bridge.mode.pendingModeRestart;
|
|
5762
6479
|
},
|
|
@@ -5813,6 +6530,7 @@ import { fileURLToPath } from "url";
|
|
|
5813
6530
|
function mapChatHistory(messages) {
|
|
5814
6531
|
if (!messages) return [];
|
|
5815
6532
|
return messages.map((m) => ({
|
|
6533
|
+
id: m.id,
|
|
5816
6534
|
role: m.role ?? "user",
|
|
5817
6535
|
content: m.content ?? "",
|
|
5818
6536
|
userId: m.userId,
|
|
@@ -5865,6 +6583,8 @@ var SessionRunner = class _SessionRunner {
|
|
|
5865
6583
|
inputResolver = null;
|
|
5866
6584
|
pendingMessages = [];
|
|
5867
6585
|
prNudgeCount = 0;
|
|
6586
|
+
/** Guards overlapping runs of the periodic git flush. */
|
|
6587
|
+
periodicFlushInFlight = false;
|
|
5868
6588
|
constructor(config, callbacks) {
|
|
5869
6589
|
this.config = config;
|
|
5870
6590
|
this.callbacks = callbacks;
|
|
@@ -5883,7 +6603,17 @@ var SessionRunner = class _SessionRunner {
|
|
|
5883
6603
|
resolver(null);
|
|
5884
6604
|
}
|
|
5885
6605
|
},
|
|
5886
|
-
|
|
6606
|
+
onDormantTimeout: () => {
|
|
6607
|
+
process.stderr.write("[conveyor-agent] Dormant idle timeout reached, shutting down\n");
|
|
6608
|
+
this.stopped = true;
|
|
6609
|
+
if (this.inputResolver) {
|
|
6610
|
+
const resolver = this.inputResolver;
|
|
6611
|
+
this.inputResolver = null;
|
|
6612
|
+
resolver(null);
|
|
6613
|
+
}
|
|
6614
|
+
},
|
|
6615
|
+
onTokenRefresh: () => void this.refreshGithubToken(),
|
|
6616
|
+
onGitFlush: () => void this.periodicGitFlush()
|
|
5887
6617
|
});
|
|
5888
6618
|
}
|
|
5889
6619
|
get state() {
|
|
@@ -5909,6 +6639,7 @@ var SessionRunner = class _SessionRunner {
|
|
|
5909
6639
|
this.wireConnectionCallbacks();
|
|
5910
6640
|
this.lifecycle.startHeartbeat();
|
|
5911
6641
|
this.lifecycle.startTokenRefresh();
|
|
6642
|
+
this.lifecycle.startGitFlush();
|
|
5912
6643
|
const { pendingMessages: serverMessages } = await this.connection.call("connectAgent", {
|
|
5913
6644
|
sessionId: this.sessionId
|
|
5914
6645
|
});
|
|
@@ -6003,9 +6734,15 @@ var SessionRunner = class _SessionRunner {
|
|
|
6003
6734
|
);
|
|
6004
6735
|
this.pendingMessages.length = 0;
|
|
6005
6736
|
if (this._state !== "idle") await this.setState("idle");
|
|
6737
|
+
this.lifecycle.startDormantTimer();
|
|
6006
6738
|
const dormantMsg = await this.waitForMessage();
|
|
6739
|
+
this.lifecycle.cancelDormantTimer();
|
|
6007
6740
|
if (!dormantMsg) break;
|
|
6008
|
-
|
|
6741
|
+
const contentPreview = dormantMsg.content.length > 80 ? `${dormantMsg.content.slice(0, 80)}...` : dormantMsg.content;
|
|
6742
|
+
process.stderr.write(
|
|
6743
|
+
`[conveyor-agent] Received message while dormant, resuming: userId=${dormantMsg.userId}, source=${dormantMsg.source || "unknown"}, content="${contentPreview.replace(/\n/g, "\\n")}"
|
|
6744
|
+
`
|
|
6745
|
+
);
|
|
6009
6746
|
this.completedThisTurn = false;
|
|
6010
6747
|
this.pendingMessages.unshift(dormantMsg);
|
|
6011
6748
|
continue;
|
|
@@ -6114,6 +6851,38 @@ var SessionRunner = class _SessionRunner {
|
|
|
6114
6851
|
}
|
|
6115
6852
|
}
|
|
6116
6853
|
// ── Stop / soft-stop ───────────────────────────────────────────────
|
|
6854
|
+
/** Periodic best-effort WIP commit + push during normal agent execution.
|
|
6855
|
+
* Covers ungraceful pod termination (OOMKilled, node crash/eviction) where
|
|
6856
|
+
* the preStop hook + SIGTERM flush don't get a chance to run. No-ops on a
|
|
6857
|
+
* clean tree. Guarded so two ticks can't overlap. Never throws. */
|
|
6858
|
+
async periodicGitFlush() {
|
|
6859
|
+
if (this.periodicFlushInFlight || this.stopped) return;
|
|
6860
|
+
this.periodicFlushInFlight = true;
|
|
6861
|
+
try {
|
|
6862
|
+
const result = await flushPendingChanges(this.config.workspaceDir, {
|
|
6863
|
+
wipMessage: "WIP: periodic auto-commit",
|
|
6864
|
+
refreshToken: async () => {
|
|
6865
|
+
try {
|
|
6866
|
+
const res = await this.connection.call("refreshGithubToken", {
|
|
6867
|
+
sessionId: this.connection.sessionId
|
|
6868
|
+
});
|
|
6869
|
+
return res.token;
|
|
6870
|
+
} catch {
|
|
6871
|
+
return void 0;
|
|
6872
|
+
}
|
|
6873
|
+
}
|
|
6874
|
+
});
|
|
6875
|
+
if (result.hadWork) {
|
|
6876
|
+
process.stderr.write(
|
|
6877
|
+
`[conveyor-agent] Periodic git flush: committed=${result.committed} pushed=${result.pushed}
|
|
6878
|
+
`
|
|
6879
|
+
);
|
|
6880
|
+
}
|
|
6881
|
+
} catch {
|
|
6882
|
+
} finally {
|
|
6883
|
+
this.periodicFlushInFlight = false;
|
|
6884
|
+
}
|
|
6885
|
+
}
|
|
6117
6886
|
/** Best-effort WIP commit + push on shutdown so in-flight work isn't lost
|
|
6118
6887
|
* when a claudespace pod is killed. Must be called BEFORE stop() so the
|
|
6119
6888
|
* connection is still alive for token refresh. Never throws. */
|
|
@@ -6241,6 +7010,7 @@ var SessionRunner = class _SessionRunner {
|
|
|
6241
7010
|
projectDescription: ctx.projectDescription ?? null,
|
|
6242
7011
|
githubPRUrl: ctx.githubPRUrl,
|
|
6243
7012
|
claudeSessionId: ctx.claudeSessionId ?? null,
|
|
7013
|
+
lastSeenMessageId: ctx.lastSeenMessageId ?? null,
|
|
6244
7014
|
isParentTask: !!ctx.parentTaskId,
|
|
6245
7015
|
storyPoints: ctx.storyPoints ?? void 0,
|
|
6246
7016
|
projectAgents: ctx.projectAgents ?? void 0,
|
|
@@ -6274,6 +7044,7 @@ var SessionRunner = class _SessionRunner {
|
|
|
6274
7044
|
onEvent: (event) => {
|
|
6275
7045
|
if (event.type === "completed") {
|
|
6276
7046
|
this.completedThisTurn = true;
|
|
7047
|
+
void this.connection.sendHeartbeat();
|
|
6277
7048
|
}
|
|
6278
7049
|
return this.callbacks.onEvent(event);
|
|
6279
7050
|
}
|
|
@@ -6410,23 +7181,30 @@ var SessionRunner = class _SessionRunner {
|
|
|
6410
7181
|
get finalState() {
|
|
6411
7182
|
return this._finalState;
|
|
6412
7183
|
}
|
|
6413
|
-
|
|
6414
|
-
|
|
6415
|
-
mode: this.mode.effectiveMode,
|
|
6416
|
-
runnerMode: this.config.runnerMode ?? "task",
|
|
6417
|
-
sessionId: this.sessionId,
|
|
6418
|
-
// Task context
|
|
7184
|
+
buildTaskContextSnapshot() {
|
|
7185
|
+
return {
|
|
6419
7186
|
isParentTask: this.fullContext?.isParentTask ?? false,
|
|
6420
7187
|
status: this.taskContext?.status,
|
|
6421
7188
|
taskTitle: this.fullContext?.title,
|
|
6422
7189
|
hasExistingPR: !!this.fullContext?.githubPRUrl,
|
|
6423
7190
|
hasExistingSession: !!this.fullContext?.claudeSessionId,
|
|
6424
7191
|
chatHistoryLength: this.fullContext?.chatHistory?.length ?? 0,
|
|
6425
|
-
tagIds: this.fullContext?.taskTagIds ?? []
|
|
6426
|
-
|
|
7192
|
+
tagIds: this.fullContext?.taskTagIds ?? []
|
|
7193
|
+
};
|
|
7194
|
+
}
|
|
7195
|
+
buildInitializationContext() {
|
|
7196
|
+
return {
|
|
7197
|
+
mode: this.mode.effectiveMode,
|
|
7198
|
+
runnerMode: this.config.runnerMode ?? "task",
|
|
7199
|
+
sessionId: this.sessionId,
|
|
7200
|
+
...this.buildTaskContextSnapshot(),
|
|
6427
7201
|
model: this.taskContext?.model,
|
|
6428
|
-
isAuto: this.config.isAuto ?? false
|
|
7202
|
+
isAuto: this.config.isAuto ?? false,
|
|
7203
|
+
subscriptionKeyLabel: process.env.CONVEYOR_SUBSCRIPTION_KEY_LABEL ?? null
|
|
6429
7204
|
};
|
|
7205
|
+
}
|
|
7206
|
+
logInitialization() {
|
|
7207
|
+
const context = this.buildInitializationContext();
|
|
6430
7208
|
process.stderr.write(`[conveyor-agent] Initialized: ${JSON.stringify(context)}
|
|
6431
7209
|
`);
|
|
6432
7210
|
this.connection.sendEvent({ type: "session_manifest", ...context });
|
|
@@ -6836,7 +7614,7 @@ function runStartCommand(cmd, cwd, onOutput) {
|
|
|
6836
7614
|
}
|
|
6837
7615
|
|
|
6838
7616
|
// src/tools/project-tools.ts
|
|
6839
|
-
import { z as
|
|
7617
|
+
import { z as z13 } from "zod";
|
|
6840
7618
|
function buildTaskListTools(connection) {
|
|
6841
7619
|
const projectId = connection.projectId;
|
|
6842
7620
|
return [
|
|
@@ -6844,9 +7622,9 @@ function buildTaskListTools(connection) {
|
|
|
6844
7622
|
"list_tasks",
|
|
6845
7623
|
"List tasks in the project. Optionally filter by status or assignee.",
|
|
6846
7624
|
{
|
|
6847
|
-
status:
|
|
6848
|
-
assigneeId:
|
|
6849
|
-
limit:
|
|
7625
|
+
status: z13.string().optional().describe("Filter by task status"),
|
|
7626
|
+
assigneeId: z13.string().optional().describe("Filter by assigned user ID"),
|
|
7627
|
+
limit: z13.number().optional().describe("Max number of tasks to return (default 50)")
|
|
6850
7628
|
},
|
|
6851
7629
|
async (params) => {
|
|
6852
7630
|
try {
|
|
@@ -6863,7 +7641,7 @@ function buildTaskListTools(connection) {
|
|
|
6863
7641
|
defineTool(
|
|
6864
7642
|
"get_project_task",
|
|
6865
7643
|
"Get detailed information about a task in this project (chat messages, child tasks, session). Project-runner scope.",
|
|
6866
|
-
{ task_id:
|
|
7644
|
+
{ task_id: z13.string().describe("The task ID to look up") },
|
|
6867
7645
|
async ({ task_id }) => {
|
|
6868
7646
|
try {
|
|
6869
7647
|
const task = await connection.call("getProjectTask", { projectId, taskId: task_id });
|
|
@@ -6880,10 +7658,10 @@ function buildTaskListTools(connection) {
|
|
|
6880
7658
|
"search_tasks",
|
|
6881
7659
|
"Search tasks by tags, text query, or status filters.",
|
|
6882
7660
|
{
|
|
6883
|
-
tagNames:
|
|
6884
|
-
searchQuery:
|
|
6885
|
-
statusFilters:
|
|
6886
|
-
limit:
|
|
7661
|
+
tagNames: z13.array(z13.string()).optional().describe("Filter by tag names"),
|
|
7662
|
+
searchQuery: z13.string().optional().describe("Text search in title/description"),
|
|
7663
|
+
statusFilters: z13.array(z13.string()).optional().describe("Filter by statuses"),
|
|
7664
|
+
limit: z13.number().optional().describe("Max results (default 20)")
|
|
6887
7665
|
},
|
|
6888
7666
|
async (params) => {
|
|
6889
7667
|
try {
|
|
@@ -6943,10 +7721,10 @@ function buildMutationTools2(connection) {
|
|
|
6943
7721
|
"create_task",
|
|
6944
7722
|
"Create a new task in the project.",
|
|
6945
7723
|
{
|
|
6946
|
-
title:
|
|
6947
|
-
description:
|
|
6948
|
-
plan:
|
|
6949
|
-
status:
|
|
7724
|
+
title: z13.string().describe("Task title"),
|
|
7725
|
+
description: z13.string().optional().describe("Task description"),
|
|
7726
|
+
plan: z13.string().optional().describe("Implementation plan in markdown"),
|
|
7727
|
+
status: z13.string().optional().describe("Initial status (default: Planning)")
|
|
6950
7728
|
},
|
|
6951
7729
|
async (params) => {
|
|
6952
7730
|
try {
|
|
@@ -6963,12 +7741,12 @@ function buildMutationTools2(connection) {
|
|
|
6963
7741
|
"update_project_task",
|
|
6964
7742
|
"Update an existing task's title, description, plan, status, or assignee. Project-runner scope.",
|
|
6965
7743
|
{
|
|
6966
|
-
task_id:
|
|
6967
|
-
title:
|
|
6968
|
-
description:
|
|
6969
|
-
plan:
|
|
6970
|
-
status:
|
|
6971
|
-
assignedUserId:
|
|
7744
|
+
task_id: z13.string().describe("The task ID to update"),
|
|
7745
|
+
title: z13.string().optional().describe("New title"),
|
|
7746
|
+
description: z13.string().optional().describe("New description"),
|
|
7747
|
+
plan: z13.string().optional().describe("New plan in markdown"),
|
|
7748
|
+
status: z13.string().optional().describe("New status"),
|
|
7749
|
+
assignedUserId: z13.string().nullable().optional().describe("Assign to user ID, or null to unassign")
|
|
6972
7750
|
},
|
|
6973
7751
|
async ({ task_id, ...fields }) => {
|
|
6974
7752
|
try {
|
|
@@ -7865,7 +8643,7 @@ var ProjectRunner = class {
|
|
|
7865
8643
|
async handleAuditTasks(request) {
|
|
7866
8644
|
this.connection.emitStatus("busy");
|
|
7867
8645
|
try {
|
|
7868
|
-
const { handleTaskAudit } = await import("./task-audit-handler-
|
|
8646
|
+
const { handleTaskAudit } = await import("./task-audit-handler-4675WBIX.js");
|
|
7869
8647
|
await handleTaskAudit(request, this.connection, this.projectDir);
|
|
7870
8648
|
} catch (error) {
|
|
7871
8649
|
const msg = parseErrorMessage(error);
|
|
@@ -7916,15 +8694,38 @@ var ProjectRunner = class {
|
|
|
7916
8694
|
import { readFile as readFile2 } from "fs/promises";
|
|
7917
8695
|
import { join as join5 } from "path";
|
|
7918
8696
|
var DEVCONTAINER_PATH = ".devcontainer/conveyor/devcontainer.json";
|
|
8697
|
+
var DEVCONTAINER_PORT_DENY_LIST = /* @__PURE__ */ new Set([5432, 6379, 9200]);
|
|
7919
8698
|
async function loadForwardPorts(workspaceDir) {
|
|
7920
8699
|
try {
|
|
7921
8700
|
const raw = await readFile2(join5(workspaceDir, DEVCONTAINER_PATH), "utf-8");
|
|
7922
8701
|
const parsed = JSON.parse(raw);
|
|
7923
|
-
|
|
8702
|
+
const ports = (parsed.forwardPorts ?? []).filter(
|
|
8703
|
+
(p) => typeof p === "number" && !DEVCONTAINER_PORT_DENY_LIST.has(p)
|
|
8704
|
+
);
|
|
8705
|
+
const attributes = {};
|
|
8706
|
+
for (const [key, value] of Object.entries(parsed.portsAttributes ?? {})) {
|
|
8707
|
+
if (!value || typeof value !== "object") continue;
|
|
8708
|
+
const entry = {};
|
|
8709
|
+
if (typeof value.label === "string") entry.label = value.label;
|
|
8710
|
+
if (value.visibility === "public" || value.visibility === "private") {
|
|
8711
|
+
entry.visibility = value.visibility;
|
|
8712
|
+
}
|
|
8713
|
+
attributes[key] = entry;
|
|
8714
|
+
}
|
|
8715
|
+
return { ports, attributes };
|
|
7924
8716
|
} catch {
|
|
7925
|
-
return [];
|
|
8717
|
+
return { ports: [], attributes: {} };
|
|
7926
8718
|
}
|
|
7927
8719
|
}
|
|
8720
|
+
function buildSessionPreviewPorts(result) {
|
|
8721
|
+
return result.ports.filter((port) => !DEVCONTAINER_PORT_DENY_LIST.has(port)).map((port) => {
|
|
8722
|
+
const attr = result.attributes[String(port)];
|
|
8723
|
+
const entry = { port };
|
|
8724
|
+
if (attr?.label) entry.label = attr.label;
|
|
8725
|
+
if (attr?.visibility) entry.visibility = attr.visibility;
|
|
8726
|
+
return entry;
|
|
8727
|
+
});
|
|
8728
|
+
}
|
|
7928
8729
|
function loadConveyorConfig() {
|
|
7929
8730
|
const envSetup = process.env.CONVEYOR_SETUP_COMMAND;
|
|
7930
8731
|
const envStart = process.env.CONVEYOR_START_COMMAND;
|
|
@@ -7964,6 +8765,7 @@ export {
|
|
|
7964
8765
|
runStartCommand,
|
|
7965
8766
|
ProjectRunner,
|
|
7966
8767
|
loadForwardPorts,
|
|
8768
|
+
buildSessionPreviewPorts,
|
|
7967
8769
|
loadConveyorConfig
|
|
7968
8770
|
};
|
|
7969
|
-
//# sourceMappingURL=chunk-
|
|
8771
|
+
//# sourceMappingURL=chunk-KO2YQJEV.js.map
|