@rallycry/conveyor-agent 5.10.0 → 5.10.3
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-MRTSBPY7.js → chunk-ASK2L7IU.js} +177 -52
- package/dist/chunk-ASK2L7IU.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-MRTSBPY7.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)
|
|
@@ -784,6 +792,14 @@ import { randomUUID as randomUUID2 } from "crypto";
|
|
|
784
792
|
import { execSync as execSync4 } from "child_process";
|
|
785
793
|
|
|
786
794
|
// src/execution/event-handlers.ts
|
|
795
|
+
function safeVoid(promise, context) {
|
|
796
|
+
if (promise && typeof promise.catch === "function") {
|
|
797
|
+
promise.catch((err) => {
|
|
798
|
+
process.stderr.write(`[safeVoid] ${context}: ${err}
|
|
799
|
+
`);
|
|
800
|
+
});
|
|
801
|
+
}
|
|
802
|
+
}
|
|
787
803
|
function epochSecondsToISO(value) {
|
|
788
804
|
if (typeof value === "string") return value;
|
|
789
805
|
if (typeof value !== "number" || value <= 0) return void 0;
|
|
@@ -960,13 +976,13 @@ function handleRateLimitEvent(event, host) {
|
|
|
960
976
|
const resetsAtDisplay = resetsAt ?? "unknown";
|
|
961
977
|
const message = `Rate limit rejected (type: ${rate_limit_info.rateLimitType ?? "unknown"}, resets at: ${resetsAtDisplay})`;
|
|
962
978
|
host.connection.sendEvent({ type: "error", message });
|
|
963
|
-
|
|
979
|
+
safeVoid(host.callbacks.onEvent({ type: "error", message }), "rateLimitRejected");
|
|
964
980
|
return resetsAt;
|
|
965
981
|
} else if (status === "allowed_warning") {
|
|
966
982
|
const utilization = rate_limit_info.utilization ? `${Math.round(rate_limit_info.utilization * 100)}%` : "high";
|
|
967
983
|
const message = `Rate limit warning: ${utilization} utilization (type: ${rate_limit_info.rateLimitType ?? "unknown"})`;
|
|
968
984
|
host.connection.sendEvent({ type: "thinking", message });
|
|
969
|
-
|
|
985
|
+
safeVoid(host.callbacks.onEvent({ type: "thinking", message }), "rateLimitWarning");
|
|
970
986
|
}
|
|
971
987
|
return void 0;
|
|
972
988
|
}
|
|
@@ -984,34 +1000,46 @@ async function handleSystemEvent(event, host, context, sessionIdStored) {
|
|
|
984
1000
|
}
|
|
985
1001
|
function handleSystemSubevents(systemEvent, host) {
|
|
986
1002
|
if (systemEvent.subtype === "compact_boundary") {
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
1003
|
+
safeVoid(
|
|
1004
|
+
host.callbacks.onEvent({
|
|
1005
|
+
type: "context_compacted",
|
|
1006
|
+
trigger: systemEvent.compact_metadata.trigger,
|
|
1007
|
+
preTokens: systemEvent.compact_metadata.pre_tokens
|
|
1008
|
+
}),
|
|
1009
|
+
"compactBoundary"
|
|
1010
|
+
);
|
|
992
1011
|
} else if (systemEvent.subtype === "task_started") {
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
1012
|
+
safeVoid(
|
|
1013
|
+
host.callbacks.onEvent({
|
|
1014
|
+
type: "subagent_started",
|
|
1015
|
+
sdkTaskId: systemEvent.task_id,
|
|
1016
|
+
description: systemEvent.description
|
|
1017
|
+
}),
|
|
1018
|
+
"taskStarted"
|
|
1019
|
+
);
|
|
998
1020
|
} else if (systemEvent.subtype === "task_progress") {
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1021
|
+
safeVoid(
|
|
1022
|
+
host.callbacks.onEvent({
|
|
1023
|
+
type: "subagent_progress",
|
|
1024
|
+
sdkTaskId: systemEvent.task_id,
|
|
1025
|
+
description: systemEvent.description,
|
|
1026
|
+
toolUses: systemEvent.usage?.tool_uses ?? 0,
|
|
1027
|
+
durationMs: systemEvent.usage?.duration_ms ?? 0
|
|
1028
|
+
}),
|
|
1029
|
+
"taskProgress"
|
|
1030
|
+
);
|
|
1006
1031
|
}
|
|
1007
1032
|
}
|
|
1008
1033
|
function handleToolProgressEvent(event, host) {
|
|
1009
1034
|
const msg = event;
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1035
|
+
safeVoid(
|
|
1036
|
+
host.callbacks.onEvent({
|
|
1037
|
+
type: "tool_progress",
|
|
1038
|
+
toolName: msg.tool_name ?? "",
|
|
1039
|
+
elapsedSeconds: msg.elapsed_time_seconds ?? 0
|
|
1040
|
+
}),
|
|
1041
|
+
"toolProgress"
|
|
1042
|
+
);
|
|
1015
1043
|
}
|
|
1016
1044
|
async function handleAssistantCase(event, host, turnToolCalls) {
|
|
1017
1045
|
await processAssistantEvent(event, host, turnToolCalls);
|
|
@@ -1034,6 +1062,7 @@ async function handleResultCase(event, host, context, startTime, isTyping, lastA
|
|
|
1034
1062
|
}
|
|
1035
1063
|
|
|
1036
1064
|
// src/execution/event-processor.ts
|
|
1065
|
+
var API_ERROR_PATTERN2 = /API Error: [45]\d\d/;
|
|
1037
1066
|
function stopTypingIfNeeded(host, isTyping) {
|
|
1038
1067
|
if (isTyping) host.connection.sendTypingStop();
|
|
1039
1068
|
}
|
|
@@ -1055,6 +1084,12 @@ async function processAssistantCase(event, host, state) {
|
|
|
1055
1084
|
}
|
|
1056
1085
|
const usage = await handleAssistantCase(event, host, state.turnToolCalls);
|
|
1057
1086
|
if (usage) state.lastAssistantUsage = usage;
|
|
1087
|
+
if (!state.sawApiError) {
|
|
1088
|
+
const fullText = event.message.content.filter((b) => b.type === "text").map((b) => b.text).join(" ");
|
|
1089
|
+
if (API_ERROR_PATTERN2.test(fullText)) {
|
|
1090
|
+
state.sawApiError = true;
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1058
1093
|
}
|
|
1059
1094
|
async function processResultCase(event, host, context, startTime, state) {
|
|
1060
1095
|
const info = await handleResultCase(
|
|
@@ -1078,6 +1113,7 @@ async function processEvents(events, context, host) {
|
|
|
1078
1113
|
sessionIdStored: false,
|
|
1079
1114
|
isTyping: false,
|
|
1080
1115
|
retriable: false,
|
|
1116
|
+
sawApiError: false,
|
|
1081
1117
|
resultSummary: void 0,
|
|
1082
1118
|
rateLimitResetsAt: void 0,
|
|
1083
1119
|
staleSession: void 0,
|
|
@@ -1117,7 +1153,7 @@ async function processEvents(events, context, host) {
|
|
|
1117
1153
|
}
|
|
1118
1154
|
stopTypingIfNeeded(host, state.isTyping);
|
|
1119
1155
|
return {
|
|
1120
|
-
retriable: state.retriable,
|
|
1156
|
+
retriable: state.retriable || state.sawApiError,
|
|
1121
1157
|
resultSummary: state.resultSummary,
|
|
1122
1158
|
rateLimitResetsAt: state.rateLimitResetsAt,
|
|
1123
1159
|
...state.staleSession && { staleSession: state.staleSession }
|
|
@@ -1478,6 +1514,8 @@ function buildDiscoveryPrompt(context) {
|
|
|
1478
1514
|
`You are in Discovery mode \u2014 helping plan and scope this task.`,
|
|
1479
1515
|
`- You have read-only codebase access (can read files, run git commands, search code)`,
|
|
1480
1516
|
`- You can write plan files in .claude/plans/ only \u2014 no other file writes`,
|
|
1517
|
+
`- Do NOT attempt to edit, write, or modify source code files \u2014 these operations will be denied`,
|
|
1518
|
+
`- If you identify code changes needed, describe them in the plan instead of implementing them`,
|
|
1481
1519
|
`- You can create and manage subtasks`,
|
|
1482
1520
|
`- Goal: collaborate with the user to create a clear plan`,
|
|
1483
1521
|
`- Proactively fill task properties (SP, tags, icon) as the plan takes shape`,
|
|
@@ -1742,7 +1780,7 @@ function detectRelaunchScenario(context, trustChatHistory = false) {
|
|
|
1742
1780
|
const hasNewUserMessages = messagesAfterAgent.some((m) => m.role === "user");
|
|
1743
1781
|
return hasNewUserMessages ? "feedback_relaunch" : "idle_relaunch";
|
|
1744
1782
|
}
|
|
1745
|
-
function buildRelaunchWithSession(mode, context, agentMode) {
|
|
1783
|
+
function buildRelaunchWithSession(mode, context, agentMode, isAuto) {
|
|
1746
1784
|
const scenario = detectRelaunchScenario(context);
|
|
1747
1785
|
if (!context.claudeSessionId || scenario === "fresh") return null;
|
|
1748
1786
|
const parts = [];
|
|
@@ -1790,7 +1828,7 @@ Address the requested changes. Do NOT re-investigate the codebase from scratch o
|
|
|
1790
1828
|
`Run \`git log --oneline -10\` to review what you already committed.`,
|
|
1791
1829
|
`Review the current state of the codebase and verify everything is working correctly.`
|
|
1792
1830
|
);
|
|
1793
|
-
if (agentMode === "auto" || agentMode === "building") {
|
|
1831
|
+
if (agentMode === "auto" || agentMode === "building" && isAuto) {
|
|
1794
1832
|
parts.push(
|
|
1795
1833
|
`If work is incomplete, continue implementing the plan. When finished, commit, push, and use mcp__conveyor__create_pull_request to open a PR.`,
|
|
1796
1834
|
`Do NOT go idle or wait for instructions \u2014 you are in auto mode.`
|
|
@@ -1996,7 +2034,7 @@ Address the requested changes directly. Do NOT re-investigate the codebase from
|
|
|
1996
2034
|
}
|
|
1997
2035
|
return parts;
|
|
1998
2036
|
}
|
|
1999
|
-
function buildInstructions(mode, context, scenario, agentMode) {
|
|
2037
|
+
function buildInstructions(mode, context, scenario, agentMode, isAuto) {
|
|
2000
2038
|
const parts = [`
|
|
2001
2039
|
## Instructions`];
|
|
2002
2040
|
const isPm = mode === "pm";
|
|
@@ -2028,7 +2066,7 @@ function buildInstructions(mode, context, scenario, agentMode) {
|
|
|
2028
2066
|
`Work on the git branch "${context.githubBranch}". Stay on this branch \u2014 do not checkout or create other branches.`,
|
|
2029
2067
|
`Run \`git log --oneline -10\` to review what you already committed, then verify the current state is correct.`
|
|
2030
2068
|
);
|
|
2031
|
-
if (agentMode === "auto" || agentMode === "building") {
|
|
2069
|
+
if (agentMode === "auto" || agentMode === "building" && isAuto) {
|
|
2032
2070
|
parts.push(
|
|
2033
2071
|
`If work is incomplete, continue implementing the plan. When finished, commit, push, and use mcp__conveyor__create_pull_request to open a PR.`,
|
|
2034
2072
|
`Do NOT go idle or wait for instructions \u2014 you are in auto mode.`
|
|
@@ -2051,13 +2089,13 @@ function buildInstructions(mode, context, scenario, agentMode) {
|
|
|
2051
2089
|
async function buildInitialPrompt(mode, context, isAuto, agentMode) {
|
|
2052
2090
|
const isPackRunner = mode === "pm" && !!isAuto && !!context.isParentTask;
|
|
2053
2091
|
if (!isPackRunner) {
|
|
2054
|
-
const sessionRelaunch = buildRelaunchWithSession(mode, context, agentMode);
|
|
2092
|
+
const sessionRelaunch = buildRelaunchWithSession(mode, context, agentMode, isAuto);
|
|
2055
2093
|
if (sessionRelaunch) return sessionRelaunch;
|
|
2056
2094
|
}
|
|
2057
2095
|
const isPm = mode === "pm";
|
|
2058
2096
|
const scenario = detectRelaunchScenario(context, isPm);
|
|
2059
2097
|
const body = await buildTaskBody(context);
|
|
2060
|
-
const instructions = isPackRunner ? buildPackRunnerInstructions(context, scenario) : buildInstructions(mode, context, scenario, agentMode);
|
|
2098
|
+
const instructions = isPackRunner ? buildPackRunnerInstructions(context, scenario) : buildInstructions(mode, context, scenario, agentMode, isAuto);
|
|
2061
2099
|
return [...body, ...instructions].join("\n");
|
|
2062
2100
|
}
|
|
2063
2101
|
|
|
@@ -2811,7 +2849,9 @@ async function handleAskUserQuestion(host, input) {
|
|
|
2811
2849
|
}
|
|
2812
2850
|
return { behavior: "allow", updatedInput: { questions: input.questions, answers } };
|
|
2813
2851
|
}
|
|
2852
|
+
var DENIAL_WARNING_THRESHOLD = 3;
|
|
2814
2853
|
function buildCanUseTool(host) {
|
|
2854
|
+
let consecutiveDenials = 0;
|
|
2815
2855
|
return async (toolName, input) => {
|
|
2816
2856
|
if (toolName === "ExitPlanMode" && (host.agentMode === "auto" || host.agentMode === "discovery") && !host.hasExitedPlanMode) {
|
|
2817
2857
|
return await handleExitPlanMode(host, input);
|
|
@@ -2819,23 +2859,39 @@ function buildCanUseTool(host) {
|
|
|
2819
2859
|
if (toolName === "AskUserQuestion") {
|
|
2820
2860
|
return await handleAskUserQuestion(host, input);
|
|
2821
2861
|
}
|
|
2862
|
+
let result;
|
|
2822
2863
|
switch (host.agentMode) {
|
|
2823
2864
|
case "discovery":
|
|
2824
|
-
|
|
2865
|
+
result = handleDiscoveryToolAccess(toolName, input);
|
|
2866
|
+
break;
|
|
2825
2867
|
case "building":
|
|
2826
|
-
|
|
2868
|
+
result = handleBuildingToolAccess(toolName, input);
|
|
2869
|
+
break;
|
|
2827
2870
|
case "review":
|
|
2828
|
-
|
|
2871
|
+
result = handleReviewToolAccess(toolName, input, host.isParentTask);
|
|
2872
|
+
break;
|
|
2829
2873
|
case "auto":
|
|
2830
|
-
|
|
2874
|
+
result = handleAutoToolAccess(toolName, input, host.hasExitedPlanMode, host.isParentTask);
|
|
2875
|
+
break;
|
|
2831
2876
|
default:
|
|
2832
|
-
|
|
2877
|
+
result = { behavior: "allow", updatedInput: input };
|
|
2878
|
+
}
|
|
2879
|
+
if (result.behavior === "deny") {
|
|
2880
|
+
consecutiveDenials++;
|
|
2881
|
+
if (consecutiveDenials === DENIAL_WARNING_THRESHOLD) {
|
|
2882
|
+
host.connection.postChatMessage(
|
|
2883
|
+
`\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.`
|
|
2884
|
+
);
|
|
2885
|
+
}
|
|
2886
|
+
} else {
|
|
2887
|
+
consecutiveDenials = 0;
|
|
2833
2888
|
}
|
|
2889
|
+
return result;
|
|
2834
2890
|
};
|
|
2835
2891
|
}
|
|
2836
2892
|
|
|
2837
2893
|
// src/execution/query-executor.ts
|
|
2838
|
-
var
|
|
2894
|
+
var API_ERROR_PATTERN3 = /API Error: [45]\d\d/;
|
|
2839
2895
|
var IMAGE_ERROR_PATTERN2 = /Could not process image/i;
|
|
2840
2896
|
var RETRY_DELAYS_MS = [6e4, 12e4, 18e4, 3e5];
|
|
2841
2897
|
function buildHooks(host) {
|
|
@@ -3083,12 +3139,17 @@ function isStaleOrExitedSession(error, context) {
|
|
|
3083
3139
|
if (error.message.includes("No conversation found with session ID")) return true;
|
|
3084
3140
|
return !!context.claudeSessionId && error.message.includes("process exited");
|
|
3085
3141
|
}
|
|
3142
|
+
function getErrorMessage(error) {
|
|
3143
|
+
if (error instanceof Error) return error.message;
|
|
3144
|
+
if (typeof error === "string") return error;
|
|
3145
|
+
return String(error);
|
|
3146
|
+
}
|
|
3086
3147
|
function isRetriableError(error) {
|
|
3087
|
-
|
|
3088
|
-
return
|
|
3148
|
+
const message = getErrorMessage(error);
|
|
3149
|
+
return API_ERROR_PATTERN3.test(message) || IMAGE_ERROR_PATTERN2.test(message);
|
|
3089
3150
|
}
|
|
3090
3151
|
function classifyImageError(error) {
|
|
3091
|
-
return
|
|
3152
|
+
return IMAGE_ERROR_PATTERN2.test(getErrorMessage(error));
|
|
3092
3153
|
}
|
|
3093
3154
|
async function emitRetryStatus(host, attempt, delayMs) {
|
|
3094
3155
|
const delayMin = Math.round(delayMs / 6e4);
|
|
@@ -4166,6 +4227,41 @@ function buildChatQueryOptions(agentCtx, projectDir) {
|
|
|
4166
4227
|
thinking: settings.thinking
|
|
4167
4228
|
};
|
|
4168
4229
|
}
|
|
4230
|
+
function emitResultCostAndContext(event, connection) {
|
|
4231
|
+
const resultEvent = event;
|
|
4232
|
+
if (resultEvent.total_cost_usd !== void 0 && resultEvent.total_cost_usd > 0) {
|
|
4233
|
+
connection.emitEvent({
|
|
4234
|
+
type: "cost_update",
|
|
4235
|
+
costUsd: resultEvent.total_cost_usd
|
|
4236
|
+
});
|
|
4237
|
+
}
|
|
4238
|
+
if (resultEvent.modelUsage && typeof resultEvent.modelUsage === "object") {
|
|
4239
|
+
const modelUsage = resultEvent.modelUsage;
|
|
4240
|
+
let contextWindow = 0;
|
|
4241
|
+
let totalInputTokens = 0;
|
|
4242
|
+
let totalCacheRead = 0;
|
|
4243
|
+
let totalCacheCreation = 0;
|
|
4244
|
+
for (const data of Object.values(modelUsage)) {
|
|
4245
|
+
const d = data;
|
|
4246
|
+
totalInputTokens += d.inputTokens ?? 0;
|
|
4247
|
+
totalCacheRead += d.cacheReadInputTokens ?? 0;
|
|
4248
|
+
totalCacheCreation += d.cacheCreationInputTokens ?? 0;
|
|
4249
|
+
const cw = d.contextWindow ?? 0;
|
|
4250
|
+
if (cw > contextWindow) contextWindow = cw;
|
|
4251
|
+
}
|
|
4252
|
+
if (contextWindow > 0) {
|
|
4253
|
+
const queryInputTokens = totalInputTokens + totalCacheRead + totalCacheCreation;
|
|
4254
|
+
connection.emitEvent({
|
|
4255
|
+
type: "context_update",
|
|
4256
|
+
contextTokens: queryInputTokens,
|
|
4257
|
+
contextWindow,
|
|
4258
|
+
inputTokens: totalInputTokens,
|
|
4259
|
+
cacheReadInputTokens: totalCacheRead,
|
|
4260
|
+
cacheCreationInputTokens: totalCacheCreation
|
|
4261
|
+
});
|
|
4262
|
+
}
|
|
4263
|
+
}
|
|
4264
|
+
}
|
|
4169
4265
|
function processEventStream(event, connection, responseParts, turnToolCalls, isTyping) {
|
|
4170
4266
|
if (event.type === "assistant") {
|
|
4171
4267
|
if (!isTyping.value) {
|
|
@@ -4187,6 +4283,7 @@ function processEventStream(event, connection, responseParts, turnToolCalls, isT
|
|
|
4187
4283
|
connection.emitEvent({ type: "agent_typing_stop" });
|
|
4188
4284
|
isTyping.value = false;
|
|
4189
4285
|
}
|
|
4286
|
+
emitResultCostAndContext(event, connection);
|
|
4190
4287
|
return true;
|
|
4191
4288
|
}
|
|
4192
4289
|
return false;
|
|
@@ -4308,14 +4405,15 @@ var TOOL_MAPPERS = {
|
|
|
4308
4405
|
recommend_merge_tags: mapMergeTags,
|
|
4309
4406
|
recommend_rename_tag: mapRenameTag
|
|
4310
4407
|
};
|
|
4311
|
-
function collectRecommendation(toolName, input, collector) {
|
|
4408
|
+
function collectRecommendation(toolName, input, collector, onRecommendation) {
|
|
4312
4409
|
const mapper = TOOL_MAPPERS[toolName];
|
|
4313
4410
|
if (!mapper) return JSON.stringify({ error: `Unknown tool: ${toolName}` });
|
|
4314
4411
|
const rec = { id: randomUUID3(), ...mapper(input) };
|
|
4315
4412
|
collector.recommendations.push(rec);
|
|
4413
|
+
onRecommendation?.({ tagName: rec.tagName ?? rec.type, type: rec.type });
|
|
4316
4414
|
return JSON.stringify({ success: true, recommendationId: rec.id });
|
|
4317
4415
|
}
|
|
4318
|
-
function createAuditMcpServer(collector) {
|
|
4416
|
+
function createAuditMcpServer(collector, onRecommendation) {
|
|
4319
4417
|
const auditTools = [
|
|
4320
4418
|
tool4(
|
|
4321
4419
|
"recommend_create_tag",
|
|
@@ -4330,7 +4428,8 @@ function createAuditMcpServer(collector) {
|
|
|
4330
4428
|
const result = collectRecommendation(
|
|
4331
4429
|
"recommend_create_tag",
|
|
4332
4430
|
args,
|
|
4333
|
-
collector
|
|
4431
|
+
collector,
|
|
4432
|
+
onRecommendation
|
|
4334
4433
|
);
|
|
4335
4434
|
return { content: [{ type: "text", text: result }] };
|
|
4336
4435
|
}
|
|
@@ -4348,7 +4447,8 @@ function createAuditMcpServer(collector) {
|
|
|
4348
4447
|
const result = collectRecommendation(
|
|
4349
4448
|
"recommend_update_description",
|
|
4350
4449
|
args,
|
|
4351
|
-
collector
|
|
4450
|
+
collector,
|
|
4451
|
+
onRecommendation
|
|
4352
4452
|
);
|
|
4353
4453
|
return { content: [{ type: "text", text: result }] };
|
|
4354
4454
|
}
|
|
@@ -4368,7 +4468,8 @@ function createAuditMcpServer(collector) {
|
|
|
4368
4468
|
const result = collectRecommendation(
|
|
4369
4469
|
"recommend_context_link",
|
|
4370
4470
|
args,
|
|
4371
|
-
collector
|
|
4471
|
+
collector,
|
|
4472
|
+
onRecommendation
|
|
4372
4473
|
);
|
|
4373
4474
|
return { content: [{ type: "text", text: result }] };
|
|
4374
4475
|
}
|
|
@@ -4388,7 +4489,8 @@ function createAuditMcpServer(collector) {
|
|
|
4388
4489
|
const result = collectRecommendation(
|
|
4389
4490
|
"flag_documentation_gap",
|
|
4390
4491
|
args,
|
|
4391
|
-
collector
|
|
4492
|
+
collector,
|
|
4493
|
+
onRecommendation
|
|
4392
4494
|
);
|
|
4393
4495
|
return { content: [{ type: "text", text: result }] };
|
|
4394
4496
|
}
|
|
@@ -4407,7 +4509,8 @@ function createAuditMcpServer(collector) {
|
|
|
4407
4509
|
const result = collectRecommendation(
|
|
4408
4510
|
"recommend_merge_tags",
|
|
4409
4511
|
args,
|
|
4410
|
-
collector
|
|
4512
|
+
collector,
|
|
4513
|
+
onRecommendation
|
|
4411
4514
|
);
|
|
4412
4515
|
return { content: [{ type: "text", text: result }] };
|
|
4413
4516
|
}
|
|
@@ -4425,7 +4528,8 @@ function createAuditMcpServer(collector) {
|
|
|
4425
4528
|
const result = collectRecommendation(
|
|
4426
4529
|
"recommend_rename_tag",
|
|
4427
4530
|
args,
|
|
4428
|
-
collector
|
|
4531
|
+
collector,
|
|
4532
|
+
onRecommendation
|
|
4429
4533
|
);
|
|
4430
4534
|
return { content: [{ type: "text", text: result }] };
|
|
4431
4535
|
}
|
|
@@ -4500,12 +4604,14 @@ function buildAuditSystemPrompt(projectName, tags, heatmapData, projectDir) {
|
|
|
4500
4604
|
].join("\n");
|
|
4501
4605
|
}
|
|
4502
4606
|
async function runAuditQuery(request, connection, projectDir) {
|
|
4607
|
+
connection.emitAgentStatus("fetching_context");
|
|
4503
4608
|
let agentCtx = null;
|
|
4504
4609
|
try {
|
|
4505
4610
|
agentCtx = await connection.fetchAgentContext();
|
|
4506
4611
|
} catch {
|
|
4507
4612
|
logger5.warn("Could not fetch agent context for audit, using defaults");
|
|
4508
4613
|
}
|
|
4614
|
+
connection.emitAgentStatus("running");
|
|
4509
4615
|
const model = agentCtx?.model || FALLBACK_MODEL2;
|
|
4510
4616
|
const settings = agentCtx?.agentSettings ?? {};
|
|
4511
4617
|
const collector = {
|
|
@@ -4513,6 +4619,13 @@ async function runAuditQuery(request, connection, projectDir) {
|
|
|
4513
4619
|
summary: "Audit completed.",
|
|
4514
4620
|
complete: false
|
|
4515
4621
|
};
|
|
4622
|
+
const onRecommendation = (rec) => {
|
|
4623
|
+
connection.emitEvent({
|
|
4624
|
+
type: "audit_recommendation",
|
|
4625
|
+
tagName: rec.tagName,
|
|
4626
|
+
recommendationType: rec.type
|
|
4627
|
+
});
|
|
4628
|
+
};
|
|
4516
4629
|
const systemPrompt = buildAuditSystemPrompt(
|
|
4517
4630
|
request.projectName,
|
|
4518
4631
|
request.tags,
|
|
@@ -4536,20 +4649,27 @@ async function runAuditQuery(request, connection, projectDir) {
|
|
|
4536
4649
|
permissionMode: "bypassPermissions",
|
|
4537
4650
|
allowDangerouslySkipPermissions: true,
|
|
4538
4651
|
tools: { type: "preset", preset: "claude_code" },
|
|
4539
|
-
mcpServers: { "tag-audit": createAuditMcpServer(collector) },
|
|
4652
|
+
mcpServers: { "tag-audit": createAuditMcpServer(collector, onRecommendation) },
|
|
4540
4653
|
maxTurns: settings.maxTurns ?? 30,
|
|
4541
4654
|
maxBudgetUsd: settings.maxBudgetUsd ?? 5,
|
|
4542
4655
|
effort: settings.effort,
|
|
4543
4656
|
thinking: settings.thinking
|
|
4544
4657
|
}
|
|
4545
4658
|
});
|
|
4659
|
+
const responseParts = [];
|
|
4660
|
+
const turnToolCalls = [];
|
|
4661
|
+
const isTyping = { value: false };
|
|
4546
4662
|
for await (const event of events) {
|
|
4547
|
-
|
|
4663
|
+
const done = processEventStream(event, connection, responseParts, turnToolCalls, isTyping);
|
|
4664
|
+
if (done) break;
|
|
4665
|
+
}
|
|
4666
|
+
if (isTyping.value) {
|
|
4667
|
+
connection.emitEvent({ type: "agent_typing_stop" });
|
|
4548
4668
|
}
|
|
4549
4669
|
return collector;
|
|
4550
4670
|
}
|
|
4551
4671
|
async function handleProjectAuditRequest(request, connection, projectDir) {
|
|
4552
|
-
connection.emitAgentStatus("
|
|
4672
|
+
connection.emitAgentStatus("running");
|
|
4553
4673
|
try {
|
|
4554
4674
|
const collector = await runAuditQuery(request, connection, projectDir);
|
|
4555
4675
|
const result = {
|
|
@@ -5027,6 +5147,11 @@ var ProjectRunner = class {
|
|
|
5027
5147
|
this.connection.onGetEnvStatus = (cb) => {
|
|
5028
5148
|
this.handleGetEnvStatus(cb);
|
|
5029
5149
|
};
|
|
5150
|
+
this.connection.onRestartStartCommand = (cb) => {
|
|
5151
|
+
void this.restartStartCommand().then(() => cb({ ok: true })).catch(
|
|
5152
|
+
(err) => cb({ ok: false, error: err instanceof Error ? err.message : "Restart failed" })
|
|
5153
|
+
);
|
|
5154
|
+
};
|
|
5030
5155
|
try {
|
|
5031
5156
|
const context = await this.connection.fetchAgentContext();
|
|
5032
5157
|
this.branchSwitchCommand = context?.branchSwitchCommand ?? process.env.CONVEYOR_BRANCH_SWITCH_COMMAND;
|
|
@@ -5238,4 +5363,4 @@ export {
|
|
|
5238
5363
|
ProjectRunner,
|
|
5239
5364
|
FileCache
|
|
5240
5365
|
};
|
|
5241
|
-
//# sourceMappingURL=chunk-
|
|
5366
|
+
//# sourceMappingURL=chunk-ASK2L7IU.js.map
|