Skip to content

Commit c39c5cc

Browse files
fix(agents): sanitize tool names in system context and deduplicate on merge
1 parent 29cf1c5 commit c39c5cc

4 files changed

Lines changed: 17 additions & 5 deletions

File tree

src/agents/command/attempt-execution.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,4 +266,12 @@ describe("buildPartialExecutionSystemContext", () => {
266266
});
267267
expect(ctx).toBeUndefined();
268268
});
269+
270+
it("returns undefined when all tool names sanitize to empty", () => {
271+
const ctx = buildPartialExecutionSystemContext({
272+
toolNames: ["!!!", "<<<>>>"],
273+
didSendViaMessagingTool: false,
274+
});
275+
expect(ctx).toBeUndefined();
276+
});
269277
});

src/agents/command/attempt-execution.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -343,10 +343,11 @@ export function resolveRetryImages(params: {
343343
export function buildPartialExecutionSystemContext(
344344
partialExecution: PartialExecution,
345345
): string | undefined {
346-
if (partialExecution.toolNames.length === 0) {
346+
const safeNames = FailoverError.sanitizeToolNames(partialExecution.toolNames);
347+
if (safeNames.length === 0) {
347348
return undefined;
348349
}
349-
const toolList = partialExecution.toolNames.join(", ");
350+
const toolList = safeNames.join(", ");
350351
const messagingWarning = partialExecution.didSendViaMessagingTool
351352
? " At least one of these tools sent a user-visible message — do not resend it."
352353
: "";

src/agents/model-fallback.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1631,14 +1631,15 @@ describe("runWithModelFallback", () => {
16311631
throw new FailoverError("rate_limit", {
16321632
reason: "rate_limit",
16331633
partialExecution: {
1634-
toolNames: ["web_search"],
1634+
toolNames: ["bash", "web_search"],
16351635
didSendViaMessagingTool: true,
16361636
},
16371637
});
16381638
}
16391639
return "ok";
16401640
},
16411641
});
1642+
// bash appears in both attempts; Set dedup should keep it only once
16421643
expect(captured[2]?.previousPartialExecution).toEqual({
16431644
toolNames: ["bash", "web_search"],
16441645
didSendViaMessagingTool: true,

src/agents/model-fallback.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -819,8 +819,10 @@ export async function runWithModelFallback<T>(params: {
819819
mergedPartialExecution = mergedPartialExecution
820820
? {
821821
toolNames: [
822-
...mergedPartialExecution.toolNames,
823-
...described.partialExecution.toolNames,
822+
...new Set([
823+
...mergedPartialExecution.toolNames,
824+
...described.partialExecution.toolNames,
825+
]),
824826
],
825827
didSendViaMessagingTool:
826828
mergedPartialExecution.didSendViaMessagingTool ||

0 commit comments

Comments
 (0)