Merge tag 'v0.3.0' into chore/sync-gemini-cli-v0.3.0

This commit is contained in:
mingholy.lmh
2025-09-10 21:01:40 +08:00
583 changed files with 30160 additions and 10770 deletions

View File

@@ -4,27 +4,28 @@
* SPDX-License-Identifier: Apache-2.0
*/
import fs from 'fs';
import path from 'path';
import os from 'os';
import crypto from 'crypto';
import { Config } from '../config/config.js';
import {
BaseDeclarativeTool,
BaseToolInvocation,
import fs from 'node:fs';
import path from 'node:path';
import os, { EOL } from 'node:os';
import crypto from 'node:crypto';
import type { Config } from '../config/config.js';
import { ToolErrorType } from './tool-error.js';
import type {
ToolInvocation,
ToolResult,
ToolCallConfirmationDetails,
ToolExecuteConfirmationDetails,
} from './tools.js';
import {
BaseDeclarativeTool,
BaseToolInvocation,
ToolConfirmationOutcome,
Kind,
} from './tools.js';
import { getErrorMessage } from '../utils/errors.js';
import { summarizeToolOutput } from '../utils/summarizer.js';
import {
ShellExecutionService,
ShellOutputEvent,
} from '../services/shellExecutionService.js';
import type { ShellOutputEvent } from '../services/shellExecutionService.js';
import { ShellExecutionService } from '../services/shellExecutionService.js';
import { formatMemoryUsage } from '../utils/formatters.js';
import {
getCommandRoots,
@@ -208,7 +209,7 @@ class ShellToolInvocation extends BaseToolInvocation<
if (fs.existsSync(tempFilePath)) {
const pgrepLines = fs
.readFileSync(tempFilePath, 'utf8')
.split('\n')
.split(EOL)
.filter(Boolean);
for (const line of pgrepLines) {
if (!/^\d+$/.test(line)) {
@@ -279,6 +280,14 @@ class ShellToolInvocation extends BaseToolInvocation<
}
const summarizeConfig = this.config.getSummarizeToolOutputConfig();
const executionError = result.error
? {
error: {
message: result.error.message,
type: ToolErrorType.SHELL_EXECUTE_ERROR,
},
}
: {};
if (summarizeConfig && summarizeConfig[ShellTool.Name]) {
const summary = await summarizeToolOutput(
llmContent,
@@ -289,12 +298,14 @@ class ShellToolInvocation extends BaseToolInvocation<
return {
llmContent: summary,
returnDisplay: returnDisplayMessage,
...executionError,
};
}
return {
llmContent,
returnDisplay: returnDisplayMessage,
...executionError,
};
} finally {
if (fs.existsSync(tempFilePath)) {
@@ -341,9 +352,7 @@ Co-authored-by: ${gitCoAuthorSettings.name} <${gitCoAuthorSettings.email}>`;
}
function getShellToolDescription(): string {
const platform = os.platform();
const toolDescription = `
${platform === 'win32' ? 'This tool executes a given shell command as `cmd.exe /c <command>`.' : 'This tool executes a given shell command as `bash -c <command>`. '}
**Background vs Foreground Execution:**
You should decide whether commands should run in background or foreground based on their nature:
@@ -362,8 +371,6 @@ function getShellToolDescription(): string {
- Git operations: \`git commit\`, \`git push\`
- Test runs: \`npm test\`, \`pytest\`
${platform === 'win32' ? '' : 'Command is executed as a subprocess that leads its own process group. Command process group can be terminated as `kill -- -PGID` or signaled as `kill -s SIGNAL -- -PGID`.'}
The following information is returned:
Command: Executed command.
@@ -376,7 +383,11 @@ function getShellToolDescription(): string {
Background PIDs: List of background processes started or \`(none)\`.
Process Group PGID: Process group started or \`(none)\``;
return toolDescription;
if (os.platform() === 'win32') {
return `This tool executes a given shell command as \`cmd.exe /c <command>\`. Command can start background processes using \`start /b\`.${toolDescription}`;
} else {
return `This tool executes a given shell command as \`bash -c <command>\`. Command can start background processes using \`&\`. Command is executed as a subprocess that leads its own process group. Command process group can be terminated as \`kill -- -PGID\` or signaled as \`kill -s SIGNAL -- -PGID\`.${toolDescription}`;
}
}
function getCommandDescription(): string {
@@ -407,11 +418,6 @@ export class ShellTool extends BaseDeclarativeTool<
type: 'string',
description: getCommandDescription(),
},
is_background: {
type: 'boolean',
description:
'Whether to run the command in background. Default is false. Set to true for long-running processes like development servers, watchers, or daemons that should continue running without blocking further commands.',
},
description: {
type: 'string',
description: