@google/gemini-cli-core 0.1.13-nightly.250726.fb751c54 → 0.1.13-nightly.250727.3e81359c
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/google-gemini-cli-core-0.1.13.tgz +0 -0
- package/dist/src/ide/ide-client.js +11 -2
- package/dist/src/ide/ide-client.js.map +1 -1
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.js +4 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/services/shellExecutionService.d.ts +70 -0
- package/dist/src/services/shellExecutionService.js +152 -0
- package/dist/src/services/shellExecutionService.js.map +1 -0
- package/dist/src/services/shellExecutionService.test.d.ts +6 -0
- package/dist/src/services/shellExecutionService.test.js +258 -0
- package/dist/src/services/shellExecutionService.test.js.map +1 -0
- package/dist/src/tools/shell.d.ts +1 -0
- package/dist/src/tools/shell.js +137 -181
- package/dist/src/tools/shell.js.map +1 -1
- package/dist/src/tools/shell.test.js +249 -102
- package/dist/src/tools/shell.test.js.map +1 -1
- package/dist/src/utils/formatters.d.ts +6 -0
- package/dist/src/utils/formatters.js +16 -0
- package/dist/src/utils/formatters.js.map +1 -0
- package/dist/src/utils/textUtils.d.ts +13 -0
- package/dist/src/utils/textUtils.js +28 -0
- package/dist/src/utils/textUtils.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
Binary file
|
|
@@ -8,7 +8,7 @@ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
|
8
8
|
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
|
|
9
9
|
const logger = {
|
|
10
10
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
11
|
-
debug: (...args) => console.debug('[DEBUG] [
|
|
11
|
+
debug: (...args) => console.debug('[DEBUG] [IDEClient]', ...args),
|
|
12
12
|
};
|
|
13
13
|
export var IDEConnectionStatus;
|
|
14
14
|
(function (IDEConnectionStatus) {
|
|
@@ -47,13 +47,14 @@ export class IdeClient {
|
|
|
47
47
|
this.connectionStatus = IDEConnectionStatus.Disconnected;
|
|
48
48
|
return;
|
|
49
49
|
}
|
|
50
|
+
let transport;
|
|
50
51
|
try {
|
|
51
52
|
this.client = new Client({
|
|
52
53
|
name: 'streamable-http-client',
|
|
53
54
|
// TODO(#3487): use the CLI version here.
|
|
54
55
|
version: '1.0.0',
|
|
55
56
|
});
|
|
56
|
-
|
|
57
|
+
transport = new StreamableHTTPClientTransport(new URL(`http://localhost:${idePort}/mcp`));
|
|
57
58
|
await this.client.connect(transport);
|
|
58
59
|
this.client.setNotificationHandler(OpenFilesNotificationSchema, (notification) => {
|
|
59
60
|
ideContext.setOpenFilesContext(notification.params);
|
|
@@ -73,6 +74,14 @@ export class IdeClient {
|
|
|
73
74
|
catch (error) {
|
|
74
75
|
this.connectionStatus = IDEConnectionStatus.Disconnected;
|
|
75
76
|
logger.debug('Failed to connect to MCP server:', error);
|
|
77
|
+
if (transport) {
|
|
78
|
+
try {
|
|
79
|
+
await transport.close();
|
|
80
|
+
}
|
|
81
|
+
catch (closeError) {
|
|
82
|
+
logger.debug('Failed to close transport:', closeError);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
76
85
|
}
|
|
77
86
|
}
|
|
78
87
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ide-client.js","sourceRoot":"","sources":["../../../src/ide/ide-client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,2BAA2B,EAAE,MAAM,sBAAsB,CAAC;AAC/E,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AAEnG,MAAM,MAAM,GAAG;IACb,8DAA8D;IAC9D,KAAK,EAAE,CAAC,GAAG,IAAW,EAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"ide-client.js","sourceRoot":"","sources":["../../../src/ide/ide-client.ts"],"names":[],"mappings":"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"}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -29,10 +29,13 @@ export * from './utils/quotaErrorDetection.js';
|
|
|
29
29
|
export * from './utils/fileUtils.js';
|
|
30
30
|
export * from './utils/retry.js';
|
|
31
31
|
export * from './utils/systemEncoding.js';
|
|
32
|
+
export * from './utils/textUtils.js';
|
|
33
|
+
export * from './utils/formatters.js';
|
|
32
34
|
export * from './services/fileDiscoveryService.js';
|
|
33
35
|
export * from './services/gitService.js';
|
|
34
36
|
export * from './ide/ide-client.js';
|
|
35
37
|
export * from './ide/ideContext.js';
|
|
38
|
+
export * from './services/shellExecutionService.js';
|
|
36
39
|
export * from './tools/tools.js';
|
|
37
40
|
export * from './tools/tool-registry.js';
|
|
38
41
|
export * from './prompts/mcp-prompts.js';
|
package/dist/src/index.js
CHANGED
|
@@ -32,12 +32,16 @@ export * from './utils/quotaErrorDetection.js';
|
|
|
32
32
|
export * from './utils/fileUtils.js';
|
|
33
33
|
export * from './utils/retry.js';
|
|
34
34
|
export * from './utils/systemEncoding.js';
|
|
35
|
+
export * from './utils/textUtils.js';
|
|
36
|
+
export * from './utils/formatters.js';
|
|
35
37
|
// Export services
|
|
36
38
|
export * from './services/fileDiscoveryService.js';
|
|
37
39
|
export * from './services/gitService.js';
|
|
38
40
|
// Export IDE specific logic
|
|
39
41
|
export * from './ide/ide-client.js';
|
|
40
42
|
export * from './ide/ideContext.js';
|
|
43
|
+
// Export Shell Execution Service
|
|
44
|
+
export * from './services/shellExecutionService.js';
|
|
41
45
|
// Export base tool definitions
|
|
42
46
|
export * from './tools/tools.js';
|
|
43
47
|
export * from './tools/tool-registry.js';
|
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,gBAAgB;AAChB,cAAc,oBAAoB,CAAC;AAEnC,oBAAoB;AACpB,cAAc,kBAAkB,CAAC;AACjC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,yBAAyB,CAAC;AACxC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,sCAAsC,CAAC;AAErD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AAEvC,mBAAmB;AACnB,cAAc,kBAAkB,CAAC;AACjC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,mBAAmB,CAAC;AAClC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,mBAAmB,CAAC;AAClC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,gBAAgB;AAChB,cAAc,oBAAoB,CAAC;AAEnC,oBAAoB;AACpB,cAAc,kBAAkB,CAAC;AACjC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,yBAAyB,CAAC;AACxC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,sCAAsC,CAAC;AAErD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AAEvC,mBAAmB;AACnB,cAAc,kBAAkB,CAAC;AACjC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,mBAAmB,CAAC;AAClC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,mBAAmB,CAAC;AAClC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AAEtC,kBAAkB;AAClB,cAAc,oCAAoC,CAAC;AACnD,cAAc,0BAA0B,CAAC;AAEzC,4BAA4B;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AAEpC,iCAAiC;AACjC,cAAc,qCAAqC,CAAC;AAEpD,+BAA+B;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,0BAA0B,CAAC;AAEzC,sBAAsB;AACtB,cAAc,0BAA0B,CAAC;AAEzC,6BAA6B;AAC7B,cAAc,sBAAsB,CAAC;AACrC,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AAEpC,YAAY;AACZ,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAGL,oBAAoB,GACrB,MAAM,8BAA8B,CAAC;AAMtC,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAElD,6BAA6B;AAC7B,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,cAAc,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
/** A structured result from a shell command execution. */
|
|
7
|
+
export interface ShellExecutionResult {
|
|
8
|
+
/** The raw, unprocessed output buffer. */
|
|
9
|
+
rawOutput: Buffer;
|
|
10
|
+
/** The combined, decoded stdout and stderr as a string. */
|
|
11
|
+
output: string;
|
|
12
|
+
/** The decoded stdout as a string. */
|
|
13
|
+
stdout: string;
|
|
14
|
+
/** The decoded stderr as a string. */
|
|
15
|
+
stderr: string;
|
|
16
|
+
/** The process exit code, or null if terminated by a signal. */
|
|
17
|
+
exitCode: number | null;
|
|
18
|
+
/** The signal that terminated the process, if any. */
|
|
19
|
+
signal: NodeJS.Signals | null;
|
|
20
|
+
/** An error object if the process failed to spawn. */
|
|
21
|
+
error: Error | null;
|
|
22
|
+
/** A boolean indicating if the command was aborted by the user. */
|
|
23
|
+
aborted: boolean;
|
|
24
|
+
/** The process ID of the spawned shell. */
|
|
25
|
+
pid: number | undefined;
|
|
26
|
+
}
|
|
27
|
+
/** A handle for an ongoing shell execution. */
|
|
28
|
+
export interface ShellExecutionHandle {
|
|
29
|
+
/** The process ID of the spawned shell. */
|
|
30
|
+
pid: number | undefined;
|
|
31
|
+
/** A promise that resolves with the complete execution result. */
|
|
32
|
+
result: Promise<ShellExecutionResult>;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Describes a structured event emitted during shell command execution.
|
|
36
|
+
*/
|
|
37
|
+
export type ShellOutputEvent = {
|
|
38
|
+
/** The event contains a chunk of output data. */
|
|
39
|
+
type: 'data';
|
|
40
|
+
/** The stream from which the data originated. */
|
|
41
|
+
stream: 'stdout' | 'stderr';
|
|
42
|
+
/** The decoded string chunk. */
|
|
43
|
+
chunk: string;
|
|
44
|
+
} | {
|
|
45
|
+
/** Signals that the output stream has been identified as binary. */
|
|
46
|
+
type: 'binary_detected';
|
|
47
|
+
} | {
|
|
48
|
+
/** Provides progress updates for a binary stream. */
|
|
49
|
+
type: 'binary_progress';
|
|
50
|
+
/** The total number of bytes received so far. */
|
|
51
|
+
bytesReceived: number;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* A centralized service for executing shell commands with robust process
|
|
55
|
+
* management, cross-platform compatibility, and streaming output capabilities.
|
|
56
|
+
*
|
|
57
|
+
*/
|
|
58
|
+
export declare class ShellExecutionService {
|
|
59
|
+
/**
|
|
60
|
+
* Executes a shell command using `spawn`, capturing all output and lifecycle events.
|
|
61
|
+
*
|
|
62
|
+
* @param commandToExecute The exact command string to run.
|
|
63
|
+
* @param cwd The working directory to execute the command in.
|
|
64
|
+
* @param onOutputEvent A callback for streaming structured events about the execution, including data chunks and status updates.
|
|
65
|
+
* @param abortSignal An AbortSignal to terminate the process and its children.
|
|
66
|
+
* @returns An object containing the process ID (pid) and a promise that
|
|
67
|
+
* resolves with the complete execution result.
|
|
68
|
+
*/
|
|
69
|
+
static execute(commandToExecute: string, cwd: string, onOutputEvent: (event: ShellOutputEvent) => void, abortSignal: AbortSignal): ShellExecutionHandle;
|
|
70
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { spawn } from 'child_process';
|
|
7
|
+
import { TextDecoder } from 'util';
|
|
8
|
+
import os from 'os';
|
|
9
|
+
import stripAnsi from 'strip-ansi';
|
|
10
|
+
import { getCachedEncodingForBuffer } from '../utils/systemEncoding.js';
|
|
11
|
+
import { isBinary } from '../utils/textUtils.js';
|
|
12
|
+
const SIGKILL_TIMEOUT_MS = 200;
|
|
13
|
+
/**
|
|
14
|
+
* A centralized service for executing shell commands with robust process
|
|
15
|
+
* management, cross-platform compatibility, and streaming output capabilities.
|
|
16
|
+
*
|
|
17
|
+
*/
|
|
18
|
+
export class ShellExecutionService {
|
|
19
|
+
/**
|
|
20
|
+
* Executes a shell command using `spawn`, capturing all output and lifecycle events.
|
|
21
|
+
*
|
|
22
|
+
* @param commandToExecute The exact command string to run.
|
|
23
|
+
* @param cwd The working directory to execute the command in.
|
|
24
|
+
* @param onOutputEvent A callback for streaming structured events about the execution, including data chunks and status updates.
|
|
25
|
+
* @param abortSignal An AbortSignal to terminate the process and its children.
|
|
26
|
+
* @returns An object containing the process ID (pid) and a promise that
|
|
27
|
+
* resolves with the complete execution result.
|
|
28
|
+
*/
|
|
29
|
+
static execute(commandToExecute, cwd, onOutputEvent, abortSignal) {
|
|
30
|
+
const isWindows = os.platform() === 'win32';
|
|
31
|
+
const shell = isWindows ? 'cmd.exe' : 'bash';
|
|
32
|
+
const shellArgs = [isWindows ? '/c' : '-c', commandToExecute];
|
|
33
|
+
const child = spawn(shell, shellArgs, {
|
|
34
|
+
cwd,
|
|
35
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
36
|
+
detached: !isWindows, // Use process groups on non-Windows for robust killing
|
|
37
|
+
env: {
|
|
38
|
+
...process.env,
|
|
39
|
+
GEMINI_CLI: '1',
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
const result = new Promise((resolve) => {
|
|
43
|
+
// Use decoders to handle multi-byte characters safely (for streaming output).
|
|
44
|
+
let stdoutDecoder = null;
|
|
45
|
+
let stderrDecoder = null;
|
|
46
|
+
let stdout = '';
|
|
47
|
+
let stderr = '';
|
|
48
|
+
const outputChunks = [];
|
|
49
|
+
let error = null;
|
|
50
|
+
let exited = false;
|
|
51
|
+
let isStreamingRawContent = true;
|
|
52
|
+
const MAX_SNIFF_SIZE = 4096;
|
|
53
|
+
let sniffedBytes = 0;
|
|
54
|
+
const handleOutput = (data, stream) => {
|
|
55
|
+
if (!stdoutDecoder || !stderrDecoder) {
|
|
56
|
+
const encoding = getCachedEncodingForBuffer(data);
|
|
57
|
+
try {
|
|
58
|
+
stdoutDecoder = new TextDecoder(encoding);
|
|
59
|
+
stderrDecoder = new TextDecoder(encoding);
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
// If the encoding is not supported, fall back to utf-8.
|
|
63
|
+
// This can happen on some platforms for certain encodings like 'utf-32le'.
|
|
64
|
+
stdoutDecoder = new TextDecoder('utf-8');
|
|
65
|
+
stderrDecoder = new TextDecoder('utf-8');
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
outputChunks.push(data);
|
|
69
|
+
// Binary detection logic. This only runs until we've made a determination.
|
|
70
|
+
if (isStreamingRawContent && sniffedBytes < MAX_SNIFF_SIZE) {
|
|
71
|
+
const sniffBuffer = Buffer.concat(outputChunks.slice(0, 20));
|
|
72
|
+
sniffedBytes = sniffBuffer.length;
|
|
73
|
+
if (isBinary(sniffBuffer)) {
|
|
74
|
+
// Change state to stop streaming raw content.
|
|
75
|
+
isStreamingRawContent = false;
|
|
76
|
+
onOutputEvent({ type: 'binary_detected' });
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
const decodedChunk = stream === 'stdout'
|
|
80
|
+
? stdoutDecoder.decode(data, { stream: true })
|
|
81
|
+
: stderrDecoder.decode(data, { stream: true });
|
|
82
|
+
const strippedChunk = stripAnsi(decodedChunk);
|
|
83
|
+
if (stream === 'stdout') {
|
|
84
|
+
stdout += strippedChunk;
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
stderr += strippedChunk;
|
|
88
|
+
}
|
|
89
|
+
if (isStreamingRawContent) {
|
|
90
|
+
onOutputEvent({ type: 'data', stream, chunk: strippedChunk });
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
const totalBytes = outputChunks.reduce((sum, chunk) => sum + chunk.length, 0);
|
|
94
|
+
onOutputEvent({ type: 'binary_progress', bytesReceived: totalBytes });
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
child.stdout.on('data', (data) => handleOutput(data, 'stdout'));
|
|
98
|
+
child.stderr.on('data', (data) => handleOutput(data, 'stderr'));
|
|
99
|
+
child.on('error', (err) => {
|
|
100
|
+
error = err;
|
|
101
|
+
});
|
|
102
|
+
const abortHandler = async () => {
|
|
103
|
+
if (child.pid && !exited) {
|
|
104
|
+
if (isWindows) {
|
|
105
|
+
spawn('taskkill', ['/pid', child.pid.toString(), '/f', '/t']);
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
try {
|
|
109
|
+
// Kill the entire process group (negative PID).
|
|
110
|
+
// SIGTERM first, then SIGKILL if it doesn't die.
|
|
111
|
+
process.kill(-child.pid, 'SIGTERM');
|
|
112
|
+
await new Promise((res) => setTimeout(res, SIGKILL_TIMEOUT_MS));
|
|
113
|
+
if (!exited) {
|
|
114
|
+
process.kill(-child.pid, 'SIGKILL');
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
catch (_e) {
|
|
118
|
+
// Fall back to killing just the main process if group kill fails.
|
|
119
|
+
if (!exited)
|
|
120
|
+
child.kill('SIGKILL');
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
abortSignal.addEventListener('abort', abortHandler, { once: true });
|
|
126
|
+
child.on('exit', (code, signal) => {
|
|
127
|
+
exited = true;
|
|
128
|
+
abortSignal.removeEventListener('abort', abortHandler);
|
|
129
|
+
if (stdoutDecoder) {
|
|
130
|
+
stdout += stripAnsi(stdoutDecoder.decode());
|
|
131
|
+
}
|
|
132
|
+
if (stderrDecoder) {
|
|
133
|
+
stderr += stripAnsi(stderrDecoder.decode());
|
|
134
|
+
}
|
|
135
|
+
const finalBuffer = Buffer.concat(outputChunks);
|
|
136
|
+
resolve({
|
|
137
|
+
rawOutput: finalBuffer,
|
|
138
|
+
output: stdout + (stderr ? `\n${stderr}` : ''),
|
|
139
|
+
stdout,
|
|
140
|
+
stderr,
|
|
141
|
+
exitCode: code,
|
|
142
|
+
signal,
|
|
143
|
+
error,
|
|
144
|
+
aborted: abortSignal.aborted,
|
|
145
|
+
pid: child.pid,
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
return { pid: child.pid, result };
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=shellExecutionService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shellExecutionService.js","sourceRoot":"","sources":["../../../src/services/shellExecutionService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { vi, describe, it, expect, beforeEach } from 'vitest';
|
|
7
|
+
const mockSpawn = vi.hoisted(() => vi.fn());
|
|
8
|
+
vi.mock('child_process', () => ({
|
|
9
|
+
spawn: mockSpawn,
|
|
10
|
+
}));
|
|
11
|
+
import EventEmitter from 'events';
|
|
12
|
+
import { ShellExecutionService, } from './shellExecutionService.js';
|
|
13
|
+
const mockIsBinary = vi.hoisted(() => vi.fn());
|
|
14
|
+
vi.mock('../utils/textUtils.js', () => ({
|
|
15
|
+
isBinary: mockIsBinary,
|
|
16
|
+
}));
|
|
17
|
+
const mockPlatform = vi.hoisted(() => vi.fn());
|
|
18
|
+
vi.mock('os', () => ({
|
|
19
|
+
default: {
|
|
20
|
+
platform: mockPlatform,
|
|
21
|
+
},
|
|
22
|
+
platform: mockPlatform,
|
|
23
|
+
}));
|
|
24
|
+
const mockProcessKill = vi
|
|
25
|
+
.spyOn(process, 'kill')
|
|
26
|
+
.mockImplementation(() => true);
|
|
27
|
+
describe('ShellExecutionService', () => {
|
|
28
|
+
let mockChildProcess;
|
|
29
|
+
let onOutputEventMock;
|
|
30
|
+
beforeEach(() => {
|
|
31
|
+
vi.clearAllMocks();
|
|
32
|
+
mockIsBinary.mockReturnValue(false);
|
|
33
|
+
mockPlatform.mockReturnValue('linux');
|
|
34
|
+
onOutputEventMock = vi.fn();
|
|
35
|
+
mockChildProcess = new EventEmitter();
|
|
36
|
+
// FIX: Cast simple EventEmitters to the expected stream type.
|
|
37
|
+
mockChildProcess.stdout = new EventEmitter();
|
|
38
|
+
mockChildProcess.stderr = new EventEmitter();
|
|
39
|
+
mockChildProcess.kill = vi.fn();
|
|
40
|
+
// FIX: Use Object.defineProperty to set the readonly 'pid' property.
|
|
41
|
+
Object.defineProperty(mockChildProcess, 'pid', {
|
|
42
|
+
value: 12345,
|
|
43
|
+
configurable: true,
|
|
44
|
+
});
|
|
45
|
+
mockSpawn.mockReturnValue(mockChildProcess);
|
|
46
|
+
});
|
|
47
|
+
// Helper function to run a standard execution simulation
|
|
48
|
+
const simulateExecution = async (command, simulation) => {
|
|
49
|
+
const abortController = new AbortController();
|
|
50
|
+
const handle = ShellExecutionService.execute(command, '/test/dir', onOutputEventMock, abortController.signal);
|
|
51
|
+
await new Promise((resolve) => setImmediate(resolve));
|
|
52
|
+
simulation(mockChildProcess, abortController);
|
|
53
|
+
const result = await handle.result;
|
|
54
|
+
return { result, handle, abortController };
|
|
55
|
+
};
|
|
56
|
+
describe('Successful Execution', () => {
|
|
57
|
+
it('should execute a command and capture stdout and stderr', async () => {
|
|
58
|
+
const { result, handle } = await simulateExecution('ls -l', (cp) => {
|
|
59
|
+
cp.stdout?.emit('data', Buffer.from('file1.txt\n'));
|
|
60
|
+
cp.stderr?.emit('data', Buffer.from('a warning'));
|
|
61
|
+
cp.emit('exit', 0, null);
|
|
62
|
+
});
|
|
63
|
+
expect(mockSpawn).toHaveBeenCalledWith('bash', ['-c', 'ls -l'], expect.any(Object));
|
|
64
|
+
expect(result.exitCode).toBe(0);
|
|
65
|
+
expect(result.signal).toBeNull();
|
|
66
|
+
expect(result.error).toBeNull();
|
|
67
|
+
expect(result.aborted).toBe(false);
|
|
68
|
+
expect(result.stdout).toBe('file1.txt\n');
|
|
69
|
+
expect(result.stderr).toBe('a warning');
|
|
70
|
+
expect(result.output).toBe('file1.txt\n\na warning');
|
|
71
|
+
expect(handle.pid).toBe(12345);
|
|
72
|
+
expect(onOutputEventMock).toHaveBeenCalledWith({
|
|
73
|
+
type: 'data',
|
|
74
|
+
stream: 'stdout',
|
|
75
|
+
chunk: 'file1.txt\n',
|
|
76
|
+
});
|
|
77
|
+
expect(onOutputEventMock).toHaveBeenCalledWith({
|
|
78
|
+
type: 'data',
|
|
79
|
+
stream: 'stderr',
|
|
80
|
+
chunk: 'a warning',
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
it('should strip ANSI codes from output', async () => {
|
|
84
|
+
const { result } = await simulateExecution('ls --color=auto', (cp) => {
|
|
85
|
+
cp.stdout?.emit('data', Buffer.from('a\u001b[31mred\u001b[0mword'));
|
|
86
|
+
cp.emit('exit', 0, null);
|
|
87
|
+
});
|
|
88
|
+
expect(result.stdout).toBe('aredword');
|
|
89
|
+
expect(onOutputEventMock).toHaveBeenCalledWith({
|
|
90
|
+
type: 'data',
|
|
91
|
+
stream: 'stdout',
|
|
92
|
+
chunk: 'aredword',
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
it('should correctly decode multi-byte characters split across chunks', async () => {
|
|
96
|
+
const { result } = await simulateExecution('echo "你好"', (cp) => {
|
|
97
|
+
const multiByteChar = Buffer.from('你好', 'utf-8');
|
|
98
|
+
cp.stdout?.emit('data', multiByteChar.slice(0, 2));
|
|
99
|
+
cp.stdout?.emit('data', multiByteChar.slice(2));
|
|
100
|
+
cp.emit('exit', 0, null);
|
|
101
|
+
});
|
|
102
|
+
expect(result.stdout).toBe('你好');
|
|
103
|
+
});
|
|
104
|
+
it('should handle commands with no output', async () => {
|
|
105
|
+
const { result } = await simulateExecution('touch file', (cp) => {
|
|
106
|
+
cp.emit('exit', 0, null);
|
|
107
|
+
});
|
|
108
|
+
expect(result.stdout).toBe('');
|
|
109
|
+
expect(result.stderr).toBe('');
|
|
110
|
+
expect(result.output).toBe('');
|
|
111
|
+
expect(onOutputEventMock).not.toHaveBeenCalled();
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
describe('Failed Execution', () => {
|
|
115
|
+
it('should capture a non-zero exit code and format output correctly', async () => {
|
|
116
|
+
const { result } = await simulateExecution('a-bad-command', (cp) => {
|
|
117
|
+
cp.stderr?.emit('data', Buffer.from('command not found'));
|
|
118
|
+
cp.emit('exit', 127, null);
|
|
119
|
+
});
|
|
120
|
+
expect(result.exitCode).toBe(127);
|
|
121
|
+
expect(result.stderr).toBe('command not found');
|
|
122
|
+
expect(result.stdout).toBe('');
|
|
123
|
+
expect(result.output).toBe('\ncommand not found');
|
|
124
|
+
expect(result.error).toBeNull();
|
|
125
|
+
});
|
|
126
|
+
it('should capture a termination signal', async () => {
|
|
127
|
+
const { result } = await simulateExecution('long-process', (cp) => {
|
|
128
|
+
cp.emit('exit', null, 'SIGTERM');
|
|
129
|
+
});
|
|
130
|
+
expect(result.exitCode).toBeNull();
|
|
131
|
+
expect(result.signal).toBe('SIGTERM');
|
|
132
|
+
});
|
|
133
|
+
it('should handle a spawn error', async () => {
|
|
134
|
+
const spawnError = new Error('spawn EACCES');
|
|
135
|
+
const { result } = await simulateExecution('protected-cmd', (cp) => {
|
|
136
|
+
cp.emit('error', spawnError);
|
|
137
|
+
cp.emit('exit', 1, null);
|
|
138
|
+
});
|
|
139
|
+
expect(result.error).toBe(spawnError);
|
|
140
|
+
expect(result.exitCode).toBe(1);
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
describe('Aborting Commands', () => {
|
|
144
|
+
describe.each([
|
|
145
|
+
{
|
|
146
|
+
platform: 'linux',
|
|
147
|
+
expectedSignal: 'SIGTERM',
|
|
148
|
+
expectedExit: { signal: 'SIGKILL' },
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
platform: 'win32',
|
|
152
|
+
expectedCommand: 'taskkill',
|
|
153
|
+
expectedExit: { code: 1 },
|
|
154
|
+
},
|
|
155
|
+
])('on $platform', ({ platform, expectedSignal, expectedCommand, expectedExit }) => {
|
|
156
|
+
it('should abort a running process and set the aborted flag', async () => {
|
|
157
|
+
mockPlatform.mockReturnValue(platform);
|
|
158
|
+
const { result } = await simulateExecution('sleep 10', (cp, abortController) => {
|
|
159
|
+
abortController.abort();
|
|
160
|
+
if (expectedExit.signal)
|
|
161
|
+
cp.emit('exit', null, expectedExit.signal);
|
|
162
|
+
if (typeof expectedExit.code === 'number')
|
|
163
|
+
cp.emit('exit', expectedExit.code, null);
|
|
164
|
+
});
|
|
165
|
+
expect(result.aborted).toBe(true);
|
|
166
|
+
if (platform === 'linux') {
|
|
167
|
+
expect(mockProcessKill).toHaveBeenCalledWith(-mockChildProcess.pid, expectedSignal);
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
expect(mockSpawn).toHaveBeenCalledWith(expectedCommand, [
|
|
171
|
+
'/pid',
|
|
172
|
+
String(mockChildProcess.pid),
|
|
173
|
+
'/f',
|
|
174
|
+
'/t',
|
|
175
|
+
]);
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
it('should gracefully attempt SIGKILL on linux if SIGTERM fails', async () => {
|
|
180
|
+
mockPlatform.mockReturnValue('linux');
|
|
181
|
+
vi.useFakeTimers();
|
|
182
|
+
// Don't await the result inside the simulation block for this specific test.
|
|
183
|
+
// We need to control the timeline manually.
|
|
184
|
+
const abortController = new AbortController();
|
|
185
|
+
const handle = ShellExecutionService.execute('unresponsive_process', '/test/dir', onOutputEventMock, abortController.signal);
|
|
186
|
+
abortController.abort();
|
|
187
|
+
// Check the first kill signal
|
|
188
|
+
expect(mockProcessKill).toHaveBeenCalledWith(-mockChildProcess.pid, 'SIGTERM');
|
|
189
|
+
// Now, advance time past the timeout
|
|
190
|
+
await vi.advanceTimersByTimeAsync(250);
|
|
191
|
+
// Check the second kill signal
|
|
192
|
+
expect(mockProcessKill).toHaveBeenCalledWith(-mockChildProcess.pid, 'SIGKILL');
|
|
193
|
+
// Finally, simulate the process exiting and await the result
|
|
194
|
+
mockChildProcess.emit('exit', null, 'SIGKILL');
|
|
195
|
+
const result = await handle.result;
|
|
196
|
+
vi.useRealTimers();
|
|
197
|
+
expect(result.aborted).toBe(true);
|
|
198
|
+
expect(result.signal).toBe('SIGKILL');
|
|
199
|
+
// The individual kill calls were already asserted above.
|
|
200
|
+
expect(mockProcessKill).toHaveBeenCalledTimes(2);
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
describe('Binary Output', () => {
|
|
204
|
+
it('should detect binary output and switch to progress events', async () => {
|
|
205
|
+
mockIsBinary.mockReturnValueOnce(true);
|
|
206
|
+
const binaryChunk1 = Buffer.from([0x89, 0x50, 0x4e, 0x47]);
|
|
207
|
+
const binaryChunk2 = Buffer.from([0x0d, 0x0a, 0x1a, 0x0a]);
|
|
208
|
+
const { result } = await simulateExecution('cat image.png', (cp) => {
|
|
209
|
+
cp.stdout?.emit('data', binaryChunk1);
|
|
210
|
+
cp.stdout?.emit('data', binaryChunk2);
|
|
211
|
+
cp.emit('exit', 0, null);
|
|
212
|
+
});
|
|
213
|
+
expect(result.rawOutput).toEqual(Buffer.concat([binaryChunk1, binaryChunk2]));
|
|
214
|
+
expect(onOutputEventMock).toHaveBeenCalledTimes(3);
|
|
215
|
+
expect(onOutputEventMock.mock.calls[0][0]).toEqual({
|
|
216
|
+
type: 'binary_detected',
|
|
217
|
+
});
|
|
218
|
+
expect(onOutputEventMock.mock.calls[1][0]).toEqual({
|
|
219
|
+
type: 'binary_progress',
|
|
220
|
+
bytesReceived: 4,
|
|
221
|
+
});
|
|
222
|
+
expect(onOutputEventMock.mock.calls[2][0]).toEqual({
|
|
223
|
+
type: 'binary_progress',
|
|
224
|
+
bytesReceived: 8,
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
it('should not emit data events after binary is detected', async () => {
|
|
228
|
+
mockIsBinary.mockImplementation((buffer) => buffer.includes(0x00));
|
|
229
|
+
await simulateExecution('cat mixed_file', (cp) => {
|
|
230
|
+
cp.stdout?.emit('data', Buffer.from('some text'));
|
|
231
|
+
cp.stdout?.emit('data', Buffer.from([0x00, 0x01, 0x02]));
|
|
232
|
+
cp.stdout?.emit('data', Buffer.from('more text'));
|
|
233
|
+
cp.emit('exit', 0, null);
|
|
234
|
+
});
|
|
235
|
+
// FIX: Provide explicit type for the 'call' parameter in the map function.
|
|
236
|
+
const eventTypes = onOutputEventMock.mock.calls.map((call) => call[0].type);
|
|
237
|
+
expect(eventTypes).toEqual([
|
|
238
|
+
'data',
|
|
239
|
+
'binary_detected',
|
|
240
|
+
'binary_progress',
|
|
241
|
+
'binary_progress',
|
|
242
|
+
]);
|
|
243
|
+
});
|
|
244
|
+
});
|
|
245
|
+
describe('Platform-Specific Behavior', () => {
|
|
246
|
+
it('should use cmd.exe on Windows', async () => {
|
|
247
|
+
mockPlatform.mockReturnValue('win32');
|
|
248
|
+
await simulateExecution('dir', (cp) => cp.emit('exit', 0, null));
|
|
249
|
+
expect(mockSpawn).toHaveBeenCalledWith('cmd.exe', ['/c', 'dir'], expect.objectContaining({ detached: false }));
|
|
250
|
+
});
|
|
251
|
+
it('should use bash and detached process group on Linux', async () => {
|
|
252
|
+
mockPlatform.mockReturnValue('linux');
|
|
253
|
+
await simulateExecution('ls', (cp) => cp.emit('exit', 0, null));
|
|
254
|
+
expect(mockSpawn).toHaveBeenCalledWith('bash', ['-c', 'ls'], expect.objectContaining({ detached: true }));
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
});
|
|
258
|
+
//# sourceMappingURL=shellExecutionService.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shellExecutionService.test.js","sourceRoot":"","sources":["../../../src/services/shellExecutionService.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { Config } from '../config/config.js';
|
|
7
7
|
import { BaseTool, ToolResult, ToolCallConfirmationDetails } from './tools.js';
|
|
8
|
+
export declare const OUTPUT_UPDATE_INTERVAL_MS = 1000;
|
|
8
9
|
export interface ShellToolParams {
|
|
9
10
|
command: string;
|
|
10
11
|
description?: string;
|