@rallycry/conveyor-agent 5.2.0 → 5.4.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-R37YJZWE.js → chunk-DJJBHD4H.js} +182 -176
- package/dist/chunk-DJJBHD4H.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-R37YJZWE.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;
|
|
@@ -890,8 +908,35 @@ async function processEvents(events, context, host) {
|
|
|
890
908
|
switch (event.type) {
|
|
891
909
|
case "system": {
|
|
892
910
|
const systemEvent = event;
|
|
893
|
-
|
|
894
|
-
|
|
911
|
+
if (systemEvent.subtype === "init") {
|
|
912
|
+
const stored = await handleSystemEvent(systemEvent, host, context, sessionIdStored);
|
|
913
|
+
if (stored) sessionIdStored = true;
|
|
914
|
+
} else if (systemEvent.subtype === "compact_boundary") {
|
|
915
|
+
const meta = systemEvent.compact_metadata;
|
|
916
|
+
if (meta) {
|
|
917
|
+
void host.callbacks.onEvent({
|
|
918
|
+
type: "context_compacted",
|
|
919
|
+
trigger: meta.trigger,
|
|
920
|
+
preTokens: meta.pre_tokens
|
|
921
|
+
});
|
|
922
|
+
}
|
|
923
|
+
} else if (systemEvent.subtype === "task_started") {
|
|
924
|
+
const msg = systemEvent;
|
|
925
|
+
void host.callbacks.onEvent({
|
|
926
|
+
type: "subagent_started",
|
|
927
|
+
sdkTaskId: msg.task_id ?? "",
|
|
928
|
+
description: msg.description ?? ""
|
|
929
|
+
});
|
|
930
|
+
} else if (systemEvent.subtype === "task_progress") {
|
|
931
|
+
const msg = systemEvent;
|
|
932
|
+
void host.callbacks.onEvent({
|
|
933
|
+
type: "subagent_progress",
|
|
934
|
+
sdkTaskId: msg.task_id ?? "",
|
|
935
|
+
description: msg.description ?? "",
|
|
936
|
+
toolUses: msg.usage?.tool_uses ?? 0,
|
|
937
|
+
durationMs: msg.usage?.duration_ms ?? 0
|
|
938
|
+
});
|
|
939
|
+
}
|
|
895
940
|
break;
|
|
896
941
|
}
|
|
897
942
|
case "assistant": {
|
|
@@ -899,7 +944,12 @@ async function processEvents(events, context, host) {
|
|
|
899
944
|
setTimeout(() => host.connection.sendTypingStart(), 200);
|
|
900
945
|
isTyping = true;
|
|
901
946
|
}
|
|
902
|
-
|
|
947
|
+
const assistantEvent = event;
|
|
948
|
+
await processAssistantEvent(assistantEvent, host, turnToolCalls);
|
|
949
|
+
const msgUsage = assistantEvent.message.usage;
|
|
950
|
+
if (msgUsage) {
|
|
951
|
+
lastAssistantUsage = msgUsage;
|
|
952
|
+
}
|
|
903
953
|
break;
|
|
904
954
|
}
|
|
905
955
|
case "result": {
|
|
@@ -911,10 +961,14 @@ async function processEvents(events, context, host) {
|
|
|
911
961
|
event,
|
|
912
962
|
host,
|
|
913
963
|
context,
|
|
914
|
-
startTime
|
|
964
|
+
startTime,
|
|
965
|
+
lastAssistantUsage
|
|
915
966
|
);
|
|
916
967
|
retriable = resultInfo.retriable;
|
|
917
968
|
resultSummary = resultInfo.resultSummary;
|
|
969
|
+
if (resultInfo.staleSession) {
|
|
970
|
+
staleSession = true;
|
|
971
|
+
}
|
|
918
972
|
break;
|
|
919
973
|
}
|
|
920
974
|
case "rate_limit_event": {
|
|
@@ -922,12 +976,26 @@ async function processEvents(events, context, host) {
|
|
|
922
976
|
if (resetsAt) rateLimitResetsAt = resetsAt;
|
|
923
977
|
break;
|
|
924
978
|
}
|
|
979
|
+
case "tool_progress": {
|
|
980
|
+
const msg = event;
|
|
981
|
+
void host.callbacks.onEvent({
|
|
982
|
+
type: "tool_progress",
|
|
983
|
+
toolName: msg.tool_name ?? "",
|
|
984
|
+
elapsedSeconds: msg.elapsed_time_seconds ?? 0
|
|
985
|
+
});
|
|
986
|
+
break;
|
|
987
|
+
}
|
|
925
988
|
}
|
|
926
989
|
}
|
|
927
990
|
if (isTyping) {
|
|
928
991
|
host.connection.sendTypingStop();
|
|
929
992
|
}
|
|
930
|
-
return {
|
|
993
|
+
return {
|
|
994
|
+
retriable,
|
|
995
|
+
resultSummary,
|
|
996
|
+
rateLimitResetsAt,
|
|
997
|
+
...staleSession && { staleSession }
|
|
998
|
+
};
|
|
931
999
|
}
|
|
932
1000
|
|
|
933
1001
|
// src/execution/query-executor.ts
|
|
@@ -1323,7 +1391,7 @@ Your responses are sent directly to the task chat \u2014 the team sees everythin
|
|
|
1323
1391
|
);
|
|
1324
1392
|
if (!isPm || isPmActive) {
|
|
1325
1393
|
parts.push(
|
|
1326
|
-
`Use the
|
|
1394
|
+
`Use the mcp__conveyor__create_pull_request tool to open PRs \u2014 do NOT use gh CLI or shell commands for PR creation.`
|
|
1327
1395
|
);
|
|
1328
1396
|
}
|
|
1329
1397
|
const modePrompt = buildModePrompt(agentMode, context);
|
|
@@ -1394,7 +1462,7 @@ Address the requested changes. Do NOT re-investigate the codebase from scratch o
|
|
|
1394
1462
|
);
|
|
1395
1463
|
} else {
|
|
1396
1464
|
parts.push(
|
|
1397
|
-
`When finished, use the
|
|
1465
|
+
`When finished, use the mcp__conveyor__create_pull_request tool to open a PR. Do NOT use gh CLI.`
|
|
1398
1466
|
);
|
|
1399
1467
|
}
|
|
1400
1468
|
} else {
|
|
@@ -1501,12 +1569,12 @@ function buildFreshInstructions(isPm, isAutoMode, context, agentMode) {
|
|
|
1501
1569
|
`Your plan has been approved. Begin implementing it now.`,
|
|
1502
1570
|
`Work on the git branch "${context.githubBranch}". Stay on this branch \u2014 do not checkout or create other branches.`,
|
|
1503
1571
|
`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
|
|
1572
|
+
`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.`,
|
|
1505
1573
|
`
|
|
1506
1574
|
CRITICAL: You are in Auto mode. Do NOT report status, ask for confirmation, or go idle without making code changes.`,
|
|
1507
1575
|
`Your FIRST action must be reading source files from the plan, then immediately writing code.`,
|
|
1508
1576
|
`Do NOT summarize the plan or say "ready to implement" \u2014 start implementing.`,
|
|
1509
|
-
`When all changes are committed and pushed, use
|
|
1577
|
+
`When all changes are committed and pushed, use mcp__conveyor__create_pull_request to open a PR.`,
|
|
1510
1578
|
`If you are genuinely blocked, explain the specific blocker \u2014 do not go idle silently.`
|
|
1511
1579
|
];
|
|
1512
1580
|
}
|
|
@@ -1540,14 +1608,14 @@ CRITICAL: You are in Auto mode. Do NOT report status, ask for confirmation, or g
|
|
|
1540
1608
|
`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.`,
|
|
1541
1609
|
`Work on the git branch "${context.githubBranch}". Stay on this branch for the entire task. Do not checkout or create other branches.`,
|
|
1542
1610
|
`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.`,
|
|
1543
|
-
`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
|
|
1611
|
+
`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.`
|
|
1544
1612
|
];
|
|
1545
1613
|
if (isAutoMode) {
|
|
1546
1614
|
parts.push(
|
|
1547
1615
|
`
|
|
1548
1616
|
CRITICAL: You are in Auto mode. Do NOT report status, ask for confirmation, or go idle without making code changes.`,
|
|
1549
1617
|
`Do NOT summarize the plan or say "ready to implement" \u2014 start implementing immediately.`,
|
|
1550
|
-
`When all changes are committed and pushed, you MUST use
|
|
1618
|
+
`When all changes are committed and pushed, you MUST use mcp__conveyor__create_pull_request to open a PR before finishing.`,
|
|
1551
1619
|
`If you are genuinely blocked, explain the specific blocker \u2014 do not go idle silently.`
|
|
1552
1620
|
);
|
|
1553
1621
|
}
|
|
@@ -1584,7 +1652,7 @@ Address the requested changes directly. Do NOT re-investigate the codebase from
|
|
|
1584
1652
|
);
|
|
1585
1653
|
} else {
|
|
1586
1654
|
parts.push(
|
|
1587
|
-
`When finished, use the
|
|
1655
|
+
`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.`
|
|
1588
1656
|
);
|
|
1589
1657
|
}
|
|
1590
1658
|
return parts;
|
|
@@ -1896,6 +1964,30 @@ function buildGetTaskIncidentsTool(connection) {
|
|
|
1896
1964
|
{ annotations: { readOnlyHint: true } }
|
|
1897
1965
|
);
|
|
1898
1966
|
}
|
|
1967
|
+
function buildCreatePullRequestTool(connection) {
|
|
1968
|
+
return tool(
|
|
1969
|
+
"create_pull_request",
|
|
1970
|
+
"Create a GitHub pull request for this task. Use this instead of gh CLI or git commands to create PRs.",
|
|
1971
|
+
{
|
|
1972
|
+
title: z.string().describe("The PR title"),
|
|
1973
|
+
body: z.string().describe("The PR description/body in markdown")
|
|
1974
|
+
},
|
|
1975
|
+
async ({ title, body }) => {
|
|
1976
|
+
try {
|
|
1977
|
+
const result = await connection.createPR({ title, body });
|
|
1978
|
+
connection.sendEvent({
|
|
1979
|
+
type: "pr_created",
|
|
1980
|
+
url: result.url,
|
|
1981
|
+
number: result.number
|
|
1982
|
+
});
|
|
1983
|
+
return textResult(`Pull request #${result.number} created: ${result.url}`);
|
|
1984
|
+
} catch (error) {
|
|
1985
|
+
const msg = error instanceof Error ? error.message : "Unknown error";
|
|
1986
|
+
return textResult(`Failed to create pull request: ${msg}`);
|
|
1987
|
+
}
|
|
1988
|
+
}
|
|
1989
|
+
);
|
|
1990
|
+
}
|
|
1899
1991
|
function buildCommonTools(connection, config) {
|
|
1900
1992
|
return [
|
|
1901
1993
|
buildReadTaskChatTool(connection),
|
|
@@ -1907,7 +1999,8 @@ function buildCommonTools(connection, config) {
|
|
|
1907
1999
|
buildListTaskFilesTool(connection),
|
|
1908
2000
|
buildGetTaskFileTool(connection),
|
|
1909
2001
|
buildSearchIncidentsTool(connection),
|
|
1910
|
-
buildGetTaskIncidentsTool(connection)
|
|
2002
|
+
buildGetTaskIncidentsTool(connection),
|
|
2003
|
+
buildCreatePullRequestTool(connection)
|
|
1911
2004
|
];
|
|
1912
2005
|
}
|
|
1913
2006
|
|
|
@@ -2075,42 +2168,12 @@ function buildPackTools(connection) {
|
|
|
2075
2168
|
];
|
|
2076
2169
|
}
|
|
2077
2170
|
|
|
2078
|
-
// src/tools/
|
|
2171
|
+
// src/tools/discovery-tools.ts
|
|
2079
2172
|
import { tool as tool3 } from "@anthropic-ai/claude-agent-sdk";
|
|
2080
2173
|
import { z as z3 } from "zod";
|
|
2081
|
-
function buildTaskTools(connection) {
|
|
2082
|
-
return [
|
|
2083
|
-
tool3(
|
|
2084
|
-
"create_pull_request",
|
|
2085
|
-
"Create a GitHub pull request for this task. Use this instead of gh CLI or git commands to create PRs.",
|
|
2086
|
-
{
|
|
2087
|
-
title: z3.string().describe("The PR title"),
|
|
2088
|
-
body: z3.string().describe("The PR description/body in markdown")
|
|
2089
|
-
},
|
|
2090
|
-
async ({ title, body }) => {
|
|
2091
|
-
try {
|
|
2092
|
-
const result = await connection.createPR({ title, body });
|
|
2093
|
-
connection.sendEvent({
|
|
2094
|
-
type: "pr_created",
|
|
2095
|
-
url: result.url,
|
|
2096
|
-
number: result.number
|
|
2097
|
-
});
|
|
2098
|
-
return textResult(`Pull request #${result.number} created: ${result.url}`);
|
|
2099
|
-
} catch (error) {
|
|
2100
|
-
const msg = error instanceof Error ? error.message : "Unknown error";
|
|
2101
|
-
return textResult(`Failed to create pull request: ${msg}`);
|
|
2102
|
-
}
|
|
2103
|
-
}
|
|
2104
|
-
)
|
|
2105
|
-
];
|
|
2106
|
-
}
|
|
2107
|
-
|
|
2108
|
-
// src/tools/discovery-tools.ts
|
|
2109
|
-
import { tool as tool4 } from "@anthropic-ai/claude-agent-sdk";
|
|
2110
|
-
import { z as z4 } from "zod";
|
|
2111
2174
|
function buildIconTools(connection) {
|
|
2112
2175
|
return [
|
|
2113
|
-
|
|
2176
|
+
tool3(
|
|
2114
2177
|
"list_icons",
|
|
2115
2178
|
"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.",
|
|
2116
2179
|
{},
|
|
@@ -2126,11 +2189,11 @@ function buildIconTools(connection) {
|
|
|
2126
2189
|
},
|
|
2127
2190
|
{ annotations: { readOnlyHint: true } }
|
|
2128
2191
|
),
|
|
2129
|
-
|
|
2192
|
+
tool3(
|
|
2130
2193
|
"set_task_icon",
|
|
2131
2194
|
"Assign an existing icon to this task by its ID. Use list_icons first to find a matching icon.",
|
|
2132
2195
|
{
|
|
2133
|
-
iconId:
|
|
2196
|
+
iconId: z3.string().describe("The icon ID to assign")
|
|
2134
2197
|
},
|
|
2135
2198
|
async ({ iconId }) => {
|
|
2136
2199
|
try {
|
|
@@ -2143,14 +2206,14 @@ function buildIconTools(connection) {
|
|
|
2143
2206
|
}
|
|
2144
2207
|
}
|
|
2145
2208
|
),
|
|
2146
|
-
|
|
2209
|
+
tool3(
|
|
2147
2210
|
"generate_task_icon",
|
|
2148
2211
|
"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.",
|
|
2149
2212
|
{
|
|
2150
|
-
prompt:
|
|
2213
|
+
prompt: z3.string().describe(
|
|
2151
2214
|
"Description of the icon to generate (e.g. 'minimal flat gear and wrench icon')"
|
|
2152
2215
|
),
|
|
2153
|
-
aspectRatio:
|
|
2216
|
+
aspectRatio: z3.enum(["auto", "portrait", "landscape", "square"]).optional().describe("Icon aspect ratio, defaults to square")
|
|
2154
2217
|
},
|
|
2155
2218
|
async ({ prompt, aspectRatio }) => {
|
|
2156
2219
|
try {
|
|
@@ -2168,10 +2231,10 @@ function buildIconTools(connection) {
|
|
|
2168
2231
|
function buildDiscoveryTools(connection, context) {
|
|
2169
2232
|
const spDescription = buildStoryPointDescription(context?.storyPoints);
|
|
2170
2233
|
return [
|
|
2171
|
-
|
|
2234
|
+
tool3(
|
|
2172
2235
|
"set_story_points",
|
|
2173
2236
|
"Set the story point estimate for this task. Use after understanding the scope of the work.",
|
|
2174
|
-
{ value:
|
|
2237
|
+
{ value: z3.number().describe(spDescription) },
|
|
2175
2238
|
async ({ value }) => {
|
|
2176
2239
|
try {
|
|
2177
2240
|
await Promise.resolve(connection.updateTaskProperties({ storyPointValue: value }));
|
|
@@ -2183,11 +2246,11 @@ function buildDiscoveryTools(connection, context) {
|
|
|
2183
2246
|
}
|
|
2184
2247
|
}
|
|
2185
2248
|
),
|
|
2186
|
-
|
|
2249
|
+
tool3(
|
|
2187
2250
|
"set_task_tags",
|
|
2188
2251
|
"Assign tags to this task from the project's available tags. Use the tag IDs from the project tags list.",
|
|
2189
2252
|
{
|
|
2190
|
-
tagIds:
|
|
2253
|
+
tagIds: z3.array(z3.string()).describe("Array of tag IDs to assign")
|
|
2191
2254
|
},
|
|
2192
2255
|
async ({ tagIds }) => {
|
|
2193
2256
|
try {
|
|
@@ -2200,11 +2263,11 @@ function buildDiscoveryTools(connection, context) {
|
|
|
2200
2263
|
}
|
|
2201
2264
|
}
|
|
2202
2265
|
),
|
|
2203
|
-
|
|
2266
|
+
tool3(
|
|
2204
2267
|
"set_task_title",
|
|
2205
2268
|
"Update the task title to better reflect the planned work.",
|
|
2206
2269
|
{
|
|
2207
|
-
title:
|
|
2270
|
+
title: z3.string().describe("The new task title")
|
|
2208
2271
|
},
|
|
2209
2272
|
async ({ title }) => {
|
|
2210
2273
|
try {
|
|
@@ -2231,10 +2294,7 @@ function imageBlock(data, mimeType) {
|
|
|
2231
2294
|
function getModeTools(agentMode, connection, config, context) {
|
|
2232
2295
|
switch (agentMode) {
|
|
2233
2296
|
case "building":
|
|
2234
|
-
return context?.isParentTask ? [
|
|
2235
|
-
...buildTaskTools(connection),
|
|
2236
|
-
...buildPmTools(connection, context?.storyPoints, { includePackTools: true })
|
|
2237
|
-
] : buildTaskTools(connection);
|
|
2297
|
+
return context?.isParentTask ? buildPmTools(connection, context?.storyPoints, { includePackTools: true }) : [];
|
|
2238
2298
|
case "review":
|
|
2239
2299
|
case "auto":
|
|
2240
2300
|
case "discovery":
|
|
@@ -2243,7 +2303,7 @@ function getModeTools(agentMode, connection, config, context) {
|
|
|
2243
2303
|
includePackTools: !!context?.isParentTask
|
|
2244
2304
|
});
|
|
2245
2305
|
default:
|
|
2246
|
-
return config.mode === "pm" ? buildPmTools(connection, context?.storyPoints, { includePackTools: false }) :
|
|
2306
|
+
return config.mode === "pm" ? buildPmTools(connection, context?.storyPoints, { includePackTools: false }) : [];
|
|
2247
2307
|
}
|
|
2248
2308
|
}
|
|
2249
2309
|
function createConveyorMcpServer(connection, config, context, agentMode) {
|
|
@@ -2696,16 +2756,15 @@ async function runWithRetry(initialQuery, context, host, options) {
|
|
|
2696
2756
|
if (host.isStopped()) return;
|
|
2697
2757
|
const agentQuery = attempt === 0 ? initialQuery : buildRetryQuery(host, context, options, lastErrorWasImage);
|
|
2698
2758
|
try {
|
|
2699
|
-
const { retriable, resultSummary, modeRestart, rateLimitResetsAt } = await processEvents(
|
|
2700
|
-
agentQuery,
|
|
2701
|
-
context,
|
|
2702
|
-
host
|
|
2703
|
-
);
|
|
2759
|
+
const { retriable, resultSummary, modeRestart, rateLimitResetsAt, staleSession } = await processEvents(agentQuery, context, host);
|
|
2704
2760
|
if (modeRestart || host.isStopped()) return;
|
|
2705
2761
|
if (rateLimitResetsAt) {
|
|
2706
2762
|
handleRateLimitPause(host, rateLimitResetsAt);
|
|
2707
2763
|
return;
|
|
2708
2764
|
}
|
|
2765
|
+
if (staleSession && context.claudeSessionId) {
|
|
2766
|
+
return handleStaleSession(context, host, options);
|
|
2767
|
+
}
|
|
2709
2768
|
if (!retriable) return;
|
|
2710
2769
|
lastErrorWasImage = IMAGE_ERROR_PATTERN2.test(resultSummary ?? "");
|
|
2711
2770
|
} catch (error) {
|
|
@@ -2859,7 +2918,6 @@ function pushSetupLog(setupLog, line) {
|
|
|
2859
2918
|
}
|
|
2860
2919
|
}
|
|
2861
2920
|
async function executeSetupConfig(config, runnerConfig, connection, setupLog) {
|
|
2862
|
-
let deferredStartConfig = null;
|
|
2863
2921
|
if (config.setupCommand) {
|
|
2864
2922
|
pushSetupLog(setupLog, `$ ${config.setupCommand}`);
|
|
2865
2923
|
await runSetupCommand(config.setupCommand, runnerConfig.workspaceDir, (stream, data) => {
|
|
@@ -2876,7 +2934,6 @@ async function executeSetupConfig(config, runnerConfig, connection, setupLog) {
|
|
|
2876
2934
|
connection.sendEvent({ type: "start_command_output", stream, data });
|
|
2877
2935
|
});
|
|
2878
2936
|
}
|
|
2879
|
-
return deferredStartConfig;
|
|
2880
2937
|
}
|
|
2881
2938
|
async function checkoutTaskBranch(runnerConfig, connection, callbacks, setupLog) {
|
|
2882
2939
|
const taskBranch = process.env.CONVEYOR_TASK_BRANCH;
|
|
@@ -2923,62 +2980,23 @@ async function runSetupSafe(runnerConfig, connection, callbacks, setupLog, _effe
|
|
|
2923
2980
|
);
|
|
2924
2981
|
}
|
|
2925
2982
|
if (!await checkoutTaskBranch(runnerConfig, connection, callbacks, setupLog)) {
|
|
2926
|
-
return { ok: false,
|
|
2927
|
-
}
|
|
2928
|
-
const taskBranch = process.env.CONVEYOR_TASK_BRANCH;
|
|
2929
|
-
if (taskBranch) {
|
|
2930
|
-
pushSetupLog(setupLog, `[conveyor] Switching to task branch ${taskBranch}...`);
|
|
2931
|
-
connection.sendEvent({
|
|
2932
|
-
type: "setup_output",
|
|
2933
|
-
stream: "stdout",
|
|
2934
|
-
data: `Switching to task branch ${taskBranch}...
|
|
2935
|
-
`
|
|
2936
|
-
});
|
|
2937
|
-
try {
|
|
2938
|
-
await runSetupCommand(
|
|
2939
|
-
`git fetch origin ${taskBranch} && git checkout ${taskBranch}`,
|
|
2940
|
-
runnerConfig.workspaceDir,
|
|
2941
|
-
(stream, data) => {
|
|
2942
|
-
connection.sendEvent({ type: "setup_output", stream, data });
|
|
2943
|
-
for (const line of data.split("\n").filter(Boolean)) {
|
|
2944
|
-
pushSetupLog(setupLog, `[${stream}] ${line}`);
|
|
2945
|
-
}
|
|
2946
|
-
}
|
|
2947
|
-
);
|
|
2948
|
-
pushSetupLog(setupLog, `[conveyor] Switched to ${taskBranch}`);
|
|
2949
|
-
} catch (error) {
|
|
2950
|
-
const message = `Failed to checkout ${taskBranch}: ${error instanceof Error ? error.message : "unknown error"}`;
|
|
2951
|
-
connection.sendEvent({ type: "setup_error", message });
|
|
2952
|
-
await callbacks.onEvent({ type: "setup_error", message });
|
|
2953
|
-
connection.postChatMessage(
|
|
2954
|
-
`Failed to switch to task branch \`${taskBranch}\`.
|
|
2955
|
-
|
|
2956
|
-
${message}`
|
|
2957
|
-
);
|
|
2958
|
-
return { ok: false, deferredStartConfig: null };
|
|
2959
|
-
}
|
|
2983
|
+
return { ok: false, conveyorConfig: null };
|
|
2960
2984
|
}
|
|
2961
2985
|
const config = await loadConveyorConfig(runnerConfig.workspaceDir);
|
|
2962
2986
|
if (!config) {
|
|
2963
2987
|
connection.sendEvent({ type: "setup_complete" });
|
|
2964
2988
|
await callbacks.onEvent({ type: "setup_complete" });
|
|
2965
|
-
return { ok: true,
|
|
2989
|
+
return { ok: true, conveyorConfig: null };
|
|
2966
2990
|
}
|
|
2967
2991
|
try {
|
|
2968
|
-
|
|
2969
|
-
config,
|
|
2970
|
-
runnerConfig,
|
|
2971
|
-
connection,
|
|
2972
|
-
setupLog
|
|
2973
|
-
);
|
|
2992
|
+
await executeSetupConfig(config, runnerConfig, connection, setupLog);
|
|
2974
2993
|
const setupEvent = {
|
|
2975
2994
|
type: "setup_complete",
|
|
2976
|
-
previewPort: config.previewPort ?? void 0
|
|
2977
|
-
startCommandDeferred: deferredStartConfig === null ? void 0 : true
|
|
2995
|
+
previewPort: config.previewPort ?? void 0
|
|
2978
2996
|
};
|
|
2979
2997
|
connection.sendEvent(setupEvent);
|
|
2980
2998
|
await callbacks.onEvent(setupEvent);
|
|
2981
|
-
return { ok: true,
|
|
2999
|
+
return { ok: true, conveyorConfig: config };
|
|
2982
3000
|
} catch (error) {
|
|
2983
3001
|
const message = error instanceof Error ? error.message : "Setup failed";
|
|
2984
3002
|
connection.sendEvent({ type: "setup_error", message });
|
|
@@ -2987,7 +3005,7 @@ ${message}`
|
|
|
2987
3005
|
`Environment setup failed: ${message}
|
|
2988
3006
|
The agent cannot start until this is resolved.`
|
|
2989
3007
|
);
|
|
2990
|
-
return { ok: false,
|
|
3008
|
+
return { ok: false, conveyorConfig: null };
|
|
2991
3009
|
}
|
|
2992
3010
|
}
|
|
2993
3011
|
function runAuthTokenSafe(config, connection, taskContext) {
|
|
@@ -3001,16 +3019,16 @@ function runAuthTokenSafe(config, connection, taskContext) {
|
|
|
3001
3019
|
} catch {
|
|
3002
3020
|
}
|
|
3003
3021
|
}
|
|
3004
|
-
function
|
|
3005
|
-
if (!
|
|
3006
|
-
pushSetupLog(setupLog, `$ ${
|
|
3022
|
+
function rerunStartCommand(conveyorConfig, runnerConfig, connection, setupLog) {
|
|
3023
|
+
if (!conveyorConfig.startCommand) return;
|
|
3024
|
+
pushSetupLog(setupLog, `$ ${conveyorConfig.startCommand} & (background, re-trigger)`);
|
|
3007
3025
|
connection.sendEvent({ type: "start_command_started" });
|
|
3008
|
-
runStartCommand(
|
|
3026
|
+
runStartCommand(conveyorConfig.startCommand, runnerConfig.workspaceDir, (stream, data) => {
|
|
3009
3027
|
connection.sendEvent({ type: "start_command_output", stream, data });
|
|
3010
3028
|
});
|
|
3011
3029
|
const setupEvent = {
|
|
3012
3030
|
type: "setup_complete",
|
|
3013
|
-
previewPort:
|
|
3031
|
+
previewPort: conveyorConfig.previewPort ?? void 0
|
|
3014
3032
|
};
|
|
3015
3033
|
connection.sendEvent(setupEvent);
|
|
3016
3034
|
}
|
|
@@ -3153,7 +3171,7 @@ var AgentRunner = class {
|
|
|
3153
3171
|
prNudgeCount = 0;
|
|
3154
3172
|
idleTimer = null;
|
|
3155
3173
|
idleCheckInterval = null;
|
|
3156
|
-
|
|
3174
|
+
conveyorConfig = null;
|
|
3157
3175
|
_queryHost = null;
|
|
3158
3176
|
constructor(config, callbacks) {
|
|
3159
3177
|
this.config = config;
|
|
@@ -3225,7 +3243,7 @@ var AgentRunner = class {
|
|
|
3225
3243
|
this.connection.disconnect();
|
|
3226
3244
|
return;
|
|
3227
3245
|
}
|
|
3228
|
-
this.
|
|
3246
|
+
this.conveyorConfig = result.conveyorConfig;
|
|
3229
3247
|
}
|
|
3230
3248
|
this.tryInitWorktree();
|
|
3231
3249
|
if (!await this.fetchAndInitContext()) return;
|
|
@@ -3295,47 +3313,38 @@ var AgentRunner = class {
|
|
|
3295
3313
|
} catch {
|
|
3296
3314
|
}
|
|
3297
3315
|
}
|
|
3298
|
-
|
|
3316
|
+
needsPRNudge() {
|
|
3299
3317
|
if (!this.config.isAuto || this.stopped) return false;
|
|
3300
3318
|
const maxNudges = this.taskContext?.agentSettings?.maxPrNudges ?? this.config.agentSettings?.maxPrNudges ?? 3;
|
|
3301
3319
|
if (this.prNudgeCount >= maxNudges) return false;
|
|
3320
|
+
const status = this.taskContext?.status;
|
|
3321
|
+
return status === "InProgress" && !this.taskContext?.githubPRUrl;
|
|
3322
|
+
}
|
|
3323
|
+
async maybeSendPRNudge() {
|
|
3302
3324
|
const fresh = await this.connection.fetchTaskContext().catch(() => null);
|
|
3303
3325
|
if (fresh) this.taskContext = fresh;
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
this.stop();
|
|
3315
|
-
return true;
|
|
3316
|
-
}
|
|
3317
|
-
if (this.prNudgeCount === 1) {
|
|
3318
|
-
this.connection.postChatMessage(
|
|
3319
|
-
"Auto-nudge: Task is still In Progress with no PR. Prompting agent to continue..."
|
|
3320
|
-
);
|
|
3321
|
-
await this.setState("running");
|
|
3322
|
-
await this.runQuerySafe(
|
|
3323
|
-
ctx,
|
|
3324
|
-
"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."
|
|
3325
|
-
);
|
|
3326
|
-
} else {
|
|
3327
|
-
this.connection.postChatMessage(
|
|
3328
|
-
`Auto-nudge (attempt ${this.prNudgeCount}/${maxNudges}): Task still has no PR. Prompting agent again...`
|
|
3329
|
-
);
|
|
3330
|
-
await this.setState("running");
|
|
3331
|
-
await this.runQuerySafe(
|
|
3332
|
-
ctx,
|
|
3333
|
-
`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.`
|
|
3334
|
-
);
|
|
3335
|
-
}
|
|
3326
|
+
if (!this.needsPRNudge()) return false;
|
|
3327
|
+
this.prNudgeCount++;
|
|
3328
|
+
const ctx = this.taskContext ?? fresh;
|
|
3329
|
+
if (!ctx) return false;
|
|
3330
|
+
const maxNudges = this.taskContext?.agentSettings?.maxPrNudges ?? this.config.agentSettings?.maxPrNudges ?? 3;
|
|
3331
|
+
if (this.prNudgeCount >= maxNudges) {
|
|
3332
|
+
this.connection.postChatMessage(
|
|
3333
|
+
`Auto-mode agent failed to open a PR after ${maxNudges} nudges. Shutting down.`
|
|
3334
|
+
);
|
|
3335
|
+
this.stop();
|
|
3336
3336
|
return true;
|
|
3337
3337
|
}
|
|
3338
|
-
|
|
3338
|
+
await this.sendPRNudgeQuery(ctx, maxNudges);
|
|
3339
|
+
return true;
|
|
3340
|
+
}
|
|
3341
|
+
async sendPRNudgeQuery(ctx, maxNudges) {
|
|
3342
|
+
const isFirst = this.prNudgeCount === 1;
|
|
3343
|
+
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...`;
|
|
3344
|
+
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.`;
|
|
3345
|
+
this.connection.postChatMessage(chatMsg);
|
|
3346
|
+
await this.setState("running");
|
|
3347
|
+
await this.runQuerySafe(ctx, prompt);
|
|
3339
3348
|
}
|
|
3340
3349
|
async executeInitialMode() {
|
|
3341
3350
|
if (!this.taskContext) return;
|
|
@@ -3418,15 +3427,9 @@ var AgentRunner = class {
|
|
|
3418
3427
|
}
|
|
3419
3428
|
}
|
|
3420
3429
|
handleRunStartCommand() {
|
|
3421
|
-
if (!this.
|
|
3430
|
+
if (!this.conveyorConfig?.startCommand || this.startCommandStarted) return;
|
|
3422
3431
|
this.startCommandStarted = true;
|
|
3423
|
-
|
|
3424
|
-
this.deferredStartConfig,
|
|
3425
|
-
this.config,
|
|
3426
|
-
this.connection,
|
|
3427
|
-
this.setupLog
|
|
3428
|
-
);
|
|
3429
|
-
this.deferredStartConfig = null;
|
|
3432
|
+
rerunStartCommand(this.conveyorConfig, this.config, this.connection, this.setupLog);
|
|
3430
3433
|
}
|
|
3431
3434
|
logEffectiveSettings() {
|
|
3432
3435
|
if (!this.taskContext) return;
|
|
@@ -3459,6 +3462,9 @@ var AgentRunner = class {
|
|
|
3459
3462
|
resolve2(msg);
|
|
3460
3463
|
} else {
|
|
3461
3464
|
this.pendingMessages.push(msg);
|
|
3465
|
+
if (this._queryHost?.activeQuery) {
|
|
3466
|
+
this.softStop();
|
|
3467
|
+
}
|
|
3462
3468
|
}
|
|
3463
3469
|
}
|
|
3464
3470
|
waitForMessage() {
|
|
@@ -3838,7 +3844,7 @@ var ProjectRunner = class {
|
|
|
3838
3844
|
projectId: config.projectId
|
|
3839
3845
|
});
|
|
3840
3846
|
}
|
|
3841
|
-
|
|
3847
|
+
checkoutWorkspaceBranch() {
|
|
3842
3848
|
const workspaceBranch = process.env.CONVEYOR_WORKSPACE_BRANCH;
|
|
3843
3849
|
if (!workspaceBranch) return;
|
|
3844
3850
|
try {
|
|
@@ -3853,7 +3859,7 @@ var ProjectRunner = class {
|
|
|
3853
3859
|
}
|
|
3854
3860
|
}
|
|
3855
3861
|
async start() {
|
|
3856
|
-
|
|
3862
|
+
this.checkoutWorkspaceBranch();
|
|
3857
3863
|
await this.connection.connect();
|
|
3858
3864
|
this.connection.onTaskAssignment((assignment) => {
|
|
3859
3865
|
this.handleAssignment(assignment);
|
|
@@ -4068,4 +4074,4 @@ export {
|
|
|
4068
4074
|
ProjectRunner,
|
|
4069
4075
|
FileCache
|
|
4070
4076
|
};
|
|
4071
|
-
//# sourceMappingURL=chunk-
|
|
4077
|
+
//# sourceMappingURL=chunk-DJJBHD4H.js.map
|