@rallycry/conveyor-agent 5.1.2 → 5.3.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-4SXL45ZH.js → chunk-DMWUXQ4M.js} +143 -130
- package/dist/chunk-DMWUXQ4M.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-4SXL45ZH.js.map +0 -1
|
@@ -752,7 +752,7 @@ function aggregateModelUsage(modelUsage) {
|
|
|
752
752
|
}
|
|
753
753
|
return { queryInputTokens, contextWindow, totalInputTokens, totalCacheRead, totalCacheCreation };
|
|
754
754
|
}
|
|
755
|
-
function emitContextUpdate(modelUsage, host, context) {
|
|
755
|
+
function emitContextUpdate(modelUsage, host, context, lastAssistantUsage) {
|
|
756
756
|
const usage = aggregateModelUsage(modelUsage);
|
|
757
757
|
let { contextWindow } = usage;
|
|
758
758
|
const settings = context.agentSettings ?? host.config.agentSettings ?? {};
|
|
@@ -761,13 +761,15 @@ function emitContextUpdate(modelUsage, host, context) {
|
|
|
761
761
|
contextWindow = 1e6;
|
|
762
762
|
}
|
|
763
763
|
if (contextWindow > 0) {
|
|
764
|
+
const currentContextTokens = lastAssistantUsage ? (lastAssistantUsage.input_tokens ?? 0) + (lastAssistantUsage.cache_read_input_tokens ?? 0) + (lastAssistantUsage.cache_creation_input_tokens ?? 0) : usage.queryInputTokens;
|
|
764
765
|
host.connection.sendEvent({
|
|
765
766
|
type: "context_update",
|
|
766
|
-
contextTokens:
|
|
767
|
+
contextTokens: currentContextTokens,
|
|
767
768
|
contextWindow,
|
|
768
769
|
inputTokens: usage.totalInputTokens,
|
|
769
770
|
cacheReadInputTokens: usage.totalCacheRead,
|
|
770
|
-
cacheCreationInputTokens: usage.totalCacheCreation
|
|
771
|
+
cacheCreationInputTokens: usage.totalCacheCreation,
|
|
772
|
+
totalTokensUsed: usage.queryInputTokens
|
|
771
773
|
});
|
|
772
774
|
}
|
|
773
775
|
}
|
|
@@ -783,7 +785,7 @@ function trackCostSpending(host, context, cumulativeTotal) {
|
|
|
783
785
|
});
|
|
784
786
|
}
|
|
785
787
|
}
|
|
786
|
-
function handleSuccessResult(event, host, context, startTime) {
|
|
788
|
+
function handleSuccessResult(event, host, context, startTime, lastAssistantUsage) {
|
|
787
789
|
const durationMs = Date.now() - startTime;
|
|
788
790
|
const summary = event.result || "Task completed.";
|
|
789
791
|
const retriable = isRetriableMessage(summary);
|
|
@@ -794,28 +796,38 @@ function handleSuccessResult(event, host, context, startTime) {
|
|
|
794
796
|
}
|
|
795
797
|
host.connection.sendEvent({ type: "completed", summary, costUsd: cumulativeTotal, durationMs });
|
|
796
798
|
if (modelUsage && typeof modelUsage === "object") {
|
|
797
|
-
emitContextUpdate(modelUsage, host, context);
|
|
799
|
+
emitContextUpdate(modelUsage, host, context, lastAssistantUsage);
|
|
798
800
|
}
|
|
799
801
|
trackCostSpending(host, context, cumulativeTotal);
|
|
800
802
|
return { totalCostUsd: cumulativeTotal, retriable };
|
|
801
803
|
}
|
|
802
804
|
function handleErrorResult(event, host) {
|
|
803
805
|
const errorMsg = event.errors.length > 0 ? event.errors.join(", ") : `Agent stopped: ${event.subtype}`;
|
|
806
|
+
const isStaleSession = errorMsg.includes("No conversation found with session ID");
|
|
807
|
+
if (isStaleSession) {
|
|
808
|
+
return { retriable: false, staleSession: true };
|
|
809
|
+
}
|
|
804
810
|
const retriable = isRetriableMessage(errorMsg);
|
|
805
811
|
host.connection.sendEvent({ type: "error", message: errorMsg });
|
|
806
812
|
return { retriable };
|
|
807
813
|
}
|
|
808
|
-
function handleResultEvent(event, host, context, startTime) {
|
|
814
|
+
function handleResultEvent(event, host, context, startTime, lastAssistantUsage) {
|
|
809
815
|
const resultSummary = event.subtype === "success" ? event.result : event.errors.join(", ");
|
|
810
816
|
if (event.subtype === "success") {
|
|
811
|
-
const result2 = handleSuccessResult(
|
|
817
|
+
const result2 = handleSuccessResult(
|
|
818
|
+
event,
|
|
819
|
+
host,
|
|
820
|
+
context,
|
|
821
|
+
startTime,
|
|
822
|
+
lastAssistantUsage
|
|
823
|
+
);
|
|
812
824
|
return { ...result2, resultSummary };
|
|
813
825
|
}
|
|
814
826
|
const result = handleErrorResult(event, host);
|
|
815
827
|
return { totalCostUsd: 0, ...result, resultSummary };
|
|
816
828
|
}
|
|
817
|
-
async function emitResultEvent(event, host, context, startTime) {
|
|
818
|
-
const result = handleResultEvent(event, host, context, startTime);
|
|
829
|
+
async function emitResultEvent(event, host, context, startTime, lastAssistantUsage) {
|
|
830
|
+
const result = handleResultEvent(event, host, context, startTime, lastAssistantUsage);
|
|
819
831
|
const durationMs = Date.now() - startTime;
|
|
820
832
|
if (event.subtype === "success") {
|
|
821
833
|
const successEvent = event;
|
|
@@ -826,12 +838,16 @@ async function emitResultEvent(event, host, context, startTime) {
|
|
|
826
838
|
costUsd: result.totalCostUsd,
|
|
827
839
|
durationMs
|
|
828
840
|
});
|
|
829
|
-
} else {
|
|
841
|
+
} else if (!result.staleSession) {
|
|
830
842
|
const errorEvent = event;
|
|
831
843
|
const errorMsg = errorEvent.errors.length > 0 ? errorEvent.errors.join(", ") : `Agent stopped: ${errorEvent.subtype}`;
|
|
832
844
|
await host.callbacks.onEvent({ type: "error", message: errorMsg });
|
|
833
845
|
}
|
|
834
|
-
return {
|
|
846
|
+
return {
|
|
847
|
+
retriable: result.retriable,
|
|
848
|
+
resultSummary: result.resultSummary,
|
|
849
|
+
staleSession: result.staleSession
|
|
850
|
+
};
|
|
835
851
|
}
|
|
836
852
|
function handleRateLimitEvent(event, host) {
|
|
837
853
|
const { rate_limit_info } = event;
|
|
@@ -878,6 +894,8 @@ async function processEvents(events, context, host) {
|
|
|
878
894
|
let retriable = false;
|
|
879
895
|
let resultSummary;
|
|
880
896
|
let rateLimitResetsAt;
|
|
897
|
+
let staleSession;
|
|
898
|
+
let lastAssistantUsage;
|
|
881
899
|
const turnToolCalls = [];
|
|
882
900
|
for await (const event of events) {
|
|
883
901
|
if (host.isStopped()) break;
|
|
@@ -899,7 +917,12 @@ async function processEvents(events, context, host) {
|
|
|
899
917
|
setTimeout(() => host.connection.sendTypingStart(), 200);
|
|
900
918
|
isTyping = true;
|
|
901
919
|
}
|
|
902
|
-
|
|
920
|
+
const assistantEvent = event;
|
|
921
|
+
await processAssistantEvent(assistantEvent, host, turnToolCalls);
|
|
922
|
+
const msgUsage = assistantEvent.message.usage;
|
|
923
|
+
if (msgUsage) {
|
|
924
|
+
lastAssistantUsage = msgUsage;
|
|
925
|
+
}
|
|
903
926
|
break;
|
|
904
927
|
}
|
|
905
928
|
case "result": {
|
|
@@ -911,10 +934,14 @@ async function processEvents(events, context, host) {
|
|
|
911
934
|
event,
|
|
912
935
|
host,
|
|
913
936
|
context,
|
|
914
|
-
startTime
|
|
937
|
+
startTime,
|
|
938
|
+
lastAssistantUsage
|
|
915
939
|
);
|
|
916
940
|
retriable = resultInfo.retriable;
|
|
917
941
|
resultSummary = resultInfo.resultSummary;
|
|
942
|
+
if (resultInfo.staleSession) {
|
|
943
|
+
staleSession = true;
|
|
944
|
+
}
|
|
918
945
|
break;
|
|
919
946
|
}
|
|
920
947
|
case "rate_limit_event": {
|
|
@@ -927,7 +954,12 @@ async function processEvents(events, context, host) {
|
|
|
927
954
|
if (isTyping) {
|
|
928
955
|
host.connection.sendTypingStop();
|
|
929
956
|
}
|
|
930
|
-
return {
|
|
957
|
+
return {
|
|
958
|
+
retriable,
|
|
959
|
+
resultSummary,
|
|
960
|
+
rateLimitResetsAt,
|
|
961
|
+
...staleSession && { staleSession }
|
|
962
|
+
};
|
|
931
963
|
}
|
|
932
964
|
|
|
933
965
|
// src/execution/query-executor.ts
|
|
@@ -1323,7 +1355,7 @@ Your responses are sent directly to the task chat \u2014 the team sees everythin
|
|
|
1323
1355
|
);
|
|
1324
1356
|
if (!isPm || isPmActive) {
|
|
1325
1357
|
parts.push(
|
|
1326
|
-
`Use the
|
|
1358
|
+
`Use the mcp__conveyor__create_pull_request tool to open PRs \u2014 do NOT use gh CLI or shell commands for PR creation.`
|
|
1327
1359
|
);
|
|
1328
1360
|
}
|
|
1329
1361
|
const modePrompt = buildModePrompt(agentMode, context);
|
|
@@ -1394,7 +1426,7 @@ Address the requested changes. Do NOT re-investigate the codebase from scratch o
|
|
|
1394
1426
|
);
|
|
1395
1427
|
} else {
|
|
1396
1428
|
parts.push(
|
|
1397
|
-
`When finished, use the
|
|
1429
|
+
`When finished, use the mcp__conveyor__create_pull_request tool to open a PR. Do NOT use gh CLI.`
|
|
1398
1430
|
);
|
|
1399
1431
|
}
|
|
1400
1432
|
} else {
|
|
@@ -1501,11 +1533,13 @@ function buildFreshInstructions(isPm, isAutoMode, context, agentMode) {
|
|
|
1501
1533
|
`Your plan has been approved. Begin implementing it now.`,
|
|
1502
1534
|
`Work on the git branch "${context.githubBranch}". Stay on this branch \u2014 do not checkout or create other branches.`,
|
|
1503
1535
|
`Start by reading the relevant source files mentioned in the plan, then write code.`,
|
|
1504
|
-
`When finished, commit and push your changes, then use the
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1536
|
+
`When finished, commit and push your changes, then use the mcp__conveyor__create_pull_request tool to open a PR. Do NOT use gh CLI.`,
|
|
1537
|
+
`
|
|
1538
|
+
CRITICAL: You are in Auto mode. Do NOT report status, ask for confirmation, or go idle without making code changes.`,
|
|
1539
|
+
`Your FIRST action must be reading source files from the plan, then immediately writing code.`,
|
|
1540
|
+
`Do NOT summarize the plan or say "ready to implement" \u2014 start implementing.`,
|
|
1541
|
+
`When all changes are committed and pushed, use mcp__conveyor__create_pull_request to open a PR.`,
|
|
1542
|
+
`If you are genuinely blocked, explain the specific blocker \u2014 do not go idle silently.`
|
|
1509
1543
|
];
|
|
1510
1544
|
}
|
|
1511
1545
|
if (isAutoMode && isPm) {
|
|
@@ -1533,13 +1567,23 @@ IMPORTANT: You are in Auto mode. You MUST create a pull request using create_pul
|
|
|
1533
1567
|
`When you finish planning, save the plan with update_task and end your turn. Your reply summarizing the plan will be visible in chat. A separate task agent will execute the plan after review.`
|
|
1534
1568
|
];
|
|
1535
1569
|
}
|
|
1536
|
-
|
|
1570
|
+
const parts = [
|
|
1537
1571
|
`Begin executing the task plan above immediately.`,
|
|
1538
1572
|
`Your FIRST action should be reading the relevant source files mentioned in the plan, then writing code. Do NOT run install, build, lint, test, or dev server commands first \u2014 the environment is already set up.`,
|
|
1539
1573
|
`Work on the git branch "${context.githubBranch}". Stay on this branch for the entire task. Do not checkout or create other branches.`,
|
|
1540
1574
|
`Your replies are visible to the team in chat \u2014 briefly describe what you're doing when you begin meaningful implementation, and again when the PR is ready.`,
|
|
1541
|
-
`When finished, commit your changes, then run \`git fetch origin ${context.githubBranch}\` and \`git push origin ${context.githubBranch}\` (use --force-with-lease if push fails). Then use the
|
|
1575
|
+
`When finished, commit your changes, then run \`git fetch origin ${context.githubBranch}\` and \`git push origin ${context.githubBranch}\` (use --force-with-lease if push fails). Then use the mcp__conveyor__create_pull_request tool to open a PR. Do NOT use gh CLI or any other method to create PRs.`
|
|
1542
1576
|
];
|
|
1577
|
+
if (isAutoMode) {
|
|
1578
|
+
parts.push(
|
|
1579
|
+
`
|
|
1580
|
+
CRITICAL: You are in Auto mode. Do NOT report status, ask for confirmation, or go idle without making code changes.`,
|
|
1581
|
+
`Do NOT summarize the plan or say "ready to implement" \u2014 start implementing immediately.`,
|
|
1582
|
+
`When all changes are committed and pushed, you MUST use mcp__conveyor__create_pull_request to open a PR before finishing.`,
|
|
1583
|
+
`If you are genuinely blocked, explain the specific blocker \u2014 do not go idle silently.`
|
|
1584
|
+
);
|
|
1585
|
+
}
|
|
1586
|
+
return parts;
|
|
1543
1587
|
}
|
|
1544
1588
|
function buildFeedbackInstructions(context, isPm) {
|
|
1545
1589
|
const lastAgentIdx = findLastAgentMessageIndex2(context.chatHistory);
|
|
@@ -1572,7 +1616,7 @@ Address the requested changes directly. Do NOT re-investigate the codebase from
|
|
|
1572
1616
|
);
|
|
1573
1617
|
} else {
|
|
1574
1618
|
parts.push(
|
|
1575
|
-
`When finished, use the
|
|
1619
|
+
`When finished, use the mcp__conveyor__create_pull_request tool to open a PR. Do NOT use gh CLI or any other method to create PRs.`
|
|
1576
1620
|
);
|
|
1577
1621
|
}
|
|
1578
1622
|
return parts;
|
|
@@ -1884,6 +1928,30 @@ function buildGetTaskIncidentsTool(connection) {
|
|
|
1884
1928
|
{ annotations: { readOnlyHint: true } }
|
|
1885
1929
|
);
|
|
1886
1930
|
}
|
|
1931
|
+
function buildCreatePullRequestTool(connection) {
|
|
1932
|
+
return tool(
|
|
1933
|
+
"create_pull_request",
|
|
1934
|
+
"Create a GitHub pull request for this task. Use this instead of gh CLI or git commands to create PRs.",
|
|
1935
|
+
{
|
|
1936
|
+
title: z.string().describe("The PR title"),
|
|
1937
|
+
body: z.string().describe("The PR description/body in markdown")
|
|
1938
|
+
},
|
|
1939
|
+
async ({ title, body }) => {
|
|
1940
|
+
try {
|
|
1941
|
+
const result = await connection.createPR({ title, body });
|
|
1942
|
+
connection.sendEvent({
|
|
1943
|
+
type: "pr_created",
|
|
1944
|
+
url: result.url,
|
|
1945
|
+
number: result.number
|
|
1946
|
+
});
|
|
1947
|
+
return textResult(`Pull request #${result.number} created: ${result.url}`);
|
|
1948
|
+
} catch (error) {
|
|
1949
|
+
const msg = error instanceof Error ? error.message : "Unknown error";
|
|
1950
|
+
return textResult(`Failed to create pull request: ${msg}`);
|
|
1951
|
+
}
|
|
1952
|
+
}
|
|
1953
|
+
);
|
|
1954
|
+
}
|
|
1887
1955
|
function buildCommonTools(connection, config) {
|
|
1888
1956
|
return [
|
|
1889
1957
|
buildReadTaskChatTool(connection),
|
|
@@ -1895,7 +1963,8 @@ function buildCommonTools(connection, config) {
|
|
|
1895
1963
|
buildListTaskFilesTool(connection),
|
|
1896
1964
|
buildGetTaskFileTool(connection),
|
|
1897
1965
|
buildSearchIncidentsTool(connection),
|
|
1898
|
-
buildGetTaskIncidentsTool(connection)
|
|
1966
|
+
buildGetTaskIncidentsTool(connection),
|
|
1967
|
+
buildCreatePullRequestTool(connection)
|
|
1899
1968
|
];
|
|
1900
1969
|
}
|
|
1901
1970
|
|
|
@@ -2063,42 +2132,12 @@ function buildPackTools(connection) {
|
|
|
2063
2132
|
];
|
|
2064
2133
|
}
|
|
2065
2134
|
|
|
2066
|
-
// src/tools/
|
|
2135
|
+
// src/tools/discovery-tools.ts
|
|
2067
2136
|
import { tool as tool3 } from "@anthropic-ai/claude-agent-sdk";
|
|
2068
2137
|
import { z as z3 } from "zod";
|
|
2069
|
-
function buildTaskTools(connection) {
|
|
2070
|
-
return [
|
|
2071
|
-
tool3(
|
|
2072
|
-
"create_pull_request",
|
|
2073
|
-
"Create a GitHub pull request for this task. Use this instead of gh CLI or git commands to create PRs.",
|
|
2074
|
-
{
|
|
2075
|
-
title: z3.string().describe("The PR title"),
|
|
2076
|
-
body: z3.string().describe("The PR description/body in markdown")
|
|
2077
|
-
},
|
|
2078
|
-
async ({ title, body }) => {
|
|
2079
|
-
try {
|
|
2080
|
-
const result = await connection.createPR({ title, body });
|
|
2081
|
-
connection.sendEvent({
|
|
2082
|
-
type: "pr_created",
|
|
2083
|
-
url: result.url,
|
|
2084
|
-
number: result.number
|
|
2085
|
-
});
|
|
2086
|
-
return textResult(`Pull request #${result.number} created: ${result.url}`);
|
|
2087
|
-
} catch (error) {
|
|
2088
|
-
const msg = error instanceof Error ? error.message : "Unknown error";
|
|
2089
|
-
return textResult(`Failed to create pull request: ${msg}`);
|
|
2090
|
-
}
|
|
2091
|
-
}
|
|
2092
|
-
)
|
|
2093
|
-
];
|
|
2094
|
-
}
|
|
2095
|
-
|
|
2096
|
-
// src/tools/discovery-tools.ts
|
|
2097
|
-
import { tool as tool4 } from "@anthropic-ai/claude-agent-sdk";
|
|
2098
|
-
import { z as z4 } from "zod";
|
|
2099
2138
|
function buildIconTools(connection) {
|
|
2100
2139
|
return [
|
|
2101
|
-
|
|
2140
|
+
tool3(
|
|
2102
2141
|
"list_icons",
|
|
2103
2142
|
"List available icons (default library + user-created). Returns icon IDs, names, and whether they're defaults. Call this FIRST before set_task_icon to check for existing matches.",
|
|
2104
2143
|
{},
|
|
@@ -2114,11 +2153,11 @@ function buildIconTools(connection) {
|
|
|
2114
2153
|
},
|
|
2115
2154
|
{ annotations: { readOnlyHint: true } }
|
|
2116
2155
|
),
|
|
2117
|
-
|
|
2156
|
+
tool3(
|
|
2118
2157
|
"set_task_icon",
|
|
2119
2158
|
"Assign an existing icon to this task by its ID. Use list_icons first to find a matching icon.",
|
|
2120
2159
|
{
|
|
2121
|
-
iconId:
|
|
2160
|
+
iconId: z3.string().describe("The icon ID to assign")
|
|
2122
2161
|
},
|
|
2123
2162
|
async ({ iconId }) => {
|
|
2124
2163
|
try {
|
|
@@ -2131,14 +2170,14 @@ function buildIconTools(connection) {
|
|
|
2131
2170
|
}
|
|
2132
2171
|
}
|
|
2133
2172
|
),
|
|
2134
|
-
|
|
2173
|
+
tool3(
|
|
2135
2174
|
"generate_task_icon",
|
|
2136
2175
|
"Generate a new SVG icon using AI and assign it to this task. Only use if no existing icon from list_icons is a good fit. Provide a concise visual description.",
|
|
2137
2176
|
{
|
|
2138
|
-
prompt:
|
|
2177
|
+
prompt: z3.string().describe(
|
|
2139
2178
|
"Description of the icon to generate (e.g. 'minimal flat gear and wrench icon')"
|
|
2140
2179
|
),
|
|
2141
|
-
aspectRatio:
|
|
2180
|
+
aspectRatio: z3.enum(["auto", "portrait", "landscape", "square"]).optional().describe("Icon aspect ratio, defaults to square")
|
|
2142
2181
|
},
|
|
2143
2182
|
async ({ prompt, aspectRatio }) => {
|
|
2144
2183
|
try {
|
|
@@ -2156,10 +2195,10 @@ function buildIconTools(connection) {
|
|
|
2156
2195
|
function buildDiscoveryTools(connection, context) {
|
|
2157
2196
|
const spDescription = buildStoryPointDescription(context?.storyPoints);
|
|
2158
2197
|
return [
|
|
2159
|
-
|
|
2198
|
+
tool3(
|
|
2160
2199
|
"set_story_points",
|
|
2161
2200
|
"Set the story point estimate for this task. Use after understanding the scope of the work.",
|
|
2162
|
-
{ value:
|
|
2201
|
+
{ value: z3.number().describe(spDescription) },
|
|
2163
2202
|
async ({ value }) => {
|
|
2164
2203
|
try {
|
|
2165
2204
|
await Promise.resolve(connection.updateTaskProperties({ storyPointValue: value }));
|
|
@@ -2171,11 +2210,11 @@ function buildDiscoveryTools(connection, context) {
|
|
|
2171
2210
|
}
|
|
2172
2211
|
}
|
|
2173
2212
|
),
|
|
2174
|
-
|
|
2213
|
+
tool3(
|
|
2175
2214
|
"set_task_tags",
|
|
2176
2215
|
"Assign tags to this task from the project's available tags. Use the tag IDs from the project tags list.",
|
|
2177
2216
|
{
|
|
2178
|
-
tagIds:
|
|
2217
|
+
tagIds: z3.array(z3.string()).describe("Array of tag IDs to assign")
|
|
2179
2218
|
},
|
|
2180
2219
|
async ({ tagIds }) => {
|
|
2181
2220
|
try {
|
|
@@ -2188,11 +2227,11 @@ function buildDiscoveryTools(connection, context) {
|
|
|
2188
2227
|
}
|
|
2189
2228
|
}
|
|
2190
2229
|
),
|
|
2191
|
-
|
|
2230
|
+
tool3(
|
|
2192
2231
|
"set_task_title",
|
|
2193
2232
|
"Update the task title to better reflect the planned work.",
|
|
2194
2233
|
{
|
|
2195
|
-
title:
|
|
2234
|
+
title: z3.string().describe("The new task title")
|
|
2196
2235
|
},
|
|
2197
2236
|
async ({ title }) => {
|
|
2198
2237
|
try {
|
|
@@ -2219,10 +2258,7 @@ function imageBlock(data, mimeType) {
|
|
|
2219
2258
|
function getModeTools(agentMode, connection, config, context) {
|
|
2220
2259
|
switch (agentMode) {
|
|
2221
2260
|
case "building":
|
|
2222
|
-
return context?.isParentTask ? [
|
|
2223
|
-
...buildTaskTools(connection),
|
|
2224
|
-
...buildPmTools(connection, context?.storyPoints, { includePackTools: true })
|
|
2225
|
-
] : buildTaskTools(connection);
|
|
2261
|
+
return context?.isParentTask ? buildPmTools(connection, context?.storyPoints, { includePackTools: true }) : [];
|
|
2226
2262
|
case "review":
|
|
2227
2263
|
case "auto":
|
|
2228
2264
|
case "discovery":
|
|
@@ -2231,7 +2267,7 @@ function getModeTools(agentMode, connection, config, context) {
|
|
|
2231
2267
|
includePackTools: !!context?.isParentTask
|
|
2232
2268
|
});
|
|
2233
2269
|
default:
|
|
2234
|
-
return config.mode === "pm" ? buildPmTools(connection, context?.storyPoints, { includePackTools: false }) :
|
|
2270
|
+
return config.mode === "pm" ? buildPmTools(connection, context?.storyPoints, { includePackTools: false }) : [];
|
|
2235
2271
|
}
|
|
2236
2272
|
}
|
|
2237
2273
|
function createConveyorMcpServer(connection, config, context, agentMode) {
|
|
@@ -2684,16 +2720,15 @@ async function runWithRetry(initialQuery, context, host, options) {
|
|
|
2684
2720
|
if (host.isStopped()) return;
|
|
2685
2721
|
const agentQuery = attempt === 0 ? initialQuery : buildRetryQuery(host, context, options, lastErrorWasImage);
|
|
2686
2722
|
try {
|
|
2687
|
-
const { retriable, resultSummary, modeRestart, rateLimitResetsAt } = await processEvents(
|
|
2688
|
-
agentQuery,
|
|
2689
|
-
context,
|
|
2690
|
-
host
|
|
2691
|
-
);
|
|
2723
|
+
const { retriable, resultSummary, modeRestart, rateLimitResetsAt, staleSession } = await processEvents(agentQuery, context, host);
|
|
2692
2724
|
if (modeRestart || host.isStopped()) return;
|
|
2693
2725
|
if (rateLimitResetsAt) {
|
|
2694
2726
|
handleRateLimitPause(host, rateLimitResetsAt);
|
|
2695
2727
|
return;
|
|
2696
2728
|
}
|
|
2729
|
+
if (staleSession && context.claudeSessionId) {
|
|
2730
|
+
return handleStaleSession(context, host, options);
|
|
2731
|
+
}
|
|
2697
2732
|
if (!retriable) return;
|
|
2698
2733
|
lastErrorWasImage = IMAGE_ERROR_PATTERN2.test(resultSummary ?? "");
|
|
2699
2734
|
} catch (error) {
|
|
@@ -2913,39 +2948,6 @@ async function runSetupSafe(runnerConfig, connection, callbacks, setupLog, _effe
|
|
|
2913
2948
|
if (!await checkoutTaskBranch(runnerConfig, connection, callbacks, setupLog)) {
|
|
2914
2949
|
return { ok: false, deferredStartConfig: null };
|
|
2915
2950
|
}
|
|
2916
|
-
const taskBranch = process.env.CONVEYOR_TASK_BRANCH;
|
|
2917
|
-
if (taskBranch) {
|
|
2918
|
-
pushSetupLog(setupLog, `[conveyor] Switching to task branch ${taskBranch}...`);
|
|
2919
|
-
connection.sendEvent({
|
|
2920
|
-
type: "setup_output",
|
|
2921
|
-
stream: "stdout",
|
|
2922
|
-
data: `Switching to task branch ${taskBranch}...
|
|
2923
|
-
`
|
|
2924
|
-
});
|
|
2925
|
-
try {
|
|
2926
|
-
await runSetupCommand(
|
|
2927
|
-
`git fetch origin ${taskBranch} && git checkout ${taskBranch}`,
|
|
2928
|
-
runnerConfig.workspaceDir,
|
|
2929
|
-
(stream, data) => {
|
|
2930
|
-
connection.sendEvent({ type: "setup_output", stream, data });
|
|
2931
|
-
for (const line of data.split("\n").filter(Boolean)) {
|
|
2932
|
-
pushSetupLog(setupLog, `[${stream}] ${line}`);
|
|
2933
|
-
}
|
|
2934
|
-
}
|
|
2935
|
-
);
|
|
2936
|
-
pushSetupLog(setupLog, `[conveyor] Switched to ${taskBranch}`);
|
|
2937
|
-
} catch (error) {
|
|
2938
|
-
const message = `Failed to checkout ${taskBranch}: ${error instanceof Error ? error.message : "unknown error"}`;
|
|
2939
|
-
connection.sendEvent({ type: "setup_error", message });
|
|
2940
|
-
await callbacks.onEvent({ type: "setup_error", message });
|
|
2941
|
-
connection.postChatMessage(
|
|
2942
|
-
`Failed to switch to task branch \`${taskBranch}\`.
|
|
2943
|
-
|
|
2944
|
-
${message}`
|
|
2945
|
-
);
|
|
2946
|
-
return { ok: false, deferredStartConfig: null };
|
|
2947
|
-
}
|
|
2948
|
-
}
|
|
2949
2951
|
const config = await loadConveyorConfig(runnerConfig.workspaceDir);
|
|
2950
2952
|
if (!config) {
|
|
2951
2953
|
connection.sendEvent({ type: "setup_complete" });
|
|
@@ -3138,7 +3140,7 @@ var AgentRunner = class {
|
|
|
3138
3140
|
sessionIds = /* @__PURE__ */ new Map();
|
|
3139
3141
|
lastQueryModeRestart = false;
|
|
3140
3142
|
startCommandStarted = false;
|
|
3141
|
-
|
|
3143
|
+
prNudgeCount = 0;
|
|
3142
3144
|
idleTimer = null;
|
|
3143
3145
|
idleCheckInterval = null;
|
|
3144
3146
|
deferredStartConfig = null;
|
|
@@ -3283,27 +3285,38 @@ var AgentRunner = class {
|
|
|
3283
3285
|
} catch {
|
|
3284
3286
|
}
|
|
3285
3287
|
}
|
|
3288
|
+
needsPRNudge() {
|
|
3289
|
+
if (!this.config.isAuto || this.stopped) return false;
|
|
3290
|
+
const maxNudges = this.taskContext?.agentSettings?.maxPrNudges ?? this.config.agentSettings?.maxPrNudges ?? 3;
|
|
3291
|
+
if (this.prNudgeCount >= maxNudges) return false;
|
|
3292
|
+
const status = this.taskContext?.status;
|
|
3293
|
+
return status === "InProgress" && !this.taskContext?.githubPRUrl;
|
|
3294
|
+
}
|
|
3286
3295
|
async maybeSendPRNudge() {
|
|
3287
|
-
if (!this.config.isAuto || this.nudgedForPR || this.stopped) return false;
|
|
3288
3296
|
const fresh = await this.connection.fetchTaskContext().catch(() => null);
|
|
3289
3297
|
if (fresh) this.taskContext = fresh;
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3298
|
+
if (!this.needsPRNudge()) return false;
|
|
3299
|
+
this.prNudgeCount++;
|
|
3300
|
+
const ctx = this.taskContext ?? fresh;
|
|
3301
|
+
if (!ctx) return false;
|
|
3302
|
+
const maxNudges = this.taskContext?.agentSettings?.maxPrNudges ?? this.config.agentSettings?.maxPrNudges ?? 3;
|
|
3303
|
+
if (this.prNudgeCount >= maxNudges) {
|
|
3294
3304
|
this.connection.postChatMessage(
|
|
3295
|
-
|
|
3296
|
-
);
|
|
3297
|
-
await this.setState("running");
|
|
3298
|
-
const ctx = this.taskContext ?? fresh;
|
|
3299
|
-
if (!ctx) return false;
|
|
3300
|
-
await this.runQuerySafe(
|
|
3301
|
-
ctx,
|
|
3302
|
-
"You are in Auto mode and your task is still In Progress with no pull request. You MUST create a pull request before finishing. Use the create_pull_request tool now to open a PR for your changes. If you are blocked, explain what is preventing you from creating a PR."
|
|
3305
|
+
`Auto-mode agent failed to open a PR after ${maxNudges} nudges. Shutting down.`
|
|
3303
3306
|
);
|
|
3307
|
+
this.stop();
|
|
3304
3308
|
return true;
|
|
3305
3309
|
}
|
|
3306
|
-
|
|
3310
|
+
await this.sendPRNudgeQuery(ctx, maxNudges);
|
|
3311
|
+
return true;
|
|
3312
|
+
}
|
|
3313
|
+
async sendPRNudgeQuery(ctx, maxNudges) {
|
|
3314
|
+
const isFirst = this.prNudgeCount === 1;
|
|
3315
|
+
const chatMsg = isFirst ? "Auto-nudge: Task is still In Progress with no PR. Prompting agent to continue..." : `Auto-nudge (attempt ${this.prNudgeCount}/${maxNudges}): Task still has no PR. Prompting agent again...`;
|
|
3316
|
+
const prompt = isFirst ? "You are in Auto mode and your task is still In Progress with no pull request. You MUST create a pull request before finishing. Use the create_pull_request tool now to open a PR for your changes. If you are blocked, explain what is preventing you from creating a PR." : `This is reminder ${this.prNudgeCount} of ${maxNudges}. You MUST open a pull request using create_pull_request NOW or explain what is blocking you. Do NOT go idle \u2014 either create the PR or describe the specific blocker.`;
|
|
3317
|
+
this.connection.postChatMessage(chatMsg);
|
|
3318
|
+
await this.setState("running");
|
|
3319
|
+
await this.runQuerySafe(ctx, prompt);
|
|
3307
3320
|
}
|
|
3308
3321
|
async executeInitialMode() {
|
|
3309
3322
|
if (!this.taskContext) return;
|
|
@@ -3723,7 +3736,7 @@ var logger4 = createServiceLogger("ProjectRunner");
|
|
|
3723
3736
|
var __filename = fileURLToPath(import.meta.url);
|
|
3724
3737
|
var __dirname = path.dirname(__filename);
|
|
3725
3738
|
var HEARTBEAT_INTERVAL_MS2 = 3e4;
|
|
3726
|
-
var MAX_CONCURRENT =
|
|
3739
|
+
var MAX_CONCURRENT = Math.max(1, parseInt(process.env.CONVEYOR_MAX_CONCURRENT ?? "10", 10) || 10);
|
|
3727
3740
|
var STOP_TIMEOUT_MS = 3e4;
|
|
3728
3741
|
function setupWorkDir(projectDir, assignment) {
|
|
3729
3742
|
const { taskId, branch, devBranch, useWorktree } = assignment;
|
|
@@ -3806,7 +3819,7 @@ var ProjectRunner = class {
|
|
|
3806
3819
|
projectId: config.projectId
|
|
3807
3820
|
});
|
|
3808
3821
|
}
|
|
3809
|
-
|
|
3822
|
+
checkoutWorkspaceBranch() {
|
|
3810
3823
|
const workspaceBranch = process.env.CONVEYOR_WORKSPACE_BRANCH;
|
|
3811
3824
|
if (!workspaceBranch) return;
|
|
3812
3825
|
try {
|
|
@@ -3821,7 +3834,7 @@ var ProjectRunner = class {
|
|
|
3821
3834
|
}
|
|
3822
3835
|
}
|
|
3823
3836
|
async start() {
|
|
3824
|
-
|
|
3837
|
+
this.checkoutWorkspaceBranch();
|
|
3825
3838
|
await this.connection.connect();
|
|
3826
3839
|
this.connection.onTaskAssignment((assignment) => {
|
|
3827
3840
|
this.handleAssignment(assignment);
|
|
@@ -4036,4 +4049,4 @@ export {
|
|
|
4036
4049
|
ProjectRunner,
|
|
4037
4050
|
FileCache
|
|
4038
4051
|
};
|
|
4039
|
-
//# sourceMappingURL=chunk-
|
|
4052
|
+
//# sourceMappingURL=chunk-DMWUXQ4M.js.map
|