Fix terminal tool incorrectly suggesting to send literal "any key" text (#270426)

This commit is contained in:
Copilot
2025-10-10 15:34:06 +00:00
committed by GitHub
parent bc7b093dd2
commit 09575e1f1b
@@ -393,7 +393,7 @@ export class OutputMonitor extends Disposable implements IOutputMonitor {
}
const lastFiveLines = execution.getOutput(this._lastPromptMarker).trimEnd().split('\n').slice(-5).join('\n');
const promptText =
`Analyze the following terminal output. If it contains a prompt requesting user input (such as a confirmation, selection, or yes/no question) and that prompt has NOT already been answered, extract the prompt text. The prompt may ask to choose from a set. If so, extract the possible options as a JSON object with keys 'prompt', 'options' (an array of strings or an object with option to description mappings), and 'freeFormInput': false. If no options are provided, and free form input is requested, for example: Password:, return the word freeFormInput. For example, if the options are "[Y] Yes [A] Yes to All [N] No [L] No to All [C] Cancel", the option to description mappings would be {"Y": "Yes", "A": "Yes to All", "N": "No", "L": "No to All", "C": "Cancel"}. If there is no such prompt, return null. If the option is ambiguous, like "any key", return null.
`Analyze the following terminal output. If it contains a prompt requesting user input (such as a confirmation, selection, or yes/no question) and that prompt has NOT already been answered, extract the prompt text. The prompt may ask to choose from a set. If so, extract the possible options as a JSON object with keys 'prompt', 'options' (an array of strings or an object with option to description mappings), and 'freeFormInput': false. If no options are provided, and free form input is requested, for example: Password:, return the word freeFormInput. For example, if the options are "[Y] Yes [A] Yes to All [N] No [L] No to All [C] Cancel", the option to description mappings would be {"Y": "Yes", "A": "Yes to All", "N": "No", "L": "No to All", "C": "Cancel"}. If there is no such prompt, return null. If the option is ambiguous or non-specific (like "any key" or "some key"), return null.
Examples:
1. Output: "Do you want to overwrite? (y/n)"
Response: {"prompt": "Do you want to overwrite?", "options": ["y", "n"], "freeFormInput": false}
@@ -413,6 +413,12 @@ export class OutputMonitor extends Disposable implements IOutputMonitor {
6. Output: "Continue [y/N]"
Response: {"prompt": "Continue", "options": ["y", "N"], "freeFormInput": false}
7. Output: "Press any key to close the terminal."
Response: null
8. Output: "Terminal will be reused by tasks, press any key to close it."
Response: null
Alternatively, the prompt may request free form input, for example:
1. Output: "Enter your username:"
Response: {"prompt": "Enter your username:", "freeFormInput": true, "options": []}
@@ -438,10 +444,25 @@ export class OutputMonitor extends Disposable implements IOutputMonitor {
if (this._lastPrompt === obj.prompt) {
return;
}
// Filter out non-specific options like "any key"
const NON_SPECIFIC_OPTIONS = new Set(['any key', 'some key', 'a key']);
const isNonSpecificOption = (option: string): boolean => {
const lowerOption = option.toLowerCase().trim();
return NON_SPECIFIC_OPTIONS.has(lowerOption);
};
if (Array.isArray(obj.options) && obj.options.every(isString)) {
return { prompt: obj.prompt, options: obj.options, detectedRequestForFreeFormInput: obj.freeFormInput };
const filteredOptions = obj.options.filter(opt => !isNonSpecificOption(opt));
if (filteredOptions.length === 0) {
return undefined;
}
return { prompt: obj.prompt, options: filteredOptions, detectedRequestForFreeFormInput: obj.freeFormInput };
} else if (isObject(obj.options) && Object.values(obj.options).every(isString)) {
return { prompt: obj.prompt, options: Object.keys(obj.options), descriptions: Object.values(obj.options), detectedRequestForFreeFormInput: obj.freeFormInput };
const keys = Object.keys(obj.options).filter(key => !isNonSpecificOption(key));
if (keys.length === 0) {
return undefined;
}
const descriptions = keys.map(key => (obj.options as Record<string, string>)[key]);
return { prompt: obj.prompt, options: keys, descriptions, detectedRequestForFreeFormInput: obj.freeFormInput };
}
}
}