mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-08-31 02:06:21 +00:00
fix(core): give complete intentional-sleep guidance on first rejection for sleep chains (#4948)
When the model tries `sleep 5 && cmd`, the old error message said 'split follow-up commands into a separate invocation' but omitted the `# intentional-sleep: <reason>` syntax. The model would then try standalone `sleep 5`, get blocked a second time, and only then learn the escape hatch. Now the first rejection for non-standalone sleep tells the model both steps: split into two calls and use the intentional-sleep comment. This reduces failures from 2 to 1. Also reuses the already-computed `strippedCommand` variable instead of calling `stripShellWrapper` a second time.
This commit is contained in:
parent
d7327df399
commit
be62f0e93d
2 changed files with 6 additions and 9 deletions
|
|
@ -195,16 +195,15 @@ describe('ShellTool', () => {
|
|||
expect(error).toBeNull();
|
||||
});
|
||||
|
||||
it('should not suggest the intentional sleep comment for sleep chains', async () => {
|
||||
it('should guide model to split and use intentional-sleep for sleep chains', async () => {
|
||||
const error = shellTool.validateToolParams({
|
||||
command: 'sleep 5 && echo ok',
|
||||
is_background: false,
|
||||
});
|
||||
|
||||
expect(error).toContain(
|
||||
'intentional-sleep escape hatch only applies to standalone sleep commands',
|
||||
);
|
||||
expect(error).not.toContain('# intentional-sleep:');
|
||||
expect(error).toContain('Split into two calls');
|
||||
expect(error).toContain('intentional-sleep:');
|
||||
expect(error).toContain('reason');
|
||||
});
|
||||
|
||||
it('should throw an error for a relative directory path', async () => {
|
||||
|
|
|
|||
|
|
@ -4361,16 +4361,14 @@ export class ShellTool extends BaseDeclarativeTool<
|
|||
// `-c` script. This matches every other sensitive check in this file
|
||||
// (directory, read-only, command-root extraction, etc.).
|
||||
if (!params.is_background) {
|
||||
const sleepPattern = detectBlockedSleepPatternDetails(
|
||||
stripShellWrapper(params.command),
|
||||
);
|
||||
const sleepPattern = detectBlockedSleepPatternDetails(strippedCommand);
|
||||
if (sleepPattern !== null) {
|
||||
const intentionalSleepGuidance =
|
||||
sleepPattern.intentionalSleepRejection ??
|
||||
(sleepPattern.isStandalone
|
||||
? 'If you genuinely need a standalone delay (rate limiting, deliberate pacing), ' +
|
||||
'add a trailing comment like `# intentional-sleep: wait for MCP rate limit reset` (up to 10 minutes).'
|
||||
: 'The intentional-sleep escape hatch only applies to standalone sleep commands; split follow-up commands into a separate invocation.');
|
||||
: 'Split into two calls: first `sleep N # intentional-sleep: <reason>` (standalone), then the follow-up command.');
|
||||
return (
|
||||
`Blocked: ${sleepPattern.description}. ` +
|
||||
'Run blocking commands in the background with is_background: true. ' +
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue