fix(cli): resolve paste issue on Windows terminals. (#15932)

This commit is contained in:
Tommaso Sciortino
2026-01-05 14:46:23 -08:00
committed by GitHub
parent fd7b6bf40a
commit 8f0324d868
15 changed files with 224 additions and 115 deletions

View File

@@ -32,7 +32,7 @@ describe('Interactive Mode', () => {
await run.sendKeys(
'Write a 200 word story about a robot. The story MUST end with the text THE_END followed by a period.',
);
await run.sendKeys('\r');
await run.type('\r');
// Wait for the specific end marker.
await run.expectText('THE_END.', 30000);

View File

@@ -95,7 +95,10 @@ describe('extension reloading', () => {
// Poll for the updated list
await rig.pollCommand(
() => run.sendKeys('\u0015/mcp list\r'),
async () => {
await run.sendText('/mcp list');
await run.type('\r');
},
() => {
const output = stripAnsi(run.output);
return (
@@ -110,9 +113,9 @@ describe('extension reloading', () => {
// Update the extension, expect the list to update, and mcp servers as well.
await run.sendKeys('\u0015/extensions update test-extension');
await run.expectText('/extensions update test-extension');
await run.sendKeys('\r');
await run.type('\r');
await new Promise((resolve) => setTimeout(resolve, 500));
await run.sendKeys('\r');
await run.type('\r');
await run.expectText(
` * test-server (remote): http://localhost:${portB}/mcp`,
);
@@ -123,7 +126,10 @@ describe('extension reloading', () => {
// Poll for the updated extension version
await rig.pollCommand(
() => run.sendKeys('\u0015/extensions list\r'),
async () => {
await run.sendText('/extensions list');
await run.type('\r');
},
() =>
stripAnsi(run.output).includes(
'test-extension (v0.0.2) - active (updated)',
@@ -133,7 +139,10 @@ describe('extension reloading', () => {
// Poll for the updated mcp tool
await rig.pollCommand(
() => run.sendKeys('\u0015/mcp list\r'),
async () => {
await run.sendText('/mcp list');
await run.type('\r');
},
() => {
const output = stripAnsi(run.output);
return (
@@ -146,7 +155,7 @@ describe('extension reloading', () => {
);
await run.sendText('/quit');
await run.sendKeys('\r');
await run.type('\r');
// Clean things up.
await serverA.stop();

View File

@@ -37,7 +37,7 @@ describe('Interactive file system', () => {
// Step 1: Read the file
const readPrompt = `Read the version from ${fileName}`;
await run.type(readPrompt);
await run.sendKeys('\r');
await run.type('\r');
const readCall = await rig.waitForToolCall('read_file', 30000);
expect(readCall, 'Expected to find a read_file tool call').toBe(true);
@@ -45,7 +45,7 @@ describe('Interactive file system', () => {
// Step 2: Write the file
const writePrompt = `now change the version to 1.0.1 in the file`;
await run.type(writePrompt);
await run.sendKeys('\r');
await run.type('\r');
// Check tool calls made with right args
await rig.expectToolCallSuccess(

View File

@@ -1087,7 +1087,7 @@ console.log(JSON.stringify({
// Send a prompt to establish a session and trigger an API call
await run.sendKeys('Hello');
await run.sendKeys('\r');
await run.type('\r');
// Wait for response to ensure API call happened
await run.expectText('Hello', 15000);
@@ -1166,7 +1166,7 @@ console.log(JSON.stringify({
// Send an initial prompt to establish a session
await run.sendKeys('Say hello');
await run.sendKeys('\r');
await run.type('\r');
// Wait for the response
await run.expectText('Hello', 10000);
@@ -1176,14 +1176,14 @@ console.log(JSON.stringify({
const numClears = 3;
for (let i = 0; i < numClears; i++) {
await run.sendKeys('/clear');
await run.sendKeys('\r');
await run.type('\r');
// Wait a bit for clear to complete
await new Promise((resolve) => setTimeout(resolve, 2000));
// Send a prompt to establish an active session before next clear
await run.sendKeys('Say hello');
await run.sendKeys('\r');
await run.type('\r');
// Wait for response
await run.expectText('Hello', 10000);

View File

@@ -200,7 +200,7 @@ describe('mcp server with cyclic tool schema is detected', () => {
const run = await rig.runInteractive();
await run.type('/mcp list');
await run.sendKeys('\r');
await run.type('\r');
await run.expectText('tool_with_cyclic_schema');
});

View File

@@ -209,6 +209,12 @@ export class InteractiveRun {
async type(text: string) {
let typedSoFar = '';
for (const char of text) {
if (char === '\r') {
// wait >30ms before `enter` to avoid fast return conversion
// from bufferFastReturn() in KeypressContent.tsx
await new Promise((resolve) => setTimeout(resolve, 50));
}
this.ptyProcess.write(char);
typedSoFar += char;