@rallycry/conveyor-agent 5.10.2 → 5.11.0
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-WPQXAPVA.js → chunk-LBEAK2VJ.js} +169 -55
- package/dist/chunk-LBEAK2VJ.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-WPQXAPVA.js.map +0 -1
|
@@ -459,6 +459,7 @@ var ProjectConnection = class {
|
|
|
459
459
|
onSwitchBranch = null;
|
|
460
460
|
onSyncEnvironment = null;
|
|
461
461
|
onGetEnvStatus = null;
|
|
462
|
+
onRestartStartCommand = null;
|
|
462
463
|
constructor(config) {
|
|
463
464
|
this.config = config;
|
|
464
465
|
}
|
|
@@ -522,6 +523,13 @@ var ProjectConnection = class {
|
|
|
522
523
|
if (this.onGetEnvStatus) this.onGetEnvStatus(cb);
|
|
523
524
|
else cb({ ok: false, data: void 0 });
|
|
524
525
|
});
|
|
526
|
+
this.socket.on(
|
|
527
|
+
"projectRunner:restartStartCommand",
|
|
528
|
+
(_data, cb) => {
|
|
529
|
+
if (this.onRestartStartCommand) this.onRestartStartCommand(cb);
|
|
530
|
+
else cb({ ok: false, error: "restartStartCommand handler not registered" });
|
|
531
|
+
}
|
|
532
|
+
);
|
|
525
533
|
this.socket.on(
|
|
526
534
|
"projectRunner:runAuthTokenCommand",
|
|
527
535
|
(data, cb) => this.handleRunAuthTokenCommand(data.userEmail, cb)
|
|
@@ -564,6 +572,10 @@ var ProjectConnection = class {
|
|
|
564
572
|
if (!this.socket) return;
|
|
565
573
|
this.socket.emit("conveyor:tagAuditResult", data);
|
|
566
574
|
}
|
|
575
|
+
emitAuditProgress(data) {
|
|
576
|
+
if (!this.socket) return;
|
|
577
|
+
this.socket.emit("conveyor:tagAuditProgress", data);
|
|
578
|
+
}
|
|
567
579
|
sendHeartbeat() {
|
|
568
580
|
if (!this.socket) return;
|
|
569
581
|
this.socket.emit("projectRunner:heartbeat", {});
|
|
@@ -784,6 +796,14 @@ import { randomUUID as randomUUID2 } from "crypto";
|
|
|
784
796
|
import { execSync as execSync4 } from "child_process";
|
|
785
797
|
|
|
786
798
|
// src/execution/event-handlers.ts
|
|
799
|
+
function safeVoid(promise, context) {
|
|
800
|
+
if (promise && typeof promise.catch === "function") {
|
|
801
|
+
promise.catch((err) => {
|
|
802
|
+
process.stderr.write(`[safeVoid] ${context}: ${err}
|
|
803
|
+
`);
|
|
804
|
+
});
|
|
805
|
+
}
|
|
806
|
+
}
|
|
787
807
|
function epochSecondsToISO(value) {
|
|
788
808
|
if (typeof value === "string") return value;
|
|
789
809
|
if (typeof value !== "number" || value <= 0) return void 0;
|
|
@@ -960,13 +980,13 @@ function handleRateLimitEvent(event, host) {
|
|
|
960
980
|
const resetsAtDisplay = resetsAt ?? "unknown";
|
|
961
981
|
const message = `Rate limit rejected (type: ${rate_limit_info.rateLimitType ?? "unknown"}, resets at: ${resetsAtDisplay})`;
|
|
962
982
|
host.connection.sendEvent({ type: "error", message });
|
|
963
|
-
|
|
983
|
+
safeVoid(host.callbacks.onEvent({ type: "error", message }), "rateLimitRejected");
|
|
964
984
|
return resetsAt;
|
|
965
985
|
} else if (status === "allowed_warning") {
|
|
966
986
|
const utilization = rate_limit_info.utilization ? `${Math.round(rate_limit_info.utilization * 100)}%` : "high";
|
|
967
987
|
const message = `Rate limit warning: ${utilization} utilization (type: ${rate_limit_info.rateLimitType ?? "unknown"})`;
|
|
968
988
|
host.connection.sendEvent({ type: "thinking", message });
|
|
969
|
-
|
|
989
|
+
safeVoid(host.callbacks.onEvent({ type: "thinking", message }), "rateLimitWarning");
|
|
970
990
|
}
|
|
971
991
|
return void 0;
|
|
972
992
|
}
|
|
@@ -984,34 +1004,46 @@ async function handleSystemEvent(event, host, context, sessionIdStored) {
|
|
|
984
1004
|
}
|
|
985
1005
|
function handleSystemSubevents(systemEvent, host) {
|
|
986
1006
|
if (systemEvent.subtype === "compact_boundary") {
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
1007
|
+
safeVoid(
|
|
1008
|
+
host.callbacks.onEvent({
|
|
1009
|
+
type: "context_compacted",
|
|
1010
|
+
trigger: systemEvent.compact_metadata.trigger,
|
|
1011
|
+
preTokens: systemEvent.compact_metadata.pre_tokens
|
|
1012
|
+
}),
|
|
1013
|
+
"compactBoundary"
|
|
1014
|
+
);
|
|
992
1015
|
} else if (systemEvent.subtype === "task_started") {
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
1016
|
+
safeVoid(
|
|
1017
|
+
host.callbacks.onEvent({
|
|
1018
|
+
type: "subagent_started",
|
|
1019
|
+
sdkTaskId: systemEvent.task_id,
|
|
1020
|
+
description: systemEvent.description
|
|
1021
|
+
}),
|
|
1022
|
+
"taskStarted"
|
|
1023
|
+
);
|
|
998
1024
|
} else if (systemEvent.subtype === "task_progress") {
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1025
|
+
safeVoid(
|
|
1026
|
+
host.callbacks.onEvent({
|
|
1027
|
+
type: "subagent_progress",
|
|
1028
|
+
sdkTaskId: systemEvent.task_id,
|
|
1029
|
+
description: systemEvent.description,
|
|
1030
|
+
toolUses: systemEvent.usage?.tool_uses ?? 0,
|
|
1031
|
+
durationMs: systemEvent.usage?.duration_ms ?? 0
|
|
1032
|
+
}),
|
|
1033
|
+
"taskProgress"
|
|
1034
|
+
);
|
|
1006
1035
|
}
|
|
1007
1036
|
}
|
|
1008
1037
|
function handleToolProgressEvent(event, host) {
|
|
1009
1038
|
const msg = event;
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1039
|
+
safeVoid(
|
|
1040
|
+
host.callbacks.onEvent({
|
|
1041
|
+
type: "tool_progress",
|
|
1042
|
+
toolName: msg.tool_name ?? "",
|
|
1043
|
+
elapsedSeconds: msg.elapsed_time_seconds ?? 0
|
|
1044
|
+
}),
|
|
1045
|
+
"toolProgress"
|
|
1046
|
+
);
|
|
1015
1047
|
}
|
|
1016
1048
|
async function handleAssistantCase(event, host, turnToolCalls) {
|
|
1017
1049
|
await processAssistantEvent(event, host, turnToolCalls);
|
|
@@ -1034,6 +1066,7 @@ async function handleResultCase(event, host, context, startTime, isTyping, lastA
|
|
|
1034
1066
|
}
|
|
1035
1067
|
|
|
1036
1068
|
// src/execution/event-processor.ts
|
|
1069
|
+
var API_ERROR_PATTERN2 = /API Error: [45]\d\d/;
|
|
1037
1070
|
function stopTypingIfNeeded(host, isTyping) {
|
|
1038
1071
|
if (isTyping) host.connection.sendTypingStop();
|
|
1039
1072
|
}
|
|
@@ -1055,6 +1088,12 @@ async function processAssistantCase(event, host, state) {
|
|
|
1055
1088
|
}
|
|
1056
1089
|
const usage = await handleAssistantCase(event, host, state.turnToolCalls);
|
|
1057
1090
|
if (usage) state.lastAssistantUsage = usage;
|
|
1091
|
+
if (!state.sawApiError) {
|
|
1092
|
+
const fullText = event.message.content.filter((b) => b.type === "text").map((b) => b.text).join(" ");
|
|
1093
|
+
if (API_ERROR_PATTERN2.test(fullText)) {
|
|
1094
|
+
state.sawApiError = true;
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1058
1097
|
}
|
|
1059
1098
|
async function processResultCase(event, host, context, startTime, state) {
|
|
1060
1099
|
const info = await handleResultCase(
|
|
@@ -1078,6 +1117,7 @@ async function processEvents(events, context, host) {
|
|
|
1078
1117
|
sessionIdStored: false,
|
|
1079
1118
|
isTyping: false,
|
|
1080
1119
|
retriable: false,
|
|
1120
|
+
sawApiError: false,
|
|
1081
1121
|
resultSummary: void 0,
|
|
1082
1122
|
rateLimitResetsAt: void 0,
|
|
1083
1123
|
staleSession: void 0,
|
|
@@ -1117,7 +1157,7 @@ async function processEvents(events, context, host) {
|
|
|
1117
1157
|
}
|
|
1118
1158
|
stopTypingIfNeeded(host, state.isTyping);
|
|
1119
1159
|
return {
|
|
1120
|
-
retriable: state.retriable,
|
|
1160
|
+
retriable: state.retriable || state.sawApiError,
|
|
1121
1161
|
resultSummary: state.resultSummary,
|
|
1122
1162
|
rateLimitResetsAt: state.rateLimitResetsAt,
|
|
1123
1163
|
...state.staleSession && { staleSession: state.staleSession }
|
|
@@ -1478,6 +1518,8 @@ function buildDiscoveryPrompt(context) {
|
|
|
1478
1518
|
`You are in Discovery mode \u2014 helping plan and scope this task.`,
|
|
1479
1519
|
`- You have read-only codebase access (can read files, run git commands, search code)`,
|
|
1480
1520
|
`- You can write plan files in .claude/plans/ only \u2014 no other file writes`,
|
|
1521
|
+
`- Do NOT attempt to edit, write, or modify source code files \u2014 these operations will be denied`,
|
|
1522
|
+
`- If you identify code changes needed, describe them in the plan instead of implementing them`,
|
|
1481
1523
|
`- You can create and manage subtasks`,
|
|
1482
1524
|
`- Goal: collaborate with the user to create a clear plan`,
|
|
1483
1525
|
`- Proactively fill task properties (SP, tags, icon) as the plan takes shape`,
|
|
@@ -1742,7 +1784,7 @@ function detectRelaunchScenario(context, trustChatHistory = false) {
|
|
|
1742
1784
|
const hasNewUserMessages = messagesAfterAgent.some((m) => m.role === "user");
|
|
1743
1785
|
return hasNewUserMessages ? "feedback_relaunch" : "idle_relaunch";
|
|
1744
1786
|
}
|
|
1745
|
-
function buildRelaunchWithSession(mode, context, agentMode) {
|
|
1787
|
+
function buildRelaunchWithSession(mode, context, agentMode, isAuto) {
|
|
1746
1788
|
const scenario = detectRelaunchScenario(context);
|
|
1747
1789
|
if (!context.claudeSessionId || scenario === "fresh") return null;
|
|
1748
1790
|
const parts = [];
|
|
@@ -1790,7 +1832,7 @@ Address the requested changes. Do NOT re-investigate the codebase from scratch o
|
|
|
1790
1832
|
`Run \`git log --oneline -10\` to review what you already committed.`,
|
|
1791
1833
|
`Review the current state of the codebase and verify everything is working correctly.`
|
|
1792
1834
|
);
|
|
1793
|
-
if (agentMode === "auto" || agentMode === "building") {
|
|
1835
|
+
if (agentMode === "auto" || agentMode === "building" && isAuto) {
|
|
1794
1836
|
parts.push(
|
|
1795
1837
|
`If work is incomplete, continue implementing the plan. When finished, commit, push, and use mcp__conveyor__create_pull_request to open a PR.`,
|
|
1796
1838
|
`Do NOT go idle or wait for instructions \u2014 you are in auto mode.`
|
|
@@ -1996,7 +2038,7 @@ Address the requested changes directly. Do NOT re-investigate the codebase from
|
|
|
1996
2038
|
}
|
|
1997
2039
|
return parts;
|
|
1998
2040
|
}
|
|
1999
|
-
function buildInstructions(mode, context, scenario, agentMode) {
|
|
2041
|
+
function buildInstructions(mode, context, scenario, agentMode, isAuto) {
|
|
2000
2042
|
const parts = [`
|
|
2001
2043
|
## Instructions`];
|
|
2002
2044
|
const isPm = mode === "pm";
|
|
@@ -2028,7 +2070,7 @@ function buildInstructions(mode, context, scenario, agentMode) {
|
|
|
2028
2070
|
`Work on the git branch "${context.githubBranch}". Stay on this branch \u2014 do not checkout or create other branches.`,
|
|
2029
2071
|
`Run \`git log --oneline -10\` to review what you already committed, then verify the current state is correct.`
|
|
2030
2072
|
);
|
|
2031
|
-
if (agentMode === "auto" || agentMode === "building") {
|
|
2073
|
+
if (agentMode === "auto" || agentMode === "building" && isAuto) {
|
|
2032
2074
|
parts.push(
|
|
2033
2075
|
`If work is incomplete, continue implementing the plan. When finished, commit, push, and use mcp__conveyor__create_pull_request to open a PR.`,
|
|
2034
2076
|
`Do NOT go idle or wait for instructions \u2014 you are in auto mode.`
|
|
@@ -2051,13 +2093,13 @@ function buildInstructions(mode, context, scenario, agentMode) {
|
|
|
2051
2093
|
async function buildInitialPrompt(mode, context, isAuto, agentMode) {
|
|
2052
2094
|
const isPackRunner = mode === "pm" && !!isAuto && !!context.isParentTask;
|
|
2053
2095
|
if (!isPackRunner) {
|
|
2054
|
-
const sessionRelaunch = buildRelaunchWithSession(mode, context, agentMode);
|
|
2096
|
+
const sessionRelaunch = buildRelaunchWithSession(mode, context, agentMode, isAuto);
|
|
2055
2097
|
if (sessionRelaunch) return sessionRelaunch;
|
|
2056
2098
|
}
|
|
2057
2099
|
const isPm = mode === "pm";
|
|
2058
2100
|
const scenario = detectRelaunchScenario(context, isPm);
|
|
2059
2101
|
const body = await buildTaskBody(context);
|
|
2060
|
-
const instructions = isPackRunner ? buildPackRunnerInstructions(context, scenario) : buildInstructions(mode, context, scenario, agentMode);
|
|
2102
|
+
const instructions = isPackRunner ? buildPackRunnerInstructions(context, scenario) : buildInstructions(mode, context, scenario, agentMode, isAuto);
|
|
2061
2103
|
return [...body, ...instructions].join("\n");
|
|
2062
2104
|
}
|
|
2063
2105
|
|
|
@@ -2319,11 +2361,14 @@ function buildCreatePullRequestTool(connection) {
|
|
|
2319
2361
|
"Create a GitHub pull request for this task. Use this instead of gh CLI or git commands to create PRs.",
|
|
2320
2362
|
{
|
|
2321
2363
|
title: z.string().describe("The PR title"),
|
|
2322
|
-
body: z.string().describe("The PR description/body in markdown")
|
|
2364
|
+
body: z.string().describe("The PR description/body in markdown"),
|
|
2365
|
+
branch: z.string().optional().describe(
|
|
2366
|
+
"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."
|
|
2367
|
+
)
|
|
2323
2368
|
},
|
|
2324
|
-
async ({ title, body }) => {
|
|
2369
|
+
async ({ title, body, branch }) => {
|
|
2325
2370
|
try {
|
|
2326
|
-
const result = await connection.createPR({ title, body });
|
|
2371
|
+
const result = await connection.createPR({ title, body, branch });
|
|
2327
2372
|
connection.sendEvent({
|
|
2328
2373
|
type: "pr_created",
|
|
2329
2374
|
url: result.url,
|
|
@@ -2811,7 +2856,9 @@ async function handleAskUserQuestion(host, input) {
|
|
|
2811
2856
|
}
|
|
2812
2857
|
return { behavior: "allow", updatedInput: { questions: input.questions, answers } };
|
|
2813
2858
|
}
|
|
2859
|
+
var DENIAL_WARNING_THRESHOLD = 3;
|
|
2814
2860
|
function buildCanUseTool(host) {
|
|
2861
|
+
let consecutiveDenials = 0;
|
|
2815
2862
|
return async (toolName, input) => {
|
|
2816
2863
|
if (toolName === "ExitPlanMode" && (host.agentMode === "auto" || host.agentMode === "discovery") && !host.hasExitedPlanMode) {
|
|
2817
2864
|
return await handleExitPlanMode(host, input);
|
|
@@ -2819,23 +2866,39 @@ function buildCanUseTool(host) {
|
|
|
2819
2866
|
if (toolName === "AskUserQuestion") {
|
|
2820
2867
|
return await handleAskUserQuestion(host, input);
|
|
2821
2868
|
}
|
|
2869
|
+
let result;
|
|
2822
2870
|
switch (host.agentMode) {
|
|
2823
2871
|
case "discovery":
|
|
2824
|
-
|
|
2872
|
+
result = handleDiscoveryToolAccess(toolName, input);
|
|
2873
|
+
break;
|
|
2825
2874
|
case "building":
|
|
2826
|
-
|
|
2875
|
+
result = handleBuildingToolAccess(toolName, input);
|
|
2876
|
+
break;
|
|
2827
2877
|
case "review":
|
|
2828
|
-
|
|
2878
|
+
result = handleReviewToolAccess(toolName, input, host.isParentTask);
|
|
2879
|
+
break;
|
|
2829
2880
|
case "auto":
|
|
2830
|
-
|
|
2881
|
+
result = handleAutoToolAccess(toolName, input, host.hasExitedPlanMode, host.isParentTask);
|
|
2882
|
+
break;
|
|
2831
2883
|
default:
|
|
2832
|
-
|
|
2884
|
+
result = { behavior: "allow", updatedInput: input };
|
|
2885
|
+
}
|
|
2886
|
+
if (result.behavior === "deny") {
|
|
2887
|
+
consecutiveDenials++;
|
|
2888
|
+
if (consecutiveDenials === DENIAL_WARNING_THRESHOLD) {
|
|
2889
|
+
host.connection.postChatMessage(
|
|
2890
|
+
`\u26A0\uFE0F Multiple tool denials detected. You are in ${host.agentMode} mode \u2014 file writes outside .claude/plans/ are not permitted. Focus on creating a plan instead of implementing code changes.`
|
|
2891
|
+
);
|
|
2892
|
+
}
|
|
2893
|
+
} else {
|
|
2894
|
+
consecutiveDenials = 0;
|
|
2833
2895
|
}
|
|
2896
|
+
return result;
|
|
2834
2897
|
};
|
|
2835
2898
|
}
|
|
2836
2899
|
|
|
2837
2900
|
// src/execution/query-executor.ts
|
|
2838
|
-
var
|
|
2901
|
+
var API_ERROR_PATTERN3 = /API Error: [45]\d\d/;
|
|
2839
2902
|
var IMAGE_ERROR_PATTERN2 = /Could not process image/i;
|
|
2840
2903
|
var RETRY_DELAYS_MS = [6e4, 12e4, 18e4, 3e5];
|
|
2841
2904
|
function buildHooks(host) {
|
|
@@ -3083,12 +3146,17 @@ function isStaleOrExitedSession(error, context) {
|
|
|
3083
3146
|
if (error.message.includes("No conversation found with session ID")) return true;
|
|
3084
3147
|
return !!context.claudeSessionId && error.message.includes("process exited");
|
|
3085
3148
|
}
|
|
3149
|
+
function getErrorMessage(error) {
|
|
3150
|
+
if (error instanceof Error) return error.message;
|
|
3151
|
+
if (typeof error === "string") return error;
|
|
3152
|
+
return String(error);
|
|
3153
|
+
}
|
|
3086
3154
|
function isRetriableError(error) {
|
|
3087
|
-
|
|
3088
|
-
return
|
|
3155
|
+
const message = getErrorMessage(error);
|
|
3156
|
+
return API_ERROR_PATTERN3.test(message) || IMAGE_ERROR_PATTERN2.test(message);
|
|
3089
3157
|
}
|
|
3090
3158
|
function classifyImageError(error) {
|
|
3091
|
-
return
|
|
3159
|
+
return IMAGE_ERROR_PATTERN2.test(getErrorMessage(error));
|
|
3092
3160
|
}
|
|
3093
3161
|
async function emitRetryStatus(host, attempt, delayMs) {
|
|
3094
3162
|
const delayMin = Math.round(delayMs / 6e4);
|
|
@@ -4344,14 +4412,15 @@ var TOOL_MAPPERS = {
|
|
|
4344
4412
|
recommend_merge_tags: mapMergeTags,
|
|
4345
4413
|
recommend_rename_tag: mapRenameTag
|
|
4346
4414
|
};
|
|
4347
|
-
function collectRecommendation(toolName, input, collector) {
|
|
4415
|
+
function collectRecommendation(toolName, input, collector, onRecommendation) {
|
|
4348
4416
|
const mapper = TOOL_MAPPERS[toolName];
|
|
4349
4417
|
if (!mapper) return JSON.stringify({ error: `Unknown tool: ${toolName}` });
|
|
4350
4418
|
const rec = { id: randomUUID3(), ...mapper(input) };
|
|
4351
4419
|
collector.recommendations.push(rec);
|
|
4420
|
+
onRecommendation?.({ tagName: rec.tagName ?? rec.type, type: rec.type });
|
|
4352
4421
|
return JSON.stringify({ success: true, recommendationId: rec.id });
|
|
4353
4422
|
}
|
|
4354
|
-
function createAuditMcpServer(collector) {
|
|
4423
|
+
function createAuditMcpServer(collector, onRecommendation) {
|
|
4355
4424
|
const auditTools = [
|
|
4356
4425
|
tool4(
|
|
4357
4426
|
"recommend_create_tag",
|
|
@@ -4366,7 +4435,8 @@ function createAuditMcpServer(collector) {
|
|
|
4366
4435
|
const result = collectRecommendation(
|
|
4367
4436
|
"recommend_create_tag",
|
|
4368
4437
|
args,
|
|
4369
|
-
collector
|
|
4438
|
+
collector,
|
|
4439
|
+
onRecommendation
|
|
4370
4440
|
);
|
|
4371
4441
|
return { content: [{ type: "text", text: result }] };
|
|
4372
4442
|
}
|
|
@@ -4384,7 +4454,8 @@ function createAuditMcpServer(collector) {
|
|
|
4384
4454
|
const result = collectRecommendation(
|
|
4385
4455
|
"recommend_update_description",
|
|
4386
4456
|
args,
|
|
4387
|
-
collector
|
|
4457
|
+
collector,
|
|
4458
|
+
onRecommendation
|
|
4388
4459
|
);
|
|
4389
4460
|
return { content: [{ type: "text", text: result }] };
|
|
4390
4461
|
}
|
|
@@ -4404,7 +4475,8 @@ function createAuditMcpServer(collector) {
|
|
|
4404
4475
|
const result = collectRecommendation(
|
|
4405
4476
|
"recommend_context_link",
|
|
4406
4477
|
args,
|
|
4407
|
-
collector
|
|
4478
|
+
collector,
|
|
4479
|
+
onRecommendation
|
|
4408
4480
|
);
|
|
4409
4481
|
return { content: [{ type: "text", text: result }] };
|
|
4410
4482
|
}
|
|
@@ -4424,7 +4496,8 @@ function createAuditMcpServer(collector) {
|
|
|
4424
4496
|
const result = collectRecommendation(
|
|
4425
4497
|
"flag_documentation_gap",
|
|
4426
4498
|
args,
|
|
4427
|
-
collector
|
|
4499
|
+
collector,
|
|
4500
|
+
onRecommendation
|
|
4428
4501
|
);
|
|
4429
4502
|
return { content: [{ type: "text", text: result }] };
|
|
4430
4503
|
}
|
|
@@ -4443,7 +4516,8 @@ function createAuditMcpServer(collector) {
|
|
|
4443
4516
|
const result = collectRecommendation(
|
|
4444
4517
|
"recommend_merge_tags",
|
|
4445
4518
|
args,
|
|
4446
|
-
collector
|
|
4519
|
+
collector,
|
|
4520
|
+
onRecommendation
|
|
4447
4521
|
);
|
|
4448
4522
|
return { content: [{ type: "text", text: result }] };
|
|
4449
4523
|
}
|
|
@@ -4461,7 +4535,8 @@ function createAuditMcpServer(collector) {
|
|
|
4461
4535
|
const result = collectRecommendation(
|
|
4462
4536
|
"recommend_rename_tag",
|
|
4463
4537
|
args,
|
|
4464
|
-
collector
|
|
4538
|
+
collector,
|
|
4539
|
+
onRecommendation
|
|
4465
4540
|
);
|
|
4466
4541
|
return { content: [{ type: "text", text: result }] };
|
|
4467
4542
|
}
|
|
@@ -4535,13 +4610,32 @@ function buildAuditSystemPrompt(projectName, tags, heatmapData, projectDir) {
|
|
|
4535
4610
|
"Analyze actual file contents, not just file names."
|
|
4536
4611
|
].join("\n");
|
|
4537
4612
|
}
|
|
4613
|
+
function emitToolCallProgress(event, request, connection) {
|
|
4614
|
+
if (event.type !== "assistant") return;
|
|
4615
|
+
const assistantEvent = event;
|
|
4616
|
+
for (const block of assistantEvent.message.content) {
|
|
4617
|
+
if (block.type === "tool_use" && block.name) {
|
|
4618
|
+
const inputStr = typeof block.input === "string" ? block.input : JSON.stringify(block.input);
|
|
4619
|
+
connection.emitAuditProgress({
|
|
4620
|
+
requestId: request.requestId,
|
|
4621
|
+
activity: {
|
|
4622
|
+
tool: block.name,
|
|
4623
|
+
input: inputStr.slice(0, 500),
|
|
4624
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
4625
|
+
}
|
|
4626
|
+
});
|
|
4627
|
+
}
|
|
4628
|
+
}
|
|
4629
|
+
}
|
|
4538
4630
|
async function runAuditQuery(request, connection, projectDir) {
|
|
4631
|
+
connection.emitAgentStatus("fetching_context");
|
|
4539
4632
|
let agentCtx = null;
|
|
4540
4633
|
try {
|
|
4541
4634
|
agentCtx = await connection.fetchAgentContext();
|
|
4542
4635
|
} catch {
|
|
4543
4636
|
logger5.warn("Could not fetch agent context for audit, using defaults");
|
|
4544
4637
|
}
|
|
4638
|
+
connection.emitAgentStatus("running");
|
|
4545
4639
|
const model = agentCtx?.model || FALLBACK_MODEL2;
|
|
4546
4640
|
const settings = agentCtx?.agentSettings ?? {};
|
|
4547
4641
|
const collector = {
|
|
@@ -4549,6 +4643,13 @@ async function runAuditQuery(request, connection, projectDir) {
|
|
|
4549
4643
|
summary: "Audit completed.",
|
|
4550
4644
|
complete: false
|
|
4551
4645
|
};
|
|
4646
|
+
const onRecommendation = (rec) => {
|
|
4647
|
+
connection.emitEvent({
|
|
4648
|
+
type: "audit_recommendation",
|
|
4649
|
+
tagName: rec.tagName,
|
|
4650
|
+
recommendationType: rec.type
|
|
4651
|
+
});
|
|
4652
|
+
};
|
|
4552
4653
|
const systemPrompt = buildAuditSystemPrompt(
|
|
4553
4654
|
request.projectName,
|
|
4554
4655
|
request.tags,
|
|
@@ -4572,20 +4673,28 @@ async function runAuditQuery(request, connection, projectDir) {
|
|
|
4572
4673
|
permissionMode: "bypassPermissions",
|
|
4573
4674
|
allowDangerouslySkipPermissions: true,
|
|
4574
4675
|
tools: { type: "preset", preset: "claude_code" },
|
|
4575
|
-
mcpServers: { "tag-audit": createAuditMcpServer(collector) },
|
|
4676
|
+
mcpServers: { "tag-audit": createAuditMcpServer(collector, onRecommendation) },
|
|
4576
4677
|
maxTurns: settings.maxTurns ?? 30,
|
|
4577
4678
|
maxBudgetUsd: settings.maxBudgetUsd ?? 5,
|
|
4578
4679
|
effort: settings.effort,
|
|
4579
4680
|
thinking: settings.thinking
|
|
4580
4681
|
}
|
|
4581
4682
|
});
|
|
4683
|
+
const responseParts = [];
|
|
4684
|
+
const turnToolCalls = [];
|
|
4685
|
+
const isTyping = { value: false };
|
|
4582
4686
|
for await (const event of events) {
|
|
4583
|
-
|
|
4687
|
+
emitToolCallProgress(event, request, connection);
|
|
4688
|
+
const done = processEventStream(event, connection, responseParts, turnToolCalls, isTyping);
|
|
4689
|
+
if (done) break;
|
|
4690
|
+
}
|
|
4691
|
+
if (isTyping.value) {
|
|
4692
|
+
connection.emitEvent({ type: "agent_typing_stop" });
|
|
4584
4693
|
}
|
|
4585
4694
|
return collector;
|
|
4586
4695
|
}
|
|
4587
4696
|
async function handleProjectAuditRequest(request, connection, projectDir) {
|
|
4588
|
-
connection.emitAgentStatus("
|
|
4697
|
+
connection.emitAgentStatus("running");
|
|
4589
4698
|
try {
|
|
4590
4699
|
const collector = await runAuditQuery(request, connection, projectDir);
|
|
4591
4700
|
const result = {
|
|
@@ -5063,6 +5172,11 @@ var ProjectRunner = class {
|
|
|
5063
5172
|
this.connection.onGetEnvStatus = (cb) => {
|
|
5064
5173
|
this.handleGetEnvStatus(cb);
|
|
5065
5174
|
};
|
|
5175
|
+
this.connection.onRestartStartCommand = (cb) => {
|
|
5176
|
+
void this.restartStartCommand().then(() => cb({ ok: true })).catch(
|
|
5177
|
+
(err) => cb({ ok: false, error: err instanceof Error ? err.message : "Restart failed" })
|
|
5178
|
+
);
|
|
5179
|
+
};
|
|
5066
5180
|
try {
|
|
5067
5181
|
const context = await this.connection.fetchAgentContext();
|
|
5068
5182
|
this.branchSwitchCommand = context?.branchSwitchCommand ?? process.env.CONVEYOR_BRANCH_SWITCH_COMMAND;
|
|
@@ -5274,4 +5388,4 @@ export {
|
|
|
5274
5388
|
ProjectRunner,
|
|
5275
5389
|
FileCache
|
|
5276
5390
|
};
|
|
5277
|
-
//# sourceMappingURL=chunk-
|
|
5391
|
+
//# sourceMappingURL=chunk-LBEAK2VJ.js.map
|