diff --git a/.github/actions/publish-release/action.yml b/.github/actions/publish-release/action.yml index 2eab2072805..f13867ab611 100644 --- a/.github/actions/publish-release/action.yml +++ b/.github/actions/publish-release/action.yml @@ -167,6 +167,7 @@ runs: shell: 'bash' run: | npm publish \ + --ignore-scripts \ --dry-run="${INPUTS_DRY_RUN}" \ --workspace="${INPUTS_CORE_PACKAGE_NAME}" \ --tag staging-tmp @@ -215,6 +216,7 @@ runs: shell: 'bash' run: | npm publish \ + --ignore-scripts \ --dry-run="${INPUTS_DRY_RUN}" \ --workspace="${INPUTS_CLI_PACKAGE_NAME}" \ --tag staging-tmp @@ -242,6 +244,7 @@ runs: # Tag staging for initial release run: | npm publish \ + --ignore-scripts \ --dry-run="${INPUTS_DRY_RUN}" \ --workspace="${INPUTS_A2A_PACKAGE_NAME}" \ --tag staging-tmp diff --git a/integration-tests/parallel-tools.responses b/integration-tests/parallel-tools.responses index d7beedc8b25..41c3780991f 100644 --- a/integration-tests/parallel-tools.responses +++ b/integration-tests/parallel-tools.responses @@ -1 +1,3 @@ +{"method":"generateContent","response":{"candidates":[{"content":{"parts":[{"text":"{\n \"reasoning\": \"Simple task.\",\n \"model_choice\": \"flash\"\n}"}]},"finishReason":"STOP","index":0}]}} {"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"functionCall":{"name":"read_file","args":{"file_path":"file1.txt"}}},{"functionCall":{"name":"read_file","args":{"file_path":"file2.txt"}}},{"functionCall":{"name":"write_file","args":{"file_path":"output.txt","content":"wave2"}}},{"functionCall":{"name":"read_file","args":{"file_path":"file3.txt"}}},{"functionCall":{"name":"read_file","args":{"file_path":"file4.txt"}}}, {"text":"All waves completed successfully."}]},"finishReason":"STOP","index":0}]}]} +{"method":"generateContent","response":{"candidates":[{"content":{"parts":[{"text":"All waves completed successfully."}]},"finishReason":"STOP","index":0}]}} \ No newline at end of file diff --git a/integration-tests/parallel-tools.test.ts b/integration-tests/parallel-tools.test.ts index 760f98cd7ab..9cd6068db35 100644 --- a/integration-tests/parallel-tools.test.ts +++ b/integration-tests/parallel-tools.test.ts @@ -23,6 +23,7 @@ describe('Parallel Tool Execution Integration', () => { it('should execute [read, read, write, read, read] in correct waves with user approval', async () => { rig.setup('parallel-wave-execution', { fakeResponsesPath: join(import.meta.dirname, 'parallel-tools.responses'), + fakeResponsesNonStrict: true, settings: { tools: { core: ['read_file', 'write_file'], @@ -40,19 +41,24 @@ describe('Parallel Tool Execution Integration', () => { const run = await rig.runInteractive({ approvalMode: 'default' }); - // 1. Trigger the wave - await run.type('ok'); - await run.type('\r'); + try { + // 1. Trigger the wave + await run.type('ok'); + await run.type('\r'); - // 3. Wait for the write_file prompt. - await run.expectText('Allow', 5000); + // 3. Wait for the write_file prompt. + await run.expectText('Allow', 10000); - // 4. Press Enter to approve the write_file. - await run.type('y'); - await run.type('\r'); + // 4. Press Enter to approve the write_file. + await run.type('y'); + await run.type('\r'); - // 5. Wait for the final model response - await run.expectText('All waves completed successfully.', 5000); + // 5. Wait for the final model response + await run.expectText('All waves completed successfully.', 10000); + } catch (err) { + fs.writeFileSync('pty_output_failure.txt', run.output); + throw err; + } // Verify all tool calls were made and succeeded in the logs await rig.expectToolCallSuccess(['write_file']); @@ -73,5 +79,5 @@ describe('Parallel Tool Execution Integration', () => { expect(fs.readFileSync(join(rig.testDir!, 'output.txt'), 'utf8')).toBe( 'wave2', ); - }); + }, 30000); }); diff --git a/packages/core/src/scheduler/scheduler.ts b/packages/core/src/scheduler/scheduler.ts index 5a4f9869514..76529c14d36 100644 --- a/packages/core/src/scheduler/scheduler.ts +++ b/packages/core/src/scheduler/scheduler.ts @@ -540,7 +540,7 @@ export class Scheduler { if (isWaitingForExternal && this.state.isActive) { // Yield to the event loop to allow external events (tool completion, user input) to progress. - await new Promise((resolve) => queueMicrotask(() => resolve(true))); + await new Promise((resolve) => setTimeout(resolve, 10)); return true; } diff --git a/packages/test-utils/src/test-rig.ts b/packages/test-utils/src/test-rig.ts index 10a0ffd569c..7c8ec5fc38e 100644 --- a/packages/test-utils/src/test-rig.ts +++ b/packages/test-utils/src/test-rig.ts @@ -365,6 +365,8 @@ export class TestRig { _lastRunStderr?: string; // Path to the copied fake responses file for this test. fakeResponsesPath?: string; + // Whether to run fake responses in non-strict mode. + fakeResponsesNonStrict?: boolean; // Original fake responses file path for rewriting goldens in record mode. originalFakeResponsesPath?: string; private _interactiveRuns: InteractiveRun[] = []; @@ -377,6 +379,7 @@ export class TestRig { settings?: Record; state?: Record; fakeResponsesPath?: string; + fakeResponsesNonStrict?: boolean; } = {}, ) { this.testName = testName; @@ -398,6 +401,7 @@ export class TestRig { if (options.fakeResponsesPath) { this.fakeResponsesPath = join(this.testDir, 'fake-responses.json'); this.originalFakeResponsesPath = options.fakeResponsesPath; + this.fakeResponsesNonStrict = options.fakeResponsesNonStrict; if (process.env['REGENERATE_MODEL_GOLDENS'] !== 'true') { fs.copyFileSync(options.fakeResponsesPath, this.fakeResponsesPath); } @@ -558,6 +562,8 @@ export class TestRig { if (this.fakeResponsesPath) { if (process.env['REGENERATE_MODEL_GOLDENS'] === 'true') { initialArgs.push('--record-responses', this.fakeResponsesPath); + } else if (this.fakeResponsesNonStrict) { + initialArgs.push('--fake-responses-non-strict', this.fakeResponsesPath); } else { initialArgs.push('--fake-responses', this.fakeResponsesPath); }