Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions integration-tests/sdk-typescript/test-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -830,6 +830,30 @@ export function assertToolCalled(
}
}

/**
* Assert that a specific tool was called and all its results succeeded
*/
export function assertToolSucceeded(
messages: SDKMessage[],
toolName: string,
): void {
const results = findToolResults(messages, toolName);

if (results.length === 0) {
throw new Error(
`Expected tool '${toolName}' to have at least one result, but found none`,
);
}

for (const result of results) {
if (result.isError) {
throw new Error(
`Expected tool '${toolName}' to succeed, but got error: ${result.content}`,
);
}
}
}

/**
* Assert that the conversation completed successfully
*/
Expand Down
31 changes: 14 additions & 17 deletions integration-tests/sdk-typescript/tool-control.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,13 @@ import {
findToolCalls,
findToolResults,
assertSuccessfulCompletion,
assertToolSucceeded,
createSharedTestOptions,
createResultWaiter,
} from './test-helper.js';

const SHARED_TEST_OPTIONS = createSharedTestOptions();
const TEST_TIMEOUT = 60000;
const TEST_TIMEOUT = process.env['CI'] ? 120_000 : 60_000;
Comment thread
qwen-code-dev-bot marked this conversation as resolved.
const SANDBOX_MODE = process.env['QWEN_SANDBOX']?.toLowerCase().trim();
const IS_CONTAINER_SANDBOX =
SANDBOX_MODE === 'docker' || SANDBOX_MODE === 'podman';
Expand Down Expand Up @@ -89,10 +90,9 @@ describe('Tool Control Parameters (E2E)', () => {
// Should NOT have list_directory since it's not in coreTools
expect(toolNames).not.toContain('list_directory');

// Verify file was actually modified (content changed from original).
// Don't assert on specific wording — the model may paraphrase.
const content = await helper.readFile('test.txt');
expect(content).not.toBe('original content');
// Verify write_file executed successfully (tool-control check,
// not model-content check — the model may echo back the original).
assertToolSucceeded(messages, 'write_file');
} finally {
await q.close();
}
Expand Down Expand Up @@ -584,10 +584,9 @@ describe('Tool Control Parameters (E2E)', () => {
// canUseTool should NOT have been called (tools are in allowedTools)
expect(canUseToolCalled).toBe(false);

// Verify file was actually modified (content changed from original).
// Don't assert on specific wording — the model may paraphrase.
const content = await helper.readFile('test.txt');
expect(content).not.toBe('original');
// Verify write_file executed successfully (tool-control check,
// not model-content check — the model may echo back the original).
assertToolSucceeded(messages, 'write_file');
} finally {
await q.close();
}
Expand Down Expand Up @@ -881,10 +880,9 @@ describe('Tool Control Parameters (E2E)', () => {
// Should NOT use tools outside coreTools
expect(toolNames).not.toContain('run_shell_command');

// Verify file was actually modified (content changed from original).
// Don't assert on specific wording — the model may paraphrase.
const content = await helper.readFile('test.txt');
expect(content).not.toBe('test');
// Verify write_file executed successfully (tool-control check,
// not model-content check — the model may echo back the original).
assertToolSucceeded(messages, 'write_file');
} finally {
await q.close();
}
Expand Down Expand Up @@ -984,10 +982,9 @@ describe('Tool Control Parameters (E2E)', () => {
// canUseTool should be called for core write tools
expect(canUseToolCalls).toContain('write_file');

// Verify file was actually modified (content changed from original).
// Don't assert on specific wording — the model may paraphrase.
const content = await helper.readFile('test.txt');
expect(content).not.toBe('test');
// Verify write_file executed successfully (tool-control check,
// not model-content check — the model may echo back the original).
assertToolSucceeded(messages, 'write_file');
} finally {
await q.close();
}
Expand Down