mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-02-01 22:48:03 +00:00
Simplify method signature. (#15114)
This commit is contained in:
committed by
GitHub
parent
d236df5b21
commit
bb0c0d8ee3
@@ -82,7 +82,7 @@ describe('extension reloading', () => {
|
||||
writeFileSync(testServerPath, safeJsonStringify(extension, 2));
|
||||
|
||||
// Start the CLI.
|
||||
const run = await rig.runInteractive('--debug');
|
||||
const run = await rig.runInteractive({ args: '--debug' });
|
||||
await run.expectText('You have 1 extension with an update available');
|
||||
// See the outdated extension
|
||||
await run.sendText('/extensions list');
|
||||
|
||||
@@ -24,9 +24,9 @@ describe('file-system', () => {
|
||||
});
|
||||
rig.createFile('test.txt', 'hello world');
|
||||
|
||||
const result = await rig.run(
|
||||
`read the file test.txt and show me its contents`,
|
||||
);
|
||||
const result = await rig.run({
|
||||
args: `read the file test.txt and show me its contents`,
|
||||
});
|
||||
|
||||
const foundToolCall = await rig.waitForToolCall('read_file');
|
||||
|
||||
@@ -53,7 +53,9 @@ describe('file-system', () => {
|
||||
});
|
||||
rig.createFile('test.txt', '');
|
||||
|
||||
const result = await rig.run(`edit test.txt to have a hello world message`);
|
||||
const result = await rig.run({
|
||||
args: `edit test.txt to have a hello world message`,
|
||||
});
|
||||
|
||||
// Accept multiple valid tools for editing files
|
||||
const foundToolCall = await rig.waitForAnyToolCall([
|
||||
@@ -109,9 +111,9 @@ describe('file-system', () => {
|
||||
});
|
||||
const fileName = 'my test file.txt';
|
||||
|
||||
const result = await rig.run(
|
||||
`write "hello" to "${fileName}" and then stop. Do not perform any other actions.`,
|
||||
);
|
||||
const result = await rig.run({
|
||||
args: `write "hello" to "${fileName}" and then stop. Do not perform any other actions.`,
|
||||
});
|
||||
|
||||
const foundToolCall = await rig.waitForToolCall('write_file');
|
||||
if (!foundToolCall) {
|
||||
@@ -134,7 +136,7 @@ describe('file-system', () => {
|
||||
rig.createFile(fileName, '1.0.0');
|
||||
|
||||
const prompt = `Read the version from ${fileName} and write the next version 1.0.1 back to the file.`;
|
||||
const result = await rig.run(prompt);
|
||||
const result = await rig.run({ args: prompt });
|
||||
|
||||
await rig.waitForTelemetryReady();
|
||||
const toolLogs = rig.readToolLogs();
|
||||
@@ -169,9 +171,9 @@ describe('file-system', () => {
|
||||
const expectedContent = 'Hey there, \nnew line\nnew line';
|
||||
rig.createFile(fileName, fileContent);
|
||||
|
||||
const result = await rig.run(
|
||||
`rewrite the file ${fileName} to replace all instances of "test line" with "new line"`,
|
||||
);
|
||||
const result = await rig.run({
|
||||
args: `rewrite the file ${fileName} to replace all instances of "test line" with "new line"`,
|
||||
});
|
||||
|
||||
const validTools = ['write_file', 'edit'];
|
||||
const foundToolCall = await rig.waitForAnyToolCall(validTools);
|
||||
@@ -220,7 +222,9 @@ describe('file-system', () => {
|
||||
);
|
||||
const fileName = 'non_existent.txt';
|
||||
|
||||
const result = await rig.run(`In ${fileName}, replace "a" with "b"`);
|
||||
const result = await rig.run({
|
||||
args: `In ${fileName}, replace "a" with "b"`,
|
||||
});
|
||||
|
||||
await rig.waitForTelemetryReady();
|
||||
const toolLogs = rig.readToolLogs();
|
||||
|
||||
@@ -24,7 +24,7 @@ describe('web search tool', () => {
|
||||
|
||||
let result;
|
||||
try {
|
||||
result = await rig.run(`what is the weather in London`);
|
||||
result = await rig.run({ args: `what is the weather in London` });
|
||||
} catch (error) {
|
||||
// Network errors can occur in CI environments
|
||||
if (
|
||||
|
||||
@@ -55,8 +55,9 @@ describe('Hooks System Integration', () => {
|
||||
},
|
||||
);
|
||||
|
||||
const prompt = 'Create a file called test.txt with content "Hello World"';
|
||||
const result = await rig.run(prompt);
|
||||
const result = await rig.run({
|
||||
args: 'Create a file called test.txt with content "Hello World"',
|
||||
});
|
||||
|
||||
// The hook should block the write_file tool
|
||||
const toolLogs = rig.readToolLogs();
|
||||
@@ -107,9 +108,9 @@ describe('Hooks System Integration', () => {
|
||||
},
|
||||
);
|
||||
|
||||
const prompt =
|
||||
'Create a file called approved.txt with content "Approved content"';
|
||||
await rig.run(prompt);
|
||||
await rig.run({
|
||||
args: 'Create a file called approved.txt with content "Approved content"',
|
||||
});
|
||||
|
||||
// The hook should allow the write_file tool
|
||||
const foundWriteFile = await rig.waitForToolCall('write_file');
|
||||
@@ -158,9 +159,9 @@ describe('Hooks System Integration', () => {
|
||||
// Create a test file to read
|
||||
rig.createFile('test-file.txt', 'This is test content');
|
||||
|
||||
const prompt =
|
||||
'Read the contents of test-file.txt and tell me what it contains';
|
||||
await rig.run(prompt);
|
||||
await rig.run({
|
||||
args: 'Read the contents of test-file.txt and tell me what it contains',
|
||||
});
|
||||
|
||||
// Should find read_file tool call
|
||||
const foundReadFile = await rig.waitForToolCall('read_file');
|
||||
@@ -232,8 +233,7 @@ echo '{
|
||||
},
|
||||
});
|
||||
|
||||
const prompt = 'Tell me a story';
|
||||
const result = await rig.run(prompt);
|
||||
const result = await rig.run({ args: 'Tell me a story' });
|
||||
|
||||
// The hook should have replaced the request entirely
|
||||
// Verify that the model responded to the modified request, not the original
|
||||
@@ -316,8 +316,7 @@ echo '{
|
||||
},
|
||||
});
|
||||
|
||||
const prompt = 'What is 2 + 2?';
|
||||
const result = await rig.run(prompt);
|
||||
const result = await rig.run({ args: 'What is 2 + 2?' });
|
||||
|
||||
// The hook should have replaced the model response
|
||||
expect(result).toContain(
|
||||
@@ -374,9 +373,9 @@ echo '{
|
||||
// Create a test file
|
||||
rig.createFile('new_file_data.txt', 'test data');
|
||||
|
||||
const prompt =
|
||||
'Check the content of new_file_data.txt, after that run echo command to see the content';
|
||||
await rig.run(prompt);
|
||||
await rig.run({
|
||||
args: 'Check the content of new_file_data.txt, after that run echo command to see the content',
|
||||
});
|
||||
|
||||
// Should use read_file (allowed) but not run_shell_command (not in allowed list)
|
||||
const foundReadFile = await rig.waitForToolCall('read_file');
|
||||
@@ -440,8 +439,7 @@ echo '{
|
||||
},
|
||||
});
|
||||
|
||||
const prompt = 'Hello, how are you?';
|
||||
const result = await rig.run(prompt);
|
||||
const result = await rig.run({ args: 'Hello, how are you?' });
|
||||
|
||||
// The hook should have added security context, which should influence the response
|
||||
expect(result).toContain('security');
|
||||
@@ -585,8 +583,7 @@ echo '{
|
||||
},
|
||||
});
|
||||
|
||||
const prompt = 'Hello, please help me with a task';
|
||||
await rig.run(prompt);
|
||||
await rig.run({ args: 'Hello, please help me with a task' });
|
||||
|
||||
// Should generate hook telemetry
|
||||
const hookTelemetryFound = await rig.waitForTelemetryEvent('hook_call');
|
||||
@@ -663,8 +660,9 @@ fi`;
|
||||
},
|
||||
});
|
||||
|
||||
const prompt = 'Create a file called input-test.txt with content "test"';
|
||||
await rig.run(prompt);
|
||||
await rig.run({
|
||||
args: 'Create a file called input-test.txt with content "test"',
|
||||
});
|
||||
|
||||
// Hook should validate input format successfully
|
||||
const foundWriteFile = await rig.waitForToolCall('write_file');
|
||||
@@ -739,11 +737,12 @@ fi`;
|
||||
},
|
||||
});
|
||||
|
||||
const prompt =
|
||||
'Create a file called multi-event-test.txt with content ' +
|
||||
'"testing multiple events", and then please reply with ' +
|
||||
'everything I say just after this:"';
|
||||
const result = await rig.run(prompt);
|
||||
const result = await rig.run({
|
||||
args:
|
||||
'Create a file called multi-event-test.txt with content ' +
|
||||
'"testing multiple events", and then please reply with ' +
|
||||
'everything I say just after this:"',
|
||||
});
|
||||
|
||||
// Should execute write_file tool
|
||||
const foundWriteFile = await rig.waitForToolCall('write_file');
|
||||
@@ -834,9 +833,9 @@ fi`;
|
||||
},
|
||||
});
|
||||
|
||||
const prompt =
|
||||
'Create a file called error-test.txt with content "testing error handling"';
|
||||
await rig.run(prompt);
|
||||
await rig.run({
|
||||
args: 'Create a file called error-test.txt with content "testing error handling"',
|
||||
});
|
||||
|
||||
// Despite one hook failing, the working hook should still allow the operation
|
||||
const foundWriteFile = await rig.waitForToolCall('write_file');
|
||||
@@ -883,8 +882,7 @@ fi`;
|
||||
},
|
||||
});
|
||||
|
||||
const prompt = 'Create a file called telemetry-test.txt';
|
||||
await rig.run(prompt);
|
||||
await rig.run({ args: 'Create a file called telemetry-test.txt' });
|
||||
|
||||
// Should execute the tool
|
||||
const foundWriteFile = await rig.waitForToolCall('write_file');
|
||||
@@ -929,8 +927,7 @@ fi`;
|
||||
});
|
||||
|
||||
// Run a simple query - the SessionStart hook will fire during app initialization
|
||||
const prompt = 'Say hello';
|
||||
await rig.run(prompt);
|
||||
await rig.run({ args: 'Say hello' });
|
||||
|
||||
// Verify hook executed with correct parameters
|
||||
const hookLogs = rig.readHookLogs();
|
||||
@@ -1174,8 +1171,7 @@ fi`;
|
||||
});
|
||||
|
||||
// Run a simple query that will trigger automatic compression
|
||||
const prompt = 'Say hello in exactly 5 words';
|
||||
await rig.run(prompt);
|
||||
await rig.run({ args: 'Say hello in exactly 5 words' });
|
||||
|
||||
// Verify hook executed with correct parameters
|
||||
const hookLogs = rig.readHookLogs();
|
||||
@@ -1236,8 +1232,7 @@ fi`;
|
||||
});
|
||||
|
||||
// Run in non-interactive mode with a simple prompt
|
||||
const prompt = 'Hello';
|
||||
await rig.run(prompt);
|
||||
await rig.run({ args: 'Hello' });
|
||||
|
||||
// The process should exit gracefully, firing the SessionEnd hook
|
||||
// Wait for telemetry to be written to disk
|
||||
@@ -1344,9 +1339,9 @@ echo '{"decision": "block", "systemMessage": "Disabled hook should not execute",
|
||||
},
|
||||
});
|
||||
|
||||
const prompt =
|
||||
'Create a file called disabled-test.txt with content "test"';
|
||||
const result = await rig.run(prompt);
|
||||
const result = await rig.run({
|
||||
args: 'Create a file called disabled-test.txt with content "test"',
|
||||
});
|
||||
|
||||
// Tool should execute (enabled hook allows it)
|
||||
const foundWriteFile = await rig.waitForToolCall('write_file');
|
||||
@@ -1431,8 +1426,9 @@ echo '{"decision": "block", "systemMessage": "Disabled hook should not execute",
|
||||
);
|
||||
|
||||
// First run - only active hook should execute
|
||||
const prompt1 = 'Create a file called first-run.txt with "test1"';
|
||||
const result1 = await rig.run(prompt1);
|
||||
const result1 = await rig.run({
|
||||
args: 'Create a file called first-run.txt with "test1"',
|
||||
});
|
||||
|
||||
// Tool should execute (active hook allows it)
|
||||
const foundWriteFile1 = await rig.waitForToolCall('write_file');
|
||||
@@ -1455,8 +1451,9 @@ echo '{"decision": "block", "systemMessage": "Disabled hook should not execute",
|
||||
expect(disabledHookLog1).toBeUndefined();
|
||||
|
||||
// Second run - verify disabled hook stays disabled
|
||||
const prompt2 = 'Create a file called second-run.txt with "test2"';
|
||||
const result2 = await rig.run(prompt2);
|
||||
const result2 = await rig.run({
|
||||
args: 'Create a file called second-run.txt with "test2"',
|
||||
});
|
||||
|
||||
const foundWriteFile2 = await rig.waitForToolCall('write_file');
|
||||
expect(foundWriteFile2).toBeTruthy();
|
||||
|
||||
@@ -22,11 +22,9 @@ describe('JSON output', () => {
|
||||
});
|
||||
|
||||
it('should return a valid JSON with response and stats', async () => {
|
||||
const result = await rig.run(
|
||||
'What is the capital of France?',
|
||||
'--output-format',
|
||||
'json',
|
||||
);
|
||||
const result = await rig.run({
|
||||
args: ['What is the capital of France?', '--output-format', 'json'],
|
||||
});
|
||||
const parsed = JSON.parse(result);
|
||||
|
||||
expect(parsed).toHaveProperty('response');
|
||||
@@ -38,7 +36,9 @@ describe('JSON output', () => {
|
||||
});
|
||||
|
||||
it('should return a valid JSON with a session ID', async () => {
|
||||
const result = await rig.run('Hello', '--output-format', 'json');
|
||||
const result = await rig.run({
|
||||
args: ['Hello', '--output-format', 'json'],
|
||||
});
|
||||
const parsed = JSON.parse(result);
|
||||
|
||||
expect(parsed).toHaveProperty('session_id');
|
||||
@@ -58,7 +58,7 @@ describe('JSON output', () => {
|
||||
|
||||
let thrown: Error | undefined;
|
||||
try {
|
||||
await rig.run('Hello', '--output-format', 'json');
|
||||
await rig.run({ args: ['Hello', '--output-format', 'json'] });
|
||||
expect.fail('Expected process to exit with error');
|
||||
} catch (e) {
|
||||
thrown = e as Error;
|
||||
@@ -108,12 +108,14 @@ describe('JSON output', () => {
|
||||
'json-output.error.responses',
|
||||
),
|
||||
});
|
||||
const result = await rig.run(
|
||||
`Read the contents of ${rig.testDir}/path/to/nonexistent/file.txt and tell me what it says. ` +
|
||||
'On error, respond to the user with exactly the text "File not found".',
|
||||
'--output-format',
|
||||
'json',
|
||||
);
|
||||
const result = await rig.run({
|
||||
args: [
|
||||
`Read the contents of ${rig.testDir}/path/to/nonexistent/file.txt and tell me what it says. ` +
|
||||
'On error, respond to the user with exactly the text "File not found".',
|
||||
'--output-format',
|
||||
'json',
|
||||
],
|
||||
});
|
||||
|
||||
const parsed = JSON.parse(result);
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ describe('list_directory', () => {
|
||||
|
||||
const prompt = `Can you list the files in the current directory.`;
|
||||
|
||||
const result = await rig.run(prompt);
|
||||
const result = await rig.run({ args: prompt });
|
||||
|
||||
try {
|
||||
await rig.expectToolCallSuccess(['list_directory']);
|
||||
|
||||
@@ -23,12 +23,10 @@ describe('mixed input crash prevention', () => {
|
||||
const stdinContent = "say '1'.";
|
||||
|
||||
try {
|
||||
await rig.run(
|
||||
{ stdin: stdinContent },
|
||||
'--prompt-interactive',
|
||||
"say '2'.",
|
||||
"say '3'.",
|
||||
);
|
||||
await rig.run({
|
||||
args: ['--prompt-interactive', "say '2'.", "say '3'."],
|
||||
stdin: stdinContent,
|
||||
});
|
||||
throw new Error('Expected the command to fail, but it succeeded');
|
||||
} catch (error: unknown) {
|
||||
expect(error).toBeInstanceOf(Error);
|
||||
@@ -50,11 +48,10 @@ describe('mixed input crash prevention', () => {
|
||||
rig.setup('should provide clear error message for mixed input');
|
||||
|
||||
try {
|
||||
await rig.run(
|
||||
{ stdin: 'test input' },
|
||||
'--prompt-interactive',
|
||||
'test prompt',
|
||||
);
|
||||
await rig.run({
|
||||
args: ['--prompt-interactive', 'test prompt'],
|
||||
stdin: 'test input',
|
||||
});
|
||||
throw new Error('Expected the command to fail, but it succeeded');
|
||||
} catch (error: unknown) {
|
||||
expect(error).toBeInstanceOf(Error);
|
||||
|
||||
@@ -25,7 +25,7 @@ describe('read_many_files', () => {
|
||||
|
||||
const prompt = `Use the read_many_files tool to read the contents of file1.txt and file2.txt and then print the contents of each file.`;
|
||||
|
||||
const result = await rig.run(prompt);
|
||||
const result = await rig.run({ args: prompt });
|
||||
|
||||
// Check for either read_many_files or multiple read_file calls
|
||||
const allTools = rig.readToolLogs();
|
||||
|
||||
@@ -26,7 +26,9 @@ describe('replace', () => {
|
||||
|
||||
rig.createFile(fileName, originalContent);
|
||||
|
||||
await rig.run(`Replace 'foo' with 'bar' in the file 'file_to_replace.txt'`);
|
||||
await rig.run({
|
||||
args: `Replace 'foo' with 'bar' in the file 'file_to_replace.txt'`,
|
||||
});
|
||||
|
||||
const foundToolCall = await rig.waitForToolCall('replace');
|
||||
expect(foundToolCall, 'Expected to find a replace tool call').toBeTruthy();
|
||||
@@ -46,9 +48,9 @@ describe('replace', () => {
|
||||
|
||||
rig.createFile(fileName, originalContent);
|
||||
|
||||
await rig.run(
|
||||
"Open regex.yml and append ' # updated' after the line containing ^[sv]d[a-z]$ without breaking the $ character.",
|
||||
);
|
||||
await rig.run({
|
||||
args: "Open regex.yml and append ' # updated' after the line containing ^[sv]d[a-z]$ without breaking the $ character.",
|
||||
});
|
||||
|
||||
const foundToolCall = await rig.waitForToolCall('replace');
|
||||
expect(foundToolCall, 'Expected to find a replace tool call').toBeTruthy();
|
||||
@@ -68,7 +70,7 @@ describe('replace', () => {
|
||||
rig.createFile(fileName, originalContent);
|
||||
|
||||
const prompt = `In ${fileName}, replace "<INSERT_TEXT_HERE>" with:\n${newBlock}. Use unix style line endings.`;
|
||||
await rig.run(prompt);
|
||||
await rig.run({ args: prompt });
|
||||
|
||||
const foundToolCall = await rig.waitForToolCall('replace');
|
||||
expect(foundToolCall, 'Expected to find a replace tool call').toBeTruthy();
|
||||
@@ -87,9 +89,9 @@ describe('replace', () => {
|
||||
const expectedContent = 'Hello\nWorld';
|
||||
rig.createFile(fileName, originalContent);
|
||||
|
||||
await rig.run(
|
||||
`In ${fileName}, delete the entire block from "## DELETE THIS ##" to "## END DELETE ##" including the markers and the newline that follows it.`,
|
||||
);
|
||||
await rig.run({
|
||||
args: `In ${fileName}, delete the entire block from "## DELETE THIS ##" to "## END DELETE ##" including the markers and the newline that follows it.`,
|
||||
});
|
||||
|
||||
const foundToolCall = await rig.waitForToolCall('replace');
|
||||
expect(foundToolCall, 'Expected to find a replace tool call').toBeTruthy();
|
||||
|
||||
@@ -98,7 +98,7 @@ describe('run_shell_command', () => {
|
||||
|
||||
const prompt = `Please run the command "echo hello-world" and show me the output`;
|
||||
|
||||
const result = await rig.run(prompt);
|
||||
const result = await rig.run({ args: prompt });
|
||||
|
||||
const foundToolCall = await rig.waitForToolCall('run_shell_command');
|
||||
|
||||
@@ -161,13 +161,11 @@ describe('run_shell_command', () => {
|
||||
const prompt = `use ${command} to tell me how many lines there are in ${testFile}`;
|
||||
|
||||
// Provide the prompt via stdin to simulate non-interactive mode
|
||||
const result = await rig.run(
|
||||
{
|
||||
stdin: prompt,
|
||||
yolo: false,
|
||||
},
|
||||
`--allowed-tools=run_shell_command(${tool})`,
|
||||
);
|
||||
const result = await rig.run({
|
||||
args: [`--allowed-tools=run_shell_command(${tool})`],
|
||||
stdin: prompt,
|
||||
yolo: false,
|
||||
});
|
||||
|
||||
const foundToolCall = await rig.waitForToolCall('run_shell_command', 15000);
|
||||
|
||||
@@ -206,13 +204,11 @@ describe('run_shell_command', () => {
|
||||
const { command } = getLineCountCommand();
|
||||
const prompt = `use ${command} to tell me how many lines there are in ${testFile}`;
|
||||
|
||||
const result = await rig.run(
|
||||
{
|
||||
stdin: prompt,
|
||||
yolo: false,
|
||||
},
|
||||
'--allowed-tools=run_shell_command',
|
||||
);
|
||||
const result = await rig.run({
|
||||
args: '--allowed-tools=run_shell_command',
|
||||
stdin: prompt,
|
||||
yolo: false,
|
||||
});
|
||||
|
||||
const foundToolCall = await rig.waitForToolCall('run_shell_command', 15000);
|
||||
|
||||
@@ -245,7 +241,7 @@ describe('run_shell_command', () => {
|
||||
const prompt = `use ${command} to tell me how many lines there are in ${testFile}`;
|
||||
|
||||
const result = await rig.run({
|
||||
prompt: prompt,
|
||||
args: prompt,
|
||||
yolo: true,
|
||||
});
|
||||
|
||||
@@ -277,13 +273,11 @@ describe('run_shell_command', () => {
|
||||
const { tool, command } = getLineCountCommand();
|
||||
const prompt = `use ${command} to tell me how many lines there are in ${testFile}`;
|
||||
|
||||
const result = await rig.run(
|
||||
{
|
||||
stdin: prompt,
|
||||
yolo: false,
|
||||
},
|
||||
`--allowed-tools=ShellTool(${tool})`,
|
||||
);
|
||||
const result = await rig.run({
|
||||
args: `--allowed-tools=ShellTool(${tool})`,
|
||||
stdin: prompt,
|
||||
yolo: false,
|
||||
});
|
||||
|
||||
const foundToolCall = await rig.waitForToolCall('run_shell_command', 15000);
|
||||
|
||||
@@ -325,14 +319,14 @@ describe('run_shell_command', () => {
|
||||
`use both ${command} and ls to count the number of lines in files in this ` +
|
||||
`directory. Do not pipe these commands into each other, run them separately.`;
|
||||
|
||||
const result = await rig.run(
|
||||
{
|
||||
stdin: prompt,
|
||||
yolo: false,
|
||||
},
|
||||
`--allowed-tools=run_shell_command(${tool})`,
|
||||
'--allowed-tools=run_shell_command(ls)',
|
||||
);
|
||||
const result = await rig.run({
|
||||
args: [
|
||||
`--allowed-tools=run_shell_command(${tool})`,
|
||||
'--allowed-tools=run_shell_command(ls)',
|
||||
],
|
||||
stdin: prompt,
|
||||
yolo: false,
|
||||
});
|
||||
|
||||
for (const expected in ['ls', tool]) {
|
||||
const foundToolCall = await rig.waitForToolCall(
|
||||
@@ -380,13 +374,11 @@ describe('run_shell_command', () => {
|
||||
`If the command fails because it is not permitted, respond with the single word FAIL. ` +
|
||||
`If it succeeds, respond with SUCCESS.`;
|
||||
|
||||
const result = await rig.run(
|
||||
{
|
||||
stdin: prompt,
|
||||
yolo: false,
|
||||
},
|
||||
`--allowed-tools=run_shell_command(${allowedCommand})`,
|
||||
);
|
||||
const result = await rig.run({
|
||||
args: `--allowed-tools=run_shell_command(${allowedCommand})`,
|
||||
stdin: prompt,
|
||||
yolo: false,
|
||||
});
|
||||
|
||||
if (!result.toLowerCase().includes('fail')) {
|
||||
printDebugInfo(rig, result, {
|
||||
@@ -443,13 +435,11 @@ describe('run_shell_command', () => {
|
||||
const chained = getChainedEchoCommand();
|
||||
const shellInjection = `!{${chained.command}}`;
|
||||
|
||||
await rig.run(
|
||||
{
|
||||
stdin: `${shellInjection}\n`,
|
||||
yolo: false,
|
||||
},
|
||||
`--allowed-tools=ShellTool(${chained.allowPattern})`,
|
||||
);
|
||||
await rig.run({
|
||||
args: `--allowed-tools=ShellTool(${chained.allowPattern})`,
|
||||
stdin: `${shellInjection}\n`,
|
||||
yolo: false,
|
||||
});
|
||||
|
||||
// CLI should refuse to execute the chained command without scheduling run_shell_command.
|
||||
const toolLogs = rig
|
||||
@@ -474,14 +464,14 @@ describe('run_shell_command', () => {
|
||||
const { tool } = getLineCountCommand();
|
||||
const prompt = `Please run the command "echo test-allow-all" and show me the output`;
|
||||
|
||||
const result = await rig.run(
|
||||
{
|
||||
stdin: prompt,
|
||||
yolo: false,
|
||||
},
|
||||
`--allowed-tools=run_shell_command(${tool})`,
|
||||
'--allowed-tools=run_shell_command',
|
||||
);
|
||||
const result = await rig.run({
|
||||
args: [
|
||||
`--allowed-tools=run_shell_command(${tool})`,
|
||||
'--allowed-tools=run_shell_command',
|
||||
],
|
||||
stdin: prompt,
|
||||
yolo: false,
|
||||
});
|
||||
|
||||
const foundToolCall = await rig.waitForToolCall('run_shell_command', 15000);
|
||||
|
||||
@@ -523,7 +513,7 @@ describe('run_shell_command', () => {
|
||||
|
||||
try {
|
||||
const prompt = `Use echo to learn the value of the environment variable named ${varName} and tell me what it is.`;
|
||||
const result = await rig.run(prompt);
|
||||
const result = await rig.run({ args: prompt });
|
||||
|
||||
const foundToolCall = await rig.waitForToolCall('run_shell_command');
|
||||
|
||||
@@ -551,7 +541,7 @@ describe('run_shell_command', () => {
|
||||
rig.createFile(fileName, 'test content');
|
||||
|
||||
const prompt = `Run a shell command to list the files in the current directory and tell me what they are.`;
|
||||
const result = await rig.run(prompt);
|
||||
const result = await rig.run({ args: prompt });
|
||||
|
||||
const foundToolCall = await rig.waitForToolCall('run_shell_command');
|
||||
|
||||
@@ -577,9 +567,9 @@ describe('run_shell_command', () => {
|
||||
settings: { tools: { core: ['run_shell_command'] } },
|
||||
});
|
||||
const invalidCommand = getInvalidCommand();
|
||||
const result = await rig.run(
|
||||
`I am testing the error handling of the run_shell_command tool. Please attempt to run the following command, which I know has invalid syntax: \`${invalidCommand}\`. If the command fails as expected, please return the word FAIL, otherwise return the word SUCCESS.`,
|
||||
);
|
||||
const result = await rig.run({
|
||||
args: `I am testing the error handling of the run_shell_command tool. Please attempt to run the following command, which I know has invalid syntax: \`${invalidCommand}\`. If the command fails as expected, please return the word FAIL, otherwise return the word SUCCESS.`,
|
||||
});
|
||||
expect(result).toContain('FAIL');
|
||||
|
||||
const escapedInvalidCommand = JSON.stringify(invalidCommand).slice(1, -1);
|
||||
|
||||
@@ -24,7 +24,7 @@ describe('save_memory', () => {
|
||||
const prompt = `remember that my favorite color is blue.
|
||||
|
||||
what is my favorite color? tell me that and surround it with $ symbol`;
|
||||
const result = await rig.run(prompt);
|
||||
const result = await rig.run({ args: prompt });
|
||||
|
||||
const foundToolCall = await rig.waitForToolCall('save_memory');
|
||||
|
||||
|
||||
@@ -218,9 +218,9 @@ describe('simple-mcp-server', () => {
|
||||
|
||||
// Test directory is already set up in before hook
|
||||
// Just run the command - MCP server config is in settings.json
|
||||
const output = await rig.run(
|
||||
'Use the `add` tool to calculate 5+10 and output only the resulting number.',
|
||||
);
|
||||
const output = await rig.run({
|
||||
args: 'Use the `add` tool to calculate 5+10 and output only the resulting number.',
|
||||
});
|
||||
|
||||
const foundToolCall = await rig.waitForToolCall('add');
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ describe.skip('stdin context', () => {
|
||||
const stdinContent = `When I ask you for a token respond with ${randomString}`;
|
||||
const prompt = 'Can I please have a token?';
|
||||
|
||||
const result = await rig.run({ prompt, stdin: stdinContent });
|
||||
const result = await rig.run({ args: prompt, stdin: stdinContent });
|
||||
|
||||
await rig.waitForTelemetryEvent('api_request');
|
||||
const lastRequest = rig.readLastApiRequest();
|
||||
|
||||
@@ -20,7 +20,7 @@ describe('telemetry', () => {
|
||||
rig.setup('should emit a metric and a log event');
|
||||
|
||||
// Run a simple command that should trigger telemetry
|
||||
await rig.run('just saying hi');
|
||||
await rig.run({ args: 'just saying hi' });
|
||||
|
||||
// Verify that a user_prompt event was logged
|
||||
const hasUserPromptEvent = await rig.waitForTelemetryEvent('user_prompt');
|
||||
|
||||
@@ -18,6 +18,7 @@ import * as os from 'node:os';
|
||||
import { GEMINI_DIR } from '../packages/core/src/utils/paths.js';
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const BUNDLE_PATH = join(__dirname, '..', 'bundle/gemini.js');
|
||||
|
||||
// Get timeout based on environment
|
||||
function getDefaultTimeout() {
|
||||
@@ -266,8 +267,7 @@ export class InteractiveRun {
|
||||
}
|
||||
|
||||
export class TestRig {
|
||||
bundlePath: string;
|
||||
testDir: string | null;
|
||||
testDir: string | null = null;
|
||||
testName?: string;
|
||||
_lastRunStdout?: string;
|
||||
// Path to the copied fake responses file for this test.
|
||||
@@ -276,11 +276,6 @@ export class TestRig {
|
||||
originalFakeResponsesPath?: string;
|
||||
private _interactiveRuns: InteractiveRun[] = [];
|
||||
|
||||
constructor() {
|
||||
this.bundlePath = join(__dirname, '..', 'bundle/gemini.js');
|
||||
this.testDir = null;
|
||||
}
|
||||
|
||||
setup(
|
||||
testName: string,
|
||||
options: {
|
||||
@@ -370,7 +365,7 @@ export class TestRig {
|
||||
const command = isNpmReleaseTest ? 'gemini' : 'node';
|
||||
const initialArgs = isNpmReleaseTest
|
||||
? extraInitialArgs
|
||||
: [this.bundlePath, ...extraInitialArgs];
|
||||
: [BUNDLE_PATH, ...extraInitialArgs];
|
||||
if (this.fakeResponsesPath) {
|
||||
if (process.env['REGENERATE_MODEL_GOLDENS'] === 'true') {
|
||||
initialArgs.push('--record-responses', this.fakeResponsesPath);
|
||||
@@ -381,19 +376,13 @@ export class TestRig {
|
||||
return { command, initialArgs };
|
||||
}
|
||||
|
||||
run(
|
||||
promptOrOptions:
|
||||
| string
|
||||
| {
|
||||
prompt?: string;
|
||||
stdin?: string;
|
||||
stdinDoesNotEnd?: boolean;
|
||||
yolo?: boolean;
|
||||
},
|
||||
...args: string[]
|
||||
): Promise<string> {
|
||||
const yolo =
|
||||
typeof promptOrOptions === 'string' || promptOrOptions.yolo !== false;
|
||||
run(options: {
|
||||
args?: string | string[];
|
||||
stdin?: string;
|
||||
stdinDoesNotEnd?: boolean;
|
||||
yolo?: boolean;
|
||||
}): Promise<string> {
|
||||
const yolo = options.yolo !== false;
|
||||
const { command, initialArgs } = this._getCommandAndArgs(
|
||||
yolo ? ['--yolo'] : [],
|
||||
);
|
||||
@@ -407,21 +396,17 @@ export class TestRig {
|
||||
encoding: 'utf-8',
|
||||
};
|
||||
|
||||
if (typeof promptOrOptions === 'string') {
|
||||
commandArgs.push(promptOrOptions);
|
||||
} else if (
|
||||
typeof promptOrOptions === 'object' &&
|
||||
promptOrOptions !== null
|
||||
) {
|
||||
if (promptOrOptions.prompt) {
|
||||
commandArgs.push(promptOrOptions.prompt);
|
||||
}
|
||||
if (promptOrOptions.stdin) {
|
||||
execOptions.input = promptOrOptions.stdin;
|
||||
if (options.args) {
|
||||
if (Array.isArray(options.args)) {
|
||||
commandArgs.push(...options.args);
|
||||
} else {
|
||||
commandArgs.push(options.args);
|
||||
}
|
||||
}
|
||||
|
||||
commandArgs.push(...args);
|
||||
if (options.stdin) {
|
||||
execOptions.input = options.stdin;
|
||||
}
|
||||
|
||||
const child = spawn(command, commandArgs, {
|
||||
cwd: this.testDir!,
|
||||
@@ -437,10 +422,7 @@ export class TestRig {
|
||||
child.stdin!.write(execOptions.input);
|
||||
}
|
||||
|
||||
if (
|
||||
typeof promptOrOptions === 'object' &&
|
||||
!promptOrOptions.stdinDoesNotEnd
|
||||
) {
|
||||
if (!options.stdinDoesNotEnd) {
|
||||
child.stdin!.end();
|
||||
}
|
||||
|
||||
@@ -1032,26 +1014,23 @@ export class TestRig {
|
||||
return null;
|
||||
}
|
||||
|
||||
async runInteractive(
|
||||
options?: { yolo?: boolean } | string,
|
||||
...args: string[]
|
||||
): Promise<InteractiveRun> {
|
||||
// Handle backward compatibility: if first param is a string, treat as arg
|
||||
let yolo = true; // Default to YOLO mode
|
||||
let additionalArgs: string[] = args;
|
||||
|
||||
if (typeof options === 'string') {
|
||||
// Old-style call: runInteractive('--debug')
|
||||
additionalArgs = [options, ...args];
|
||||
} else if (typeof options === 'object' && options !== null) {
|
||||
// New-style call: runInteractive({ yolo: false })
|
||||
yolo = options.yolo !== false;
|
||||
}
|
||||
|
||||
async runInteractive(options?: {
|
||||
args?: string | string[];
|
||||
yolo?: boolean;
|
||||
}): Promise<InteractiveRun> {
|
||||
const yolo = options?.yolo !== false;
|
||||
const { command, initialArgs } = this._getCommandAndArgs(
|
||||
yolo ? ['--yolo'] : [],
|
||||
);
|
||||
const commandArgs = [...initialArgs, ...additionalArgs];
|
||||
const commandArgs = [...initialArgs];
|
||||
|
||||
if (options?.args) {
|
||||
if (Array.isArray(options.args)) {
|
||||
commandArgs.push(...options.args);
|
||||
} else {
|
||||
commandArgs.push(options.args);
|
||||
}
|
||||
}
|
||||
|
||||
const ptyOptions: pty.IPtyForkOptions = {
|
||||
name: 'xterm-color',
|
||||
|
||||
@@ -66,7 +66,7 @@ describe('BOM end-to-end integraion', () => {
|
||||
) {
|
||||
writeFileSync(join(rig.testDir!, filename), content);
|
||||
const prompt = `read the file ${filename} and output its exact contents`;
|
||||
const output = await rig.run(prompt);
|
||||
const output = await rig.run({ args: prompt });
|
||||
await rig.waitForToolCall('read_file');
|
||||
const lower = output.toLowerCase();
|
||||
if (expectedText === null) {
|
||||
@@ -126,7 +126,7 @@ describe('BOM end-to-end integraion', () => {
|
||||
const filename = 'gemini-screenshot.png';
|
||||
writeFileSync(join(rig.testDir!, filename), imageContent);
|
||||
const prompt = `What is shown in the image ${filename}?`;
|
||||
const output = await rig.run(prompt);
|
||||
const output = await rig.run({ args: prompt });
|
||||
await rig.waitForToolCall('read_file');
|
||||
const lower = output.toLowerCase();
|
||||
// The response is non-deterministic, so we just check for some
|
||||
|
||||
@@ -27,7 +27,7 @@ describe('write_file', () => {
|
||||
});
|
||||
const prompt = `show me an example of using the write tool. put a dad joke in dad.txt`;
|
||||
|
||||
const result = await rig.run(prompt);
|
||||
const result = await rig.run({ args: prompt });
|
||||
|
||||
const foundToolCall = await rig.waitForToolCall('write_file');
|
||||
|
||||
|
||||
Reference in New Issue
Block a user